use super::Step;
use crate::actions::verbs::{self, Outcome, log_step_done, log_step_failure};
use crate::cli_outbound::Cli;
use crate::opslog::Origin;
use crate::ui_state::UiState;
use std::io;
use std::path::Path;
pub const DELETE_STEP: &str = "delete-workspace";
#[derive(Debug, thiserror::Error)]
pub enum DeleteError {
#[error("refused — live conversations: {}", .0.join(", "))]
Live(Vec<String>),
#[error("type the workspace's name to confirm")]
NotArmed,
#[error("not a yog-named workspace")]
Unnamed,
#[error("`bl unclaim {id}` failed (exit {}): {}", .outcome.exit, .outcome.stderr)]
ReleaseFailed { id: String, outcome: Outcome },
#[error(transparent)]
Io(#[from] io::Error),
}
pub fn execute(
steps: &[Step],
bl: &Cli,
ui: &mut UiState,
state_root: &Path,
ts: &str,
) -> Result<(), DeleteError> {
for step in steps {
match step {
Step::Release { project, id, name } => {
let outcome = verbs::unclaim(bl, state_root, ts, project, id, name)?;
if !outcome.ok() {
return Err(DeleteError::ReleaseFailed {
id: id.clone(),
outcome,
});
}
}
Step::Prune { key } => ui.prune_workspace(key),
Step::Remove { workspace, wall } => remove(workspace, wall, state_root, ts)?,
}
}
Ok(())
}
fn remove(workspace: &Path, wall: &Path, state_root: &Path, ts: &str) -> Result<(), DeleteError> {
let cwd = workspace.parent().unwrap_or(workspace);
match remove_both(workspace, wall) {
Ok(()) => {
log_step_done(state_root, ts, cwd, DELETE_STEP, Origin::World)?;
Ok(())
}
Err(e) => {
log_step_failure(
state_root,
ts,
cwd,
DELETE_STEP,
&e.to_string(),
Origin::World,
)?;
Err(DeleteError::Io(e))
}
}
}
fn remove_both(workspace: &Path, wall: &Path) -> io::Result<()> {
match std::fs::remove_dir_all(wall) {
Err(e) if e.kind() != io::ErrorKind::NotFound => return Err(e),
_ => {}
}
std::fs::remove_dir_all(workspace)
}
#[cfg(test)]
mod tests;