From f9c5faeda89f1089df7aa0e3ca3367bb9547eea8 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Thu, 13 Jul 2023 14:58:27 +0200 Subject: [PATCH] feat: add repo group manager to global context --- server/src/main.rs | 25 +++++++++++++++++++++++-- server/src/repo/manager.rs | 2 +- server/src/repo/mod.rs | 18 +++++++++--------- server/src/repo/package.rs | 17 +++++++++++++++++ 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/server/src/main.rs b/server/src/main.rs index 3891722..1930d12 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,7 +1,10 @@ mod repo; use axum::Router; +use repo::RepoGroupManager; use std::path::PathBuf; +use std::sync::{RwLock, Arc}; +use axum::extract::FromRef; #[derive(Clone)] pub struct Config { @@ -10,6 +13,18 @@ pub struct Config { pkg_dir: PathBuf, } +#[derive(Clone)] +pub struct Global { + config: Config, + repo_manager: Arc>, +} + +impl FromRef for Arc> { + fn from_ref(global: &Global) -> Self { + Arc::clone(&global.repo_manager) + } +} + #[tokio::main] async fn main() { let config = Config { @@ -17,11 +32,17 @@ async fn main() { repo_dir: "./data/repos".into(), pkg_dir: "./data/pkgs".into(), }; + let repo_manager = RepoGroupManager::new("./data/repos", "./data/pkgs"); + + let global = Global { + config, + repo_manager: Arc::new(RwLock::new(repo_manager)), + }; // build our application with a single route let app = Router::new() - .merge(repo::router(&config)) - .with_state(config); + .merge(repo::router(&global)) + .with_state(global); // run it with hyper on localhost:3000 axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) diff --git a/server/src/repo/manager.rs b/server/src/repo/manager.rs index 7dc9eb6..376eba6 100644 --- a/server/src/repo/manager.rs +++ b/server/src/repo/manager.rs @@ -7,7 +7,7 @@ pub struct RepoGroupManager { } impl RepoGroupManager { - fn new, P2: AsRef>(repo_dir: P1, pkg_dir: P2) -> Self { + pub fn new, P2: AsRef>(repo_dir: P1, pkg_dir: P2) -> Self { RepoGroupManager { repo_dir: repo_dir.as_ref().to_path_buf(), pkg_dir: pkg_dir.as_ref().to_path_buf(), diff --git a/server/src/repo/mod.rs b/server/src/repo/mod.rs index 2e00802..72df5ed 100644 --- a/server/src/repo/mod.rs +++ b/server/src/repo/mod.rs @@ -1,6 +1,8 @@ mod manager; mod package; +pub use manager::RepoGroupManager; + use axum::extract::{BodyStream, Path, State}; use axum::http::StatusCode; use axum::response::IntoResponse; @@ -9,29 +11,27 @@ use axum::Router; use futures::StreamExt; use futures::TryFutureExt; use futures::TryStreamExt; -use libarchive::archive::Entry; -use libarchive::read::Archive; -use libarchive::read::Builder; use std::io::Read; use tokio::{fs, io, io::AsyncWriteExt}; use tower_http::services::ServeDir; use uuid::Uuid; -pub fn router(config: &crate::Config) -> Router { +pub fn router(global: &crate::Global) -> Router { // Try to serve packages by default, and try the database files instead if not found - let serve_repos = - get_service(ServeDir::new(&config.pkg_dir).fallback(ServeDir::new(&config.repo_dir))); + let serve_repos = get_service( + ServeDir::new(&global.config.pkg_dir).fallback(ServeDir::new(&global.config.repo_dir)), + ); Router::new() .route( "/:repo", post(post_package_archive).get(serve_repos.clone()), ) .fallback(serve_repos) - .with_state(config.clone()) + .with_state(global.clone()) } async fn post_package_archive( - State(config): State, + State(global): State, Path(repo): Path, body: BodyStream, ) -> Result<(), StatusCode> { @@ -42,7 +42,7 @@ async fn post_package_archive( // We first stream the uploaded file to disk let uuid: uuid::fmt::Simple = Uuid::new_v4().into(); - let path = config.pkg_dir.join(uuid.to_string()); + let path = global.config.pkg_dir.join(uuid.to_string()); let mut f = fs::File::create(&path) .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR) .await?; diff --git a/server/src/repo/package.rs b/server/src/repo/package.rs index d23aeee..beb156c 100644 --- a/server/src/repo/package.rs +++ b/server/src/repo/package.rs @@ -176,4 +176,21 @@ impl Package { Ok(()) } + + pub fn full_name(&self) -> String { + format!( + "{}-{}-{}", + self.info.name, self.info.version, self.info.arch + ) + } + + pub fn file_name(&self) -> String { + // This unwrap should be safe, because we only allow passing through compressions with + // known file extensions + format!( + "{}.pkg.tar{}", + self.full_name(), + self.compression.extension().unwrap() + ) + } }