forked from lix-project/lix-installer
Compare commits
2 commits
main
...
hoverbear/
Author | SHA1 | Date | |
---|---|---|---|
a8f56d609f | |||
160347e788 |
97
src/action/macos/mac_remote_builder_fix.rs
Normal file
97
src/action/macos/mac_remote_builder_fix.rs
Normal file
|
@ -0,0 +1,97 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use tracing::{span, Span};
|
||||
|
||||
use crate::action::{
|
||||
Action, ActionDescription, ActionError, ActionErrorKind, ActionTag, StatefulAction,
|
||||
};
|
||||
|
||||
const NIX_STORE_SYMLINK_LOCATION: &str = "/usr/local/bin/nix-store";
|
||||
const NIX_STORE_SYMLINK_TARGET: &str = "/nix/var/nix/profiles/default/bin/nix-store";
|
||||
|
||||
/**
|
||||
Perform a remote builder fix for Mac which links `nix-store` into `/usr/local/bin`
|
||||
*/
|
||||
// Previously, the installer suggested users use a workaround: https://github.com/DeterminateSystems/nix-installer/blob/4bfd6c2547dab100cde1dbc60e3d623499ead2c4/README.md?plain=1#L377-L418
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct MacRemoteBuilderFix;
|
||||
|
||||
impl MacRemoteBuilderFix {
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
pub async fn plan() -> Result<StatefulAction<Self>, ActionError> {
|
||||
let nix_path = Path::new(NIX_STORE_SYMLINK_LOCATION);
|
||||
if nix_path.exists() {
|
||||
if !nix_path.is_symlink() {
|
||||
return Err(Self::error(ActionErrorKind::PathWasNotSymlink(
|
||||
nix_path.into(),
|
||||
)));
|
||||
}
|
||||
let link_destination = std::fs::read_link(nix_path)
|
||||
.map_err(|e| ActionErrorKind::ReadSymlink(nix_path.into(), e))
|
||||
.map_err(Self::error)?;
|
||||
if link_destination == Path::new("/nix/var/nix/profiles/default/bin/nix-store") {
|
||||
return Ok(StatefulAction::completed(Self));
|
||||
} else {
|
||||
return Err(Self::error(ActionErrorKind::SymlinkExists(nix_path.into())));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(StatefulAction::uncompleted(Self))
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
#[typetag::serde(name = "mac_remote_builder_fix")]
|
||||
impl Action for MacRemoteBuilderFix {
|
||||
fn action_tag() -> ActionTag {
|
||||
ActionTag("mac_remote_builder_fix")
|
||||
}
|
||||
fn tracing_synopsis(&self) -> String {
|
||||
format!(
|
||||
"Create symlink at `{NIX_STORE_SYMLINK_LOCATION}` to `{NIX_STORE_SYMLINK_TARGET}`",
|
||||
)
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(tracing::Level::DEBUG, "mac_remote_builder_fix",)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(self.tracing_synopsis(), vec![
|
||||
"In order to support acting as a remote builder (Mac populates the `PATH` environment differently than other environments)".to_string()
|
||||
])]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
tokio::fs::symlink(NIX_STORE_SYMLINK_TARGET, NIX_STORE_SYMLINK_LOCATION)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
ActionErrorKind::Symlink(
|
||||
PathBuf::from(NIX_STORE_SYMLINK_LOCATION),
|
||||
PathBuf::from(NIX_STORE_SYMLINK_TARGET),
|
||||
e,
|
||||
)
|
||||
})
|
||||
.map_err(Self::error)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn revert_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(
|
||||
format!("Remove symlink at `{NIX_STORE_SYMLINK_LOCATION}`",),
|
||||
vec![],
|
||||
)]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
tokio::fs::remove_file(NIX_STORE_SYMLINK_LOCATION)
|
||||
.await
|
||||
.map_err(|e| ActionErrorKind::Remove(PathBuf::from(NIX_STORE_SYMLINK_LOCATION), e))
|
||||
.map_err(Self::error)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ pub(crate) mod create_volume_service;
|
|||
pub(crate) mod enable_ownership;
|
||||
pub(crate) mod encrypt_apfs_volume;
|
||||
pub(crate) mod kickstart_launchctl_service;
|
||||
pub(crate) mod mac_remote_builder_fix;
|
||||
pub(crate) mod set_tmutil_exclusion;
|
||||
pub(crate) mod set_tmutil_exclusions;
|
||||
pub(crate) mod unmount_apfs_volume;
|
||||
|
@ -22,6 +23,7 @@ pub use create_volume_service::CreateVolumeService;
|
|||
pub use enable_ownership::{EnableOwnership, EnableOwnershipError};
|
||||
pub use encrypt_apfs_volume::EncryptApfsVolume;
|
||||
pub use kickstart_launchctl_service::KickstartLaunchctlService;
|
||||
pub use mac_remote_builder_fix::MacRemoteBuilderFix;
|
||||
use serde::Deserialize;
|
||||
pub use set_tmutil_exclusion::SetTmutilExclusion;
|
||||
pub use set_tmutil_exclusions::SetTmutilExclusions;
|
||||
|
|
|
@ -409,6 +409,8 @@ pub enum ActionErrorKind {
|
|||
PathModeMismatch(std::path::PathBuf, u32, u32),
|
||||
#[error("Path `{0}` exists, but is not a file, consider removing it with `rm {0}`")]
|
||||
PathWasNotFile(std::path::PathBuf),
|
||||
#[error("Path `{0}` exists, but is not a symlink, consider removing it with `rm {0}`")]
|
||||
PathWasNotSymlink(std::path::PathBuf),
|
||||
#[error("Path `{0}` exists, but is not a directory, consider removing it with `rm {0}`")]
|
||||
PathWasNotDirectory(std::path::PathBuf),
|
||||
#[error("Getting metadata for {0}`")]
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::{
|
|||
action::{
|
||||
base::RemoveDirectory,
|
||||
common::{ConfigureInitService, ConfigureNix, CreateUsersAndGroups, ProvisionNix},
|
||||
macos::{CreateNixVolume, SetTmutilExclusions},
|
||||
macos::{CreateNixVolume, SetTmutilExclusions,MacRemoteBuilderFix},
|
||||
StatefulAction,
|
||||
},
|
||||
execute_command,
|
||||
|
@ -161,6 +161,10 @@ impl Planner for Macos {
|
|||
.await
|
||||
.map_err(PlannerError::Action)?
|
||||
.boxed(),
|
||||
MacRemoteBuilderFix::plan()
|
||||
.await
|
||||
.map_err(PlannerError::Action)?
|
||||
.boxed(),
|
||||
RemoveDirectory::plan(crate::settings::SCRATCH_DIR)
|
||||
.await
|
||||
.map_err(PlannerError::Action)?
|
||||
|
|
Loading…
Reference in a new issue