#![allow(unused)]
#![allow(clippy::result_unit_err)]
use std::{
borrow::Cow,
convert::TryFrom,
path::{Path, PathBuf},
};
use crate::file::{GitConfig, GitConfigError};
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum ConfigSource {
System,
Global,
User,
Repository,
Env,
Cli,
}
#[derive(Debug, PartialEq, Clone, Eq, Hash, Default)]
pub struct ConfigBuilder {
no_system: bool,
load_env_conf: bool,
override_system_config: Option<PathBuf>,
override_global_config: Option<PathBuf>,
override_repo_config: Option<PathBuf>,
}
impl ConfigBuilder {
#[inline]
#[must_use]
pub fn new() -> Self {
Self {
load_env_conf: true,
..Self::default()
}
}
#[must_use]
pub fn no_system(&mut self, no_system: bool) -> &mut Self {
self.no_system = no_system;
self
}
#[must_use]
pub fn load_environment_entries(&mut self, load_conf: bool) -> &mut Self {
self.load_env_conf = load_conf;
self
}
#[must_use]
pub fn system_config_path(&mut self, path: Option<PathBuf>) -> &mut Self {
self.override_system_config = path;
self
}
#[must_use]
pub fn global_config_path(&mut self, path: Option<PathBuf>) -> &mut Self {
self.override_global_config = path;
self
}
#[must_use]
pub fn repository_config_path(&mut self, path: Option<PathBuf>) -> &mut Self {
self.override_repo_config = path;
self
}
#[must_use]
pub fn build(&self) -> Config {
let system_conf = if self.no_system { None } else { todo!() };
let global_conf = {
let path = self
.override_global_config
.as_ref()
.map_or_else(|| Path::new(".git/config"), PathBuf::as_path);
GitConfig::open(path).ok()
};
let env_conf = if self.load_env_conf {
GitConfig::from_env().ok().flatten()
} else {
None
};
Config {
system_conf,
global_conf,
user_conf: todo!(),
repository_conf: todo!(),
worktree_conf: todo!(),
env_conf,
cli_conf: todo!(),
}
}
pub fn try_build(&self) -> Result<Config, ()> {
todo!()
}
}
pub struct Config<'config> {
system_conf: Option<GitConfig<'config>>,
global_conf: Option<GitConfig<'config>>,
user_conf: Option<GitConfig<'config>>,
repository_conf: Option<GitConfig<'config>>,
worktree_conf: Option<GitConfig<'config>>,
env_conf: Option<GitConfig<'config>>,
cli_conf: Option<GitConfig<'config>>,
}
impl<'config> Config<'config> {
#[inline]
#[must_use]
pub fn value<T: TryFrom<Cow<'config, [u8]>>>(
&'config self,
section_name: &str,
subsection_name: Option<&str>,
key: &str,
) -> Option<T> {
self.value_with_source(section_name, subsection_name, key)
.map(|(value, _)| value)
}
fn value_with_source<T: TryFrom<Cow<'config, [u8]>>>(
&'config self,
section_name: &str,
subsection_name: Option<&str>,
key: &str,
) -> Option<(T, ConfigSource)> {
let mapping = self.mapping();
for (conf, source) in mapping {
if let Some(conf) = conf {
if let Ok(v) = conf.value(section_name, subsection_name, key) {
return Some((v, source));
}
}
}
None
}
#[inline]
pub fn try_value<'lookup, T: TryFrom<Cow<'config, [u8]>>>(
&'config self,
section_name: &'lookup str,
subsection_name: Option<&'lookup str>,
key: &'lookup str,
) -> Result<Option<T>, GitConfigError<'lookup>> {
self.try_value_with_source(section_name, subsection_name, key)
.map(|res| res.map(|(value, _)| value))
}
pub fn try_value_with_source<'lookup, T: TryFrom<Cow<'config, [u8]>>>(
&'config self,
section_name: &'lookup str,
subsection_name: Option<&'lookup str>,
key: &'lookup str,
) -> Result<Option<(T, ConfigSource)>, GitConfigError<'lookup>> {
let mapping = self.mapping();
for (conf, source) in mapping {
if let Some(conf) = conf {
return Ok(Some((conf.value(section_name, subsection_name, key)?, source)));
}
}
Ok(None)
}
const fn mapping(&self) -> [(&Option<GitConfig>, ConfigSource); 6] {
[
(&self.cli_conf, ConfigSource::Cli),
(&self.env_conf, ConfigSource::Env),
(&self.repository_conf, ConfigSource::Repository),
(&self.user_conf, ConfigSource::User),
(&self.global_conf, ConfigSource::Global),
(&self.system_conf, ConfigSource::System),
]
}
}
impl<'config> Config<'config> {
#[must_use]
pub fn get_config(&self, source: ConfigSource) -> Option<&GitConfig<'config>> {
match source {
ConfigSource::System => self.system_conf.as_ref(),
ConfigSource::Global => self.global_conf.as_ref(),
ConfigSource::User => self.user_conf.as_ref(),
ConfigSource::Repository => self.repository_conf.as_ref(),
ConfigSource::Env => self.env_conf.as_ref(),
ConfigSource::Cli => self.cli_conf.as_ref(),
}
}
#[must_use]
pub fn get_config_mut(&mut self, source: ConfigSource) -> Option<&mut GitConfig<'config>> {
match source {
ConfigSource::System => self.system_conf.as_mut(),
ConfigSource::Global => self.global_conf.as_mut(),
ConfigSource::User => self.user_conf.as_mut(),
ConfigSource::Repository => self.repository_conf.as_mut(),
ConfigSource::Env => self.env_conf.as_mut(),
ConfigSource::Cli => self.cli_conf.as_mut(),
}
}
}