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 /// [std::ops::ControlFlow::Break] 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 /// [std::ops::ControlFlow::Break] 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 ///
57 /// Use [`std::ops::ControlFlow::Break`] to stop the traversal of entries, making this the last call to [`visit_(tree|nontree)(…)`](super::Visit::visit_nontree()).
58 /// Use [`std::ops::ControlFlow::Continue`] with `true` to continue the traversal and descend into tree entries.
59 /// Use [`std::ops::ControlFlow::Continue`] with `false` to skip descending into the entry (only useful in [`visit_tree(…)`](super::Visit::visit_tree())).
60 pub type Action = std::ops::ControlFlow<(), bool>;
61}
62
63///
64pub mod recorder;
65
66///
67pub mod breadthfirst;
68pub use breadthfirst::function::breadthfirst;
69
70///
71pub mod depthfirst;
72pub use depthfirst::function::depthfirst;