flake_edit/
change.rs

1#![allow(clippy::option_map_unit_fn)]
2use crate::walk::Context;
3
4#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)]
5pub enum Change {
6    #[default]
7    None,
8    Add {
9        id: Option<String>,
10        uri: Option<String>,
11        // Add an input as a flake.
12        flake: bool,
13    },
14    Remove {
15        id: ChangeId,
16    },
17    Pin {
18        id: String,
19    },
20    Change {
21        id: Option<String>,
22        uri: Option<String>,
23        ref_or_rev: Option<String>,
24    },
25}
26
27#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
28pub struct ChangeId(String);
29
30impl ChangeId {
31    pub fn follows(&self) -> Option<String> {
32        let id = &self.0;
33        let follows = id.split_once('.');
34        follows.map(|(_pre, post)| post.into())
35    }
36    pub fn input(&self) -> Option<String> {
37        let id = &self.0;
38        let follows = id.split_once('.');
39        if let Some((pre, _post)) = follows {
40            Some(pre.into())
41        } else {
42            Some(id.clone())
43        }
44    }
45    pub fn matches_with_follows(&self, input: &str, follows: Option<String>) -> bool {
46        if let Some(input_id) = self.input() {
47            if self.follows().is_some() {
48                (self.follows() == follows) && (input_id == input)
49            } else {
50                input_id == input
51            }
52        } else {
53            false
54        }
55    }
56    // The context carries the input attribute
57    pub fn matches_with_ctx(&self, follows: &str, ctx: Option<Context>) -> bool {
58        let ctx = ctx.and_then(|f| f.level().first().cloned());
59
60        if let Some(input_id) = self.input() {
61            if let Some(ctx) = ctx {
62                if self.follows().is_some() {
63                    (input_id == ctx) && (self.follows() == Some(follows.into()))
64                } else {
65                    input_id == ctx
66                }
67            } else {
68                input_id == follows
69            }
70        } else {
71            false
72        }
73    }
74}
75
76impl std::fmt::Display for ChangeId {
77    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78        write!(f, "{}", self.0)
79    }
80}
81
82impl From<String> for ChangeId {
83    fn from(value: String) -> Self {
84        ChangeId(value)
85    }
86}
87
88impl Change {
89    pub fn id(&self) -> Option<ChangeId> {
90        match self {
91            Change::None => None,
92            Change::Add { id, .. } => id.clone().map(|id| id.into()),
93            Change::Remove { id } => Some(id.clone()),
94            Change::Change { id, .. } => id.clone().map(|id| id.into()),
95            Change::Pin { id } => Some(id.clone().into()),
96        }
97    }
98    pub fn is_remove(&self) -> bool {
99        matches!(self, Change::Remove { .. })
100    }
101    pub fn is_some(&self) -> bool {
102        !matches!(self, Change::None)
103    }
104    pub fn is_add(&self) -> bool {
105        matches!(self, Change::Add { .. })
106    }
107}