diff --git a/src/bin/repo/main.rs b/src/bin/repo/main.rs index 1854e4ba0..74d1a32a9 100644 --- a/src/bin/repo/main.rs +++ b/src/bin/repo/main.rs @@ -72,7 +72,9 @@ const REPO_HELP_STR: &str = r#" ignored when command "fetch" is used COOKBOOK_NONSTOP=false keep running even a recipe build failed COOKBOOK_COMPRESSED=false build packages in compressed format + COOKBOOK_GIT_TREELESS=false clone sources as treeless by default COOKBOOK_VERBOSE=true print success/error on each recipe + COOKBOOK_VERBOSE_CMD=true add -x to bash build script COOKBOOK_CLEAN_BUILD=false remove build directory before building COOKBOOK_CLEAN_TARGET=false remove target directory after building COOKBOOK_WRITE_FILETREE=false whether to write stage files tree diff --git a/src/config.rs b/src/config.rs index 93e7a429d..e432cd65a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,6 +1,6 @@ use std::{ collections::{BTreeMap, HashMap}, - env, fs, + fs, str::FromStr, sync::OnceLock, }; @@ -23,6 +23,8 @@ pub struct CookConfigOpt { pub nonstop: Option, /// whether to archive packages with compressed format pub compressed: Option, + /// whether to clone as treeless clone by default + pub git_treeless: Option, /// whether to print everything in progress, /// will always hide cached build logs, /// build failure will be printed anyway @@ -47,6 +49,7 @@ pub struct CookConfig { pub logs: bool, pub nonstop: bool, pub compressed: bool, + pub git_treeless: bool, pub verbose: bool, pub verbose_cmd: bool, pub clean_build: bool, @@ -63,6 +66,7 @@ impl From for CookConfig { logs: value.logs.unwrap(), nonstop: value.nonstop.unwrap(), compressed: value.compressed.unwrap(), + git_treeless: value.git_treeless.unwrap(), verbose: value.verbose.unwrap(), verbose_cmd: value.verbose_cmd.unwrap(), clean_build: value.clean_build.unwrap(), @@ -116,6 +120,7 @@ pub struct CookbookConfig { static CONFIG: OnceLock = OnceLock::new(); pub fn init_config() { + #[cfg(not(test))] let mut config: CookbookConfig = if fs::exists("cookbook.toml").unwrap_or(false) { let toml_content = fs::read_to_string("cookbook.toml") .map_err(|e| format!("Unable to read config: {:?}", e)) @@ -126,9 +131,22 @@ pub fn init_config() { } else { CookbookConfig::default() }; + #[cfg(test)] + let mut config: CookbookConfig = toml::from_str( + "[mirrors]\n\ + \"ftp.gnu.org/gnu\" = \"example.com/gnu\"\n\ + \"github.com/foo/bar\" = \"github.com/baz/bar\"\n\ + \"github.com/a\" = \"github.com/b\"\n", + ) + .expect("Unable to parse test config"); + #[cfg(not(test))] if config.cook_opt.tui.is_none() { - config.cook_opt.tui = Some(!env::var("CI").is_ok_and(|s| !s.is_empty())); + config.cook_opt.tui = Some(!std::env::var("CI").is_ok_and(|s| !s.is_empty())); + } + #[cfg(test)] + if config.cook_opt.tui.is_none() { + config.cook_opt.tui = Some(true); } if config.cook_opt.jobs.is_none() { config.cook_opt.jobs = Some(extract_env( @@ -148,6 +166,9 @@ pub fn init_config() { if config.cook_opt.compressed.is_none() { config.cook_opt.compressed = Some(extract_env("COOKBOOK_COMPRESSED", false)); } + if config.cook_opt.git_treeless.is_none() { + config.cook_opt.git_treeless = Some(extract_env("COOKBOOK_GIT_TREELESS", false)); + } if config.cook_opt.verbose.is_none() { let default = config.cook_opt.logs.unwrap(); config.cook_opt.verbose = Some(extract_env("COOKBOOK_VERBOSE", default)); @@ -193,16 +214,24 @@ pub fn init_config() { }; config.recipe_lock = lock.recipes; - + #[cfg(not(test))] CONFIG.set(config).expect("config is initialized twice"); + #[cfg(test)] + let _ = CONFIG.set(config); } +#[allow(unused_variables)] fn extract_env(key: &str, default: T) -> T { - if let Ok(e) = env::var(&key) { + #[cfg(not(test))] + if let Ok(e) = std::env::var(&key) { str::parse(&e).unwrap_or(default) } else { default } + #[cfg(test)] + { + default + } } pub fn get_config() -> &'static CookbookConfig { @@ -253,16 +282,9 @@ mod tests { use super::*; fn setup_test_config() { - let app_config = toml::from_str( - "[mirrors]\n\ - \"ftp.gnu.org/gnu\" = \"example.com/gnu\"\n\ - \"github.com/foo/bar\" = \"github.com/baz/bar\"\n\ - \"github.com/a\" = \"github.com/b\"\n", - ) - .expect("Unable to parse test config"); // This will be called for each test. If the config is already set, // it will do nothing, which is fine as all tests use the same config. - let _ = CONFIG.set(app_config); + init_config(); } #[test] @@ -276,6 +298,30 @@ mod tests { assert_eq!(app_config.cook_opt.jobs, None); } + #[test] + fn test_default_cook() { + setup_test_config(); + assert_eq!( + get_config().cook, + CookConfig { + offline: false, + jobs: std::thread::available_parallelism() + .map(|f| usize::from(f)) + .unwrap_or(1), + tui: true, + logs: true, + nonstop: false, + compressed: false, + git_treeless: false, + verbose: true, + verbose_cmd: true, + clean_build: false, + clean_target: false, + write_filetree: false + } + ); + } + #[test] fn test_exact_match() { setup_test_config(); diff --git a/src/cook/fetch.rs b/src/cook/fetch.rs index cbb06079e..5d1816a62 100644 --- a/src/cook/fetch.rs +++ b/src/cook/fetch.rs @@ -207,7 +207,8 @@ pub fn fetch(recipe: &CookRecipe, check_source: bool, logger: &PtyOut) -> Result shallow_clone, }) => { //TODO: use libgit? - let shallow_clone = *shallow_clone == Some(true); + let shallow_clone = + shallow_clone.unwrap_or_else(|| crate::config::get_config().cook.git_treeless); let mut fetch_is_ran = false; let patches_ident = get_patches_blake3(&recipe_dir, patches, script)?; let cached = if !source_dir.is_dir() {