Add plist use to the CreateFstabEntry action (#221)
This commit is contained in:
parent
fd149eef47
commit
8042ac5131
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -1868,6 +1868,9 @@ name = "uuid"
|
||||||
version = "1.2.2"
|
version = "1.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c"
|
checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "valuable"
|
name = "valuable"
|
||||||
|
|
|
@ -52,7 +52,7 @@ dyn-clone = { version = "1.0.9", default-features = false }
|
||||||
rand = { version = "0.8.5", default-features = false, features = [ "std", "std_rng" ] }
|
rand = { version = "0.8.5", default-features = false, features = [ "std", "std_rng" ] }
|
||||||
semver = { version = "1.0.14", default-features = false, features = ["serde", "std"] }
|
semver = { version = "1.0.14", default-features = false, features = ["serde", "std"] }
|
||||||
term = { version = "0.7.0", default-features = false }
|
term = { version = "0.7.0", default-features = false }
|
||||||
uuid = "1.2.2"
|
uuid = { version = "1.2.2", features = ["serde"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
eyre = { version = "0.6.8", default-features = false, features = [ "track-caller" ] }
|
eyre = { version = "0.6.8", default-features = false, features = [ "track-caller" ] }
|
||||||
|
|
|
@ -6,9 +6,9 @@ use crate::{
|
||||||
execute_command,
|
execute_command,
|
||||||
};
|
};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
use serde::Deserialize;
|
||||||
use std::{
|
use std::{
|
||||||
io::SeekFrom,
|
io::SeekFrom,
|
||||||
os::unix::prelude::PermissionsExt,
|
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
};
|
};
|
||||||
|
@ -82,13 +82,7 @@ impl Action for CreateFstabEntry {
|
||||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||||
let Self { apfs_volume_label } = self;
|
let Self { apfs_volume_label } = self;
|
||||||
let fstab_path = Path::new(FSTAB_PATH);
|
let fstab_path = Path::new(FSTAB_PATH);
|
||||||
let uuid = get_uuid_for_label(&apfs_volume_label)
|
let uuid = get_uuid_for_label(&apfs_volume_label).await?;
|
||||||
.await?
|
|
||||||
.ok_or_else(|| {
|
|
||||||
ActionError::Custom(Box::new(CreateFstabEntryError::NoVolume(
|
|
||||||
apfs_volume_label.clone(),
|
|
||||||
)))
|
|
||||||
})?;
|
|
||||||
let fstab_entry = fstab_entry(&uuid, apfs_volume_label);
|
let fstab_entry = fstab_entry(&uuid, apfs_volume_label);
|
||||||
|
|
||||||
let mut fstab = tokio::fs::OpenOptions::new()
|
let mut fstab = tokio::fs::OpenOptions::new()
|
||||||
|
@ -133,13 +127,7 @@ impl Action for CreateFstabEntry {
|
||||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||||
let Self { apfs_volume_label } = self;
|
let Self { apfs_volume_label } = self;
|
||||||
let fstab_path = Path::new(FSTAB_PATH);
|
let fstab_path = Path::new(FSTAB_PATH);
|
||||||
let uuid = get_uuid_for_label(&apfs_volume_label)
|
let uuid = get_uuid_for_label(&apfs_volume_label).await?;
|
||||||
.await?
|
|
||||||
.ok_or_else(|| {
|
|
||||||
ActionError::Custom(Box::new(CreateFstabEntryError::NoVolume(
|
|
||||||
apfs_volume_label.clone(),
|
|
||||||
)))
|
|
||||||
})?;
|
|
||||||
let fstab_entry = fstab_entry(&uuid, apfs_volume_label);
|
let fstab_entry = fstab_entry(&uuid, apfs_volume_label);
|
||||||
|
|
||||||
let mut file = OpenOptions::new()
|
let mut file = OpenOptions::new()
|
||||||
|
@ -177,11 +165,12 @@ impl Action for CreateFstabEntry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_uuid_for_label(apfs_volume_label: &str) -> Result<Option<Uuid>, ActionError> {
|
async fn get_uuid_for_label(apfs_volume_label: &str) -> Result<Uuid, ActionError> {
|
||||||
let output = execute_command(
|
let output = execute_command(
|
||||||
Command::new("/usr/sbin/diskutil")
|
Command::new("/usr/sbin/diskutil")
|
||||||
.process_group(0)
|
.process_group(0)
|
||||||
.arg("info")
|
.arg("info")
|
||||||
|
.arg("-plist")
|
||||||
.arg(apfs_volume_label)
|
.arg(apfs_volume_label)
|
||||||
.stdin(std::process::Stdio::null())
|
.stdin(std::process::Stdio::null())
|
||||||
.stdout(std::process::Stdio::piped()),
|
.stdout(std::process::Stdio::piped()),
|
||||||
|
@ -189,27 +178,9 @@ async fn get_uuid_for_label(apfs_volume_label: &str) -> Result<Option<Uuid>, Act
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ActionError::Command(e))?;
|
.map_err(|e| ActionError::Command(e))?;
|
||||||
|
|
||||||
let stdout = String::from_utf8(output.stdout)?;
|
let parsed: DiskUtilApfsInfoOutput = plist::from_bytes(&output.stdout)?;
|
||||||
|
|
||||||
let mut found = None;
|
Ok(parsed.volume_uuid)
|
||||||
for line in stdout.lines() {
|
|
||||||
let prefix = "Volume UUID:";
|
|
||||||
let trimmed = line.trim();
|
|
||||||
if let Some(index) = trimmed.find(prefix) {
|
|
||||||
let maybe_uuid = trimmed[(index + prefix.len())..].trim();
|
|
||||||
let uuid = Uuid::parse_str(maybe_uuid).map_err(|err| {
|
|
||||||
ActionError::Custom(Box::new(CreateFstabEntryError::Uuid(
|
|
||||||
maybe_uuid.to_string(),
|
|
||||||
err,
|
|
||||||
)))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
found = Some(uuid);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(found)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fstab_prelude_comment(apfs_volume_label: &str) -> String {
|
fn fstab_prelude_comment(apfs_volume_label: &str) -> String {
|
||||||
|
@ -228,10 +199,13 @@ fn fstab_entry(uuid: &Uuid, apfs_volume_label: &str) -> String {
|
||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
pub enum CreateFstabEntryError {
|
pub enum CreateFstabEntryError {
|
||||||
#[error("UUID error: {0}")]
|
|
||||||
Uuid(String, #[source] uuid::Error),
|
|
||||||
#[error("No volume labelled `{0}` present, cannot get UUID to add to /etc/fstab")]
|
|
||||||
NoVolume(String),
|
|
||||||
#[error("An `/etc/fstab` entry for the volume labelled `{0}` already exists. If a Nix Store already exists it may need to be deleted with `diskutil apfs deleteVolume \"{0}\") and should be removed from `/etc/fstab`")]
|
#[error("An `/etc/fstab` entry for the volume labelled `{0}` already exists. If a Nix Store already exists it may need to be deleted with `diskutil apfs deleteVolume \"{0}\") and should be removed from `/etc/fstab`")]
|
||||||
EntryExists(String),
|
EntryExists(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Clone, Debug)]
|
||||||
|
#[serde(rename_all = "PascalCase")]
|
||||||
|
struct DiskUtilApfsInfoOutput {
|
||||||
|
#[serde(rename = "VolumeUUID")]
|
||||||
|
volume_uuid: Uuid,
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue