diff --git a/crates/spk-cli/common/src/flags.rs b/crates/spk-cli/common/src/flags.rs index e0d9255d7..78e4cc47d 100644 --- a/crates/spk-cli/common/src/flags.rs +++ b/crates/spk-cli/common/src/flags.rs @@ -32,15 +32,25 @@ use spk_schema::ident::{ PinnableRequest, PinnedValue, PkgRequest, + PkgRequestOptionValue, + PkgRequestOptions, + PkgRequestWithOptions, RangeIdent, - RequestWithOptions, RequestedBy, VarRequest, parse_ident, }; use spk_schema::option_map::HOST_OPTIONS; -use spk_schema::{Recipe, SpecFileData, SpecRecipe, Template, TestStage, VariantExt}; -use spk_solve as solve; +use spk_schema::{ + Recipe, + RequestWithOptions, + SpecFileData, + SpecRecipe, + Template, + TestStage, + VariantExt, +}; +use spk_solve::{self as solve}; #[cfg(unix)] #[cfg(feature = "statsd")] use spk_solve::{SPK_RUN_TIME_METRIC, get_metrics_client}; @@ -673,7 +683,23 @@ impl Requests { if req.required_compat.is_none() { req.required_compat = Some(CompatRule::API); } - out.push(req.into()); + let mut pkg_request_options = PkgRequestOptions::default(); + for (opt_name, value) in options.iter() { + if let Some(ns) = opt_name.namespace() + && ns == req.pkg.name + { + pkg_request_options.insert( + opt_name.clone(), + // `--opt` from the command line apply to all requests + // equally therefore this value is `Complete`. + PkgRequestOptionValue::Complete(value.clone()), + ); + } + } + out.push(RequestWithOptions::Pkg(PkgRequestWithOptions { + pkg_request: req, + options: pkg_request_options, + })); Ok(out) } diff --git a/crates/spk-cli/common/src/flags_test.rs b/crates/spk-cli/common/src/flags_test.rs index 5f91d6c24..b0bd0fffb 100644 --- a/crates/spk-cli/common/src/flags_test.rs +++ b/crates/spk-cli/common/src/flags_test.rs @@ -3,9 +3,10 @@ // https://github.com/spkenv/spk use rstest::rstest; +use spk_schema::RequestWithOptions; use spk_schema::foundation::name::OptName; use spk_schema::foundation::option_map::OptionMap; -use spk_schema::ident::VarRequest; +use spk_schema::ident::{PkgRequestOptionValue, VarRequest}; use spk_schema::option_map::HOST_OPTIONS; use spk_solve::Solver; @@ -115,3 +116,40 @@ async fn test_get_solver_with_host_options( } } } + +#[tokio::test] +async fn test_parse_request_includes_matching_cli_options() { + let request_flags = crate::flags::Requests { + pre: false, + workspace: crate::flags::Workspace::default(), + }; + let options_flags = crate::flags::Options { + no_host: true, + options: vec![ + "mylib.namespace_style=major_minor".to_string(), + "other.namespace_style=ignored".to_string(), + ], + }; + let repos: &[std::sync::Arc] = &[]; + + let (request, extra_options) = request_flags + .parse_request("mylib", &options_flags, repos) + .await + .unwrap(); + + assert!(extra_options.is_empty()); + + let RequestWithOptions::Pkg(pkg_request) = request else { + panic!("expected package request"); + }; + + let matching_opt = OptName::new("mylib.namespace_style").unwrap().to_owned(); + assert_eq!( + pkg_request.options.get(&matching_opt), + Some(&PkgRequestOptionValue::Complete("major_minor".to_string())) + ); + assert_eq!(pkg_request.options.len(), 1); + + let unrelated_opt = OptName::new("other.namespace_style").unwrap().to_owned(); + assert!(!pkg_request.options.contains_key(&unrelated_opt)); +}