support more package compressions

This commit is contained in:
JMARyA 2025-03-28 09:17:24 +01:00
parent 788de4da7d
commit 656df96792
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
6 changed files with 115 additions and 36 deletions

View file

@ -23,17 +23,27 @@ pub struct Package {
pub rel: i32,
/// Version of the package
pub version: Option<String>,
/// Compression used
pub compression: Compression,
}
impl Package {
/// Create a new package
pub fn new(repo: &str, arch: Architecture, pkg_name: &str, version: &str, rel: i32) -> Self {
pub fn new(
repo: &str,
arch: Architecture,
pkg_name: &str,
version: &str,
rel: i32,
compression: Compression,
) -> Self {
let pkg = Package {
repo: repo.to_string(),
arch,
name: pkg_name.to_string(),
rel: rel,
version: Some(version.to_string()),
compression,
};
std::fs::create_dir_all(pkg.base_path()).unwrap();
@ -128,27 +138,38 @@ impl Package {
/// ```
/// use pacco::pkg::Package;
///
/// let (name, version, rel, arch) = Package::extract_pkg_name("pkg-ver-rel-x86_64.pkg.tar.zst").unwrap();
/// let (name, version, rel, arch, compress) = Package::extract_pkg_name("pkg-ver-rel-x86_64.pkg.tar.zst").unwrap();
/// assert_eq!(name, "pkg");
/// assert_eq!(version, "ver");
/// assert_eq!(rel, "rel");
/// assert_eq!(arch, pacco::pkg::arch::Architecture::x86_64);
/// assert_eq!(compress, pacco::pkg::package::Compression::Zstd);
///
/// let (name, version, rel, arch) = Package::extract_pkg_name("my-pkg-ver-rel-x86_64.pkg.tar.zst").unwrap();
/// let (name, version, rel, arch, compress) = Package::extract_pkg_name("my-pkg-ver-rel-x86_64.pkg.tar.xz").unwrap();
/// assert_eq!(name, "my-pkg");
/// assert_eq!(version, "ver");
/// assert_eq!(rel, "rel");
/// assert_eq!(arch, pacco::pkg::arch::Architecture::x86_64);
/// assert_eq!(compress, pacco::pkg::package::Compression::Xz);
/// ```
pub fn extract_pkg_name(file_name: &str) -> Option<(String, String, String, Architecture)> {
pub fn extract_pkg_name(
file_name: &str,
) -> Option<(String, String, String, Architecture, Compression)> {
// Extract (assuming the filename is "<pkg_name>-<version>-<relation>-<arch>.pkg.tar.zst")
let file_name = file_name.trim_end_matches(".sig").to_string();
let mut splitted = file_name.split('-').collect::<Vec<&str>>();
let arch = splitted.pop()?;
assert!(arch.ends_with(".pkg.tar.zst"), "{file_name}");
let arch = arch.trim_end_matches(".pkg.tar.zst");
let compression = Compression::from_filename(arch);
assert!(compression.is_some());
let compression = compression.unwrap();
let arch = match compression {
Compression::Zstd => arch.trim_end_matches(".pkg.tar.zst"),
Compression::Xz => arch.trim_end_matches(".pkg.tar.xz"),
};
let relation = splitted.pop()?;
let version = splitted.pop()?;
@ -160,29 +181,50 @@ impl Package {
version.to_string(),
relation.to_string(),
Architecture::parse(arch)?,
compression,
))
}
/// Parse a pkg filename
pub fn from_filename(repo: &str, file_name: &str) -> Package {
let (pkg_name, version, rel, arch) = Package::extract_pkg_name(file_name).unwrap();
let (pkg_name, version, rel, arch, compression) =
Package::extract_pkg_name(file_name).unwrap();
Self {
repo: repo.to_string(),
arch,
name: pkg_name,
rel: rel.parse().unwrap(),
version: Some(version.to_string()),
compression,
}
}
/// Find a package with latest version
pub fn find(repo: &str, arch: Architecture, pkg_name: &str) -> Option<Self> {
if let Some(pkg) = Self::find_compressed(repo, arch.clone(), pkg_name, Compression::Zstd) {
return Some(pkg);
}
if let Some(pkg) = Self::find_compressed(repo, arch, pkg_name, Compression::Xz) {
return Some(pkg);
}
None
}
/// Find a package with latest version
fn find_compressed(
repo: &str,
arch: Architecture,
pkg_name: &str,
compression: Compression,
) -> Option<Self> {
let mut base = Package {
repo: repo.to_string(),
arch,
name: pkg_name.to_string(),
rel: 1,
version: None,
compression,
};
let versions = base.versions();
@ -397,7 +439,7 @@ impl Package {
/// Build a pkg filename from the packages values
pub fn file_name(&self) -> String {
format!(
"{}-{}-{}-{}.pkg.tar.zst",
"{}-{}-{}-{}.pkg.tar.{}",
self.name,
if let Some(ver) = &self.version {
ver.to_string()
@ -407,9 +449,14 @@ impl Package {
},
self.rel,
self.arch.to_string(),
self.compression.extension()
)
}
pub fn has_pkg_ext(filename: &str) -> bool {
filename.ends_with(".pkg.tar.zst") || filename.ends_with(".pkg.tar.xz")
}
/// Get all versions of the package
pub fn versions(&self) -> Vec<String> {
let dir_path = self.base_path();
@ -418,8 +465,8 @@ impl Package {
if let Ok(entries) = std::fs::read_dir(dir_path) {
for entry in entries.filter_map(Result::ok) {
let file_name = entry.file_name().into_string().unwrap_or_default();
if file_name.starts_with(&self.name) && file_name.ends_with(".pkg.tar.zst") {
let (_, version, rel, _) = Package::extract_pkg_name(&file_name).unwrap();
if file_name.starts_with(&self.name) && Package::has_pkg_ext(&file_name) {
let (_, version, rel, _, _) = Package::extract_pkg_name(&file_name).unwrap();
versions.push(format!("{version}-{rel}"));
}
}
@ -562,3 +609,28 @@ impl PackageMetaInfo for Package {
.execute(get_pg!()).await.unwrap();
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Compression {
Zstd,
Xz,
}
impl Compression {
pub fn from_filename(name: &str) -> Option<Self> {
if name.ends_with("zst") {
Some(Self::Zstd)
} else if name.ends_with("xz") {
Some(Self::Xz)
} else {
None
}
}
pub fn extension(&self) -> &str {
match self {
Compression::Zstd => "zst",
Compression::Xz => "xz",
}
}
}