objects/worktree/
worktree_reserved.rs1use std::path::{Component, Path};
10
11#[must_use]
16pub fn is_reserved_worktree_path(path: &Path) -> bool {
17 first_normal_component(path).is_some_and(|name| name == ".heddle")
18}
19
20#[must_use]
25pub fn is_reserved_directory_child(parent: &Path, name: &str) -> bool {
26 if is_reserved_worktree_path(parent) {
27 return true;
28 }
29 name == ".heddle" && is_worktree_root(parent)
30}
31
32fn is_worktree_root(path: &Path) -> bool {
33 path.as_os_str().is_empty() || path == Path::new(".")
34}
35
36fn first_normal_component(path: &Path) -> Option<&std::ffi::OsStr> {
37 for component in path.components() {
38 match component {
39 Component::CurDir => continue,
40 Component::Normal(name) => return Some(name),
41 Component::ParentDir | Component::Prefix(_) | Component::RootDir => return None,
42 }
43 }
44 None
45}
46
47#[cfg(test)]
48mod tests {
49 use std::path::Path;
50
51 use super::{is_reserved_directory_child, is_reserved_worktree_path};
52
53 #[test]
54 fn reserves_root_heddle_tree_and_identity() {
55 for path in [
56 ".heddle",
57 ".heddle/identity.toml",
58 ".heddle/objects/pack",
59 ".heddle/info/exclude",
60 "./.heddle/identity.toml",
61 ] {
62 assert!(
63 is_reserved_worktree_path(Path::new(path)),
64 "expected reserved: {path}"
65 );
66 }
67 }
68
69 #[test]
70 fn does_not_reserve_nested_or_unrelated_paths() {
71 for path in [
72 "",
73 ".",
74 "src/main.rs",
75 "heddle",
76 ".heddleignore",
77 "examples/calculator/.heddle/identity.toml",
78 "examples/calculator/.heddle",
79 "../.heddle/identity.toml",
80 ] {
81 assert!(
82 !is_reserved_worktree_path(Path::new(path)),
83 "expected not reserved: {path}"
84 );
85 }
86 }
87
88 #[test]
89 fn directory_child_reserves_root_heddle_and_descendants() {
90 assert!(is_reserved_directory_child(Path::new(""), ".heddle"));
91 assert!(is_reserved_directory_child(Path::new("."), ".heddle"));
92 assert!(is_reserved_directory_child(
93 Path::new(".heddle"),
94 "identity.toml"
95 ));
96 assert!(!is_reserved_directory_child(Path::new(""), "src"));
97 assert!(!is_reserved_directory_child(
98 Path::new("examples/calculator"),
99 ".heddle"
100 ));
101 }
102}