From 5fe3bc61c66b51183ba790261bc33aa26d1ca9a6 Mon Sep 17 00:00:00 2001 From: NotAShelf Date: Tue, 3 Mar 2026 22:36:01 +0300 Subject: [PATCH] util: optimize package flag checking; better error handling Signed-off-by: NotAShelf Change-Id: I1fb76c5fe6360339e568936d32f9e7656a6a6964 --- eh/src/util.rs | 67 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/eh/src/util.rs b/eh/src/util.rs index c6eff61..4b57921 100644 --- a/eh/src/util.rs +++ b/eh/src/util.rs @@ -290,13 +290,14 @@ fn is_hash_mismatch_error(stderr: &str) -> bool { /// Returns the appropriate `RetryAction` if any of these are true. Makes a /// single nix eval call to minimize overhead. fn check_package_flags(args: &[String]) -> Result { - let eval_arg = args.iter().find(|arg| !arg.starts_with('-')); + // Default to "." if no argument provided (like `nix build` without args) + let eval_arg = args + .iter() + .find(|arg| !arg.starts_with('-')) + .cloned() + .unwrap_or_else(|| ".".to_string()); - let Some(eval_arg) = eval_arg else { - return Ok(RetryAction::None); - }; - - let eval_expr = format!("nixpkgs#{}.meta", eval_arg); + let eval_expr = format!("nixpkgs#{eval_arg}.meta"); let eval_cmd = NixCommand::new("eval") .arg("--json") .arg(&eval_expr) @@ -304,15 +305,32 @@ fn check_package_flags(args: &[String]) -> Result { let output = match eval_cmd.output() { Ok(o) if o.status.success() => o, - _ => return Ok(RetryAction::None), + Ok(o) => { + let stderr = String::from_utf8_lossy(&o.stderr); + if stderr.contains("does not provide attribute") { + return Ok(RetryAction::None); + } + log_warn!( + "failed to check package flags for '{}': {}", + eval_arg, + stderr.trim() + ); + return Ok(RetryAction::None); + }, + + Err(e) => { + log_warn!("failed to check package flags for '{}': {}", eval_arg, e); + return Ok(RetryAction::None); + }, }; - let meta: serde_json::Value = serde_json::from_slice(&output.stdout) - .map_err(|_| { - EhError::JsonParse { - detail: "failed to parse nix eval --json output".to_string(), - } - })?; + let meta: serde_json::Value = match serde_json::from_slice(&output.stdout) { + Ok(v) => v, + Err(e) => { + log_warn!("failed to parse package metadata for '{}': {}", eval_arg, e); + return Ok(RetryAction::None); + }, + }; let flags = [ ("unfree", RetryAction::AllowUnfree), @@ -321,7 +339,11 @@ fn check_package_flags(args: &[String]) -> Result { ]; for (key, action) in flags { - if meta.get(key).and_then(|v| v.as_bool()).unwrap_or(false) { + if meta + .get(key) + .and_then(serde_json::Value::as_bool) + .unwrap_or(false) + { return Ok(action); } } @@ -343,14 +365,19 @@ fn pre_evaluate(args: &[String]) -> Result { // Find flake references or expressions to evaluate // Only take the first non-flag argument (the package/expression) - let eval_arg = args.iter().find(|arg| !arg.starts_with('-')); - - let Some(eval_arg) = eval_arg else { - return Ok(RetryAction::None); // No expression to evaluate - }; + // Default to "." if no argument provided (like `nix build` without args) + let eval_arg = args + .iter() + .find(|arg| !arg.starts_with('-')) + .cloned() + .unwrap_or_else(|| { + log_warn!("no package specified, defaulting to '.' (current directory)"); + ".".to_string() + }); + let eval_arg_ref = &eval_arg; let eval_cmd = NixCommand::new("eval") - .arg(eval_arg) + .arg(eval_arg_ref) .print_build_logs(false); let output = eval_cmd.output()?;