use std::path::{Path, PathBuf};
use git_cliff_core::config::Config;
pub fn resolve_config_path(
config: Option<&Path>,
workdir: Option<&Path>,
current_dir: &Path,
user_config: impl FnOnce() -> Option<PathBuf>,
) -> Option<PathBuf> {
match config {
Some(path) if path.exists() => Some(path.to_path_buf()),
Some(_) => user_config(),
None => workdir
.unwrap_or(current_dir)
.ancestors()
.find_map(Config::retrieve_project_config_path)
.or_else(user_config),
}
}
#[cfg(test)]
mod tests {
use std::fs;
use git_cliff_core::DEFAULT_CONFIG;
use git_cliff_core::error::Result;
use pretty_assertions::assert_eq;
use temp_dir::TempDir;
use super::*;
fn temp_dir() -> Result<TempDir> {
Ok(TempDir::with_prefix("git-cliff-")?)
}
fn write_config(dir: &Path) -> Result<PathBuf> {
let path = dir.join(DEFAULT_CONFIG);
fs::write(&path, "[changelog]\n")?;
Ok(path)
}
#[test]
fn explicit_config_is_used_when_it_exists() -> Result<()> {
let config_dir = temp_dir()?;
let current_dir = temp_dir()?;
let config = write_config(config_dir.path())?;
assert_eq!(
Some(config),
resolve_config_path(
Some(&config_dir.path().join(DEFAULT_CONFIG)),
None,
current_dir.path(),
|| None
)
);
Ok(())
}
#[test]
fn missing_explicit_config_skips_discovery_and_uses_the_user_config() -> Result<()> {
let dir = temp_dir()?;
write_config(dir.path())?;
let user_config = dir.path().join("user-cliff.toml");
assert_eq!(
Some(user_config.clone()),
resolve_config_path(
Some(&dir.path().join("does-not-exist.toml")),
None,
dir.path(),
|| Some(user_config.clone())
)
);
Ok(())
}
#[test]
fn config_is_discovered_from_the_working_directory() -> Result<()> {
let workdir = temp_dir()?;
let current_dir = temp_dir()?;
let config = write_config(workdir.path())?;
write_config(current_dir.path())?;
assert_eq!(
Some(config),
resolve_config_path(None, Some(workdir.path()), current_dir.path(), || None)
);
Ok(())
}
#[test]
fn config_is_discovered_from_the_current_directory_without_workdir() -> Result<()> {
let dir = temp_dir()?;
let config = write_config(dir.path())?;
assert_eq!(
Some(config),
resolve_config_path(None, None, dir.path(), || None)
);
Ok(())
}
#[test]
fn config_is_discovered_from_a_parent_directory() -> Result<()> {
let dir = temp_dir()?;
let nested = dir.path().join("nested");
fs::create_dir(&nested)?;
let config = write_config(dir.path())?;
assert_eq!(
Some(config),
resolve_config_path(None, None, &nested, || None)
);
Ok(())
}
#[test]
fn user_config_is_used_when_no_project_config_is_discovered() -> Result<()> {
let dir = temp_dir()?;
let nested = dir.path().join("nested");
fs::create_dir(&nested)?;
assert_eq!(
None,
dir.path()
.ancestors()
.find_map(Config::retrieve_project_config_path),
"a configuration file above the temporary directory defeats this test"
);
let user_config = dir.path().join("user-cliff.toml");
assert_eq!(
Some(user_config.clone()),
resolve_config_path(None, Some(&nested), dir.path(), || Some(
user_config.clone()
))
);
Ok(())
}
}