1use crate::errors::*;
2use chrono::NaiveDateTime;
3use colored::*;
4use serde::{Deserialize, Serialize};
5use std::iter::FromIterator;
6use std::ops::Deref;
7use std::str::FromStr;
8
9pub mod api;
10pub mod auth;
11pub mod config;
12pub mod errors;
13pub mod http;
14pub mod utils;
15
16#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
17pub struct PkgRelease {
18 pub name: String,
19 pub version: String,
20 pub status: Status,
21 pub distro: String,
22 pub suite: String,
23 pub architecture: String,
24 pub artifact_url: String,
25 pub build_id: Option<i32>,
26 pub built_at: Option<NaiveDateTime>,
27 pub has_diffoscope: bool,
28 pub has_attestation: bool,
29}
30
31impl PkgRelease {
32 pub fn new(
33 name: String,
34 version: String,
35 distro: String,
36 suite: String,
37 architecture: String,
38 artifact_url: String,
39 ) -> PkgRelease {
40 PkgRelease {
41 name,
42 version,
43 status: Status::Unknown,
44 distro,
45 suite,
46 architecture,
47 artifact_url,
48 build_id: None,
49 built_at: None,
50 has_diffoscope: false,
51 has_attestation: false,
52 }
53 }
54}
55
56#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
57pub struct PkgGroup {
58 pub name: String,
59 pub version: String,
60
61 pub distro: String,
62 pub suite: String,
63 pub architecture: String,
64
65 pub input_url: Option<String>,
66 pub artifacts: Vec<PkgArtifact>,
67}
68
69#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
70pub struct PkgArtifact {
71 pub name: String,
72 pub version: String,
73 pub url: String,
74}
75
76impl PkgGroup {
77 pub fn new(
78 name: String,
79 version: String,
80 distro: String,
81 suite: String,
82 architecture: String,
83 input_url: Option<String>,
84 ) -> PkgGroup {
85 PkgGroup {
86 name,
87 version,
88 distro,
89 suite,
90 architecture,
91 input_url,
92 artifacts: Vec::new(),
93 }
94 }
95
96 pub fn add_artifact(&mut self, artifact: PkgArtifact) {
97 if !self.artifacts.contains(&artifact) {
99 self.artifacts.push(artifact);
100 }
101 }
102
103 pub fn input_url(&self) -> Result<&str> {
104 if let Some(input_url) = &self.input_url {
105 Ok(input_url.as_str())
106 } else if !self.artifacts.is_empty() {
107 let mut artifacts = Vec::from_iter(self.artifacts.iter().collect::<Vec<_>>());
108 artifacts.sort_by_key(|a| &a.name);
109 let input = artifacts.into_iter().next().unwrap();
111 Ok(&input.url)
112 } else {
113 bail!("Package group has no artifacts")
114 }
115 }
116}
117
118#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, clap::ValueEnum)]
119pub enum Status {
120 #[serde(rename = "GOOD")]
121 #[clap(name = "GOOD")]
122 Good,
123 #[serde(rename = "BAD")]
124 #[clap(name = "BAD")]
125 Bad,
126 #[serde(rename = "UNKWN")]
127 #[clap(name = "UNKWN")]
128 Unknown,
129}
130
131impl Status {
132 pub fn fancy(&self) -> String {
133 match self {
134 Status::Good => "GOOD ".green().to_string(),
135 Status::Bad => "BAD ".red().to_string(),
136 Status::Unknown => "UNKWN".yellow().to_string(),
137 }
138 }
139}
140
141impl Deref for Status {
142 type Target = str;
143
144 fn deref(&self) -> &'static str {
145 match self {
146 Status::Good => "GOOD",
147 Status::Bad => "BAD",
148 Status::Unknown => "UNKWN",
149 }
150 }
151}
152
153impl FromStr for Status {
154 type Err = Error;
155
156 fn from_str(s: &str) -> Result<Status> {
157 match s {
158 "GOOD" => Ok(Status::Good),
159 "BAD" => Ok(Status::Bad),
160 "UNKWN" => Ok(Status::Unknown),
161 _ => bail!("Unknown status: {:?}", s),
162 }
163 }
164}
165
166#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
167pub struct PublicKeys {
168 pub current: Vec<String>,
169}