gix_config/
types.rs

1use std::collections::{HashMap, VecDeque};
2
3use gix_features::threading::OwnShared;
4
5use crate::{
6    file,
7    file::{Metadata, SectionBodyIdsLut, SectionId},
8    parse::section,
9};
10
11/// A list of known sources for git configuration in order of ascending precedence.
12///
13/// This means values from the first one will be overridden by values in the second one, and so forth.
14/// Note that included files via `include.path` and `includeIf.<condition>.path` inherit
15/// their source.
16#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
17pub enum Source {
18    /// A special configuration file that ships with the git installation, and is thus tied to the used git binary.
19    GitInstallation,
20    /// System-wide configuration path. This is defined as
21    /// `$(prefix)/etc/gitconfig` (where prefix is the git-installation directory).
22    System,
23    /// A platform defined location for where a user's git application configuration should be located.
24    /// If `$XDG_CONFIG_HOME` is not set or empty, `$HOME/.config/git/config` will be used
25    /// on unix.
26    Git,
27    /// This is usually `~/.gitconfig` on unix.
28    User,
29    /// The configuration of the repository itself, located in `.git/config`.
30    Local,
31    /// Configuration specific to a worktree as created with `git worktree` and
32    /// typically located in `$GIT_DIR/config.worktree` if `extensions.worktreeConfig`
33    /// is enabled.
34    Worktree,
35    /// Values parsed from the environment using `GIT_CONFIG_COUNT`,
36    /// `GIT_CONFIG_KEY_N` and `GIT_CONFIG_VALUE_N` where `N` is incremented from 0 up to the
37    /// value of `GIT_CONFIG_COUNT`.
38    Env,
39    /// Values set from the command-line, typically controlled by the user running a program.
40    Cli,
41    /// Entirely internal from a programmatic source, and can be used to have (near final) say in configuration values.
42    Api,
43    /// Values obtained from specific environment variables that override values in the git configuration.
44    ///
45    /// For example, `HTTP_PROXY` overrides `http.proxy`, no matter where it is specified, and thus
46    /// controls the value similar to how it's done in `git`.
47    EnvOverride,
48}
49
50/// High level `git-config` reader and writer.
51///
52/// This is the full-featured implementation that can deserialize, serialize,
53/// and edit `git-config` files without loss of whitespace or comments.
54///
55/// # 'multivar' behavior
56///
57/// `git` is flexible enough to allow users to set a key multiple times in
58/// any number of identically named sections. When this is the case, the key
59/// is known as a _"multivar"_. In this case, [`raw_value()`] follows the
60/// "last one wins".
61///
62/// Concretely, the following config has a multivar, `a`, with the values
63/// of `b`, `c`, and `d`, while `e` is a single variable with the value
64/// `f g h`.
65///
66/// ```text
67/// [core]
68///     a = b
69///     a = c
70/// [core]
71///     a = d
72///     e = f g h
73/// ```
74///
75/// Calling methods that fetch or set only one value (such as [`raw_value()`])
76/// key `a` with the above config will fetch `d` or replace `d`, since the last
77/// valid config key/value pair is `a = d`:
78///
79/// # Filtering
80///
81/// All methods exist in a `*_filter(…, filter)` version to allow skipping sections by
82/// their metadata. That way it's possible to select values based on their `gix_sec::Trust`
83/// for example, or by their location.
84///
85/// Note that the filter may be executed even on sections that don't contain the key in question,
86/// even though the section will have matched the `name` and `subsection_name` respectively.
87///
88/// ```
89/// # use std::borrow::Cow;
90/// # use std::convert::TryFrom;
91/// # let git_config = gix_config::File::try_from("[core]a=b\n[core]\na=c\na=d").unwrap();
92/// assert_eq!(git_config.raw_value("core.a").unwrap().as_ref(), "d");
93/// ```
94///
95/// Consider the `multi` variants of the methods instead, if you want to work
96/// with all values.
97///
98/// # Equality
99///
100/// In order to make it useful, equality will ignore all non-value bearing information, hence compare
101/// only sections and their names, as well as all of their values. The ordering matters, of course.
102///
103/// [`raw_value()`]: Self::raw_value
104#[derive(Eq, Clone, Debug, Default)]
105pub struct File<'event> {
106    /// The list of events that occur before any section. Since a
107    /// `git-config` file prohibits global values, this vec is limited to only
108    /// comment, newline, and whitespace events.
109    pub(crate) frontmatter_events: crate::parse::FrontMatterEvents<'event>,
110    /// Frontmatter events to be placed after the given section.
111    pub(crate) frontmatter_post_section: HashMap<SectionId, crate::parse::FrontMatterEvents<'event>>,
112    /// Section name to section id lookup tree, with section bodies for subsections being in a non-terminal
113    /// variant of `SectionBodyIds`.
114    pub(crate) section_lookup_tree: HashMap<section::Name<'event>, Vec<SectionBodyIdsLut<'event>>>,
115    /// This indirection with the SectionId as the key is critical to flexibly
116    /// supporting `git-config` sections, as duplicated keys are permitted.
117    pub(crate) sections: HashMap<SectionId, file::Section<'event>>,
118    /// Internal monotonically increasing counter for section ids.
119    pub(crate) section_id_counter: usize,
120    /// Section order for output ordering.
121    pub(crate) section_order: VecDeque<SectionId>,
122    /// The source of the File itself, which is attached to new sections automatically.
123    pub(crate) meta: OwnShared<Metadata>,
124}