use std::path::{Path, PathBuf};
pub const COMMON_ROOT_NAMES: &[&str] = &[
"main.bean",
"main.beancount",
"ledger.bean",
"ledger.beancount",
"journal.bean",
"journal.beancount",
"index.bean",
"index.beancount",
];
#[must_use]
pub fn discover_journal_file(dir: &Path) -> Option<PathBuf> {
for name in COMMON_ROOT_NAMES {
let candidate = dir.join(name);
if candidate.is_file() {
return Some(candidate);
}
}
None
}
#[must_use]
pub fn discover_journal_upward(start: &Path) -> Option<PathBuf> {
let mut dir = Some(start);
while let Some(d) = dir {
if let Some(found) = discover_journal_file(d) {
return Some(found);
}
dir = d.parent();
}
None
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn finds_a_root_beside_the_file_and_prefers_the_nearest() {
let dir = tempfile::tempdir().expect("tempdir");
let outer = dir.path();
let inner = outer.join("sub/deeper");
std::fs::create_dir_all(&inner).expect("mkdir");
std::fs::write(outer.join("main.beancount"), "").expect("write outer");
assert_eq!(
discover_journal_upward(&inner),
Some(outer.join("main.beancount")),
"walks up when nothing is nearer"
);
let nested = outer.join("sub").join("ledger.beancount");
std::fs::write(&nested, "").expect("write inner");
assert_eq!(
discover_journal_upward(&inner),
Some(nested),
"a nearer root wins over an outer one"
);
}
#[test]
fn name_priority_is_stable_and_directories_do_not_count() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::create_dir(dir.path().join("main.bean")).expect("mkdir");
assert_eq!(discover_journal_file(dir.path()), None);
std::fs::write(dir.path().join("journal.beancount"), "").expect("write");
std::fs::write(dir.path().join("main.beancount"), "").expect("write");
assert_eq!(
discover_journal_file(dir.path()),
Some(dir.path().join("main.beancount")),
"`main.beancount` outranks `journal.beancount`"
);
}
#[test]
fn returns_none_when_there_is_no_ledger_anywhere_above() {
let dir = tempfile::tempdir().expect("tempdir");
let deep = dir.path().join("a/b/c");
std::fs::create_dir_all(&deep).expect("mkdir");
assert_eq!(discover_journal_upward(&deep), None);
}
}