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 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 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}