securegit 0.8.5

Zero-trust git replacement with 12 built-in security scanners, LLM redteam bridge, universal undo, durable backups, and a 50-tool MCP server
Documentation
use anyhow::{bail, Result};
use git2::Config;
use std::path::Path;
use tracing::warn;

/// Config keys that are dangerous to set.
const DANGEROUS_SET_KEYS: &[&str] = &[
    "core.fsmonitor",
    "core.sshcommand",
    "core.gitproxy",
    "core.hookspath",
    "filter.",
    "credential.helper",
    "include.path",
    "url.",
];

fn open_config(path: &Path, global: bool) -> Result<Config> {
    if global {
        let config = Config::open_default()?;
        Ok(config.open_level(git2::ConfigLevel::Global)?)
    } else {
        let repo = crate::ops::open_repo(path)?;
        Ok(repo.config()?)
    }
}

pub fn get(path: &Path, key: &str, global: bool) -> Result<()> {
    let config = open_config(path, global)?;

    match config.get_string(key) {
        Ok(val) => println!("{}", val),
        Err(_) => bail!("key '{}' not found", key),
    }

    Ok(())
}

pub fn set(path: &Path, key: &str, value: &str, global: bool) -> Result<()> {
    let key_lower = key.to_lowercase();
    for dangerous in DANGEROUS_SET_KEYS {
        if key_lower.starts_with(dangerous) {
            warn!(
                "WARNING: Setting '{}' can enable code execution. Proceed with caution.",
                key
            );
            eprintln!(
                "WARNING: Setting '{}' can enable code execution. Proceed with caution.",
                key
            );
        }
    }

    let mut config = open_config(path, global)?;
    config.set_str(key, value)?;

    Ok(())
}

pub fn list(path: &Path, global: bool) -> Result<()> {
    let config = open_config(path, global)?;
    let mut entries = config.entries(None)?;

    while let Some(entry) = entries.next() {
        let entry = entry?;
        if let (Some(name), Some(value)) = (entry.name(), entry.value()) {
            println!("{}={}", name, value);
        }
    }

    Ok(())
}