feat: add POST api route for creating mirror repos
parent
cbb04a40e0
commit
d39205b653
|
@ -2,8 +2,12 @@ pub mod query;
|
||||||
|
|
||||||
use crate::config::DbConfig;
|
use crate::config::DbConfig;
|
||||||
|
|
||||||
use sea_orm::{ConnectionTrait, Database, DbConn};
|
use sea_orm::{
|
||||||
use serde::Serialize;
|
ActiveModelTrait,
|
||||||
|
ActiveValue::{NotSet, Set},
|
||||||
|
ConnectionTrait, Database, DbConn, EntityTrait, TransactionTrait,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
type Result<T> = std::result::Result<T, sea_orm::DbErr>;
|
type Result<T> = std::result::Result<T, sea_orm::DbErr>;
|
||||||
|
|
||||||
|
@ -17,6 +21,61 @@ pub struct FullPackage {
|
||||||
files: Vec<String>,
|
files: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "type")]
|
||||||
|
pub enum RepoType {
|
||||||
|
Regular,
|
||||||
|
FullMirror { mirrors: Vec<String> },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct NewRepo {
|
||||||
|
distro_id: i32,
|
||||||
|
name: String,
|
||||||
|
description: Option<String>,
|
||||||
|
#[serde(flatten)]
|
||||||
|
r#type: RepoType,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NewRepo {
|
||||||
|
pub async fn insert(self, conn: &DbConn) -> crate::Result<entity::repo::Model> {
|
||||||
|
let txn = conn.begin().await?;
|
||||||
|
|
||||||
|
let repo_type = match self.r#type {
|
||||||
|
RepoType::Regular => entity::RepoType::Regular,
|
||||||
|
RepoType::FullMirror { .. } => entity::RepoType::FullMirror,
|
||||||
|
};
|
||||||
|
|
||||||
|
let repo = entity::repo::ActiveModel {
|
||||||
|
id: NotSet,
|
||||||
|
distro_id: Set(self.distro_id),
|
||||||
|
name: Set(self.name),
|
||||||
|
description: Set(self.description),
|
||||||
|
r#type: Set(repo_type),
|
||||||
|
};
|
||||||
|
let model = repo.insert(conn).await?;
|
||||||
|
|
||||||
|
match self.r#type {
|
||||||
|
RepoType::Regular => {}
|
||||||
|
RepoType::FullMirror { mirrors } => {
|
||||||
|
entity::RepoMirror::insert_many(mirrors.into_iter().map(|url| {
|
||||||
|
entity::repo_mirror::ActiveModel {
|
||||||
|
id: NotSet,
|
||||||
|
repo_id: Set(model.id),
|
||||||
|
url: Set(url),
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.on_empty_do_nothing()
|
||||||
|
.exec(&txn)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
txn.commit().await?;
|
||||||
|
Ok(model)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn connect(conn: &DbConfig) -> crate::Result<DbConn> {
|
pub async fn connect(conn: &DbConfig) -> crate::Result<DbConn> {
|
||||||
match conn {
|
match conn {
|
||||||
DbConfig::Sqlite {
|
DbConfig::Sqlite {
|
||||||
|
|
|
@ -30,9 +30,16 @@ impl Handle {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_or_create_repo(&self, distro: &str, repo: &str) -> crate::Result<i32> {
|
pub async fn register_repo(&self, repo_id: i32) -> crate::Result<()> {
|
||||||
let mut repos = self.state.repos.write().await;
|
tokio::fs::create_dir(self.state.repos_dir.join(repo_id.to_string())).await?;
|
||||||
|
|
||||||
|
let mut repos = self.state.repos.write().await;
|
||||||
|
repos.insert(repo_id, Default::default());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_or_create_repo(&self, distro: &str, repo: &str) -> crate::Result<i32> {
|
||||||
let distro_id: Option<i32> = entity::Distro::find()
|
let distro_id: Option<i32> = entity::Distro::find()
|
||||||
.filter(entity::distro::Column::Name.eq(distro))
|
.filter(entity::distro::Column::Name.eq(distro))
|
||||||
.select_only()
|
.select_only()
|
||||||
|
@ -74,8 +81,7 @@ impl Handle {
|
||||||
};
|
};
|
||||||
let id = new_repo.insert(&self.state.conn).await?.id;
|
let id = new_repo.insert(&self.state.conn).await?.id;
|
||||||
|
|
||||||
tokio::fs::create_dir(self.state.repos_dir.join(id.to_string())).await?;
|
self.register_repo(id).await?;
|
||||||
repos.insert(id, Default::default());
|
|
||||||
|
|
||||||
id
|
id
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
mod pagination;
|
mod pagination;
|
||||||
|
mod repo;
|
||||||
|
|
||||||
use crate::db;
|
use crate::db;
|
||||||
use pagination::PaginatedResponse;
|
use pagination::PaginatedResponse;
|
||||||
|
|
||||||
use axum::{
|
use axum::{
|
||||||
extract::{Path, Query, State},
|
extract::{Path, Query, State},
|
||||||
|
http::StatusCode,
|
||||||
routing::get,
|
routing::get,
|
||||||
Json, Router,
|
Json, Router,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn router() -> Router<crate::Global> {
|
pub fn router() -> Router<crate::Global> {
|
||||||
Router::new()
|
Router::new()
|
||||||
.route("/repos", get(get_repos))
|
.route("/repos", get(get_repos).post(post_repo))
|
||||||
.route("/repos/:id", get(get_single_repo))
|
.route("/repos/:id", get(get_single_repo))
|
||||||
.route("/packages", get(get_packages))
|
.route("/packages", get(get_packages))
|
||||||
.route("/packages/:id", get(get_single_package))
|
.route("/packages/:id", get(get_single_package))
|
||||||
|
@ -39,6 +41,16 @@ async fn get_single_repo(
|
||||||
Ok(Json(repo))
|
Ok(Json(repo))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn post_repo(
|
||||||
|
State(global): State<crate::Global>,
|
||||||
|
Json(repo): Json<crate::db::NewRepo>,
|
||||||
|
) -> crate::Result<(StatusCode, Json<entity::repo::Model>)> {
|
||||||
|
let model = repo.insert(&global.db).await?;
|
||||||
|
global.repo.register_repo(model.id).await?;
|
||||||
|
|
||||||
|
Ok((StatusCode::CREATED, Json(model)))
|
||||||
|
}
|
||||||
|
|
||||||
async fn get_packages(
|
async fn get_packages(
|
||||||
State(global): State<crate::Global>,
|
State(global): State<crate::Global>,
|
||||||
Query(pagination): Query<pagination::Query>,
|
Query(pagination): Query<pagination::Query>,
|
||||||
|
|
Loading…
Reference in New Issue