Find xpath crate, scaffold more
This commit is contained in:
parent
a29baa2b33
commit
da0219deb0
41
Cargo.lock
generated
41
Cargo.lock
generated
|
@ -758,6 +758,8 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"serde_with",
|
||||
"sxd-document",
|
||||
"sxd-xpath",
|
||||
"tar",
|
||||
"target-lexicon",
|
||||
"tempdir",
|
||||
|
@ -1202,6 +1204,12 @@ version = "2.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
|
||||
|
||||
[[package]]
|
||||
name = "peresil"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f658886ed52e196e850cfbbfddab9eaa7f6d90dd0929e264c31e5cec07e09e57"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.0.12"
|
||||
|
@ -1287,6 +1295,12 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-error"
|
||||
version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.21"
|
||||
|
@ -1651,6 +1665,27 @@ dependencies = [
|
|||
"is_ci",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sxd-document"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94d82f37be9faf1b10a82c4bd492b74f698e40082f0f40de38ab275f31d42078"
|
||||
dependencies = [
|
||||
"peresil",
|
||||
"typed-arena",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sxd-xpath"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36e39da5d30887b5690e29de4c5ebb8ddff64ebd9933f98a01daaa4fd11b36ea"
|
||||
dependencies = [
|
||||
"peresil",
|
||||
"quick-error",
|
||||
"sxd-document",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.99"
|
||||
|
@ -1921,6 +1956,12 @@ version = "0.2.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
|
||||
|
||||
[[package]]
|
||||
name = "typed-arena"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d"
|
||||
|
||||
[[package]]
|
||||
name = "typetag"
|
||||
version = "0.2.3"
|
||||
|
|
26
Cargo.toml
26
Cargo.toml
|
@ -9,30 +9,32 @@ resolver = "2"
|
|||
async-tar = "0.4.2"
|
||||
async-trait = "0.1.57"
|
||||
atty = "0.2.14"
|
||||
bytes = "1.2.1"
|
||||
clap = { version = "4", features = ["derive", "env"] }
|
||||
color-eyre = "0.6.2"
|
||||
crossterm = { version = "0.25.0", features = ["event-stream"] }
|
||||
eyre = "0.6.8"
|
||||
futures = "0.3.24"
|
||||
glob = "0.3.0"
|
||||
nix = { version = "0.25.0", features = ["user", "fs"], default-features = false }
|
||||
owo-colors = { version = "3.5.0", features = [ "supports-colors" ] }
|
||||
reqwest = { version = "0.11.11", default-features = false, features = ["rustls-tls", "stream"] }
|
||||
serde = { version = "1.0.144", features = ["derive"] }
|
||||
serde_json = "1.0.85"
|
||||
serde_with = "2.0.1"
|
||||
tar = "0.4.38"
|
||||
target-lexicon = "0.12.4"
|
||||
tempdir = { version = "0.3.7"}
|
||||
thiserror = "1.0.33"
|
||||
tokio = { version = "1.21.0", features = ["time", "io-std", "process", "fs", "tracing", "rt-multi-thread", "macros", "io-util"] }
|
||||
tokio-util = { version = "0.7", features = ["io"] }
|
||||
tracing = { version = "0.1.36", features = [ "valuable" ] }
|
||||
tracing-error = "0.2.0"
|
||||
tracing-subscriber = { version = "0.3.15", features = [ "env-filter", "valuable" ] }
|
||||
valuable = { version = "0.1.0", features = ["derive"] }
|
||||
tempdir = { version = "0.3.7"}
|
||||
glob = "0.3.0"
|
||||
xz2 = { version = "0.1.7", features = ["static", "tokio"] }
|
||||
bytes = "1.2.1"
|
||||
tar = "0.4.38"
|
||||
nix = { version = "0.25.0", features = ["user", "fs"], default-features = false }
|
||||
walkdir = "2.3.2"
|
||||
serde = { version = "1.0.144", features = ["derive"] }
|
||||
url = { version = "2.3.1", features = ["serde"] }
|
||||
serde_json = "1.0.85"
|
||||
typetag = "0.2.3"
|
||||
serde_with = "2.0.1"
|
||||
url = { version = "2.3.1", features = ["serde"] }
|
||||
valuable = { version = "0.1.0", features = ["derive"] }
|
||||
walkdir = "2.3.2"
|
||||
sxd-xpath = "0.4.2"
|
||||
xz2 = { version = "0.1.7", features = ["static", "tokio"] }
|
||||
sxd-document = "0.3.2"
|
||||
|
|
116
src/actions/base/darwin/bootstrap_volume.rs
Normal file
116
src/actions/base/darwin/bootstrap_volume.rs
Normal file
|
@ -0,0 +1,116 @@
|
|||
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 BootstrapVolume {
|
||||
unit: String,
|
||||
action_state: ActionState,
|
||||
}
|
||||
|
||||
impl BootstrapVolume {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn plan(unit: String) -> Result<Self, BootstrapVolumeError> {
|
||||
Ok(Self {
|
||||
unit,
|
||||
action_state: ActionState::Uncompleted,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Actionable for BootstrapVolume {
|
||||
type Error = BootstrapVolumeError;
|
||||
|
||||
fn describe_execute(&self) -> Vec<ActionDescription> {
|
||||
if self.action_state == ActionState::Completed {
|
||||
vec![]
|
||||
} else {
|
||||
vec![ActionDescription::new(
|
||||
"Start the systemd Nix service and socket".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 execute(&mut self) -> Result<(), Self::Error> {
|
||||
let Self { unit, action_state } = self;
|
||||
if *action_state == ActionState::Completed {
|
||||
tracing::trace!("Already completed: Starting systemd unit");
|
||||
return Ok(());
|
||||
}
|
||||
tracing::debug!("Starting systemd unit");
|
||||
|
||||
// TODO(@Hoverbear): Handle proxy vars
|
||||
execute_command(
|
||||
Command::new("systemctl")
|
||||
.arg("enable")
|
||||
.arg("--now")
|
||||
.arg(format!("{unit}")),
|
||||
)
|
||||
.await
|
||||
.map_err(BootstrapVolumeError::Command)?;
|
||||
|
||||
tracing::trace!("Started systemd unit");
|
||||
*action_state = ActionState::Completed;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn describe_revert(&self) -> Vec<ActionDescription> {
|
||||
if self.action_state == ActionState::Uncompleted {
|
||||
vec![]
|
||||
} else {
|
||||
vec![ActionDescription::new(
|
||||
"Stop the systemd Nix service and socket".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 systemd unit");
|
||||
return Ok(());
|
||||
}
|
||||
tracing::debug!("Stopping systemd unit");
|
||||
|
||||
// TODO(@Hoverbear): Handle proxy vars
|
||||
execute_command(Command::new("systemctl").arg("stop").arg(format!("{unit}")))
|
||||
.await
|
||||
.map_err(BootstrapVolumeError::Command)?;
|
||||
|
||||
tracing::trace!("Stopped systemd unit");
|
||||
*action_state = ActionState::Completed;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BootstrapVolume> for Action {
|
||||
fn from(v: BootstrapVolume) -> Self {
|
||||
Action::DarwinBootstrapVolume(v)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error, Serialize)]
|
||||
pub enum BootstrapVolumeError {
|
||||
#[error("Failed to execute command")]
|
||||
Command(
|
||||
#[source]
|
||||
#[serde(serialize_with = "crate::serialize_error_to_display")]
|
||||
std::io::Error,
|
||||
),
|
||||
}
|
116
src/actions/base/darwin/create_synthetic_objects.rs
Normal file
116
src/actions/base/darwin/create_synthetic_objects.rs
Normal file
|
@ -0,0 +1,116 @@
|
|||
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 CreateSyntheticObjects {
|
||||
unit: String,
|
||||
action_state: ActionState,
|
||||
}
|
||||
|
||||
impl CreateSyntheticObjects {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn plan(unit: String) -> Result<Self, CreateSyntheticObjectsError> {
|
||||
Ok(Self {
|
||||
unit,
|
||||
action_state: ActionState::Uncompleted,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Actionable for CreateSyntheticObjects {
|
||||
type Error = CreateSyntheticObjectsError;
|
||||
|
||||
fn describe_execute(&self) -> Vec<ActionDescription> {
|
||||
if self.action_state == ActionState::Completed {
|
||||
vec![]
|
||||
} else {
|
||||
vec![ActionDescription::new(
|
||||
"Start the systemd Nix service and socket".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 execute(&mut self) -> Result<(), Self::Error> {
|
||||
let Self { unit, action_state } = self;
|
||||
if *action_state == ActionState::Completed {
|
||||
tracing::trace!("Already completed: Starting systemd unit");
|
||||
return Ok(());
|
||||
}
|
||||
tracing::debug!("Starting systemd unit");
|
||||
|
||||
// TODO(@Hoverbear): Handle proxy vars
|
||||
execute_command(
|
||||
Command::new("systemctl")
|
||||
.arg("enable")
|
||||
.arg("--now")
|
||||
.arg(format!("{unit}")),
|
||||
)
|
||||
.await
|
||||
.map_err(CreateSyntheticObjectsError::Command)?;
|
||||
|
||||
tracing::trace!("Started systemd unit");
|
||||
*action_state = ActionState::Completed;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn describe_revert(&self) -> Vec<ActionDescription> {
|
||||
if self.action_state == ActionState::Uncompleted {
|
||||
vec![]
|
||||
} else {
|
||||
vec![ActionDescription::new(
|
||||
"Stop the systemd Nix service and socket".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 systemd unit");
|
||||
return Ok(());
|
||||
}
|
||||
tracing::debug!("Stopping systemd unit");
|
||||
|
||||
// TODO(@Hoverbear): Handle proxy vars
|
||||
execute_command(Command::new("systemctl").arg("stop").arg(format!("{unit}")))
|
||||
.await
|
||||
.map_err(CreateSyntheticObjectsError::Command)?;
|
||||
|
||||
tracing::trace!("Stopped systemd unit");
|
||||
*action_state = ActionState::Completed;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CreateSyntheticObjects> for Action {
|
||||
fn from(v: CreateSyntheticObjects) -> Self {
|
||||
Action::DarwinCreateSyntheticObjects(v)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error, Serialize)]
|
||||
pub enum CreateSyntheticObjectsError {
|
||||
#[error("Failed to execute command")]
|
||||
Command(
|
||||
#[source]
|
||||
#[serde(serialize_with = "crate::serialize_error_to_display")]
|
||||
std::io::Error,
|
||||
),
|
||||
}
|
116
src/actions/base/darwin/create_volume.rs
Normal file
116
src/actions/base/darwin/create_volume.rs
Normal file
|
@ -0,0 +1,116 @@
|
|||
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 CreateVolume {
|
||||
unit: String,
|
||||
action_state: ActionState,
|
||||
}
|
||||
|
||||
impl CreateVolume {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn plan(unit: String) -> Result<Self, CreateVolumeError> {
|
||||
Ok(Self {
|
||||
unit,
|
||||
action_state: ActionState::Uncompleted,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Actionable for CreateVolume {
|
||||
type Error = CreateVolumeError;
|
||||
|
||||
fn describe_execute(&self) -> Vec<ActionDescription> {
|
||||
if self.action_state == ActionState::Completed {
|
||||
vec![]
|
||||
} else {
|
||||
vec![ActionDescription::new(
|
||||
"Start the systemd Nix service and socket".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 execute(&mut self) -> Result<(), Self::Error> {
|
||||
let Self { unit, action_state } = self;
|
||||
if *action_state == ActionState::Completed {
|
||||
tracing::trace!("Already completed: Starting systemd unit");
|
||||
return Ok(());
|
||||
}
|
||||
tracing::debug!("Starting systemd unit");
|
||||
|
||||
// TODO(@Hoverbear): Handle proxy vars
|
||||
execute_command(
|
||||
Command::new("systemctl")
|
||||
.arg("enable")
|
||||
.arg("--now")
|
||||
.arg(format!("{unit}")),
|
||||
)
|
||||
.await
|
||||
.map_err(CreateVolumeError::Command)?;
|
||||
|
||||
tracing::trace!("Started systemd unit");
|
||||
*action_state = ActionState::Completed;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn describe_revert(&self) -> Vec<ActionDescription> {
|
||||
if self.action_state == ActionState::Uncompleted {
|
||||
vec![]
|
||||
} else {
|
||||
vec![ActionDescription::new(
|
||||
"Stop the systemd Nix service and socket".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 systemd unit");
|
||||
return Ok(());
|
||||
}
|
||||
tracing::debug!("Stopping systemd unit");
|
||||
|
||||
// TODO(@Hoverbear): Handle proxy vars
|
||||
execute_command(Command::new("systemctl").arg("stop").arg(format!("{unit}")))
|
||||
.await
|
||||
.map_err(CreateVolumeError::Command)?;
|
||||
|
||||
tracing::trace!("Stopped systemd unit");
|
||||
*action_state = ActionState::Completed;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CreateVolume> for Action {
|
||||
fn from(v: CreateVolume) -> Self {
|
||||
Action::DarwinCreateVolume(v)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error, Serialize)]
|
||||
pub enum CreateVolumeError {
|
||||
#[error("Failed to execute command")]
|
||||
Command(
|
||||
#[source]
|
||||
#[serde(serialize_with = "crate::serialize_error_to_display")]
|
||||
std::io::Error,
|
||||
),
|
||||
}
|
116
src/actions/base/darwin/enable_ownership.rs
Normal file
116
src/actions/base/darwin/enable_ownership.rs
Normal file
|
@ -0,0 +1,116 @@
|
|||
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 EnableOwnership {
|
||||
unit: String,
|
||||
action_state: ActionState,
|
||||
}
|
||||
|
||||
impl EnableOwnership {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn plan(unit: String) -> Result<Self, EnableOwnershipError> {
|
||||
Ok(Self {
|
||||
unit,
|
||||
action_state: ActionState::Uncompleted,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Actionable for EnableOwnership {
|
||||
type Error = EnableOwnershipError;
|
||||
|
||||
fn describe_execute(&self) -> Vec<ActionDescription> {
|
||||
if self.action_state == ActionState::Completed {
|
||||
vec![]
|
||||
} else {
|
||||
vec![ActionDescription::new(
|
||||
"Start the systemd Nix service and socket".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 execute(&mut self) -> Result<(), Self::Error> {
|
||||
let Self { unit, action_state } = self;
|
||||
if *action_state == ActionState::Completed {
|
||||
tracing::trace!("Already completed: Starting systemd unit");
|
||||
return Ok(());
|
||||
}
|
||||
tracing::debug!("Starting systemd unit");
|
||||
|
||||
// TODO(@Hoverbear): Handle proxy vars
|
||||
execute_command(
|
||||
Command::new("systemctl")
|
||||
.arg("enable")
|
||||
.arg("--now")
|
||||
.arg(format!("{unit}")),
|
||||
)
|
||||
.await
|
||||
.map_err(EnableOwnershipError::Command)?;
|
||||
|
||||
tracing::trace!("Started systemd unit");
|
||||
*action_state = ActionState::Completed;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn describe_revert(&self) -> Vec<ActionDescription> {
|
||||
if self.action_state == ActionState::Uncompleted {
|
||||
vec![]
|
||||
} else {
|
||||
vec![ActionDescription::new(
|
||||
"Stop the systemd Nix service and socket".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 systemd unit");
|
||||
return Ok(());
|
||||
}
|
||||
tracing::debug!("Stopping systemd unit");
|
||||
|
||||
// TODO(@Hoverbear): Handle proxy vars
|
||||
execute_command(Command::new("systemctl").arg("stop").arg(format!("{unit}")))
|
||||
.await
|
||||
.map_err(EnableOwnershipError::Command)?;
|
||||
|
||||
tracing::trace!("Stopped systemd unit");
|
||||
*action_state = ActionState::Completed;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EnableOwnership> for Action {
|
||||
fn from(v: EnableOwnership) -> Self {
|
||||
Action::DarwinEnableOwnership(v)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error, Serialize)]
|
||||
pub enum EnableOwnershipError {
|
||||
#[error("Failed to execute command")]
|
||||
Command(
|
||||
#[source]
|
||||
#[serde(serialize_with = "crate::serialize_error_to_display")]
|
||||
std::io::Error,
|
||||
),
|
||||
}
|
116
src/actions/base/darwin/encrypt_volume.rs
Normal file
116
src/actions/base/darwin/encrypt_volume.rs
Normal file
|
@ -0,0 +1,116 @@
|
|||
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 EncryptVolume {
|
||||
unit: String,
|
||||
action_state: ActionState,
|
||||
}
|
||||
|
||||
impl EncryptVolume {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn plan(unit: String) -> Result<Self, EncryptVolumeError> {
|
||||
Ok(Self {
|
||||
unit,
|
||||
action_state: ActionState::Uncompleted,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Actionable for EncryptVolume {
|
||||
type Error = EncryptVolumeError;
|
||||
|
||||
fn describe_execute(&self) -> Vec<ActionDescription> {
|
||||
if self.action_state == ActionState::Completed {
|
||||
vec![]
|
||||
} else {
|
||||
vec![ActionDescription::new(
|
||||
"Start the systemd Nix service and socket".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 execute(&mut self) -> Result<(), Self::Error> {
|
||||
let Self { unit, action_state } = self;
|
||||
if *action_state == ActionState::Completed {
|
||||
tracing::trace!("Already completed: Starting systemd unit");
|
||||
return Ok(());
|
||||
}
|
||||
tracing::debug!("Starting systemd unit");
|
||||
|
||||
// TODO(@Hoverbear): Handle proxy vars
|
||||
execute_command(
|
||||
Command::new("systemctl")
|
||||
.arg("enable")
|
||||
.arg("--now")
|
||||
.arg(format!("{unit}")),
|
||||
)
|
||||
.await
|
||||
.map_err(EncryptVolumeError::Command)?;
|
||||
|
||||
tracing::trace!("Started systemd unit");
|
||||
*action_state = ActionState::Completed;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn describe_revert(&self) -> Vec<ActionDescription> {
|
||||
if self.action_state == ActionState::Uncompleted {
|
||||
vec![]
|
||||
} else {
|
||||
vec![ActionDescription::new(
|
||||
"Stop the systemd Nix service and socket".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 systemd unit");
|
||||
return Ok(());
|
||||
}
|
||||
tracing::debug!("Stopping systemd unit");
|
||||
|
||||
// TODO(@Hoverbear): Handle proxy vars
|
||||
execute_command(Command::new("systemctl").arg("stop").arg(format!("{unit}")))
|
||||
.await
|
||||
.map_err(EncryptVolumeError::Command)?;
|
||||
|
||||
tracing::trace!("Stopped systemd unit");
|
||||
*action_state = ActionState::Completed;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EncryptVolume> for Action {
|
||||
fn from(v: EncryptVolume) -> Self {
|
||||
Action::DarwinEncryptVolume(v)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error, Serialize)]
|
||||
pub enum EncryptVolumeError {
|
||||
#[error("Failed to execute command")]
|
||||
Command(
|
||||
#[source]
|
||||
#[serde(serialize_with = "crate::serialize_error_to_display")]
|
||||
std::io::Error,
|
||||
),
|
||||
}
|
13
src/actions/base/darwin/mod.rs
Normal file
13
src/actions/base/darwin/mod.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
mod bootstrap_volume;
|
||||
mod create_synthetic_objects;
|
||||
mod create_volume;
|
||||
mod enable_ownership;
|
||||
mod encrypt_volume;
|
||||
mod unmount_volume;
|
||||
|
||||
pub use bootstrap_volume::{BootstrapVolume, BootstrapVolumeError};
|
||||
pub use create_synthetic_objects::{CreateSyntheticObjects, CreateSyntheticObjectsError};
|
||||
pub use create_volume::{CreateVolume, CreateVolumeError};
|
||||
pub use enable_ownership::{EnableOwnership, EnableOwnershipError};
|
||||
pub use encrypt_volume::{EncryptVolume, EncryptVolumeError};
|
||||
pub use unmount_volume::{UnmountVolume, UnmountVolumeError};
|
116
src/actions/base/darwin/unmount_volume.rs
Normal file
116
src/actions/base/darwin/unmount_volume.rs
Normal file
|
@ -0,0 +1,116 @@
|
|||
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 UnmountVolume {
|
||||
unit: String,
|
||||
action_state: ActionState,
|
||||
}
|
||||
|
||||
impl UnmountVolume {
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn plan(unit: String) -> Result<Self, UnmountVolumeError> {
|
||||
Ok(Self {
|
||||
unit,
|
||||
action_state: ActionState::Uncompleted,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Actionable for UnmountVolume {
|
||||
type Error = UnmountVolumeError;
|
||||
|
||||
fn describe_execute(&self) -> Vec<ActionDescription> {
|
||||
if self.action_state == ActionState::Completed {
|
||||
vec![]
|
||||
} else {
|
||||
vec![ActionDescription::new(
|
||||
"Start the systemd Nix service and socket".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 execute(&mut self) -> Result<(), Self::Error> {
|
||||
let Self { unit, action_state } = self;
|
||||
if *action_state == ActionState::Completed {
|
||||
tracing::trace!("Already completed: Starting systemd unit");
|
||||
return Ok(());
|
||||
}
|
||||
tracing::debug!("Starting systemd unit");
|
||||
|
||||
// TODO(@Hoverbear): Handle proxy vars
|
||||
execute_command(
|
||||
Command::new("systemctl")
|
||||
.arg("enable")
|
||||
.arg("--now")
|
||||
.arg(format!("{unit}")),
|
||||
)
|
||||
.await
|
||||
.map_err(UnmountVolumeError::Command)?;
|
||||
|
||||
tracing::trace!("Started systemd unit");
|
||||
*action_state = ActionState::Completed;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn describe_revert(&self) -> Vec<ActionDescription> {
|
||||
if self.action_state == ActionState::Uncompleted {
|
||||
vec![]
|
||||
} else {
|
||||
vec![ActionDescription::new(
|
||||
"Stop the systemd Nix service and socket".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 systemd unit");
|
||||
return Ok(());
|
||||
}
|
||||
tracing::debug!("Stopping systemd unit");
|
||||
|
||||
// TODO(@Hoverbear): Handle proxy vars
|
||||
execute_command(Command::new("systemctl").arg("stop").arg(format!("{unit}")))
|
||||
.await
|
||||
.map_err(UnmountVolumeError::Command)?;
|
||||
|
||||
tracing::trace!("Stopped systemd unit");
|
||||
*action_state = ActionState::Completed;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UnmountVolume> for Action {
|
||||
fn from(v: UnmountVolume) -> Self {
|
||||
Action::DarwinUnmountVolume(v)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error, Serialize)]
|
||||
pub enum UnmountVolumeError {
|
||||
#[error("Failed to execute command")]
|
||||
Command(
|
||||
#[source]
|
||||
#[serde(serialize_with = "crate::serialize_error_to_display")]
|
||||
std::io::Error,
|
||||
),
|
||||
}
|
|
@ -6,6 +6,7 @@ mod create_file;
|
|||
mod create_group;
|
||||
mod create_or_append_file;
|
||||
mod create_user;
|
||||
pub mod darwin;
|
||||
mod fetch_nix;
|
||||
mod move_unpacked_nix;
|
||||
mod setup_default_profile;
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::actions::base::{
|
|||
CreateDirectory, CreateDirectoryError, CreateFile, CreateFileError, CreateOrAppendFile,
|
||||
CreateOrAppendFileError,
|
||||
};
|
||||
use crate::actions::{Action, ActionDescription, ActionState, Actionable};
|
||||
use crate::actions::{base::darwin, Action, ActionDescription, ActionState, Actionable};
|
||||
|
||||
const NIX_VOLUME_MOUNTD_DEST: &str = "/Library/LaunchDaemons/org.nixos.darwin-store.plist";
|
||||
|
||||
|
@ -71,7 +71,7 @@ impl CreateApfsVolume {
|
|||
None
|
||||
};
|
||||
|
||||
let bootstrap_volume = BootstrapVolume::plan(NIX_VOLUME_MOUNTD_DEST).await?;
|
||||
let bootstrap_volume = BootstrapVolume::plan(NIX_VOLUME_MOUNTD_DEST, disk, name).await?;
|
||||
let enable_ownership = EnableOwnership::plan("/nix").await?;
|
||||
|
||||
Ok(Self {
|
||||
|
@ -116,7 +116,7 @@ impl Actionable for CreateApfsVolume {
|
|||
vec![]
|
||||
} else {
|
||||
vec![ActionDescription::new(
|
||||
format!("Create an APFS volume", destination.display()),
|
||||
format!("Create an APFS volume `{name}` on `{}`", disk.display()),
|
||||
vec![format!(
|
||||
"Create a writable, persistent systemd system extension.",
|
||||
)],
|
||||
|
@ -142,18 +142,21 @@ impl Actionable for CreateApfsVolume {
|
|||
action_state,
|
||||
} = self;
|
||||
if *action_state == ActionState::Completed {
|
||||
tracing::trace!("Already completed: Creating sysext");
|
||||
tracing::trace!("Already completed: Creating APFS volume");
|
||||
return Ok(());
|
||||
}
|
||||
tracing::debug!("Creating sysext");
|
||||
tracing::debug!("Creating APFS volume");
|
||||
|
||||
for create_directory in create_directories {
|
||||
create_directory.execute().await?;
|
||||
}
|
||||
create_extension_release.execute().await?;
|
||||
create_bind_mount_unit.execute().await?;
|
||||
create_or_append_synthetic_conf.execute().await?;
|
||||
create_synthetic_objects.execute().await?;
|
||||
unmount_volume.execute().await?;
|
||||
create_volume.execute().await?;
|
||||
create_or_append_fstab.execute().await?;
|
||||
encrypt_volume.execute().await?;
|
||||
bootstrap_volume.execute().await?;
|
||||
enable_ownership.execute().await?;
|
||||
|
||||
tracing::trace!("Created sysext");
|
||||
tracing::trace!("Created APFS volume");
|
||||
*action_state = ActionState::Completed;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -178,19 +181,21 @@ impl Actionable for CreateApfsVolume {
|
|||
vec![]
|
||||
} else {
|
||||
vec![ActionDescription::new(
|
||||
format!("Remove the sysext located at `{}`", destination.display()),
|
||||
vec![],
|
||||
format!("Remove the APFS volume `{name}` on `{}`", disk.display()),
|
||||
vec![format!(
|
||||
"Create a writable, persistent systemd system extension.",
|
||||
)],
|
||||
)]
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all, fields(destination,))]
|
||||
#[tracing::instrument(skip_all, fields(disk, name))]
|
||||
async fn revert(&mut self) -> Result<(), Self::Error> {
|
||||
let Self {
|
||||
disk,
|
||||
name,
|
||||
case_sensitive,
|
||||
encrypt,
|
||||
disk: _,
|
||||
name: _,
|
||||
case_sensitive: _,
|
||||
encrypt: _,
|
||||
create_or_append_synthetic_conf,
|
||||
create_synthetic_objects,
|
||||
unmount_volume,
|
||||
|
@ -202,20 +207,26 @@ impl Actionable for CreateApfsVolume {
|
|||
action_state,
|
||||
} = self;
|
||||
if *action_state == ActionState::Uncompleted {
|
||||
tracing::trace!("Already reverted: Removing sysext");
|
||||
tracing::trace!("Already reverted: Removing APFS volume");
|
||||
return Ok(());
|
||||
}
|
||||
tracing::debug!("Removing sysext");
|
||||
tracing::debug!("Removing APFS volume");
|
||||
|
||||
create_bind_mount_unit.revert().await?;
|
||||
|
||||
create_extension_release.revert().await?;
|
||||
|
||||
for create_directory in create_directories.iter_mut().rev() {
|
||||
create_directory.revert().await?;
|
||||
enable_ownership.revert().await?;
|
||||
bootstrap_volume.revert().await?;
|
||||
if let Some(encrypt_volume) = encrypt_volume {
|
||||
encrypt_volume.revert().await?;
|
||||
}
|
||||
create_or_append_fstab.revert().await?;
|
||||
|
||||
tracing::trace!("Removed sysext");
|
||||
unmount_volume.revert().await?;
|
||||
create_volume.revert().await?;
|
||||
|
||||
// Purposefully not reversed
|
||||
create_or_append_synthetic_conf.revert().await?;
|
||||
create_synthetic_objects.revert().await?;
|
||||
|
||||
tracing::trace!("Removed APFS volume");
|
||||
*action_state = ActionState::Uncompleted;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -229,6 +240,18 @@ impl From<CreateApfsVolume> for Action {
|
|||
|
||||
#[derive(Debug, thiserror::Error, Serialize)]
|
||||
pub enum CreateApfsVolumeError {
|
||||
#[error(transparent)]
|
||||
DarwinBootstrapVolume(#[from] BootstrapVolumeError),
|
||||
#[error(transparent)]
|
||||
DarwinCreateSyntheticObjects(#[from] CreateSyntheticObjectsError),
|
||||
#[error(transparent)]
|
||||
DarwinCreateVolume(#[from] CreateVolumeError),
|
||||
#[error(transparent)]
|
||||
DarwinEnableOwnership(#[from] EnableOwnershipError),
|
||||
#[error(transparent)]
|
||||
DarwinEncryptVolume(#[from] EncryptVolumeError),
|
||||
#[error(transparent)]
|
||||
DarwinUnmountVolume(#[from] UnmountVolumeError),
|
||||
#[error(transparent)]
|
||||
CreateOrAppendFile(#[from] CreateOrAppendFileError),
|
||||
}
|
||||
|
|
|
@ -57,6 +57,12 @@ impl ActionDescription {
|
|||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub enum Action {
|
||||
DarwinBootstrapVolume(base::darwin::BootstrapVolume),
|
||||
DarwinCreateSyntheticObjects(base::darwin::CreateSyntheticObjects),
|
||||
DarwinCreateVolume(base::darwin::CreateVolume),
|
||||
DarwinEnableOwnership(base::darwin::EnableOwnership),
|
||||
DarwinEncryptVolume(base::darwin::EncryptVolume),
|
||||
DarwinUnmountVolume(base::darwin::UnmountVolume),
|
||||
ConfigureNix(ConfigureNix),
|
||||
ConfigureNixDaemonService(ConfigureNixDaemonService),
|
||||
ConfigureShellProfile(ConfigureShellProfile),
|
||||
|
@ -82,6 +88,18 @@ pub enum Action {
|
|||
|
||||
#[derive(Debug, thiserror::Error, serde::Serialize)]
|
||||
pub enum ActionError {
|
||||
#[error(transparent)]
|
||||
DarwinBootstrapVolume(#[from] base::darwin::BootstrapVolumeError),
|
||||
#[error(transparent)]
|
||||
DarwinCreateSyntheticObjects(#[from] base::darwin::CreateSyntheticObjectsError),
|
||||
#[error(transparent)]
|
||||
DarwinCreateVolume(#[from] base::darwin::CreateVolumeError),
|
||||
#[error(transparent)]
|
||||
DarwinEnableOwnership(#[from] base::darwin::EnableOwnershipError),
|
||||
#[error(transparent)]
|
||||
DarwinEncryptVolume(#[from] base::darwin::EncryptVolumeError),
|
||||
#[error(transparent)]
|
||||
DarwinUnmountVolume(#[from] base::darwin::UnmountVolumeError),
|
||||
#[error("Attempted to revert an unexecuted action")]
|
||||
NotExecuted(Action),
|
||||
#[error("Attempted to execute an already executed action")]
|
||||
|
@ -137,6 +155,12 @@ impl Actionable for Action {
|
|||
type Error = ActionError;
|
||||
fn describe_execute(&self) -> Vec<ActionDescription> {
|
||||
match self {
|
||||
Action::DarwinBootstrapVolume(i) => i.describe_execute(),
|
||||
Action::DarwinCreateSyntheticObjects(i) => i.describe_execute(),
|
||||
Action::DarwinCreateVolume(i) => i.describe_execute(),
|
||||
Action::DarwinEnableOwnership(i) => i.describe_execute(),
|
||||
Action::DarwinEncryptVolume(i) => i.describe_execute(),
|
||||
Action::DarwinUnmountVolume(i) => i.describe_execute(),
|
||||
Action::ConfigureNix(i) => i.describe_execute(),
|
||||
Action::ConfigureNixDaemonService(i) => i.describe_execute(),
|
||||
Action::ConfigureShellProfile(i) => i.describe_execute(),
|
||||
|
@ -163,6 +187,12 @@ impl Actionable for Action {
|
|||
|
||||
async fn execute(&mut self) -> Result<(), Self::Error> {
|
||||
match self {
|
||||
Action::DarwinBootstrapVolume(i) => i.execute().await?,
|
||||
Action::DarwinCreateSyntheticObjects(i) => i.execute().await?,
|
||||
Action::DarwinCreateVolume(i) => i.execute().await?,
|
||||
Action::DarwinEnableOwnership(i) => i.execute().await?,
|
||||
Action::DarwinEncryptVolume(i) => i.execute().await?,
|
||||
Action::DarwinUnmountVolume(i) => i.execute().await?,
|
||||
Action::ConfigureNix(i) => i.execute().await?,
|
||||
Action::ConfigureNixDaemonService(i) => i.execute().await?,
|
||||
Action::ConfigureShellProfile(i) => i.execute().await?,
|
||||
|
@ -190,6 +220,12 @@ impl Actionable for Action {
|
|||
|
||||
fn describe_revert(&self) -> Vec<ActionDescription> {
|
||||
match self {
|
||||
Action::DarwinBootstrapVolume(i) => i.describe_revert(),
|
||||
Action::DarwinCreateSyntheticObjects(i) => i.describe_revert(),
|
||||
Action::DarwinCreateVolume(i) => i.describe_revert(),
|
||||
Action::DarwinEnableOwnership(i) => i.describe_revert(),
|
||||
Action::DarwinEncryptVolume(i) => i.describe_revert(),
|
||||
Action::DarwinUnmountVolume(i) => i.describe_revert(),
|
||||
Action::ConfigureNix(i) => i.describe_revert(),
|
||||
Action::ConfigureNixDaemonService(i) => i.describe_revert(),
|
||||
Action::ConfigureShellProfile(i) => i.describe_revert(),
|
||||
|
@ -216,6 +252,12 @@ impl Actionable for Action {
|
|||
|
||||
async fn revert(&mut self) -> Result<(), Self::Error> {
|
||||
match self {
|
||||
Action::DarwinBootstrapVolume(i) => i.revert().await?,
|
||||
Action::DarwinCreateSyntheticObjects(i) => i.revert().await?,
|
||||
Action::DarwinCreateVolume(i) => i.revert().await?,
|
||||
Action::DarwinEnableOwnership(i) => i.revert().await?,
|
||||
Action::DarwinEncryptVolume(i) => i.revert().await?,
|
||||
Action::DarwinUnmountVolume(i) => i.revert().await?,
|
||||
Action::ConfigureNix(i) => i.revert().await?,
|
||||
Action::ConfigureNixDaemonService(i) => i.revert().await?,
|
||||
Action::ConfigureShellProfile(i) => i.revert().await?,
|
||||
|
|
14
src/lib.rs
14
src/lib.rs
|
@ -4,7 +4,11 @@ mod plan;
|
|||
mod planner;
|
||||
mod settings;
|
||||
|
||||
use std::{ffi::OsStr, fmt::Display, process::ExitStatus};
|
||||
use std::{
|
||||
ffi::OsStr,
|
||||
fmt::Display,
|
||||
process::{ExitStatus, Output},
|
||||
};
|
||||
|
||||
pub use error::HarmonicError;
|
||||
pub use plan::InstallPlan;
|
||||
|
@ -15,12 +19,12 @@ pub use settings::InstallSettings;
|
|||
use tokio::process::Command;
|
||||
|
||||
#[tracing::instrument(skip_all, fields(command = %format!("{:?}", command.as_std())))]
|
||||
async fn execute_command(command: &mut Command) -> Result<ExitStatus, std::io::Error> {
|
||||
async fn execute_command(command: &mut Command) -> Result<Output, std::io::Error> {
|
||||
tracing::trace!("Executing");
|
||||
let command_str = format!("{:?}", command.as_std());
|
||||
let status = command.status().await?;
|
||||
match status.success() {
|
||||
true => Ok(status),
|
||||
let output = command.output().await?;
|
||||
match output.status.success() {
|
||||
true => Ok(output),
|
||||
false => Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!("Command `{command_str}` failed status"),
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
use tokio::process::Command;
|
||||
|
||||
use crate::{
|
||||
actions::{
|
||||
meta::{darwin::CreateApfsVolume, ConfigureNix, ProvisionNix, StartNixDaemon},
|
||||
Action, ActionError,
|
||||
},
|
||||
planner::Plannable,
|
||||
execute_command,
|
||||
planner::{Plannable, PlannerError},
|
||||
InstallPlan, Planner,
|
||||
};
|
||||
|
||||
|
@ -18,6 +21,28 @@ impl Plannable for DarwinMultiUser {
|
|||
async fn plan(
|
||||
settings: crate::InstallSettings,
|
||||
) -> Result<crate::InstallPlan, crate::planner::PlannerError> {
|
||||
let root_disk = {
|
||||
let root_disk_buf =
|
||||
execute_command(Command::new("/usr/sbin/diskutil").args(["info", "-plist", "/"]))
|
||||
.await
|
||||
.unwrap()
|
||||
.stdout;
|
||||
let package =
|
||||
sxd_document::parser::parse(&String::from_utf8(root_disk_buf).unwrap()).unwrap();
|
||||
|
||||
match sxd_xpath::evaluate_xpath(
|
||||
&package.as_document(),
|
||||
"/plist/dict/key[text()='ParentWholeDisk']/following-sibling::string[1]/text()",
|
||||
)
|
||||
.unwrap()
|
||||
{
|
||||
sxd_xpath::Value::String(s) => s,
|
||||
_ => panic!("At the disk i/o!!!"),
|
||||
}
|
||||
};
|
||||
|
||||
let volume_label = "Nix Store".into();
|
||||
|
||||
Ok(InstallPlan {
|
||||
planner: Self.into(),
|
||||
settings: settings.clone(),
|
||||
|
@ -26,7 +51,7 @@ impl Plannable for DarwinMultiUser {
|
|||
//
|
||||
// setup_Synthetic -> create_synthetic_objects
|
||||
// Unmount -> create_volume -> Setup_fstab -> maybe encrypt_volume -> launchctl bootstrap -> launchctl kickstart -> await_volume -> maybe enableOwnership
|
||||
CreateApfsVolume::plan(settings.clone())
|
||||
CreateApfsVolume::plan(root_disk, volume_label, false, None)
|
||||
.await
|
||||
.map(Action::from)
|
||||
.map_err(ActionError::from)?,
|
||||
|
|
Loading…
Reference in a new issue