use super::exec::{CONTROL, Deps, MKDIR, NEW, REPO_MARK, StartError, verb_ok};
use super::instructions::manifest;
use crate::actions::verbs::{self, log_step_failure};
use crate::cli_outbound::Cli;
use crate::config_edit::branch::edit::{
DraftFile, EditOrigin, EditPlan, drive, next_nonce, stage_files,
};
use crate::control;
use crate::opslog::{OpEntry, Origin};
use crate::world::Layout;
use crate::xdg::stage_root_under;
use std::io;
use std::path::Path;
pub fn execute_ensure_workspace(
deps: &Deps,
ts: &str,
workspace: &Path,
config: &str,
layout: &Layout,
origin: Origin,
) -> Result<bool, StartError> {
let (litany, state_root) = (&deps.litany, deps.state_root.as_path());
let created = create_workspace(litany, state_root, ts, workspace, origin)?;
let shim = crate::world::tools::control_path(&layout.tools);
let drafts: Vec<DraftFile> = [
control::author::workflow_drift(workspace, config, &shim),
manifest::drift(workspace, config),
]
.into_iter()
.flatten()
.collect();
let authored = converge(deps, workspace, config, &drafts, state_root, ts, origin)?;
if let Some(entry) = authored.filter(|e| e.exit != 0) {
log_step_failure(state_root, ts, workspace, CONTROL, &entry.stderr, origin)?;
return Err(StartError::Control(entry.stderr));
}
Ok(created)
}
fn converge(
deps: &Deps,
workspace: &Path,
config: &str,
drafts: &[DraftFile],
state_root: &Path,
ts: &str,
origin: Origin,
) -> io::Result<Option<OpEntry>> {
if drafts.is_empty() {
return Ok(None);
}
let staging = stage_files(&stage_root_under(state_root), &next_nonce(), drafts)?;
let plan = EditPlan::compose(
&deps.yog_binary,
workspace,
config,
&EditOrigin::Advance,
&staging,
);
Ok(Some(drive(
&deps.litany,
workspace,
&plan,
ts,
state_root,
origin,
)))
}
fn create_workspace(
litany: &Cli,
state_root: &Path,
ts: &str,
workspace: &Path,
origin: Origin,
) -> Result<bool, StartError> {
if workspace.join(REPO_MARK).exists() {
return Ok(false);
}
let parent = workspace.parent().unwrap_or(workspace);
if let Err(e) = std::fs::create_dir_all(parent) {
log_step_failure(state_root, ts, parent, MKDIR, &e.to_string(), origin)?;
return Err(StartError::Io(e));
}
let ws_s = workspace.to_string_lossy();
verb_ok(
verbs::run_logged(litany, state_root, ts, parent, &[NEW, &ws_s], origin)?,
NEW,
)?;
Ok(true)
}