git_traverse/tree/
recorder.rs

1use git_hash::ObjectId;
2use git_object::{
3    bstr::{BStr, BString, ByteSlice, ByteVec},
4    tree,
5};
6
7use crate::tree::{visit::Action, Recorder, Visit};
8
9/// An owned entry as observed by a call to [`visit_(tree|nontree)(…)`][Visit::visit_tree()], enhanced with the full path to it.
10/// Otherwise similar to [`git_object::tree::EntryRef`].
11#[derive(Clone, Debug, PartialEq, Eq)]
12pub struct Entry {
13    /// The kind of entry, similar to entries in a unix directory tree.
14    pub mode: tree::EntryMode,
15    /// The full path to the entry. A root entry would be `d`, and a file `a` within the directory would be `d/a`.
16    ///
17    /// This is independent of the platform and the path separators actually used there.
18    pub filepath: BString,
19    /// The id of the entry which can be used to locate it in an object database.
20    pub oid: ObjectId,
21}
22
23impl Entry {
24    fn new(entry: &tree::EntryRef<'_>, filepath: BString) -> Self {
25        Entry {
26            filepath,
27            oid: entry.oid.to_owned(),
28            mode: entry.mode,
29        }
30    }
31}
32
33impl Recorder {
34    fn pop_element(&mut self) {
35        if let Some(pos) = self.path.rfind_byte(b'/') {
36            self.path.resize(pos, 0);
37        } else {
38            self.path.clear();
39        }
40    }
41
42    fn push_element(&mut self, name: &BStr) {
43        if !self.path.is_empty() {
44            self.path.push(b'/');
45        }
46        self.path.push_str(name);
47    }
48
49    fn path_clone(&self) -> BString {
50        self.path.clone()
51    }
52}
53
54impl Visit for Recorder {
55    fn pop_front_tracked_path_and_set_current(&mut self) {
56        self.path = self
57            .path_deque
58            .pop_front()
59            .expect("every call is matched with push_tracked_path_component");
60    }
61
62    fn push_back_tracked_path_component(&mut self, component: &BStr) {
63        self.push_element(component);
64        self.path_deque.push_back(self.path.clone());
65    }
66
67    fn push_path_component(&mut self, component: &BStr) {
68        self.push_element(component);
69    }
70
71    fn pop_path_component(&mut self) {
72        self.pop_element();
73    }
74
75    fn visit_tree(&mut self, entry: &tree::EntryRef<'_>) -> Action {
76        self.records.push(Entry::new(entry, self.path_clone()));
77        Action::Continue
78    }
79
80    fn visit_nontree(&mut self, entry: &tree::EntryRef<'_>) -> Action {
81        self.records.push(Entry::new(entry, self.path_clone()));
82        Action::Continue
83    }
84}