diff options
Diffstat (limited to 'vendor/gix-pathspec/src/lib.rs')
-rw-r--r-- | vendor/gix-pathspec/src/lib.rs | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/vendor/gix-pathspec/src/lib.rs b/vendor/gix-pathspec/src/lib.rs new file mode 100644 index 000000000..9f91567da --- /dev/null +++ b/vendor/gix-pathspec/src/lib.rs @@ -0,0 +1,143 @@ +//! Parse [path specifications](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefpathspecapathspec) and +//! see if a path matches. +#![deny(missing_docs, rust_2018_idioms)] +#![forbid(unsafe_code)] + +use std::path::PathBuf; + +use bitflags::bitflags; +use bstr::BString; +/// `gix-glob` types are available through [`attributes::glob`]. +pub use gix_attributes as attributes; + +/// +pub mod normalize { + use std::path::PathBuf; + + /// The error returned by [Pattern::normalize()](super::Pattern::normalize()). + #[derive(Debug, thiserror::Error)] + #[allow(missing_docs)] + pub enum Error { + #[error("The path '{}' is not inside of the worktree '{}'", path.display(), worktree_path.display())] + AbsolutePathOutsideOfWorktree { path: PathBuf, worktree_path: PathBuf }, + #[error("The path '{}' leaves the repository", path.display())] + OutsideOfWorktree { path: PathBuf }, + } +} + +mod pattern; + +/// +pub mod search; + +/// +pub mod parse; + +/// Default settings for some fields of a [`Pattern`]. +/// +/// These can be used to represent `GIT_*_PATHSPECS` environment variables, for example. +#[derive(Debug, Default, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] +pub struct Defaults { + /// The default signature. + pub signature: MagicSignature, + /// The default search-mode. + /// + /// Note that even if it's [`SearchMode::Literal`], the pathspecs will be parsed as usual, but matched verbatim afterwards. + /// + /// Note that pathspecs can override this the [`SearchMode::Literal`] variant with an explicit `:(glob)` prefix. + pub search_mode: SearchMode, + /// If set, the pathspec will not be parsed but used verbatim. Implies [`SearchMode::Literal`] for `search_mode`. + pub literal: bool, +} + +/// +pub mod defaults; + +/// A lists of pathspec patterns, possibly from a file. +/// +/// Pathspecs are generally relative to the root of the repository. +#[derive(Debug, Clone)] +pub struct Search { + /// Patterns and their associated data in the order they were loaded in or specified, + /// the line number in its source file or its sequence number (_`(pattern, value, line_number)`_). + /// + /// During matching, this order is reversed. + patterns: Vec<gix_glob::search::pattern::Mapping<search::Spec>>, + + /// The path from which the patterns were read, or `None` if the patterns + /// don't originate in a file on disk. + pub source: Option<PathBuf>, + + /// If `true`, this means all `patterns` are exclude patterns. This means that if there is no match + /// (which would exclude an item), we would actually match it for lack of exclusion. + all_patterns_are_excluded: bool, + /// The amount of bytes that are in common among all `patterns` and that aren't matched case-insensitively + common_prefix_len: usize, +} + +/// The output of a pathspec [parsing][parse()] operation. It can be used to match against a one or more paths. +#[derive(Default, PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] +pub struct Pattern { + /// The path part of a pathspec, which is typically a path possibly mixed with glob patterns. + /// Note that it might be an empty string as well. + /// + /// For example, `:(top,literal,icase,attr,exclude)some/path` would yield `some/path`. + path: BString, + /// All magic signatures that were included in the pathspec. + pub signature: MagicSignature, + /// The search mode of the pathspec. + pub search_mode: SearchMode, + /// All attributes that were included in the `ATTR` part of the pathspec, if present. + /// + /// `:(attr:a=one b=):path` would yield attribute `a` and `b`. + pub attributes: Vec<gix_attributes::Assignment>, + /// If `true`, we are a special Nil pattern and always match. + nil: bool, + /// The length of bytes in `path` that belong to the prefix, which will always be matched case-sensitively + /// on case-sensitive filesystems. + /// + /// That way, even though pathspecs are applied from the top, we can emulate having changed directory into + /// a specific sub-directory in a case-sensitive file-system, even if the rest of the pathspec can be set to + /// match case-insensitively. + /// Is set by [Pattern::normalize()]. + prefix_len: usize, +} + +bitflags! { + /// Flags to represent 'magic signatures' which are parsed behind colons, like `:top:`. + #[derive(Default, PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)] + pub struct MagicSignature: u32 { + /// Matches patterns from the root of the repository + const TOP = 1 << 0; + /// Matches patterns in case insensitive mode + const ICASE = 1 << 1; + /// Excludes the matching patterns from the previous results + const EXCLUDE = 1 << 2; + /// The pattern must match a directory, and not a file. + /// This is equivalent to how it's handled in `gix-glob` + const MUST_BE_DIR = 1 << 3; + } +} + +/// Parts of [magic signatures][MagicSignature] which don't stack as they all configure +/// the way path specs are matched. +#[derive(Default, PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)] +pub enum SearchMode { + /// Expand special characters like `*` similar to how the shell would do it. + /// + /// See [`PathAwareGlob`](SearchMode::PathAwareGlob) for the alternative. + #[default] + ShellGlob, + /// Special characters in the pattern, like `*` or `?`, are treated literally, effectively turning off globbing. + Literal, + /// A single `*` will not match a `/` in the pattern, but a `**` will + PathAwareGlob, +} + +/// Parse a git-style pathspec into a [`Pattern`][Pattern], +/// setting the given `default` values in case these aren't specified in `input`. +/// +/// Note that empty [paths](Pattern::path) are allowed here, and generally some processing has to be performed. +pub fn parse(input: &[u8], default: Defaults) -> Result<Pattern, parse::Error> { + Pattern::from_bytes(input, default) +} |