summaryrefslogtreecommitdiffstats
path: root/src/git_config/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/git_config/mod.rs')
-rw-r--r--src/git_config/mod.rs300
1 files changed, 0 insertions, 300 deletions
diff --git a/src/git_config/mod.rs b/src/git_config/mod.rs
deleted file mode 100644
index f508b933..00000000
--- a/src/git_config/mod.rs
+++ /dev/null
@@ -1,300 +0,0 @@
-mod remote;
-
-pub use remote::GitRemoteRepo;
-
-use crate::env::DeltaEnv;
-use regex::Regex;
-use std::collections::HashMap;
-use std::path::Path;
-use std::str::FromStr;
-
-use lazy_static::lazy_static;
-
-pub struct GitConfig {
- config: git2::Config,
- config_from_env_var: HashMap<String, String>,
- pub enabled: bool,
- repo: Option<git2::Repository>,
- // To make GitConfig cloneable when testing (in turn to make Config cloneable):
- #[cfg(test)]
- path: std::path::PathBuf,
-}
-
-#[cfg(test)]
-impl Clone for GitConfig {
- fn clone(&self) -> Self {
- assert!(self.repo.is_none());
- GitConfig {
- // Assumes no test modifies the file pointed to by `path`
- config: git2::Config::open(&self.path).unwrap(),
- config_from_env_var: self.config_from_env_var.clone(),
- enabled: self.enabled,
- repo: None,
- path: self.path.clone(),
- }
- }
-}
-
-impl GitConfig {
- #[cfg(not(test))]
- pub fn try_create(env: &DeltaEnv) -> Option<Self> {
- use crate::fatal;
-
- let repo = match &env.current_dir {
- Some(dir) => git2::Repository::discover(dir).ok(),
- _ => None,
- };
- let config = match &repo {
- Some(repo) => repo.config().ok(),
- None => git2::Config::open_default().ok(),
- };
- match config {
- Some(mut config) => {
- let config = config.snapshot().unwrap_or_else(|err| {
- fatal(format!("Failed to read git config: {err}"));
- });
- Some(Self {
- config,
- config_from_env_var: parse_config_from_env_var(env),
- repo,
- enabled: true,
- })
- }
- None => None,
- }
- }
-
- #[cfg(test)]
- pub fn try_create(_env: &DeltaEnv) -> Option<Self> {
- unreachable!("GitConfig::try_create() is not available when testing");
- }
-
- pub fn from_path(env: &DeltaEnv, path: &Path, honor_env_var: bool) -> Self {
- use crate::fatal;
-
- match git2::Config::open(path) {
- Ok(mut config) => {
- let config = config.snapshot().unwrap_or_else(|err| {
- fatal(format!("Failed to read git config: {err}"));
- });
-
- Self {
- config,
- config_from_env_var: if honor_env_var {
- parse_config_from_env_var(env)
- } else {
- HashMap::new()
- },
- repo: None,
- enabled: true,
- #[cfg(test)]
- path: path.into(),
- }
- }
- Err(e) => {
- fatal(format!("Failed to read git config: {}", e.message()));
- }
- }
- }
-
- pub fn get<T>(&self, key: &str) -> Option<T>
- where
- T: GitConfigGet,
- {
- if self.enabled {
- T::git_config_get(key, self)
- } else {
- None
- }
- }
-
- pub fn get_remote_url(&self) -> Option<GitRemoteRepo> {
- self.repo
- .as_ref()?
- .find_remote("origin")
- .ok()?
- .url()
- .and_then(|url| GitRemoteRepo::from_str(url).ok())
- }
-
- pub fn for_each<F>(&self, regex: &str, mut f: F)
- where
- F: FnMut(&str, Option<&str>),
- {
- let mut entries = self.config.entries(Some(regex)).unwrap();
- while let Some(entry) = entries.next() {
- let entry = entry.unwrap();
- let name = entry.name().unwrap();
- f(name, entry.value());
- }
- }
-}
-
-fn parse_config_from_env_var(env: &DeltaEnv) -> HashMap<String, String> {
- if let Some(s) = &env.git_config_parameters {
- parse_config_from_env_var_value(s)
- } else {
- HashMap::new()
- }
-}
-
-lazy_static! {
- static ref GIT_CONFIG_PARAMETERS_REGEX: Regex = Regex::new(
- r"(?x)
- (?: # Non-capturing group containing union
- '(delta\.[a-z-]+)=([^']+)' # Git <2.31.0 format
- |
- '(delta\.[a-z-]+)'='([^']+)' # Git ≥2.31.0 format
- )
- "
- )
- .unwrap();
-}
-
-fn parse_config_from_env_var_value(s: &str) -> HashMap<String, String> {
- GIT_CONFIG_PARAMETERS_REGEX
- .captures_iter(s)
- .map(|captures| {
- let (i, j) = match (
- captures.get(1),
- captures.get(2),
- captures.get(3),
- captures.get(4),
- ) {
- (Some(_), Some(_), None, None) => (1, 2),
- (None, None, Some(_), Some(_)) => (3, 4),
- _ => (0, 0),
- };
- if (i, j) == (0, 0) {
- ("".to_string(), "".to_string())
- } else {
- (captures[i].to_string(), captures[j].to_string())
- }
- })
- .collect()
-}
-
-pub trait GitConfigGet {
- fn git_config_get(key: &str, git_config: &GitConfig) -> Option<Self>
- where
- Self: Sized;
-}
-
-impl GitConfigGet for String {
- fn git_config_get(key: &str, git_config: &GitConfig) -> Option<Self> {
- match git_config.config_from_env_var.get(key) {
- Some(val) => Some(val.to_string()),
- None => git_config.config.get_string(key).ok(),
- }
- }
-}
-
-impl GitConfigGet for Option<String> {
- fn git_config_get(key: &str, git_config: &GitConfig) -> Option<Self> {
- match git_config.config_from_env_var.get(key) {
- Some(val) => Some(Some(val.to_string())),
- None => match git_config.config.get_string(key) {
- Ok(val) => Some(Some(val)),
- _ => None,
- },
- }
- }
-}
-
-impl GitConfigGet for bool {
- fn git_config_get(key: &str, git_config: &GitConfig) -> Option<Self> {
- match git_config.config_from_env_var.get(key).map(|s| s.as_str()) {
- Some("true") => Some(true),
- Some("false") => Some(false),
- _ => git_config.config.get_bool(key).ok(),
- }
- }
-}
-
-impl GitConfigGet for usize {
- fn git_config_get(key: &str, git_config: &GitConfig) -> Option<Self> {
- if let Some(s) = git_config.config_from_env_var.get(key) {
- if let Ok(n) = s.parse::<usize>() {
- return Some(n);
- }
- }
- match git_config.config.get_i64(key) {
- Ok(value) => Some(value as usize),
- _ => None,
- }
- }
-}
-
-impl GitConfigGet for f64 {
- fn git_config_get(key: &str, git_config: &GitConfig) -> Option<Self> {
- if let Some(s) = git_config.config_from_env_var.get(key) {
- if let Ok(n) = s.parse::<f64>() {
- return Some(n);
- }
- }
- match git_config.config.get_string(key) {
- Ok(value) => value.parse::<f64>().ok(),
- _ => None,
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
-
- use super::parse_config_from_env_var_value;
-
- #[test]
- fn test_parse_config_from_env_var_value() {
- // To generate test cases, use git -c ... with
- // [core]
- // pager = env | grep GIT_CONFIG_PARAMETERS
-
- // We test multiple formats because the format of the value stored by
- // git in this environment variable has changed in recent versions of
- // Git. See
- // https://github.com/git/git/blob/311531c9de557d25ac087c1637818bd2aad6eb3a/Documentation/RelNotes/2.31.0.txt#L127-L130
-
- for env_var_value in &["'user.name=xxx'", "'user.name'='xxx'"] {
- let config = parse_config_from_env_var_value(env_var_value);
- assert!(config.is_empty());
- }
-
- for env_var_value in &["'delta.plus-style=green'", "'delta.plus-style'='green'"] {
- let config = parse_config_from_env_var_value(env_var_value);
- assert_eq!(config["delta.plus-style"], "green");
- }
-
- for env_var_value in &[
- r##"'user.name=xxx' 'delta.hunk-header-line-number-style=red "#067a00"'"##,
- r##"'user.name'='xxx' 'delta.hunk-header-line-number-style'='red "#067a00"'"##,
- ] {
- let config = parse_config_from_env_var_value(env_var_value);
- assert_eq!(
- config["delta.hunk-header-line-number-style"],
- r##"red "#067a00""##
- );
- }
-
- for env_var_value in &[
- r##"'user.name=xxx' 'delta.side-by-side=false'"##,
- r##"'user.name'='xxx' 'delta.side-by-side'='false'"##,
- ] {
- let config = parse_config_from_env_var_value(env_var_value);
- assert_eq!(config["delta.side-by-side"], "false");
- }
-
- for env_var_value in &[
- r##"'delta.plus-style=green' 'delta.side-by-side=false' 'delta.hunk-header-line-number-style=red "#067a00"'"##,
- r##"'delta.plus-style'='green' 'delta.side-by-side'='false' 'delta.hunk-header-line-number-style'='red "#067a00"'"##,
- ] {
- let config = parse_config_from_env_var_value(env_var_value);
- assert_eq!(config["delta.plus-style"], "green");
- assert_eq!(config["delta.side-by-side"], "false");
- assert_eq!(
- config["delta.hunk-header-line-number-style"],
- r##"red "#067a00""##
- );
- }
- }
-}