summaryrefslogtreecommitdiffstats
path: root/src/git_config
diff options
context:
space:
mode:
authorDan Davison <dandavison7@gmail.com>2021-01-08 08:09:52 -0500
committerDan Davison <dandavison7@gmail.com>2021-01-08 10:12:35 -0500
commitba0d36cb2de1be6e8c4332d37f796393ccc07b15 (patch)
treeeed08fab180fdf338531a37f451fe87441c0139a /src/git_config
parent60aa0cc14714da2bdc3b05686253f757869f697c (diff)
Parse GIT_CONFIG_PARAMETERS
When git is invoked as `git -c aaa.bbb=ccc -c ddd.eee=fff` then git sets the env var GIT_CONFIG_PARAMETERS containing the changed config entries, so that child processes can honor them. libgit2 doesn't yet honor the env var: see https://github.com/libgit2/libgit2/issues/3854. Fixes #493 Fixes #307 Ref https://github.com/dandavison/magit-delta/issues/13
Diffstat (limited to 'src/git_config')
-rw-r--r--src/git_config/git_config.rs99
1 files changed, 94 insertions, 5 deletions
diff --git a/src/git_config/git_config.rs b/src/git_config/git_config.rs
index ab831b31..96209603 100644
--- a/src/git_config/git_config.rs
+++ b/src/git_config/git_config.rs
@@ -1,9 +1,15 @@
+use regex::Regex;
+use std::collections::HashMap;
+use std::env;
#[cfg(test)]
use std::path::Path;
use std::process;
+use lazy_static::lazy_static;
+
pub struct GitConfig {
config: git2::Config,
+ config_from_env_var: HashMap<String, String>,
pub enabled: bool,
pub repo: Option<git2::Repository>,
}
@@ -26,6 +32,7 @@ impl GitConfig {
});
Some(Self {
config,
+ config_from_env_var: parse_config_from_env_var(),
repo,
enabled: true,
})
@@ -38,6 +45,7 @@ impl GitConfig {
pub fn from_path(path: &Path) -> Self {
Self {
config: git2::Config::open(path).unwrap(),
+ config_from_env_var: parse_config_from_env_var(),
repo: None,
enabled: true,
}
@@ -55,6 +63,26 @@ impl GitConfig {
}
}
+fn parse_config_from_env_var() -> HashMap<String, String> {
+ if let Ok(s) = env::var("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"'(delta\.[a-z-]+)=([^']+)'").unwrap();
+}
+
+fn parse_config_from_env_var_value(s: &str) -> HashMap<String, String> {
+ GIT_CONFIG_PARAMETERS_REGEX
+ .captures_iter(s)
+ .map(|captures| (captures[1].to_string(), captures[2].to_string()))
+ .collect()
+}
+
pub trait GitConfigGet {
fn git_config_get(key: &str, git_config: &GitConfig) -> Option<Self>
where
@@ -63,27 +91,42 @@ pub trait GitConfigGet {
impl GitConfigGet for String {
fn git_config_get(key: &str, git_config: &GitConfig) -> Option<Self> {
- git_config.config.get_string(key).ok()
+ 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.get_string(key) {
- Ok(value) => Some(Some(value)),
- _ => None,
+ 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> {
- git_config.config.get_bool(key).ok()
+ 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,
@@ -93,9 +136,55 @@ impl GitConfigGet for usize {
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
+
+ let config = parse_config_from_env_var_value("'user.name=xxx'");
+ assert!(config.is_empty());
+
+ let config = parse_config_from_env_var_value("'delta.plus-style=green'");
+ assert_eq!(config["delta.plus-style"], "green");
+
+ let config = parse_config_from_env_var_value(
+ r##"'user.name=xxx' 'delta.hunk-header-line-number-style=red "#067a00"'"##,
+ );
+ assert_eq!(
+ config["delta.hunk-header-line-number-style"],
+ r##"red "#067a00""##
+ );
+
+ let config =
+ parse_config_from_env_var_value(r##"'user.name=xxx' 'delta.side-by-side=false'"##);
+ assert_eq!(config["delta.side-by-side"], "false");
+
+ let config = parse_config_from_env_var_value(
+ r##"'delta.plus-style=green' 'delta.side-by-side=false' 'delta.hunk-header-line-number-style=red "#067a00"'"##,
+ );
+ 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""##
+ );
+ }
+}