Skip to main content

securegit/ops/
config.rs

1use anyhow::{bail, Result};
2use git2::{Config, Repository};
3use std::path::Path;
4use tracing::warn;
5
6/// Config keys that are dangerous to set.
7const DANGEROUS_SET_KEYS: &[&str] = &[
8    "core.fsmonitor",
9    "core.sshcommand",
10    "core.gitproxy",
11    "core.hookspath",
12    "filter.",
13    "credential.helper",
14    "include.path",
15    "url.",
16];
17
18fn open_config(path: &Path, global: bool) -> Result<Config> {
19    if global {
20        let config = Config::open_default()?;
21        Ok(config.open_level(git2::ConfigLevel::Global)?)
22    } else {
23        let repo = Repository::open(path)?;
24        Ok(repo.config()?)
25    }
26}
27
28pub fn get(path: &Path, key: &str, global: bool) -> Result<()> {
29    let config = open_config(path, global)?;
30
31    match config.get_string(key) {
32        Ok(val) => println!("{}", val),
33        Err(_) => bail!("key '{}' not found", key),
34    }
35
36    Ok(())
37}
38
39pub fn set(path: &Path, key: &str, value: &str, global: bool) -> Result<()> {
40    let key_lower = key.to_lowercase();
41    for dangerous in DANGEROUS_SET_KEYS {
42        if key_lower.starts_with(dangerous) {
43            warn!(
44                "WARNING: Setting '{}' can enable code execution. Proceed with caution.",
45                key
46            );
47            eprintln!(
48                "WARNING: Setting '{}' can enable code execution. Proceed with caution.",
49                key
50            );
51        }
52    }
53
54    let mut config = open_config(path, global)?;
55    config.set_str(key, value)?;
56
57    Ok(())
58}
59
60pub fn list(path: &Path, global: bool) -> Result<()> {
61    let config = open_config(path, global)?;
62    let mut entries = config.entries(None)?;
63
64    while let Some(entry) = entries.next() {
65        let entry = entry?;
66        if let (Some(name), Some(value)) = (entry.name(), entry.value()) {
67            println!("{}={}", name, value);
68        }
69    }
70
71    Ok(())
72}