1 //! Parse [path specifications](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefpathspecapathspec) and
2 //! see if a path matches.
3 #![deny(missing_docs, rust_2018_idioms)]
4 #![forbid(unsafe_code)]
6 use std
::path
::PathBuf
;
8 use bitflags
::bitflags
;
10 /// `gix-glob` types are available through [`attributes::glob`].
11 pub use gix_attributes
as attributes
;
15 use std
::path
::PathBuf
;
17 /// The error returned by [Pattern::normalize()](super::Pattern::normalize()).
18 #[derive(Debug, thiserror::Error)]
19 #[allow(missing_docs)]
21 #[error("The path '{}' is not inside of the worktree '{}'", path.display(), worktree_path.display())]
22 AbsolutePathOutsideOfWorktree { path: PathBuf, worktree_path: PathBuf }
,
23 #[error("The path '{}' leaves the repository", path.display())]
24 OutsideOfWorktree { path: PathBuf }
,
36 /// Default settings for some fields of a [`Pattern`].
38 /// These can be used to represent `GIT_*_PATHSPECS` environment variables, for example.
39 #[derive(Debug, Default, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
41 /// The default signature.
42 pub signature
: MagicSignature
,
43 /// The default search-mode.
45 /// Note that even if it's [`SearchMode::Literal`], the pathspecs will be parsed as usual, but matched verbatim afterwards.
47 /// Note that pathspecs can override this the [`SearchMode::Literal`] variant with an explicit `:(glob)` prefix.
48 pub search_mode
: SearchMode
,
49 /// If set, the pathspec will not be parsed but used verbatim. Implies [`SearchMode::Literal`] for `search_mode`.
56 /// A lists of pathspec patterns, possibly from a file.
58 /// Pathspecs are generally relative to the root of the repository.
59 #[derive(Debug, Clone)]
61 /// Patterns and their associated data in the order they were loaded in or specified,
62 /// the line number in its source file or its sequence number (_`(pattern, value, line_number)`_).
64 /// During matching, this order is reversed.
65 patterns
: Vec
<gix_glob
::search
::pattern
::Mapping
<search
::Spec
>>,
67 /// The path from which the patterns were read, or `None` if the patterns
68 /// don't originate in a file on disk.
69 pub source
: Option
<PathBuf
>,
71 /// If `true`, this means all `patterns` are exclude patterns. This means that if there is no match
72 /// (which would exclude an item), we would actually match it for lack of exclusion.
73 all_patterns_are_excluded
: bool
,
74 /// The amount of bytes that are in common among all `patterns` and that aren't matched case-insensitively
75 common_prefix_len
: usize,
78 /// The output of a pathspec [parsing][parse()] operation. It can be used to match against a one or more paths.
79 #[derive(Default, PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
81 /// The path part of a pathspec, which is typically a path possibly mixed with glob patterns.
82 /// Note that it might be an empty string as well.
84 /// For example, `:(top,literal,icase,attr,exclude)some/path` would yield `some/path`.
86 /// All magic signatures that were included in the pathspec.
87 pub signature
: MagicSignature
,
88 /// The search mode of the pathspec.
89 pub search_mode
: SearchMode
,
90 /// All attributes that were included in the `ATTR` part of the pathspec, if present.
92 /// `:(attr:a=one b=):path` would yield attribute `a` and `b`.
93 pub attributes
: Vec
<gix_attributes
::Assignment
>,
94 /// If `true`, we are a special Nil pattern and always match.
96 /// The length of bytes in `path` that belong to the prefix, which will always be matched case-sensitively
97 /// on case-sensitive filesystems.
99 /// That way, even though pathspecs are applied from the top, we can emulate having changed directory into
100 /// a specific sub-directory in a case-sensitive file-system, even if the rest of the pathspec can be set to
101 /// match case-insensitively.
102 /// Is set by [Pattern::normalize()].
107 /// Flags to represent 'magic signatures' which are parsed behind colons, like `:top:`.
108 #[derive(Default, PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
109 pub struct MagicSignature
: u32 {
110 /// Matches patterns from the root of the repository
112 /// Matches patterns in case insensitive mode
113 const ICASE
= 1 << 1;
114 /// Excludes the matching patterns from the previous results
115 const EXCLUDE
= 1 << 2;
116 /// The pattern must match a directory, and not a file.
117 /// This is equivalent to how it's handled in `gix-glob`
118 const MUST_BE_DIR
= 1 << 3;
122 /// Parts of [magic signatures][MagicSignature] which don't stack as they all configure
123 /// the way path specs are matched.
124 #[derive(Default, PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
125 pub enum SearchMode
{
126 /// Expand special characters like `*` similar to how the shell would do it.
128 /// See [`PathAwareGlob`](SearchMode::PathAwareGlob) for the alternative.
131 /// Special characters in the pattern, like `*` or `?`, are treated literally, effectively turning off globbing.
133 /// A single `*` will not match a `/` in the pattern, but a `**` will
137 /// Parse a git-style pathspec into a [`Pattern`][Pattern],
138 /// setting the given `default` values in case these aren't specified in `input`.
140 /// Note that empty [paths](Pattern::path) are allowed here, and generally some processing has to be performed.
141 pub fn parse(input
: &[u8], default: Defaults
) -> Result
<Pattern
, parse
::Error
> {
142 Pattern
::from_bytes(input
, default)