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 self.artifacts.push(artifact);
98 }
99
100 pub fn input_url(&self) -> Result<&str> {
101 if let Some(input_url) = &self.input_url {
102 Ok(input_url.as_str())
103 } else if !self.artifacts.is_empty() {
104 let mut artifacts = Vec::from_iter(self.artifacts.iter().collect::<Vec<_>>());
105 artifacts.sort_by_key(|a| &a.name);
106 let input = artifacts.into_iter().next().unwrap();
108 Ok(&input.url)
109 } else {
110 bail!("Package group has no artifacts")
111 }
112 }
113}
114
115#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, clap::ValueEnum)]
116pub enum Status {
117 #[serde(rename = "GOOD")]
118 #[clap(name = "GOOD")]
119 Good,
120 #[serde(rename = "BAD")]
121 #[clap(name = "BAD")]
122 Bad,
123 #[serde(rename = "UNKWN")]
124 #[clap(name = "UNKWN")]
125 Unknown,
126}
127
128impl Status {
129 pub fn fancy(&self) -> String {
130 match self {
131 Status::Good => "GOOD ".green().to_string(),
132 Status::Bad => "BAD ".red().to_string(),
133 Status::Unknown => "UNKWN".yellow().to_string(),
134 }
135 }
136}
137
138impl Deref for Status {
139 type Target = str;
140
141 fn deref(&self) -> &'static str {
142 match self {
143 Status::Good => "GOOD",
144 Status::Bad => "BAD",
145 Status::Unknown => "UNKWN",
146 }
147 }
148}
149
150impl FromStr for Status {
151 type Err = Error;
152
153 fn from_str(s: &str) -> Result<Status> {
154 match s {
155 "GOOD" => Ok(Status::Good),
156 "BAD" => Ok(Status::Bad),
157 "UNKWN" => Ok(Status::Unknown),
158 _ => bail!("Unknown status: {:?}", s),
159 }
160 }
161}