diff --git a/flake.nix b/flake.nix index 5cb1e32da..17d594a27 100644 --- a/flake.nix +++ b/flake.nix @@ -233,6 +233,10 @@ default = pkgs.nix-installer-static; } // nixpkgs.lib.optionalAttrs (pkgs.stdenv.isDarwin) { default = pkgs.nix-installer; + + determinate-nixd = pkgs.runCommand "determinate-nixd-link" { } '' + ln -s ${optionalPathToDeterminateNixd system} $out + ''; }); hydraJobs = { diff --git a/src/action/base/create_directory.rs b/src/action/base/create_directory.rs index a28b95e2c..c60e819c0 100644 --- a/src/action/base/create_directory.rs +++ b/src/action/base/create_directory.rs @@ -4,13 +4,13 @@ use std::path::{Path, PathBuf}; use nix::unistd::{chown, Group, User}; use target_lexicon::OperatingSystem; -use tokio::fs::{create_dir_all, remove_dir_all, remove_file}; use tokio::process::Command; use tracing::{span, Span}; use crate::action::{Action, ActionDescription, ActionErrorKind, ActionState}; use crate::action::{ActionError, StatefulAction}; use crate::execute_command; +use crate::util::OnMissing; /** Create a directory at the given location, optionally with an owning user, group, and mode. @@ -184,7 +184,7 @@ impl Action for CreateDirectory { None }; - create_dir_all(&path) + tokio::fs::create_dir_all(&path) .await .map_err(|e| ActionErrorKind::CreateDirectory(path.clone(), e)) .map_err(Self::error)?; @@ -263,12 +263,12 @@ impl Action for CreateDirectory { .map_err(|e| ActionErrorKind::GettingMetadata(child_path_path.clone(), e)) .map_err(Self::error)?; if child_path_type.is_dir() { - remove_dir_all(child_path_path.clone()) + crate::util::remove_dir_all(&child_path_path, OnMissing::Error) .await .map_err(|e| ActionErrorKind::Remove(path.clone(), e)) .map_err(Self::error)? } else { - remove_file(child_path_path) + crate::util::remove_file(&child_path_path, OnMissing::Error) .await .map_err(|e| ActionErrorKind::Remove(path.clone(), e)) .map_err(Self::error)? @@ -278,10 +278,12 @@ impl Action for CreateDirectory { (true, _, false) => { tracing::debug!("Not cleaning mountpoint `{}`", path.display()); }, - (false, true, _) | (false, false, true) => remove_dir_all(path.clone()) - .await - .map_err(|e| ActionErrorKind::Remove(path.clone(), e)) - .map_err(Self::error)?, + (false, true, _) | (false, false, true) => { + crate::util::remove_dir_all(&path, OnMissing::Error) + .await + .map_err(|e| ActionErrorKind::Remove(path.clone(), e)) + .map_err(Self::error)? + }, (false, false, false) => { tracing::debug!("Not removing `{}`, the folder is not empty", path.display()); }, diff --git a/src/action/base/create_file.rs b/src/action/base/create_file.rs index f5003f0f2..82cdd4c8c 100644 --- a/src/action/base/create_file.rs +++ b/src/action/base/create_file.rs @@ -6,12 +6,13 @@ use std::{ path::{Path, PathBuf}, }; use tokio::{ - fs::{remove_file, File, OpenOptions}, + fs::{File, OpenOptions}, io::{AsyncReadExt, AsyncWriteExt}, }; -use crate::action::{ - Action, ActionDescription, ActionError, ActionErrorKind, ActionTag, StatefulAction, +use crate::{ + action::{Action, ActionDescription, ActionError, ActionErrorKind, ActionTag, StatefulAction}, + util::OnMissing, }; /** Create a file at the given location with the provided `buf`, @@ -258,12 +259,8 @@ impl Action for CreateFile { buf: _, force: _, } = self; - // The user already deleted it - if !path.exists() { - return Ok(()); - } - remove_file(&path) + crate::util::remove_file(&path, OnMissing::Ignore) .await .map_err(|e| ActionErrorKind::Remove(path.to_owned(), e)) .map_err(Self::error)?; diff --git a/src/action/base/move_unpacked_nix.rs b/src/action/base/move_unpacked_nix.rs index c2c18828d..b4248f41a 100644 --- a/src/action/base/move_unpacked_nix.rs +++ b/src/action/base/move_unpacked_nix.rs @@ -6,8 +6,9 @@ use std::{ use tracing::{span, Span}; use walkdir::WalkDir; -use crate::action::{ - Action, ActionDescription, ActionError, ActionErrorKind, ActionTag, StatefulAction, +use crate::{ + action::{Action, ActionDescription, ActionError, ActionErrorKind, ActionTag, StatefulAction}, + util::OnMissing, }; pub(crate) const DEST: &str = "/nix/"; @@ -99,7 +100,7 @@ impl Action for MoveUnpackedNix { let entry_dest = dest_store.join(entry.file_name()); if entry_dest.exists() { tracing::trace!(src = %entry.path().display(), dest = %entry_dest.display(), "Removing already existing package"); - tokio::fs::remove_dir_all(&entry_dest) + crate::util::remove_dir_all(&entry_dest, OnMissing::Ignore) .await .map_err(|e| ActionErrorKind::Remove(entry_dest.clone(), e)) .map_err(Self::error)?; diff --git a/src/action/base/remove_directory.rs b/src/action/base/remove_directory.rs index d2dd73b38..858433e05 100644 --- a/src/action/base/remove_directory.rs +++ b/src/action/base/remove_directory.rs @@ -1,10 +1,10 @@ use std::path::{Path, PathBuf}; -use tokio::fs::remove_dir_all; use tracing::{span, Span}; use crate::action::{Action, ActionDescription, ActionErrorKind, ActionState}; use crate::action::{ActionError, StatefulAction}; +use crate::util::OnMissing; /** Remove a directory, does nothing on revert. */ @@ -56,7 +56,10 @@ impl Action for RemoveDirectory { self.path.clone(), ))); } - remove_dir_all(&self.path) + + // At this point, we know the path exists, but just in case it was deleted between then + // and now, we still ignore the case where it no longer exists. + crate::util::remove_dir_all(&self.path, OnMissing::Ignore) .await .map_err(|e| Self::error(ActionErrorKind::Remove(self.path.clone(), e)))?; } else { diff --git a/src/action/common/configure_determinate_nixd_init_service/mod.rs b/src/action/common/configure_determinate_nixd_init_service/mod.rs index a53884d19..c78954fb4 100644 --- a/src/action/common/configure_determinate_nixd_init_service/mod.rs +++ b/src/action/common/configure_determinate_nixd_init_service/mod.rs @@ -1,5 +1,5 @@ use std::collections::HashMap; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use serde::{Deserialize, Serialize}; use tokio::io::AsyncWriteExt; @@ -9,6 +9,7 @@ use crate::action::common::configure_init_service::{SocketFile, UnitSrc}; use crate::action::{common::ConfigureInitService, Action, ActionDescription}; use crate::action::{ActionError, ActionErrorKind, ActionTag, StatefulAction}; use crate::settings::InitSystem; +use crate::util::OnMissing; // Linux const LINUX_NIXD_DAEMON_DEST: &str = "/etc/systemd/system/nix-daemon.service"; @@ -44,22 +45,17 @@ impl ConfigureDeterminateNixdInitService { // these service files wouldn't get removed, so we can't rely on them not being // there after phase 1 of the uninstall // [1]: https://github.com/DeterminateSystems/nix-installer/pull/1266 - if std::path::Path::new( - super::configure_upstream_init_service::DARWIN_NIX_DAEMON_DEST, + crate::util::remove_file( + Path::new(super::configure_upstream_init_service::DARWIN_NIX_DAEMON_DEST), + OnMissing::Ignore, ) - .exists() - { - tokio::fs::remove_file( - super::configure_upstream_init_service::DARWIN_NIX_DAEMON_DEST, - ) - .await - .map_err(|e| { - Self::error(ActionErrorKind::Remove( - super::configure_upstream_init_service::DARWIN_NIX_DAEMON_DEST.into(), - e, - )) - })?; - } + .await + .map_err(|e| { + Self::error(ActionErrorKind::Remove( + super::configure_upstream_init_service::DARWIN_NIX_DAEMON_DEST.into(), + e, + )) + })?; Some(DARWIN_NIXD_DAEMON_DEST.into()) }, diff --git a/src/action/common/configure_init_service.rs b/src/action/common/configure_init_service.rs index 128fd6550..3fa847190 100644 --- a/src/action/common/configure_init_service.rs +++ b/src/action/common/configure_init_service.rs @@ -10,6 +10,7 @@ use crate::execute_command; use crate::action::{Action, ActionDescription}; use crate::settings::InitSystem; +use crate::util::OnMissing; const TMPFILES_SRC: &str = "/nix/var/nix/profiles/default/lib/tmpfiles.d/nix-daemon.conf"; const TMPFILES_DEST: &str = "/etc/tmpfiles.d/nix-daemon.conf"; @@ -360,13 +361,12 @@ impl Action for ConfigureInitService { ) .await .map_err(Self::error)?; - if Path::new(service_dest).exists() { - tracing::trace!(path = %service_dest.display(), "Removing"); - tokio::fs::remove_file(service_dest) - .await - .map_err(|e| ActionErrorKind::Remove(service_dest.into(), e)) - .map_err(Self::error)?; - } + + crate::util::remove_file(service_dest, OnMissing::Ignore) + .await + .map_err(|e| ActionErrorKind::Remove(service_dest.into(), e)) + .map_err(Self::error)?; + tracing::trace!(src = %service_src.display(), dest = %service_dest.display(), "Symlinking"); tokio::fs::symlink(service_src, service_dest) .await @@ -384,13 +384,10 @@ impl Action for ConfigureInitService { Self::check_if_systemd_unit_exists(src, dest) .await .map_err(Self::error)?; - if Path::new(dest).exists() { - tracing::trace!(path = %dest.display(), "Removing"); - tokio::fs::remove_file(dest) - .await - .map_err(|e| ActionErrorKind::Remove(dest.into(), e)) - .map_err(Self::error)?; - } + crate::util::remove_file(dest, OnMissing::Ignore) + .await + .map_err(|e| ActionErrorKind::Remove(dest.into(), e)) + .map_err(Self::error)?; match src { UnitSrc::Path(src) => { @@ -610,13 +607,12 @@ impl Action for ConfigureInitService { errors.push(err); } - if Path::new(TMPFILES_DEST).exists() { - if let Err(err) = tokio::fs::remove_file(TMPFILES_DEST) + if let Err(err) = + crate::util::remove_file(Path::new(TMPFILES_DEST), OnMissing::Ignore) .await .map_err(|e| ActionErrorKind::Remove(PathBuf::from(TMPFILES_DEST), e)) - { - errors.push(err); - } + { + errors.push(err); } if let Err(err) = execute_command( @@ -636,26 +632,20 @@ impl Action for ConfigureInitService { }; if let Some(dest) = &self.service_dest { - if dest.exists() { - tracing::trace!(path = %dest.display(), "Removing"); - if let Err(err) = tokio::fs::remove_file(dest) - .await - .map_err(|e| ActionErrorKind::Remove(PathBuf::from(dest), e)) - { - errors.push(err); - } + if let Err(err) = crate::util::remove_file(dest, OnMissing::Ignore) + .await + .map_err(|e| ActionErrorKind::Remove(PathBuf::from(dest), e)) + { + errors.push(err); } } for socket in self.socket_files.iter() { - if socket.dest.exists() { - tracing::trace!(path = %socket.dest.display(), "Removing"); - if let Err(err) = tokio::fs::remove_file(&socket.dest) - .await - .map_err(|e| ActionErrorKind::Remove(socket.dest.to_path_buf(), e)) - { - errors.push(err); - } + if let Err(err) = crate::util::remove_file(&socket.dest, OnMissing::Ignore) + .await + .map_err(|e| ActionErrorKind::Remove(socket.dest.to_path_buf(), e)) + { + errors.push(err); } } diff --git a/src/action/common/configure_nix.rs b/src/action/common/configure_nix.rs index 665b19d4a..35b0ed23f 100644 --- a/src/action/common/configure_nix.rs +++ b/src/action/common/configure_nix.rs @@ -11,7 +11,7 @@ use crate::{ }; use glob::glob; -use tracing::{span, Instrument, Span}; +use tracing::{span, Span}; /** Configure Nix and start it @@ -21,7 +21,7 @@ Configure Nix and start it pub struct ConfigureNix { setup_default_profile: StatefulAction, configure_shell_profile: Option>, - place_nix_configuration: StatefulAction, + place_nix_configuration: Option>, } impl ConfigureNix { @@ -44,16 +44,23 @@ impl ConfigureNix { } else { None }; - let place_nix_configuration = PlaceNixConfiguration::plan( - settings.nix_build_group_name.clone(), - settings.proxy.clone(), - settings.ssl_cert_file.clone(), - extra_internal_conf.clone(), - settings.extra_conf.clone(), - settings.force, - ) - .await - .map_err(Self::error)?; + + let place_nix_configuration = if settings.skip_nix_conf { + None + } else { + Some( + PlaceNixConfiguration::plan( + settings.nix_build_group_name.clone(), + settings.proxy.clone(), + settings.ssl_cert_file.clone(), + extra_internal_conf.clone(), + settings.extra_conf.clone(), + settings.force, + ) + .await + .map_err(Self::error)?, + ) + }; Ok(Self { place_nix_configuration, @@ -145,7 +152,9 @@ impl Action for ConfigureNix { } = &self; let mut buf = setup_default_profile.describe_execute(); - buf.append(&mut place_nix_configuration.describe_execute()); + if let Some(place_nix_configuration) = place_nix_configuration { + buf.append(&mut place_nix_configuration.describe_execute()); + } if let Some(configure_shell_profile) = configure_shell_profile { buf.append(&mut configure_shell_profile.describe_execute()); } @@ -160,55 +169,22 @@ impl Action for ConfigureNix { configure_shell_profile, } = self; + setup_default_profile + .try_execute() + .await + .map_err(Self::error)?; + if let Some(place_nix_configuration) = place_nix_configuration { + place_nix_configuration + .try_execute() + .await + .map_err(Self::error)?; + } if let Some(configure_shell_profile) = configure_shell_profile { - let setup_default_profile_span = tracing::Span::current().clone(); - let (place_nix_configuration_span, configure_shell_profile_span) = ( - setup_default_profile_span.clone(), - setup_default_profile_span.clone(), - ); - tokio::try_join!( - async move { - setup_default_profile - .try_execute() - .instrument(setup_default_profile_span) - .await - .map_err(Self::error) - }, - async move { - place_nix_configuration - .try_execute() - .instrument(place_nix_configuration_span) - .await - .map_err(Self::error) - }, - async move { - configure_shell_profile - .try_execute() - .instrument(configure_shell_profile_span) - .await - .map_err(Self::error) - }, - )?; - } else { - let setup_default_profile_span = tracing::Span::current().clone(); - let place_nix_configuration_span = setup_default_profile_span.clone(); - tokio::try_join!( - async move { - setup_default_profile - .try_execute() - .instrument(setup_default_profile_span) - .await - .map_err(Self::error) - }, - async move { - place_nix_configuration - .try_execute() - .instrument(place_nix_configuration_span) - .await - .map_err(Self::error) - }, - )?; - }; + configure_shell_profile + .try_execute() + .await + .map_err(Self::error)?; + } Ok(()) } @@ -224,7 +200,9 @@ impl Action for ConfigureNix { if let Some(configure_shell_profile) = configure_shell_profile { buf.append(&mut configure_shell_profile.describe_revert()); } - buf.append(&mut place_nix_configuration.describe_revert()); + if let Some(place_nix_configuration) = place_nix_configuration { + buf.append(&mut place_nix_configuration.describe_revert()); + } buf.append(&mut setup_default_profile.describe_revert()); buf @@ -238,8 +216,10 @@ impl Action for ConfigureNix { errors.push(err); } } - if let Err(err) = self.place_nix_configuration.try_revert().await { - errors.push(err); + if let Some(place_nix_configuration) = &mut self.place_nix_configuration { + if let Err(err) = place_nix_configuration.try_revert().await { + errors.push(err); + } } if let Err(err) = self.setup_default_profile.try_revert().await { errors.push(err); diff --git a/src/action/common/configure_upstream_init_service.rs b/src/action/common/configure_upstream_init_service.rs index 68a57210a..b74972df2 100644 --- a/src/action/common/configure_upstream_init_service.rs +++ b/src/action/common/configure_upstream_init_service.rs @@ -1,4 +1,4 @@ -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use tracing::{span, Span}; @@ -7,6 +7,7 @@ use crate::action::{ActionError, ActionErrorKind, ActionTag, StatefulAction}; use crate::action::common::configure_init_service::{SocketFile, UnitSrc}; use crate::action::{common::ConfigureInitService, Action, ActionDescription}; use crate::settings::InitSystem; +use crate::util::OnMissing; // Linux const SERVICE_SRC: &str = "/nix/var/nix/profiles/default/lib/systemd/system/nix-daemon.service"; @@ -45,23 +46,20 @@ impl ConfigureUpstreamInitService { // these service files wouldn't get removed, so we can't rely on them not being // there after phase 1 of the uninstall // [1]: https://github.com/DeterminateSystems/nix-installer/pull/1266 - if std::path::Path::new( - super::configure_determinate_nixd_init_service::DARWIN_NIXD_DAEMON_DEST, - ) - .exists() - { - tokio::fs::remove_file( + crate::util::remove_file( + Path::new( super::configure_determinate_nixd_init_service::DARWIN_NIXD_DAEMON_DEST, - ) - .await - .map_err(|e| { - Self::error(ActionErrorKind::Remove( - super::configure_determinate_nixd_init_service::DARWIN_NIXD_DAEMON_DEST - .into(), - e, - )) - })?; - } + ), + OnMissing::Ignore, + ) + .await + .map_err(|e| { + Self::error(ActionErrorKind::Remove( + super::configure_determinate_nixd_init_service::DARWIN_NIXD_DAEMON_DEST + .into(), + e, + )) + })?; Some(DARWIN_NIX_DAEMON_DEST.into()) }, diff --git a/src/action/common/place_nix_configuration.rs b/src/action/common/place_nix_configuration.rs index 27d2f049a..0df21cfd2 100644 --- a/src/action/common/place_nix_configuration.rs +++ b/src/action/common/place_nix_configuration.rs @@ -15,7 +15,7 @@ pub const NIX_CONF_FOLDER: &str = "/etc/nix"; const NIX_CONF: &str = "/etc/nix/nix.conf"; /** -Place the `/etc/nix.conf` file +Place the `/etc/nix/nix.conf` file */ #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[serde(tag = "action_name", rename = "place_nix_configuration")] diff --git a/src/action/common/provision_determinate_nixd.rs b/src/action/common/provision_determinate_nixd.rs index 04fc31dfc..b144028c8 100644 --- a/src/action/common/provision_determinate_nixd.rs +++ b/src/action/common/provision_determinate_nixd.rs @@ -1,11 +1,11 @@ use std::os::unix::fs::PermissionsExt; use std::path::PathBuf; -use tokio::fs::{create_dir_all, remove_file}; use tracing::{span, Span}; -use crate::action::{ - Action, ActionDescription, ActionError, ActionErrorKind, ActionTag, StatefulAction, +use crate::{ + action::{Action, ActionDescription, ActionError, ActionErrorKind, ActionTag, StatefulAction}, + util::OnMissing, }; const DETERMINATE_NIXD_BINARY_PATH: &str = "/usr/local/bin/determinate-nixd"; @@ -62,15 +62,13 @@ impl Action for ProvisionDeterminateNixd { let bytes = crate::settings::DETERMINATE_NIXD_BINARY .ok_or_else(|| Self::error(ActionErrorKind::DeterminateNixUnavailable))?; - if self.binary_location.exists() { - remove_file(&self.binary_location) - .await - .map_err(|e| ActionErrorKind::Remove(self.binary_location.clone(), e)) - .map_err(Self::error)?; - } + crate::util::remove_file(&self.binary_location, OnMissing::Ignore) + .await + .map_err(|e| ActionErrorKind::Remove(self.binary_location.clone(), e)) + .map_err(Self::error)?; if let Some(parent) = self.binary_location.parent() { - create_dir_all(&parent) + tokio::fs::create_dir_all(&parent) .await .map_err(|e| ActionErrorKind::CreateDirectory(parent.into(), e)) .map_err(Self::error)?; @@ -98,12 +96,10 @@ impl Action for ProvisionDeterminateNixd { #[tracing::instrument(level = "debug", skip_all)] async fn revert(&mut self) -> Result<(), ActionError> { - if self.binary_location.exists() { - remove_file(&self.binary_location) - .await - .map_err(|e| ActionErrorKind::Remove(self.binary_location.clone(), e)) - .map_err(Self::error)?; - } + crate::util::remove_file(&self.binary_location, OnMissing::Ignore) + .await + .map_err(|e| ActionErrorKind::Remove(self.binary_location.clone(), e)) + .map_err(Self::error)?; Ok(()) } diff --git a/src/action/linux/provision_selinux.rs b/src/action/linux/provision_selinux.rs index 756177e27..d6d6ecbb6 100644 --- a/src/action/linux/provision_selinux.rs +++ b/src/action/linux/provision_selinux.rs @@ -1,6 +1,5 @@ use std::path::{Path, PathBuf}; -use tokio::fs::{create_dir_all, remove_file}; use tokio::process::Command; use tracing::{span, Span}; @@ -8,6 +7,7 @@ use crate::action::{ActionError, ActionErrorKind, ActionTag}; use crate::execute_command; use crate::action::{Action, ActionDescription, StatefulAction}; +use crate::util::OnMissing; pub const SELINUX_POLICY_PP_CONTENT: &[u8] = include_bytes!("selinux/nix.pp"); pub const DETERMINATE_SELINUX_POLICY_PP_CONTENT: &[u8] = @@ -77,7 +77,7 @@ impl Action for ProvisionSelinux { } if let Some(parent) = self.policy_path.parent() { - create_dir_all(&parent) + tokio::fs::create_dir_all(&parent) .await .map_err(|e| ActionErrorKind::CreateDirectory(parent.into(), e)) .map_err(Self::error)?; @@ -125,7 +125,7 @@ impl Action for ProvisionSelinux { async fn remove_existing_policy(policy_path: &Path) -> Result<(), ActionErrorKind> { execute_command(Command::new("semodule").arg("--remove").arg("nix")).await?; - remove_file(&policy_path) + crate::util::remove_file(&policy_path, OnMissing::Ignore) .await .map_err(|e| ActionErrorKind::Remove(policy_path.into(), e))?; diff --git a/src/action/linux/revert_clean_steamos_nix_offload.rs b/src/action/linux/revert_clean_steamos_nix_offload.rs index deaad8d20..6d8eb1539 100644 --- a/src/action/linux/revert_clean_steamos_nix_offload.rs +++ b/src/action/linux/revert_clean_steamos_nix_offload.rs @@ -5,6 +5,7 @@ use tracing::{span, Span}; use crate::action::{ActionError, ActionErrorKind, ActionTag}; use crate::action::{Action, ActionDescription, StatefulAction}; +use crate::util::OnMissing; const OFFLOAD_PATH: &str = "/home/.steamos/offload/nix"; @@ -68,8 +69,7 @@ impl Action for RevertCleanSteamosNixOffload { for path in paths { let path = path.map_err(Self::error)?; - tracing::trace!(path = %path.display(), "Removing"); - tokio::fs::remove_dir_all(&path) + crate::util::remove_dir_all(&path, OnMissing::Error) .await .map_err(|e| Self::error(ActionErrorKind::Remove(path, e)))?; } diff --git a/src/cli/subcommand/install.rs b/src/cli/subcommand/install.rs index 2458b2de0..9aafb5c79 100644 --- a/src/cli/subcommand/install.rs +++ b/src/cli/subcommand/install.rs @@ -17,6 +17,7 @@ use crate::{ plan::RECEIPT_LOCATION, planner::Planner, settings::CommonSettings, + util::OnMissing, BuiltinPlanner, InstallPlan, NixInstallerError, }; use clap::{ArgAction, Parser}; @@ -322,15 +323,18 @@ impl CommandExecute for Install { .await .wrap_err("Copying `nix-installer` to `/nix/nix-installer`")?; - if Path::new(PHASE1_RECEIPT_LOCATION).exists() { + let phase1_receipt_path = Path::new(PHASE1_RECEIPT_LOCATION); + if phase1_receipt_path.exists() { tracing::debug!("Removing pre-existing uninstall phase 1 receipt at {PHASE1_RECEIPT_LOCATION} after successful install"); - tokio::fs::remove_file(PHASE1_RECEIPT_LOCATION) + crate::util::remove_file(phase1_receipt_path, OnMissing::Ignore) .await .wrap_err_with(|| format!("Failed to remove uninstall phase 1 receipt at {PHASE1_RECEIPT_LOCATION}"))?; } - if Path::new(PHASE2_RECEIPT_LOCATION).exists() { + + let phase2_receipt_path = Path::new(PHASE2_RECEIPT_LOCATION); + if phase2_receipt_path.exists() { tracing::debug!("Removing pre-existing uninstall phase 2 receipt at {PHASE2_RECEIPT_LOCATION} after successful install"); - tokio::fs::remove_file(PHASE2_RECEIPT_LOCATION) + crate::util::remove_file(phase2_receipt_path, OnMissing::Ignore) .await .wrap_err_with(|| format!("Failed to remove uninstall phase 2 receipt at {PHASE2_RECEIPT_LOCATION}"))?; } diff --git a/src/lib.rs b/src/lib.rs index a2c2793bd..0db472c27 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -80,6 +80,7 @@ mod plan; pub mod planner; pub mod self_test; pub mod settings; +mod util; use std::{ffi::OsStr, path::Path, process::Output}; diff --git a/src/settings.rs b/src/settings.rs index 49482af07..793ec8f76 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -181,6 +181,20 @@ pub struct CommonSettings { )] pub force: bool, + /// If `nix-installer` should skip creating `/etc/nix/nix.conf` + #[cfg_attr( + feature = "cli", + clap( + long, + action(ArgAction::SetTrue), + default_value = "false", + global = true, + env = "NIX_INSTALLER_SKIP_NIX_CONF", + conflicts_with = "extra_conf", + ) + )] + pub skip_nix_conf: bool, + #[cfg(feature = "diagnostics")] /// Relate the install diagnostic to a specific value #[cfg_attr( @@ -285,6 +299,7 @@ impl CommonSettings { proxy: Default::default(), extra_conf: Default::default(), force: false, + skip_nix_conf: false, ssl_cert_file: Default::default(), #[cfg(feature = "diagnostics")] diagnostic_attribution: None, @@ -307,6 +322,7 @@ impl CommonSettings { proxy, extra_conf, force, + skip_nix_conf, ssl_cert_file, #[cfg(feature = "diagnostics")] diagnostic_attribution: _, @@ -351,6 +367,7 @@ impl CommonSettings { map.insert("ssl_cert_file".into(), serde_json::to_value(ssl_cert_file)?); map.insert("extra_conf".into(), serde_json::to_value(extra_conf)?); map.insert("force".into(), serde_json::to_value(force)?); + map.insert("skip_nix_conf".into(), serde_json::to_value(skip_nix_conf)?); #[cfg(feature = "diagnostics")] map.insert( diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 000000000..a16657a96 --- /dev/null +++ b/src/util.rs @@ -0,0 +1,35 @@ +use std::path::Path; + +#[derive(Debug, PartialEq, Eq)] +pub(crate) enum OnMissing { + Ignore, + Error, +} + +#[tracing::instrument(skip(path), fields(path = %path.display()))] +pub(crate) async fn remove_file(path: &Path, on_missing: OnMissing) -> std::io::Result<()> { + tracing::trace!("Removing file"); + let res = tokio::fs::remove_file(path).await; + match res { + Ok(_) => Ok(()), + Err(e) if e.kind() == std::io::ErrorKind::NotFound && on_missing == OnMissing::Ignore => { + tracing::trace!("Ignoring nonexistent file"); + Ok(()) + }, + e @ Err(_) => e, + } +} + +#[tracing::instrument(skip(path), fields(path = %path.display()))] +pub(crate) async fn remove_dir_all(path: &Path, on_missing: OnMissing) -> std::io::Result<()> { + tracing::trace!("Removing directory and all contents"); + let res = tokio::fs::remove_dir_all(path).await; + match res { + Ok(_) => Ok(()), + Err(e) if e.kind() == std::io::ErrorKind::NotFound && on_missing == OnMissing::Ignore => { + tracing::trace!("Ignoring nonexistent directory"); + Ok(()) + }, + e @ Err(_) => e, + } +} diff --git a/tests/fixtures/linux/linux.json b/tests/fixtures/linux/linux.json index b68cb399b..fa5d17e98 100644 --- a/tests/fixtures/linux/linux.json +++ b/tests/fixtures/linux/linux.json @@ -1139,6 +1139,7 @@ "ssl_cert_file": null, "extra_conf": [], "force": false, + "skip_nix_conf": false, "diagnostic_attribution": null, "diagnostic_endpoint": "https://install.determinate.systems/nix/diagnostic" }, diff --git a/tests/fixtures/linux/steam-deck.json b/tests/fixtures/linux/steam-deck.json index a25f31629..1910295bc 100644 --- a/tests/fixtures/linux/steam-deck.json +++ b/tests/fixtures/linux/steam-deck.json @@ -1191,6 +1191,7 @@ "ssl_cert_file": null, "extra_conf": [], "force": false, + "skip_nix_conf": false, "diagnostic_attribution": null, "diagnostic_endpoint": "https://install.determinate.systems/nix/diagnostic" } diff --git a/tests/fixtures/macos/macos.json b/tests/fixtures/macos/macos.json index 0d24aeca4..eae29f355 100644 --- a/tests/fixtures/macos/macos.json +++ b/tests/fixtures/macos/macos.json @@ -1240,6 +1240,7 @@ "ssl_cert_file": null, "extra_conf": [], "force": false, + "skip_nix_conf": false, "diagnostic_attribution": null, "diagnostic_endpoint": "https://install.determinate.systems/nix/diagnostic" },