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::path::Path;
|
||||||
use std::{fs, process, str};
|
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)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[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))
|
create_store_link(&store_path, Path::new(gcroot_path))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(flake_uri: &str) -> Result<StorePath> {
|
pub fn build(flake_uri: &str, nix_options: &NixOptions) -> Result<StorePath> {
|
||||||
let full_flake_uri = find_flake_attr(flake_uri)?;
|
let full_flake_uri = find_flake_attr(flake_uri, nix_options)?;
|
||||||
|
|
||||||
log::info!("Building new system-manager generation...");
|
log::info!("Building new system-manager generation...");
|
||||||
log::info!("Running nix build...");
|
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}");
|
log::info!("Built system-manager profile {store_path}");
|
||||||
Ok(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 {
|
fn full_uri(flake: &str, attr: &str) -> String {
|
||||||
format!("{flake}#{FLAKE_ATTR}.{attr}")
|
format!("{flake}#{FLAKE_ATTR}.{attr}")
|
||||||
}
|
}
|
||||||
|
|
@ -85,7 +88,7 @@ fn find_flake_attr(flake_uri: &str) -> Result<String> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(attr) = attr {
|
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));
|
return Ok(full_uri(flake, attr));
|
||||||
} else {
|
} else {
|
||||||
anyhow::bail!(
|
anyhow::bail!(
|
||||||
|
|
@ -99,18 +102,18 @@ fn find_flake_attr(flake_uri: &str) -> Result<String> {
|
||||||
let hostname = hostname_os.to_string_lossy();
|
let hostname = hostname_os.to_string_lossy();
|
||||||
let default = "default";
|
let default = "default";
|
||||||
|
|
||||||
if try_flake_attr(flake, &hostname)? {
|
if try_flake_attr(flake, &hostname, nix_options)? {
|
||||||
return Ok(full_uri(flake, &hostname));
|
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));
|
return Ok(full_uri(flake, default));
|
||||||
};
|
};
|
||||||
anyhow::bail!("No suitable flake attribute found, giving up.");
|
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}");
|
let full_uri = format!("{flake}#{FLAKE_ATTR}.{attr}");
|
||||||
log::info!("Trying flake URI: {full_uri}...");
|
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 {
|
if status {
|
||||||
log::info!("Success, using {full_uri}");
|
log::info!("Success, using {full_uri}");
|
||||||
} else {
|
} 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.")
|
anyhow::bail!("Multiple build results were returned, we cannot handle that yet.")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_nix_build(flake_uri: &str) -> Result<process::Output> {
|
fn run_nix_build(flake_uri: &str, nix_options: &NixOptions) -> Result<process::Output> {
|
||||||
let output = nix_cmd()
|
let output = nix_cmd(nix_options)
|
||||||
.arg("build")
|
.arg("build")
|
||||||
.arg(flake_uri)
|
.arg(flake_uri)
|
||||||
.arg("--json")
|
.arg("--json")
|
||||||
|
|
@ -156,8 +159,8 @@ fn run_nix_build(flake_uri: &str) -> Result<process::Output> {
|
||||||
Ok(output)
|
Ok(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_nix_eval(flake: &str, attr: &str) -> Result<bool> {
|
fn try_nix_eval(flake: &str, attr: &str, nix_options: &NixOptions) -> Result<bool> {
|
||||||
let output = nix_cmd()
|
let output = nix_cmd(nix_options)
|
||||||
.arg("eval")
|
.arg("eval")
|
||||||
.arg(format!("{flake}#{FLAKE_ATTR}"))
|
.arg(format!("{flake}#{FLAKE_ATTR}"))
|
||||||
.arg("--json")
|
.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");
|
let mut cmd = process::Command::new("nix");
|
||||||
cmd.arg("--extra-experimental-features")
|
cmd.arg("--extra-experimental-features")
|
||||||
.arg("nix-command flakes");
|
.arg("nix-command flakes");
|
||||||
|
nix_options.options.iter().for_each(|option| {
|
||||||
|
cmd.arg("--option").arg(&option.0).arg(&option.1);
|
||||||
|
});
|
||||||
cmd
|
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<()> {
|
fn create_store_link(store_path: &StorePath, from: &Path) -> Result<()> {
|
||||||
create_link(Path::new(&store_path.store_path), from)
|
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::path::{Path, PathBuf};
|
||||||
use std::process::{self, ExitCode};
|
use std::process::{self, ExitCode};
|
||||||
|
|
||||||
use system_manager::StorePath;
|
use system_manager::{NixOptions, StorePath};
|
||||||
|
|
||||||
#[derive(clap::Parser, Debug)]
|
#[derive(clap::Parser, Debug)]
|
||||||
#[command(
|
#[command(
|
||||||
|
|
@ -25,6 +25,9 @@ struct Args {
|
||||||
/// Invoke the remote command with sudo.
|
/// Invoke the remote command with sudo.
|
||||||
/// Only useful in combination with --target-host
|
/// Only useful in combination with --target-host
|
||||||
use_remote_sudo: bool,
|
use_remote_sudo: bool,
|
||||||
|
|
||||||
|
#[clap(long = "nix-option", num_args = 2)]
|
||||||
|
nix_options: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(clap::Args, Debug)]
|
#[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
|
// TODO: create a general lock while we are running to avoid running system-manager concurrently
|
||||||
fn main() -> ExitCode {
|
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()))
|
handle_toplevel_error(go(Args::parse()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,8 +134,26 @@ fn go(args: Args) -> Result<()> {
|
||||||
action,
|
action,
|
||||||
target_host,
|
target_host,
|
||||||
use_remote_sudo,
|
use_remote_sudo,
|
||||||
|
nix_options,
|
||||||
} = args;
|
} = 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 {
|
match action {
|
||||||
Action::Activate {
|
Action::Activate {
|
||||||
store_path,
|
store_path,
|
||||||
|
|
@ -149,24 +170,29 @@ fn go(args: Args) -> Result<()> {
|
||||||
ephemeral,
|
ephemeral,
|
||||||
&target_host,
|
&target_host,
|
||||||
use_remote_sudo,
|
use_remote_sudo,
|
||||||
|
&nix_options,
|
||||||
)
|
)
|
||||||
.and_then(print_store_path),
|
.and_then(print_store_path),
|
||||||
Action::Build {
|
Action::Build {
|
||||||
build_args: BuildArgs { flake_uri },
|
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 {
|
Action::Deactivate {
|
||||||
optional_store_path_args: OptionalStorePathArg { maybe_store_path },
|
optional_store_path_args: OptionalStorePathArg { maybe_store_path },
|
||||||
} => deactivate(maybe_store_path, &target_host, use_remote_sudo),
|
} => deactivate(maybe_store_path, &target_host, use_remote_sudo),
|
||||||
Action::Generate {
|
Action::Generate {
|
||||||
store_or_flake_args,
|
store_or_flake_args,
|
||||||
} => {
|
} => generate(
|
||||||
generate(store_or_flake_args, &target_host, use_remote_sudo).and_then(print_store_path)
|
store_or_flake_args,
|
||||||
}
|
&target_host,
|
||||||
|
use_remote_sudo,
|
||||||
|
&nix_options,
|
||||||
|
)
|
||||||
|
.and_then(print_store_path),
|
||||||
Action::Switch {
|
Action::Switch {
|
||||||
build_args: BuildArgs { flake_uri },
|
build_args: BuildArgs { flake_uri },
|
||||||
activation_args: ActivationArgs { ephemeral },
|
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)?;
|
copy_closure(&store_path, &target_host)?;
|
||||||
do_generate(&store_path, &target_host, use_remote_sudo)?;
|
do_generate(&store_path, &target_host, use_remote_sudo)?;
|
||||||
activate(&store_path, ephemeral, &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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build(flake_uri: &str, target_host: &Option<String>) -> Result<StorePath> {
|
fn build(
|
||||||
let store_path = do_build(flake_uri)?;
|
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)?;
|
copy_closure(&store_path, target_host)?;
|
||||||
Ok(store_path)
|
Ok(store_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_build(flake_uri: &str) -> Result<StorePath> {
|
fn do_build(flake_uri: &str, nix_options: &NixOptions) -> Result<StorePath> {
|
||||||
system_manager::generate::build(flake_uri)
|
system_manager::generate::build(flake_uri, nix_options)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate(
|
fn generate(
|
||||||
args: StoreOrFlakeArgs,
|
args: StoreOrFlakeArgs,
|
||||||
target_host: &Option<String>,
|
target_host: &Option<String>,
|
||||||
use_remote_sudo: bool,
|
use_remote_sudo: bool,
|
||||||
|
nix_options: &NixOptions,
|
||||||
) -> Result<StorePath> {
|
) -> Result<StorePath> {
|
||||||
match args {
|
match args {
|
||||||
StoreOrFlakeArgs {
|
StoreOrFlakeArgs {
|
||||||
|
|
@ -206,7 +237,7 @@ fn generate(
|
||||||
maybe_flake_uri: Some(flake_uri),
|
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)?;
|
copy_closure(&store_path, target_host)?;
|
||||||
do_generate(&store_path, target_host, use_remote_sudo)?;
|
do_generate(&store_path, target_host, use_remote_sudo)?;
|
||||||
Ok(store_path)
|
Ok(store_path)
|
||||||
|
|
@ -284,6 +315,7 @@ fn prepopulate(
|
||||||
ephemeral: bool,
|
ephemeral: bool,
|
||||||
target_host: &Option<String>,
|
target_host: &Option<String>,
|
||||||
use_remote_sudo: bool,
|
use_remote_sudo: bool,
|
||||||
|
nix_options: &NixOptions,
|
||||||
) -> Result<StorePath> {
|
) -> Result<StorePath> {
|
||||||
match args {
|
match args {
|
||||||
StoreOrFlakeArgs {
|
StoreOrFlakeArgs {
|
||||||
|
|
@ -296,7 +328,7 @@ fn prepopulate(
|
||||||
maybe_flake_uri: Some(flake_uri),
|
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)?;
|
copy_closure(&store_path, target_host)?;
|
||||||
do_generate(&store_path, target_host, use_remote_sudo)?;
|
do_generate(&store_path, target_host, use_remote_sudo)?;
|
||||||
do_prepopulate(&store_path, ephemeral, 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