diff --git a/Cargo.toml b/Cargo.toml index c97e62a..5b851dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,5 @@ [package] +# todo rename to AURCentral name = "untitled" version = "0.1.0" edition = "2021" diff --git a/src/api/add.rs b/src/api/add.rs new file mode 100644 index 0000000..5930533 --- /dev/null +++ b/src/api/add.rs @@ -0,0 +1,56 @@ +use crate::aur::aur::get_info_by_name; +use crate::builder::types::Action; +use crate::db::{packages, versions}; +use rocket::serde::json::Json; +use rocket::serde::Deserialize; +use rocket::{post, State}; +use rocket_okapi::okapi::schemars; +use rocket_okapi::{openapi, JsonSchema}; +use sea_orm::ActiveModelTrait; +use sea_orm::{DatabaseConnection, Set}; +use tokio::sync::broadcast::Sender; + +#[derive(Deserialize, JsonSchema)] +#[serde(crate = "rocket::serde")] +pub struct AddBody { + name: String, +} + +#[openapi(tag = "test")] +#[post("/packages/add", data = "")] +pub async fn package_add( + db: &State, + input: Json, + tx: &State>, +) -> Result<(), String> { + let db = db as &DatabaseConnection; + let pkg_name = &input.name; + + let pkg = get_info_by_name(pkg_name) + .await + .map_err(|_| "couldn't download package metadata".to_string())?; + + let new_package = packages::ActiveModel { + name: Set(pkg_name.clone()), + ..Default::default() + }; + + let pkt_model = new_package.save(db).await.expect("TODO: panic message"); + + let new_version = versions::ActiveModel { + version: Set(pkg.version.clone()), + package_id: Set(pkt_model.id.clone().unwrap()), + ..Default::default() + }; + + let version_model = new_version.save(db).await.expect("TODO: panic message"); + + let _ = tx.send(Action::Build( + pkg.name, + pkg.version, + pkg.url_path.unwrap(), + version_model, + )); + + Ok(()) +} diff --git a/src/api/backend.rs b/src/api/backend.rs index fcfa75a..ac32f84 100644 --- a/src/api/backend.rs +++ b/src/api/backend.rs @@ -1,147 +1,13 @@ -use crate::aur::aur::get_info_by_name; -use crate::builder::types::Action; -use crate::db::{packages, versions}; -use crate::query_aur; -use rocket::serde::json::Json; -use rocket::serde::{Deserialize, Serialize}; -use rocket::State; -use rocket::{get, post, Route}; -use rocket_okapi::okapi::schemars; -use rocket_okapi::{openapi, openapi_get_routes, JsonSchema}; -use sea_orm::EntityTrait; -use sea_orm::{ActiveModelTrait, DatabaseConnection, FromQueryResult, JoinType, QuerySelect, Set}; -use sea_orm::{ColumnTrait, RelationTrait}; -use tokio::sync::broadcast::Sender; - -use crate::db::prelude::Packages; -use crate::repo::repo::{remove_pkg, remove_version}; - -#[derive(Serialize, JsonSchema)] -#[serde(crate = "rocket::serde")] -struct ApiPackage { - name: String, - version: String, -} - -#[openapi(tag = "test")] -#[get("/search?")] -async fn search(query: &str) -> Result>, String> { - match query_aur(query).await { - Ok(v) => { - let mapped = v - .iter() - .map(|x| ApiPackage { - name: x.name.clone(), - version: x.version.clone(), - }) - .collect(); - return Ok(Json(mapped)); - } - Err(e) => { - return Err(format!("{}", e)); - } - } -} - -#[derive(FromQueryResult, Deserialize, JsonSchema, Serialize)] -#[serde(crate = "rocket::serde")] -struct ListPackageModel { - name: String, - count: i32, -} - -#[openapi(tag = "test")] -#[get("/packages/list")] -async fn package_list( - db: &State, -) -> Result>, String> { - let db = db as &DatabaseConnection; - - let all: Vec = Packages::find() - .join_rev(JoinType::InnerJoin, versions::Relation::Packages.def()) - .select_only() - .column_as(versions::Column::Id.count(), "count") - .column(packages::Column::Name) - .group_by(packages::Column::Name) - .into_model::() - .all(db) - .await - .unwrap(); - - Ok(Json(all)) -} - -#[derive(Deserialize, JsonSchema)] -#[serde(crate = "rocket::serde")] -struct AddBody { - name: String, -} - -#[openapi(tag = "test")] -#[post("/packages/add", data = "")] -async fn package_add( - db: &State, - input: Json, - tx: &State>, -) -> Result<(), String> { - let db = db as &DatabaseConnection; - let pkg_name = &input.name; - - let pkg = get_info_by_name(pkg_name) - .await - .map_err(|_| "couldn't download package metadata".to_string())?; - - let new_package = packages::ActiveModel { - name: Set(pkg_name.clone()), - ..Default::default() - }; - - let pkt_model = new_package.save(db).await.expect("TODO: panic message"); - - let new_version = versions::ActiveModel { - version: Set(pkg.version.clone()), - package_id: Set(pkt_model.id.clone().unwrap()), - ..Default::default() - }; - - let version_model = new_version.save(db).await.expect("TODO: panic message"); - - let _ = tx.send(Action::Build( - pkg.name, - pkg.version, - pkg.url_path.unwrap(), - version_model, - )); - - Ok(()) -} - -#[derive(Deserialize, JsonSchema)] -#[serde(crate = "rocket::serde")] -struct DelBody { - id: i32, -} - -#[openapi(tag = "test")] -#[post("/packages/delete", data = "")] -async fn package_del(db: &State, input: Json) -> Result<(), String> { - let db = db as &DatabaseConnection; - let pkg_id = input.id.clone(); - - remove_pkg(db, pkg_id).await.map_err(|e| e.to_string())?; - - Ok(()) -} - -#[openapi(tag = "test")] -#[post("/versions/delete/")] -async fn version_del(db: &State, id: i32) -> Result<(), String> { - let db = db as &DatabaseConnection; - - remove_version(db, id).await.map_err(|e| e.to_string())?; - - Ok(()) -} +use crate::api::add::okapi_add_operation_for_package_add_; +use crate::api::add::package_add; +use crate::api::list::okapi_add_operation_for_package_list_; +use crate::api::list::okapi_add_operation_for_search_; +use crate::api::list::{package_list, search}; +use crate::api::remove::okapi_add_operation_for_package_del_; +use crate::api::remove::okapi_add_operation_for_version_del_; +use crate::api::remove::{package_del, version_del}; +use rocket::Route; +use rocket_okapi::openapi_get_routes; pub fn build_api() -> Vec { openapi_get_routes![search, package_list, package_add, package_del, version_del] diff --git a/src/api/list.rs b/src/api/list.rs new file mode 100644 index 0000000..d3335be --- /dev/null +++ b/src/api/list.rs @@ -0,0 +1,66 @@ +use crate::aur::aur::query_aur; +use crate::db::migration::JoinType; +use crate::db::prelude::Packages; +use crate::db::{packages, versions}; +use rocket::serde::json::Json; +use rocket::serde::{Deserialize, Serialize}; +use rocket::{get, State}; +use rocket_okapi::okapi::schemars; +use rocket_okapi::{openapi, JsonSchema}; +use sea_orm::ColumnTrait; +use sea_orm::{DatabaseConnection, EntityTrait, FromQueryResult, QuerySelect, RelationTrait}; + +#[derive(Serialize, JsonSchema)] +#[serde(crate = "rocket::serde")] +pub struct ApiPackage { + name: String, + version: String, +} + +#[openapi(tag = "test")] +#[get("/search?")] +pub async fn search(query: &str) -> Result>, String> { + match query_aur(query).await { + Ok(v) => { + let mapped = v + .iter() + .map(|x| ApiPackage { + name: x.name.clone(), + version: x.version.clone(), + }) + .collect(); + return Ok(Json(mapped)); + } + Err(e) => { + return Err(format!("{}", e)); + } + } +} + +#[derive(FromQueryResult, Deserialize, JsonSchema, Serialize)] +#[serde(crate = "rocket::serde")] +pub struct ListPackageModel { + name: String, + count: i32, +} + +#[openapi(tag = "test")] +#[get("/packages/list")] +pub async fn package_list( + db: &State, +) -> Result>, String> { + let db = db as &DatabaseConnection; + + let all: Vec = Packages::find() + .join_rev(JoinType::InnerJoin, versions::Relation::Packages.def()) + .select_only() + .column_as(versions::Column::Id.count(), "count") + .column(packages::Column::Name) + .group_by(packages::Column::Name) + .into_model::() + .all(db) + .await + .unwrap(); + + Ok(Json(all)) +} diff --git a/src/api/mod.rs b/src/api/mod.rs index fceb141..e16d575 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -1 +1,4 @@ +mod add; pub mod backend; +mod list; +mod remove; diff --git a/src/api/remove.rs b/src/api/remove.rs new file mode 100644 index 0000000..255f8f3 --- /dev/null +++ b/src/api/remove.rs @@ -0,0 +1,37 @@ +use crate::repo::repo::{remove_pkg, remove_version}; +use rocket::serde::json::Json; +use rocket::serde::Deserialize; +use rocket::{post, State}; +use rocket_okapi::okapi::schemars; +use rocket_okapi::{openapi, JsonSchema}; +use sea_orm::DatabaseConnection; + +#[derive(Deserialize, JsonSchema)] +#[serde(crate = "rocket::serde")] +pub struct DelBody { + id: i32, +} + +#[openapi(tag = "test")] +#[post("/packages/delete", data = "")] +pub async fn package_del( + db: &State, + input: Json, +) -> Result<(), String> { + let db = db as &DatabaseConnection; + let pkg_id = input.id.clone(); + + remove_pkg(db, pkg_id).await.map_err(|e| e.to_string())?; + + Ok(()) +} + +#[openapi(tag = "test")] +#[post("/versions/delete/")] +pub async fn version_del(db: &State, id: i32) -> Result<(), String> { + let db = db as &DatabaseConnection; + + remove_version(db, id).await.map_err(|e| e.to_string())?; + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index 9d423fc..9f3c244 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,6 @@ mod pkgbuild; mod repo; use crate::api::backend; -use crate::aur::aur::query_aur; use crate::builder::types::Action; use crate::db::migration::Migrator; use rocket::config::Config; diff --git a/src/pkgbuild/build.rs b/src/pkgbuild/build.rs index bcf228f..54858e4 100644 --- a/src/pkgbuild/build.rs +++ b/src/pkgbuild/build.rs @@ -1,6 +1,7 @@ use anyhow::anyhow; use std::fs; -use std::process::{Command, Stdio}; +use std::io::{BufRead, BufReader}; +use std::process::Command; use std::time::SystemTime; pub fn build_pkgbuild( @@ -14,7 +15,7 @@ pub fn build_pkgbuild( let script_file = std::env::temp_dir().join("makepkg_custom.sh"); fs::write(&script_file, makepkg).expect("Unable to write script to file"); - let output = Command::new("bash") + let mut output = Command::new("bash") .args(&[ script_file.as_os_str().to_str().unwrap(), "-f", @@ -23,20 +24,29 @@ pub fn build_pkgbuild( "-c", ]) .current_dir(folder_path.clone()) - .stdout(Stdio::inherit()) .spawn() .unwrap(); - let output = output.wait_with_output(); - match output { - Ok(output) => { - if output.status.success() { - let stdout = String::from_utf8_lossy(&output.stdout); - println!("makepkg output: {}", stdout); - } else { - let stderr = String::from_utf8_lossy(&output.stderr); - eprintln!("makepkg error: {}", stderr); + if let Some(stdout) = output.stdout.take() { + let reader = BufReader::new(stdout); + // Iterate through each line of output + for line in reader.lines() { + if let Ok(line_content) = line { + // Print the line to the terminal + println!("{}", line_content); + + // todo store line to database for being fetchable from api + } + } + } + + // Ensure the command completes + let result = output.wait(); + + match result { + Ok(result) => { + if !result.success() { return Err(anyhow!("failed to build package")); } } @@ -46,6 +56,14 @@ pub fn build_pkgbuild( } } + locate_built_package(pkg_name.to_string(), pkg_vers.to_string(), folder_path) +} + +fn locate_built_package( + pkg_name: String, + pkg_vers: String, + folder_path: String, +) -> anyhow::Result { // check if expected built dir exists let built_name = build_expected_repo_packagename(pkg_name.to_string(), pkg_vers.to_string()); if fs::metadata(format!("{folder_path}/{built_name}")).is_ok() { @@ -65,7 +83,8 @@ pub fn build_pkgbuild( if let Some(file_name) = path.file_name() { let file_name = file_name.to_str().unwrap(); - if file_name.ends_with("-x86_64.pkg.tar.zst") && file_name.starts_with(pkg_name) + if file_name.ends_with("-x86_64.pkg.tar.zst") + && file_name.starts_with(pkg_name.as_str()) { if let Ok(metadata) = path.metadata() { if let Ok(modified_time) = metadata.modified() { @@ -87,7 +106,7 @@ pub fn build_pkgbuild( } } - Err(anyhow!("No package built")) + Err(anyhow!("Built package not found")) } /// don't trust this pkg name from existing diff --git a/src/repo/repo.rs b/src/repo/repo.rs index 7183676..3987312 100644 --- a/src/repo/repo.rs +++ b/src/repo/repo.rs @@ -1,7 +1,7 @@ use crate::aur::aur::download_pkgbuild; use crate::db::prelude::Packages; use crate::db::prelude::Versions; -use crate::db::{versions}; +use crate::db::versions; use crate::pkgbuild::build::build_pkgbuild; use anyhow::anyhow; use sea_orm::{ColumnTrait, DatabaseConnection, EntityTrait, ModelTrait, QueryFilter}; @@ -69,7 +69,10 @@ fn repo_remove(pkg_file_name: String) -> anyhow::Result<()> { } pub async fn remove_pkg(db: &DatabaseConnection, pkg_id: i32) -> anyhow::Result<()> { - let pkg = Packages::find_by_id(pkg_id).one(db).await?.ok_or(anyhow!("id not found"))?; + let pkg = Packages::find_by_id(pkg_id) + .one(db) + .await? + .ok_or(anyhow!("id not found"))?; fs::remove_dir_all(format!("./builds/{}", pkg.name))?;