1use serde::Deserialize;
4use std::ops::Not;
5use std::path::{Path, PathBuf};
6
7pub enum GitHost {
9 Github,
10 Gitlab,
11}
12
13impl GitHost {
14 pub fn source(&self, package: &Package) -> String {
15 match self {
16 GitHost::Github => format!(
17 "{}/releases/download/v$pkgver/{}-$pkgver-x86_64.tar.gz",
18 package.repository, package.name
19 ),
20 GitHost::Gitlab => format!(
21 "{}/-/archive/v$pkgver/{}-$pkgver-x86_64.tar.gz",
22 package.repository, package.name
23 ),
24 }
25 }
26}
27
28#[derive(Deserialize, Debug)]
30pub struct Package {
31 pub name: String,
32 pub version: String,
33 pub authors: Vec<String>,
34 pub description: String,
35 pub repository: String,
36 pub license: String,
37 pub metadata: Option<Metadata>,
38 pub homepage: Option<String>,
39 pub documentation: Option<String>,
40}
41
42impl Package {
43 pub fn tarball(&self, output: &Path) -> PathBuf {
45 output.join(format!("{}-{}-x86_64.tar.gz", self.name, self.version))
46 }
47
48 pub fn git_host(&self) -> Option<GitHost> {
49 if self.repository.starts_with("https://github") {
50 Some(GitHost::Github)
51 } else if self.repository.starts_with("https://gitlab") {
52 Some(GitHost::Gitlab)
53 } else {
54 None
55 }
56 }
57
58 pub fn url(&self) -> &str {
61 self.homepage
62 .as_deref()
63 .or(self.documentation.as_deref())
64 .unwrap_or(&self.repository)
65 }
66}
67
68#[derive(Deserialize, Debug)]
83pub struct Metadata {
84 #[serde(default)]
86 pub depends: Vec<String>,
87 #[serde(default)]
89 pub optdepends: Vec<String>,
90 pub aur: Option<AUR>,
92}
93
94impl Metadata {
95 pub fn non_empty(&self) -> bool {
97 self.depends.is_empty().not()
98 || self.optdepends.is_empty().not()
99 || self
100 .aur
101 .as_ref()
102 .is_some_and(|aur| aur.depends.is_empty().not() || aur.optdepends.is_empty().not())
103 }
104}
105
106impl std::fmt::Display for Metadata {
107 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108 let (deps, opts) = if let Some(aur) = self.aur.as_ref() {
123 (aur.depends.as_slice(), aur.optdepends.as_slice())
124 } else {
125 (self.depends.as_slice(), self.optdepends.as_slice())
126 };
127
128 match deps {
129 [middle @ .., last] => {
130 write!(f, "depends=(")?;
131 for item in middle {
132 write!(f, "\"{}\" ", item)?;
133 }
134 if opts.is_empty().not() {
135 writeln!(f, "\"{}\")", last)?;
136 } else {
137 write!(f, "\"{}\")", last)?;
138 }
139 }
140 [] => {}
141 }
142
143 match opts {
144 [middle @ .., last] => {
145 write!(f, "optdepends=(")?;
146 for item in middle {
147 write!(f, "\"{}\" ", item)?;
148 }
149 write!(f, "\"{}\")", last)?;
150 }
151 [] => {}
152 }
153
154 Ok(())
155 }
156}
157
158#[derive(Deserialize, Debug)]
160pub struct AUR {
161 #[serde(default)]
162 depends: Vec<String>,
163 #[serde(default)]
164 optdepends: Vec<String>,
165 #[serde(default)]
166 pub files: Vec<(PathBuf, PathBuf)>,
167}