use crate::db::migration::{JoinType, Order}; use crate::db::prelude::Builds; use crate::db::{builds, packages, versions}; use rocket::response::status::NotFound; use rocket::serde::json::Json; use rocket::{delete, get, post, State}; use crate::api::types::input::ListBuildsModel; use rocket_okapi::openapi; use sea_orm::ColumnTrait; use sea_orm::QueryFilter; use sea_orm::{ DatabaseConnection, EntityTrait, ModelTrait, QueryOrder, QuerySelect, RelationTrait, }; use tokio::sync::broadcast::Sender; use crate::builder::types::Action; #[openapi(tag = "build")] #[get("/build//output?")] pub async fn build_output( db: &State, buildid: i32, startline: Option, ) -> Result> { let db = db as &DatabaseConnection; let build = Builds::find_by_id(buildid) .one(db) .await .map_err(|e| NotFound(e.to_string()))? .ok_or(NotFound("couldn't find id".to_string()))?; return match build.ouput { None => Err(NotFound("No Output".to_string())), Some(v) => match startline { None => Ok(v), Some(startline) => { let output: Vec = v.split('\n').map(|x| x.to_string()).collect(); let len = output.len(); let len_missing = len as i32 - startline; let output = output .iter() .rev() .take(if len_missing > 0 { len_missing as usize } else { 0 }) .rev() .cloned() .collect::>(); let output = output.join("\n"); Ok(output) } }, }; } #[openapi(tag = "build")] #[get("/builds?&")] pub async fn list_builds( db: &State, pkgid: Option, limit: Option, ) -> Result>, NotFound> { let db = db as &DatabaseConnection; let basequery = Builds::find() .join_rev(JoinType::InnerJoin, packages::Relation::Builds.def()) .join_rev(JoinType::InnerJoin, versions::Relation::Builds.def()) .select_only() .column_as(builds::Column::Id, "id") .column(builds::Column::Status) .column_as(packages::Column::Name, "pkg_name") .column_as(packages::Column::Id, "pkg_id") .column(versions::Column::Version) .column(builds::Column::EndTime) .column(builds::Column::StartTime) .order_by(builds::Column::StartTime, Order::Desc) .limit(limit); let build = match pkgid { None => basequery.into_model::().all(db), Some(pkgid) => basequery .filter(builds::Column::PkgId.eq(pkgid)) .into_model::() .all(db), } .await .map_err(|e| NotFound(e.to_string()))?; Ok(Json(build)) } #[openapi(tag = "build")] #[get("/build/")] pub async fn get_build( db: &State, buildid: i32, ) -> Result, NotFound> { let db = db as &DatabaseConnection; let result = Builds::find() .join_rev(JoinType::InnerJoin, packages::Relation::Builds.def()) .join_rev(JoinType::InnerJoin, versions::Relation::Builds.def()) .filter(builds::Column::Id.eq(buildid)) .select_only() .column_as(builds::Column::Id, "id") .column(builds::Column::Status) .column_as(packages::Column::Name, "pkg_name") .column_as(packages::Column::Id, "pkg_id") .column(versions::Column::Version) .column(builds::Column::EndTime) .column(builds::Column::StartTime) .into_model::() .one(db) .await .map_err(|e| NotFound(e.to_string()))? .ok_or(NotFound("no item with id found".to_string()))?; Ok(Json(result)) } #[openapi(tag = "build")] #[delete("/build/")] pub async fn delete_build( db: &State, buildid: i32, ) -> Result<(), NotFound> { let db = db as &DatabaseConnection; let build = Builds::find_by_id(buildid) .one(db) .await .map_err(|e| NotFound(e.to_string()))? .ok_or(NotFound("Id not found".to_string()))?; build .delete(db) .await .map_err(|e| NotFound(e.to_string()))?; Ok(()) } #[openapi(tag = "build")] #[post("/build//cancel")] pub async fn cancle_build( db: &State, tx: &State>, buildid: i32, ) -> Result<(), NotFound> { let db = db as &DatabaseConnection; let _ = tx.send(Action::Cancel(buildid)).map_err(|e| NotFound(e.to_string()))?; Ok(()) }