Skip to main content

gix_attributes/
lib.rs

1//! Parse `.gitattribute` files and provide utilities to match against them.
2//!
3//! ## Examples
4//!
5//! ```
6//! use gix_attributes::search::{MetadataCollection, Outcome};
7//! use gix_glob::pattern::Case;
8//!
9//! let mut search = gix_attributes::Search::default();
10//! let mut collection = MetadataCollection::default();
11//! search.add_patterns_buffer(
12//!     b"*.sh text eol=lf",
13//!     "<memory>".into(),
14//!     None,
15//!     &mut collection,
16//!     true,
17//! );
18//!
19//! let mut out = Outcome::default();
20//! out.initialize_with_selection(&collection, ["text", "eol"]);
21//! assert!(search.pattern_matching_relative_path("script.sh".into(), Case::Sensitive, Some(false), &mut out));
22//!
23//! let assignments = out
24//!     .iter_selected()
25//!     .map(|m| m.assignment.to_string())
26//!     .collect::<Vec<_>>();
27//! assert_eq!(assignments, vec!["text", "eol=lf"]);
28//! ```
29//!
30//! ## Feature Flags
31#![cfg_attr(
32    all(doc, feature = "document-features"),
33    doc = ::document_features::document_features!()
34)]
35#![cfg_attr(all(doc, feature = "document-features"), feature(doc_cfg))]
36#![deny(missing_docs)]
37#![forbid(unsafe_code)]
38
39pub use gix_glob as glob;
40
41mod assignment;
42///
43pub mod name;
44///
45pub mod state;
46
47///
48pub mod search;
49
50///
51pub mod parse;
52
53/// Parse attribute assignments line by line from `bytes`, and fail the operation on error.
54///
55/// For leniency, ignore errors using `filter_map(Result::ok)` for example.
56pub fn parse(bytes: &[u8]) -> parse::Lines<'_> {
57    parse::Lines::new(bytes)
58}
59
60/// The state an attribute can be in, referencing the value.
61///
62/// Note that this doesn't contain the name.
63#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
64#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
65pub enum StateRef<'a> {
66    /// The attribute is listed, or has the special value 'true'
67    Set,
68    /// The attribute has the special value 'false', or was prefixed with a `-` sign.
69    Unset,
70    /// The attribute is set to the given value, which followed the `=` sign.
71    /// Note that values can be empty.
72    #[cfg_attr(feature = "serde", serde(borrow))]
73    Value(state::ValueRef<'a>),
74    /// The attribute isn't mentioned with a given path or is explicitly set to `Unspecified` using the `!` sign.
75    Unspecified,
76}
77
78/// The state an attribute can be in, owning the value.
79///
80/// Note that this doesn't contain the name.
81#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
82#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
83pub enum State {
84    /// The attribute is listed, or has the special value 'true'
85    Set,
86    /// The attribute has the special value 'false', or was prefixed with a `-` sign.
87    Unset,
88    /// The attribute is set to the given value, which followed the `=` sign.
89    /// Note that values can be empty.
90    Value(state::Value),
91    /// The attribute isn't mentioned with a given path or is explicitly set to `Unspecified` using the `!` sign.
92    Unspecified,
93}
94
95/// Represents a validated attribute name.
96///
97/// Enable the `parallel` feature to make this type thread-safe. Without it, the name is backed by an `Rc<str>` and is
98/// neither `Send` nor `Sync`; with `parallel`, it is backed by an `Arc<str>` instead.
99#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
100pub struct Name(pub(crate) gix_features::threading::OwnShared<str>);
101
102/// Holds a validated attribute name as a reference
103#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Ord, PartialOrd)]
104pub struct NameRef<'a>(&'a str);
105
106/// Name an attribute and describe it's assigned state.
107#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
108#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
109pub struct Assignment {
110    /// The validated name of the attribute.
111    pub name: Name,
112    /// The state of the attribute.
113    pub state: State,
114}
115
116/// Holds validated attribute data as a reference
117#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Ord, PartialOrd)]
118pub struct AssignmentRef<'a> {
119    /// The name of the attribute.
120    pub name: NameRef<'a>,
121    /// The state of the attribute.
122    pub state: StateRef<'a>,
123}
124
125/// A grouping of lists of patterns while possibly keeping associated to their base path in order to find matches.
126///
127/// Pattern lists with base path are queryable relative to that base, otherwise they are relative to the repository root.
128#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Default)]
129pub struct Search {
130    /// A list of pattern lists, each representing a patterns from a file or specified by hand, in the order they were
131    /// specified in.
132    ///
133    /// When matching, this order is reversed.
134    patterns: Vec<gix_glob::search::pattern::List<search::Attributes>>,
135}
136
137/// A list of known global sources for git attribute files in order of ascending precedence.
138///
139/// This means that values from the first variant will be returned first.
140#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
141pub enum Source {
142    /// The attribute file that the installation itself ships with.
143    GitInstallation,
144    /// System-wide attributes file. This is typically defined as
145    /// `$(prefix)/etc/gitattributes` (where prefix is the git-installation directory).
146    System,
147    /// This is `<xdg-config-home>/git/attributes` and is git application configuration per user.
148    ///
149    /// Note that there is no `~/.gitattributes` file.
150    Git,
151    /// The configuration of the repository itself, located in `$GIT_DIR/info/attributes`.
152    Local,
153}
154
155mod source;