use anyhow::{bail, Result};
use git2::Config;
use std::path::Path;
use tracing::warn;
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(())
}