diff --git a/Cargo.lock b/Cargo.lock index d9c6efe..7e82ecd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -407,11 +407,8 @@ checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" dependencies = [ "android-tzdata", "iana-time-zone", - "js-sys", "num-traits", "serde", - "time 0.1.45", - "wasm-bindgen", "winapi", ] @@ -777,7 +774,7 @@ checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", ] [[package]] @@ -1197,7 +1194,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys", ] @@ -1627,7 +1624,6 @@ name = "rieterd" version = "0.1.0" dependencies = [ "axum", - "chrono", "clap", "futures", "libarchive", @@ -1838,7 +1834,7 @@ dependencies = [ "sqlx", "strum", "thiserror", - "time 0.3.23", + "time", "tracing", "url", "uuid", @@ -1906,7 +1902,7 @@ dependencies = [ "rust_decimal", "sea-query-derive", "serde_json", - "time 0.3.23", + "time", "uuid", ] @@ -1922,7 +1918,7 @@ dependencies = [ "sea-query", "serde_json", "sqlx", - "time 0.3.23", + "time", "uuid", ] @@ -2200,7 +2196,7 @@ dependencies = [ "smallvec", "sqlformat", "thiserror", - "time 0.3.23", + "time", "tokio", "tokio-stream", "tracing", @@ -2289,7 +2285,7 @@ dependencies = [ "sqlx-core", "stringprep", "thiserror", - "time 0.3.23", + "time", "tracing", "uuid", "whoami", @@ -2334,7 +2330,7 @@ dependencies = [ "sqlx-core", "stringprep", "thiserror", - "time 0.3.23", + "time", "tracing", "uuid", "whoami", @@ -2359,7 +2355,7 @@ dependencies = [ "percent-encoding", "serde", "sqlx-core", - "time 0.3.23", + "time", "tracing", "url", "uuid", @@ -2476,17 +2472,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - [[package]] name = "time" version = "0.3.23" @@ -2824,12 +2809,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/server/Cargo.toml b/server/Cargo.toml index c147eae..aeb0f48 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -8,10 +8,10 @@ authors = ["Jef Roosens"] [dependencies] axum = { version = "0.6.18", features = ["http2"] } -chrono = { version = "0.4.26", features = ["serde"] } clap = { version = "4.3.12", features = ["env", "derive"] } futures = "0.3.28" libarchive = { path = "../libarchive" } +sea-orm = { version = "0.12.1", features = ["sqlx-sqlite", "runtime-tokio-rustls", "macros"] } sea-orm-migration = "0.12.1" serde = { version = "1.0.178", features = ["derive"] } sha256 = "1.1.4" @@ -22,13 +22,3 @@ tower-http = { version = "0.4.1", features = ["fs", "trace"] } tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } uuid = { version = "1.4.0", features = ["v4"] } - -[dependencies.sea-orm] -version = "0.12.1" -features = [ - "sqlx-sqlite", - "sqlx-postgres", - "runtime-tokio-rustls", - "macros", - "with-chrono" -] diff --git a/server/src/api/mod.rs b/server/src/api/mod.rs index 011f008..91a1023 100644 --- a/server/src/api/mod.rs +++ b/server/src/api/mod.rs @@ -10,14 +10,12 @@ use sea_orm::PaginatorTrait; use pagination::PaginatedResponse; -use crate::db::entities::package; use crate::db::entities::repo; pub fn router() -> Router { Router::new() .route("/repos", get(get_repos)) .route("/repos/:id", get(get_single_repo)) - .route("/packages", get(get_packages)) } async fn get_repos( @@ -44,16 +42,3 @@ async fn get_single_repo( Ok(Json(repo)) } - -async fn get_packages( - State(global): State, - Query(pagination): Query, -) -> crate::Result>> { - let pkgs = package::Entity::find() - .order_by_asc(package::Column::Id) - .paginate(&global.db, pagination.per_page.unwrap_or(25)) - .fetch_page(pagination.page.unwrap_or(1) - 1) - .await?; - - Ok(Json(pagination.res(pkgs))) -} diff --git a/server/src/cli.rs b/server/src/cli.rs index 7fa1566..3ec7cd8 100644 --- a/server/src/cli.rs +++ b/server/src/cli.rs @@ -48,9 +48,6 @@ impl Cli { self.init_tracing(); let db = crate::db::init("sqlite://test.db").await.unwrap(); - // let db = crate::db::init("postgres://rieter:rieter@localhost:5432/rieter") - // .await - // .unwrap(); let config = Config { repo_dir: self.repo_dir.clone(), diff --git a/server/src/db/entities/mod.rs b/server/src/db/entities/mod.rs index e5ad810..f1e964a 100644 --- a/server/src/db/entities/mod.rs +++ b/server/src/db/entities/mod.rs @@ -2,6 +2,4 @@ pub mod prelude; -pub mod package; -pub mod package_license; pub mod repo; diff --git a/server/src/db/entities/package.rs b/server/src/db/entities/package.rs deleted file mode 100644 index 86606bf..0000000 --- a/server/src/db/entities/package.rs +++ /dev/null @@ -1,53 +0,0 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.1 - -use sea_orm::entity::prelude::*; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] -#[sea_orm(table_name = "package")] -pub struct Model { - #[sea_orm(primary_key)] - pub id: i32, - pub repo_id: i32, - pub base: String, - pub name: String, - pub version: String, - pub arch: String, - pub size: i64, - pub c_size: i64, - pub description: Option, - pub url: Option, - pub build_date: DateTime, - pub packager: Option, - pub pgp_sig: Option, - pub pgp_sig_size: Option, - pub sha256_sum: String, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm(has_many = "super::package_license::Entity")] - PackageLicense, - #[sea_orm( - belongs_to = "super::repo::Entity", - from = "Column::RepoId", - to = "super::repo::Column::Id", - on_update = "NoAction", - on_delete = "Cascade" - )] - Repo, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::PackageLicense.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Repo.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/server/src/db/entities/package_license.rs b/server/src/db/entities/package_license.rs deleted file mode 100644 index 2920d3f..0000000 --- a/server/src/db/entities/package_license.rs +++ /dev/null @@ -1,33 +0,0 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.1 - -use sea_orm::entity::prelude::*; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] -#[sea_orm(table_name = "package_license")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub package_id: i32, - #[sea_orm(primary_key, auto_increment = false)] - pub value: String, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::package::Entity", - from = "Column::PackageId", - to = "super::package::Column::Id", - on_update = "NoAction", - on_delete = "Cascade" - )] - Package, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Package.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/server/src/db/entities/prelude.rs b/server/src/db/entities/prelude.rs index 1f8176c..8b651f8 100644 --- a/server/src/db/entities/prelude.rs +++ b/server/src/db/entities/prelude.rs @@ -1,5 +1,3 @@ //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.1 -pub use super::package::Entity as Package; -pub use super::package_license::Entity as PackageLicense; pub use super::repo::Entity as Repo; diff --git a/server/src/db/entities/repo.rs b/server/src/db/entities/repo.rs index b7a1af1..0676a76 100644 --- a/server/src/db/entities/repo.rs +++ b/server/src/db/entities/repo.rs @@ -1,28 +1,18 @@ //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.1 use sea_orm::entity::prelude::*; -use serde::{Deserialize, Serialize}; +use serde::Serialize; -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize)] #[sea_orm(table_name = "repo")] pub struct Model { #[sea_orm(primary_key)] pub id: i32, - #[sea_orm(unique)] pub name: String, pub description: Option, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm(has_many = "super::package::Entity")] - Package, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Package.def() - } -} +pub enum Relation {} impl ActiveModelBehavior for ActiveModel {} diff --git a/server/src/db/migrator/m20230730_000001_create_repo_tables.rs b/server/src/db/migrator/m20230730_000001_create_repo_tables.rs index df56657..4c36ade 100644 --- a/server/src/db/migrator/m20230730_000001_create_repo_tables.rs +++ b/server/src/db/migrator/m20230730_000001_create_repo_tables.rs @@ -10,6 +10,7 @@ impl MigrationName for Migration { #[async_trait::async_trait] impl MigrationTrait for Migration { + // Define how to apply this migration: Create the Bakery table. async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { manager .create_table( @@ -26,81 +27,11 @@ impl MigrationTrait for Migration { .col(ColumnDef::new(Repo::Description).string()) .to_owned(), ) - .await?; - manager - .create_table( - Table::create() - .table(Package::Table) - .col( - ColumnDef::new(Package::Id) - .integer() - .not_null() - .auto_increment() - .primary_key(), - ) - .col(ColumnDef::new(Package::RepoId).integer().not_null()) - .col(ColumnDef::new(Package::Base).string_len(255).not_null()) - .col(ColumnDef::new(Package::Name).string_len(255).not_null()) - .col(ColumnDef::new(Package::Version).string_len(255).not_null()) - .col(ColumnDef::new(Package::Arch).string_len(255).not_null()) - .col(ColumnDef::new(Package::Size).big_integer().not_null()) - .col(ColumnDef::new(Package::CSize).big_integer().not_null()) - .col(ColumnDef::new(Package::Description).string()) - .col(ColumnDef::new(Package::Url).string_len(255)) - .col(ColumnDef::new(Package::BuildDate).date_time().not_null()) - .col(ColumnDef::new(Package::Packager).string_len(255)) - .col(ColumnDef::new(Package::PgpSig).string_len(255)) - .col(ColumnDef::new(Package::PgpSigSize).big_integer()) - .col(ColumnDef::new(Package::Sha256Sum).char_len(64).not_null()) - .foreign_key( - ForeignKey::create() - .name("fk-package-repo_id") - .from(Package::Table, Package::RepoId) - .to(Repo::Table, Repo::Id) - .on_delete(ForeignKeyAction::Cascade), - ) - .to_owned(), - ) - .await?; - manager - .create_table( - Table::create() - .table(PackageLicense::Table) - .col( - ColumnDef::new(PackageLicense::PackageId) - .integer() - .not_null(), - ) - .col( - ColumnDef::new(PackageLicense::Value) - .string_len(255) - .not_null(), - ) - .primary_key( - Index::create() - .col(PackageLicense::PackageId) - .col(PackageLicense::Value), - ) - .foreign_key( - ForeignKey::create() - .name("fk-package_license-package_id") - .from(PackageLicense::Table, PackageLicense::PackageId) - .to(Package::Table, Package::Id) - .on_delete(ForeignKeyAction::Cascade), - ) - .to_owned(), - ) .await } // Define how to rollback this migration: Drop the Bakery table. async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .drop_table(Table::drop().table(PackageLicense::Table).to_owned()) - .await?; - manager - .drop_table(Table::drop().table(Package::Table).to_owned()) - .await?; manager .drop_table(Table::drop().table(Repo::Table).to_owned()) .await @@ -114,30 +45,3 @@ pub enum Repo { Name, Description, } - -#[derive(Iden)] -pub enum Package { - Table, - Id, - RepoId, - Name, - Base, - Version, - Description, - Size, - CSize, - Url, - Arch, - BuildDate, - Packager, - PgpSig, - PgpSigSize, - Sha256Sum, -} - -#[derive(Iden)] -pub enum PackageLicense { - Table, - PackageId, - Value, -} diff --git a/server/src/main.rs b/server/src/main.rs index 8217909..a6d41b5 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,6 +1,6 @@ mod api; mod cli; -pub mod db; +mod db; mod error; mod repo; diff --git a/server/src/repo/manager.rs b/server/src/repo/manager.rs index d036aab..df6ee17 100644 --- a/server/src/repo/manager.rs +++ b/server/src/repo/manager.rs @@ -71,12 +71,9 @@ impl RepoGroupManager { ar_db.close().and(ar_files.close()).map_err(Into::into) } - pub fn add_pkg_from_path>( - &mut self, - repo: &str, - path: P, - ) -> io::Result { - let pkg = Package::open(&path)?; + pub fn add_pkg_from_path>(&mut self, repo: &str, path: P) -> io::Result<()> { + let mut pkg = Package::open(&path)?; + pkg.calculate_checksum()?; let archs = self.add_pkg_in_repo(repo, &pkg)?; @@ -90,9 +87,7 @@ impl RepoGroupManager { fs::hard_link(&path, dest_pkg_path)?; } - fs::remove_file(path)?; - - Ok(pkg) + fs::remove_file(path) } /// Add a package to the given repo, returning to what architectures the package was added. diff --git a/server/src/repo/mod.rs b/server/src/repo/mod.rs index e4be526..57ddd11 100644 --- a/server/src/repo/mod.rs +++ b/server/src/repo/mod.rs @@ -3,13 +3,11 @@ mod package; pub use manager::RepoGroupManager; -use crate::db::entities::{package as db_package, repo as db_repo}; use axum::extract::{BodyStream, Path, State}; use axum::http::StatusCode; use axum::routing::{delete, get_service, post}; use axum::Router; use futures::StreamExt; -use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter}; use std::sync::Arc; use tokio::{fs, io::AsyncWriteExt}; use tower_http::services::ServeDir; @@ -45,38 +43,8 @@ async fn post_package_archive( } let clone = Arc::clone(&global.repo_manager); - - let repo_clone = repo.clone(); - let pkg = tokio::task::spawn_blocking(move || { - clone.write().unwrap().add_pkg_from_path(&repo_clone, &path) - }) - .await??; - - // Query the repo for its ID, or create it if it does not already exist - let repo_entity = db_repo::Entity::find() - .filter(db_repo::Column::Name.eq(&repo)) - .one(&global.db) - .await?; - - let repo_id = if let Some(repo_entity) = repo_entity { - repo_entity.id - } else { - let model = db_repo::ActiveModel { - name: sea_orm::Set(repo.clone()), - ..Default::default() - }; - - db_repo::Entity::insert(model) - .exec(&global.db) - .await? - .last_insert_id - }; - - // Insert the package's data into the database - let mut model: db_package::ActiveModel = pkg.into(); - model.repo_id = sea_orm::Set(repo_id); - - model.insert(&global.db).await?; + tokio::task::spawn_blocking(move || clone.write().unwrap().add_pkg_from_path(&repo, &path)) + .await??; Ok(()) } diff --git a/server/src/repo/package.rs b/server/src/repo/package.rs index ddafbd9..4ff9433 100644 --- a/server/src/repo/package.rs +++ b/server/src/repo/package.rs @@ -1,14 +1,10 @@ -use chrono::NaiveDateTime; use libarchive::read::{Archive, Builder}; use libarchive::{Entry, ReadFilter}; -use sea_orm::ActiveValue::Set; use std::fmt; use std::fs; use std::io::{self, BufRead, BufReader, BufWriter, Read, Write}; use std::path::{Path, PathBuf}; -use crate::db::entities::package; - const IGNORED_FILES: [&str; 5] = [".BUILDINFO", ".INSTALL", ".MTREE", ".PKGINFO", ".CHANGELOG"]; #[derive(Debug)] @@ -21,18 +17,18 @@ pub struct Package { #[derive(Debug, Default)] pub struct PkgInfo { - pub base: String, pub name: String, + pub base: String, pub version: String, + pub description: String, + pub size: u64, + pub csize: u64, + pub url: String, pub arch: String, - pub description: Option, - pub size: i64, - pub csize: i64, - pub url: Option, - pub build_date: NaiveDateTime, - pub packager: Option, - pub pgpsig: Option, - pub pgpsigsize: Option, + pub build_date: i64, + pub packager: String, + pub pgpsig: String, + pub pgpsigsize: i64, pub groups: Vec, pub licenses: Vec, pub replaces: Vec, @@ -42,7 +38,7 @@ pub struct PkgInfo { pub optdepends: Vec, pub makedepends: Vec, pub checkdepends: Vec, - pub sha256sum: String, + pub sha256sum: Option, } #[derive(Debug, PartialEq, Eq)] @@ -74,27 +70,23 @@ impl PkgInfo { "pkgname" => self.name = value.to_string(), "pkgbase" => self.base = value.to_string(), "pkgver" => self.version = value.to_string(), - "pkgdesc" => self.description = Some(value.to_string()), + "pkgdesc" => self.description = value.to_string(), "size" => { self.size = value.parse().map_err(|_| ParsePkgInfoError::InvalidSize)? } - "url" => self.url = Some(value.to_string()), + "url" => self.url = value.to_string(), "arch" => self.arch = value.to_string(), "builddate" => { - let seconds: i64 = value + self.build_date = value .parse() - .map_err(|_| ParsePkgInfoError::InvalidBuildDate)?; - self.build_date = NaiveDateTime::from_timestamp_millis(seconds * 1000) - .ok_or(ParsePkgInfoError::InvalidBuildDate)? + .map_err(|_| ParsePkgInfoError::InvalidBuildDate)? } - "packager" => self.packager = Some(value.to_string()), - "pgpsig" => self.pgpsig = Some(value.to_string()), + "packager" => self.packager = value.to_string(), + "pgpsig" => self.pgpsig = value.to_string(), "pgpsigsize" => { - self.pgpsigsize = Some( - value - .parse() - .map_err(|_| ParsePkgInfoError::InvalidPgpSigSize)?, - ) + self.pgpsigsize = value + .parse() + .map_err(|_| ParsePkgInfoError::InvalidPgpSigSize)? } "group" => self.groups.push(value.to_string()), "license" => self.licenses.push(value.to_string()), @@ -164,9 +156,7 @@ impl Package { } if let Some(mut info) = info { - // I'll take my chances on a file size fitting in an i64 - info.csize = fs::metadata(path.as_ref())?.len().try_into().unwrap(); - info.sha256sum = sha256::try_digest(path.as_ref())?; + info.csize = fs::metadata(path.as_ref())?.len(); Ok(Package { path: path.as_ref().to_path_buf(), @@ -182,6 +172,12 @@ impl Package { } } + pub fn calculate_checksum(&mut self) -> io::Result<()> { + self.info.sha256sum = Some(sha256::try_digest(self.path.as_ref())?); + + Ok(()) + } + pub fn full_name(&self) -> String { format!( "{}-{}-{}", @@ -220,27 +216,20 @@ impl Package { write("NAME", &info.name)?; write("BASE", &info.base)?; write("VERSION", &info.version)?; - - if let Some(ref description) = info.description { - write("DESC", description)?; - } + write("DESC", &info.description)?; write("GROUPS", &info.groups.join("\n"))?; write("CSIZE", &info.csize.to_string())?; write("ISIZE", &info.size.to_string())?; - write("SHA256SUM", &info.sha256sum)?; - - if let Some(ref url) = info.url { - write("URL", url)?; + if let Some(checksum) = &info.sha256sum { + write("SHA256SUM", checksum)?; } + write("URL", &info.url)?; write("LICENSE", &info.licenses.join("\n"))?; write("ARCH", &info.arch)?; - write("BUILDDATE", &info.build_date.timestamp().to_string())?; - - if let Some(ref packager) = info.packager { - write("PACKAGER", packager)?; - } + write("BUILDDATE", &info.build_date.to_string())?; + write("PACKAGER", &info.packager)?; write("REPLACES", &info.replaces.join("\n"))?; write("CONFLICTS", &info.conflicts.join("\n"))?; @@ -267,26 +256,3 @@ impl Package { Ok(()) } } - -impl From for package::ActiveModel { - fn from(pkg: Package) -> Self { - let info = pkg.info; - - package::ActiveModel { - base: Set(info.base), - name: Set(info.name), - version: Set(info.version), - arch: Set(info.arch), - size: Set(info.size), - c_size: Set(info.csize), - description: Set(info.description), - url: Set(info.url), - build_date: Set(info.build_date), - packager: Set(info.packager), - pgp_sig: Set(info.pgpsig), - pgp_sig_size: Set(info.pgpsigsize), - sha256_sum: Set(info.sha256sum), - ..Default::default() - } - } -}