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, rust_2018_idioms)]
37#![forbid(unsafe_code)]
38
39pub use gix_glob as glob;
40use kstring::{KString, KStringRef};
41
42mod assignment;
43///
44pub mod name;
45///
46pub mod state;
47
48///
49pub mod search;
50
51///
52pub mod parse;
53
54/// Parse attribute assignments line by line from `bytes`, and fail the operation on error.
55///
56/// For leniency, ignore errors using `filter_map(Result::ok)` for example.
57pub fn parse(bytes: &[u8]) -> parse::Lines<'_> {
58    parse::Lines::new(bytes)
59}
60
61/// The state an attribute can be in, referencing the value.
62///
63/// Note that this doesn't contain the name.
64#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
65#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
66pub enum StateRef<'a> {
67    /// The attribute is listed, or has the special value 'true'
68    Set,
69    /// The attribute has the special value 'false', or was prefixed with a `-` sign.
70    Unset,
71    /// The attribute is set to the given value, which followed the `=` sign.
72    /// Note that values can be empty.
73    #[cfg_attr(feature = "serde", serde(borrow))]
74    Value(state::ValueRef<'a>),
75    /// The attribute isn't mentioned with a given path or is explicitly set to `Unspecified` using the `!` sign.
76    Unspecified,
77}
78
79/// The state an attribute can be in, owning the value.
80///
81/// Note that this doesn't contain the name.
82#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
83#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
84pub enum State {
85    /// The attribute is listed, or has the special value 'true'
86    Set,
87    /// The attribute has the special value 'false', or was prefixed with a `-` sign.
88    Unset,
89    /// The attribute is set to the given value, which followed the `=` sign.
90    /// Note that values can be empty.
91    Value(state::Value),
92    /// The attribute isn't mentioned with a given path or is explicitly set to `Unspecified` using the `!` sign.
93    Unspecified,
94}
95
96/// Represents a validated attribute name
97#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
98#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
99pub struct Name(pub(crate) KString);
100
101/// Holds a validated attribute name as a reference
102#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Ord, PartialOrd)]
103pub struct NameRef<'a>(KStringRef<'a>);
104
105/// Name an attribute and describe it's assigned state.
106#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
107#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
108pub struct Assignment {
109    /// The validated name of the attribute.
110    pub name: Name,
111    /// The state of the attribute.
112    pub state: State,
113}
114
115/// Holds validated attribute data as a reference
116#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Ord, PartialOrd)]
117pub struct AssignmentRef<'a> {
118    /// The name of the attribute.
119    pub name: NameRef<'a>,
120    /// The state of the attribute.
121    pub state: StateRef<'a>,
122}
123
124/// A grouping of lists of patterns while possibly keeping associated to their base path in order to find matches.
125///
126/// Pattern lists with base path are queryable relative to that base, otherwise they are relative to the repository root.
127#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Default)]
128pub struct Search {
129    /// A list of pattern lists, each representing a patterns from a file or specified by hand, in the order they were
130    /// specified in.
131    ///
132    /// When matching, this order is reversed.
133    patterns: Vec<gix_glob::search::pattern::List<search::Attributes>>,
134}
135
136/// A list of known global sources for git attribute files in order of ascending precedence.
137///
138/// This means that values from the first variant will be returned first.
139#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
140pub enum Source {
141    /// The attribute file that the installation itself ships with.
142    GitInstallation,
143    /// System-wide attributes file. This is typically defined as
144    /// `$(prefix)/etc/gitattributes` (where prefix is the git-installation directory).
145    System,
146    /// This is `<xdg-config-home>/git/attributes` and is git application configuration per user.
147    ///
148    /// Note that there is no `~/.gitattributes` file.
149    Git,
150    /// The configuration of the repository itself, located in `$GIT_DIR/info/attributes`.
151    Local,
152}
153
154mod source;