oma_pm_operation_type/
lib.rs

1use std::fmt::Display;
2
3use bon::{Builder, builder};
4use num_enum::{FromPrimitive, IntoPrimitive};
5use oma_utils::human_bytes::HumanBytes;
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct OmaOperation {
10    pub install: Vec<InstallEntry>,
11    pub remove: Vec<RemoveEntry>,
12    pub disk_size_delta: i64,
13    pub autoremovable: (u64, u64),
14    pub total_download_size: u64,
15    pub suggest: Vec<(String, String)>,
16    pub recommend: Vec<(String, String)>,
17}
18
19impl Display for OmaOperation {
20    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21        let mut install = vec![];
22        let mut upgrade = vec![];
23        let mut reinstall = vec![];
24        let mut downgrade = vec![];
25        let mut remove = vec![];
26        let mut purge = vec![];
27
28        for ins in &self.install {
29            let name = ins.name();
30            let arch = ins.arch();
31            let version = ins.new_version();
32            match ins.op() {
33                InstallOperation::Default | InstallOperation::Download => unreachable!(),
34                InstallOperation::Install => {
35                    if !ins.automatic() {
36                        install.push(format!("{name}:{arch} ({version})"));
37                    } else {
38                        install.push(format!("{name}:{arch} ({version}, automatic)"));
39                    }
40                }
41                InstallOperation::ReInstall => {
42                    reinstall.push(format!("{name}:{arch} ({version})"));
43                }
44                InstallOperation::Upgrade => {
45                    // Upgrade 的情况下 old_version 的值肯定存在,因此直接 unwreap
46                    upgrade.push(format!(
47                        "{name}:{arch} ({}, {version})",
48                        ins.old_version().unwrap()
49                    ));
50                }
51                InstallOperation::Downgrade => {
52                    downgrade.push(format!("{name}:{arch} ({version})"));
53                }
54            }
55        }
56
57        for rm in &self.remove {
58            let tags = rm.details();
59            let name = rm.name();
60            let version = rm.version();
61            let arch = rm.arch();
62
63            let mut s = format!("{name}:{arch}");
64            if let Some(ver) = version {
65                s.push_str(&format!(" ({ver})"));
66            }
67
68            if tags.contains(&RemoveTag::Purge) {
69                purge.push(s);
70            } else {
71                remove.push(s);
72            }
73        }
74
75        if !install.is_empty() {
76            writeln!(f, "Install: {}", install.join(", "))?;
77        }
78
79        if !upgrade.is_empty() {
80            writeln!(f, "Upgrade: {}", upgrade.join(", "))?;
81        }
82
83        if !reinstall.is_empty() {
84            writeln!(f, "ReInstall: {}", reinstall.join(", "))?;
85        }
86
87        if !downgrade.is_empty() {
88            writeln!(f, "Downgrade: {}", downgrade.join(", "))?;
89        }
90
91        if !remove.is_empty() {
92            writeln!(f, "Remove: {}", remove.join(", "))?;
93        }
94
95        if !purge.is_empty() {
96            writeln!(f, "Purge: {}", purge.join(", "))?;
97        }
98
99        let (symbol, n) = if self.disk_size_delta >= 0 {
100            ("+", self.disk_size_delta as u64)
101        } else {
102            ("-", (0 - self.disk_size_delta) as u64)
103        };
104
105        writeln!(f, "Size-delta: {symbol}{}", HumanBytes(n.to_owned()))?;
106
107        Ok(())
108    }
109}
110
111#[derive(Debug, PartialEq, Eq, Hash, Clone, Default, Serialize, Deserialize, Builder)]
112pub struct InstallEntry {
113    name: String,
114    name_without_arch: String,
115    old_version: Option<String>,
116    new_version: String,
117    old_size: Option<u64>,
118    new_size: u64,
119    pkg_urls: Vec<PackageUrl>,
120    sha256: Option<String>,
121    md5: Option<String>,
122    sha512: Option<String>,
123    arch: String,
124    download_size: u64,
125    op: InstallOperation,
126    #[builder(default)]
127    automatic: bool,
128    index: usize,
129}
130
131#[derive(Debug, PartialEq, Eq, Hash, Clone, Default, Serialize, Deserialize, Builder)]
132pub struct PackageUrl {
133    pub download_url: String,
134    pub index_url: String,
135}
136
137#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
138pub struct RemoveEntry {
139    name: String,
140    version: Option<String>,
141    size: u64,
142    details: Vec<RemoveTag>,
143    arch: String,
144    index: usize,
145}
146
147#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
148pub enum RemoveTag {
149    Purge,
150    AutoRemove,
151    Resolver,
152}
153
154#[derive(
155    Debug,
156    PartialEq,
157    Eq,
158    Hash,
159    Clone,
160    Default,
161    Serialize,
162    Deserialize,
163    IntoPrimitive,
164    FromPrimitive,
165    Copy,
166)]
167#[repr(u8)]
168pub enum InstallOperation {
169    #[default]
170    Default = 0,
171    Install,
172    ReInstall,
173    Upgrade,
174    Downgrade,
175    Download,
176}
177
178impl InstallEntry {
179    pub fn name(&self) -> &str {
180        &self.name
181    }
182
183    pub fn name_without_arch(&self) -> &str {
184        &self.name_without_arch
185    }
186
187    pub fn old_size(&self) -> Option<u64> {
188        self.old_size
189    }
190
191    pub fn new_size(&self) -> u64 {
192        self.new_size
193    }
194
195    pub fn old_version(&self) -> Option<&str> {
196        self.old_version.as_deref()
197    }
198
199    pub fn new_version(&self) -> &str {
200        &self.new_version
201    }
202
203    pub fn pkg_urls(&self) -> &[PackageUrl] {
204        &self.pkg_urls
205    }
206
207    pub fn sha256(&self) -> Option<&str> {
208        self.sha256.as_deref()
209    }
210
211    pub fn md5(&self) -> Option<&str> {
212        self.md5.as_deref()
213    }
214
215    pub fn sha512(&self) -> Option<&str> {
216        self.sha512.as_deref()
217    }
218
219    pub fn arch(&self) -> &str {
220        &self.arch
221    }
222
223    pub fn download_size(&self) -> u64 {
224        self.download_size
225    }
226
227    pub fn op(&self) -> &InstallOperation {
228        &self.op
229    }
230
231    pub fn automatic(&self) -> bool {
232        self.automatic
233    }
234
235    pub fn index(&self) -> usize {
236        self.index
237    }
238}
239
240impl RemoveEntry {
241    pub fn new(
242        name: String,
243        version: Option<String>,
244        size: u64,
245        details: Vec<RemoveTag>,
246        arch: String,
247        index: usize,
248    ) -> Self {
249        Self {
250            name,
251            version,
252            size,
253            details,
254            arch,
255            index,
256        }
257    }
258
259    pub fn name(&self) -> &str {
260        &self.name
261    }
262
263    pub fn version(&self) -> Option<&str> {
264        self.version.as_deref()
265    }
266
267    pub fn size(&self) -> u64 {
268        self.size
269    }
270
271    pub fn details(&self) -> &[RemoveTag] {
272        &self.details
273    }
274
275    pub fn arch(&self) -> &str {
276        &self.arch
277    }
278
279    pub fn index(&self) -> usize {
280        self.index
281    }
282}