use std::{borrow::Cow, fs}; use git_config::{ file::{includes, init, init::from_env}, File, }; use git_testtools::Env; use serial_test::serial; use tempfile::tempdir; use crate::file::init::from_paths::escape_backslashes; #[test] #[serial] fn empty_without_relevant_environment() { let config = File::from_env(Default::default()).unwrap(); assert!(config.is_none()); } #[test] #[serial] fn empty_with_zero_count() { let _env = Env::new().set("GIT_CONFIG_COUNT", "0"); let config = File::from_env(Default::default()).unwrap(); assert!(config.is_none()); } #[test] #[serial] fn parse_error_with_invalid_count() { let _env = Env::new().set("GIT_CONFIG_COUNT", "invalid"); let err = File::from_env(Default::default()).unwrap_err(); assert!(matches!(err, from_env::Error::InvalidConfigCount { .. })); } #[test] #[serial] fn single_key_value_pair() -> crate::Result { let _env = Env::new() .set("GIT_CONFIG_COUNT", "1") .set("GIT_CONFIG_KEY_0", "core.key") .set("GIT_CONFIG_VALUE_0", "value"); let config = File::from_env(Default::default())?.unwrap(); assert_eq!(config.raw_value("core", None, "key")?, Cow::<[u8]>::Borrowed(b"value")); assert_eq!( config.section("core", None)?.meta(), &git_config::file::Metadata::from(git_config::Source::Env), "source if configured correctly" ); assert_eq!(config.num_values(), 1); Ok(()) } #[test] #[serial] fn multiple_key_value_pairs() { let _env = Env::new() .set("GIT_CONFIG_COUNT", "3") .set("GIT_CONFIG_KEY_0", "core.a") .set("GIT_CONFIG_VALUE_0", "a") .set("GIT_CONFIG_KEY_1", "core.b") .set("GIT_CONFIG_VALUE_1", "b") .set("GIT_CONFIG_KEY_2", "core.c") .set("GIT_CONFIG_VALUE_2", "c"); let config = File::from_env(Default::default()).unwrap().unwrap(); assert_eq!( config.raw_value("core", None, "a").unwrap(), Cow::<[u8]>::Borrowed(b"a") ); assert_eq!( config.raw_value("core", None, "b").unwrap(), Cow::<[u8]>::Borrowed(b"b") ); assert_eq!( config.raw_value("core", None, "c").unwrap(), Cow::<[u8]>::Borrowed(b"c") ); assert_eq!(config.num_values(), 3); } #[test] #[serial] fn error_on_relative_paths_in_include_paths() { let _env = Env::new() .set("GIT_CONFIG_COUNT", "1") .set("GIT_CONFIG_KEY_0", "include.path") .set("GIT_CONFIG_VALUE_0", "some_git_config"); let res = File::from_env(init::Options { includes: includes::Options { max_depth: 1, ..Default::default() } .strict(), ..Default::default() }); assert!(matches!( res, Err(from_env::Error::Includes(includes::Error::MissingConfigPath)) )); } #[test] #[serial] fn follow_include_paths() { let dir = tempdir().unwrap(); let a_path = dir.path().join("a"); fs::write(&a_path, "[core]\nkey = changed").unwrap(); let b_path = dir.path().join("b"); fs::write(&b_path, "[core]\nkey = invalid").unwrap(); let _env = Env::new() .set("GIT_CONFIG_COUNT", "4") .set("GIT_CONFIG_KEY_0", "core.key") .set("GIT_CONFIG_VALUE_0", "value") .set("GIT_CONFIG_KEY_1", "include.path") .set("GIT_CONFIG_VALUE_1", escape_backslashes(a_path)) .set("GIT_CONFIG_KEY_2", "other.path") .set("GIT_CONFIG_VALUE_2", escape_backslashes(&b_path)) .set("GIT_CONFIG_KEY_3", "include.origin.path") .set("GIT_CONFIG_VALUE_3", escape_backslashes(b_path)); let config = File::from_env(init::Options { includes: includes::Options { max_depth: 1, ..Default::default() }, ..Default::default() }) .unwrap() .unwrap(); assert_eq!( config.raw_value("core", None, "key").unwrap(), Cow::<[u8]>::Borrowed(b"changed") ); assert_eq!(config.num_values(), 5); }