Skip to content

Commit

Permalink
Don't use sudo nix build for Home Manager
Browse files Browse the repository at this point in the history
  • Loading branch information
lucperkins committed Jul 29, 2024
1 parent 970a5a1 commit a1f7346
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 13 deletions.
3 changes: 3 additions & 0 deletions src/cli/cmd/apply/home_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ pub(super) struct HomeManager {
/// References must take one of two forms: {org}/{flake}/{version_req}#{attr_path} or {org}/{flake}/{version_req}.
/// If the latter, the attribute path defaults to homeConfigurations.{whoami}.
pub(super) output_ref: String,

#[arg(long, short, env = "FH_APPLY_PROFILE", default_value = "system")]
pub(super) profile: String,
}

impl HomeManager {
Expand Down
46 changes: 36 additions & 10 deletions src/cli/cmd/apply/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::{

use self::{
home_manager::{HomeManager, HOME_MANAGER_SCRIPT},
nix_darwin::{NixDarwin, DARWIN_REBUILD_ACTION, NIX_DARWIN_PROFILE, NIX_DARWIN_SCRIPT},
nix_darwin::{NixDarwin, DARWIN_REBUILD_ACTION, NIX_DARWIN_SCRIPT},
nixos::{NixOs, NIXOS_PROFILE, NIXOS_SCRIPT},
};

Expand Down Expand Up @@ -72,15 +72,26 @@ impl CommandExecute for ApplySubcommand {
);

match self.system {
System::HomeManager(_) => {
System::HomeManager(HomeManager { profile, .. }) => {
let profile_path = apply_path_to_profile(
&profile,
&resolved_path.store_path,
false, // don't sudo when running `nix build`
)
.await?;

// /nix/store/{path}/activate
let script_path = path!(&resolved_path.store_path, HOME_MANAGER_SCRIPT);
let script_path = path!(&profile_path, HOME_MANAGER_SCRIPT);

run_script(script_path, None, HOME_MANAGER_SCRIPT).await?;
}
System::NixDarwin(_) => {
let profile_path =
apply_path_to_profile(NIX_DARWIN_PROFILE, &resolved_path.store_path).await?;
System::NixDarwin(NixDarwin { profile, .. }) => {
let profile_path = apply_path_to_profile(
&profile,
&resolved_path.store_path,
true, // sudo if necessary when running `nix build`
)
.await?;

// {path}/sw/bin/darwin-rebuild
let script_path = path!(&profile_path, "sw", "bin", NIX_DARWIN_SCRIPT);
Expand All @@ -93,8 +104,12 @@ impl CommandExecute for ApplySubcommand {
.await?;
}
System::NixOs(NixOs { action, .. }) => {
let profile_path =
apply_path_to_profile(NIXOS_PROFILE, &resolved_path.store_path).await?;
let profile_path = apply_path_to_profile(
NIXOS_PROFILE,
&resolved_path.store_path,
true, // sudo if necessary when running `nix build`
)
.await?;

let script_path = path!(&profile_path, "bin", NIXOS_SCRIPT);

Expand Down Expand Up @@ -155,7 +170,18 @@ async fn run_script(
Ok(())
}

async fn apply_path_to_profile(profile: &str, store_path: &str) -> Result<String, FhError> {
async fn apply_path_to_profile(
profile: &str,
store_path: &str,
sudo_if_necessary: bool,
) -> Result<String, FhError> {
// Ensure that we support both formats:
// 1. some-profile
// 2. /nix/var/nix/profiles/some-profile
let profile = profile
.strip_prefix("h/nix/var/nix/profiles/")
.unwrap_or(profile);

let profile_path = format!("/nix/var/nix/profiles/{profile}");

tracing::info!(
Expand All @@ -176,7 +202,7 @@ async fn apply_path_to_profile(profile: &str, store_path: &str) -> Result<String
&profile_path,
store_path,
],
true,
sudo_if_necessary,
)
.await
.wrap_err("failed to build resolved store path with Nix")?;
Expand Down
4 changes: 3 additions & 1 deletion src/cli/cmd/apply/nix_darwin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use crate::cli::{cmd::parse_release_ref, error::FhError};

pub(super) const DARWIN_REBUILD_ACTION: &str = "activate";
pub(super) const NIX_DARWIN_SCRIPT: &str = "darwin-rebuild";
pub(super) const NIX_DARWIN_PROFILE: &str = "system";

#[derive(Parser)]
pub(super) struct NixDarwin {
Expand All @@ -13,6 +12,9 @@ pub(super) struct NixDarwin {
/// If the latter, the attribute path defaults to darwinConfigurations.{devicename}.system, where devicename
/// is the output of scutil --get LocalHostName.
pub(super) output_ref: String,

#[arg(long, short, env = "FH_APPLY_PROFILE", default_value = "system")]
pub(super) profile: String,
}

impl NixDarwin {
Expand Down
7 changes: 5 additions & 2 deletions src/cli/cmd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,11 +395,14 @@ macro_rules! path {
}};
}

fn is_root_user() -> bool {
nix::unistd::getuid().is_root()
}

async fn nix_command(args: &[&str], sudo_if_necessary: bool) -> Result<(), FhError> {
command_exists("nix")?;

let is_root_user = nix::unistd::getuid().is_root();
let use_sudo = sudo_if_necessary && !is_root_user;
let use_sudo = sudo_if_necessary && !is_root_user();

let mut cmd = if use_sudo {
tracing::warn!(
Expand Down

0 comments on commit a1f7346

Please sign in to comment.