1use std::path::{Path, PathBuf};
10
11pub const PIN_FILE: &str = "varve.toml";
13
14pub fn find_pin(start: &Path) -> Option<PathBuf> {
16 let mut dir = Some(start);
17 while let Some(d) = dir {
18 let candidate = d.join(PIN_FILE);
19 if candidate.is_file() {
20 return Some(candidate);
21 }
22 dir = d.parent();
23 }
24 None
25}
26
27#[cfg(test)]
28mod tests {
29 use super::*;
30 use std::fs;
31
32 #[test]
34 fn finds_pin_in_the_starting_directory() {
35 let tmp = tempfile::tempdir().unwrap();
36 let pin = tmp.path().join("varve.toml");
37 fs::write(&pin, "").unwrap();
38 assert_eq!(find_pin(tmp.path()), Some(pin));
39 }
40
41 #[test]
43 fn walks_up_to_an_ancestor_pin() {
44 let tmp = tempfile::tempdir().unwrap();
45 let pin = tmp.path().join("varve.toml");
46 fs::write(&pin, "").unwrap();
47 let deep = tmp.path().join("a/b/c");
48 fs::create_dir_all(&deep).unwrap();
49 assert_eq!(find_pin(&deep), Some(pin));
50 }
51
52 #[test]
54 fn nearest_pin_wins() {
55 let tmp = tempfile::tempdir().unwrap();
56 fs::write(tmp.path().join("varve.toml"), "").unwrap();
57 let sub = tmp.path().join("sub");
58 fs::create_dir_all(&sub).unwrap();
59 let near = sub.join("varve.toml");
60 fs::write(&near, "").unwrap();
61 assert_eq!(find_pin(&sub), Some(near));
62 }
63
64 #[test]
66 fn no_pin_means_none_not_a_default() {
67 let tmp = tempfile::tempdir().unwrap();
68 let deep = tmp.path().join("x/y");
69 fs::create_dir_all(&deep).unwrap();
70 assert_eq!(find_pin(&deep), None);
71 }
72}