1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
use std::collections::{HashMap, VecDeque};

use git_features::threading::OwnShared;

use crate::{
    color, file,
    file::{Metadata, SectionBodyIdsLut, SectionId},
    integer,
    parse::section,
};

/// A list of known sources for git configuration in order of ascending precedence.
///
/// This means values from the first one will be overridden by values in the second one, and so forth.
/// Note that included files via `include.path` and `includeIf.<condition>.path` inherit
/// their source.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub enum Source {
    /// System-wide configuration path. This is defined as
    /// `$(prefix)/etc/gitconfig` (where prefix is the git-installation directory).
    System,
    /// A platform defined location for where a user's git application configuration should be located.
    /// If `$XDG_CONFIG_HOME` is not set or empty, `$HOME/.config/git/config` will be used
    /// on unix.
    Git,
    /// This is usually `~/.gitconfig` on unix.
    User,
    /// The configuration of the repository itself, located in `.git/config`.
    Local,
    /// Configuration specific to a worktree as created with `git worktree` and
    /// typically located in `$GIT_DIR/config.worktree` if `extensions.worktreeConfig`
    /// is enabled.
    Worktree,
    /// values parsed from the environment.
    Env,
    /// Values set from the command-line.
    Cli,
    /// Entirely internal from a programmatic source
    Api,
}

/// High level `git-config` reader and writer.
///
/// This is the full-featured implementation that can deserialize, serialize,
/// and edit `git-config` files without loss of whitespace or comments.
///
/// # 'multivar' behavior
///
/// `git` is flexible enough to allow users to set a key multiple times in
/// any number of identically named sections. When this is the case, the key
/// is known as a _"multivar"_. In this case, [`raw_value()`] follows the
/// "last one wins".
///
/// Concretely, the following config has a multivar, `a`, with the values
/// of `b`, `c`, and `d`, while `e` is a single variable with the value
/// `f g h`.
///
/// ```text
/// [core]
///     a = b
///     a = c
/// [core]
///     a = d
///     e = f g h
/// ```
///
/// Calling methods that fetch or set only one value (such as [`raw_value()`])
/// key `a` with the above config will fetch `d` or replace `d`, since the last
/// valid config key/value pair is `a = d`:
///
/// # Filtering
///
/// All methods exist in a `*_filter(…, filter)` version to allow skipping sections by
/// their metadata. That way it's possible to select values based on their `git_sec::Trust`
/// for example, or by their location.
///
/// Note that the filter may be executed even on sections that don't contain the key in question,
/// even though the section will have matched the `name` and `subsection_name` respectively.
///
/// ```
/// # use std::borrow::Cow;
/// # use std::convert::TryFrom;
/// # let git_config = git_config::File::try_from("[core]a=b\n[core]\na=c\na=d").unwrap();
/// assert_eq!(git_config.raw_value("core", None, "a").unwrap().as_ref(), "d");
/// ```
///
/// Consider the `multi` variants of the methods instead, if you want to work
/// with all values.
///
/// # Equality
///
/// In order to make it useful, equality will ignore all non-value bearing information, hence compare
/// only sections and their names, as well as all of their values. The ordering matters, of course.
///
/// [`raw_value()`]: Self::raw_value
#[derive(Eq, Clone, Debug, Default)]
pub struct File<'event> {
    /// The list of events that occur before any section. Since a
    /// `git-config` file prohibits global values, this vec is limited to only
    /// comment, newline, and whitespace events.
    pub(crate) frontmatter_events: crate::parse::FrontMatterEvents<'event>,
    /// Frontmatter events to be placed after the given section.
    pub(crate) frontmatter_post_section: HashMap<SectionId, crate::parse::FrontMatterEvents<'event>>,
    /// Section name to section id lookup tree, with section bodies for subsections being in a non-terminal
    /// variant of `SectionBodyIds`.
    pub(crate) section_lookup_tree: HashMap<section::Name<'event>, Vec<SectionBodyIdsLut<'event>>>,
    /// This indirection with the SectionId as the key is critical to flexibly
    /// supporting `git-config` sections, as duplicated keys are permitted.
    pub(crate) sections: HashMap<SectionId, file::Section<'event>>,
    /// Internal monotonically increasing counter for section ids.
    pub(crate) section_id_counter: usize,
    /// Section order for output ordering.
    pub(crate) section_order: VecDeque<SectionId>,
    /// The source of the File itself, which is attached to new sections automatically.
    pub(crate) meta: OwnShared<Metadata>,
}

/// Any value that may contain a foreground color, background color, a
/// collection of color (text) modifiers, or a combination of any of the
/// aforementioned values, like `red` or `brightgreen`.
///
/// Note that `git-config` allows color values to simply be a collection of
/// [`color::Attribute`]s, and does not require a [`color::Name`] for either the
/// foreground or background color.
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
pub struct Color {
    /// A provided foreground color
    pub foreground: Option<color::Name>,
    /// A provided background color
    pub background: Option<color::Name>,
    /// A potentially empty set of text attributes
    pub attributes: color::Attribute,
}

/// Any value that can be interpreted as an integer.
///
/// This supports any numeric value that can fit in a [`i64`], excluding the
/// suffix. The suffix is parsed separately from the value itself, so if you
/// wish to obtain the true value of the integer, you must account for the
/// suffix after fetching the value. [`integer::Suffix`] provides
/// [`bitwise_offset()`][integer::Suffix::bitwise_offset] to help with the
/// math, or [to_decimal()][Integer::to_decimal()] for obtaining a usable value in one step.
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct Integer {
    /// The value, without any suffix modification
    pub value: i64,
    /// A provided suffix, if any.
    pub suffix: Option<integer::Suffix>,
}

/// Any value that can be interpreted as a boolean.
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
#[allow(missing_docs)]
pub struct Boolean(pub bool);

/// Any value that can be interpreted as a path to a resource on disk.
///
/// Git represents file paths as byte arrays, modeled here as owned or borrowed byte sequences.
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct Path<'a> {
    /// The path string, un-interpolated
    pub value: std::borrow::Cow<'a, bstr::BStr>,
}