diff --git a/src/action/base/create_directory.rs b/src/action/base/create_directory.rs index 915e737..883d5b9 100644 --- a/src/action/base/create_directory.rs +++ b/src/action/base/create_directory.rs @@ -78,7 +78,7 @@ impl CreateDirectory { } tracing::debug!("Creating directory `{}` already complete", path.display(),); - ActionState::Skipped + ActionState::Completed } else { ActionState::Uncompleted }; diff --git a/src/action/base/mod.rs b/src/action/base/mod.rs index 1344dc5..3b09580 100644 --- a/src/action/base/mod.rs +++ b/src/action/base/mod.rs @@ -9,6 +9,7 @@ pub(crate) mod create_or_merge_nix_config; pub(crate) mod create_user; pub(crate) mod fetch_and_unpack_nix; pub(crate) mod move_unpacked_nix; +pub(crate) mod remove_directory; pub(crate) mod setup_default_profile; pub use add_user_to_group::AddUserToGroup; @@ -20,4 +21,5 @@ pub use create_or_merge_nix_config::CreateOrMergeNixConfig; pub use create_user::CreateUser; pub use fetch_and_unpack_nix::{FetchAndUnpackNix, FetchUrlError}; pub use move_unpacked_nix::{MoveUnpackedNix, MoveUnpackedNixError}; +pub use remove_directory::RemoveDirectory; pub use setup_default_profile::{SetupDefaultProfile, SetupDefaultProfileError}; diff --git a/src/action/base/move_unpacked_nix.rs b/src/action/base/move_unpacked_nix.rs index e4c6d2b..1ca3b75 100644 --- a/src/action/base/move_unpacked_nix.rs +++ b/src/action/base/move_unpacked_nix.rs @@ -11,14 +11,14 @@ Move an unpacked Nix at `src` to `/nix` */ #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] pub struct MoveUnpackedNix { - src: PathBuf, + unpacked_path: PathBuf, } impl MoveUnpackedNix { #[tracing::instrument(level = "debug", skip_all)] - pub async fn plan(src: PathBuf) -> Result, ActionError> { + pub async fn plan(unpacked_path: PathBuf) -> Result, ActionError> { // Note: Do NOT try to check for the src/dest since the installer creates those - Ok(Self { src }.into()) + Ok(Self { unpacked_path }.into()) } } @@ -36,7 +36,7 @@ impl Action for MoveUnpackedNix { span!( tracing::Level::DEBUG, "mount_unpacked_nix", - src = tracing::field::display(self.src.display()), + src = tracing::field::display(self.unpacked_path.display()), dest = DEST, ) } @@ -46,44 +46,56 @@ impl Action for MoveUnpackedNix { format!("Move the downloaded Nix into `/nix`"), vec![format!( "Nix is being downloaded to `{}` and should be in `/nix`", - self.src.display(), + self.unpacked_path.display(), )], )] } #[tracing::instrument(level = "debug", skip_all)] async fn execute(&mut self) -> Result<(), ActionError> { - let Self { src } = self; + let Self { unpacked_path } = self; - // TODO(@Hoverbear): I would like to make this less awful - let found_nix_paths = glob::glob(&format!("{}/nix-*", src.display())) + // This is the `nix-$VERSION` folder which unpacks from the tarball, not a nix derivation + let found_nix_paths = glob::glob(&format!("{}/nix-*", unpacked_path.display())) .map_err(|e| ActionError::Custom(Box::new(e)))? .collect::, _>>() .map_err(|e| ActionError::Custom(Box::new(e)))?; - assert_eq!( - found_nix_paths.len(), - 1, - "Did not expect to find multiple nix paths, please report this" - ); + if found_nix_paths.len() != 1 { + return Err(ActionError::MalformedBinaryTarball); + } let found_nix_path = found_nix_paths.into_iter().next().unwrap(); let src_store = found_nix_path.join("store"); - let dest = Path::new(DEST).join("store"); - tracing::trace!(src = %src_store.display(), dest = %dest.display(), "Renaming"); - tokio::fs::rename(&src_store, &dest) + let mut src_store_listing = tokio::fs::read_dir(src_store.clone()) .await - .map_err(|e| ActionError::Rename(src_store.clone(), dest.to_owned(), e))?; + .map_err(|e| ActionError::ReadDir(src_store.clone(), e))?; + let dest_store = Path::new(DEST).join("store"); + if dest_store.exists() { + if !dest_store.is_dir() { + return Err(ActionError::PathWasNotDirectory(dest_store.clone()))?; + } + } else { + tokio::fs::create_dir(&dest_store) + .await + .map_err(|e| ActionError::CreateDirectory(dest_store.clone(), e))?; + } - let src_reginfo = found_nix_path.join(".reginfo"); - - // Move_unpacked_nix expects it here - let dest_reginfo = Path::new(DEST).join(".reginfo"); - tokio::fs::rename(&src_reginfo, &dest_reginfo) + while let Some(entry) = src_store_listing + .next_entry() .await - .map_err(|e| ActionError::Rename(src_reginfo.clone(), dest_reginfo.to_owned(), e))?; - - tokio::fs::remove_dir_all(&src) - .await - .map_err(|e| ActionError::Remove(src.clone(), e))?; + .map_err(|e| ActionError::ReadDir(src_store.clone(), e))? + { + let entry_dest = dest_store.join(entry.file_name()); + if entry_dest.exists() { + tracing::trace!(src = %entry.path().display(), dest = %entry_dest.display(), "Skipping, already exists"); + } else { + tracing::trace!(src = %entry.path().display(), dest = %entry_dest.display(), "Renaming"); + tokio::fs::rename(&entry.path(), &entry_dest) + .await + .map_err(|e| { + ActionError::Rename(entry.path().clone(), entry_dest.to_owned(), e) + })?; + } + } Ok(()) } diff --git a/src/action/base/remove_directory.rs b/src/action/base/remove_directory.rs new file mode 100644 index 0000000..57ca1a6 --- /dev/null +++ b/src/action/base/remove_directory.rs @@ -0,0 +1,76 @@ +use std::path::{Path, PathBuf}; + +use tokio::fs::remove_dir_all; +use tracing::{span, Span}; + +use crate::action::{Action, ActionDescription, ActionState}; +use crate::action::{ActionError, StatefulAction}; + +/** Remove a directory, does nothing on revert. +*/ +#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] +pub struct RemoveDirectory { + path: PathBuf, +} + +impl RemoveDirectory { + #[tracing::instrument(level = "debug", skip_all)] + pub async fn plan(path: impl AsRef) -> Result, ActionError> { + let path = path.as_ref().to_path_buf(); + + Ok(StatefulAction { + action: Self { + path: path.to_path_buf(), + }, + state: ActionState::Uncompleted, + }) + } +} + +#[async_trait::async_trait] +#[typetag::serde(name = "remove_directory")] +impl Action for RemoveDirectory { + fn action_tag() -> crate::action::ActionTag { + crate::action::ActionTag("remove_directory") + } + fn tracing_synopsis(&self) -> String { + format!("Remove directory `{}`", self.path.display()) + } + + fn tracing_span(&self) -> Span { + span!( + tracing::Level::DEBUG, + "remove_directory", + path = tracing::field::display(self.path.display()), + ) + } + + fn execute_description(&self) -> Vec { + vec![ActionDescription::new(self.tracing_synopsis(), vec![])] + } + + #[tracing::instrument(level = "debug", skip_all)] + async fn execute(&mut self) -> Result<(), ActionError> { + if self.path.exists() { + if !self.path.is_dir() { + return Err(ActionError::PathWasNotDirectory(self.path.clone())); + } + remove_dir_all(&self.path) + .await + .map_err(|e| ActionError::Remove(self.path.clone(), e))?; + } else { + tracing::debug!("Directory `{}` not present, skipping", self.path.display(),); + }; + + Ok(()) + } + + fn revert_description(&self) -> Vec { + vec![] + } + + #[tracing::instrument(level = "debug", skip_all)] + async fn revert(&mut self) -> Result<(), ActionError> { + Ok(()) + } +} diff --git a/src/action/base/setup_default_profile.rs b/src/action/base/setup_default_profile.rs index cc10053..c10e064 100644 --- a/src/action/base/setup_default_profile.rs +++ b/src/action/base/setup_default_profile.rs @@ -1,4 +1,4 @@ -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use crate::{ action::{ActionError, ActionTag, StatefulAction}, @@ -16,12 +16,14 @@ use crate::action::{Action, ActionDescription}; Setup the default Nix profile with `nss-cacert` and `nix` itself. */ #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] -pub struct SetupDefaultProfile {} +pub struct SetupDefaultProfile { + unpacked_path: PathBuf, +} impl SetupDefaultProfile { #[tracing::instrument(level = "debug", skip_all)] - pub async fn plan() -> Result, ActionError> { - Ok(Self {}.into()) + pub async fn plan(unpacked_path: PathBuf) -> Result, ActionError> { + Ok(Self { unpacked_path }.into()) } } @@ -91,56 +93,61 @@ impl Action for SetupDefaultProfile { ))); }; - { - let reginfo_path = - Path::new(crate::action::base::move_unpacked_nix::DEST).join(".reginfo"); - let reginfo = tokio::fs::read(®info_path) - .await - .map_err(|e| ActionError::Read(reginfo_path.to_path_buf(), e))?; - let mut load_db_command = Command::new(nix_pkg.join("bin/nix-store")); - load_db_command.process_group(0); - load_db_command.arg("--load-db"); - load_db_command.stdin(std::process::Stdio::piped()); - load_db_command.stdout(std::process::Stdio::piped()); - load_db_command.stderr(std::process::Stdio::piped()); - load_db_command.env( - "HOME", - dirs::home_dir().ok_or_else(|| { - ActionError::Custom(Box::new(SetupDefaultProfileError::NoRootHome)) - })?, - ); - tracing::trace!( - "Executing `{:?}` with stdin from `{}`", - load_db_command.as_std(), - reginfo_path.display() - ); - let mut handle = load_db_command - .spawn() - .map_err(|e| ActionError::command(&load_db_command, e))?; - - let mut stdin = handle.stdin.take().unwrap(); - stdin - .write_all(®info) - .await - .map_err(|e| ActionError::Write(PathBuf::from("/dev/stdin"), e))?; - stdin - .flush() - .await - .map_err(|e| ActionError::Write(PathBuf::from("/dev/stdin"), e))?; - drop(stdin); - tracing::trace!( - "Wrote `{}` to stdin of `nix-store --load-db`", - reginfo_path.display() - ); - - let output = handle - .wait_with_output() - .await - .map_err(|e| ActionError::command(&load_db_command, e))?; - if !output.status.success() { - return Err(ActionError::command_output(&load_db_command, output)); - }; + let found_nix_paths = glob::glob(&format!("{}/nix-*", self.unpacked_path.display())) + .map_err(|e| ActionError::Custom(Box::new(e)))? + .collect::, _>>() + .map_err(|e| ActionError::Custom(Box::new(e)))?; + if found_nix_paths.len() != 1 { + return Err(ActionError::MalformedBinaryTarball); } + let found_nix_path = found_nix_paths.into_iter().next().unwrap(); + let reginfo_path = PathBuf::from(found_nix_path).join(".reginfo"); + let reginfo = tokio::fs::read(®info_path) + .await + .map_err(|e| ActionError::Read(reginfo_path.to_path_buf(), e))?; + let mut load_db_command = Command::new(nix_pkg.join("bin/nix-store")); + load_db_command.process_group(0); + load_db_command.arg("--load-db"); + load_db_command.stdin(std::process::Stdio::piped()); + load_db_command.stdout(std::process::Stdio::piped()); + load_db_command.stderr(std::process::Stdio::piped()); + load_db_command.env( + "HOME", + dirs::home_dir().ok_or_else(|| { + ActionError::Custom(Box::new(SetupDefaultProfileError::NoRootHome)) + })?, + ); + tracing::trace!( + "Executing `{:?}` with stdin from `{}`", + load_db_command.as_std(), + reginfo_path.display() + ); + let mut handle = load_db_command + .spawn() + .map_err(|e| ActionError::command(&load_db_command, e))?; + + let mut stdin = handle.stdin.take().unwrap(); + stdin + .write_all(®info) + .await + .map_err(|e| ActionError::Write(PathBuf::from("/dev/stdin"), e))?; + stdin + .flush() + .await + .map_err(|e| ActionError::Write(PathBuf::from("/dev/stdin"), e))?; + drop(stdin); + tracing::trace!( + "Wrote `{}` to stdin of `nix-store --load-db`", + reginfo_path.display() + ); + + let output = handle + .wait_with_output() + .await + .map_err(|e| ActionError::command(&load_db_command, e))?; + if !output.status.success() { + return Err(ActionError::command_output(&load_db_command, output)); + }; // Install `nix` itself into the store execute_command( diff --git a/src/action/common/configure_init_service.rs b/src/action/common/configure_init_service.rs index 8c4e470..583a257 100644 --- a/src/action/common/configure_init_service.rs +++ b/src/action/common/configure_init_service.rs @@ -1,4 +1,4 @@ -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use tokio::process::Command; use tracing::{span, Span}; @@ -138,15 +138,17 @@ impl Action for ConfigureInitService { #[cfg(target_os = "linux")] InitSystem::Systemd => { tracing::trace!(src = TMPFILES_SRC, dest = TMPFILES_DEST, "Symlinking"); - tokio::fs::symlink(TMPFILES_SRC, TMPFILES_DEST) - .await - .map_err(|e| { - ActionError::Symlink( - PathBuf::from(TMPFILES_SRC), - PathBuf::from(TMPFILES_DEST), - e, - ) - })?; + if !Path::new(TMPFILES_DEST).exists() { + tokio::fs::symlink(TMPFILES_SRC, TMPFILES_DEST) + .await + .map_err(|e| { + ActionError::Symlink( + PathBuf::from(TMPFILES_SRC), + PathBuf::from(TMPFILES_DEST), + e, + ) + })?; + } execute_command( Command::new("systemd-tmpfiles") diff --git a/src/action/common/configure_nix.rs b/src/action/common/configure_nix.rs index 64b3b4a..029c689 100644 --- a/src/action/common/configure_nix.rs +++ b/src/action/common/configure_nix.rs @@ -1,10 +1,12 @@ +use std::path::PathBuf; + use crate::{ action::{ base::SetupDefaultProfile, common::{ConfigureShellProfile, PlaceNixConfiguration}, Action, ActionDescription, ActionError, ActionTag, StatefulAction, }, - settings::CommonSettings, + settings::{CommonSettings, SCRATCH_DIR}, }; use tracing::{span, Instrument, Span}; @@ -22,7 +24,7 @@ pub struct ConfigureNix { impl ConfigureNix { #[tracing::instrument(level = "debug", skip_all)] pub async fn plan(settings: &CommonSettings) -> Result, ActionError> { - let setup_default_profile = SetupDefaultProfile::plan() + let setup_default_profile = SetupDefaultProfile::plan(PathBuf::from(SCRATCH_DIR)) .await .map_err(|e| ActionError::Child(SetupDefaultProfile::action_tag(), Box::new(e)))?; diff --git a/src/action/common/provision_nix.rs b/src/action/common/provision_nix.rs index d28d9a9..f9c86ab 100644 --- a/src/action/common/provision_nix.rs +++ b/src/action/common/provision_nix.rs @@ -6,7 +6,7 @@ use crate::{ base::{FetchAndUnpackNix, MoveUnpackedNix}, Action, ActionDescription, ActionError, ActionTag, StatefulAction, }, - settings::CommonSettings, + settings::{CommonSettings, SCRATCH_DIR}, }; use std::path::PathBuf; @@ -24,18 +24,16 @@ pub struct ProvisionNix { impl ProvisionNix { #[tracing::instrument(level = "debug", skip_all)] pub async fn plan(settings: &CommonSettings) -> Result, ActionError> { - let fetch_nix = FetchAndUnpackNix::plan( - settings.nix_package_url.clone(), - PathBuf::from("/nix/temp-install-dir"), - ) - .await?; + let fetch_nix = + FetchAndUnpackNix::plan(settings.nix_package_url.clone(), PathBuf::from(SCRATCH_DIR)) + .await?; let create_users_and_group = CreateUsersAndGroups::plan(settings.clone()) .await .map_err(|e| ActionError::Child(CreateUsersAndGroups::action_tag(), Box::new(e)))?; let create_nix_tree = CreateNixTree::plan() .await .map_err(|e| ActionError::Child(CreateNixTree::action_tag(), Box::new(e)))?; - let move_unpacked_nix = MoveUnpackedNix::plan(PathBuf::from("/nix/temp-install-dir")) + let move_unpacked_nix = MoveUnpackedNix::plan(PathBuf::from(SCRATCH_DIR)) .await .map_err(|e| ActionError::Child(MoveUnpackedNix::action_tag(), Box::new(e)))?; Ok(Self { diff --git a/src/action/mod.rs b/src/action/mod.rs index f36a10e..87795bb 100644 --- a/src/action/mod.rs +++ b/src/action/mod.rs @@ -311,8 +311,10 @@ pub enum ActionError { existing_mode = .1 & 0o777, planned_mode = .2 & 0o777)] PathModeMismatch(std::path::PathBuf, u32, u32), - #[error("`{0}` was not a file")] + #[error("Path `{0}` exists, but is not a file, consider removing it with `rm {0}`")] PathWasNotFile(std::path::PathBuf), + #[error("Path `{0}` exists, but is not a directory, consider removing it with `rm {0}`")] + PathWasNotDirectory(std::path::PathBuf), #[error("Getting metadata for {0}`")] GettingMetadata(std::path::PathBuf, #[source] std::io::Error), #[error("Creating directory `{0}`")] @@ -341,6 +343,8 @@ pub enum ActionError { ), #[error("Read path `{0}`")] Read(std::path::PathBuf, #[source] std::io::Error), + #[error("Reading directory `{0}`")] + ReadDir(std::path::PathBuf, #[source] std::io::Error), #[error("Open path `{0}`")] Open(std::path::PathBuf, #[source] std::io::Error), #[error("Write path `{0}`")] @@ -410,6 +414,8 @@ pub enum ActionError { /// A MacOS (Darwin) plist related error #[error(transparent)] Plist(#[from] plist::Error), + #[error("Unexpected binary tarball contents found, the build result from `https://releases.nixos.org/?prefix=nix/` or `nix build nix#hydraJobs.binaryTarball.$SYSTEM` is expected")] + MalformedBinaryTarball, } impl ActionError { diff --git a/src/cli/subcommand/install.rs b/src/cli/subcommand/install.rs index 3923276..4efce9e 100644 --- a/src/cli/subcommand/install.rs +++ b/src/cli/subcommand/install.rs @@ -71,6 +71,7 @@ impl CommandExecute for Install { let existing_receipt: Option = match Path::new(RECEIPT_LOCATION).exists() { true => { + tracing::trace!("Reading existing receipt"); let install_plan_string = tokio::fs::read_to_string(&RECEIPT_LOCATION) .await .wrap_err("Reading plan")?; @@ -79,6 +80,11 @@ impl CommandExecute for Install { false => None, }; + let uninstall_command = match Path::new("/nix/nix-installer").exists() { + true => "/nix/nix-installer uninstall".into(), + false => format!("curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix/tag/v{} | sh -s -- uninstall", env!("CARGO_PKG_VERSION")), + }; + let mut install_plan = match (planner, plan) { (Some(planner), None) => { let chosen_planner: Box = planner.clone().boxed(); @@ -86,18 +92,15 @@ impl CommandExecute for Install { match existing_receipt { Some(existing_receipt) => { if existing_receipt.planner.typetag_name() != chosen_planner.typetag_name() { - eprintln!("{}", format!("Found existing plan in `{RECEIPT_LOCATION}` which used a different planner, try uninstalling the existing install").red()); + eprintln!("{}", format!("Found existing plan in `{RECEIPT_LOCATION}` which used a different planner, try uninstalling the existing install with `{uninstall_command}`").red()); return Ok(ExitCode::FAILURE) } if existing_receipt.planner.settings().map_err(|e| eyre!(e))? != chosen_planner.settings().map_err(|e| eyre!(e))? { - eprintln!("{}", format!("Found existing plan in `{RECEIPT_LOCATION}` which used different planner settings, try uninstalling the existing install").red()); + eprintln!("{}", format!("Found existing plan in `{RECEIPT_LOCATION}` which used different planner settings, try uninstalling the existing install with `{uninstall_command}`").red()); return Ok(ExitCode::FAILURE) } - if existing_receipt.actions.iter().all(|v| v.state == ActionState::Completed) { - eprintln!("{}", format!("Found existing plan in `{RECEIPT_LOCATION}`, with the same settings, already completed, try uninstalling and reinstalling if Nix isn't working").red()); - return Ok(ExitCode::FAILURE) - } - existing_receipt + eprintln!("{}", format!("Found existing plan in `{RECEIPT_LOCATION}`, with the same settings, already completed, try uninstalling (`{uninstall_command}`) and reinstalling if Nix isn't working").red()); + return Ok(ExitCode::FAILURE) } , None => { planner.plan().await.map_err(|e| eyre!(e))? @@ -114,18 +117,19 @@ impl CommandExecute for Install { let builtin_planner = BuiltinPlanner::from_common_settings(settings) .await .map_err(|e| eyre::eyre!(e))?; + match existing_receipt { Some(existing_receipt) => { if existing_receipt.planner.typetag_name() != builtin_planner.typetag_name() { - eprintln!("{}", format!("Found existing plan in `{RECEIPT_LOCATION}` which used a different planner, try uninstalling the existing install").red()); + eprintln!("{}", format!("Found existing plan in `{RECEIPT_LOCATION}` which used a different planner, try uninstalling the existing install with `{uninstall_command}`").red()); return Ok(ExitCode::FAILURE) } if existing_receipt.planner.settings().map_err(|e| eyre!(e))? != builtin_planner.settings().map_err(|e| eyre!(e))? { - eprintln!("{}", format!("Found existing plan in `{RECEIPT_LOCATION}` which used different planner settings, try uninstalling the existing install").red()); + eprintln!("{}", format!("Found existing plan in `{RECEIPT_LOCATION}` which used different planner settings, try uninstalling the existing install with `{uninstall_command}`").red()); return Ok(ExitCode::FAILURE) } if existing_receipt.actions.iter().all(|v| v.state == ActionState::Completed) { - eprintln!("{}", format!("Found existing plan in `{RECEIPT_LOCATION}`, with the same settings, already completed, try uninstalling and reinstalling if Nix isn't working").red()); + eprintln!("{}", format!("Found existing plan in `{RECEIPT_LOCATION}`, with the same settings, already completed, try uninstalling (`{uninstall_command}`) and reinstalling if Nix isn't working").red()); return Ok(ExitCode::FAILURE) } existing_receipt diff --git a/src/planner/linux.rs b/src/planner/linux.rs index 7b947e5..cd09347 100644 --- a/src/planner/linux.rs +++ b/src/planner/linux.rs @@ -1,6 +1,6 @@ use crate::{ action::{ - base::CreateDirectory, + base::{CreateDirectory, RemoveDirectory}, common::{ConfigureInitService, ConfigureNix, ProvisionNix}, StatefulAction, }, @@ -88,6 +88,10 @@ impl Planner for Linux { .await .map_err(PlannerError::Action)? .boxed(), + RemoveDirectory::plan(crate::settings::SCRATCH_DIR) + .await + .map_err(PlannerError::Action)? + .boxed(), ]) } diff --git a/src/planner/macos.rs b/src/planner/macos.rs index 351f182..037f7fa 100644 --- a/src/planner/macos.rs +++ b/src/planner/macos.rs @@ -6,6 +6,7 @@ use tokio::process::Command; use crate::{ action::{ + base::RemoveDirectory, common::{ConfigureInitService, ConfigureNix, ProvisionNix}, macos::CreateNixVolume, StatefulAction, @@ -145,6 +146,10 @@ impl Planner for Macos { .await .map_err(PlannerError::Action)? .boxed(), + RemoveDirectory::plan(crate::settings::SCRATCH_DIR) + .await + .map_err(PlannerError::Action)? + .boxed(), ]) } diff --git a/src/planner/steam_deck.rs b/src/planner/steam_deck.rs index 8b52b07..d4fbce9 100644 --- a/src/planner/steam_deck.rs +++ b/src/planner/steam_deck.rs @@ -63,7 +63,7 @@ use std::{collections::HashMap, path::PathBuf}; use crate::{ action::{ - base::{CreateDirectory, CreateFile}, + base::{CreateDirectory, CreateFile, RemoveDirectory}, common::{ConfigureInitService, ConfigureNix, ProvisionNix}, linux::StartSystemdUnit, Action, StatefulAction, @@ -234,6 +234,10 @@ impl Planner for SteamDeck { .await .map_err(PlannerError::Action)? .boxed(), + RemoveDirectory::plan(crate::settings::SCRATCH_DIR) + .await + .map_err(PlannerError::Action)? + .boxed(), ]) } diff --git a/src/settings.rs b/src/settings.rs index 5d9263e..29fe90b 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -6,6 +6,8 @@ use std::collections::HashMap; use clap::ArgAction; use url::Url; +pub const SCRATCH_DIR: &str = "/nix/temp-install-dir"; + /// Default [`nix_package_url`](CommonSettings::nix_package_url) for Linux x86_64 pub const NIX_X64_64_LINUX_URL: &str = "https://releases.nixos.org/nix/nix-2.13.3/nix-2.13.3-x86_64-linux.tar.xz"; diff --git a/tests/fixtures/linux/linux.json b/tests/fixtures/linux/linux.json index 9b4c708..4921d4d 100644 --- a/tests/fixtures/linux/linux.json +++ b/tests/fixtures/linux/linux.json @@ -758,7 +758,7 @@ }, "move_unpacked_nix": { "action": { - "src": "/nix/temp-install-dir" + "unpacked_path": "/nix/temp-install-dir" }, "state": "Uncompleted" } @@ -775,7 +775,8 @@ "nixpkgs", "https://nixos.org/channels/nixpkgs-unstable" ] - ] + ], + "unpacked_path": "/nix/temp-install-dir" }, "state": "Uncompleted" }, diff --git a/tests/fixtures/linux/steam-deck.json b/tests/fixtures/linux/steam-deck.json index 50bfb4a..4d7316f 100644 --- a/tests/fixtures/linux/steam-deck.json +++ b/tests/fixtures/linux/steam-deck.json @@ -802,7 +802,7 @@ }, "move_unpacked_nix": { "action": { - "src": "/nix/temp-install-dir" + "unpacked_path": "/nix/temp-install-dir" }, "state": "Uncompleted" } @@ -819,7 +819,8 @@ "nixpkgs", "https://nixos.org/channels/nixpkgs-unstable" ] - ] + ], + "unpacked_path": "/nix/temp-install-dir" }, "state": "Uncompleted" }, diff --git a/tests/fixtures/macos/macos.json b/tests/fixtures/macos/macos.json index a6595c1..8ed43c2 100644 --- a/tests/fixtures/macos/macos.json +++ b/tests/fixtures/macos/macos.json @@ -823,7 +823,7 @@ }, "move_unpacked_nix": { "action": { - "src": "/nix/temp-install-dir" + "unpacked_path": "/nix/temp-install-dir" }, "state": "Uncompleted" } @@ -840,7 +840,8 @@ "nixpkgs", "https://nixos.org/channels/nixpkgs-unstable" ] - ] + ], + "unpacked_path": "/nix/temp-install-dir" }, "state": "Uncompleted" },