Sebastian Thiel[git-diff] refactor087e8535 years agoHistory
93 lines · 2.8 KB · Rust
RawDownload
use crate::{tree::visit, tree::visit::Action};use git_hash::ObjectId;use git_object::{    bstr::{BStr, BString, ByteSlice, ByteVec},    immutable, tree,};use std::collections::VecDeque; /// An owned entry as observed by a call to [`visit_(tree|nontree)(…)`][visit::Visit::visit_tree()], enhanced with the full path to it./// Otherwise similar to [`immutable::tree::Entry`][git_object::immutable::tree::Entry].#[derive(Clone, Debug, PartialEq, Eq)]pub struct Entry {    /// The kind of entry, similar to entries in a unix directory tree.    pub mode: tree::EntryMode,    /// The full path to the entry. A root entry would be `d`, and a file `a` within the directory would be `d/a`.    ///    /// This is independent of the platform and the path separators actually used there.    pub filepath: BString,    /// The id of the entry which can be used to locate it in an object database.    pub oid: ObjectId,} impl Entry {    fn new(entry: &immutable::tree::Entry<'_>, filepath: BString) -> Self {        Entry {            filepath,            oid: entry.oid.to_owned(),            mode: entry.mode,        }    }} /// A [Visit][visit::Visit] implementation to record every observed change and keep track of the changed paths.#[derive(Clone, Debug, Default)]pub struct Recorder {    path_deque: VecDeque<BString>,    path: BString,    /// The observed entries.    pub records: Vec<Entry>,} impl Recorder {    fn pop_element(&mut self) {        if let Some(pos) = self.path.rfind_byte(b'/') {            self.path.resize(pos, 0);        } else {            self.path.clear();        }    }     fn push_element(&mut self, name: &BStr) {        if !self.path.is_empty() {            self.path.push(b'/');        }        self.path.push_str(name);    }     fn path_clone(&self) -> BString {        self.path.clone()    }} impl visit::Visit for Recorder {    fn pop_front_tracked_path_and_set_current(&mut self) {        self.path = self            .path_deque            .pop_front()            .expect("every call is matched with push_tracked_path_component");    }     fn push_back_tracked_path_component(&mut self, component: &BStr) {        self.push_element(component);        self.path_deque.push_back(self.path.clone());    }     fn push_path_component(&mut self, component: &BStr) {        self.push_element(component);    }     fn pop_path_component(&mut self) {        self.pop_element();    }     fn visit_tree(&mut self, entry: &immutable::tree::Entry<'_>) -> Action {        self.records.push(Entry::new(entry, self.path_clone()));        Action::Continue    }     fn visit_nontree(&mut self, entry: &immutable::tree::Entry<'_>) -> Action {        self.records.push(Entry::new(entry, self.path_clone()));        Action::Continue    }}