Skip to content

Commit 814d921

Browse files
committed
various: allow specifying profiles for platform commands
Signed-off-by: NotAShelf <[email protected]> Change-Id: I6a6a6964ededbfb54041c1c3e7c98467d08b5fd3
1 parent 440d3a6 commit 814d921

File tree

5 files changed

+73
-21
lines changed

5 files changed

+73
-21
lines changed

src/commands.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,17 @@ static PASSWORD_CACHE: OnceLock<Mutex<HashMap<String, SecretString>>> =
2222

2323
fn get_cached_password(host: &str) -> Option<SecretString> {
2424
let cache = PASSWORD_CACHE.get_or_init(|| Mutex::new(HashMap::new()));
25-
let guard = cache.lock().unwrap_or_else(|e| e.into_inner());
25+
let guard = cache
26+
.lock()
27+
.unwrap_or_else(std::sync::PoisonError::into_inner);
2628
guard.get(host).cloned()
2729
}
2830

2931
fn cache_password(host: &str, password: SecretString) {
3032
let cache = PASSWORD_CACHE.get_or_init(|| Mutex::new(HashMap::new()));
31-
let mut guard = cache.lock().unwrap_or_else(|e| e.into_inner());
33+
let mut guard = cache
34+
.lock()
35+
.unwrap_or_else(std::sync::PoisonError::into_inner);
3236
guard.insert(host.to_string(), password);
3337
}
3438

@@ -449,7 +453,7 @@ impl Command {
449453
Some(cached_password)
450454
} else {
451455
let password =
452-
inquire::Password::new(&format!("[sudo] password for {}:", host))
456+
inquire::Password::new(&format!("[sudo] password for {host}:"))
453457
.without_confirmation()
454458
.prompt()
455459
.context("Failed to read sudo password")?;
@@ -492,11 +496,11 @@ impl Command {
492496
for (key, action) in &self.env_vars {
493497
match action {
494498
EnvAction::Set(value) => {
495-
elev_cmd = elev_cmd.arg(format!("{}={}", key, value));
499+
elev_cmd = elev_cmd.arg(format!("{key}={value}"));
496500
},
497501
EnvAction::Preserve => {
498502
if let Ok(value) = std::env::var(key) {
499-
elev_cmd = elev_cmd.arg(format!("{}={}", key, value));
503+
elev_cmd = elev_cmd.arg(format!("{key}={value}"));
500504
}
501505
},
502506
_ => {},

src/darwin.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,13 @@ impl DarwinRebuildArgs {
155155
}
156156

157157
if matches!(variant, Switch) {
158+
let profile_path = self.profile.as_ref().map_or_else(
159+
|| std::ffi::OsStr::new(SYSTEM_PROFILE),
160+
|p| p.as_os_str(),
161+
);
158162
Command::new("nix")
159-
.args(["build", "--no-link", "--profile", SYSTEM_PROFILE])
163+
.args(["build", "--no-link", "--profile"])
164+
.arg(profile_path)
160165
.arg(&out_path)
161166
.elevate(Some(elevation.clone()))
162167
.dry(self.common.dry)

src/home.rs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -99,17 +99,27 @@ impl HomeRebuildArgs {
9999
.run()
100100
.wrap_err("Failed to build Home-Manager configuration")?;
101101

102-
let prev_generation: Option<PathBuf> = [
103-
PathBuf::from("/nix/var/nix/profiles/per-user")
104-
.join(env::var("USER").map_err(|_| eyre!("Couldn't get username"))?)
105-
.join("home-manager"),
106-
PathBuf::from(
107-
env::var("HOME").map_err(|_| eyre!("Couldn't get home directory"))?,
108-
)
109-
.join(".local/state/nix/profiles/home-manager"),
110-
]
111-
.into_iter()
112-
.find(|next| next.exists());
102+
let prev_generation: Option<PathBuf> = if let Some(ref profile) =
103+
self.profile
104+
{
105+
if profile.exists() {
106+
Some(profile.clone())
107+
} else {
108+
None
109+
}
110+
} else {
111+
[
112+
PathBuf::from("/nix/var/nix/profiles/per-user")
113+
.join(env::var("USER").map_err(|_| eyre!("Couldn't get username"))?)
114+
.join("home-manager"),
115+
PathBuf::from(
116+
env::var("HOME").map_err(|_| eyre!("Couldn't get home directory"))?,
117+
)
118+
.join(".local/state/nix/profiles/home-manager"),
119+
]
120+
.into_iter()
121+
.find(|next| next.exists())
122+
};
113123

114124
debug!("Previous generation: {prev_generation:?}");
115125

src/interface.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,10 @@ pub struct OsRebuildArgs {
228228
/// Build the configuration to a different host over ssh
229229
#[arg(long)]
230230
pub build_host: Option<String>,
231+
232+
/// Path to Nix' system profile
233+
#[arg(long, short = 'P')]
234+
pub profile: Option<std::path::PathBuf>,
231235
}
232236

233237
impl OsRebuildArgs {
@@ -285,6 +289,10 @@ pub struct OsRollbackArgs {
285289
/// Whether to display a package diff
286290
#[arg(long, short, value_enum, default_value_t = DiffType::Auto)]
287291
pub diff: DiffType,
292+
293+
/// Path to Nix' system profile for rollback
294+
#[arg(long, short = 'P')]
295+
pub profile: Option<std::path::PathBuf>,
288296
}
289297

290298
#[derive(Debug, Args)]
@@ -514,6 +522,10 @@ pub struct HomeRebuildArgs {
514522
/// Move existing files by backing up with this file extension
515523
#[arg(long, short = 'b')]
516524
pub backup_extension: Option<String>,
525+
526+
/// Path to Home-Manager profile
527+
#[arg(long, short = 'P')]
528+
pub profile: Option<std::path::PathBuf>,
517529
}
518530

519531
impl HomeRebuildArgs {
@@ -623,6 +635,10 @@ pub struct DarwinRebuildArgs {
623635
/// Don't panic if calling nh as root
624636
#[arg(short = 'R', long, env = "NH_BYPASS_ROOT_CHECK")]
625637
pub bypass_root_check: bool,
638+
639+
/// Path to Darwin system profile
640+
#[arg(long, short = 'P')]
641+
pub profile: Option<std::path::PathBuf>,
626642
}
627643

628644
impl DarwinRebuildArgs {

src/nixos.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -330,9 +330,14 @@ impl OsRebuildArgs {
330330
.canonicalize()
331331
.context("Failed to resolve output path")?;
332332

333+
let system_profile_path = self.profile.as_ref().map_or_else(
334+
|| std::ffi::OsStr::new(SYSTEM_PROFILE),
335+
|p| p.as_os_str(),
336+
);
333337
Command::new("nix")
334338
.elevate(elevate.then_some(elevation.clone()))
335-
.args(["build", "--no-link", "--profile", SYSTEM_PROFILE])
339+
.args(["build", "--no-link", "--profile"])
340+
.arg(system_profile_path)
336341
.arg(&canonical_out_path)
337342
.ssh(self.target_host.clone())
338343
.with_required_env()
@@ -401,7 +406,11 @@ impl OsRollbackArgs {
401406
info!("Rolling back to generation {}", target_generation.number);
402407

403408
// Construct path to the generation
404-
let profile_dir = Path::new(SYSTEM_PROFILE).parent().unwrap_or_else(|| {
409+
let system_profile_path = self
410+
.profile
411+
.as_deref()
412+
.unwrap_or_else(|| Path::new(SYSTEM_PROFILE));
413+
let profile_dir = system_profile_path.parent().unwrap_or_else(|| {
405414
tracing::warn!(
406415
"SYSTEM_PROFILE has no parent, defaulting to /nix/var/nix/profiles"
407416
);
@@ -469,10 +478,14 @@ impl OsRollbackArgs {
469478
info!("Setting system profile...");
470479

471480
// Instead of direct symlink operations, use a command with proper elevation
481+
let system_profile_path = self
482+
.profile
483+
.as_deref()
484+
.unwrap_or_else(|| Path::new(SYSTEM_PROFILE));
472485
Command::new("ln")
473486
.arg("-sfn") // force, symbolic link
474487
.arg(&generation_link)
475-
.arg(SYSTEM_PROFILE)
488+
.arg(system_profile_path)
476489
.elevate(elevate.then_some(elevation.clone()))
477490
.message("Setting system profile")
478491
.with_required_env()
@@ -534,10 +547,14 @@ impl OsRollbackArgs {
534547
let current_gen_link =
535548
profile_dir.join(format!("system-{current_gen_number}-link"));
536549

550+
let system_profile_path = self
551+
.profile
552+
.as_deref()
553+
.unwrap_or_else(|| Path::new(SYSTEM_PROFILE));
537554
Command::new("ln")
538555
.arg("-sfn") // Force, symbolic link
539556
.arg(&current_gen_link)
540-
.arg(SYSTEM_PROFILE)
557+
.arg(system_profile_path)
541558
.elevate(elevate.then_some(elevation))
542559
.message("Rolling back system profile")
543560
.with_required_env()

0 commit comments

Comments
 (0)