diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
commit | 9835e2ae736235810b4ea1c162ca5e65c547e770 (patch) | |
tree | 3fcebf40ed70e581d776a8a4c65923e8ec20e026 /vendor/gix-worktree/src/cache/mod.rs | |
parent | Releasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff) | |
download | rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip |
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/gix-worktree/src/cache/mod.rs')
-rw-r--r-- | vendor/gix-worktree/src/cache/mod.rs | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/vendor/gix-worktree/src/cache/mod.rs b/vendor/gix-worktree/src/cache/mod.rs new file mode 100644 index 000000000..7984b2c4c --- /dev/null +++ b/vendor/gix-worktree/src/cache/mod.rs @@ -0,0 +1,178 @@ +#![allow(missing_docs)] +use std::path::{Path, PathBuf}; + +use bstr::{BStr, ByteSlice}; +use gix_hash::oid; + +use super::Cache; +use crate::PathIdMapping; + +/// Various aggregate numbers collected from when the corresponding [`Cache`] was instantiated. +#[derive(Default, Clone, Copy, Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Statistics { + /// The amount of platforms created to do further matching. + pub platforms: usize, + /// Information about the stack delegate. + pub delegate: delegate::Statistics, + /// Information about attributes + pub attributes: state::attributes::Statistics, + /// Information about the ignore stack + pub ignore: state::ignore::Statistics, +} + +#[derive(Clone)] +pub enum State { + /// Useful for checkout where directories need creation, but we need to access attributes as well. + CreateDirectoryAndAttributesStack { + /// If there is a symlink or a file in our path, try to unlink it before creating the directory. + unlink_on_collision: bool, + /// State to handle attribute information + attributes: state::Attributes, + }, + /// Used when adding files, requiring access to both attributes and ignore information, for example during add operations. + AttributesAndIgnoreStack { + /// State to handle attribute information + attributes: state::Attributes, + /// State to handle exclusion information + ignore: state::Ignore, + }, + /// Used when providing worktree status information. + IgnoreStack(state::Ignore), +} + +#[must_use] +pub struct Platform<'a> { + parent: &'a Cache, + is_dir: Option<bool>, +} + +/// Initialization +impl Cache { + /// Create a new instance with `worktree_root` being the base for all future paths we match. + /// `state` defines the capabilities of the cache. + /// The `case` configures attribute and exclusion case sensitivity at *query time*, which should match the case that + /// `state` might be configured with. + /// `buf` is used when reading files, and `id_mappings` should have been created with [State::id_mappings_from_index()]. + pub fn new( + worktree_root: impl Into<PathBuf>, + state: State, + case: gix_glob::pattern::Case, + buf: Vec<u8>, + id_mappings: Vec<PathIdMapping>, + ) -> Self { + let root = worktree_root.into(); + Cache { + stack: gix_fs::Stack::new(root), + state, + case, + buf, + id_mappings, + statistics: Statistics::default(), + } + } +} + +/// Entry points for attribute query +impl Cache { + /// Append the `relative` path to the root directory of the cache and efficiently create leading directories, while assuring that no + /// symlinks are in that path. + /// Unless `is_dir` is known with `Some(…)`, then `relative` points to a directory itself in which case the entire resulting + /// path is created as directory. If it's not known it is assumed to be a file. + /// `find` maybe used to lookup objects from an [id mapping][crate::cache::State::id_mappings_from_index()], with mappnigs + /// + /// Provide access to cached information for that `relative` path via the returned platform. + pub fn at_path<Find, E>( + &mut self, + relative: impl AsRef<Path>, + is_dir: Option<bool>, + find: Find, + ) -> std::io::Result<Platform<'_>> + where + Find: for<'a> FnMut(&oid, &'a mut Vec<u8>) -> Result<gix_object::BlobRef<'a>, E>, + E: std::error::Error + Send + Sync + 'static, + { + self.statistics.platforms += 1; + let mut delegate = StackDelegate { + state: &mut self.state, + buf: &mut self.buf, + is_dir: is_dir.unwrap_or(false), + id_mappings: &self.id_mappings, + find, + case: self.case, + statistics: &mut self.statistics, + }; + self.stack.make_relative_path_current(relative, &mut delegate)?; + Ok(Platform { parent: self, is_dir }) + } + + /// Obtain a platform for lookups from a repo-`relative` path, typically obtained from an index entry. `is_dir` should reflect + /// whether it's a directory or not, or left at `None` if unknown. + /// `find` maybe used to lookup objects from an [id mapping][crate::cache::State::id_mappings_from_index()]. + /// All effects are similar to [`at_path()`][Self::at_path()]. + /// + /// If `relative` ends with `/` and `is_dir` is `None`, it is automatically assumed to be a directory. + /// + /// ### Panics + /// + /// on illformed UTF8 in `relative` + pub fn at_entry<'r, Find, E>( + &mut self, + relative: impl Into<&'r BStr>, + is_dir: Option<bool>, + find: Find, + ) -> std::io::Result<Platform<'_>> + where + Find: for<'a> FnMut(&oid, &'a mut Vec<u8>) -> Result<gix_object::BlobRef<'a>, E>, + E: std::error::Error + Send + Sync + 'static, + { + let relative = relative.into(); + let relative_path = gix_path::from_bstr(relative); + + self.at_path( + relative_path, + is_dir.or_else(|| relative.ends_with_str("/").then_some(true)), + find, + ) + } +} + +/// Mutation +impl Cache { + /// Reset the statistics after returning them. + pub fn take_statistics(&mut self) -> Statistics { + std::mem::take(&mut self.statistics) + } + + /// Return our state for applying changes. + pub fn state_mut(&mut self) -> &mut State { + &mut self.state + } +} + +/// Access +impl Cache { + /// Return the statistics we gathered thus far. + pub fn statistics(&self) -> &Statistics { + &self.statistics + } + /// Return the state for introspection. + pub fn state(&self) -> &State { + &self.state + } + + /// Return the base path against which all entries or paths should be relative to when querying. + /// + /// Note that this path _may_ not be canonicalized. + pub fn base(&self) -> &Path { + self.stack.root() + } +} + +/// +pub mod delegate; +use delegate::StackDelegate; + +mod platform; +/// +pub mod state; |