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..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>, /// 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, Vec>>, /// 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>, /// Internal monotonically increasing counter for section ids. pub(crate) section_id_counter: usize, /// Section order for output ordering. pub(crate) section_order: VecDeque, /// The source of the File itself, which is attached to new sections automatically. pub(crate) meta: OwnShared, } /// 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, /// A provided background color pub background: Option, /// 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, } /// 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>, }