From 462e40ad231abf8dcc94be872265512a27adf707 Mon Sep 17 00:00:00 2001 From: Alex Huszagh Date: Wed, 15 Jun 2022 13:19:50 -0500 Subject: [PATCH] Make config vectors optional. Allows us to differentiate between an empty array and an array that was not provided when merging config files. https://github.com/cross-rs/cross/pull/754#issuecomment-1156722398 Required for #754. --- src/config.rs | 8 ++--- src/cross_toml.rs | 91 +++++++++++++++++++++++++++++++++++++---------- 2 files changed, 77 insertions(+), 22 deletions(-) diff --git a/src/config.rs b/src/config.rs index b7a3ddf77..1b09b74d6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -179,8 +179,8 @@ impl Config { &self, target: &Target, env: impl Fn(&Environment, &Target) -> (Option>, Option>), - config_build: impl for<'a> Fn(&'a CrossToml) -> &'a [String], - config_target: impl for<'a> Fn(&'a CrossToml, &Target) -> &'a [String], + config_build: impl for<'a> Fn(&'a CrossToml) -> Option<&'a [String]>, + config_target: impl for<'a> Fn(&'a CrossToml, &Target) -> Option<&'a [String]>, ) -> Result> { let (env_build, env_target) = env(&self.env, target); @@ -241,12 +241,12 @@ impl Config { fn sum_of_env_toml_values<'a>( &'a self, env_values: Option>, - toml_getter: impl FnOnce(&'a CrossToml) -> &'a [String], + toml_getter: impl FnOnce(&'a CrossToml) -> Option<&'a [String]>, ) -> Result> { let mut collect = vec![]; if let Some(mut vars) = env_values { collect.append(&mut vars); - } else if let Some(toml_values) = self.toml.as_ref().map(toml_getter) { + } else if let Some(Some(toml_values)) = self.toml.as_ref().map(toml_getter) { collect.extend(toml_values.iter().cloned()); } diff --git a/src/cross_toml.rs b/src/cross_toml.rs index 1c125b505..683d475ee 100644 --- a/src/cross_toml.rs +++ b/src/cross_toml.rs @@ -8,10 +8,8 @@ use std::collections::{BTreeSet, HashMap}; /// Environment configuration #[derive(Debug, Deserialize, PartialEq, Eq, Default)] pub struct CrossEnvConfig { - #[serde(default)] - volumes: Vec, - #[serde(default)] - passthrough: Vec, + volumes: Option>, + passthrough: Option>, } /// Build configuration @@ -88,23 +86,23 @@ impl CrossToml { } /// Returns the list of environment variables to pass through for `build`, - pub fn env_passthrough_build(&self) -> &[String] { - &self.build.env.passthrough + pub fn env_passthrough_build(&self) -> Option<&[String]> { + self.build.env.passthrough.as_deref() } /// Returns the list of environment variables to pass through for `target`, - pub fn env_passthrough_target(&self, target: &Target) -> &[String] { - self.get_vec(target, |e| &e.passthrough) + pub fn env_passthrough_target(&self, target: &Target) -> Option<&[String]> { + self.get_vec(target, |e| e.passthrough.as_deref()) } /// Returns the list of environment variables to pass through for `build`, - pub fn env_volumes_build(&self) -> &[String] { - &self.build.env.volumes + pub fn env_volumes_build(&self) -> Option<&[String]> { + self.build.env.volumes.as_deref() } /// Returns the list of environment variables to pass through for `target`, - pub fn env_volumes_target(&self, target: &Target) -> &[String] { - self.get_vec(target, |e| &e.volumes) + pub fn env_volumes_target(&self, target: &Target) -> Option<&[String]> { + self.get_vec(target, |e| e.volumes.as_deref()) } /// Returns the default target to build, @@ -140,8 +138,12 @@ impl CrossToml { (build, target) } - fn get_vec(&self, target: &Target, get: impl Fn(&CrossEnvConfig) -> &[String]) -> &[String] { - self.get_target(target).map_or(&[], |t| get(&t.env)) + fn get_vec( + &self, + target: &Target, + get: impl Fn(&CrossEnvConfig) -> Option<&[String]>, + ) -> Option<&[String]> { + self.get_target(target).and_then(|t| get(&t.env)) } } @@ -169,8 +171,8 @@ mod tests { targets: HashMap::new(), build: CrossBuildConfig { env: CrossEnvConfig { - volumes: vec!["VOL1_ARG".to_string(), "VOL2_ARG".to_string()], - passthrough: vec!["VAR1".to_string(), "VAR2".to_string()], + volumes: Some(vec!["VOL1_ARG".to_string(), "VOL2_ARG".to_string()]), + passthrough: Some(vec!["VAR1".to_string(), "VAR2".to_string()]), }, xargo: Some(true), build_std: None, @@ -203,8 +205,8 @@ mod tests { }, CrossTargetConfig { env: CrossEnvConfig { - passthrough: vec!["VAR1".to_string(), "VAR2".to_string()], - volumes: vec!["VOL1_ARG".to_string(), "VOL2_ARG".to_string()], + passthrough: Some(vec!["VAR1".to_string(), "VAR2".to_string()]), + volumes: Some(vec!["VOL1_ARG".to_string(), "VOL2_ARG".to_string()]), }, xargo: Some(false), build_std: Some(true), @@ -234,4 +236,57 @@ mod tests { Ok(()) } + + #[test] + pub fn parse_mixed_toml() -> Result<()> { + let mut target_map = HashMap::new(); + target_map.insert( + Target::BuiltIn { + triple: "aarch64-unknown-linux-gnu".to_string(), + }, + CrossTargetConfig { + env: CrossEnvConfig { + passthrough: None, + volumes: Some(vec!["VOL".to_string()]), + }, + xargo: Some(false), + build_std: None, + image: None, + runner: None, + }, + ); + + let cfg = CrossToml { + targets: target_map, + build: CrossBuildConfig { + env: CrossEnvConfig { + volumes: None, + passthrough: Some(vec![]), + }, + xargo: Some(true), + build_std: None, + default_target: None, + }, + }; + + let test_str = r#" + [build] + xargo = true + + [build.env] + passthrough = [] + + [target.aarch64-unknown-linux-gnu] + xargo = false + + [target.aarch64-unknown-linux-gnu.env] + volumes = ["VOL"] + "#; + let (parsed_cfg, unused) = CrossToml::parse(test_str)?; + + assert_eq!(parsed_cfg, cfg); + assert!(unused.is_empty()); + + Ok(()) + } }