debian_analyzer/
config.rs

1//! Lintian-brush configuration file.
2use crate::Certainty;
3use breezyshim::tree::WorkingTree;
4use configparser::ini::Ini;
5use log::warn;
6
7const SUPPORTED_KEYS: &[&str] = &[
8    "compat-release",
9    "minimum-certainty",
10    "allow-reformatting",
11    "update-changelog",
12];
13
14/// Configuration file name
15pub const PACKAGE_CONFIG_FILENAME: &str = "debian/lintian-brush.conf";
16
17/// Configuration file
18pub struct Config {
19    obj: Ini,
20}
21
22impl Config {
23    /// Load configuration from a working tree
24    pub fn from_workingtree(
25        tree: &WorkingTree,
26        subpath: &std::path::Path,
27    ) -> std::io::Result<Self> {
28        let path = tree
29            .abspath(&subpath.join(PACKAGE_CONFIG_FILENAME))
30            .unwrap();
31        Self::load_from_path(&path)
32    }
33
34    /// Load configuration from a path
35    pub fn load_from_path(path: &std::path::Path) -> Result<Self, std::io::Error> {
36        let mut ini = Ini::new();
37        let data = std::fs::read_to_string(path)?;
38        ini.read(data)
39            .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
40
41        for (section, contents) in ini.get_map_ref() {
42            if section != "default" {
43                warn!(
44                    "unknown section {} in {}, ignoring.",
45                    section,
46                    path.display()
47                );
48                continue;
49            }
50            for key in contents.keys() {
51                if !SUPPORTED_KEYS.contains(&key.as_str()) {
52                    warn!(
53                        "unknown key {} in section {} in {}, ignoring.",
54                        key,
55                        section,
56                        path.display()
57                    );
58
59                    continue;
60                }
61            }
62        }
63
64        Ok(Config { obj: ini })
65    }
66
67    /// Return the compatibility release.
68    pub fn compat_release(&self) -> Option<String> {
69        if let Some(value) = self.obj.get("default", "compat-release") {
70            let codename = crate::release_info::resolve_release_codename(value.as_str(), None);
71            if codename.is_none() {
72                warn!("unknown compat release {}, ignoring.", value);
73            }
74            codename
75        } else {
76            None
77        }
78    }
79
80    /// Return whether reformatting is allowed.
81    pub fn allow_reformatting(&self) -> Option<bool> {
82        match self.obj.getbool("default", "allow-reformatting") {
83            Ok(value) => value,
84            Err(e) => {
85                warn!("invalid allow-reformatting value {}, ignoring.", e);
86                None
87            }
88        }
89    }
90
91    /// Return the minimum certainty level for changes to be applied.
92    pub fn minimum_certainty(&self) -> Option<Certainty> {
93        self.obj
94            .get("default", "minimum-certainty")
95            .and_then(|value| {
96                value
97                    .parse::<Certainty>()
98                    .map_err(|e| {
99                        warn!("invalid minimum-certainty value {}, ignoring.", value);
100                        e
101                    })
102                    .ok()
103            })
104    }
105
106    /// Return whether the changelog should be updated.
107    pub fn update_changelog(&self) -> Option<bool> {
108        match self.obj.getbool("default", "update-changelog") {
109            Ok(value) => value,
110            Err(e) => {
111                warn!("invalid update-changelog value {}, ignoring.", e);
112                None
113            }
114        }
115    }
116}
117
118#[cfg(test)]
119mod tests {
120    use super::*;
121
122    #[test]
123    fn test_compat_release() {
124        let td = tempfile::tempdir().unwrap();
125        std::fs::create_dir(td.path().join("debian")).unwrap();
126        std::fs::write(
127            td.path().join("debian/lintian-brush.conf"),
128            "compat-release = testing\n",
129        )
130        .unwrap();
131        let cfg = Config::load_from_path(&td.path().join("debian/lintian-brush.conf")).unwrap();
132
133        let testing = crate::release_info::resolve_release_codename("testing", None);
134
135        assert_eq!(cfg.compat_release(), testing);
136    }
137
138    #[test]
139    fn test_minimum_certainty() {
140        let td = tempfile::tempdir().unwrap();
141        std::fs::create_dir(td.path().join("debian")).unwrap();
142        std::fs::write(
143            td.path().join("debian/lintian-brush.conf"),
144            "minimum-certainty = possible\n",
145        )
146        .unwrap();
147        let cfg = Config::load_from_path(&td.path().join("debian/lintian-brush.conf")).unwrap();
148
149        assert_eq!(cfg.minimum_certainty(), Some(Certainty::Possible));
150    }
151
152    #[test]
153    fn test_update_changelog() {
154        let td = tempfile::tempdir().unwrap();
155        std::fs::create_dir(td.path().join("debian")).unwrap();
156        std::fs::write(
157            td.path().join("debian/lintian-brush.conf"),
158            "update-changelog = True\n",
159        )
160        .unwrap();
161        let cfg = Config::load_from_path(&td.path().join("debian/lintian-brush.conf")).unwrap();
162
163        assert_eq!(cfg.update_changelog(), Some(true));
164    }
165
166    #[test]
167    fn test_unknown() {
168        let td = tempfile::tempdir().unwrap();
169        std::fs::create_dir(td.path().join("debian")).unwrap();
170        std::fs::write(
171            td.path().join("debian/lintian-brush.conf"),
172            "unknown = dunno\n",
173        )
174        .unwrap();
175        let cfg = Config::load_from_path(&td.path().join("debian/lintian-brush.conf")).unwrap();
176        assert_eq!(cfg.compat_release(), None);
177    }
178
179    #[test]
180    fn test_missing() {
181        let td = tempfile::tempdir().unwrap();
182        let path = td.path().join("debian/lintian-brush.conf");
183        let cfg = Config::load_from_path(&path);
184        assert!(cfg.is_err());
185    }
186}