use alpm_types::{
Architecture,
Architectures,
FullVersion,
License,
MakepkgOption,
Name,
OpenPGPIdentifier,
OptionalDependency,
PackageDescription,
PackageRelation,
RelationOrSoname,
RelativeFilePath,
SkippableChecksum,
Source,
Url,
digests::{Blake2b512, Crc32Cksum, Md5, Sha1, Sha224, Sha256, Sha384, Sha512},
};
use serde::{Deserialize, Serialize};
#[cfg(doc)]
use crate::source_info::v1::package::Override;
use crate::{
SourceInfoV1,
source_info::v1::{
package::Package,
package_base::{PackageBase, PackageBaseArchitecture},
},
};
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct MergedPackage {
pub name: Name,
pub description: Option<PackageDescription>,
pub url: Option<Url>,
pub licenses: Vec<License>,
pub architecture: Architecture,
pub changelog: Option<RelativeFilePath>,
pub install: Option<RelativeFilePath>,
pub groups: Vec<String>,
pub options: Vec<MakepkgOption>,
pub backups: Vec<RelativeFilePath>,
pub version: FullVersion,
pub pgp_fingerprints: Vec<OpenPGPIdentifier>,
pub dependencies: Vec<RelationOrSoname>,
pub optional_dependencies: Vec<OptionalDependency>,
pub provides: Vec<RelationOrSoname>,
pub conflicts: Vec<PackageRelation>,
pub replaces: Vec<PackageRelation>,
pub check_dependencies: Vec<PackageRelation>,
pub make_dependencies: Vec<PackageRelation>,
pub sources: Vec<MergedSource>,
pub no_extracts: Vec<String>,
}
#[derive(Clone, Debug)]
pub struct MergedPackagesIterator<'a> {
pub(crate) architecture: Architecture,
pub(crate) source_info: &'a SourceInfoV1,
pub(crate) package_iterator: std::slice::Iter<'a, Package>,
}
impl Iterator for MergedPackagesIterator<'_> {
type Item = MergedPackage;
fn next(&mut self) -> Option<MergedPackage> {
let package = self.package_iterator.find(|package| {
let architectures = match &package.architectures {
Some(value) => value,
None => &self.source_info.base.architectures,
};
match &self.architecture {
Architecture::Any => *architectures == Architectures::Any,
Architecture::Some(iterator_arch) => match architectures {
Architectures::Any => true,
Architectures::Some(arch_vec) => arch_vec.contains(iterator_arch),
},
}
})?;
Some(MergedPackage::from_base_and_package(
self.architecture.clone(),
&self.source_info.base,
package,
))
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct MergedSource {
pub source: Source,
pub b2_checksum: Option<SkippableChecksum<Blake2b512>>,
pub md5_checksum: Option<SkippableChecksum<Md5>>,
pub sha1_checksum: Option<SkippableChecksum<Sha1>>,
pub sha224_checksum: Option<SkippableChecksum<Sha224>>,
pub sha256_checksum: Option<SkippableChecksum<Sha256>>,
pub sha384_checksum: Option<SkippableChecksum<Sha384>>,
pub sha512_checksum: Option<SkippableChecksum<Sha512>>,
pub crc_checksum: Option<SkippableChecksum<Crc32Cksum>>,
}
#[derive(Clone, Debug)]
pub struct MergedSourceIterator<'a> {
sources: std::slice::Iter<'a, Source>,
b2_checksums: std::slice::Iter<'a, SkippableChecksum<Blake2b512>>,
md5_checksums: std::slice::Iter<'a, SkippableChecksum<Md5>>,
sha1_checksums: std::slice::Iter<'a, SkippableChecksum<Sha1>>,
sha224_checksums: std::slice::Iter<'a, SkippableChecksum<Sha224>>,
sha256_checksums: std::slice::Iter<'a, SkippableChecksum<Sha256>>,
sha384_checksums: std::slice::Iter<'a, SkippableChecksum<Sha384>>,
sha512_checksums: std::slice::Iter<'a, SkippableChecksum<Sha512>>,
crc_checksums: std::slice::Iter<'a, SkippableChecksum<Crc32Cksum>>,
}
impl Iterator for MergedSourceIterator<'_> {
type Item = MergedSource;
fn next(&mut self) -> Option<MergedSource> {
let source = self.sources.next()?;
Some(MergedSource {
source: source.clone(),
b2_checksum: self.b2_checksums.next().cloned(),
md5_checksum: self.md5_checksums.next().cloned(),
sha1_checksum: self.sha1_checksums.next().cloned(),
sha224_checksum: self.sha224_checksums.next().cloned(),
sha256_checksum: self.sha256_checksums.next().cloned(),
sha384_checksum: self.sha384_checksums.next().cloned(),
sha512_checksum: self.sha512_checksums.next().cloned(),
crc_checksum: self.crc_checksums.next().cloned(),
})
}
}
impl MergedPackage {
pub fn from_base_and_package<A: Into<Architecture>>(
architecture: A,
base: &PackageBase,
package: &Package,
) -> MergedPackage {
let name = package.name.clone();
let architecture = &architecture.into();
let mut merged_package = Self::from_base(architecture.clone(), name, base);
merged_package.merge_package(package);
let mut architecture_properties = if let Architecture::Some(system_arch) = &architecture
&& let Some(properties) = base.architecture_properties.get(system_arch)
{
properties.clone()
} else {
PackageBaseArchitecture::default()
};
if let Architecture::Some(system_arch) = architecture
&& let Some(package_properties) = package.architecture_properties.get(system_arch)
{
architecture_properties.merge_package_properties(package_properties.clone());
}
merged_package.merge_architecture_properties(&architecture_properties);
merged_package
}
pub fn from_base<A: Into<Architecture>>(
architecture: A,
name: Name,
base: &PackageBase,
) -> MergedPackage {
let merged_sources = MergedSourceIterator {
sources: base.sources.iter(),
b2_checksums: base.b2_checksums.iter(),
md5_checksums: base.md5_checksums.iter(),
sha1_checksums: base.sha1_checksums.iter(),
sha224_checksums: base.sha224_checksums.iter(),
sha256_checksums: base.sha256_checksums.iter(),
sha384_checksums: base.sha384_checksums.iter(),
sha512_checksums: base.sha512_checksums.iter(),
crc_checksums: base.crc_checksums.iter(),
};
let architecture = match &base.architectures {
Architectures::Any => &Architecture::Any,
Architectures::Some(_) => &architecture.into(),
};
MergedPackage {
name,
description: base.description.clone(),
url: base.url.clone(),
licenses: base.licenses.clone(),
architecture: architecture.clone(),
changelog: base.changelog.clone(),
install: base.install.clone(),
groups: base.groups.clone(),
options: base.options.clone(),
backups: base.backups.clone(),
version: base.version.clone(),
pgp_fingerprints: base.pgp_fingerprints.clone(),
dependencies: base.dependencies.clone(),
optional_dependencies: base.optional_dependencies.clone(),
provides: base.provides.clone(),
conflicts: base.conflicts.clone(),
replaces: base.replaces.clone(),
check_dependencies: base.check_dependencies.clone(),
make_dependencies: base.make_dependencies.clone(),
sources: merged_sources.collect(),
no_extracts: base.no_extracts.clone(),
}
}
fn merge_package(&mut self, package: &Package) {
let package = package.clone();
if let Some(value) = package.architectures {
if matches!(value, Architectures::Any) {
self.architecture = Architecture::Any
}
};
package.description.merge_option(&mut self.description);
package.url.merge_option(&mut self.url);
package.changelog.merge_option(&mut self.changelog);
package.licenses.merge_vec(&mut self.licenses);
package.install.merge_option(&mut self.install);
package.groups.merge_vec(&mut self.groups);
package.options.merge_vec(&mut self.options);
package.backups.merge_vec(&mut self.backups);
package.dependencies.merge_vec(&mut self.dependencies);
package
.optional_dependencies
.merge_vec(&mut self.optional_dependencies);
package.provides.merge_vec(&mut self.provides);
package.conflicts.merge_vec(&mut self.conflicts);
package.replaces.merge_vec(&mut self.replaces);
}
fn merge_architecture_properties(&mut self, base_architecture: &PackageBaseArchitecture) {
let merged_sources = MergedSourceIterator {
sources: base_architecture.sources.iter(),
b2_checksums: base_architecture.b2_checksums.iter(),
md5_checksums: base_architecture.md5_checksums.iter(),
sha1_checksums: base_architecture.sha1_checksums.iter(),
sha224_checksums: base_architecture.sha224_checksums.iter(),
sha256_checksums: base_architecture.sha256_checksums.iter(),
sha384_checksums: base_architecture.sha384_checksums.iter(),
sha512_checksums: base_architecture.sha512_checksums.iter(),
crc_checksums: base_architecture.crc_checksums.iter(),
};
self.dependencies
.extend_from_slice(&base_architecture.dependencies);
self.optional_dependencies
.extend_from_slice(&base_architecture.optional_dependencies);
self.provides.extend_from_slice(&base_architecture.provides);
self.conflicts
.extend_from_slice(&base_architecture.conflicts);
self.replaces.extend_from_slice(&base_architecture.replaces);
self.check_dependencies
.extend_from_slice(&base_architecture.check_dependencies);
self.make_dependencies
.extend_from_slice(&base_architecture.make_dependencies);
self.sources
.extend_from_slice(&merged_sources.collect::<Vec<MergedSource>>());
}
}