1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
//! Configuration
use std::collections::BTreeMap;
use crate::{error::Error, repo::GitRepository};
/// A more user-friendly config object
pub type GitConfig = BTreeMap<String, String>;
/// Config key for the user email
pub const USER_EMAIL: &str = "user.email";
/// Config key for the user name
pub const USER_NAME: &str = "user.name";
/// Returns the repo config
///
/// The config is the config which can be applied taking into
/// account the hierarchy which exists between the global config,
/// and the local/repo config overwriting the global config.
pub fn get_config(repo: &GitRepository) -> Result<GitConfig, Error> {
let git2_cfg = repo.config().unwrap();
let mut cfg = BTreeMap::new();
git2_cfg.entries(None).into_iter().for_each(|entries| {
// NB: this loop is over the types of config, starting from the most generic one (global => local)
entries
.for_each(|entry| {
// NB: this loop is for each entry in the config file
// let level = entry.level();
let name = entry.name().unwrap().to_string();
let value = entry.value().unwrap_or("").to_string();
// eprintln!("{:?} {} {}", level, name, value);
cfg.insert(name, value);
})
.unwrap();
});
Ok(cfg)
}
/// Retrieves the repo origin url
pub fn get_origin_url(repo: &GitRepository, origin_name: &str) -> Result<Option<String>, Error> {
let cfg = get_config(repo)?;
let key = format!("remote.{}.url", origin_name);
Ok(cfg.get(key.as_str()).map(|s| s.to_string()))
}
#[cfg(test)]
mod tests {
use crate::repo::discover_repo;
// Note this useful idiom: importing names from outer (for mod tests) scope.
use super::*;
#[test]
fn test_cfg() {
let cwd = std::env::current_dir().unwrap();
let repo = discover_repo(&cwd).unwrap();
let cfg = get_config(&repo).unwrap();
for (k, v) in cfg.iter() {
eprintln!("{}: {}", k, v);
}
}
}