From 656df96792149989579b2c385f791eb42136e377 Mon Sep 17 00:00:00 2001 From: JMARyA Date: Fri, 28 Mar 2025 09:17:24 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20support=20more=20package=20compress?= =?UTF-8?q?ions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 31 +++++++--------- src/pkg/mirror.rs | 2 +- src/pkg/package.rs | 92 +++++++++++++++++++++++++++++++++++++++++----- src/pkg/repo.rs | 11 +++++- src/routes/mod.rs | 10 ++--- src/routes/push.rs | 5 ++- 6 files changed, 115 insertions(+), 36 deletions(-) diff --git a/src/main.rs b/src/main.rs index 2c20f6d..176f2d1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -51,23 +51,20 @@ async fn launch() -> _ { ..Default::default() }) .mount_assets() - .mount( - "/", - routes![ - routes::index_page, - routes::pkg_route, - routes::push::upload_pkg, - routes::user::login, - routes::user::login_post, - routes::user::account_page, - routes::ui::pkg_ui, - routes::ui::repo_ui, - routes::user::new_api_key, - routes::user::end_session, - routes::user::change_password, - routes::user::change_password_post - ], - ) + .mount("/", routes![ + routes::index_page, + routes::pkg_route, + routes::push::upload_pkg, + routes::user::login, + routes::user::login_post, + routes::user::account_page, + routes::ui::pkg_ui, + routes::ui::repo_ui, + routes::user::new_api_key, + routes::user::end_session, + routes::user::change_password, + routes::user::change_password_post + ]) .manage(config) .manage(shell) } diff --git a/src/pkg/mirror.rs b/src/pkg/mirror.rs index 1c30e2b..1f2c678 100644 --- a/src/pkg/mirror.rs +++ b/src/pkg/mirror.rs @@ -110,7 +110,7 @@ impl MirrorRepository { } // PKG - let (name, _, _, arch) = Package::extract_pkg_name(pkg_name).unwrap(); + let (name, _, _, arch, _) = Package::extract_pkg_name(pkg_name).unwrap(); self.download_package(pkg_name, &name, arch, mirrorlist) .await; diff --git a/src/pkg/package.rs b/src/pkg/package.rs index 51d4ccc..bda9d2d 100644 --- a/src/pkg/package.rs +++ b/src/pkg/package.rs @@ -23,17 +23,27 @@ pub struct Package { pub rel: i32, /// Version of the package pub version: Option, + /// 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.tar.zst") let file_name = file_name.trim_end_matches(".sig").to_string(); let mut splitted = file_name.split('-').collect::>(); 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 { + 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 { 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 { 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 { + 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", + } + } +} diff --git a/src/pkg/repo.rs b/src/pkg/repo.rs index 5afc2eb..7cadf2d 100644 --- a/src/pkg/repo.rs +++ b/src/pkg/repo.rs @@ -140,8 +140,15 @@ impl Repository { pub fn get_pkg(&self, pkg_name: &str) -> Option { // Find package - let (name, version, rel, arch) = Package::extract_pkg_name(pkg_name).unwrap(); - let pkg = Package::new(&self.name, arch, &name, &version, rel.parse().unwrap()); + let (name, version, rel, arch, compress) = Package::extract_pkg_name(pkg_name).unwrap(); + let pkg = Package::new( + &self.name, + arch, + &name, + &version, + rel.parse().unwrap(), + compress, + ); // Return if exists if pkg.exists() { Some(pkg) } else { None } diff --git a/src/routes/mod.rs b/src/routes/mod.rs index a022786..914bbc5 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -9,8 +9,8 @@ use pacco::pkg::package::PackageMetaInfo; use rocket::http::{ContentType, Status}; use rocket::{State, get}; -use pacco::pkg::Repository; use pacco::pkg::arch::Architecture; +use pacco::pkg::{Package, Repository}; use crate::config::Config; @@ -103,14 +103,14 @@ pub async fn pkg_route( .await .unwrap(); - if pkg_name.ends_with("pkg.tar.zst") { + if Package::has_pkg_ext(&pkg_name) { pkg.increase_download_count().await; return DataResponse::new_file( &pkg.pkg_content_path().unwrap(), "application/tar".to_string(), cache_duration, ); - } else if pkg_name.ends_with("pkg.tar.zst.sig") { + } else if pkg_name.ends_with("sig") { return DataResponse::new( pkg.sig_content().unwrap(), "application/pgp-signature".to_string(), @@ -144,13 +144,13 @@ pub async fn pkg_route( let pkg = repo.get_pkg(pkg_name).unwrap(); - if pkg_name.ends_with("pkg.tar.zst") { + if Package::has_pkg_ext(&pkg_name) { return DataResponse::new_file( &pkg.pkg_content_path().unwrap(), "application/tar".to_string(), cache_duration, ); - } else if pkg_name.ends_with("pkg.tar.zst.sig") { + } else if pkg_name.ends_with("sig") { return DataResponse::new( pkg.sig_content().unwrap(), "application/pgp-signature".to_string(), diff --git a/src/routes/push.rs b/src/routes/push.rs index 0881e76..42df102 100644 --- a/src/routes/push.rs +++ b/src/routes/push.rs @@ -77,7 +77,10 @@ pub async fn upload_pkg( let arch = Architecture::parse(&arch).ok_or_else(|| api_error("Invalid architecture"))?; - let pkg = Package::new(repo, arch, pkg_name, &version, rel); + let (_, _, _, _, compression) = Package::extract_pkg_name(upload.pkg.name().unwrap()) + .ok_or_else(|| api_error("Package has weird filename"))?; + + let pkg = Package::new(repo, arch, pkg_name, &version, rel, compression); pkg.save( pkg_file,