✨ support more package compressions
This commit is contained in:
parent
788de4da7d
commit
656df96792
6 changed files with 115 additions and 36 deletions
31
src/main.rs
31
src/main.rs
|
@ -51,23 +51,20 @@ async fn launch() -> _ {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
.mount_assets()
|
.mount_assets()
|
||||||
.mount(
|
.mount("/", routes![
|
||||||
"/",
|
routes::index_page,
|
||||||
routes![
|
routes::pkg_route,
|
||||||
routes::index_page,
|
routes::push::upload_pkg,
|
||||||
routes::pkg_route,
|
routes::user::login,
|
||||||
routes::push::upload_pkg,
|
routes::user::login_post,
|
||||||
routes::user::login,
|
routes::user::account_page,
|
||||||
routes::user::login_post,
|
routes::ui::pkg_ui,
|
||||||
routes::user::account_page,
|
routes::ui::repo_ui,
|
||||||
routes::ui::pkg_ui,
|
routes::user::new_api_key,
|
||||||
routes::ui::repo_ui,
|
routes::user::end_session,
|
||||||
routes::user::new_api_key,
|
routes::user::change_password,
|
||||||
routes::user::end_session,
|
routes::user::change_password_post
|
||||||
routes::user::change_password,
|
])
|
||||||
routes::user::change_password_post
|
|
||||||
],
|
|
||||||
)
|
|
||||||
.manage(config)
|
.manage(config)
|
||||||
.manage(shell)
|
.manage(shell)
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ impl MirrorRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
// PKG
|
// 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)
|
self.download_package(pkg_name, &name, arch, mirrorlist)
|
||||||
.await;
|
.await;
|
||||||
|
|
|
@ -23,17 +23,27 @@ pub struct Package {
|
||||||
pub rel: i32,
|
pub rel: i32,
|
||||||
/// Version of the package
|
/// Version of the package
|
||||||
pub version: Option<String>,
|
pub version: Option<String>,
|
||||||
|
/// Compression used
|
||||||
|
pub compression: Compression,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Package {
|
impl Package {
|
||||||
/// Create a new 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 {
|
let pkg = Package {
|
||||||
repo: repo.to_string(),
|
repo: repo.to_string(),
|
||||||
arch,
|
arch,
|
||||||
name: pkg_name.to_string(),
|
name: pkg_name.to_string(),
|
||||||
rel: rel,
|
rel: rel,
|
||||||
version: Some(version.to_string()),
|
version: Some(version.to_string()),
|
||||||
|
compression,
|
||||||
};
|
};
|
||||||
|
|
||||||
std::fs::create_dir_all(pkg.base_path()).unwrap();
|
std::fs::create_dir_all(pkg.base_path()).unwrap();
|
||||||
|
@ -128,27 +138,38 @@ impl Package {
|
||||||
/// ```
|
/// ```
|
||||||
/// use pacco::pkg::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!(name, "pkg");
|
||||||
/// assert_eq!(version, "ver");
|
/// assert_eq!(version, "ver");
|
||||||
/// assert_eq!(rel, "rel");
|
/// assert_eq!(rel, "rel");
|
||||||
/// assert_eq!(arch, pacco::pkg::arch::Architecture::x86_64);
|
/// 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!(name, "my-pkg");
|
||||||
/// assert_eq!(version, "ver");
|
/// assert_eq!(version, "ver");
|
||||||
/// assert_eq!(rel, "rel");
|
/// assert_eq!(rel, "rel");
|
||||||
/// assert_eq!(arch, pacco::pkg::arch::Architecture::x86_64);
|
/// 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")
|
// 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 file_name = file_name.trim_end_matches(".sig").to_string();
|
||||||
|
|
||||||
let mut splitted = file_name.split('-').collect::<Vec<&str>>();
|
let mut splitted = file_name.split('-').collect::<Vec<&str>>();
|
||||||
|
|
||||||
let arch = splitted.pop()?;
|
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 relation = splitted.pop()?;
|
||||||
let version = splitted.pop()?;
|
let version = splitted.pop()?;
|
||||||
|
@ -160,29 +181,50 @@ impl Package {
|
||||||
version.to_string(),
|
version.to_string(),
|
||||||
relation.to_string(),
|
relation.to_string(),
|
||||||
Architecture::parse(arch)?,
|
Architecture::parse(arch)?,
|
||||||
|
compression,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a pkg filename
|
/// Parse a pkg filename
|
||||||
pub fn from_filename(repo: &str, file_name: &str) -> Package {
|
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 {
|
Self {
|
||||||
repo: repo.to_string(),
|
repo: repo.to_string(),
|
||||||
arch,
|
arch,
|
||||||
name: pkg_name,
|
name: pkg_name,
|
||||||
rel: rel.parse().unwrap(),
|
rel: rel.parse().unwrap(),
|
||||||
version: Some(version.to_string()),
|
version: Some(version.to_string()),
|
||||||
|
compression,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find a package with latest version
|
/// Find a package with latest version
|
||||||
pub fn find(repo: &str, arch: Architecture, pkg_name: &str) -> Option<Self> {
|
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 {
|
let mut base = Package {
|
||||||
repo: repo.to_string(),
|
repo: repo.to_string(),
|
||||||
arch,
|
arch,
|
||||||
name: pkg_name.to_string(),
|
name: pkg_name.to_string(),
|
||||||
rel: 1,
|
rel: 1,
|
||||||
version: None,
|
version: None,
|
||||||
|
compression,
|
||||||
};
|
};
|
||||||
|
|
||||||
let versions = base.versions();
|
let versions = base.versions();
|
||||||
|
@ -397,7 +439,7 @@ impl Package {
|
||||||
/// Build a pkg filename from the packages values
|
/// Build a pkg filename from the packages values
|
||||||
pub fn file_name(&self) -> String {
|
pub fn file_name(&self) -> String {
|
||||||
format!(
|
format!(
|
||||||
"{}-{}-{}-{}.pkg.tar.zst",
|
"{}-{}-{}-{}.pkg.tar.{}",
|
||||||
self.name,
|
self.name,
|
||||||
if let Some(ver) = &self.version {
|
if let Some(ver) = &self.version {
|
||||||
ver.to_string()
|
ver.to_string()
|
||||||
|
@ -407,9 +449,14 @@ impl Package {
|
||||||
},
|
},
|
||||||
self.rel,
|
self.rel,
|
||||||
self.arch.to_string(),
|
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
|
/// Get all versions of the package
|
||||||
pub fn versions(&self) -> Vec<String> {
|
pub fn versions(&self) -> Vec<String> {
|
||||||
let dir_path = self.base_path();
|
let dir_path = self.base_path();
|
||||||
|
@ -418,8 +465,8 @@ impl Package {
|
||||||
if let Ok(entries) = std::fs::read_dir(dir_path) {
|
if let Ok(entries) = std::fs::read_dir(dir_path) {
|
||||||
for entry in entries.filter_map(Result::ok) {
|
for entry in entries.filter_map(Result::ok) {
|
||||||
let file_name = entry.file_name().into_string().unwrap_or_default();
|
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") {
|
if file_name.starts_with(&self.name) && Package::has_pkg_ext(&file_name) {
|
||||||
let (_, version, rel, _) = Package::extract_pkg_name(&file_name).unwrap();
|
let (_, version, rel, _, _) = Package::extract_pkg_name(&file_name).unwrap();
|
||||||
versions.push(format!("{version}-{rel}"));
|
versions.push(format!("{version}-{rel}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -562,3 +609,28 @@ impl PackageMetaInfo for Package {
|
||||||
.execute(get_pg!()).await.unwrap();
|
.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",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -140,8 +140,15 @@ impl Repository {
|
||||||
|
|
||||||
pub fn get_pkg(&self, pkg_name: &str) -> Option<Package> {
|
pub fn get_pkg(&self, pkg_name: &str) -> Option<Package> {
|
||||||
// Find package
|
// Find package
|
||||||
let (name, version, rel, arch) = Package::extract_pkg_name(pkg_name).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());
|
let pkg = Package::new(
|
||||||
|
&self.name,
|
||||||
|
arch,
|
||||||
|
&name,
|
||||||
|
&version,
|
||||||
|
rel.parse().unwrap(),
|
||||||
|
compress,
|
||||||
|
);
|
||||||
|
|
||||||
// Return if exists
|
// Return if exists
|
||||||
if pkg.exists() { Some(pkg) } else { None }
|
if pkg.exists() { Some(pkg) } else { None }
|
||||||
|
|
|
@ -9,8 +9,8 @@ use pacco::pkg::package::PackageMetaInfo;
|
||||||
use rocket::http::{ContentType, Status};
|
use rocket::http::{ContentType, Status};
|
||||||
use rocket::{State, get};
|
use rocket::{State, get};
|
||||||
|
|
||||||
use pacco::pkg::Repository;
|
|
||||||
use pacco::pkg::arch::Architecture;
|
use pacco::pkg::arch::Architecture;
|
||||||
|
use pacco::pkg::{Package, Repository};
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
|
||||||
|
@ -103,14 +103,14 @@ pub async fn pkg_route(
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
if pkg_name.ends_with("pkg.tar.zst") {
|
if Package::has_pkg_ext(&pkg_name) {
|
||||||
pkg.increase_download_count().await;
|
pkg.increase_download_count().await;
|
||||||
return DataResponse::new_file(
|
return DataResponse::new_file(
|
||||||
&pkg.pkg_content_path().unwrap(),
|
&pkg.pkg_content_path().unwrap(),
|
||||||
"application/tar".to_string(),
|
"application/tar".to_string(),
|
||||||
cache_duration,
|
cache_duration,
|
||||||
);
|
);
|
||||||
} else if pkg_name.ends_with("pkg.tar.zst.sig") {
|
} else if pkg_name.ends_with("sig") {
|
||||||
return DataResponse::new(
|
return DataResponse::new(
|
||||||
pkg.sig_content().unwrap(),
|
pkg.sig_content().unwrap(),
|
||||||
"application/pgp-signature".to_string(),
|
"application/pgp-signature".to_string(),
|
||||||
|
@ -144,13 +144,13 @@ pub async fn pkg_route(
|
||||||
|
|
||||||
let pkg = repo.get_pkg(pkg_name).unwrap();
|
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(
|
return DataResponse::new_file(
|
||||||
&pkg.pkg_content_path().unwrap(),
|
&pkg.pkg_content_path().unwrap(),
|
||||||
"application/tar".to_string(),
|
"application/tar".to_string(),
|
||||||
cache_duration,
|
cache_duration,
|
||||||
);
|
);
|
||||||
} else if pkg_name.ends_with("pkg.tar.zst.sig") {
|
} else if pkg_name.ends_with("sig") {
|
||||||
return DataResponse::new(
|
return DataResponse::new(
|
||||||
pkg.sig_content().unwrap(),
|
pkg.sig_content().unwrap(),
|
||||||
"application/pgp-signature".to_string(),
|
"application/pgp-signature".to_string(),
|
||||||
|
|
|
@ -77,7 +77,10 @@ pub async fn upload_pkg(
|
||||||
|
|
||||||
let arch = Architecture::parse(&arch).ok_or_else(|| api_error("Invalid architecture"))?;
|
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.save(
|
||||||
pkg_file,
|
pkg_file,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue