gix_traverse/tree/mod.rs
1use std::collections::VecDeque;
2
3use gix_object::bstr::{BStr, BString};
4
5/// A trait to allow responding to a traversal designed to observe all entries in a tree, recursively while keeping track of
6/// paths if desired.
7pub trait Visit {
8 /// Sets the full path in the back of the queue so future calls to push and pop components affect it instead.
9 ///
10 /// Note that the first call is made without an accompanying call to [`Self::push_back_tracked_path_component()`]
11 ///
12 /// This is used by the depth-first traversal of trees.
13 fn pop_back_tracked_path_and_set_current(&mut self);
14 /// Sets the full path in front of the queue so future calls to push and pop components affect it instead.
15 ///
16 /// This is used by the breadth-first traversal of trees.
17 fn pop_front_tracked_path_and_set_current(&mut self);
18 /// Append a `component` to the end of a path, which may be empty.
19 ///
20 /// If `component` is empty, store the current path.
21 fn push_back_tracked_path_component(&mut self, component: &BStr);
22 /// Append a `component` to the end of a path, which may be empty.
23 fn push_path_component(&mut self, component: &BStr);
24 /// Removes the last component from the path, which may leave it empty.
25 fn pop_path_component(&mut self);
26
27 /// Observe a tree entry that is a tree and return an instruction whether to continue or not.
28 /// [`Action::Skip`][visit::Action::Skip] can be used to prevent traversing it, for example if it's known to the caller already.
29 ///
30 /// The implementation may use the current path to learn where in the tree the change is located.
31 fn visit_tree(&mut self, entry: &gix_object::tree::EntryRef<'_>) -> visit::Action;
32
33 /// Observe a tree entry that is NO tree and return an instruction whether to continue or not.
34 /// [`Action::Skip`][visit::Action::Skip] has no effect here.
35 ///
36 /// The implementation may use the current path to learn where in the tree the change is located.
37 fn visit_nontree(&mut self, entry: &gix_object::tree::EntryRef<'_>) -> visit::Action;
38}
39
40/// A [Visit] implementation to record every observed change and keep track of the changed paths.
41///
42/// Recorders can also be instructed to track the filename only, or no location at all.
43#[derive(Clone, Debug)]
44pub struct Recorder {
45 path_deque: VecDeque<BString>,
46 path: BString,
47 /// How to track the location.
48 location: Option<recorder::Location>,
49 /// The observed entries.
50 pub records: Vec<recorder::Entry>,
51}
52
53///
54pub mod visit {
55 /// What to do after an entry was [recorded][super::Visit::visit_tree()].
56 #[derive(Clone, Copy, PartialOrd, PartialEq, Ord, Eq, Hash)]
57 pub enum Action {
58 /// Continue the traversal of entries.
59 Continue,
60 /// Stop the traversal of entries, making this the last call to [`visit_(tree|nontree)(…)`][super::Visit::visit_nontree()].
61 Cancel,
62 /// Don't dive into the entry, skipping children effectively. Only useful in [`visit_tree(…)`][super::Visit::visit_tree()].
63 Skip,
64 }
65
66 impl Action {
67 /// Returns true if this action means to stop the traversal.
68 pub fn cancelled(&self) -> bool {
69 matches!(self, Action::Cancel)
70 }
71 }
72}
73
74///
75pub mod recorder;
76
77///
78pub mod breadthfirst;
79pub use breadthfirst::function::breadthfirst;
80
81///
82pub mod depthfirst;
83pub use depthfirst::function::depthfirst;