staxman-old/src/route/stack/edit.rs

78 lines
2.1 KiB
Rust

use axum::{
extract::{Multipart, Path, State},
http::StatusCode,
response::Redirect,
};
use crate::{
http::error::{AppError, Result},
stack::{self, arion, compose, FileList, COMPOSE_FILE},
AppState,
};
pub(super) async fn edit_stack(
Path(stack_name): Path<String>,
State(state): State<AppState>,
mut multipart: Multipart,
) -> Result<Redirect> {
let mut commit_message = format!("Update {}", stack_name);
let mut files = FileList::new();
while let Ok(Some(field)) = multipart.next_field().await {
let name = field.name().unwrap_or_default().to_string();
let data = field.text().await.map_err(|e| AppError::Client {
status: StatusCode::BAD_REQUEST,
code: "invalid-data",
message: e.to_string(),
})?;
if name.starts_with("files/") {
// Clean up source (like line endings) in each file
let source = data.replace("\r\n", "\n");
files.insert(name.strip_prefix("files/").unwrap().to_string(), source);
} else if name == "commit_message" && !data.is_empty() {
commit_message = data;
}
}
if files.is_empty() {
return Err(AppError::Client {
status: StatusCode::BAD_REQUEST,
code: "invalid-files",
message: "no files provided".to_string(),
});
}
edit_stack_int(state, &stack_name, &files, &commit_message).await?;
Ok(Redirect::to("./"))
}
pub(super) async fn edit_stack_int(
state: AppState,
stack_name: &str,
files: &FileList,
commit_message: &str,
) -> Result<()> {
// Get compose
if let Some(compose_file) = files.get(COMPOSE_FILE) {
// Make sure file is ok
compose::check(&state.arion_bin, compose_file).await?;
}
// Write compose file
stack::write(&state.stack_dir, stack_name, files).await?;
// Git commit
compose::commit(state.repository, stack_name, files, commit_message)?;
// Update stack
arion::command(
&state.stack_dir,
stack_name,
&state.arion_bin,
arion::StackCommand::Start,
)
.await?;
Ok(())
}