use crate::actions::verbs::{self, Outcome, log_step_failure};
use crate::cli_outbound::Cli;
use crate::opslog::Origin;
use crate::world::seed;
use litany::mint::MintError;
use std::io;
use std::path::{Path, PathBuf};
const CREATE: &str = "create";
const AS: &str = "--as";
const BODY: &str = "--body";
pub(super) const NEW: &str = "new";
pub(super) const REPO_MARK: &str = "repo.git";
const MINT: &str = "mint";
pub(super) const MKDIR: &str = "mkdir";
pub(super) const CONTROL: &str = "control";
pub use crate::opslog::DETACHED_EXIT;
mod claim;
pub use claim::{ClaimResolved, cross_check_claim, execute_claim};
pub struct Deps {
pub bl: Cli,
pub litany: Cli,
pub state_root: PathBuf,
pub yog_binary: PathBuf,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Prepared {
pub workspace: String,
pub binding: Option<PathBuf>,
pub lineage: Option<String>,
pub goal: String,
pub origin: Origin,
}
#[derive(Debug, thiserror::Error)]
pub enum StartError {
#[error("`{verb}` failed (exit {}): {}", .outcome.exit, .outcome.stderr)]
VerbFailed {
verb: &'static str,
outcome: Outcome,
},
#[error("claim worktree drift: bl printed {stdout:?}, expected {canonical} or {suffixed}")]
Drift {
stdout: String,
canonical: String,
suffixed: String,
},
#[error(transparent)]
Mint(#[from] MintError),
#[error(transparent)]
Seed(#[from] seed::SeedError),
#[error("the capability control could not be authored: {0}")]
Control(String),
#[error(transparent)]
Io(#[from] io::Error),
}
pub fn on_mint(
result: Result<String, MintError>,
state_root: &Path,
ts: &str,
cwd: &Path,
origin: Origin,
) -> Result<String, StartError> {
match result {
Ok(name) => Ok(name),
Err(e) => {
log_step_failure(state_root, ts, cwd, MINT, &e.to_string(), origin)?;
Err(StartError::Mint(e))
}
}
}
pub fn execute_create(
bl: &Cli,
state_root: &Path,
ts: &str,
project: &Path,
title: &str,
body: &str,
name: &str,
) -> Result<String, StartError> {
let mut args = vec![CREATE, title, AS, name];
if !body.is_empty() {
args.extend([BODY, body]);
}
let out = verbs::run_logged(bl, state_root, ts, project, &args, Origin::Balls)?;
verb_ok(out, CREATE).map(|o| o.stdout.trim().to_owned())
}
pub(super) fn verb_ok(out: Outcome, verb: &'static str) -> Result<Outcome, StartError> {
if out.ok() {
Ok(out)
} else {
Err(StartError::VerbFailed { verb, outcome: out })
}
}