//TODO: hopefully released in next rust (see https://github.com/rust-lang/rust-clippy/issues/9440) #![allow(clippy::use_self)] use crate::error::Result; use git2::Repository; use scopetime::scope_time; use serde::{Deserialize, Serialize}; use super::{repository::repo, RepoPath}; // see https://git-scm.com/docs/git-config#Documentation/git-config.txt-statusshowUntrackedFiles /// represents the `status.showUntrackedFiles` git config state #[derive( Hash, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, )] pub enum ShowUntrackedFilesConfig { /// No, /// Normal, /// All, } impl Default for ShowUntrackedFilesConfig { fn default() -> Self { Self::No } } impl ShowUntrackedFilesConfig { /// pub const fn include_none(self) -> bool { matches!(self, Self::No) } /// pub const fn include_untracked(self) -> bool { matches!(self, Self::Normal | Self::All) } /// pub const fn recurse_untracked_dirs(self) -> bool { matches!(self, Self::All) } } pub fn untracked_files_config_repo( repo: &Repository, ) -> Result { let show_untracked_files = get_config_string_repo(repo, "status.showUntrackedFiles")?; if let Some(show_untracked_files) = show_untracked_files { if &show_untracked_files == "no" { return Ok(ShowUntrackedFilesConfig::No); } else if &show_untracked_files == "normal" { return Ok(ShowUntrackedFilesConfig::Normal); } } Ok(ShowUntrackedFilesConfig::All) } /// pub fn untracked_files_config( repo_path: &RepoPath, ) -> Result { let repo = repo(repo_path)?; untracked_files_config_repo(&repo) } /// get string from config pub fn get_config_string( repo_path: &RepoPath, key: &str, ) -> Result> { let repo = repo(repo_path)?; get_config_string_repo(&repo, key) } pub fn get_config_string_repo( repo: &Repository, key: &str, ) -> Result> { scope_time!("get_config_string_repo"); let cfg = repo.config()?; // this code doesn't match what the doc says regarding what // gets returned when but it actually works let entry_res = cfg.get_entry(key); let Ok(entry) = entry_res else { return Ok(None); }; if entry.has_value() { Ok(entry.value().map(std::string::ToString::to_string)) } else { Ok(None) } } #[cfg(test)] mod tests { use super::*; use crate::sync::tests::repo_init; #[test] fn test_get_config() { let bad_dir_cfg = get_config_string( &"oodly_noodly".into(), "this.doesnt.exist", ); assert!(bad_dir_cfg.is_err()); let (_td, repo) = repo_init().unwrap(); let path = repo.path(); let rpath = path.as_os_str().to_str().unwrap(); let bad_cfg = get_config_string(&rpath.into(), "this.doesnt.exist"); assert!(bad_cfg.is_ok()); assert!(bad_cfg.unwrap().is_none()); // repo init sets user.name let good_cfg = get_config_string(&rpath.into(), "user.name"); assert!(good_cfg.is_ok()); assert!(good_cfg.unwrap().is_some()); } }