aur_depends/
base.rs

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/// Packages from a pkgbuild repo.
26#[derive(Debug, Eq, Clone, PartialEq, Ord, PartialOrd, Hash)]
27pub struct PkgbuildPackages {
28    /// the repo the package came from.
29    pub repo: String,
30    /// The srcinfo of the pkgbase.
31    pub srcinfo: Box<srcinfo::Srcinfo>,
32    /// The pkgs from the srcinfo to install.
33    pub pkgs: Vec<Pkgbuild>,
34    /// Should the package be built.
35    pub build: bool,
36}
37
38/// Describes an AUR package base.
39#[derive(Debug, Eq, Clone, PartialEq, Ord, PartialOrd, Hash)]
40pub struct AurBase {
41    /// List of packages belonging to the package base.
42    pub pkgs: Vec<AurPackage>,
43    /// Should the package be built.
44    pub build: bool,
45}
46
47/// A package base.
48/// This descripes  packages that should be built then installed.
49#[derive(Debug, Eq, Clone, PartialEq, Ord, PartialOrd, Hash)]
50pub enum Base {
51    /// Aur packages.
52    Aur(AurBase),
53    /// pkgbuild packages.
54    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    /// Gets the package base of base.
82    pub fn package_base(&self) -> &str {
83        &self.pkgs[0].pkg.package_base
84    }
85
86    /// Gets the version of base.
87    pub fn version(&self) -> String {
88        self.pkgs[0].pkg.version.clone()
89    }
90}
91
92impl PkgbuildPackages {
93    /// Gets the package base of base.
94    pub fn package_base(&self) -> &str {
95        &self.srcinfo.base.pkgbase
96    }
97
98    /// Gets the version of base.
99    pub fn version(&self) -> String {
100        self.srcinfo.version()
101    }
102}
103
104impl Base {
105    /// Gets the package base of base.
106    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    /// Gets the version of base.
114    pub fn version(&self) -> String {
115        match self {
116            Base::Aur(base) => base.version(),
117            Base::Pkgbuild(base) => base.version(),
118        }
119    }
120
121    /// Ammount of packages in this base.
122    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    /// Iterator of package names in this base.
130    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    /// Are any packages in this base make only.
140    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    /// Are any packages in this base targets.
148    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    /// Should the packages be built
156    pub fn build(&self) -> bool {
157        match self {
158            Base::Aur(a) => a.build,
159            Base::Pkgbuild(c) => c.build,
160        }
161    }
162
163    /// Formats a base into the format:
164    /// pkgname-ver
165    /// or, if there are multiple packages:
166    /// pkgbase-ver (pkg1 pkg2 pkg2)
167    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    /// True if the package base contains a single package
190    /// with the same name as the pkgbase.
191    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}