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::Meta(SharedMetaProperty::Architecture(architecture)) = prop
320 else {
321 continue;
322 };
323 architectures.push(architecture);
324 }
325
326 if architectures.is_empty() {
329 return Err(Error::MissingKeyword { keyword: "arch" });
330 }
331
332 let architectures: Architectures = architectures.try_into()?;
335
336 for prop in parsed.properties.into_iter() {
337 match prop {
338 PackageBaseProperty::EmptyLine | PackageBaseProperty::Comment(_) => continue,
340 PackageBaseProperty::PackageVersion(inner) => package_version = Some(inner),
341 PackageBaseProperty::PackageRelease(inner) => package_release = Some(inner),
342 PackageBaseProperty::PackageEpoch(inner) => epoch = Some(inner),
343 PackageBaseProperty::ValidPgpKeys(inner) => {
344 pgp_fingerprints.push(inner);
345 }
346 PackageBaseProperty::CheckDependency(arch_property) => {
347 package_base_arch_prop!(
348 architecture_properties,
349 arch_property,
350 check_dependencies,
351 )
352 }
353 PackageBaseProperty::MakeDependency(arch_property) => {
354 package_base_arch_prop!(
355 architecture_properties,
356 arch_property,
357 make_dependencies,
358 )
359 }
360 PackageBaseProperty::Meta(shared_meta_property) => {
361 match shared_meta_property {
362 SharedMetaProperty::Description(inner) => description = Some(inner),
363 SharedMetaProperty::Url(inner) => url = Some(inner),
364 SharedMetaProperty::License(inner) => licenses.push(inner),
365 SharedMetaProperty::Architecture(_) => continue,
367 SharedMetaProperty::Changelog(inner) => changelog = Some(inner),
368 SharedMetaProperty::Install(inner) => install = Some(inner),
369 SharedMetaProperty::Group(inner) => groups.push(inner),
370 SharedMetaProperty::Option(inner) => options.push(inner),
371 SharedMetaProperty::Backup(inner) => backups.push(inner),
372 }
373 }
374 PackageBaseProperty::Relation(relation_property) => match relation_property {
375 parser::RelationProperty::Dependency(arch_property) => package_base_arch_prop!(
376 architecture_properties,
377 arch_property,
378 dependencies,
379 ),
380 parser::RelationProperty::OptionalDependency(arch_property) => {
381 package_base_arch_prop!(
382 architecture_properties,
383 arch_property,
384 optional_dependencies,
385 )
386 }
387 parser::RelationProperty::Provides(arch_property) => {
388 package_base_arch_prop!(architecture_properties, arch_property, provides,)
389 }
390 parser::RelationProperty::Conflicts(arch_property) => {
391 package_base_arch_prop!(architecture_properties, arch_property, conflicts,)
392 }
393 parser::RelationProperty::Replaces(arch_property) => {
394 package_base_arch_prop!(architecture_properties, arch_property, replaces,)
395 }
396 },
397 PackageBaseProperty::Source(source_property) => match source_property {
398 parser::SourceProperty::Source(arch_property) => {
399 package_base_arch_prop!(architecture_properties, arch_property, sources,)
400 }
401 parser::SourceProperty::NoExtract(value) => no_extracts.push(value),
402 parser::SourceProperty::B2Checksum(arch_property) => package_base_arch_prop!(
403 architecture_properties,
404 arch_property,
405 b2_checksums,
406 ),
407 parser::SourceProperty::Md5Checksum(arch_property) => {
408 package_base_arch_prop!(
409 architecture_properties,
410 arch_property,
411 md5_checksums,
412 );
413 }
414 parser::SourceProperty::Sha1Checksum(arch_property) => {
415 package_base_arch_prop!(
416 architecture_properties,
417 arch_property,
418 sha1_checksums,
419 );
420 }
421 parser::SourceProperty::Sha224Checksum(arch_property) => {
422 package_base_arch_prop!(
423 architecture_properties,
424 arch_property,
425 sha224_checksums,
426 )
427 }
428 parser::SourceProperty::Sha256Checksum(arch_property) => {
429 package_base_arch_prop!(
430 architecture_properties,
431 arch_property,
432 sha256_checksums,
433 )
434 }
435 parser::SourceProperty::Sha384Checksum(arch_property) => {
436 package_base_arch_prop!(
437 architecture_properties,
438 arch_property,
439 sha384_checksums,
440 )
441 }
442 parser::SourceProperty::Sha512Checksum(arch_property) => {
443 package_base_arch_prop!(
444 architecture_properties,
445 arch_property,
446 sha512_checksums,
447 )
448 }
449 parser::SourceProperty::CrcChecksum(arch_property) => {
450 package_base_arch_prop!(
451 architecture_properties,
452 arch_property,
453 crc_checksums,
454 )
455 }
456 },
457 }
458 }
459
460 let package_version = match package_version {
462 Some(package_version) => package_version,
463 None => {
464 return Err(Error::MissingKeyword { keyword: "pkgver" });
465 }
466 };
467
468 let package_release = match package_release {
470 Some(package_release) => package_release,
471 None => {
472 return Err(Error::MissingKeyword { keyword: "pkgrel" });
473 }
474 };
475 let version = FullVersion::new(package_version, package_release, epoch);
476
477 Ok(PackageBase {
478 name: parsed.name,
479 description,
480 url,
481 licenses,
482 changelog,
483 architectures,
484 architecture_properties,
485 install,
486 groups,
487 options,
488 backups,
489 version,
490 pgp_fingerprints,
491 dependencies,
492 optional_dependencies,
493 provides,
494 conflicts,
495 replaces,
496 check_dependencies,
497 make_dependencies,
498 sources,
499 no_extracts,
500 b2_checksums,
501 md5_checksums,
502 sha1_checksums,
503 sha224_checksums,
504 sha256_checksums,
505 sha384_checksums,
506 sha512_checksums,
507 crc_checksums,
508 })
509 }
510}