Skip to main content

difflore_core/infra/
paths.rs

1use std::path::PathBuf;
2
3/// `~/.difflore` (or `$DIFFLORE_HOME` in production / shared test home in
4/// tests). All local data + config files live under this root.
5pub fn data_home() -> Result<PathBuf, String> {
6    crate::infra::db::difflore_dir()
7}
8
9/// Currently equals `data_home()`. Kept as a separate function so a future
10/// split (e.g. honoring XDG `$XDG_CONFIG_HOME`) doesn't break callers.
11pub fn config_home() -> Result<PathBuf, String> {
12    data_home()
13}
14
15/// `<config_home>/config.toml`.
16pub fn config_file() -> Result<PathBuf, String> {
17    Ok(config_home()?.join("config.toml"))
18}
19
20/// Project root: `git rev-parse --show-toplevel`, falling back to cwd.
21pub use crate::infra::db::current_project_root;
22
23#[cfg(test)]
24mod tests {
25    use super::*;
26
27    #[test]
28    fn data_home_resolves_to_existing_dir_under_test_home() {
29        // The shared test home is set up by db.rs's `shared_test_home()`
30        // singleton — `data_home()` must return that path so all test
31        // I/O lands in the per-process tempdir, never the user's real
32        // ~/.difflore.
33        let home = data_home().expect("data_home should resolve in tests");
34        assert!(home.is_absolute(), "expected absolute path, got {home:?}");
35    }
36
37    #[test]
38    fn config_home_equals_data_home() {
39        assert_eq!(config_home().unwrap(), data_home().unwrap());
40    }
41
42    #[test]
43    fn config_file_is_config_toml_under_config_home() {
44        let cfg = config_file().unwrap();
45        assert_eq!(cfg.file_name().unwrap(), "config.toml");
46        assert!(cfg.starts_with(config_home().unwrap()));
47    }
48
49    #[test]
50    fn current_project_root_returns_path() {
51        // Smoke test — must not panic even outside a git checkout.
52        let p = current_project_root();
53        assert!(!p.as_os_str().is_empty());
54    }
55}