forked from lix-project/lix-installer
Curing existing /nix (#310)
* Curing existing /nix * Fixup macs * Suggest an uninstall command if the binary is not present * Fixup some nits * Skip a not great suggestion * Suggest a nice url
This commit is contained in:
parent
b7d7afd02e
commit
85abfc3cb5
|
@ -78,7 +78,7 @@ impl CreateDirectory {
|
|||
}
|
||||
|
||||
tracing::debug!("Creating directory `{}` already complete", path.display(),);
|
||||
ActionState::Skipped
|
||||
ActionState::Completed
|
||||
} else {
|
||||
ActionState::Uncompleted
|
||||
};
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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<StatefulAction<Self>, ActionError> {
|
||||
pub async fn plan(unpacked_path: PathBuf) -> Result<StatefulAction<Self>, 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::<Result<Vec<_>, _>>()
|
||||
.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(())
|
||||
}
|
||||
|
|
76
src/action/base/remove_directory.rs
Normal file
76
src/action/base/remove_directory.rs
Normal file
|
@ -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<Path>) -> Result<StatefulAction<Self>, 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<ActionDescription> {
|
||||
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<ActionDescription> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -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<StatefulAction<Self>, ActionError> {
|
||||
Ok(Self {}.into())
|
||||
pub async fn plan(unpacked_path: PathBuf) -> Result<StatefulAction<Self>, 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::<Result<Vec<_>, _>>()
|
||||
.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(
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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<StatefulAction<Self>, 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)))?;
|
||||
|
||||
|
|
|
@ -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<StatefulAction<Self>, 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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -71,6 +71,7 @@ impl CommandExecute for Install {
|
|||
|
||||
let existing_receipt: Option<InstallPlan> = 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<dyn Planner> = 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
|
||||
|
|
|
@ -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(),
|
||||
])
|
||||
}
|
||||
|
||||
|
|
|
@ -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(),
|
||||
])
|
||||
}
|
||||
|
||||
|
|
|
@ -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(),
|
||||
])
|
||||
}
|
||||
|
||||
|
|
|
@ -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";
|
||||
|
|
5
tests/fixtures/linux/linux.json
vendored
5
tests/fixtures/linux/linux.json
vendored
|
@ -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"
|
||||
},
|
||||
|
|
5
tests/fixtures/linux/steam-deck.json
vendored
5
tests/fixtures/linux/steam-deck.json
vendored
|
@ -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"
|
||||
},
|
||||
|
|
5
tests/fixtures/macos/macos.json
vendored
5
tests/fixtures/macos/macos.json
vendored
|
@ -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"
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue