Coverage Report

Created: 2026-02-14 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gitoxide/gix-pathspec/src/defaults.rs
Line
Count
Source
1
use std::ffi::OsString;
2
3
use crate::{Defaults, MagicSignature, SearchMode};
4
5
///
6
pub mod from_environment {
7
    /// The error returned by [Defaults::from_environment()](super::Defaults::from_environment()).
8
    #[derive(Debug, thiserror::Error)]
9
    #[allow(missing_docs)]
10
    pub enum Error {
11
        #[error(transparent)]
12
        ParseValue(#[from] gix_config_value::Error),
13
        #[error("Glob and no-glob settings are mutually exclusive")]
14
        MixedGlobAndNoGlob,
15
    }
16
}
17
18
impl Defaults {
19
    /// Initialize this instance using information from the environment as
20
    /// [per the official documentation](https://git-scm.com/book/en/v2/Git-Internals-Environment-Variables) *(look for `PATHSPECS`)*,
21
    /// calling `var(variable_name)` for each variable that should be obtained.
22
    ///
23
    /// Used environment variables are `GIT_GLOB_PATHSPECS`, `GIT_NOGLOB_PATHSPECS`, `GIT_LITERAL_PATHSPECS` and `GIT_ICASE_PATHSPECS`.
24
    /// Note that there are lot of failure modes, and instead of offering lenient parsing, the caller may ignore errors and
25
    /// use other defaults instead.
26
    ///
27
    /// ### Deviation
28
    ///
29
    /// Instead of failing if `GIT_LITERAL_PATHSPECS` is used with glob globals, we ignore these. Also our implementation allows global
30
    /// `icase` settings in combination with this setting.
31
0
    pub fn from_environment(var: &mut dyn FnMut(&str) -> Option<OsString>) -> Result<Self, from_environment::Error> {
32
0
        let mut env_bool = |name: &str| -> Result<Option<bool>, gix_config_value::Error> {
33
0
            var(name)
34
0
                .map(|val| gix_config_value::Boolean::try_from(val).map(|b| b.0))
35
0
                .transpose()
36
0
        };
37
38
0
        let literal = env_bool("GIT_LITERAL_PATHSPECS")?.unwrap_or_default();
39
0
        let signature = env_bool("GIT_ICASE_PATHSPECS")?
40
0
            .and_then(|val| val.then_some(MagicSignature::ICASE))
41
0
            .unwrap_or_default();
42
0
        if literal {
43
0
            return Ok(Defaults {
44
0
                signature,
45
0
                search_mode: SearchMode::Literal,
46
0
                literal,
47
0
            });
48
0
        }
49
0
        let glob = env_bool("GIT_GLOB_PATHSPECS")?;
50
0
        let mut search_mode = glob
51
0
            .and_then(|glob| glob.then_some(SearchMode::PathAwareGlob))
52
0
            .unwrap_or_default();
53
0
        search_mode = env_bool("GIT_NOGLOB_PATHSPECS")?
54
0
            .map(|no_glob| {
55
0
                if glob.unwrap_or_default() && no_glob {
56
0
                    Err(from_environment::Error::MixedGlobAndNoGlob)
57
                } else {
58
0
                    Ok(SearchMode::Literal)
59
                }
60
0
            })
61
0
            .transpose()?
62
0
            .unwrap_or(search_mode);
63
64
0
        Ok(Defaults {
65
0
            signature,
66
0
            search_mode,
67
0
            literal,
68
0
        })
69
0
    }
70
}