use std::path::Path;
use std::process::Command;
pub const NIX_EXPERIMENTAL_FEATURES: &str = "nix-command flakes";
#[must_use]
fn nix_base(nix_bin: &Path, subcommand: &[&str]) -> Command {
let mut cmd = Command::new(nix_bin);
cmd.args(subcommand);
cmd.args(["--extra-experimental-features", NIX_EXPERIMENTAL_FEATURES]);
cmd
}
#[must_use]
fn sui_base(sui_bin: &Path, subcommand: &[&str]) -> Command {
let mut cmd = Command::new(sui_bin);
cmd.args(subcommand);
cmd
}
pub mod nix_cli {
use super::*;
#[must_use]
pub fn eval_expr(nix_bin: &Path, expr: &str) -> Command {
let mut cmd = nix_base(nix_bin, &["eval", "--impure", "--json"]);
cmd.args(["--expr", expr]);
cmd
}
#[must_use]
pub fn eval_installable(nix_bin: &Path, installable: &str) -> Command {
let mut cmd = nix_base(nix_bin, &["eval", "--impure", "--json"]);
cmd.arg(installable);
cmd
}
#[must_use]
pub fn flake_show(nix_bin: &Path, flake_ref: &str) -> Command {
let mut cmd = nix_base(nix_bin, &["flake", "show", "--json"]);
cmd.arg(flake_ref);
cmd
}
#[must_use]
pub fn flake_check(nix_bin: &Path, flake_ref: &str) -> Command {
let mut cmd = nix_base(nix_bin, &["flake", "check"]);
cmd.arg(flake_ref);
cmd
}
#[must_use]
pub fn build_dry_run(nix_bin: &Path, installable: &str) -> Command {
let mut cmd = nix_base(
nix_bin,
&["build", "--dry-run", "--print-out-paths", "--no-link"],
);
cmd.arg(installable);
cmd
}
}
pub mod sui_cli {
use super::*;
#[must_use]
pub fn eval_expr(sui_bin: &Path, expr: &str) -> Command {
let mut cmd = sui_base(sui_bin, &["eval", "--json"]);
cmd.arg(expr);
cmd
}
#[must_use]
pub fn eval_installable(sui_bin: &Path, installable: &str) -> Command {
let mut cmd = sui_base(sui_bin, &["eval", "--json"]);
cmd.arg(installable);
cmd
}
#[must_use]
pub fn eval_expr_explicit(sui_bin: &Path, expr: &str) -> Command {
let mut cmd = sui_base(sui_bin, &["eval", "--impure", "--json"]);
cmd.args(["--expr", expr]);
cmd
}
#[must_use]
pub fn flake_show(sui_bin: &Path, flake_ref: &str) -> Command {
let mut cmd = sui_base(sui_bin, &["flake", "show", "--json"]);
cmd.arg(flake_ref);
cmd
}
#[must_use]
pub fn flake_check(sui_bin: &Path, flake_ref: &str) -> Command {
let mut cmd = sui_base(sui_bin, &["flake", "check"]);
cmd.arg(flake_ref);
cmd
}
#[must_use]
pub fn build_dry_run(sui_bin: &Path, installable: &str) -> Command {
let mut cmd = sui_base(
sui_bin,
&["build", "--dry-run", "--print-out-paths", "--no-link"],
);
cmd.arg(installable);
cmd
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::exec::command_argv;
use std::path::PathBuf;
fn nix_path() -> PathBuf {
PathBuf::from("/usr/local/bin/nix")
}
fn sui_path() -> PathBuf {
PathBuf::from("/usr/local/bin/sui")
}
#[test]
fn nix_eval_expr_includes_experimental_features() {
let cmd = nix_cli::eval_expr(&nix_path(), "1 + 2");
let argv = command_argv(&cmd);
assert_eq!(argv[0], "/usr/local/bin/nix");
assert!(argv.iter().any(|a| a == "--extra-experimental-features"));
assert!(argv.iter().any(|a| a == NIX_EXPERIMENTAL_FEATURES));
assert!(argv.iter().any(|a| a == "--expr"));
assert!(argv.iter().any(|a| a == "1 + 2"));
assert!(argv.iter().any(|a| a == "--impure"));
assert!(argv.iter().any(|a| a == "--json"));
}
#[test]
fn nix_flake_show_includes_experimental_features_and_ref() {
let cmd = nix_cli::flake_show(&nix_path(), "path:/tmp/myflake");
let argv = command_argv(&cmd);
assert!(argv.windows(2).any(|w| w == ["flake", "show"]));
assert!(argv.iter().any(|a| a == "--json"));
assert!(argv.iter().any(|a| a == "--extra-experimental-features"));
assert!(argv.iter().any(|a| a == "path:/tmp/myflake"));
}
#[test]
fn nix_build_dry_run_carries_all_flags() {
let cmd = nix_cli::build_dry_run(&nix_path(), "path:/tmp/f#x.y");
let argv = command_argv(&cmd);
for required in ["--dry-run", "--print-out-paths", "--no-link"] {
assert!(
argv.iter().any(|a| a == required),
"build_dry_run missing {required}; argv: {argv:?}",
);
}
}
#[test]
fn sui_eval_expr_is_positional() {
let cmd = sui_cli::eval_expr(&sui_path(), "1 + 2");
let argv = command_argv(&cmd);
assert_eq!(argv[0], "/usr/local/bin/sui");
assert_eq!(argv[1], "eval");
assert_eq!(argv[2], "--json");
assert_eq!(argv[3], "1 + 2");
assert!(!argv.iter().any(|a| a == "--extra-experimental-features"));
}
#[test]
fn sui_eval_expr_explicit_uses_dash_dash_expr() {
let cmd = sui_cli::eval_expr_explicit(&sui_path(), "1 + 2");
let argv = command_argv(&cmd);
assert!(argv.iter().any(|a| a == "--expr"));
assert!(argv.iter().any(|a| a == "1 + 2"));
assert!(argv.iter().any(|a| a == "--impure"));
}
#[test]
fn sui_flake_show_and_check() {
let show = sui_cli::flake_show(&sui_path(), "path:/tmp/f");
let check = sui_cli::flake_check(&sui_path(), "path:/tmp/f");
let show_argv = command_argv(&show);
let check_argv = command_argv(&check);
assert!(show_argv.windows(2).any(|w| w == ["flake", "show"]));
assert!(check_argv.windows(2).any(|w| w == ["flake", "check"]));
assert!(show_argv.iter().any(|a| a == "--json"));
assert!(!check_argv.iter().any(|a| a == "--json")); }
#[test]
fn symmetric_signatures() {
let p = "path:/tmp/f";
let n = nix_cli::flake_show(&nix_path(), p);
let s = sui_cli::flake_show(&sui_path(), p);
let na = command_argv(&n);
let sa = command_argv(&s);
assert!(na.iter().any(|a| a == p) && sa.iter().any(|a| a == p));
assert!(na.iter().any(|a| a == "--json") && sa.iter().any(|a| a == "--json"));
}
}