zoi/pkg/
types.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Copy)]
5#[serde(rename_all = "lowercase")]
6#[derive(Default)]
7pub enum Scope {
8    #[default]
9    User,
10    System,
11    Project,
12}
13
14#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Copy)]
15#[serde(rename_all = "lowercase")]
16#[derive(Default)]
17pub enum PackageType {
18    #[default]
19    Package,
20    Collection,
21    App,
22    Extension,
23}
24
25#[derive(Debug, Serialize, Deserialize, Clone)]
26#[serde(rename_all = "lowercase")]
27pub enum UpdateType {
28    Change,
29    Vulnerability,
30    Update,
31}
32
33#[derive(Debug, Serialize, Deserialize, Clone)]
34pub struct UpdateInfo {
35    #[serde(rename = "type")]
36    pub update_type: UpdateType,
37    pub message: String,
38}
39
40#[derive(Debug, Serialize, Deserialize, Clone)]
41#[serde(tag = "type")]
42#[serde(rename_all = "kebab-case")]
43pub enum ExtensionChange {
44    RepoGit { add: String },
45    RegistryRepo { add: String },
46    RegistryAdd { add: String },
47    RepoAdd { add: String },
48    Project { add: String },
49    Pgp { name: String, key: String },
50}
51
52#[derive(Debug, Serialize, Deserialize, Clone)]
53pub struct ExtensionInfo {
54    #[serde(rename = "type")]
55    pub extension_type: String,
56    pub changes: Vec<ExtensionChange>,
57}
58
59#[derive(Debug, Serialize, Deserialize, Clone)]
60#[allow(dead_code)]
61pub struct Package {
62    pub name: String,
63    pub repo: String,
64    pub version: Option<String>,
65    #[serde(default, skip_serializing_if = "Option::is_none")]
66    pub sub_packages: Option<Vec<String>>,
67    #[serde(default, skip_serializing_if = "Option::is_none")]
68    pub main_subs: Option<Vec<String>>,
69    pub versions: Option<HashMap<String, String>>,
70    pub description: String,
71    pub website: Option<String>,
72    #[serde(default)]
73    pub readme: Option<String>,
74    #[serde(default)]
75    pub man: Option<String>,
76    #[serde(default)]
77    pub git: String,
78    pub maintainer: Maintainer,
79    pub author: Option<Author>,
80    #[serde(default)]
81    pub license: String,
82    #[serde(default)]
83    pub types: Vec<String>,
84    pub dependencies: Option<Dependencies>,
85    #[serde(rename = "type", default)]
86    pub package_type: PackageType,
87    pub alt: Option<String>,
88    #[serde(default)]
89    pub scope: Scope,
90    #[serde(default)]
91    pub bins: Option<Vec<String>>,
92    #[serde(default)]
93    pub conflicts: Option<Vec<String>>,
94    #[serde(default)]
95    pub tags: Vec<String>,
96    #[serde(default)]
97    pub extension: Option<ExtensionInfo>,
98    #[serde(default)]
99    pub rollback: Option<bool>,
100    #[serde(default)]
101    pub updates: Option<Vec<UpdateInfo>>,
102    #[serde(default)]
103    pub hooks: Option<Hooks>,
104}
105
106#[derive(Debug, Serialize, Deserialize, Clone)]
107#[serde(untagged)]
108pub enum PlatformOrStringVec {
109    StringVec(Vec<String>),
110    Platform(HashMap<String, Vec<String>>),
111}
112
113#[derive(Debug, Serialize, Deserialize, Clone, Default)]
114pub struct Hooks {
115    #[serde(default, skip_serializing_if = "Option::is_none")]
116    pub pre_install: Option<PlatformOrStringVec>,
117    #[serde(default, skip_serializing_if = "Option::is_none")]
118    pub post_install: Option<PlatformOrStringVec>,
119    #[serde(default, skip_serializing_if = "Option::is_none")]
120    pub pre_upgrade: Option<PlatformOrStringVec>,
121    #[serde(default, skip_serializing_if = "Option::is_none")]
122    pub post_upgrade: Option<PlatformOrStringVec>,
123    #[serde(default, skip_serializing_if = "Option::is_none")]
124    pub pre_remove: Option<PlatformOrStringVec>,
125    #[serde(default, skip_serializing_if = "Option::is_none")]
126    pub post_remove: Option<PlatformOrStringVec>,
127}
128
129#[derive(Debug, Serialize, Deserialize, Clone)]
130#[allow(dead_code)]
131pub struct Maintainer {
132    pub name: String,
133    pub email: String,
134    pub website: Option<String>,
135}
136
137#[derive(Debug, Serialize, Deserialize, Clone)]
138#[allow(dead_code)]
139pub struct Author {
140    pub name: String,
141    pub email: Option<String>,
142    pub website: Option<String>,
143}
144
145#[derive(Debug, Serialize, Deserialize, Clone)]
146#[allow(dead_code)]
147pub struct DependencyOptionGroup {
148    pub name: String,
149    pub desc: String,
150    #[serde(default)]
151    pub all: bool,
152    pub depends: Vec<String>,
153}
154
155#[derive(Debug, Serialize, Deserialize, Clone)]
156#[serde(untagged)]
157pub enum DependencyGroup {
158    Simple(Vec<String>),
159    Complex(ComplexDependencyGroup),
160}
161
162impl DependencyGroup {
163    pub fn get_required_simple(&self) -> Vec<String> {
164        match self {
165            DependencyGroup::Simple(deps) => deps.clone(),
166            DependencyGroup::Complex(group) => group.required.clone(),
167        }
168    }
169
170    pub fn get_required_options(&self) -> Vec<DependencyOptionGroup> {
171        match self {
172            DependencyGroup::Simple(_) => Vec::new(),
173            DependencyGroup::Complex(group) => group.options.clone(),
174        }
175    }
176
177    pub fn get_optional(&self) -> &Vec<String> {
178        match self {
179            DependencyGroup::Simple(_) => {
180                static EMPTY_VEC: Vec<String> = Vec::new();
181                &EMPTY_VEC
182            }
183            DependencyGroup::Complex(group) => &group.optional,
184        }
185    }
186}
187
188#[derive(Debug, Serialize, Deserialize, Clone, Default)]
189pub struct ComplexDependencyGroup {
190    #[serde(default)]
191    pub required: Vec<String>,
192    #[serde(default)]
193    pub options: Vec<DependencyOptionGroup>,
194    #[serde(default)]
195    pub optional: Vec<String>,
196    #[serde(default, skip_serializing_if = "Option::is_none")]
197    pub sub_packages: Option<HashMap<String, DependencyGroup>>,
198}
199
200#[derive(Debug, Serialize, Deserialize, Clone)]
201pub struct Dependencies {
202    #[serde(default)]
203    pub runtime: Option<DependencyGroup>,
204    #[serde(default)]
205    pub build: Option<DependencyGroup>,
206}
207
208#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
209pub enum InstallReason {
210    Direct,
211    Dependency { parent: String },
212}
213
214#[derive(Debug, Serialize, Deserialize, Clone)]
215pub struct InstallManifest {
216    pub name: String,
217    pub version: String,
218    #[serde(default, skip_serializing_if = "Option::is_none")]
219    pub sub_package: Option<String>,
220    pub repo: String,
221    pub registry_handle: String,
222    pub package_type: PackageType,
223    pub reason: InstallReason,
224    pub scope: Scope,
225    pub bins: Option<Vec<String>>,
226    pub conflicts: Option<Vec<String>>,
227    #[serde(default)]
228    pub installed_dependencies: Vec<String>,
229    #[serde(default)]
230    pub chosen_options: Vec<String>,
231    #[serde(default)]
232    pub chosen_optionals: Vec<String>,
233    #[serde(default)]
234    pub install_method: Option<String>,
235    #[serde(default)]
236    pub installed_files: Vec<String>,
237}
238
239#[derive(Debug, Serialize, Deserialize, Clone)]
240#[serde(rename_all = "camelCase")]
241pub enum TransactionOperation {
242    Install {
243        manifest: Box<InstallManifest>,
244    },
245    Uninstall {
246        manifest: Box<InstallManifest>,
247    },
248    Upgrade {
249        old_manifest: Box<InstallManifest>,
250        new_manifest: Box<InstallManifest>,
251    },
252}
253
254#[derive(Debug, Serialize, Deserialize, Clone)]
255pub struct Transaction {
256    pub id: String,
257    pub start_time: String,
258    pub operations: Vec<TransactionOperation>,
259}
260
261#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
262pub struct Registry {
263    pub handle: String,
264    pub url: String,
265}
266
267#[derive(Debug, Serialize, Deserialize, Default, Clone)]
268pub struct Config {
269    pub repos: Vec<String>,
270    pub package_managers: Option<Vec<String>>,
271    pub native_package_manager: Option<String>,
272    #[serde(default)]
273    pub telemetry_enabled: bool,
274    #[serde(skip_serializing_if = "Option::is_none")]
275    pub registry: Option<String>,
276    #[serde(default)]
277    pub default_registry: Option<Registry>,
278    #[serde(default)]
279    pub added_registries: Vec<Registry>,
280    #[serde(default)]
281    pub git_repos: Vec<String>,
282    #[serde(default)]
283    pub rollback_enabled: bool,
284    #[serde(default)]
285    pub policy: Policy,
286    #[serde(skip_serializing_if = "Option::is_none")]
287    pub parallel_jobs: Option<usize>,
288}
289
290#[derive(Debug, Serialize, Deserialize, Clone, Default)]
291pub struct Policy {
292    #[serde(default, skip_serializing_if = "is_false")]
293    pub repos_unoverridable: bool,
294    #[serde(default, skip_serializing_if = "is_false")]
295    pub telemetry_enabled_unoverridable: bool,
296    #[serde(default, skip_serializing_if = "is_false")]
297    pub rollback_enabled_unoverridable: bool,
298    #[serde(default, skip_serializing_if = "is_false")]
299    pub default_registry_unoverridable: bool,
300    #[serde(default, skip_serializing_if = "is_false")]
301    pub added_registries_unoverridable: bool,
302    #[serde(default, skip_serializing_if = "is_false")]
303    pub git_repos_unoverridable: bool,
304    #[serde(default, skip_serializing_if = "is_false")]
305    pub allow_deny_lists_unoverridable: bool,
306    #[serde(default, skip_serializing_if = "is_false")]
307    pub signature_enforcement_unoverridable: bool,
308
309    #[serde(default, skip_serializing_if = "Option::is_none")]
310    pub allowed_licenses: Option<Vec<String>>,
311    #[serde(default, skip_serializing_if = "Option::is_none")]
312    pub denied_licenses: Option<Vec<String>>,
313
314    #[serde(default, skip_serializing_if = "Option::is_none")]
315    pub allowed_packages: Option<Vec<String>>,
316    #[serde(default, skip_serializing_if = "Option::is_none")]
317    pub denied_packages: Option<Vec<String>>,
318
319    #[serde(default, skip_serializing_if = "Option::is_none")]
320    pub allowed_repos: Option<Vec<String>>,
321    #[serde(default, skip_serializing_if = "Option::is_none")]
322    pub denied_repos: Option<Vec<String>>,
323
324    #[serde(default, skip_serializing_if = "Option::is_none")]
325    pub signature_enforcement: Option<SignatureEnforcementPolicy>,
326}
327
328#[derive(Debug, Serialize, Deserialize, Clone, Default)]
329pub struct SignatureEnforcementPolicy {
330    #[serde(default)]
331    pub enable: bool,
332    #[serde(default)]
333    pub trusted_keys: Vec<String>,
334}
335
336fn is_false(b: &bool) -> bool {
337    !*b
338}
339
340#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
341pub struct SharableInstallManifest {
342    pub name: String,
343    pub version: String,
344    pub repo: String,
345    pub registry_handle: String,
346    pub scope: Scope,
347    #[serde(default, skip_serializing_if = "Vec::is_empty")]
348    pub chosen_options: Vec<String>,
349    #[serde(default, skip_serializing_if = "Vec::is_empty")]
350    pub chosen_optionals: Vec<String>,
351}
352
353#[derive(Debug, Serialize, Deserialize, Clone)]
354pub struct ZoiLockOld {
355    pub packages: HashMap<String, String>,
356}
357
358#[derive(Debug, Serialize, Deserialize, Clone, Default)]
359pub struct ZoiLock {
360    pub version: String,
361    #[serde(default, skip_serializing_if = "HashMap::is_empty")]
362    pub registries: HashMap<String, String>,
363    #[serde(default, skip_serializing_if = "HashMap::is_empty")]
364    pub packages: HashMap<String, String>,
365    #[serde(flatten)]
366    pub details: HashMap<String, HashMap<String, LockPackageDetail>>,
367}
368
369#[derive(Debug, Serialize, Deserialize, Clone)]
370pub struct LockPackageDetail {
371    pub version: String,
372    #[serde(default, skip_serializing_if = "Option::is_none")]
373    pub sub_package: Option<String>,
374    pub integrity: String,
375    #[serde(default, skip_serializing_if = "Vec::is_empty")]
376    pub dependencies: Vec<String>,
377    #[serde(default, skip_serializing_if = "Vec::is_empty")]
378    pub options_dependencies: Vec<String>,
379    #[serde(default, skip_serializing_if = "Vec::is_empty")]
380    pub optionals_dependencies: Vec<String>,
381}
382
383#[derive(Debug, Serialize, Deserialize, Clone)]
384pub struct Lockfile {
385    pub version: String,
386    pub packages: HashMap<String, LockfilePackage>,
387}
388
389#[derive(Debug, Serialize, Deserialize, Clone)]
390pub struct LockfilePackage {
391    pub name: String,
392    #[serde(default, skip_serializing_if = "Option::is_none")]
393    pub sub_package: Option<String>,
394    pub repo: String,
395    pub registry: String,
396    pub version: String,
397    pub date: String,
398    pub reason: InstallReason,
399    pub scope: Scope,
400    #[serde(default, skip_serializing_if = "Option::is_none")]
401    pub bins: Option<Vec<String>>,
402    #[serde(default, skip_serializing_if = "Option::is_none")]
403    pub conflicts: Option<Vec<String>>,
404    #[serde(default, skip_serializing_if = "Vec::is_empty")]
405    pub dependencies: Vec<String>,
406    #[serde(default, skip_serializing_if = "Vec::is_empty")]
407    pub chosen_options: Vec<String>,
408    #[serde(default, skip_serializing_if = "Vec::is_empty")]
409    pub chosen_optionals: Vec<String>,
410}
411
412#[derive(Debug, Serialize, Deserialize, Clone)]
413pub struct GitLink {
414    #[serde(rename = "type")]
415    pub link_type: String,
416    pub url: String,
417}
418
419#[derive(Debug, Serialize, Deserialize, Clone)]
420pub struct PkgLink {
421    #[serde(rename = "type")]
422    pub link_type: String,
423    pub url: String,
424    pub pgp: Option<String>,
425    pub hash: Option<String>,
426}
427
428#[derive(Debug, Serialize, Deserialize, Clone)]
429pub struct PgpKey {
430    pub name: String,
431    pub key: String,
432}
433
434#[derive(Debug, Serialize, Deserialize, Clone)]
435pub struct RepoEntry {
436    pub name: String,
437    #[serde(rename = "type")]
438    pub repo_type: String,
439    pub active: bool,
440}
441
442#[derive(Debug, Serialize, Deserialize, Clone)]
443pub struct RepoConfig {
444    pub name: String,
445    pub description: String,
446    pub git: Vec<GitLink>,
447    #[serde(default)]
448    pub pkg: Vec<PkgLink>,
449    #[serde(default)]
450    pub pgp: Vec<PgpKey>,
451    pub repos: Vec<RepoEntry>,
452}