diff --git a/server/src/cli.rs b/server/src/cli.rs index 740e2ad..2419606 100644 --- a/server/src/cli.rs +++ b/server/src/cli.rs @@ -1,4 +1,4 @@ -use crate::{distro::MetaDistroMgr, repo::MetaRepoMgr, Config, Global}; +use crate::{repo::MetaRepoMgr, Config, Global}; use axum::{extract::FromRef, Router}; use clap::Parser; @@ -42,6 +42,12 @@ pub struct Cli { pub log: String, } +impl FromRef for Arc> { + fn from_ref(global: &Global) -> Self { + Arc::clone(&global.repo_manager) + } +} + impl Cli { pub fn init_tracing(&self) { tracing_subscriber::registry() @@ -75,11 +81,13 @@ impl Cli { let config = Config { data_dir: self.data_dir.clone(), }; + let repo_manager = MetaRepoMgr::new(&self.data_dir.join("repos"), db.clone()); - let mgr = MetaDistroMgr::new(&self.data_dir.join("distros"), db.clone()); - mgr.bootstrap().await?; - - let global = Global { config, mgr, db }; + let global = Global { + config, + repo_manager: Arc::new(RwLock::new(repo_manager)), + db, + }; // build our application with a single route let app = Router::new() diff --git a/server/src/db/entities/distro.rs b/server/src/db/entities/distro.rs deleted file mode 100644 index f39ad53..0000000 --- a/server/src/db/entities/distro.rs +++ /dev/null @@ -1,27 +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 = "distro")] -pub struct Model { - #[sea_orm(primary_key)] - pub id: i32, - pub name: String, - pub description: Option, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm(has_many = "super::repo::Entity")] - Repo, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::Repo.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/server/src/db/entities/mod.rs b/server/src/db/entities/mod.rs index b38dbb1..ab8f32a 100644 --- a/server/src/db/entities/mod.rs +++ b/server/src/db/entities/mod.rs @@ -2,7 +2,6 @@ pub mod prelude; -pub mod distro; pub mod package; pub mod package_file; pub mod package_group; diff --git a/server/src/db/entities/prelude.rs b/server/src/db/entities/prelude.rs index 8ebe873..1a6e503 100644 --- a/server/src/db/entities/prelude.rs +++ b/server/src/db/entities/prelude.rs @@ -1,6 +1,5 @@ //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.1 -pub use super::distro::Entity as Distro; pub use super::package::Entity as Package; pub use super::package_file::Entity as PackageFile; pub use super::package_group::Entity as PackageGroup; diff --git a/server/src/db/entities/repo.rs b/server/src/db/entities/repo.rs index 1ddd39e..25291da 100644 --- a/server/src/db/entities/repo.rs +++ b/server/src/db/entities/repo.rs @@ -8,31 +8,16 @@ use serde::{Deserialize, Serialize}; pub struct Model { #[sea_orm(primary_key)] pub id: i32, - pub distro_id: i32, pub name: String, pub description: Option, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { - #[sea_orm( - belongs_to = "super::distro::Entity", - from = "Column::DistroId", - to = "super::distro::Column::Id", - on_update = "NoAction", - on_delete = "Cascade" - )] - Distro, #[sea_orm(has_many = "super::package::Entity")] Package, } -impl Related for Entity { - fn to() -> RelationDef { - Relation::Distro.def() - } -} - impl Related for Entity { fn to() -> RelationDef { Relation::Package.def() 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 b1e1fbe..9d76afc 100644 --- a/server/src/db/migrator/m20230730_000001_create_repo_tables.rs +++ b/server/src/db/migrator/m20230730_000001_create_repo_tables.rs @@ -11,27 +11,6 @@ impl MigrationName for Migration { #[async_trait::async_trait] impl MigrationTrait for Migration { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .create_table( - Table::create() - .table(Distro::Table) - .col( - ColumnDef::new(Distro::Id) - .integer() - .not_null() - .auto_increment() - .primary_key(), - ) - .col( - ColumnDef::new(Distro::Name) - .string() - .not_null() - .unique_key(), - ) - .col(ColumnDef::new(Distro::Description).string()) - .to_owned(), - ) - .await?; manager .create_table( Table::create() @@ -43,16 +22,8 @@ impl MigrationTrait for Migration { .auto_increment() .primary_key(), ) - .col(ColumnDef::new(Repo::DistroId).integer().not_null()) .col(ColumnDef::new(Repo::Name).string().not_null().unique_key()) .col(ColumnDef::new(Repo::Description).string()) - .foreign_key( - ForeignKey::create() - .name("fk-repo-distro_id") - .from(Repo::Table, Repo::DistroId) - .to(Distro::Table, Distro::Id) - .on_delete(ForeignKeyAction::Cascade), - ) .to_owned(), ) .await?; @@ -221,26 +192,14 @@ impl MigrationTrait for Migration { .await?; manager .drop_table(Table::drop().table(Repo::Table).to_owned()) - .await?; - manager - .drop_table(Table::drop().table(Distro::Table).to_owned()) .await } } -#[derive(Iden)] -pub enum Distro { - Table, - Id, - Name, - Description, -} - #[derive(Iden)] pub enum Repo { Table, Id, - DistroId, Name, Description, } diff --git a/server/src/db/query/distro.rs b/server/src/db/query/distro.rs deleted file mode 100644 index c4fc70f..0000000 --- a/server/src/db/query/distro.rs +++ /dev/null @@ -1,47 +0,0 @@ -use crate::db::*; - -use sea_orm::{sea_query::IntoCondition, *}; - -#[derive(Deserialize)] -pub struct Filter { - name: Option, -} - -impl IntoCondition for Filter { - fn into_condition(self) -> Condition { - Condition::all().add_option( - self.name - .map(|name| distro::Column::Name.like(format!("%{}%", name))), - ) - } -} - -pub async fn page( - conn: &DbConn, - per_page: u64, - page: u64, - filter: Filter, -) -> Result<(u64, Vec)> { - let paginator = Distro::find() - .filter(filter) - .order_by_asc(distro::Column::Id) - .paginate(conn, per_page); - let repos = paginator.fetch_page(page).await?; - let total_pages = paginator.num_pages().await?; - - Ok((total_pages, repos)) -} - -pub async fn by_id(conn: &DbConn, id: i32) -> Result> { - distro::Entity::find_by_id(id).one(conn).await -} - -pub async fn insert(conn: &DbConn, name: &str, description: Option<&str>) -> Result { - let model = distro::ActiveModel { - id: NotSet, - name: Set(String::from(name)), - description: Set(description.map(String::from)), - }; - - model.insert(conn).await -} diff --git a/server/src/db/query/mod.rs b/server/src/db/query/mod.rs index f0a809b..87d61e3 100644 --- a/server/src/db/query/mod.rs +++ b/server/src/db/query/mod.rs @@ -1,4 +1,3 @@ -pub mod distro; pub mod package; pub mod repo; diff --git a/server/src/db/query/repo.rs b/server/src/db/query/repo.rs index 2ad54bf..0370c2b 100644 --- a/server/src/db/query/repo.rs +++ b/server/src/db/query/repo.rs @@ -43,15 +43,9 @@ pub async fn by_name(conn: &DbConn, name: &str) -> Result> { .await } -pub async fn insert( - conn: &DbConn, - distro_id: i32, - name: &str, - description: Option<&str>, -) -> Result { +pub async fn insert(conn: &DbConn, name: &str, description: Option<&str>) -> Result { let model = repo::ActiveModel { id: NotSet, - distro_id: Set(distro_id), name: Set(String::from(name)), description: Set(description.map(String::from)), }; diff --git a/server/src/distro.rs b/server/src/distro.rs deleted file mode 100644 index 209d227..0000000 --- a/server/src/distro.rs +++ /dev/null @@ -1,69 +0,0 @@ -use crate::{db, MetaRepoMgr}; - -use std::{ - collections::HashMap, - path::{Path, PathBuf}, - sync::Arc, -}; - -use sea_orm::{DbConn, EntityTrait}; -use tokio::sync::Mutex; - -#[derive(Clone)] -pub struct MetaDistroMgr { - distro_dir: PathBuf, - conn: DbConn, - distros: Arc>>>, -} - -impl MetaDistroMgr { - pub fn new>(distro_dir: P, conn: DbConn) -> Self { - Self { - distro_dir: distro_dir.as_ref().to_path_buf(), - conn, - distros: Arc::new(Mutex::new(HashMap::new())), - } - } - - /// Populate the manager with the currently known distros from the database. - pub async fn bootstrap(&self) -> crate::Result<()> { - let mut map = self.distros.lock().await; - let distros = db::Distro::find().all(&self.conn).await?; - - for distro in distros { - let mgr = MetaRepoMgr::new( - self.distro_dir.join(&distro.name), - distro.id, - self.conn.clone(), - ); - map.insert(distro.name, Arc::new(mgr)); - } - - Ok(()) - } - - pub async fn get_mgr(&self, distro: &str) -> Option> { - let map = self.distros.lock().await; - - map.get(distro).map(|mgr| Arc::clone(mgr)) - } - - pub async fn get_or_create_mgr(&self, distro: &str) -> crate::Result> { - let mut map = self.distros.lock().await; - - if let Some(mgr) = map.get(distro) { - Ok(Arc::clone(mgr)) - } else { - let distro = db::query::distro::insert(&self.conn, distro, None).await?; - - let mgr = Arc::new(MetaRepoMgr::new( - self.distro_dir.join(&distro.name), - distro.id, - self.conn.clone(), - )); - map.insert(distro.name, Arc::clone(&mgr)); - - Ok(mgr) - } - } -} diff --git a/server/src/main.rs b/server/src/main.rs index a428e39..c57420a 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,7 +1,6 @@ mod api; mod cli; pub mod db; -mod distro; mod error; mod repo; @@ -20,7 +19,7 @@ pub struct Config { #[derive(Clone)] pub struct Global { config: Config, - mgr: distro::MetaDistroMgr, + repo_manager: Arc>, db: sea_orm::DbConn, } diff --git a/server/src/repo/manager.rs b/server/src/repo/manager.rs index a877d0d..e2d9c4d 100644 --- a/server/src/repo/manager.rs +++ b/server/src/repo/manager.rs @@ -12,15 +12,13 @@ pub const ANY_ARCH: &'static str = "any"; pub struct MetaRepoMgr { repo_dir: PathBuf, - distro_id: i32, conn: DbConn, } impl MetaRepoMgr { - pub fn new>(repo_dir: P, distro_id: i32, conn: DbConn) -> Self { + pub fn new>(repo_dir: P, conn: DbConn) -> Self { MetaRepoMgr { repo_dir: repo_dir.as_ref().to_path_buf(), - distro_id, conn, } } @@ -239,9 +237,7 @@ impl MetaRepoMgr { let repo_id = if let Some(repo_entity) = res { repo_entity.id } else { - db::query::repo::insert(&self.conn, self.distro_id, repo, None) - .await? - .id + db::query::repo::insert(&self.conn, repo, None).await?.id }; // If the package already exists in the database, we remove it first diff --git a/server/src/repo/mod.rs b/server/src/repo/mod.rs index 7544faa..2f2dacb 100644 --- a/server/src/repo/mod.rs +++ b/server/src/repo/mod.rs @@ -20,19 +20,19 @@ use tower_http::{services::ServeFile, validate_request::ValidateRequestHeaderLay pub fn router(api_key: &str) -> Router { Router::new() .route( - "/:distro/:repo", + "/:repo", post(post_package_archive) .delete(delete_repo) .route_layer(ValidateRequestHeaderLayer::bearer(api_key)), ) .route( - "/:distro/:repo/:arch", + "/:repo/:arch", delete(delete_arch_repo).route_layer(ValidateRequestHeaderLayer::bearer(api_key)), ) // Routes added after the layer do not get that layer applied, so the GET requests will not // be authorized .route( - "/:distro/:repo/:arch/:filename", + "/:repo/:arch/:filename", delete(delete_package) .route_layer(ValidateRequestHeaderLayer::bearer(api_key)) .get(get_file), @@ -44,15 +44,10 @@ pub fn router(api_key: &str) -> Router { /// is returned. async fn get_file( State(global): State, - Path((distro, repo, arch, file_name)): Path<(String, String, String, String)>, + Path((repo, arch, file_name)): Path<(String, String, String)>, req: Request, ) -> crate::Result { - let repo_dir = global - .config - .data_dir - .join("distros") - .join(&distro) - .join(&repo); + let repo_dir = global.config.data_dir.join("repos").join(&repo); let file_name = if file_name == format!("{}.db", repo) || file_name == format!("{}.db.tar.gz", repo) { @@ -70,12 +65,16 @@ async fn get_file( async fn post_package_archive( State(global): State, - Path((distro, repo)): Path<(String, String)>, + Path(repo): Path, body: Body, ) -> crate::Result<()> { let mut body = StreamReader::new(body.into_data_stream().map_err(std::io::Error::other)); - let mgr = global.mgr.get_or_create_mgr(&distro).await?; - let (name, version, arch) = mgr.add_pkg_from_reader(&mut body, &repo).await?; + let (name, version, arch) = global + .repo_manager + .write() + .await + .add_pkg_from_reader(&mut body, &repo) + .await?; tracing::info!( "Added '{}-{}' to repository '{}' ({})", @@ -90,18 +89,14 @@ async fn post_package_archive( async fn delete_repo( State(global): State, - Path((distro, repo)): Path<(String, String)>, + Path(repo): Path, ) -> crate::Result { - if let Some(mgr) = global.mgr.get_mgr(&distro).await { - let repo_removed = mgr.remove_repo(&repo).await?; + let repo_removed = global.repo_manager.write().await.remove_repo(&repo).await?; - if repo_removed { - tracing::info!("Removed repository '{}'", repo); + if repo_removed { + tracing::info!("Removed repository '{}'", repo); - Ok(StatusCode::OK) - } else { - Ok(StatusCode::NOT_FOUND) - } + Ok(StatusCode::OK) } else { Ok(StatusCode::NOT_FOUND) } @@ -109,18 +104,19 @@ async fn delete_repo( async fn delete_arch_repo( State(global): State, - Path((distro, repo, arch)): Path<(String, String, String)>, + Path((repo, arch)): Path<(String, String)>, ) -> crate::Result { - if let Some(mgr) = global.mgr.get_mgr(&distro).await { - let repo_removed = mgr.remove_repo_arch(&repo, &arch).await?; + let repo_removed = global + .repo_manager + .write() + .await + .remove_repo_arch(&repo, &arch) + .await?; - if repo_removed { - tracing::info!("Removed arch '{}' from repository '{}'", arch, repo); + if repo_removed { + tracing::info!("Removed arch '{}' from repository '{}'", arch, repo); - Ok(StatusCode::OK) - } else { - Ok(StatusCode::NOT_FOUND) - } + Ok(StatusCode::OK) } else { Ok(StatusCode::NOT_FOUND) } @@ -128,23 +124,24 @@ async fn delete_arch_repo( async fn delete_package( State(global): State, - Path((distro, repo, arch, pkg_name)): Path<(String, String, String, String)>, + Path((repo, arch, pkg_name)): Path<(String, String, String)>, ) -> crate::Result { - if let Some(mgr) = global.mgr.get_mgr(&distro).await { - let pkg_removed = mgr.remove_pkg(&repo, &arch, &pkg_name).await?; + let pkg_removed = global + .repo_manager + .write() + .await + .remove_pkg(&repo, &arch, &pkg_name) + .await?; - if pkg_removed { - tracing::info!( - "Removed package '{}' ({}) from repository '{}'", - pkg_name, - arch, - repo - ); + if pkg_removed { + tracing::info!( + "Removed package '{}' ({}) from repository '{}'", + pkg_name, + arch, + repo + ); - Ok(StatusCode::OK) - } else { - Ok(StatusCode::NOT_FOUND) - } + Ok(StatusCode::OK) } else { Ok(StatusCode::NOT_FOUND) }