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;