use crate::actions::verbs::Outcome;
use crate::config_edit::RealFileIo;
use crate::config_edit::branch::edit::{
DraftFile, EditOrigin, EditPlan, drive, next_nonce, stage_files,
};
use crate::config_edit::brazen::{Applied, BrazenEditor, RealBzRunner};
use crate::config_edit::litany_global::{Editor, Saved};
use crate::opslog::Origin;
use crate::xdg::Env;
use std::path::{Path, PathBuf};
use crate::boundary::dispatch::Deps;
use crate::boundary::reply::Reply;
pub(super) const CONFLICT: &str =
"the file changed since it was read — re-read it and restate the apply";
pub(super) fn brazen(deps: &Deps, workspace: &Path, text: &str) -> Result<Reply, String> {
let paths = super::brazen_paths(deps, workspace);
let io = RealFileIo;
let mut editor = BrazenEditor::load(paths, &io).map_err(|e| e.to_string())?;
editor.set_draft(text.to_owned());
applied(editor.apply(
&RealBzRunner::resolve(&super::wall_env(deps, workspace)),
&io,
))?;
Ok(Reply::Applied)
}
pub(super) fn applied(applied: Applied) -> Result<(), String> {
match applied {
Applied::Ok => Ok(()),
Applied::Rejected { stderr } => Err(format!("bz refused the draft: {stderr}")),
Applied::Conflict => Err(CONFLICT.to_owned()),
Applied::Io { error } => Err(error),
}
}
pub(super) fn write_file(dest: PathBuf, text: &str) -> Result<Reply, String> {
let mut editor = editor_at(&dest)?;
editor.set_draft(text.to_owned());
saved(editor.apply(&RealFileIo))?;
Ok(Reply::Applied)
}
pub(super) fn editor_at(dest: &Path) -> Result<Editor, String> {
Editor::load(dest.to_path_buf(), &RealFileIo).map_err(|e| e.to_string())
}
pub(super) fn saved(saved: Saved) -> Result<(), String> {
match saved {
Saved::Ok => Ok(()),
Saved::Conflict => Err(CONFLICT.to_owned()),
Saved::Io { error } => Err(error),
}
}
pub(super) fn cadence_path(world: &Env) -> PathBuf {
let root = world.yog_state_root();
root.join(crate::app::cadence::CADENCE_YAML)
}
pub(super) fn commit(
deps: &Deps,
ts: &str,
workspace: &Path,
lineage: &str,
origin: &EditOrigin,
path: &str,
text: &str,
) -> Result<Reply, String> {
let files = [DraftFile {
rel_path: path.to_owned(),
bytes: text.as_bytes().to_vec(),
}];
let dir = stage_files(&deps.world.yog_stage_root(), &next_nonce(), &files)
.map_err(|e| e.to_string())?;
let plan = EditPlan::compose(&deps.yog_binary, workspace, lineage, origin, &dir);
let entry = drive(
&deps.litany,
workspace,
&plan,
ts,
&deps.state_root,
Origin::World,
);
Ok(Reply::Outcome(Outcome {
exit: entry.exit,
stdout: entry.stdout,
stderr: entry.stderr,
}))
}