mod exec;
mod goal;
mod plan;
mod prompt;
mod run;
use crate::names::SplitMix64;
use crate::opslog::{self, OpEntry};
use crate::projects::join::JoinState;
use crate::start::{BallSpec, Payload, StartInputs, Target};
use std::fs;
use std::os::unix::fs::PermissionsExt;
use std::path::{Path, PathBuf};
use tempfile::{TempDir, tempdir};
pub(super) fn write_exec(dir: &Path, name: &str, body: &str) -> PathBuf {
let path = dir.join(name);
fs::write(&path, body).unwrap();
let mut perms = fs::metadata(&path).unwrap().permissions();
perms.set_mode(0o755);
fs::set_permissions(&path, perms).unwrap();
path
}
pub(super) fn fake_bl(dir: &Path, id: &str, worktree: &Path) -> PathBuf {
let body = format!(
"#!/bin/sh\ncase \"$1\" in\ncreate) printf '%s\\n' '{id}';;\nclaim) printf '%s\\n' '{wt}';;\nesac\nexit 0\n",
wt = worktree.display(),
);
write_exec(dir, "bl", &body)
}
pub(super) fn fake_lernie(dir: &Path) -> PathBuf {
write_exec(
dir,
"lernie",
"#!/bin/sh\ncase \"$1\" in\nprime) [ -n \"$LERNIE_HOME\" ] && mkdir -p \"$LERNIE_HOME\" && : > \"$LERNIE_HOME/models.yaml\";;\nnew) mkdir -p \"$2/repo.git\";;\nesac\nexit 0\n",
)
}
pub(super) fn fake_fail(dir: &Path, name: &str, msg: &str) -> PathBuf {
write_exec(
dir,
name,
&format!("#!/bin/sh\nprintf '%s\\n' '{msg}' 1>&2\nexit 3\n"),
)
}
pub(super) struct World {
pub(super) bin: TempDir,
pub(super) state: TempDir,
pub(super) balls: TempDir,
pub(super) yog: TempDir,
pub(super) home: TempDir,
pub(super) project: TempDir,
}
impl World {
pub(super) fn new() -> Self {
Self {
bin: tempdir().unwrap(),
state: tempdir().unwrap(),
balls: tempdir().unwrap(),
yog: tempdir().unwrap(),
home: tempdir().unwrap(),
project: tempdir().unwrap(),
}
}
pub(super) fn ops(&self) -> Vec<OpEntry> {
opslog::tail(self.state.path(), 16)
}
pub(super) fn verbs(&self) -> Vec<String> {
self.ops()
.into_iter()
.filter_map(|e| e.argv.get(1).cloned())
.collect()
}
pub(super) fn lernie(&self) -> crate::cli_outbound::Cli {
let home = crate::world::layout_under(self.yog.path()).lernie;
crate::cli_outbound::Cli::new(fake_lernie(self.bin.path())).with_env(vec![(
"LERNIE_HOME".to_owned(),
home.to_string_lossy().into_owned(),
)])
}
pub(super) fn inputs(&self, target: Target, payload: Payload) -> StartInputs {
StartInputs {
target,
payload,
home: self.home.path().to_path_buf(),
yog_data_root: self.yog.path().to_path_buf(),
balls_state_root: self.balls.path().to_path_buf(),
claimants: Vec::new(),
}
}
}
pub(super) fn rng() -> SplitMix64 {
SplitMix64::from_seed(0x5eed)
}
pub(super) fn ball(project: &Path, id: &str, join: JoinState) -> Payload {
Payload::Ball {
project: project.to_path_buf(),
ball: BallSpec::Existing {
id: id.to_owned(),
title: "T".to_owned(),
body: "B".to_owned(),
join,
},
}
}