1use std::collections::BTreeMap;
3
4use alpm_types::{
5 Architecture,
6 Architectures,
7 Epoch,
8 FullVersion,
9 License,
10 MakepkgOption,
11 Name,
12 OpenPGPIdentifier,
13 OptionalDependency,
14 PackageDescription,
15 PackageRelation,
16 PackageRelease,
17 PackageVersion,
18 RelationOrSoname,
19 RelativeFilePath,
20 SkippableChecksum,
21 Source,
22 SystemArchitecture,
23 Url,
24 digests::{Blake2b512, Crc32Cksum, Md5, Sha1, Sha224, Sha256, Sha384, Sha512},
25};
26use serde::{Deserialize, Serialize};
27
28use super::package::PackageArchitecture;
29use crate::{
30 Error,
31 source_info::parser::{self, PackageBaseProperty, RawPackageBase, SharedMetaProperty},
32};
33#[cfg(doc)]
34use crate::{MergedPackage, SourceInfoV1, source_info::v1::package::Package};
35
36#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
44pub struct PackageBase {
45 pub name: Name,
47 pub description: Option<PackageDescription>,
49 pub url: Option<Url>,
51 pub changelog: Option<RelativeFilePath>,
53 pub licenses: Vec<License>,
55
56 pub install: Option<RelativeFilePath>,
59 pub groups: Vec<String>,
61 pub options: Vec<MakepkgOption>,
63 pub backups: Vec<RelativeFilePath>,
65
66 pub version: FullVersion,
69 pub pgp_fingerprints: Vec<OpenPGPIdentifier>,
72
73 pub architectures: Architectures,
75 pub architecture_properties: BTreeMap<SystemArchitecture, PackageBaseArchitecture>,
77
78 pub dependencies: Vec<RelationOrSoname>,
80 pub optional_dependencies: Vec<OptionalDependency>,
82 pub provides: Vec<RelationOrSoname>,
84 pub conflicts: Vec<PackageRelation>,
86 pub replaces: Vec<PackageRelation>,
88 pub check_dependencies: Vec<PackageRelation>,
93 pub make_dependencies: Vec<PackageRelation>,
95
96 pub sources: Vec<Source>,
98 pub no_extracts: Vec<String>,
100 pub b2_checksums: Vec<SkippableChecksum<Blake2b512>>,
102 pub md5_checksums: Vec<SkippableChecksum<Md5>>,
104 pub sha1_checksums: Vec<SkippableChecksum<Sha1>>,
106 pub sha224_checksums: Vec<SkippableChecksum<Sha224>>,
108 pub sha256_checksums: Vec<SkippableChecksum<Sha256>>,
110 pub sha384_checksums: Vec<SkippableChecksum<Sha384>>,
112 pub sha512_checksums: Vec<SkippableChecksum<Sha512>>,
114 pub crc_checksums: Vec<SkippableChecksum<Crc32Cksum>>,
116}
117
118#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
123pub struct PackageBaseArchitecture {
124 pub dependencies: Vec<RelationOrSoname>,
126 pub optional_dependencies: Vec<OptionalDependency>,
128 pub provides: Vec<RelationOrSoname>,
130 pub conflicts: Vec<PackageRelation>,
132 pub replaces: Vec<PackageRelation>,
134 pub check_dependencies: Vec<PackageRelation>,
139 pub make_dependencies: Vec<PackageRelation>,
141
142 pub sources: Vec<Source>,
144 pub b2_checksums: Vec<SkippableChecksum<Blake2b512>>,
146 pub md5_checksums: Vec<SkippableChecksum<Md5>>,
148 pub sha1_checksums: Vec<SkippableChecksum<Sha1>>,
150 pub sha224_checksums: Vec<SkippableChecksum<Sha224>>,
152 pub sha256_checksums: Vec<SkippableChecksum<Sha256>>,
154 pub sha384_checksums: Vec<SkippableChecksum<Sha384>>,
156 pub sha512_checksums: Vec<SkippableChecksum<Sha512>>,
158 pub crc_checksums: Vec<SkippableChecksum<Crc32Cksum>>,
160}
161
162impl PackageBaseArchitecture {
163 pub fn merge_package_properties(&mut self, properties: PackageArchitecture) {
168 properties.dependencies.merge_vec(&mut self.dependencies);
169 properties
170 .optional_dependencies
171 .merge_vec(&mut self.optional_dependencies);
172 properties.provides.merge_vec(&mut self.provides);
173 properties.conflicts.merge_vec(&mut self.conflicts);
174 properties.replaces.merge_vec(&mut self.replaces);
175 }
176}
177
178macro_rules! package_base_arch_prop {
184 (
185 $architecture_properties:ident,
186 $arch_property:ident,
187 $field_name:ident,
188 ) => {
189 if let Some(architecture) = $arch_property.architecture
192 && let Architecture::Some(system_arch) = architecture
193 {
194 let architecture_properties = $architecture_properties
196 .entry(system_arch)
197 .or_insert(PackageBaseArchitecture::default());
198
199 architecture_properties
201 .$field_name
202 .push($arch_property.value);
203 } else {
204 $field_name.push($arch_property.value)
205 }
206 };
207}
208
209impl PackageBase {
210 pub fn new_with_defaults(name: Name, version: FullVersion) -> Self {
233 PackageBase {
234 name,
235 version,
236 description: None,
237 architectures: Architectures::Some(Vec::new()),
238 url: None,
239 licenses: Vec::new(),
240 groups: Vec::new(),
241 dependencies: Vec::new(),
242 make_dependencies: Vec::new(),
243 check_dependencies: Vec::new(),
244 optional_dependencies: Vec::new(),
245 provides: Vec::new(),
246 conflicts: Vec::new(),
247 replaces: Vec::new(),
248 backups: Vec::new(),
249 options: Vec::new(),
250 install: None,
251 changelog: None,
252 sources: Vec::new(),
253 no_extracts: Vec::new(),
254 md5_checksums: Vec::new(),
255 sha1_checksums: Vec::new(),
256 sha224_checksums: Vec::new(),
257 sha256_checksums: Vec::new(),
258 sha384_checksums: Vec::new(),
259 sha512_checksums: Vec::new(),
260 b2_checksums: Vec::new(),
261 crc_checksums: Vec::new(),
262 pgp_fingerprints: Vec::new(),
263 architecture_properties: BTreeMap::new(),
264 }
265 }
266
267 pub fn from_parsed(parsed: RawPackageBase) -> Result<Self, Error> {
275 let mut description = None;
276 let mut url = None;
277 let mut licenses = Vec::new();
278 let mut changelog = None;
279 let mut architectures = Vec::new();
280 let mut architecture_properties = BTreeMap::new();
281
282 let mut install = None;
284 let mut groups = Vec::new();
285 let mut options = Vec::new();
286 let mut backups = Vec::new();
287
288 let mut epoch: Option<Epoch> = None;
290 let mut package_version: Option<PackageVersion> = None;
291 let mut package_release: Option<PackageRelease> = None;
292 let mut pgp_fingerprints = Vec::new();
293
294 let mut dependencies = Vec::new();
295 let mut optional_dependencies = Vec::new();
296 let mut provides = Vec::new();
297 let mut conflicts = Vec::new();
298 let mut replaces = Vec::new();
299 let mut check_dependencies = Vec::new();
303 let mut make_dependencies = Vec::new();
304
305 let mut sources = Vec::new();
306 let mut no_extracts = Vec::new();
307 let mut b2_checksums = Vec::new();
308 let mut md5_checksums = Vec::new();
309 let mut sha1_checksums = Vec::new();
310 let mut sha224_checksums = Vec::new();
311 let mut sha256_checksums = Vec::new();
312 let mut sha384_checksums = Vec::new();
313 let mut sha512_checksums = Vec::new();
314 let mut crc_checksums = Vec::new();
315
316 for prop in parsed.properties.iter() {
318 let PackageBaseProperty::MetaProperty(SharedMetaProperty::Architecture(architecture)) =
320 prop
321 else {
322 continue;
323 };
324 architectures.push(architecture);
325 }
326
327 if architectures.is_empty() {
330 return Err(Error::MissingKeyword { keyword: "arch" });
331 }
332
333 let architectures: Architectures = architectures.try_into()?;
336
337 for prop in parsed.properties.into_iter() {
338 match prop {
339 PackageBaseProperty::EmptyLine | PackageBaseProperty::Comment(_) => continue,
341 PackageBaseProperty::PackageVersion(inner) => package_version = Some(inner),
342 PackageBaseProperty::PackageRelease(inner) => package_release = Some(inner),
343 PackageBaseProperty::PackageEpoch(inner) => epoch = Some(inner),
344 PackageBaseProperty::ValidPgpKeys(inner) => {
345 pgp_fingerprints.push(inner);
346 }
347 PackageBaseProperty::CheckDependency(arch_property) => {
348 package_base_arch_prop!(
349 architecture_properties,
350 arch_property,
351 check_dependencies,
352 )
353 }
354 PackageBaseProperty::MakeDependency(arch_property) => {
355 package_base_arch_prop!(
356 architecture_properties,
357 arch_property,
358 make_dependencies,
359 )
360 }
361 PackageBaseProperty::MetaProperty(shared_meta_property) => {
362 match shared_meta_property {
363 SharedMetaProperty::Description(inner) => description = Some(inner),
364 SharedMetaProperty::Url(inner) => url = Some(inner),
365 SharedMetaProperty::License(inner) => licenses.push(inner),
366 SharedMetaProperty::Architecture(_) => continue,
368 SharedMetaProperty::Changelog(inner) => changelog = Some(inner),
369 SharedMetaProperty::Install(inner) => install = Some(inner),
370 SharedMetaProperty::Group(inner) => groups.push(inner),
371 SharedMetaProperty::Option(inner) => options.push(inner),
372 SharedMetaProperty::Backup(inner) => backups.push(inner),
373 }
374 }
375 PackageBaseProperty::RelationProperty(relation_property) => match relation_property
376 {
377 parser::RelationProperty::Dependency(arch_property) => package_base_arch_prop!(
378 architecture_properties,
379 arch_property,
380 dependencies,
381 ),
382 parser::RelationProperty::OptionalDependency(arch_property) => {
383 package_base_arch_prop!(
384 architecture_properties,
385 arch_property,
386 optional_dependencies,
387 )
388 }
389 parser::RelationProperty::Provides(arch_property) => {
390 package_base_arch_prop!(architecture_properties, arch_property, provides,)
391 }
392 parser::RelationProperty::Conflicts(arch_property) => {
393 package_base_arch_prop!(architecture_properties, arch_property, conflicts,)
394 }
395 parser::RelationProperty::Replaces(arch_property) => {
396 package_base_arch_prop!(architecture_properties, arch_property, replaces,)
397 }
398 },
399 PackageBaseProperty::SourceProperty(source_property) => match source_property {
400 parser::SourceProperty::Source(arch_property) => {
401 package_base_arch_prop!(architecture_properties, arch_property, sources,)
402 }
403 parser::SourceProperty::NoExtract(value) => no_extracts.push(value),
404 parser::SourceProperty::B2Checksum(arch_property) => package_base_arch_prop!(
405 architecture_properties,
406 arch_property,
407 b2_checksums,
408 ),
409 parser::SourceProperty::Md5Checksum(arch_property) => {
410 package_base_arch_prop!(
411 architecture_properties,
412 arch_property,
413 md5_checksums,
414 );
415 }
416 parser::SourceProperty::Sha1Checksum(arch_property) => {
417 package_base_arch_prop!(
418 architecture_properties,
419 arch_property,
420 sha1_checksums,
421 );
422 }
423 parser::SourceProperty::Sha224Checksum(arch_property) => {
424 package_base_arch_prop!(
425 architecture_properties,
426 arch_property,
427 sha224_checksums,
428 )
429 }
430 parser::SourceProperty::Sha256Checksum(arch_property) => {
431 package_base_arch_prop!(
432 architecture_properties,
433 arch_property,
434 sha256_checksums,
435 )
436 }
437 parser::SourceProperty::Sha384Checksum(arch_property) => {
438 package_base_arch_prop!(
439 architecture_properties,
440 arch_property,
441 sha384_checksums,
442 )
443 }
444 parser::SourceProperty::Sha512Checksum(arch_property) => {
445 package_base_arch_prop!(
446 architecture_properties,
447 arch_property,
448 sha512_checksums,
449 )
450 }
451 parser::SourceProperty::CrcChecksum(arch_property) => {
452 package_base_arch_prop!(
453 architecture_properties,
454 arch_property,
455 crc_checksums,
456 )
457 }
458 },
459 }
460 }
461
462 let package_version = match package_version {
464 Some(package_version) => package_version,
465 None => {
466 return Err(Error::MissingKeyword { keyword: "pkgver" });
467 }
468 };
469
470 let package_release = match package_release {
472 Some(package_release) => package_release,
473 None => {
474 return Err(Error::MissingKeyword { keyword: "pkgrel" });
475 }
476 };
477 let version = FullVersion::new(package_version, package_release, epoch);
478
479 Ok(PackageBase {
480 name: parsed.name,
481 description,
482 url,
483 licenses,
484 changelog,
485 architectures,
486 architecture_properties,
487 install,
488 groups,
489 options,
490 backups,
491 version,
492 pgp_fingerprints,
493 dependencies,
494 optional_dependencies,
495 provides,
496 conflicts,
497 replaces,
498 check_dependencies,
499 make_dependencies,
500 sources,
501 no_extracts,
502 b2_checksums,
503 md5_checksums,
504 sha1_checksums,
505 sha224_checksums,
506 sha256_checksums,
507 sha384_checksums,
508 sha512_checksums,
509 crc_checksums,
510 })
511 }
512}