Allow passing options to nix.
This commit is contained in:
parent
cecf202ff4
commit
b0430700b5
3 changed files with 76 additions and 28 deletions
|
|
@ -5,7 +5,9 @@ use std::fs::DirBuilder;
|
|||
use std::path::Path;
|
||||
use std::{fs, process, str};
|
||||
|
||||
use super::{create_store_link, StorePath, FLAKE_ATTR, GCROOT_PATH, PROFILE_DIR, PROFILE_NAME};
|
||||
use super::{
|
||||
create_store_link, NixOptions, StorePath, FLAKE_ATTR, GCROOT_PATH, PROFILE_DIR, PROFILE_NAME,
|
||||
};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
|
|
@ -58,17 +60,18 @@ fn create_gcroot(gcroot_path: &str, profile_path: &Path) -> Result<()> {
|
|||
create_store_link(&store_path, Path::new(gcroot_path))
|
||||
}
|
||||
|
||||
pub fn build(flake_uri: &str) -> Result<StorePath> {
|
||||
let full_flake_uri = find_flake_attr(flake_uri)?;
|
||||
pub fn build(flake_uri: &str, nix_options: &NixOptions) -> Result<StorePath> {
|
||||
let full_flake_uri = find_flake_attr(flake_uri, nix_options)?;
|
||||
|
||||
log::info!("Building new system-manager generation...");
|
||||
log::info!("Running nix build...");
|
||||
let store_path = run_nix_build(full_flake_uri.as_ref()).and_then(get_store_path)?;
|
||||
let store_path =
|
||||
run_nix_build(full_flake_uri.as_ref(), nix_options).and_then(get_store_path)?;
|
||||
log::info!("Built system-manager profile {store_path}");
|
||||
Ok(store_path)
|
||||
}
|
||||
|
||||
fn find_flake_attr(flake_uri: &str) -> Result<String> {
|
||||
fn find_flake_attr(flake_uri: &str, nix_options: &NixOptions) -> Result<String> {
|
||||
fn full_uri(flake: &str, attr: &str) -> String {
|
||||
format!("{flake}#{FLAKE_ATTR}.{attr}")
|
||||
}
|
||||
|
|
@ -85,7 +88,7 @@ fn find_flake_attr(flake_uri: &str) -> Result<String> {
|
|||
}
|
||||
|
||||
if let Some(attr) = attr {
|
||||
if try_flake_attr(flake, attr)? {
|
||||
if try_flake_attr(flake, attr, nix_options)? {
|
||||
return Ok(full_uri(flake, attr));
|
||||
} else {
|
||||
anyhow::bail!(
|
||||
|
|
@ -99,18 +102,18 @@ fn find_flake_attr(flake_uri: &str) -> Result<String> {
|
|||
let hostname = hostname_os.to_string_lossy();
|
||||
let default = "default";
|
||||
|
||||
if try_flake_attr(flake, &hostname)? {
|
||||
if try_flake_attr(flake, &hostname, nix_options)? {
|
||||
return Ok(full_uri(flake, &hostname));
|
||||
} else if try_flake_attr(flake, default)? {
|
||||
} else if try_flake_attr(flake, default, nix_options)? {
|
||||
return Ok(full_uri(flake, default));
|
||||
};
|
||||
anyhow::bail!("No suitable flake attribute found, giving up.");
|
||||
}
|
||||
|
||||
fn try_flake_attr(flake: &str, attr: &str) -> Result<bool> {
|
||||
fn try_flake_attr(flake: &str, attr: &str, nix_options: &NixOptions) -> Result<bool> {
|
||||
let full_uri = format!("{flake}#{FLAKE_ATTR}.{attr}");
|
||||
log::info!("Trying flake URI: {full_uri}...");
|
||||
let status = try_nix_eval(flake, attr)?;
|
||||
let status = try_nix_eval(flake, attr, nix_options)?;
|
||||
if status {
|
||||
log::info!("Success, using {full_uri}");
|
||||
} else {
|
||||
|
|
@ -143,8 +146,8 @@ fn parse_nix_build_output(output: String) -> Result<StorePath> {
|
|||
anyhow::bail!("Multiple build results were returned, we cannot handle that yet.")
|
||||
}
|
||||
|
||||
fn run_nix_build(flake_uri: &str) -> Result<process::Output> {
|
||||
let output = nix_cmd()
|
||||
fn run_nix_build(flake_uri: &str, nix_options: &NixOptions) -> Result<process::Output> {
|
||||
let output = nix_cmd(nix_options)
|
||||
.arg("build")
|
||||
.arg(flake_uri)
|
||||
.arg("--json")
|
||||
|
|
@ -156,8 +159,8 @@ fn run_nix_build(flake_uri: &str) -> Result<process::Output> {
|
|||
Ok(output)
|
||||
}
|
||||
|
||||
fn try_nix_eval(flake: &str, attr: &str) -> Result<bool> {
|
||||
let output = nix_cmd()
|
||||
fn try_nix_eval(flake: &str, attr: &str, nix_options: &NixOptions) -> Result<bool> {
|
||||
let output = nix_cmd(nix_options)
|
||||
.arg("eval")
|
||||
.arg(format!("{flake}#{FLAKE_ATTR}"))
|
||||
.arg("--json")
|
||||
|
|
@ -175,9 +178,12 @@ fn try_nix_eval(flake: &str, attr: &str) -> Result<bool> {
|
|||
}
|
||||
}
|
||||
|
||||
fn nix_cmd() -> process::Command {
|
||||
fn nix_cmd(nix_options: &NixOptions) -> process::Command {
|
||||
let mut cmd = process::Command::new("nix");
|
||||
cmd.arg("--extra-experimental-features")
|
||||
.arg("nix-command flakes");
|
||||
nix_options.options.iter().for_each(|option| {
|
||||
cmd.arg("--option").arg(&option.0).arg(&option.1);
|
||||
});
|
||||
cmd
|
||||
}
|
||||
|
|
|
|||
10
src/lib.rs
10
src/lib.rs
|
|
@ -99,6 +99,16 @@ impl<'a> From<&'a StorePath> for Cow<'a, StorePath> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct NixOptions {
|
||||
options: Vec<(String, String)>,
|
||||
}
|
||||
|
||||
impl NixOptions {
|
||||
pub fn new(options: Vec<(String, String)>) -> Self {
|
||||
Self { options }
|
||||
}
|
||||
}
|
||||
|
||||
fn create_store_link(store_path: &StorePath, from: &Path) -> Result<()> {
|
||||
create_link(Path::new(&store_path.store_path), from)
|
||||
}
|
||||
|
|
|
|||
58
src/main.rs
58
src/main.rs
|
|
@ -4,7 +4,7 @@ use std::ffi::OsString;
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::process::{self, ExitCode};
|
||||
|
||||
use system_manager::StorePath;
|
||||
use system_manager::{NixOptions, StorePath};
|
||||
|
||||
#[derive(clap::Parser, Debug)]
|
||||
#[command(
|
||||
|
|
@ -25,6 +25,9 @@ struct Args {
|
|||
/// Invoke the remote command with sudo.
|
||||
/// Only useful in combination with --target-host
|
||||
use_remote_sudo: bool,
|
||||
|
||||
#[clap(long = "nix-option", num_args = 2)]
|
||||
nix_options: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
#[derive(clap::Args, Debug)]
|
||||
|
|
@ -122,7 +125,7 @@ enum Action {
|
|||
|
||||
// TODO: create a general lock while we are running to avoid running system-manager concurrently
|
||||
fn main() -> ExitCode {
|
||||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
|
||||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("debug")).init();
|
||||
handle_toplevel_error(go(Args::parse()))
|
||||
}
|
||||
|
||||
|
|
@ -131,8 +134,26 @@ fn go(args: Args) -> Result<()> {
|
|||
action,
|
||||
target_host,
|
||||
use_remote_sudo,
|
||||
nix_options,
|
||||
} = args;
|
||||
|
||||
let nix_options = NixOptions::new(nix_options.map_or(Vec::new(), |vals| {
|
||||
vals.chunks(2)
|
||||
.map(|slice| {
|
||||
(
|
||||
slice
|
||||
.get(0)
|
||||
.expect("Error parsing nix-option values")
|
||||
.to_owned(),
|
||||
slice
|
||||
.get(1)
|
||||
.expect("Error parsing nix-option values")
|
||||
.to_owned(),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}));
|
||||
|
||||
match action {
|
||||
Action::Activate {
|
||||
store_path,
|
||||
|
|
@ -149,24 +170,29 @@ fn go(args: Args) -> Result<()> {
|
|||
ephemeral,
|
||||
&target_host,
|
||||
use_remote_sudo,
|
||||
&nix_options,
|
||||
)
|
||||
.and_then(print_store_path),
|
||||
Action::Build {
|
||||
build_args: BuildArgs { flake_uri },
|
||||
} => build(&flake_uri, &target_host).and_then(print_store_path),
|
||||
} => build(&flake_uri, &target_host, &nix_options).and_then(print_store_path),
|
||||
Action::Deactivate {
|
||||
optional_store_path_args: OptionalStorePathArg { maybe_store_path },
|
||||
} => deactivate(maybe_store_path, &target_host, use_remote_sudo),
|
||||
Action::Generate {
|
||||
store_or_flake_args,
|
||||
} => {
|
||||
generate(store_or_flake_args, &target_host, use_remote_sudo).and_then(print_store_path)
|
||||
}
|
||||
} => generate(
|
||||
store_or_flake_args,
|
||||
&target_host,
|
||||
use_remote_sudo,
|
||||
&nix_options,
|
||||
)
|
||||
.and_then(print_store_path),
|
||||
Action::Switch {
|
||||
build_args: BuildArgs { flake_uri },
|
||||
activation_args: ActivationArgs { ephemeral },
|
||||
} => {
|
||||
let store_path = do_build(&flake_uri)?;
|
||||
let store_path = do_build(&flake_uri, &nix_options)?;
|
||||
copy_closure(&store_path, &target_host)?;
|
||||
do_generate(&store_path, &target_host, use_remote_sudo)?;
|
||||
activate(&store_path, ephemeral, &target_host, use_remote_sudo)
|
||||
|
|
@ -180,20 +206,25 @@ fn print_store_path<SP: AsRef<StorePath>>(store_path: SP) -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn build(flake_uri: &str, target_host: &Option<String>) -> Result<StorePath> {
|
||||
let store_path = do_build(flake_uri)?;
|
||||
fn build(
|
||||
flake_uri: &str,
|
||||
target_host: &Option<String>,
|
||||
nix_options: &NixOptions,
|
||||
) -> Result<StorePath> {
|
||||
let store_path = do_build(flake_uri, nix_options)?;
|
||||
copy_closure(&store_path, target_host)?;
|
||||
Ok(store_path)
|
||||
}
|
||||
|
||||
fn do_build(flake_uri: &str) -> Result<StorePath> {
|
||||
system_manager::generate::build(flake_uri)
|
||||
fn do_build(flake_uri: &str, nix_options: &NixOptions) -> Result<StorePath> {
|
||||
system_manager::generate::build(flake_uri, nix_options)
|
||||
}
|
||||
|
||||
fn generate(
|
||||
args: StoreOrFlakeArgs,
|
||||
target_host: &Option<String>,
|
||||
use_remote_sudo: bool,
|
||||
nix_options: &NixOptions,
|
||||
) -> Result<StorePath> {
|
||||
match args {
|
||||
StoreOrFlakeArgs {
|
||||
|
|
@ -206,7 +237,7 @@ fn generate(
|
|||
maybe_flake_uri: Some(flake_uri),
|
||||
},
|
||||
} => {
|
||||
let store_path = do_build(&flake_uri)?;
|
||||
let store_path = do_build(&flake_uri, nix_options)?;
|
||||
copy_closure(&store_path, target_host)?;
|
||||
do_generate(&store_path, target_host, use_remote_sudo)?;
|
||||
Ok(store_path)
|
||||
|
|
@ -284,6 +315,7 @@ fn prepopulate(
|
|||
ephemeral: bool,
|
||||
target_host: &Option<String>,
|
||||
use_remote_sudo: bool,
|
||||
nix_options: &NixOptions,
|
||||
) -> Result<StorePath> {
|
||||
match args {
|
||||
StoreOrFlakeArgs {
|
||||
|
|
@ -296,7 +328,7 @@ fn prepopulate(
|
|||
maybe_flake_uri: Some(flake_uri),
|
||||
},
|
||||
} => {
|
||||
let store_path = do_build(&flake_uri)?;
|
||||
let store_path = do_build(&flake_uri, nix_options)?;
|
||||
copy_closure(&store_path, target_host)?;
|
||||
do_generate(&store_path, target_host, use_remote_sudo)?;
|
||||
do_prepopulate(&store_path, ephemeral, target_host, use_remote_sudo)?;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue