1use crate::{AurPackage, Pkgbuild};
2
3use std::fmt::{Display, Formatter, Write};
4
5enum PkgNames<A, C> {
6 Aur(A),
7 Pkgbuild(C),
8}
9
10impl<'a, A, C> Iterator for PkgNames<A, C>
11where
12 A: Iterator<Item = &'a str>,
13 C: Iterator<Item = &'a str>,
14{
15 type Item = &'a str;
16
17 fn next(&mut self) -> Option<Self::Item> {
18 match self {
19 PkgNames::Aur(i) => i.next(),
20 PkgNames::Pkgbuild(i) => i.next(),
21 }
22 }
23}
24
25#[derive(Debug, Eq, Clone, PartialEq, Ord, PartialOrd, Hash)]
27pub struct PkgbuildPackages {
28 pub repo: String,
30 pub srcinfo: Box<srcinfo::Srcinfo>,
32 pub pkgs: Vec<Pkgbuild>,
34 pub build: bool,
36}
37
38#[derive(Debug, Eq, Clone, PartialEq, Ord, PartialOrd, Hash)]
40pub struct AurBase {
41 pub pkgs: Vec<AurPackage>,
43 pub build: bool,
45}
46
47#[derive(Debug, Eq, Clone, PartialEq, Ord, PartialOrd, Hash)]
50pub enum Base {
51 Aur(AurBase),
53 Pkgbuild(PkgbuildPackages),
55}
56
57impl Display for AurBase {
58 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
59 let pkgs = self.pkgs.iter().map(|p| p.pkg.name.as_str());
60 Base::write_base(f, self.package_base(), &self.version(), pkgs)
61 }
62}
63
64impl Display for PkgbuildPackages {
65 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
66 let pkgs = self.pkgs.iter().map(|p| p.pkg.pkgname.as_str());
67 Base::write_base(f, self.package_base(), &self.version(), pkgs)
68 }
69}
70
71impl Display for Base {
72 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
73 match self {
74 Base::Aur(base) => base.fmt(f),
75 Base::Pkgbuild(base) => base.fmt(f),
76 }
77 }
78}
79
80impl AurBase {
81 pub fn package_base(&self) -> &str {
83 &self.pkgs[0].pkg.package_base
84 }
85
86 pub fn version(&self) -> String {
88 self.pkgs[0].pkg.version.clone()
89 }
90}
91
92impl PkgbuildPackages {
93 pub fn package_base(&self) -> &str {
95 &self.srcinfo.base.pkgbase
96 }
97
98 pub fn version(&self) -> String {
100 self.srcinfo.version()
101 }
102}
103
104impl Base {
105 pub fn package_base(&self) -> &str {
107 match self {
108 Base::Aur(base) => base.package_base(),
109 Base::Pkgbuild(base) => base.package_base(),
110 }
111 }
112
113 pub fn version(&self) -> String {
115 match self {
116 Base::Aur(base) => base.version(),
117 Base::Pkgbuild(base) => base.version(),
118 }
119 }
120
121 pub fn package_count(&self) -> usize {
123 match self {
124 Base::Aur(base) => base.pkgs.len(),
125 Base::Pkgbuild(base) => base.pkgs.len(),
126 }
127 }
128
129 pub fn packages(&self) -> impl Iterator<Item = &str> {
131 match self {
132 Base::Aur(base) => PkgNames::Aur(base.pkgs.iter().map(|p| p.pkg.name.as_str())),
133 Base::Pkgbuild(base) => {
134 PkgNames::Pkgbuild(base.pkgs.iter().map(|p| p.pkg.pkgname.as_str()))
135 }
136 }
137 }
138
139 pub fn make(&self) -> bool {
141 match self {
142 Base::Aur(a) => a.pkgs.iter().any(|p| p.make),
143 Base::Pkgbuild(c) => c.pkgs.iter().any(|p| p.make),
144 }
145 }
146
147 pub fn target(&self) -> bool {
149 match self {
150 Base::Aur(a) => a.pkgs.iter().any(|p| p.target),
151 Base::Pkgbuild(c) => c.pkgs.iter().any(|p| p.target),
152 }
153 }
154
155 pub fn build(&self) -> bool {
157 match self {
158 Base::Aur(a) => a.build,
159 Base::Pkgbuild(c) => c.build,
160 }
161 }
162
163 pub fn write_base<'a, W: Write, I: IntoIterator<Item = &'a str>>(
168 mut writer: W,
169 pkgbase: &str,
170 ver: &str,
171 pkgs: I,
172 ) -> std::fmt::Result {
173 let mut pkgs = pkgs.into_iter().peekable();
174 let name = pkgs.next().unwrap_or("");
175
176 if pkgs.peek().is_none() && name == pkgbase {
177 write!(writer, "{pkgbase}-{ver}")
178 } else {
179 write!(writer, "{pkgbase}-{ver} ({name}")?;
180 for pkg in pkgs {
181 writer.write_str(" ")?;
182 writer.write_str(pkg.as_ref())?;
183 }
184 writer.write_str(")")?;
185 Ok(())
186 }
187 }
188
189 pub fn base_is_pkg<'a, I: IntoIterator<Item = &'a str>>(pkgbase: &str, pkgs: I) -> bool {
192 let mut pkgs = pkgs.into_iter();
193 let Some(p) = pkgs.next() else { return false };
194 p == pkgbase && pkgs.next().is_none()
195 }
196}