diff --git a/tests/tools/src/lib.rs b/tests/tools/src/lib.rs index d4f1b2766a9..e190a1ac58b 100644 --- a/tests/tools/src/lib.rs +++ b/tests/tools/src/lib.rs @@ -583,12 +583,16 @@ fn scripted_fixture_read_only_with_args_inner( Ok(script_result_directory) } +#[cfg(windows)] +const NULL_DEVICE: &str = "NUL"; +#[cfg(not(windows))] +const NULL_DEVICE: &str = "/dev/null"; + fn configure_command<'a>( cmd: &'a mut std::process::Command, args: &[String], script_result_directory: &Path, ) -> &'a mut std::process::Command { - let never_path = if cfg!(windows) { "-" } else { ":" }; let mut msys_for_git_bash_on_windows = std::env::var("MSYS").unwrap_or_default(); msys_for_git_bash_on_windows.push_str(" winsymlinks:nativestrict"); cmd.args(args) @@ -599,8 +603,8 @@ fn configure_command<'a>( .env_remove("GIT_ASKPASS") .env_remove("SSH_ASKPASS") .env("MSYS", msys_for_git_bash_on_windows) - .env("GIT_CONFIG_SYSTEM", never_path) - .env("GIT_CONFIG_GLOBAL", never_path) + .env("GIT_CONFIG_SYSTEM", NULL_DEVICE) + .env("GIT_CONFIG_GLOBAL", NULL_DEVICE) .env("GIT_TERMINAL_PROMPT", "false") .env("GIT_AUTHOR_DATE", "2000-01-01 00:00:00 +0000") .env("GIT_AUTHOR_EMAIL", "author@example.com") @@ -882,4 +886,55 @@ mod tests { fn parse_version_with_trailing_newline() { assert_eq!(git_version_from_bytes(b"git version 2.37.2\n").unwrap(), (2, 37, 2)); } + + const SCOPE_ENV_VALUE: &str = "gitconfig"; + + fn populate_ad_hoc_config_files(dir: &Path) { + const CONFIG_DATA: &[u8] = b"[foo]\n\tbar = baz\n"; + + let paths: &[PathBuf] = if cfg!(windows) { + let unc_literal_nul = dir.canonicalize().expect("directory exists").join("NUL"); + &[dir.join(SCOPE_ENV_VALUE), dir.join("-"), unc_literal_nul] + } else { + &[dir.join(SCOPE_ENV_VALUE), dir.join("-"), dir.join(":")] + }; + + // Create the files. + for path in paths { + std::fs::write(path, CONFIG_DATA).expect("can write contents"); + } + + // Verify the files. This is mostly to show we really made a `\\?\...\NUL` on Windows. + for path in paths { + let buf = std::fs::read(path).expect("the file really exists"); + assert_eq!(buf, CONFIG_DATA, "File {path:?} should be created"); + } + } + + fn check_configure_clears_scope(scope_env_key: &str, scope_option: &str) { + let temp = tempfile::TempDir::new().expect("can create temp dir"); + let dir = temp.path(); + populate_ad_hoc_config_files(dir); + + let mut cmd = std::process::Command::new("git"); + cmd.env(scope_env_key, SCOPE_ENV_VALUE); // configure_command() should override it. + let args = ["config", "-l", "--show-origin", scope_option].map(String::from); + configure_command(&mut cmd, &args, dir); + + let output = cmd.output().expect("can run git"); + let stdout = output.stdout.to_str().expect("valid UTF-8"); + let status = output.status.code().expect("terminated normally"); + assert_eq!(stdout, "", "should be no config variables to display"); + assert_eq!(status, 0, "reading the config should nonetheless succeed"); + } + + #[test] + fn configure_command_clears_system_scope() { + check_configure_clears_scope("GIT_CONFIG_SYSTEM", "--system"); + } + + #[test] + fn configure_command_clears_global_scope() { + check_configure_clears_scope("GIT_CONFIG_GLOBAL", "--global"); + } }