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>,
}