gnostr_asyncgit/sync/
config.rs

1//TODO: hopefully released in next rust (see https://github.com/rust-lang/rust-clippy/issues/9440)
2#![allow(clippy::use_self)]
3
4use git2::Repository;
5use scopetime::scope_time;
6use serde::{Deserialize, Serialize};
7
8use super::{repository::repo, RepoPath};
9use crate::error::Result;
10
11// see https://git-scm.com/docs/git-config#Documentation/git-config.txt-statusshowUntrackedFiles
12/// represents the `status.showUntrackedFiles` git config state
13#[derive(Hash, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
14pub enum ShowUntrackedFilesConfig {
15    ///
16    No,
17    ///
18    Normal,
19    ///
20    All,
21}
22
23impl Default for ShowUntrackedFilesConfig {
24    fn default() -> Self {
25        Self::No
26    }
27}
28
29impl ShowUntrackedFilesConfig {
30    ///
31    pub const fn include_none(self) -> bool {
32        matches!(self, Self::No)
33    }
34
35    ///
36    pub const fn include_untracked(self) -> bool {
37        matches!(self, Self::Normal | Self::All)
38    }
39
40    ///
41    pub const fn recurse_untracked_dirs(self) -> bool {
42        matches!(self, Self::All)
43    }
44}
45
46pub fn untracked_files_config_repo(repo: &Repository) -> Result<ShowUntrackedFilesConfig> {
47    let show_untracked_files = get_config_string_repo(repo, "status.showUntrackedFiles")?;
48
49    if let Some(show_untracked_files) = show_untracked_files {
50        if &show_untracked_files == "no" {
51            return Ok(ShowUntrackedFilesConfig::No);
52        } else if &show_untracked_files == "normal" {
53            return Ok(ShowUntrackedFilesConfig::Normal);
54        }
55    }
56
57    Ok(ShowUntrackedFilesConfig::All)
58}
59
60///
61pub fn untracked_files_config(repo_path: &RepoPath) -> Result<ShowUntrackedFilesConfig> {
62    let repo = repo(repo_path)?;
63    untracked_files_config_repo(&repo)
64}
65
66/// get string from config
67pub fn get_config_string(repo_path: &RepoPath, key: &str) -> Result<Option<String>> {
68    let repo = repo(repo_path)?;
69    get_config_string_repo(&repo, key)
70}
71
72pub fn get_config_string_repo(repo: &Repository, key: &str) -> Result<Option<String>> {
73    scope_time!("get_config_string_repo");
74
75    let cfg = repo.config()?;
76
77    // this code doesn't match what the doc says regarding what
78    // gets returned when but it actually works
79    let entry_res = cfg.get_entry(key);
80
81    let Ok(entry) = entry_res else {
82        return Ok(None);
83    };
84
85    if entry.has_value() {
86        Ok(entry.value().map(std::string::ToString::to_string))
87    } else {
88        Ok(None)
89    }
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95    use crate::sync::tests::repo_init;
96
97    #[test]
98    fn test_get_config() {
99        let bad_dir_cfg = get_config_string(&"oodly_noodly".into(), "this.doesnt.exist");
100        assert!(bad_dir_cfg.is_err());
101
102        let (_td, repo) = repo_init().unwrap();
103        let path = repo.path();
104        let rpath = path.as_os_str().to_str().unwrap();
105        let bad_cfg = get_config_string(&rpath.into(), "this.doesnt.exist");
106        assert!(bad_cfg.is_ok());
107        assert!(bad_cfg.unwrap().is_none());
108        // repo init sets user.name
109        let good_cfg = get_config_string(&rpath.into(), "user.name");
110        assert!(good_cfg.is_ok());
111        assert!(good_cfg.unwrap().is_some());
112    }
113}