alpm_buildinfo/build_info/
v1.rs1use std::{
2 fmt::{Display, Formatter},
3 str::FromStr,
4};
5
6use alpm_types::{
7 Architecture,
8 BuildDate,
9 BuildDirectory,
10 BuildEnvironmentOption,
11 Checksum,
12 FullVersion,
13 InstalledPackage,
14 Name,
15 PackageOption,
16 Packager,
17 SchemaVersion,
18 digests::Sha256,
19 semver_version::Version as SemverVersion,
20};
21use serde_with::{DisplayFromStr, serde_as};
22
23use crate::{BuildInfoSchema, Error, build_info::format::BuildInfoFormat};
24
25#[serde_as]
61#[derive(Clone, Debug, serde::Deserialize, PartialEq, serde_more::SerializeMore)]
62#[more(key = "format", position = "front")]
63pub struct BuildInfoV1 {
64 #[serde_as(as = "DisplayFromStr")]
66 pub pkgname: Name,
67
68 #[serde_as(as = "DisplayFromStr")]
70 pub pkgbase: Name,
71
72 #[serde_as(as = "DisplayFromStr")]
74 pub pkgver: FullVersion,
75
76 #[serde_as(as = "DisplayFromStr")]
78 pub pkgarch: Architecture,
79
80 #[serde_as(as = "DisplayFromStr")]
82 pub pkgbuild_sha256sum: Checksum<Sha256>,
83
84 #[serde_as(as = "DisplayFromStr")]
86 pub packager: Packager,
87
88 #[serde_as(as = "DisplayFromStr")]
90 pub builddate: BuildDate,
91
92 #[serde_as(as = "DisplayFromStr")]
94 pub builddir: BuildDirectory,
95
96 #[serde_as(as = "Vec<DisplayFromStr>")]
98 #[serde(default)]
99 pub buildenv: Vec<BuildEnvironmentOption>,
100
101 #[serde_as(as = "Vec<DisplayFromStr>")]
103 #[serde(default)]
104 pub options: Vec<PackageOption>,
105
106 #[serde_as(as = "Vec<DisplayFromStr>")]
108 #[serde(default)]
109 pub installed: Vec<InstalledPackage>,
110}
111
112impl BuildInfoV1 {
113 fn format(&self) -> String {
115 BuildInfoSchema::V1(SchemaVersion::new(SemverVersion::new(1, 0, 0))).to_string()
116 }
117}
118
119impl FromStr for BuildInfoV1 {
120 type Err = Error;
121 fn from_str(input: &str) -> Result<BuildInfoV1, Self::Err> {
128 let build_info_format: BuildInfoFormat = alpm_parsers::custom_ini::from_str(input)?;
129 let schema_version: SchemaVersion = build_info_format.into();
130 if schema_version.inner().major != 1 {
131 return Err(Error::WrongSchemaVersion(schema_version));
132 }
133
134 let buildinfo: BuildInfoV1 = alpm_parsers::custom_ini::from_str(input)?;
135 Ok(buildinfo)
136 }
137}
138
139impl Display for BuildInfoV1 {
140 fn fmt(&self, fmt: &mut Formatter) -> std::fmt::Result {
141 write!(
142 fmt,
143 "format = {}\n\
144 pkgname = {}\n\
145 pkgbase = {}\n\
146 pkgver = {}\n\
147 pkgarch = {}\n\
148 pkgbuild_sha256sum = {}\n\
149 packager = {}\n\
150 builddate = {}\n\
151 builddir = {}\n\
152 {}\n\
153 {}\n\
154 {}\n\
155 ",
156 self.format(),
157 self.pkgname,
158 self.pkgbase,
159 self.pkgver,
160 self.pkgarch,
161 self.pkgbuild_sha256sum,
162 self.packager,
163 self.builddate,
164 self.builddir,
165 self.buildenv
166 .iter()
167 .map(|v| format!("buildenv = {v}"))
168 .collect::<Vec<String>>()
169 .join("\n"),
170 self.options
171 .iter()
172 .map(|v| format!("options = {v}"))
173 .collect::<Vec<String>>()
174 .join("\n"),
175 self.installed
176 .iter()
177 .map(|v| format!("installed = {v}"))
178 .collect::<Vec<String>>()
179 .join("\n"),
180 )
181 }
182}
183
184#[cfg(test)]
185mod tests {
186 use rstest::{fixture, rstest};
187 use testresult::TestResult;
188
189 use super::*;
190
191 #[fixture]
192 fn valid_buildinfov1() -> String {
193 r#"format = 1
194builddate = 1
195builddir = /build
196buildenv = ccache
197buildenv = color
198installed = bar-1.2.3-1-any
199installed = beh-2.2.3-4-any
200options = lto
201options = !strip
202packager = Foobar McFooface <foobar@mcfooface.org>
203pkgarch = any
204pkgbase = foo
205pkgbuild_sha256sum = b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c
206pkgname = foo
207pkgver = 1:1.0.0-1
208"#
209 .to_string()
210 }
211
212 #[fixture]
213 fn invalid_format_buildinfov1() -> String {
214 r#"format = 2
215builddate = 1
216builddir = /build
217buildenv = ccache
218buildenv = color
219installed = bar-1.2.3-1-any
220installed = beh-2.2.3-4-any
221options = lto
222options = !strip
223packager = Foobar McFooface <foobar@mcfooface.org>
224pkgarch = any
225pkgbase = foo
226pkgbuild_sha256sum = b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c
227pkgname = foo
228pkgver = 1:1.0.0-1
229"#
230 .to_string()
231 }
232
233 #[rstest]
234 fn buildinfov1_from_str(valid_buildinfov1: String) -> TestResult {
235 BuildInfoV1::from_str(&valid_buildinfov1)?;
236 Ok(())
237 }
238
239 #[rstest]
240 fn buildinfov1() -> TestResult {
241 BuildInfoV1 {
242 builddate: 1,
243 builddir: BuildDirectory::from_str("/build")?,
244 buildenv: vec![BuildEnvironmentOption::new("check")?],
245 installed: vec![InstalledPackage::from_str("bar-1:1.0.0-2-any")?],
246 options: vec![PackageOption::new("lto")?],
247 packager: Packager::from_str("Foobar McFooface <foobar@mcfooface.org>")?,
248 pkgarch: Architecture::Any,
249 pkgbase: Name::new("foo")?,
250 pkgbuild_sha256sum: Checksum::<Sha256>::calculate_from("foo"),
251 pkgname: Name::new("foo")?,
252 pkgver: FullVersion::from_str("1:1.0.0-1")?,
253 };
254 Ok(())
255 }
256
257 #[rstest]
258 fn buildinfov1_invalid_schemaversion(invalid_format_buildinfov1: String) -> TestResult {
259 assert!(BuildInfoV1::from_str(&invalid_format_buildinfov1).is_err());
260 Ok(())
261 }
262
263 #[rstest]
264 #[case("builddate = 2")]
265 #[case("builddir = /build2")]
266 #[case("format = 1")]
267 #[case("packager = Foobar McFooface <foobar@mcfooface.org>")]
268 #[case("pkgarch = any")]
269 #[case("pkgbase = foo")]
270 #[case("pkgbuild_sha256sum = b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c")]
271 #[case("pkgname = foo")]
272 #[case("pkgver = 1:1.0.0-1")]
273 fn buildinfov1_from_str_duplicate_fail(mut valid_buildinfov1: String, #[case] duplicate: &str) {
274 valid_buildinfov1.push_str(duplicate);
275 assert!(BuildInfoV1::from_str(&valid_buildinfov1).is_err());
276 }
277}