Convert eval arguments to type-safe clap derive

This commit is contained in:
i1i1 2023-08-10 01:47:10 +03:00 committed by Zhaofeng Li
parent cdfc1f15a1
commit 5b8611744b
2 changed files with 45 additions and 53 deletions

View file

@ -191,8 +191,7 @@ It's also possible to specify the preference using environment variables. See <h
), ),
); );
// deprecated alias // TODO: handle deprecated alias
app = app.subcommand(command::eval::deprecated_alias());
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
register_command!(test_progress, app); register_command!(test_progress, app);

View file

@ -1,44 +1,39 @@
use std::path::PathBuf; use std::path::PathBuf;
use clap::{value_parser, Arg, ArgMatches, Command as ClapCommand, FromArgMatches}; use clap::{ArgMatches, Args, Command as ClapCommand, FromArgMatches};
use crate::error::ColmenaError; use crate::error::ColmenaError;
use crate::nix::hive::HiveArgs; use crate::nix::hive::HiveArgs;
pub fn subcommand() -> ClapCommand { #[derive(Debug, Args)]
subcommand_gen("eval") #[command(
} name = "eval",
alias = "introspect",
pub fn deprecated_alias() -> ClapCommand { about = "Evaluate an expression using the complete configuration",
subcommand_gen("introspect").hide(true) long_about = r#"Evaluate an expression using the complete configuration
}
fn subcommand_gen(name: &'static str) -> ClapCommand {
ClapCommand::new(name)
.about("Evaluate an expression using the complete configuration")
.long_about(r#"Evaluate an expression using the complete configuration
Your expression should take an attribute set with keys `pkgs`, `lib` and `nodes` (like a NixOS module) and return a JSON-serializable value. Your expression should take an attribute set with keys `pkgs`, `lib` and `nodes` (like a NixOS module) and return a JSON-serializable value.
For example, to retrieve the configuration of one node, you may write something like: For example, to retrieve the configuration of one node, you may write something like:
{ nodes, ... }: nodes.node-a.config.networking.hostName { nodes, ... }: nodes.node-a.config.networking.hostName
"#) "#
.arg(Arg::new("expression_file") )]
.index(1) pub struct Opts {
.value_name("FILE") #[arg(short = 'E', value_name = "EXPRESSION", help = "The Nix expression")]
.help("The .nix file containing the expression") expression: Option<String>,
.num_args(1) #[arg(long, help = "Actually instantiate the expression")]
.value_parser(value_parser!(PathBuf))) instantiate: bool,
.arg(Arg::new("expression") #[arg(
.short('E') value_name = "FILE",
.value_name("EXPRESSION") help = "The .nix file containing the expression",
.help("The Nix expression") conflicts_with("expression")
.num_args(1)) )]
.arg(Arg::new("instantiate") expression_file: Option<PathBuf>,
.long("instantiate") }
.help("Actually instantiate the expression")
.num_args(0)) pub fn subcommand() -> ClapCommand {
Opts::augment_args(ClapCommand::new("eval"))
} }
pub async fn run(global_args: &ArgMatches, local_args: &ArgMatches) -> Result<(), ColmenaError> { pub async fn run(global_args: &ArgMatches, local_args: &ArgMatches) -> Result<(), ColmenaError> {
@ -54,21 +49,14 @@ pub async fn run(global_args: &ArgMatches, local_args: &ArgMatches) -> Result<()
.await .await
.unwrap(); .unwrap();
if !(local_args.contains_id("expression") ^ local_args.contains_id("expression_file")) { let Opts {
log::error!("Either an expression (-E) or a .nix file containing an expression should be specified, not both."); instantiate,
quit::with_code(1); expression,
} expression_file,
} = Opts::from_arg_matches(local_args).expect("Failed to parse args");
let expression = if local_args.contains_id("expression") { let expression = expression_file
local_args .map(|path| {
.get_one::<String>("expression")
.unwrap()
.to_owned()
} else {
let path = local_args
.get_one::<PathBuf>("expression_file")
.unwrap()
.to_owned();
format!( format!(
"import {}", "import {}",
path.canonicalize() path.canonicalize()
@ -76,9 +64,14 @@ pub async fn run(global_args: &ArgMatches, local_args: &ArgMatches) -> Result<()
.to_str() .to_str()
.unwrap() .unwrap()
) )
})
.or(expression);
let Some(expression) = expression else {
log::error!("Provide either an expression (-E) or a .nix file containing an expression.");
quit::with_code(1);
}; };
let instantiate = local_args.get_flag("instantiate");
let result = hive.introspect(expression, instantiate).await?; let result = hive.introspect(expression, instantiate).await?;
if instantiate { if instantiate {