forked from lix-project/lix-installer
Cleanup BoxableError location
Signed-off-by: Ana Hobden <operator@hoverbear.org>
This commit is contained in:
parent
ed039bf1dd
commit
92f6a4e2b7
|
@ -6,7 +6,10 @@ use tokio::process::Command;
|
|||
|
||||
use crate::execute_command;
|
||||
|
||||
use crate::action::{Action, ActionDescription, ActionError, ActionState};
|
||||
use crate::{
|
||||
action::{Action, ActionDescription, ActionState},
|
||||
BoxableError,
|
||||
};
|
||||
|
||||
const SERVICE_SRC: &str = "/nix/var/nix/profiles/default/lib/systemd/system/nix-daemon.service";
|
||||
const SOCKET_SRC: &str = "/nix/var/nix/profiles/default/lib/systemd/system/nix-daemon.socket";
|
||||
|
|
|
@ -5,7 +5,10 @@ use nix::unistd::{chown, Group, User};
|
|||
|
||||
use tokio::fs::{create_dir, remove_dir_all};
|
||||
|
||||
use crate::action::{Action, ActionDescription, ActionError, ActionState};
|
||||
use crate::{
|
||||
action::{Action, ActionDescription, ActionState},
|
||||
BoxableError,
|
||||
};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateDirectory {
|
||||
|
|
|
@ -6,9 +6,10 @@ use tokio::{
|
|||
io::AsyncWriteExt,
|
||||
};
|
||||
|
||||
use crate::action::{ActionError, ActionState};
|
||||
|
||||
use crate::action::{Action, ActionDescription};
|
||||
use crate::{
|
||||
action::{Action, ActionDescription, ActionState},
|
||||
BoxableError,
|
||||
};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateFile {
|
||||
|
|
|
@ -2,7 +2,10 @@ use tokio::process::Command;
|
|||
|
||||
use crate::execute_command;
|
||||
|
||||
use crate::action::{Action, ActionDescription, ActionError, ActionState};
|
||||
use crate::{
|
||||
action::{Action, ActionDescription, ActionState},
|
||||
BoxableError,
|
||||
};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateGroup {
|
||||
|
|
|
@ -10,9 +10,10 @@ use tokio::{
|
|||
io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt},
|
||||
};
|
||||
|
||||
use crate::action::{ActionError, ActionState};
|
||||
|
||||
use crate::action::{Action, ActionDescription};
|
||||
use crate::{
|
||||
action::{Action, ActionDescription, ActionState},
|
||||
BoxableError,
|
||||
};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateOrAppendFile {
|
||||
|
|
|
@ -2,7 +2,10 @@ use tokio::process::Command;
|
|||
|
||||
use crate::execute_command;
|
||||
|
||||
use crate::action::{Action, ActionDescription, ActionError, ActionState};
|
||||
use crate::{
|
||||
action::{Action, ActionDescription, ActionState},
|
||||
BoxableError,
|
||||
};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateUser {
|
||||
|
|
|
@ -4,7 +4,10 @@ use tokio::process::Command;
|
|||
|
||||
use crate::execute_command;
|
||||
|
||||
use crate::action::{Action, ActionDescription, ActionError, ActionState};
|
||||
use crate::{
|
||||
action::{Action, ActionDescription, ActionState},
|
||||
BoxableError,
|
||||
};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct BootstrapVolume {
|
||||
|
|
|
@ -4,7 +4,10 @@ use tokio::process::Command;
|
|||
|
||||
use crate::execute_command;
|
||||
|
||||
use crate::action::{Action, ActionDescription, ActionError, ActionState};
|
||||
use crate::{
|
||||
action::{Action, ActionDescription, ActionState},
|
||||
BoxableError,
|
||||
};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateVolume {
|
||||
|
|
|
@ -5,8 +5,11 @@ use tokio::process::Command;
|
|||
|
||||
use crate::execute_command;
|
||||
|
||||
use crate::action::{Action, ActionDescription, ActionError, ActionState};
|
||||
use crate::os::darwin::DiskUtilOutput;
|
||||
use crate::{
|
||||
action::{Action, ActionDescription, ActionState},
|
||||
BoxableError,
|
||||
};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct EnableOwnership {
|
||||
|
|
|
@ -2,7 +2,10 @@ use tokio::process::Command;
|
|||
|
||||
use crate::execute_command;
|
||||
|
||||
use crate::action::{Action, ActionDescription, ActionError, ActionState};
|
||||
use crate::{
|
||||
action::{Action, ActionDescription, ActionState},
|
||||
BoxableError,
|
||||
};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct KickstartLaunchctlService {
|
||||
|
|
|
@ -4,7 +4,10 @@ use tokio::process::Command;
|
|||
|
||||
use crate::execute_command;
|
||||
|
||||
use crate::action::{Action, ActionDescription, ActionError, ActionState};
|
||||
use crate::{
|
||||
action::{Action, ActionDescription, ActionState},
|
||||
BoxableError,
|
||||
};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct UnmountVolume {
|
||||
|
|
|
@ -5,7 +5,10 @@ use reqwest::Url;
|
|||
|
||||
use tokio::task::JoinError;
|
||||
|
||||
use crate::action::{Action, ActionDescription, ActionError, ActionState};
|
||||
use crate::{
|
||||
action::{Action, ActionDescription, ActionState},
|
||||
BoxableError,
|
||||
};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct FetchNix {
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::action::{Action, ActionDescription, ActionError, ActionState};
|
||||
use crate::{
|
||||
action::{Action, ActionDescription, ActionState},
|
||||
BoxableError,
|
||||
};
|
||||
|
||||
const DEST: &str = "/nix/store";
|
||||
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
use crate::{
|
||||
action::{ActionError, ActionState},
|
||||
execute_command, set_env,
|
||||
};
|
||||
use crate::{action::ActionState, execute_command, set_env, BoxableError};
|
||||
|
||||
use glob::glob;
|
||||
|
||||
|
|
|
@ -2,7 +2,10 @@ use tokio::process::Command;
|
|||
|
||||
use crate::execute_command;
|
||||
|
||||
use crate::action::{Action, ActionDescription, ActionError, ActionState};
|
||||
use crate::{
|
||||
action::{Action, ActionDescription, ActionState},
|
||||
BoxableError,
|
||||
};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct StartSystemdUnit {
|
||||
|
|
|
@ -4,7 +4,10 @@ use tokio::process::Command;
|
|||
|
||||
use crate::execute_command;
|
||||
|
||||
use crate::action::{Action, ActionDescription, ActionError, ActionState};
|
||||
use crate::{
|
||||
action::{Action, ActionDescription, ActionState},
|
||||
BoxableError,
|
||||
};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct SystemdSysextMerge {
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
use reqwest::Url;
|
||||
|
||||
use crate::CommonSettings;
|
||||
use crate::{
|
||||
action::{
|
||||
base::{ConfigureNixDaemonService, SetupDefaultProfile},
|
||||
meta::{ConfigureShellProfile, PlaceChannelConfiguration, PlaceNixConfiguration},
|
||||
ActionState,
|
||||
Action, ActionDescription, ActionState,
|
||||
},
|
||||
cli::arg::ChannelValue,
|
||||
BoxableError, CommonSettings,
|
||||
};
|
||||
|
||||
use crate::action::{Action, ActionDescription, ActionError};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct ConfigureNix {
|
||||
setup_default_profile: SetupDefaultProfile,
|
||||
|
|
|
@ -3,7 +3,10 @@ use std::path::Path;
|
|||
use tokio::task::{JoinError, JoinSet};
|
||||
|
||||
use crate::action::base::{CreateOrAppendFile, CreateOrAppendFileError};
|
||||
use crate::action::{Action, ActionDescription, ActionError, ActionState};
|
||||
use crate::{
|
||||
action::{Action, ActionDescription, ActionState},
|
||||
BoxableError,
|
||||
};
|
||||
|
||||
const PROFILE_TARGETS: &[&str] = &[
|
||||
"/etc/bashrc",
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::action::base::{CreateDirectory, CreateDirectoryError, CreateFile, CreateFileError};
|
||||
use crate::action::{Action, ActionDescription, ActionError, ActionState};
|
||||
use crate::{
|
||||
action::{Action, ActionDescription, ActionState},
|
||||
BoxableError,
|
||||
};
|
||||
|
||||
const PATHS: &[&str] = &[
|
||||
"usr",
|
||||
|
|
|
@ -2,9 +2,12 @@ use tokio::task::{JoinError, JoinSet};
|
|||
|
||||
use crate::CommonSettings;
|
||||
|
||||
use crate::action::{
|
||||
base::{CreateGroup, CreateGroupError, CreateUser, CreateUserError},
|
||||
Action, ActionDescription, ActionError, ActionState,
|
||||
use crate::{
|
||||
action::{
|
||||
base::{CreateGroup, CreateGroupError, CreateUser, CreateUserError},
|
||||
Action, ActionDescription, ActionState,
|
||||
},
|
||||
BoxableError,
|
||||
};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
|
|
|
@ -4,19 +4,21 @@ use std::{
|
|||
};
|
||||
use tokio::process::Command;
|
||||
|
||||
use crate::action::{
|
||||
base::{
|
||||
darwin::{
|
||||
BootstrapVolume, BootstrapVolumeError, CreateSyntheticObjects,
|
||||
CreateSyntheticObjectsError, CreateVolume, CreateVolumeError, EnableOwnership,
|
||||
EnableOwnershipError, EncryptVolume, EncryptVolumeError, UnmountVolume,
|
||||
UnmountVolumeError,
|
||||
use crate::{
|
||||
action::{
|
||||
base::{
|
||||
darwin::{
|
||||
BootstrapVolume, BootstrapVolumeError, CreateSyntheticObjects,
|
||||
CreateSyntheticObjectsError, CreateVolume, CreateVolumeError, EnableOwnership,
|
||||
EnableOwnershipError, EncryptVolume, EncryptVolumeError, UnmountVolume,
|
||||
UnmountVolumeError,
|
||||
},
|
||||
CreateFile, CreateFileError, CreateOrAppendFile, CreateOrAppendFileError,
|
||||
},
|
||||
CreateFile, CreateFileError, CreateOrAppendFile, CreateOrAppendFileError,
|
||||
Action, ActionDescription, ActionState,
|
||||
},
|
||||
ActionError,
|
||||
BoxableError,
|
||||
};
|
||||
use crate::action::{Action, ActionDescription, ActionState};
|
||||
|
||||
const NIX_VOLUME_MOUNTD_DEST: &str = "/Library/LaunchDaemons/org.nixos.darwin-store.plist";
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
use reqwest::Url;
|
||||
|
||||
use crate::action::{Action, ActionDescription, ActionError, ActionState};
|
||||
use crate::{
|
||||
action::{Action, ActionDescription, ActionState},
|
||||
BoxableError,
|
||||
};
|
||||
|
||||
use crate::action::base::{CreateFile, CreateFileError};
|
||||
|
||||
|
|
|
@ -7,7 +7,10 @@ use crate::action::base::{
|
|||
};
|
||||
use crate::CommonSettings;
|
||||
|
||||
use crate::action::{Action, ActionDescription, ActionError, ActionState};
|
||||
use crate::{
|
||||
action::{Action, ActionDescription, ActionState},
|
||||
BoxableError,
|
||||
};
|
||||
|
||||
use super::{CreateNixTree, CreateNixTreeError, CreateUsersAndGroup, CreateUsersAndGroupError};
|
||||
|
||||
|
|
|
@ -3,17 +3,6 @@ pub mod meta;
|
|||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub trait ActionError: std::error::Error + Send + Sync {
|
||||
fn boxed(self) -> Box<dyn std::error::Error + Send + Sync>
|
||||
where
|
||||
Self: Sized + 'static,
|
||||
{
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> ActionError for E where E: std::error::Error + Send + Sized + Sync {}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
#[typetag::serde(tag = "action")]
|
||||
pub trait Action: Send + Sync + std::fmt::Debug + dyn_clone::DynClone {
|
||||
|
|
|
@ -21,24 +21,30 @@ pub(crate) async fn confirm(question: impl AsRef<str>) -> eyre::Result<bool> {
|
|||
stdout.write_all(with_confirm.as_bytes()).await?;
|
||||
stdout.flush().await?;
|
||||
|
||||
crossterm::terminal::enable_raw_mode()?;
|
||||
// crossterm::terminal::enable_raw_mode()?;
|
||||
let mut reader = EventStream::new();
|
||||
|
||||
let retval = loop {
|
||||
let event = reader.next().fuse().await;
|
||||
match event {
|
||||
Some(Ok(event)) => {
|
||||
if let crossterm::event::Event::Key(key) = event {
|
||||
match key.code {
|
||||
KeyCode::Enter => continue, // Many users will hit enter accidentally when they are agreeing/declining prompts.
|
||||
// TODO(@hoverbear): Should maybe actually even wait for it?
|
||||
KeyCode::Char('y') => break Ok(true),
|
||||
_ => {
|
||||
KeyCode::Char('y') | KeyCode::Char('Y') => {
|
||||
stdout
|
||||
.write_all("Cancelled!".red().to_string().as_bytes())
|
||||
.write_all("Confirmed!\n".green().to_string().as_bytes())
|
||||
.await?;
|
||||
stdout.flush().await?;
|
||||
break Ok(true);
|
||||
},
|
||||
KeyCode::Char('N') | KeyCode::Char('n') => {
|
||||
stdout
|
||||
.write_all("Cancelled!\n".red().to_string().as_bytes())
|
||||
.await?;
|
||||
stdout.flush().await?;
|
||||
break Ok(false);
|
||||
},
|
||||
KeyCode::Enter | _ => continue,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -46,7 +52,7 @@ pub(crate) async fn confirm(question: impl AsRef<str>) -> eyre::Result<bool> {
|
|||
None => break Err(eyre!("Bailed, no confirmation event")),
|
||||
}
|
||||
};
|
||||
crossterm::terminal::disable_raw_mode()?;
|
||||
// crossterm::terminal::disable_raw_mode()?;
|
||||
retval
|
||||
}
|
||||
|
||||
|
|
11
src/lib.rs
11
src/lib.rs
|
@ -42,3 +42,14 @@ fn set_env(k: impl AsRef<OsStr>, v: impl AsRef<OsStr>) {
|
|||
tracing::trace!("Setting env");
|
||||
std::env::set_var(k.as_ref(), v.as_ref());
|
||||
}
|
||||
|
||||
pub trait BoxableError: std::error::Error + Send + Sync {
|
||||
fn boxed(self) -> Box<dyn std::error::Error + Send + Sync>
|
||||
where
|
||||
Self: Sized + 'static,
|
||||
{
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> BoxableError for E where E: std::error::Error + Send + Sized + Sync {}
|
||||
|
|
|
@ -99,6 +99,7 @@ impl InstallPlan {
|
|||
nix_channels = "todo",
|
||||
actions = actions
|
||||
.iter()
|
||||
.rev()
|
||||
.map(|v| v.describe_revert())
|
||||
.flatten()
|
||||
.map(|desc| {
|
||||
|
@ -131,7 +132,7 @@ impl InstallPlan {
|
|||
// This is **deliberately sequential**.
|
||||
// Actions which are parallelizable are represented by "group actions" like CreateUsers
|
||||
// The plan itself represents the concept of the sequence of stages.
|
||||
for action in actions {
|
||||
for action in actions.iter_mut().rev() {
|
||||
if let Err(err) = action.revert().await {
|
||||
if let Err(err) = write_receipt(self.clone()).await {
|
||||
tracing::error!("Error saving receipt: {:?}", err);
|
||||
|
|
|
@ -53,16 +53,22 @@ impl Planner for DarwinMulti {
|
|||
})
|
||||
}
|
||||
|
||||
async fn plan(self) -> Result<crate::InstallPlan, Box<dyn std::error::Error + Sync + Send>> {
|
||||
let root_disk = {
|
||||
let buf =
|
||||
execute_command(Command::new("/usr/sbin/diskutil").args(["info", "-plist", "/"]))
|
||||
.await
|
||||
.unwrap()
|
||||
.stdout;
|
||||
let the_plist: DiskUtilOutput = plist::from_reader(Cursor::new(buf)).unwrap();
|
||||
async fn plan(
|
||||
mut self,
|
||||
) -> Result<crate::InstallPlan, Box<dyn std::error::Error + Sync + Send>> {
|
||||
self.root_disk = match self.root_disk {
|
||||
root_disk @ Some(_) => root_disk,
|
||||
None => {
|
||||
let buf = execute_command(
|
||||
Command::new("/usr/sbin/diskutil").args(["info", "-plist", "/"]),
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.stdout;
|
||||
let the_plist: DiskUtilOutput = plist::from_reader(Cursor::new(buf)).unwrap();
|
||||
|
||||
the_plist.parent_whole_disk
|
||||
Some(the_plist.parent_whole_disk)
|
||||
},
|
||||
};
|
||||
|
||||
let volume_label = "Nix Store".into();
|
||||
|
@ -74,7 +80,15 @@ impl Planner for DarwinMulti {
|
|||
//
|
||||
// setup_Synthetic -> create_synthetic_objects
|
||||
// Unmount -> create_volume -> Setup_fstab -> maybe encrypt_volume -> launchctl bootstrap -> launchctl kickstart -> await_volume -> maybe enableOwnership
|
||||
Box::new(CreateApfsVolume::plan(root_disk, volume_label, false, None).await?),
|
||||
Box::new(
|
||||
CreateApfsVolume::plan(
|
||||
self.root_disk.unwrap(), /* We just ensured it was populated */
|
||||
volume_label,
|
||||
false,
|
||||
None,
|
||||
)
|
||||
.await?,
|
||||
),
|
||||
Box::new(ProvisionNix::plan(self.settings.clone()).await?),
|
||||
Box::new(ConfigureNix::plan(self.settings).await?),
|
||||
Box::new(
|
||||
|
|
|
@ -2,7 +2,7 @@ pub mod darwin;
|
|||
pub mod linux;
|
||||
pub mod specific;
|
||||
|
||||
use crate::{action::ActionError, settings::InstallSettingsError, InstallPlan};
|
||||
use crate::{settings::InstallSettingsError, BoxableError, InstallPlan};
|
||||
|
||||
#[async_trait::async_trait]
|
||||
#[typetag::serde(tag = "planner")]
|
||||
|
|
Loading…
Reference in a new issue