diff --git a/tvix/cli/src/args.rs b/tvix/cli/src/args.rs index d47258f10..746e355e1 100644 --- a/tvix/cli/src/args.rs +++ b/tvix/cli/src/args.rs @@ -45,9 +45,13 @@ pub struct Args { #[clap(long)] pub no_warnings: bool, - /// A colon-separated list of directories to use to resolve `<...>`-style paths - #[clap(long, short = 'I', env = "NIX_PATH")] - pub nix_search_path: Option, + /// Additional entries to the Nix expression search path, a colon-separated list of directories + /// used to resolve `<...>`-style lookup paths. + /// + /// This option may be given multiple times. Paths added through -I take precedence over + /// NIX_PATH. + #[clap(long = "extra-nix-path", short = 'I', env = "NIX_PATH", action = clap::ArgAction::Append)] + pub extra_nix_paths: Option>, /// Print "raw" (unquoted) output. #[clap(long)] @@ -76,3 +80,53 @@ pub struct Args { #[clap(long)] pub drv_dumpdir: Option, } + +impl Args { + pub fn nix_path(&self) -> Option { + resolve_nix_path(std::env::var("NIX_PATH"), &self.extra_nix_paths) + } +} + +fn resolve_nix_path( + nix_path: Result, + extra_nix_paths: &Option>, +) -> Option { + let nix_path_option = nix_path.ok().filter(|string| !string.is_empty()); + let extra_nix_paths_option = extra_nix_paths.to_owned().map(|vec| vec.join(":")); + match (nix_path_option, extra_nix_paths_option) { + (Some(nix_path), Some(mut extra_nix_paths)) => { + extra_nix_paths.push(':'); + Some(extra_nix_paths + &nix_path) + } + (nix_path_option, extra_nix_paths_option) => nix_path_option.or(extra_nix_paths_option), + } +} + +#[cfg(test)] +mod tests { + use super::resolve_nix_path; + + #[test] + fn test_resolve_nix_path() { + let nix_path = Ok("/nixpath1:nixpath2=/nixpath2".to_owned()); + let extra_nix_paths = Some(vec!["/extra1".to_owned(), "extra2=/extra2".to_owned()]); + let expected = Some("/extra1:extra2=/extra2:/nixpath1:nixpath2=/nixpath2".to_owned()); + let actual = resolve_nix_path(nix_path, &extra_nix_paths); + assert!(actual == expected); + let nix_path = Err(std::env::VarError::NotPresent); + let extra_nix_paths = Some(vec!["/extra1".to_owned(), "extra2=/extra2".to_owned()]); + let expected = Some("/extra1:extra2=/extra2".to_owned()); + let actual = resolve_nix_path(nix_path, &extra_nix_paths); + assert!(actual == expected); + let nix_path = Ok("/nixpath1:nixpath2=/nixpath2".to_owned()); + let extra_nix_paths = None; + let expected = Some("/nixpath1:nixpath2=/nixpath2".to_owned()); + let actual = resolve_nix_path(nix_path, &extra_nix_paths); + assert!(actual == expected); + let nix_path = Err(std::env::VarError::NotPresent); + let extra_nix_paths = None; + let expected = None; + let actual = resolve_nix_path(nix_path, &extra_nix_paths); + assert!(actual == expected); + } +} diff --git a/tvix/cli/src/lib.rs b/tvix/cli/src/lib.rs index 3a0040ea1..ce3ece145 100644 --- a/tvix/cli/src/lib.rs +++ b/tvix/cli/src/lib.rs @@ -118,7 +118,7 @@ pub fn evaluate( eval_builder = add_import_builtins(eval_builder, Rc::clone(&tvix_store_io)); } }; - eval_builder = configure_nix_path(eval_builder, &args.nix_search_path); + eval_builder = configure_nix_path(eval_builder, &args.nix_path()); if let Some(source_map) = source_map { eval_builder = eval_builder.with_source_map(source_map); diff --git a/tvix/cli/tests/repl.rs b/tvix/cli/tests/repl.rs index 7b9b9e345..072ccda7c 100644 --- a/tvix/cli/tests/repl.rs +++ b/tvix/cli/tests/repl.rs @@ -11,7 +11,7 @@ macro_rules! test_repl { let tokio_runtime = tokio::runtime::Runtime::new().unwrap(); let args = tvix_cli::Args::parse_from(vec![ OsString::from("tvix"), - OsString::from("--nix-search-path"), + OsString::from("--extra-nix-path"), OsString::from("nixpkgs=/tmp"), ]); let mut repl = tvix_cli::Repl::new(init_io_handle(&tokio_runtime, &args), &args);