Cleanup BoxableError location

Signed-off-by: Ana Hobden <operator@hoverbear.org>
This commit is contained in:
Ana Hobden 2022-10-27 08:38:21 -07:00
parent ed039bf1dd
commit 92f6a4e2b7
29 changed files with 148 additions and 74 deletions

View file

@ -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";

View file

@ -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 {

View file

@ -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 {

View file

@ -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 {

View file

@ -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 {

View file

@ -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 {

View file

@ -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 {

View file

@ -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 {

View file

@ -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 {

View file

@ -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 {

View file

@ -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 {

View file

@ -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 {

View file

@ -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";

View file

@ -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;

View file

@ -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 {

View file

@ -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 {

View file

@ -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,

View file

@ -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",

View file

@ -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",

View file

@ -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)]

View file

@ -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";

View file

@ -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};

View file

@ -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};

View file

@ -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 {

View file

@ -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
}

View file

@ -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 {}

View file

@ -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);

View file

@ -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(

View file

@ -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")]