diff --git a/src/action/macos/create_apfs_volume.rs b/src/action/macos/create_apfs_volume.rs index 1a15d86..401ebd8 100644 --- a/src/action/macos/create_apfs_volume.rs +++ b/src/action/macos/create_apfs_volume.rs @@ -1,3 +1,4 @@ +use std::io::Cursor; use std::path::{Path, PathBuf}; use tokio::process::Command; @@ -7,7 +8,7 @@ use crate::action::{ActionError, ActionTag, StatefulAction}; use crate::execute_command; use crate::action::{Action, ActionDescription}; -use crate::os::darwin::DiskUtilApfsListOutput; +use crate::os::darwin::{DiskUtilApfsListOutput, DiskUtilInfoOutput}; #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] pub struct CreateApfsVolume { @@ -122,6 +123,38 @@ impl Action for CreateApfsVolume { #[tracing::instrument(level = "debug", skip_all)] async fn revert(&mut self) -> Result<(), ActionError> { + let currently_mounted = { + let buf = execute_command( + Command::new("/usr/sbin/diskutil") + .process_group(0) + .args(["info", "-plist"]) + .arg(&self.name) + .stdin(std::process::Stdio::null()), + ) + .await + .map_err(Self::error)? + .stdout; + let the_plist: DiskUtilInfoOutput = + plist::from_reader(Cursor::new(buf)).map_err(Self::error)?; + + the_plist.mount_point.is_some() + }; + + // Unmounts the volume before attempting to remove it, avoiding 'in use' errors + // https://github.com/DeterminateSystems/nix-installer/issues/647 + if !currently_mounted { + execute_command( + Command::new("/usr/sbin/diskutil") + .process_group(0) + .args(["unmount", "force", &self.name]) + .stdin(std::process::Stdio::null()), + ) + .await + .map_err(Self::error)?; + } else { + tracing::debug!("Volume was already unmounted, can skip unmounting") + } + execute_command( Command::new("/usr/sbin/diskutil") .process_group(0)