use std::io;
use std::path::Path;
use crate::cli_outbound::{Binary, Cli};
use crate::world::toolgate::ToolchainState;
mod dispatch;
pub use dispatch::{Outcome, log_step_failure, run_logged, run_logged_cwdless};
pub(crate) use dispatch::collect;
const GATE_STEP: &str = "gate";
fn gate_check(
gate: &ToolchainState,
binary: Binary,
state_root: &Path,
ts: &str,
cwd: &Path,
) -> io::Result<()> {
match gate.require(binary) {
Ok(()) => Ok(()),
Err(refusal) => {
log_step_failure(state_root, ts, cwd, GATE_STEP, &refusal.to_string())?;
Err(io::Error::other(refusal))
}
}
}
const MESSAGE: &str = "message";
const STOP: &str = "stop";
const SCAN: &str = "scan";
const STOP_CHILDREN: &str = "--stop-children";
const CLOSE: &str = "close";
const CLAIM: &str = "claim";
const UNCLAIM: &str = "unclaim";
const CREATE: &str = "create";
const UPDATE: &str = "update";
const AS: &str = "--as";
const TITLE: &str = "--title";
const BODY: &str = "--body";
const NOTE: &str = "-m";
const YOG_NAME: &str = "YOG_NAME";
fn ws_name(ws: &Path) -> String {
ws.file_name()
.map(|s| s.to_string_lossy().into_owned())
.unwrap_or_default()
}
pub fn message(
gate: &ToolchainState,
lernie: &Cli,
state_root: &Path,
ts: &str,
ws: &Path,
agent: &str,
content: &str,
) -> io::Result<Outcome> {
gate_check(gate, Binary::Lernie, state_root, ts, ws)?;
let ws_s = ws.to_string_lossy();
let named = lernie.and_env(vec![(YOG_NAME.to_owned(), ws_name(ws))]);
run_logged(
&named,
state_root,
ts,
ws,
&[MESSAGE, &ws_s, agent, content],
)
}
pub fn stop(
gate: &ToolchainState,
lernie: &Cli,
state_root: &Path,
ts: &str,
ws: &Path,
agent: &str,
stop_children: bool,
) -> io::Result<Outcome> {
gate_check(gate, Binary::Lernie, state_root, ts, ws)?;
let ws_s = ws.to_string_lossy();
let mut args = vec![STOP, ws_s.as_ref(), agent];
if stop_children {
args.push(STOP_CHILDREN);
}
run_logged(lernie, state_root, ts, ws, &args)
}
pub fn scan(
gate: &ToolchainState,
lernie: &Cli,
state_root: &Path,
ts: &str,
ws: &Path,
) -> io::Result<Outcome> {
gate_check(gate, Binary::Lernie, state_root, ts, ws)?;
let ws_s = ws.to_string_lossy();
run_logged(lernie, state_root, ts, ws, &[SCAN, &ws_s])
}
pub fn close(
gate: &ToolchainState,
bl: &Cli,
state_root: &Path,
ts: &str,
project: &Path,
id: &str,
name: &str,
) -> io::Result<Outcome> {
gate_check(gate, Binary::Bl, state_root, ts, project)?;
run_logged(bl, state_root, ts, project, &[CLOSE, id, AS, name])
}
pub fn assign(
gate: &ToolchainState,
bl: &Cli,
state_root: &Path,
ts: &str,
project: &Path,
id: &str,
name: &str,
) -> io::Result<Outcome> {
gate_check(gate, Binary::Bl, state_root, ts, project)?;
run_logged(bl, state_root, ts, project, &[CLAIM, id, AS, name])
}
pub fn unclaim(
gate: &ToolchainState,
bl: &Cli,
state_root: &Path,
ts: &str,
project: &Path,
id: &str,
name: &str,
) -> io::Result<Outcome> {
gate_check(gate, Binary::Bl, state_root, ts, project)?;
run_logged(bl, state_root, ts, project, &[UNCLAIM, id, AS, name])
}
pub fn reassign(
gate: &ToolchainState,
bl: &Cli,
stamp: (&Path, &str),
project: &Path,
id: &str,
from: &str,
to: &str,
) -> io::Result<Outcome> {
let (state_root, ts) = stamp;
unclaim(gate, bl, state_root, ts, project, id, from)?;
assign(gate, bl, state_root, ts, project, id, to)
}
pub fn create(
gate: &ToolchainState,
bl: &Cli,
stamp: (&Path, &str),
project: &Path,
title: &str,
name: &str,
body: Option<&str>,
) -> io::Result<Outcome> {
let (state_root, ts) = stamp;
gate_check(gate, Binary::Bl, state_root, ts, project)?;
let mut args = vec![CREATE, title, AS, name];
if let Some(b) = body {
args.push(BODY);
args.push(b);
}
run_logged(bl, state_root, ts, project, &args)
}
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct Update {
pub title: Option<String>,
pub body: Option<String>,
pub note: Option<String>,
}
pub fn update(
gate: &ToolchainState,
bl: &Cli,
stamp: (&Path, &str),
project: &Path,
id: &str,
name: &str,
fields: &Update,
) -> io::Result<Outcome> {
let (state_root, ts) = stamp;
gate_check(gate, Binary::Bl, state_root, ts, project)?;
let mut args = vec![UPDATE, id, AS, name];
if let Some(t) = &fields.title {
args.push(TITLE);
args.push(t);
}
if let Some(b) = &fields.body {
args.push(BODY);
args.push(b);
}
if let Some(n) = &fields.note {
args.push(NOTE);
args.push(n);
}
run_logged(bl, state_root, ts, project, &args)
}
#[cfg(test)]
mod tests;