debian_analyzer/
transition.rs

1//! Handling of transitions
2//!
3//! See https://release.debian.org/transitions/ for more information about transitions.
4use crate::benfile::{read_benfile, Assignment, Expr};
5
6#[derive(Debug, Default)]
7/// A transition
8pub struct Transition {
9    /// The title of the transition
10    pub title: Option<String>,
11
12    /// Expression to check if the transition has been applied
13    pub is_good: Option<Expr>,
14
15    /// Expression to check if the transition has not been applied
16    pub is_bad: Option<Expr>,
17
18    /// Expression to check if a package is involved in the transition
19    pub is_affected: Option<Expr>,
20
21    /// Notes about the transition
22    pub notes: Option<String>,
23
24    /// Whether to export the transition
25    pub export: Option<bool>,
26}
27
28impl std::convert::TryFrom<Vec<Assignment>> for Transition {
29    type Error = String;
30
31    fn try_from(value: Vec<Assignment>) -> Result<Self, Self::Error> {
32        let mut transition = Transition::default();
33        for assignment in value.iter() {
34            match assignment.field.as_str() {
35                "title" => {
36                    transition.title = if let Expr::String(s) = &assignment.expr {
37                        Some(s.to_string())
38                    } else {
39                        return Err("title must be a string".to_string());
40                    }
41                }
42                "is_good" => {
43                    transition.is_good = Some(assignment.expr.clone());
44                }
45                "is_bad" => {
46                    transition.is_bad = Some(assignment.expr.clone());
47                }
48                "is_affected" => {
49                    transition.is_affected = Some(assignment.expr.clone());
50                }
51                "notes" => {
52                    transition.notes = if let Expr::String(s) = &assignment.expr {
53                        Some(s.to_string())
54                    } else {
55                        return Err("notes must be a string".to_string());
56                    }
57                }
58                "export" => {
59                    transition.export = if let Expr::Bool(b) = assignment.expr {
60                        Some(b)
61                    } else {
62                        return Err("export must be a boolean".to_string());
63                    }
64                }
65                n => {
66                    log::warn!("Unknown field: {}", n);
67                }
68            }
69        }
70        Ok(transition)
71    }
72}
73
74/// Read a transition from a reader
75pub fn read_transition<R: std::io::Read>(reader: &mut R) -> Result<Transition, String> {
76    let benfile = read_benfile(reader).map_err(|e| e.to_string())?;
77    Transition::try_from(benfile)
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83
84    #[test]
85    fn test_parse_transition() {
86        let input = r###"title = "libsoup2.4 -> libsoup3";
87is_affected = .build-depends ~ /libsoup2.4-dev|libsoup-gnome2.4-dev|libsoup-3.0-dev/ | .build-depends-arch ~ /libsoup2.4-dev|libsoup-gnome2.4-dev|libsoup-3.0-dev/ | .build-depends ~ /gir1.2-soup-2.4|gir1.2-soup-3.0/ | .depends ~ /gir1.2-soup-2.4/;
88is_good = .depends ~ /libsoup-3.0-0|gir1.2-soup-3.0/;
89is_bad = .depends ~ /libsoup-2.4-1|libsoup-gnome-2.4-1|gir1.2-soup-2.4/;
90notes = "https://bugs.debian.org/cgi-bin/pkgreport.cgi?users=pkg-gnome-maintainers@lists.alioth.debian.org&tag=libsoup2";
91export = false;
92"###;
93        let transition = read_transition(&mut input.as_bytes()).unwrap();
94        assert_eq!(transition.title, Some("libsoup2.4 -> libsoup3".to_string()));
95        assert_eq!(
96            transition.is_affected,
97            Some(Expr::Or(vec![
98                Box::new(Expr::FieldRegex(
99                    "build-depends".to_string(),
100                    "libsoup2.4-dev|libsoup-gnome2.4-dev|libsoup-3.0-dev".to_string()
101                )),
102                Box::new(Expr::FieldRegex(
103                    "build-depends-arch".to_string(),
104                    "libsoup2.4-dev|libsoup-gnome2.4-dev|libsoup-3.0-dev".to_string()
105                )),
106                Box::new(Expr::FieldRegex(
107                    "build-depends".to_string(),
108                    "gir1.2-soup-2.4|gir1.2-soup-3.0".to_string()
109                )),
110                Box::new(Expr::FieldRegex(
111                    "depends".to_string(),
112                    "gir1.2-soup-2.4".to_string()
113                ))
114            ]))
115        );
116        assert_eq!(
117            transition.is_good,
118            Some(Expr::FieldRegex(
119                "depends".to_string(),
120                "libsoup-3.0-0|gir1.2-soup-3.0".to_string()
121            ))
122        );
123        assert_eq!(
124            transition.is_bad,
125            Some(Expr::FieldRegex(
126                "depends".to_string(),
127                "libsoup-2.4-1|libsoup-gnome-2.4-1|gir1.2-soup-2.4".to_string()
128            ))
129        );
130        assert_eq!(transition.notes, Some("https://bugs.debian.org/cgi-bin/pkgreport.cgi?users=pkg-gnome-maintainers@lists.alioth.debian.org&tag=libsoup2".to_string()));
131        assert_eq!(transition.export, Some(false));
132    }
133}