forked from lix-project/lix-installer
Even more mac progress, can plan and start runs
This commit is contained in:
parent
c75a4ed511
commit
86a518f2fe
43
Cargo.lock
generated
43
Cargo.lock
generated
|
@ -498,6 +498,26 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "4.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
|
||||
dependencies = [
|
||||
"dirs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.8.31"
|
||||
|
@ -684,6 +704,17 @@ dependencies = [
|
|||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ghost"
|
||||
version = "0.1.6"
|
||||
|
@ -749,6 +780,7 @@ dependencies = [
|
|||
"clap",
|
||||
"color-eyre",
|
||||
"crossterm",
|
||||
"dirs",
|
||||
"eyre",
|
||||
"futures 0.3.24",
|
||||
"glob",
|
||||
|
@ -1380,6 +1412,17 @@ dependencies = [
|
|||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"redox_syscall",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.6.0"
|
||||
|
|
|
@ -39,3 +39,4 @@ sxd-xpath = "0.4.2"
|
|||
xz2 = { version = "0.1.7", features = ["static", "tokio"] }
|
||||
sxd-document = "0.3.2"
|
||||
plist = "1.3.1"
|
||||
dirs = "4.0.0"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use serde::Serialize;
|
||||
use target_lexicon::OperatingSystem;
|
||||
use tokio::fs::remove_file;
|
||||
use tokio::process::Command;
|
||||
|
||||
|
@ -21,9 +22,20 @@ pub struct ConfigureNixDaemonService {
|
|||
impl ConfigureNixDaemonService {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn plan() -> Result<Self, ConfigureNixDaemonServiceError> {
|
||||
match OperatingSystem::host() {
|
||||
OperatingSystem::MacOSX {
|
||||
major: _,
|
||||
minor: _,
|
||||
patch: _,
|
||||
}
|
||||
| OperatingSystem::Darwin => (),
|
||||
_ => {
|
||||
if !Path::new("/run/systemd/system").exists() {
|
||||
return Err(ConfigureNixDaemonServiceError::InitNotSupported);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
action_state: ActionState::Uncompleted,
|
||||
})
|
||||
|
@ -59,11 +71,45 @@ impl Actionable for ConfigureNixDaemonService {
|
|||
}
|
||||
tracing::debug!("Configuring nix daemon service");
|
||||
|
||||
match OperatingSystem::host() {
|
||||
OperatingSystem::MacOSX {
|
||||
major: _,
|
||||
minor: _,
|
||||
patch: _,
|
||||
}
|
||||
| OperatingSystem::Darwin => {
|
||||
const DARWIN_NIX_DAEMON_DEST: &str =
|
||||
"/Library/LaunchDaemons/org.nixos.nix-daemon.plist";
|
||||
|
||||
let src = Path::new("/nix/var/nix/profiles/default").join(DARWIN_NIX_DAEMON_DEST);
|
||||
tokio::fs::copy(src.clone(), DARWIN_NIX_DAEMON_DEST)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
Self::Error::Copy(
|
||||
src.to_path_buf(),
|
||||
PathBuf::from(DARWIN_NIX_DAEMON_DEST),
|
||||
e,
|
||||
)
|
||||
})?;
|
||||
|
||||
execute_command(
|
||||
Command::new("launchctl")
|
||||
.arg("load")
|
||||
.arg(DARWIN_NIX_DAEMON_DEST),
|
||||
)
|
||||
.await
|
||||
.map_err(Self::Error::CommandFailed)?;
|
||||
},
|
||||
_ => {
|
||||
tracing::trace!(src = TMPFILES_SRC, dest = TMPFILES_DEST, "Symlinking");
|
||||
tokio::fs::symlink(TMPFILES_SRC, TMPFILES_DEST)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
Self::Error::Symlink(PathBuf::from(TMPFILES_SRC), PathBuf::from(TMPFILES_DEST), e)
|
||||
Self::Error::Symlink(
|
||||
PathBuf::from(TMPFILES_SRC),
|
||||
PathBuf::from(TMPFILES_DEST),
|
||||
e,
|
||||
)
|
||||
})?;
|
||||
|
||||
execute_command(
|
||||
|
@ -85,6 +131,8 @@ impl Actionable for ConfigureNixDaemonService {
|
|||
execute_command(Command::new("systemctl").arg("daemon-reload"))
|
||||
.await
|
||||
.map_err(Self::Error::CommandFailed)?;
|
||||
},
|
||||
};
|
||||
|
||||
tracing::trace!("Configured nix daemon service");
|
||||
*action_state = ActionState::Completed;
|
||||
|
@ -176,6 +224,14 @@ pub enum ConfigureNixDaemonServiceError {
|
|||
#[serde(serialize_with = "crate::serialize_error_to_display")]
|
||||
std::io::Error,
|
||||
),
|
||||
#[error("Copying file `{0}` to `{1}`")]
|
||||
Copy(
|
||||
std::path::PathBuf,
|
||||
std::path::PathBuf,
|
||||
#[source]
|
||||
#[serde(serialize_with = "crate::serialize_error_to_display")]
|
||||
std::io::Error,
|
||||
),
|
||||
#[error("No supported init system found")]
|
||||
InitNotSupported,
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@ use crate::actions::{Action, ActionDescription, ActionState, Actionable};
|
|||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateDirectory {
|
||||
path: PathBuf,
|
||||
user: String,
|
||||
group: String,
|
||||
mode: u32,
|
||||
user: Option<String>,
|
||||
group: Option<String>,
|
||||
mode: Option<u32>,
|
||||
action_state: ActionState,
|
||||
force_prune_on_revert: bool,
|
||||
}
|
||||
|
@ -21,12 +21,15 @@ impl CreateDirectory {
|
|||
#[tracing::instrument(skip_all)]
|
||||
pub async fn plan(
|
||||
path: impl AsRef<Path>,
|
||||
user: String,
|
||||
group: String,
|
||||
mode: u32,
|
||||
user: impl Into<Option<String>>,
|
||||
group: impl Into<Option<String>>,
|
||||
mode: impl Into<Option<u32>>,
|
||||
force_prune_on_revert: bool,
|
||||
) -> Result<Self, CreateDirectoryError> {
|
||||
let path = path.as_ref();
|
||||
let user = user.into();
|
||||
let group = group.into();
|
||||
let mode = mode.into();
|
||||
|
||||
let action_state = if path.exists() {
|
||||
let metadata = tokio::fs::metadata(path)
|
||||
|
@ -77,10 +80,7 @@ impl Actionable for CreateDirectory {
|
|||
} else {
|
||||
vec![ActionDescription::new(
|
||||
format!("Create the directory `{}`", path.display()),
|
||||
vec![format!(
|
||||
"Creating directory `{}` owned by `{user}:{group}` with mode `{mode:#o}`",
|
||||
path.display()
|
||||
)],
|
||||
vec![],
|
||||
)]
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ impl Actionable for CreateDirectory {
|
|||
path = %self.path.display(),
|
||||
user = self.user,
|
||||
group = self.group,
|
||||
mode = format!("{:#o}", self.mode),
|
||||
mode = self.mode.map(|v| tracing::field::display(format!("{:#o}", v))),
|
||||
))]
|
||||
async fn execute(&mut self) -> Result<(), Self::Error> {
|
||||
let Self {
|
||||
|
@ -106,23 +106,37 @@ impl Actionable for CreateDirectory {
|
|||
}
|
||||
tracing::debug!("Creating directory");
|
||||
|
||||
let gid = Group::from_name(group.as_str())
|
||||
let gid = if let Some(group) = group {
|
||||
Some(
|
||||
Group::from_name(group.as_str())
|
||||
.map_err(|e| Self::Error::GroupId(group.clone(), e))?
|
||||
.ok_or(Self::Error::NoGroup(group.clone()))?
|
||||
.gid;
|
||||
let uid = User::from_name(user.as_str())
|
||||
.gid,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let uid = if let Some(user) = user {
|
||||
Some(
|
||||
User::from_name(user.as_str())
|
||||
.map_err(|e| Self::Error::UserId(user.clone(), e))?
|
||||
.ok_or(Self::Error::NoUser(user.clone()))?
|
||||
.uid;
|
||||
.uid,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
create_dir(path.clone())
|
||||
.await
|
||||
.map_err(|e| Self::Error::Creating(path.clone(), e))?;
|
||||
chown(path, Some(uid), Some(gid)).map_err(|e| Self::Error::Chown(path.clone(), e))?;
|
||||
chown(path, uid, gid).map_err(|e| Self::Error::Chown(path.clone(), e))?;
|
||||
|
||||
if let Some(mode) = mode {
|
||||
tokio::fs::set_permissions(&path, PermissionsExt::from_mode(*mode))
|
||||
.await
|
||||
.map_err(|e| Self::Error::SetPermissions(*mode, path.to_owned(), e))?;
|
||||
}
|
||||
|
||||
tracing::trace!("Created directory");
|
||||
*action_state = ActionState::Completed;
|
||||
|
@ -160,7 +174,7 @@ impl Actionable for CreateDirectory {
|
|||
path = %self.path.display(),
|
||||
user = self.user,
|
||||
group = self.group,
|
||||
mode = format!("{:#o}", self.mode),
|
||||
mode = self.mode.map(|v| tracing::field::display(format!("{:#o}", v))),
|
||||
))]
|
||||
async fn revert(&mut self) -> Result<(), Self::Error> {
|
||||
let Self {
|
||||
|
|
|
@ -12,10 +12,10 @@ use crate::actions::{ActionDescription, Actionable};
|
|||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateFile {
|
||||
path: PathBuf,
|
||||
user: String,
|
||||
group: String,
|
||||
mode: u32,
|
||||
pub(crate) path: PathBuf,
|
||||
user: Option<String>,
|
||||
group: Option<String>,
|
||||
mode: Option<u32>,
|
||||
buf: String,
|
||||
force: bool,
|
||||
action_state: ActionState,
|
||||
|
@ -25,9 +25,9 @@ impl CreateFile {
|
|||
#[tracing::instrument(skip_all)]
|
||||
pub async fn plan(
|
||||
path: impl AsRef<Path>,
|
||||
user: String,
|
||||
group: String,
|
||||
mode: u32,
|
||||
user: impl Into<Option<String>>,
|
||||
group: impl Into<Option<String>>,
|
||||
mode: impl Into<Option<u32>>,
|
||||
buf: String,
|
||||
force: bool,
|
||||
) -> Result<Self, CreateFileError> {
|
||||
|
@ -39,9 +39,9 @@ impl CreateFile {
|
|||
|
||||
Ok(Self {
|
||||
path,
|
||||
user,
|
||||
group,
|
||||
mode,
|
||||
user: user.into(),
|
||||
group: group.into(),
|
||||
mode: mode.into(),
|
||||
buf,
|
||||
force,
|
||||
action_state: ActionState::Uncompleted,
|
||||
|
@ -68,9 +68,7 @@ impl Actionable for CreateFile {
|
|||
} else {
|
||||
vec![ActionDescription::new(
|
||||
format!("Create or overwrite file `{}`", path.display()),
|
||||
vec![format!(
|
||||
"Create or overwrite `{}` owned by `{user}:{group}` with mode `{mode:#o}` with `{buf}`", path.display()
|
||||
)],
|
||||
vec![],
|
||||
)]
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +77,7 @@ impl Actionable for CreateFile {
|
|||
path = %self.path.display(),
|
||||
user = self.user,
|
||||
group = self.group,
|
||||
mode = format!("{:#o}", self.mode),
|
||||
mode = self.mode.map(|v| tracing::field::display(format!("{:#o}", v))),
|
||||
))]
|
||||
async fn execute(&mut self) -> Result<(), Self::Error> {
|
||||
let Self {
|
||||
|
@ -97,11 +95,14 @@ impl Actionable for CreateFile {
|
|||
}
|
||||
tracing::debug!("Creating file");
|
||||
|
||||
let mut file = OpenOptions::new()
|
||||
.create_new(true)
|
||||
.mode(*mode)
|
||||
.write(true)
|
||||
.read(true)
|
||||
let mut options = OpenOptions::new();
|
||||
options.create_new(true).write(true).read(true);
|
||||
|
||||
if let Some(mode) = mode {
|
||||
options.mode(*mode);
|
||||
}
|
||||
|
||||
let mut file = options
|
||||
.open(&path)
|
||||
.await
|
||||
.map_err(|e| Self::Error::OpenFile(path.to_owned(), e))?;
|
||||
|
@ -110,16 +111,27 @@ impl Actionable for CreateFile {
|
|||
.await
|
||||
.map_err(|e| Self::Error::WriteFile(path.to_owned(), e))?;
|
||||
|
||||
let gid = Group::from_name(group.as_str())
|
||||
let gid = if let Some(group) = group {
|
||||
Some(
|
||||
Group::from_name(group.as_str())
|
||||
.map_err(|e| Self::Error::GroupId(group.clone(), e))?
|
||||
.ok_or(Self::Error::NoGroup(group.clone()))?
|
||||
.gid;
|
||||
let uid = User::from_name(user.as_str())
|
||||
.gid,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let uid = if let Some(user) = user {
|
||||
Some(
|
||||
User::from_name(user.as_str())
|
||||
.map_err(|e| Self::Error::UserId(user.clone(), e))?
|
||||
.ok_or(Self::Error::NoUser(user.clone()))?
|
||||
.uid;
|
||||
|
||||
chown(path, Some(uid), Some(gid)).map_err(|e| Self::Error::Chown(path.clone(), e))?;
|
||||
.uid,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
chown(path, uid, gid).map_err(|e| Self::Error::Chown(path.clone(), e))?;
|
||||
|
||||
tracing::trace!("Created file");
|
||||
*action_state = ActionState::Completed;
|
||||
|
@ -150,7 +162,7 @@ impl Actionable for CreateFile {
|
|||
path = %self.path.display(),
|
||||
user = self.user,
|
||||
group = self.group,
|
||||
mode = format!("{:#o}", self.mode),
|
||||
mode = self.mode.map(|v| tracing::field::display(format!("{:#o}", v))),
|
||||
))]
|
||||
async fn revert(&mut self) -> Result<(), Self::Error> {
|
||||
let Self {
|
||||
|
|
|
@ -17,9 +17,9 @@ use crate::actions::{ActionDescription, Actionable};
|
|||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct CreateOrAppendFile {
|
||||
path: PathBuf,
|
||||
user: String,
|
||||
group: String,
|
||||
mode: u32,
|
||||
user: Option<String>,
|
||||
group: Option<String>,
|
||||
mode: Option<u32>,
|
||||
buf: String,
|
||||
action_state: ActionState,
|
||||
}
|
||||
|
@ -28,18 +28,18 @@ impl CreateOrAppendFile {
|
|||
#[tracing::instrument(skip_all)]
|
||||
pub async fn plan(
|
||||
path: impl AsRef<Path>,
|
||||
user: String,
|
||||
group: String,
|
||||
mode: u32,
|
||||
user: impl Into<Option<String>>,
|
||||
group: impl Into<Option<String>>,
|
||||
mode: impl Into<Option<u32>>,
|
||||
buf: String,
|
||||
) -> Result<Self, CreateOrAppendFileError> {
|
||||
let path = path.as_ref().to_path_buf();
|
||||
|
||||
Ok(Self {
|
||||
path,
|
||||
user,
|
||||
group,
|
||||
mode,
|
||||
user: user.into(),
|
||||
group: group.into(),
|
||||
mode: mode.into(),
|
||||
buf,
|
||||
action_state: ActionState::Uncompleted,
|
||||
})
|
||||
|
@ -64,9 +64,7 @@ impl Actionable for CreateOrAppendFile {
|
|||
} else {
|
||||
vec![ActionDescription::new(
|
||||
format!("Create or append file `{}`", path.display()),
|
||||
vec![format!(
|
||||
"Create or append `{}` owned by `{user}:{group}` with mode `{mode:#o}` with `{buf}`", path.display()
|
||||
)],
|
||||
vec![],
|
||||
)]
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +73,7 @@ impl Actionable for CreateOrAppendFile {
|
|||
path = %self.path.display(),
|
||||
user = self.user,
|
||||
group = self.group,
|
||||
mode = format!("{:#o}", self.mode),
|
||||
mode = self.mode.map(|v| tracing::field::display(format!("{:#o}", v))),
|
||||
))]
|
||||
async fn execute(&mut self) -> Result<(), Self::Error> {
|
||||
let Self {
|
||||
|
@ -108,20 +106,34 @@ impl Actionable for CreateOrAppendFile {
|
|||
.await
|
||||
.map_err(|e| Self::Error::WriteFile(path.to_owned(), e))?;
|
||||
|
||||
let gid = Group::from_name(group.as_str())
|
||||
let gid = if let Some(group) = group {
|
||||
Some(
|
||||
Group::from_name(group.as_str())
|
||||
.map_err(|e| Self::Error::GroupId(group.clone(), e))?
|
||||
.ok_or(Self::Error::NoGroup(group.clone()))?
|
||||
.gid;
|
||||
let uid = User::from_name(user.as_str())
|
||||
.gid,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let uid = if let Some(user) = user {
|
||||
Some(
|
||||
User::from_name(user.as_str())
|
||||
.map_err(|e| Self::Error::UserId(user.clone(), e))?
|
||||
.ok_or(Self::Error::NoUser(user.clone()))?
|
||||
.uid;
|
||||
.uid,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if let Some(mode) = mode {
|
||||
tokio::fs::set_permissions(&path, PermissionsExt::from_mode(*mode))
|
||||
.await
|
||||
.map_err(|e| Self::Error::SetPermissions(*mode, path.to_owned(), e))?;
|
||||
}
|
||||
|
||||
chown(path, Some(uid), Some(gid)).map_err(|e| Self::Error::Chown(path.clone(), e))?;
|
||||
chown(path, uid, gid).map_err(|e| Self::Error::Chown(path.clone(), e))?;
|
||||
|
||||
tracing::trace!("Created or appended fragment to file");
|
||||
*action_state = ActionState::Completed;
|
||||
|
@ -154,7 +166,7 @@ impl Actionable for CreateOrAppendFile {
|
|||
path = %self.path.display(),
|
||||
user = self.user,
|
||||
group = self.group,
|
||||
mode = format!("{:#o}", self.mode),
|
||||
mode = self.mode.map(|v| tracing::field::display(format!("{:#o}", v))),
|
||||
))]
|
||||
async fn revert(&mut self) -> Result<(), Self::Error> {
|
||||
let Self {
|
||||
|
|
|
@ -68,7 +68,7 @@ impl Actionable for CreateUser {
|
|||
tracing::debug!("Creating user");
|
||||
|
||||
use target_lexicon::OperatingSystem;
|
||||
match target_lexicon::OperatingSystem::host() {
|
||||
match OperatingSystem::host() {
|
||||
OperatingSystem::MacOSX {
|
||||
major: _,
|
||||
minor: _,
|
||||
|
|
115
src/actions/base/darwin/kickstart_launchctl_service.rs
Normal file
115
src/actions/base/darwin/kickstart_launchctl_service.rs
Normal file
|
@ -0,0 +1,115 @@
|
|||
use serde::Serialize;
|
||||
use tokio::process::Command;
|
||||
|
||||
use crate::execute_command;
|
||||
|
||||
use crate::actions::{Action, ActionDescription, ActionState, Actionable};
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct KickstartLaunchctlService {
|
||||
unit: String,
|
||||
action_state: ActionState,
|
||||
}
|
||||
|
||||
impl KickstartLaunchctlService {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn plan(unit: String) -> Result<Self, KickstartLaunchctlServiceError> {
|
||||
Ok(Self {
|
||||
unit,
|
||||
action_state: ActionState::Uncompleted,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Actionable for KickstartLaunchctlService {
|
||||
type Error = KickstartLaunchctlServiceError;
|
||||
|
||||
fn describe_execute(&self) -> Vec<ActionDescription> {
|
||||
let Self { unit, action_state } = self;
|
||||
if *action_state == ActionState::Completed {
|
||||
vec![]
|
||||
} else {
|
||||
vec![ActionDescription::new(
|
||||
format!("Kickstart the launchctl unit `{unit}`"),
|
||||
vec![
|
||||
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
|
||||
]
|
||||
)]
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all, fields(
|
||||
unit = %self.unit,
|
||||
))]
|
||||
async fn execute(&mut self) -> Result<(), Self::Error> {
|
||||
let Self { unit, action_state } = self;
|
||||
if *action_state == ActionState::Completed {
|
||||
tracing::trace!("Already completed: Kickstarting launchctl unit");
|
||||
return Ok(());
|
||||
}
|
||||
tracing::debug!("Kickstarting launchctl unit");
|
||||
|
||||
execute_command(
|
||||
Command::new("launchctl")
|
||||
.arg("kickstart")
|
||||
.arg("-k")
|
||||
.arg(unit),
|
||||
)
|
||||
.await
|
||||
.map_err(KickstartLaunchctlServiceError::Command)?;
|
||||
|
||||
tracing::trace!("Kickstarted launchctl unit");
|
||||
*action_state = ActionState::Completed;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn describe_revert(&self) -> Vec<ActionDescription> {
|
||||
if self.action_state == ActionState::Uncompleted {
|
||||
vec![]
|
||||
} else {
|
||||
vec![ActionDescription::new(
|
||||
"Kick".to_string(),
|
||||
vec![
|
||||
"The `nix` command line tool communicates with a running Nix daemon managed by your init system".to_string()
|
||||
]
|
||||
)]
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all, fields(
|
||||
unit = %self.unit,
|
||||
))]
|
||||
async fn revert(&mut self) -> Result<(), Self::Error> {
|
||||
let Self { unit, action_state } = self;
|
||||
if *action_state == ActionState::Uncompleted {
|
||||
tracing::trace!("Already reverted: Stopping launchctl unit");
|
||||
return Ok(());
|
||||
}
|
||||
tracing::debug!("Stopping launchctl unit");
|
||||
|
||||
execute_command(Command::new("launchctl").arg("stop").arg(unit))
|
||||
.await
|
||||
.map_err(KickstartLaunchctlServiceError::Command)?;
|
||||
|
||||
tracing::trace!("Stopped launchctl unit");
|
||||
*action_state = ActionState::Completed;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<KickstartLaunchctlService> for Action {
|
||||
fn from(v: KickstartLaunchctlService) -> Self {
|
||||
Action::DarwinKickStartLaunchctlService(v)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error, Serialize)]
|
||||
pub enum KickstartLaunchctlServiceError {
|
||||
#[error("Failed to execute command")]
|
||||
Command(
|
||||
#[source]
|
||||
#[serde(serialize_with = "crate::serialize_error_to_display")]
|
||||
std::io::Error,
|
||||
),
|
||||
}
|
|
@ -3,6 +3,7 @@ mod create_synthetic_objects;
|
|||
mod create_volume;
|
||||
mod enable_ownership;
|
||||
mod encrypt_volume;
|
||||
mod kickstart_launchctl_service;
|
||||
mod unmount_volume;
|
||||
|
||||
pub use bootstrap_volume::{BootstrapVolume, BootstrapVolumeError};
|
||||
|
@ -10,4 +11,5 @@ pub use create_synthetic_objects::{CreateSyntheticObjects, CreateSyntheticObject
|
|||
pub use create_volume::{CreateVolume, CreateVolumeError};
|
||||
pub use enable_ownership::{EnableOwnership, EnableOwnershipError};
|
||||
pub use encrypt_volume::{EncryptVolume, EncryptVolumeError};
|
||||
pub use kickstart_launchctl_service::{KickstartLaunchctlService, KickstartLaunchctlServiceError};
|
||||
pub use unmount_volume::{UnmountVolume, UnmountVolumeError};
|
||||
|
|
|
@ -60,7 +60,7 @@ impl Actionable for UnmountVolume {
|
|||
tracing::debug!("Unmounting volume");
|
||||
|
||||
execute_command(
|
||||
Command::new(" /usr/sbin/diskutil")
|
||||
Command::new("/usr/sbin/diskutil")
|
||||
.args(["unmount", "force"])
|
||||
.arg(name),
|
||||
)
|
||||
|
|
|
@ -41,10 +41,8 @@ impl ConfigureShellProfile {
|
|||
# End Nix\n
|
||||
\n",
|
||||
);
|
||||
create_or_append_files.push(
|
||||
CreateOrAppendFile::plan(path, "root".to_string(), "root".to_string(), 0o0644, buf)
|
||||
.await?,
|
||||
);
|
||||
create_or_append_files
|
||||
.push(CreateOrAppendFile::plan(path, None, None, 0o0644, buf).await?);
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
|
|
|
@ -31,9 +31,7 @@ impl CreateNixTree {
|
|||
let mut create_directories = Vec::default();
|
||||
for path in PATHS {
|
||||
// We use `create_dir` over `create_dir_all` to ensure we always set permissions right
|
||||
create_directories.push(
|
||||
CreateDirectory::plan(path, "root".into(), "root".into(), 0o0755, false).await?,
|
||||
)
|
||||
create_directories.push(CreateDirectory::plan(path, None, None, 0o0755, false).await?)
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
|
|
|
@ -26,19 +26,11 @@ impl CreateSystemdSysext {
|
|||
pub async fn plan(destination: impl AsRef<Path>) -> Result<Self, CreateSystemdSysextError> {
|
||||
let destination = destination.as_ref();
|
||||
|
||||
let mut create_directories = vec![
|
||||
CreateDirectory::plan(destination, "root".into(), "root".into(), 0o0755, true).await?,
|
||||
];
|
||||
let mut create_directories =
|
||||
vec![CreateDirectory::plan(destination, None, None, 0o0755, true).await?];
|
||||
for path in PATHS {
|
||||
create_directories.push(
|
||||
CreateDirectory::plan(
|
||||
destination.join(path),
|
||||
"root".into(),
|
||||
"root".into(),
|
||||
0o0755,
|
||||
false,
|
||||
)
|
||||
.await?,
|
||||
CreateDirectory::plan(destination.join(path), None, None, 0o0755, false).await?,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -57,8 +49,8 @@ impl CreateSystemdSysext {
|
|||
format!("SYSEXT_LEVEL=1.0\nID=steamos\nVERSION_ID={version_id}");
|
||||
let create_extension_release = CreateFile::plan(
|
||||
destination.join("usr/lib/extension-release.d/extension-release.nix"),
|
||||
"root".into(),
|
||||
"root".into(),
|
||||
None,
|
||||
None,
|
||||
0o0755,
|
||||
extension_release_buf,
|
||||
false,
|
||||
|
@ -77,8 +69,8 @@ impl CreateSystemdSysext {
|
|||
);
|
||||
let create_bind_mount_unit = CreateFile::plan(
|
||||
destination.join("usr/lib/systemd/system/nix.mount"),
|
||||
"root".into(),
|
||||
"root".into(),
|
||||
None,
|
||||
None,
|
||||
0o0755,
|
||||
create_bind_mount_buf,
|
||||
false,
|
||||
|
|
|
@ -39,13 +39,8 @@ impl CreateApfsVolume {
|
|||
encrypt: Option<String>,
|
||||
) -> Result<Self, CreateApfsVolumeError> {
|
||||
let disk = disk.as_ref();
|
||||
let create_or_append_synthetic_conf = CreateOrAppendFile::plan(
|
||||
"/etc/synthetic.conf",
|
||||
"root".into(),
|
||||
"wheel".into(),
|
||||
0o0655,
|
||||
"nix".into(),
|
||||
)
|
||||
let create_or_append_synthetic_conf =
|
||||
CreateOrAppendFile::plan("/etc/synthetic.conf", None, None, 0o0655, "nix".into())
|
||||
.await?;
|
||||
|
||||
let create_synthetic_objects = CreateSyntheticObjects::plan().await?;
|
||||
|
@ -56,10 +51,10 @@ impl CreateApfsVolume {
|
|||
|
||||
let create_or_append_fstab = CreateOrAppendFile::plan(
|
||||
"/etc/fstab",
|
||||
"root".into(),
|
||||
"root".into(),
|
||||
None,
|
||||
None,
|
||||
0o0655,
|
||||
"NAME={name} /nix apfs rw,noauto,nobrowse,suid,owners".into(),
|
||||
format!("NAME=\"{name}\" /nix apfs rw,noauto,nobrowse,suid,owners"),
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
@ -138,7 +133,7 @@ impl Actionable for CreateApfsVolume {
|
|||
|
||||
create_or_append_synthetic_conf.execute().await?;
|
||||
create_synthetic_objects.execute().await?;
|
||||
unmount_volume.execute().await?;
|
||||
unmount_volume.execute().await.ok(); // We actually expect this may fail.
|
||||
create_volume.execute().await?;
|
||||
create_or_append_fstab.execute().await?;
|
||||
if let Some(encrypt_volume) = encrypt_volume {
|
||||
|
|
|
@ -9,7 +9,6 @@ pub mod darwin;
|
|||
mod place_channel_configuration;
|
||||
mod place_nix_configuration;
|
||||
mod provision_nix;
|
||||
mod start_nix_daemon;
|
||||
|
||||
pub use configure_nix::{ConfigureNix, ConfigureNixError};
|
||||
pub use configure_shell_profile::{ConfigureShellProfile, ConfigureShellProfileError};
|
||||
|
@ -19,4 +18,3 @@ pub use create_users_and_group::{CreateUsersAndGroup, CreateUsersAndGroupError};
|
|||
pub use place_channel_configuration::{PlaceChannelConfiguration, PlaceChannelConfigurationError};
|
||||
pub use place_nix_configuration::{PlaceNixConfiguration, PlaceNixConfigurationError};
|
||||
pub use provision_nix::{ProvisionNix, ProvisionNixError};
|
||||
pub use start_nix_daemon::{StartNixDaemon, StartNixDaemonError};
|
||||
|
|
|
@ -5,8 +5,6 @@ use crate::actions::{Action, ActionDescription, ActionState, Actionable};
|
|||
|
||||
use crate::actions::base::{CreateFile, CreateFileError};
|
||||
|
||||
const NIX_CHANNELS_PATH: &str = "/root/.nix-channels";
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct PlaceChannelConfiguration {
|
||||
channels: Vec<(String, Url)>,
|
||||
|
@ -26,9 +24,11 @@ impl PlaceChannelConfiguration {
|
|||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
let create_file = CreateFile::plan(
|
||||
NIX_CHANNELS_PATH,
|
||||
"root".into(),
|
||||
"root".into(),
|
||||
dirs::home_dir()
|
||||
.ok_or(PlaceChannelConfigurationError::NoRootHome)?
|
||||
.join("/.nix-channels"),
|
||||
None,
|
||||
None,
|
||||
0o0664,
|
||||
buf,
|
||||
force,
|
||||
|
@ -49,17 +49,18 @@ impl Actionable for PlaceChannelConfiguration {
|
|||
fn describe_execute(&self) -> Vec<ActionDescription> {
|
||||
let Self {
|
||||
channels: _,
|
||||
create_file: _,
|
||||
create_file,
|
||||
action_state: _,
|
||||
} = self;
|
||||
if self.action_state == ActionState::Completed {
|
||||
vec![]
|
||||
} else {
|
||||
vec![ActionDescription::new(
|
||||
format!("Place channel configuration at `{NIX_CHANNELS_PATH}`"),
|
||||
vec![format!(
|
||||
"Place channel configuration at `{NIX_CHANNELS_PATH}`"
|
||||
)],
|
||||
format!(
|
||||
"Place channel configuration at `{}`",
|
||||
create_file.path.display()
|
||||
),
|
||||
vec![],
|
||||
)]
|
||||
}
|
||||
}
|
||||
|
@ -90,17 +91,18 @@ impl Actionable for PlaceChannelConfiguration {
|
|||
fn describe_revert(&self) -> Vec<ActionDescription> {
|
||||
let Self {
|
||||
channels: _,
|
||||
create_file: _,
|
||||
create_file,
|
||||
action_state: _,
|
||||
} = self;
|
||||
if self.action_state == ActionState::Uncompleted {
|
||||
vec![]
|
||||
} else {
|
||||
vec![ActionDescription::new(
|
||||
format!("Remove channel configuration at `{NIX_CHANNELS_PATH}`"),
|
||||
vec![format!(
|
||||
"Remove channel configuration at `{NIX_CHANNELS_PATH}`"
|
||||
)],
|
||||
format!(
|
||||
"Remove channel configuration at `{}`",
|
||||
create_file.path.display()
|
||||
),
|
||||
vec![],
|
||||
)]
|
||||
}
|
||||
}
|
||||
|
@ -143,4 +145,6 @@ pub enum PlaceChannelConfigurationError {
|
|||
#[from]
|
||||
CreateFileError,
|
||||
),
|
||||
#[error("No root home found to place channel configuration in")]
|
||||
NoRootHome,
|
||||
}
|
||||
|
|
|
@ -33,10 +33,8 @@ impl PlaceNixConfiguration {
|
|||
extra_conf = extra_conf.unwrap_or_else(|| "".into()),
|
||||
);
|
||||
let create_directory =
|
||||
CreateDirectory::plan(NIX_CONF_FOLDER, "root".into(), "root".into(), 0o0755, force)
|
||||
.await?;
|
||||
let create_file =
|
||||
CreateFile::plan(NIX_CONF, "root".into(), "root".into(), 0o0664, buf, force).await?;
|
||||
CreateDirectory::plan(NIX_CONF_FOLDER, None, None, 0o0755, force).await?;
|
||||
let create_file = CreateFile::plan(NIX_CONF, None, None, 0o0664, buf, force).await?;
|
||||
Ok(Self {
|
||||
create_directory,
|
||||
create_file,
|
||||
|
|
|
@ -26,8 +26,7 @@ pub struct ProvisionNix {
|
|||
impl ProvisionNix {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn plan(settings: InstallSettings) -> Result<Self, ProvisionNixError> {
|
||||
let create_nix_dir =
|
||||
CreateDirectory::plan("/nix", "root".into(), "root".into(), 0o0755, true).await?;
|
||||
let create_nix_dir = CreateDirectory::plan("/nix", None, None, 0o0755, true).await?;
|
||||
|
||||
let fetch_nix = FetchNix::plan(
|
||||
settings.nix_package_url.clone(),
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
use serde::Serialize;
|
||||
|
||||
use crate::actions::base::{StartSystemdUnit, StartSystemdUnitError};
|
||||
|
||||
use crate::actions::{Action, ActionDescription, ActionState, Actionable};
|
||||
|
||||
/// This is mostly indirection for supporting non-systemd
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct StartNixDaemon {
|
||||
start_systemd_socket: StartSystemdUnit,
|
||||
action_state: ActionState,
|
||||
}
|
||||
|
||||
impl StartNixDaemon {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn plan() -> Result<Self, StartNixDaemonError> {
|
||||
let start_systemd_socket = StartSystemdUnit::plan("nix-daemon.socket".into()).await?;
|
||||
Ok(Self {
|
||||
start_systemd_socket,
|
||||
action_state: ActionState::Uncompleted,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Actionable for StartNixDaemon {
|
||||
type Error = StartNixDaemonError;
|
||||
|
||||
fn describe_execute(&self) -> Vec<ActionDescription> {
|
||||
if self.action_state == ActionState::Completed {
|
||||
vec![]
|
||||
} else {
|
||||
self.start_systemd_socket.describe_execute()
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), Self::Error> {
|
||||
let Self {
|
||||
start_systemd_socket,
|
||||
action_state,
|
||||
} = self;
|
||||
if *action_state == ActionState::Completed {
|
||||
tracing::trace!("Already completed: Starting the nix daemon");
|
||||
return Ok(());
|
||||
}
|
||||
*action_state = ActionState::Progress;
|
||||
tracing::debug!("Starting the nix daemon");
|
||||
|
||||
start_systemd_socket.execute().await?;
|
||||
|
||||
tracing::trace!("Started the nix daemon");
|
||||
*action_state = ActionState::Completed;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn describe_revert(&self) -> Vec<ActionDescription> {
|
||||
if self.action_state == ActionState::Uncompleted {
|
||||
vec![]
|
||||
} else {
|
||||
self.start_systemd_socket.describe_revert()
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), Self::Error> {
|
||||
let Self {
|
||||
start_systemd_socket,
|
||||
action_state,
|
||||
..
|
||||
} = self;
|
||||
if *action_state == ActionState::Uncompleted {
|
||||
tracing::trace!("Already reverted: Stop the nix daemon");
|
||||
return Ok(());
|
||||
}
|
||||
*action_state = ActionState::Progress;
|
||||
tracing::debug!("Stop the nix daemon");
|
||||
|
||||
start_systemd_socket.revert().await?;
|
||||
|
||||
tracing::trace!("Stopped the nix daemon");
|
||||
*action_state = ActionState::Uncompleted;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StartNixDaemon> for Action {
|
||||
fn from(v: StartNixDaemon) -> Self {
|
||||
Action::StartNixDaemon(v)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error, Serialize)]
|
||||
pub enum StartNixDaemonError {
|
||||
#[error("Starting systemd unit")]
|
||||
StartSystemdUnit(
|
||||
#[source]
|
||||
#[from]
|
||||
StartSystemdUnitError,
|
||||
),
|
||||
}
|
|
@ -15,7 +15,7 @@ use meta::{
|
|||
CreateNixTree, CreateNixTreeError, CreateSystemdSysext, CreateSystemdSysextError,
|
||||
CreateUsersAndGroup, CreateUsersAndGroupError, PlaceChannelConfiguration,
|
||||
PlaceChannelConfigurationError, PlaceNixConfiguration, PlaceNixConfigurationError,
|
||||
ProvisionNix, ProvisionNixError, StartNixDaemon, StartNixDaemonError,
|
||||
ProvisionNix, ProvisionNixError,
|
||||
};
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
|
||||
|
@ -62,6 +62,7 @@ pub enum Action {
|
|||
DarwinCreateVolume(base::darwin::CreateVolume),
|
||||
DarwinEnableOwnership(base::darwin::EnableOwnership),
|
||||
DarwinEncryptVolume(base::darwin::EncryptVolume),
|
||||
DarwinKickStartLaunchctlService(base::darwin::KickstartLaunchctlService),
|
||||
DarwinUnmountVolume(base::darwin::UnmountVolume),
|
||||
ConfigureNix(ConfigureNix),
|
||||
ConfigureNixDaemonService(ConfigureNixDaemonService),
|
||||
|
@ -81,7 +82,6 @@ pub enum Action {
|
|||
PlaceNixConfiguration(PlaceNixConfiguration),
|
||||
ProvisionNix(ProvisionNix),
|
||||
SetupDefaultProfile(SetupDefaultProfile),
|
||||
StartNixDaemon(StartNixDaemon),
|
||||
StartSystemdUnit(StartSystemdUnit),
|
||||
SystemdSysextMerge(SystemdSysextMerge),
|
||||
}
|
||||
|
@ -99,6 +99,8 @@ pub enum ActionError {
|
|||
#[error(transparent)]
|
||||
DarwinEncryptVolume(#[from] base::darwin::EncryptVolumeError),
|
||||
#[error(transparent)]
|
||||
DarwinKickStartLaunchctlService(#[from] base::darwin::KickstartLaunchctlServiceError),
|
||||
#[error(transparent)]
|
||||
DarwinUnmountVolume(#[from] base::darwin::UnmountVolumeError),
|
||||
#[error("Attempted to revert an unexecuted action")]
|
||||
NotExecuted(Action),
|
||||
|
@ -141,8 +143,6 @@ pub enum ActionError {
|
|||
#[error(transparent)]
|
||||
SetupDefaultProfile(#[from] SetupDefaultProfileError),
|
||||
#[error(transparent)]
|
||||
StartNixDaemon(#[from] StartNixDaemonError),
|
||||
#[error(transparent)]
|
||||
StartSystemdUnit(#[from] StartSystemdUnitError),
|
||||
#[error(transparent)]
|
||||
SystemdSysExtMerge(#[from] SystemdSysextMergeError),
|
||||
|
@ -179,7 +179,7 @@ impl Actionable for Action {
|
|||
Action::PlaceNixConfiguration(i) => i.describe_execute(),
|
||||
Action::ProvisionNix(i) => i.describe_execute(),
|
||||
Action::SetupDefaultProfile(i) => i.describe_execute(),
|
||||
Action::StartNixDaemon(i) => i.describe_execute(),
|
||||
Action::DarwinKickStartLaunchctlService(i) => i.describe_execute(),
|
||||
Action::StartSystemdUnit(i) => i.describe_execute(),
|
||||
Action::SystemdSysextMerge(i) => i.describe_execute(),
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ impl Actionable for Action {
|
|||
Action::PlaceNixConfiguration(i) => i.execute().await?,
|
||||
Action::ProvisionNix(i) => i.execute().await?,
|
||||
Action::SetupDefaultProfile(i) => i.execute().await?,
|
||||
Action::StartNixDaemon(i) => i.execute().await?,
|
||||
Action::DarwinKickStartLaunchctlService(i) => i.execute().await?,
|
||||
Action::StartSystemdUnit(i) => i.execute().await?,
|
||||
Action::SystemdSysextMerge(i) => i.execute().await?,
|
||||
};
|
||||
|
@ -244,7 +244,7 @@ impl Actionable for Action {
|
|||
Action::PlaceNixConfiguration(i) => i.describe_revert(),
|
||||
Action::ProvisionNix(i) => i.describe_revert(),
|
||||
Action::SetupDefaultProfile(i) => i.describe_revert(),
|
||||
Action::StartNixDaemon(i) => i.describe_revert(),
|
||||
Action::DarwinKickStartLaunchctlService(i) => i.describe_revert(),
|
||||
Action::StartSystemdUnit(i) => i.describe_revert(),
|
||||
Action::SystemdSysextMerge(i) => i.describe_revert(),
|
||||
}
|
||||
|
@ -276,7 +276,7 @@ impl Actionable for Action {
|
|||
Action::PlaceNixConfiguration(i) => i.revert().await?,
|
||||
Action::ProvisionNix(i) => i.revert().await?,
|
||||
Action::SetupDefaultProfile(i) => i.revert().await?,
|
||||
Action::StartNixDaemon(i) => i.revert().await?,
|
||||
Action::DarwinKickStartLaunchctlService(i) => i.revert().await?,
|
||||
Action::StartSystemdUnit(i) => i.revert().await?,
|
||||
Action::SystemdSysextMerge(i) => i.revert().await?,
|
||||
}
|
||||
|
|
|
@ -85,7 +85,9 @@ impl InstallPlan {
|
|||
// The plan itself represents the concept of the sequence of stages.
|
||||
for action in actions {
|
||||
if let Err(err) = action.execute().await {
|
||||
write_receipt(self.clone()).await?;
|
||||
if let Err(err) = write_receipt(self.clone()).await {
|
||||
tracing::error!("Error saving receipt: {:?}", err);
|
||||
}
|
||||
return Err(ActionError::from(err).into());
|
||||
}
|
||||
}
|
||||
|
@ -157,7 +159,9 @@ impl InstallPlan {
|
|||
// The plan itself represents the concept of the sequence of stages.
|
||||
for action in actions {
|
||||
if let Err(err) = action.revert().await {
|
||||
write_receipt(self.clone()).await?;
|
||||
if let Err(err) = write_receipt(self.clone()).await {
|
||||
tracing::error!("Error saving receipt: {:?}", err);
|
||||
}
|
||||
return Err(ActionError::from(err).into());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,8 @@ use tokio::process::Command;
|
|||
|
||||
use crate::{
|
||||
actions::{
|
||||
meta::{darwin::CreateApfsVolume, ConfigureNix, ProvisionNix, StartNixDaemon},
|
||||
base::darwin::KickstartLaunchctlService,
|
||||
meta::{darwin::CreateApfsVolume, ConfigureNix, ProvisionNix},
|
||||
Action, ActionError,
|
||||
},
|
||||
execute_command,
|
||||
|
@ -57,7 +58,7 @@ impl Plannable for DarwinMultiUser {
|
|||
.await
|
||||
.map(Action::from)
|
||||
.map_err(ActionError::from)?,
|
||||
StartNixDaemon::plan()
|
||||
KickstartLaunchctlService::plan("system/org.nixos.nix-daemon".into())
|
||||
.await
|
||||
.map(Action::from)
|
||||
.map_err(ActionError::from)?,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::{
|
||||
actions::{
|
||||
meta::{ConfigureNix, ProvisionNix, StartNixDaemon},
|
||||
base::StartSystemdUnit,
|
||||
meta::{ConfigureNix, ProvisionNix},
|
||||
Action, ActionError,
|
||||
},
|
||||
planner::{Plannable, PlannerError},
|
||||
|
@ -28,7 +29,7 @@ impl Plannable for LinuxMultiUser {
|
|||
.await
|
||||
.map(Action::from)
|
||||
.map_err(ActionError::from)?,
|
||||
StartNixDaemon::plan()
|
||||
StartSystemdUnit::plan("nix-daemon.socket".into())
|
||||
.await
|
||||
.map(Action::from)
|
||||
.map_err(ActionError::from)?,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::{
|
||||
actions::{
|
||||
meta::{CreateSystemdSysext, ProvisionNix, StartNixDaemon},
|
||||
base::StartSystemdUnit,
|
||||
meta::{CreateSystemdSysext, ProvisionNix},
|
||||
Action, ActionError,
|
||||
},
|
||||
planner::Plannable,
|
||||
|
@ -30,7 +31,7 @@ impl Plannable for SteamDeck {
|
|||
.await
|
||||
.map(Action::from)
|
||||
.map_err(ActionError::from)?,
|
||||
StartNixDaemon::plan()
|
||||
StartSystemdUnit::plan("nix-daemon.socket".into())
|
||||
.await
|
||||
.map(Action::from)
|
||||
.map_err(ActionError::from)?,
|
||||
|
|
Loading…
Reference in a new issue