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;