debian_analyzer/
transition.rs1use crate::benfile::{read_benfile, Assignment, Expr};
5
6#[derive(Debug, Default)]
7pub struct Transition {
9 pub title: Option<String>,
11
12 pub is_good: Option<Expr>,
14
15 pub is_bad: Option<Expr>,
17
18 pub is_affected: Option<Expr>,
20
21 pub notes: Option<String>,
23
24 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
74pub 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}