mod candidates;
mod plan;
mod read;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use tempfile::{TempDir, tempdir};
use crate::app::Snapshot;
use crate::binding::{Workspace, WorkspaceKind};
use crate::git_tree::tests::git::run_git;
use crate::projects::balls::{Ball, Blocker};
pub(crate) const MAIN: &str = "main";
pub(crate) struct Project {
_dir: TempDir,
pub(crate) path: PathBuf,
}
impl Project {
pub(crate) fn new() -> Self {
let dir = tempdir().unwrap();
let path = dir.path().to_path_buf();
run_git(&path, &["init", "-q", "-b", MAIN]);
run_git(&path, &["config", "user.email", "t@t.local"]);
run_git(&path, &["config", "user.name", "Tester"]);
run_git(&path, &["config", "commit.gpgsign", "false"]);
let project = Self { _dir: dir, path };
project.commit("README.md", "the project\n");
project
}
pub(crate) fn commit(&self, file: &str, body: &str) {
let full = self.path.join(file);
if let Some(parent) = full.parent() {
std::fs::create_dir_all(parent).unwrap();
}
std::fs::write(&full, body).unwrap();
run_git(&self.path, &["add", file]);
run_git(&self.path, &["commit", "-q", "-m", &format!("add {file}")]);
}
pub(crate) fn switch(&self, name: &str) {
run_git(&self.path, &["checkout", "-q", "-b", name]);
}
pub(crate) fn checkout(&self, name: &str) {
run_git(&self.path, &["checkout", "-q", name]);
}
}
pub(crate) fn ball(id: &str, claimant: Option<&str>, parent: Option<&str>) -> Ball {
Ball {
id: id.to_owned(),
title: format!("ball {id}"),
body: String::new(),
claimant: claimant.map(str::to_owned),
blockers: Vec::new(),
parent: parent.map(str::to_owned),
priority: 0,
tags: Vec::new(),
created: None,
updated: None,
root_commit: None,
}
}
pub(super) fn close_gate(mut parent: Ball, child: &str) -> Ball {
parent.blockers.push(Blocker {
id: child.to_owned(),
on: "close".to_owned(),
});
parent
}
pub(crate) fn world(root: &Path) -> crate::xdg::Env {
crate::xdg::Env::from_pairs([
("HOME", root.join("home").to_string_lossy().into_owned()),
(
"XDG_STATE_HOME",
root.join("state").to_string_lossy().into_owned(),
),
])
}
pub(crate) fn xdg(root: &Path) -> balls::layout::Xdg {
balls::layout::Xdg::with(
&root.join("home"),
None,
Some(&root.join("state").to_string_lossy()),
)
}
pub(super) fn read0(snap: &Snapshot, ws: &Path) -> Vec<crate::workdiff::Attempt> {
let dir = tempfile::tempdir().unwrap();
crate::workdiff::read(snap, ws, &[], &world(dir.path()))
}
pub(crate) fn snap(ws: &Path, name: &str, project: &Path, balls: Vec<Ball>) -> Snapshot {
let mut snap = Snapshot::empty(0);
snap.workspaces = vec![Workspace {
path: ws.to_path_buf(),
kind: WorkspaceKind::Named {
name: name.to_owned(),
},
}];
snap.projects = vec![project.to_path_buf()];
snap.balls_by_project = HashMap::from([(project.to_path_buf(), balls)]);
snap
}