diff --git a/server/src/repo/archive.rs b/server/src/repo/archive.rs index 2e31fb7..8f7fb49 100644 --- a/server/src/repo/archive.rs +++ b/server/src/repo/archive.rs @@ -38,10 +38,11 @@ impl RepoArchiveWriter { } /// Set the current entry to be a new "files" list - pub async fn add_files_entry>( + pub async fn add_entry>( &self, full_name: &str, path: P, + desc: bool, ) -> io::Result<()> { let metadata = tokio::fs::metadata(&path).await?; let file_size = metadata.len(); @@ -53,7 +54,10 @@ impl RepoArchiveWriter { Ok(tokio::task::spawn_blocking(move || { let mut ar_entry = WriteEntry::new(); ar_entry.set_filetype(libarchive::archive::FileType::RegularFile); - ar_entry.set_pathname(PathBuf::from(full_name).join("files")); + + let name = if desc { "desc" } else { "files" }; + + ar_entry.set_pathname(PathBuf::from(full_name).join(name)); ar_entry.set_mode(0o100644); ar_entry.set_size(file_size.try_into().unwrap()); diff --git a/server/src/repo/manager_new.rs b/server/src/repo/manager_new.rs index 4dbea8a..9728764 100644 --- a/server/src/repo/manager_new.rs +++ b/server/src/repo/manager_new.rs @@ -80,30 +80,29 @@ impl MetaRepoMgr { .await?; let uuid: uuid::fmt::Simple = Uuid::new_v4().into(); - let tmp_file_path = self.pkg_dir.join(uuid.to_string()); + let files_tmp_file_path = self.pkg_dir.join(uuid.to_string()); + + let uuid: uuid::fmt::Simple = Uuid::new_v4().into(); + let desc_tmp_file_path = self.pkg_dir.join(uuid.to_string()); while let Some(pkg) = pkgs.next().await.transpose()? { - let mut tmp_file = tokio::fs::File::create(&tmp_file_path).await?; + let mut files_tmp_file = tokio::fs::File::create(&files_tmp_file_path).await?; + let mut desc_tmp_file = tokio::fs::File::create(&desc_tmp_file_path).await?; - let line = "%FILES%\n"; - tmp_file.write_all(line.as_bytes()).await?; - - // Generate the files list for the package - let mut files = pkg.find_related(db::PackageFile).stream(conn).await?; - - while let Some(file) = files.next().await.transpose()? { - tmp_file - .write_all(format!("{}\n", file.path).as_bytes()) - .await?; - } + package::write_files(conn, &mut files_tmp_file, &pkg).await?; + package::write_desc(conn, &mut desc_tmp_file, &pkg).await?; + let full_name = format!("{}-{}", pkg.name, pkg.version); ar_files - .add_files_entry(&format!("{}-{}", pkg.name, pkg.version), &tmp_file_path) + .add_entry(&full_name, &desc_tmp_file_path, true) + .await?; + ar_files + .add_entry(&full_name, &files_tmp_file_path, false) .await?; } ar_files.close().await?; - tokio::fs::remove_file(tmp_file_path).await?; + tokio::fs::remove_file(files_tmp_file_path).await?; Ok(()) } diff --git a/server/src/repo/package.rs b/server/src/repo/package.rs index 3c11c38..7c9a778 100644 --- a/server/src/repo/package.rs +++ b/server/src/repo/package.rs @@ -1,13 +1,15 @@ use chrono::NaiveDateTime; +use futures::StreamExt; use libarchive::read::{Archive, Builder}; use libarchive::{Entry, ReadFilter}; -use sea_orm::ActiveValue::Set; +use sea_orm::{ActiveValue::Set, ColumnTrait, DbConn, ModelTrait, QueryFilter, QuerySelect}; use std::fmt; use std::fs; use std::io::{self, BufRead, BufReader, BufWriter, Read, Write}; use std::path::{Path, PathBuf}; +use tokio::io::{AsyncWrite, AsyncWriteExt}; -use crate::db::entities::package; +use crate::db::{self, entities::package, PackageRelatedEnum}; const IGNORED_FILES: [&str; 5] = [".BUILDINFO", ".INSTALL", ".MTREE", ".PKGINFO", ".CHANGELOG"]; @@ -290,3 +292,121 @@ impl From for package::ActiveModel { } } } + +pub fn filename(pkg: &package::Model) -> String { + format!( + "{}-{}-{}.pkg.tar.{}", + pkg.name, pkg.version, pkg.arch, pkg.compression + ) +} + +async fn write_attribute( + writer: &mut W, + key: &str, + value: &str, +) -> io::Result<()> { + if !value.is_empty() { + let s = format!("\n%{}%\n{}\n", key, value); + writer.write_all(s.as_bytes()).await?; + } + + Ok(()) +} + +pub async fn write_desc( + conn: &DbConn, + writer: &mut W, + pkg: &package::Model, +) -> crate::Result<()> { + writer + .write_all(format!("%FILENAME%\n{}\n", filename(pkg)).as_bytes()) + .await?; + + write_attribute(writer, "NAME", &pkg.name).await?; + write_attribute(writer, "BASE", &pkg.base).await?; + write_attribute(writer, "VERSION", &pkg.version).await?; + + if let Some(ref description) = pkg.description { + write_attribute(writer, "DESC", description).await?; + } + + let groups: Vec = pkg + .find_related(db::PackageGroup) + .select_only() + .column(db::package_group::Column::Name) + .into_tuple() + .all(conn) + .await?; + write_attribute(writer, "GROUPS", &groups.join("\n")).await?; + + write_attribute(writer, "CSIZE", &pkg.c_size.to_string()).await?; + write_attribute(writer, "ISIZE", &pkg.size.to_string()).await?; + write_attribute(writer, "SHA256SUM", &pkg.sha256_sum).await?; + + if let Some(ref url) = pkg.url { + write_attribute(writer, "URL", url).await?; + } + + let licenses: Vec = pkg + .find_related(db::PackageLicense) + .select_only() + .column(db::package_license::Column::Name) + .into_tuple() + .all(conn) + .await?; + write_attribute(writer, "LICENSE", &licenses.join("\n")).await?; + + write_attribute(writer, "ARCH", &pkg.arch).await?; + + // TODO build date + //write_attribute(writer, "BUILDDATE", &pkg.build_) + + if let Some(ref packager) = pkg.packager { + write_attribute(writer, "PACKAGER", packager).await?; + } + + let related = [ + ("REPLACES", PackageRelatedEnum::Replaces), + ("CONFLICTS", PackageRelatedEnum::Conflicts), + ("PROVIDES", PackageRelatedEnum::Provides), + ("DEPENDS", PackageRelatedEnum::Depend), + ("OPTDEPENDS", PackageRelatedEnum::Optdepend), + ("MAKEDEPENDS", PackageRelatedEnum::Makedepend), + ("CHECKDEPENDS", PackageRelatedEnum::Checkdepend), + ]; + + for (key, attr) in related.into_iter() { + let items: Vec = pkg + .find_related(db::PackageRelated) + .filter(db::package_related::Column::Type.eq(attr)) + .select_only() + .column(db::package_related::Column::Name) + .into_tuple() + .all(conn) + .await?; + + write_attribute(writer, key, &items.join("\n")).await?; + } + + Ok(()) +} + +pub async fn write_files( + conn: &DbConn, + writer: &mut W, + pkg: &package::Model, +) -> crate::Result<()> { + let line = "%FILES%\n"; + writer.write_all(line.as_bytes()).await?; + + // Generate the files list for the package + let mut files = pkg.find_related(db::PackageFile).stream(conn).await?; + + while let Some(file) = files.next().await.transpose()? { + writer + .write_all(format!("{}\n", file.path).as_bytes()) + .await?; + } + + Ok(()) +}