#![allow(clippy::unwrap_used, clippy::expect_used)]
use grit_lib::config::environment::Environment;
use grit_lib::config::{
parse_bool, parse_color, parse_git_config_int_strict, parse_i64, parse_path,
parse_path_optional, ConfigFile, ConfigScope, ConfigSet, LoadConfigOptions,
};
use grit_lib::repo::{InitOptions, Repository};
use tempfile::tempdir;
#[test]
fn many_parse_snippets_and_typed_parsers() {
let snippets: &[&str] = &[
"[s]\n\tk = v\n",
"[sec \"sub\"]\n\tk = 1\n",
"[sec \"sub\"]\n\tinline = x\n",
"[a]\n\tk = line1 \\\n\t\tline2\n",
"[m]\n\tk = a\n\tk = b\n",
"[fetch]\n\tnegotiationAlgorithm = skip\n",
"[core]\n\tbare = true\n\tfilemode = false\n",
"[url \"https://x/\"]\n\tinsteadOf = y:\n",
];
for content in snippets {
let file = ConfigFile::parse(std::path::Path::new("c"), content, ConfigScope::Local)
.expect("parse snippet");
let mut set = ConfigSet::new();
set.merge(&file);
assert!(set.entries().len() >= 1);
}
for input in ["true", "false", "yes", "no", "on", "off", "1", "0"] {
let _ = parse_bool(input).unwrap();
}
for input in ["0", "1", "42", "-3", "1k", "2m", "3g"] {
let _ = parse_i64(input).unwrap();
}
let _ = parse_git_config_int_strict("0").unwrap();
let _ = parse_color("bold red").unwrap();
let env = Environment::empty();
let _ = parse_path(&env, "~/x");
let _ = parse_path_optional(&env, ":(optional,create)/no/such/path");
}
#[test]
fn load_includes_system_global_and_local_layers() {
let dir = tempdir().expect("tempdir");
let home = dir.path().join("home");
std::fs::create_dir_all(&home).expect("home");
let system = dir.path().join("system.conf");
std::fs::write(&system, "[sys]\n\tk = 1\n").expect("sys");
std::fs::write(home.join(".gitconfig"), "[usr]\n\tk = 2\n").expect("usr");
let repo = dir.path().join("repo");
Repository::init(
&repo,
&InitOptions::new()
.with_initial_branch("main".to_owned())
.with_ref_storage(grit_lib::RefStorageFormat::Files),
)
.expect("init");
let git_dir = repo.join(".git");
std::fs::write(git_dir.join("config"), "[loc]\n\tk = 3\n").expect("loc");
let mut env = Environment::empty();
env.home = Some(home.as_os_str().to_os_string());
env.git_config_system = Some(system.display().to_string());
env.git_config_global = Some(home.join(".gitconfig").display().to_string());
env.cwd = repo.clone();
let set = ConfigSet::load(&env, Some(&git_dir), true).expect("full load");
assert_eq!(set.get("loc.k").as_deref(), Some("3"));
assert!(set.get("usr.k").is_some());
assert!(set.get("sys.k").is_some());
let early = ConfigSet::read_early_config(&env, Some(&git_dir), "loc.k").expect("early");
assert!(!early.is_empty());
}
#[test]
fn command_parameters_merged_when_includes_enabled() {
let dir = tempdir().expect("tempdir");
let inc = dir.path().join("p.conf");
std::fs::write(&inc, "[fromparam]\n\tk = yes\n").expect("inc");
let mut env = Environment::empty();
env.git_config_parameters = Some(format!(
"'include.path={}' 'top.key=override'",
inc.display().to_string().replace('\\', "\\\\")
));
env.cwd = dir.path().to_path_buf();
let opts = LoadConfigOptions {
include_system: false,
process_includes: true,
command_includes: true,
include_ctx: grit_lib::config::IncludeContext {
cwd: dir.path().to_path_buf(),
env: std::sync::Arc::new(env.clone()),
..Default::default()
},
..Default::default()
};
let set = ConfigSet::load_with_options(&env, None, &opts).expect("load");
assert_eq!(set.get("top.key").as_deref(), Some("override"));
assert_eq!(set.get("fromparam.k").as_deref(), Some("yes"));
}
#[test]
fn parse_error_branches_and_from_path_missing() {
let bad_lines: &[&str] = &[
"[s]\n\t!!!garbage\n",
"[s]\n\t1bad = x\n",
"[s]\n\tkey = \"unclosed\n",
"[bad section\n\tk = 1\n",
"[s]\n\tfetch.negotiationalgorithm\n",
"[s]\n\tkey = line1 \\\n\t\tline2 \\\n\t\tline3\n",
];
for content in bad_lines {
let _ = ConfigFile::parse(std::path::Path::new("c"), content, ConfigScope::Local);
}
assert!(ConfigFile::parse(
std::path::Path::new("c"),
"[s]\n\tkey = \"unclosed\n",
ConfigScope::Local
)
.is_err());
let dir = tempdir().expect("tempdir");
let missing = dir.path().join("nope.conf");
assert!(ConfigFile::from_path(&missing, ConfigScope::Local)
.expect("io")
.is_none());
}
#[test]
fn includeif_onbranch_misses_when_branch_differs() {
let dir = tempdir().expect("tempdir");
Repository::init(
dir.path(),
&InitOptions::new()
.with_initial_branch("other".to_owned())
.with_ref_storage(grit_lib::RefStorageFormat::Files),
)
.expect("init");
let git_dir = dir.path().join(".git");
std::fs::write(
git_dir.join("config"),
"[includeIf \"onbranch:main\"]\n\tpath = miss.conf\n",
)
.expect("cfg");
std::fs::write(git_dir.join("miss.conf"), "[miss]\n\tk = 1\n").expect("miss");
let env = Environment::empty();
let set = ConfigSet::load_with_options(
&env,
Some(&git_dir),
&grit_lib::config::LoadConfigOptions {
include_system: false,
process_includes: true,
command_includes: true,
include_ctx: grit_lib::config::IncludeContext {
git_dir: Some(git_dir.clone()),
..Default::default()
},
..Default::default()
},
)
.expect("load");
assert!(set.get("miss.k").is_none());
}