use super::{Error, Origin, Pass, author};
use crate::template::{GitRunner, RealGit, scaffold};
use std::fs;
use std::io;
use std::path::Path;
use tempfile::TempDir;
fn workspace() -> (TempDir, std::path::PathBuf) {
let holder = TempDir::new().unwrap();
let ws = holder.path().join("ws");
let roots = crate::test_support::bare_roots(holder.path());
scaffold(&ws, &roots, &RealGit::new()).unwrap();
(holder, ws)
}
fn noop(_dir: &Path) -> io::Result<()> {
Ok(())
}
struct StubGit<F: Fn(&Path)> {
on_worktree_add: F,
fail_commit: bool,
}
impl<F: Fn(&Path)> GitRunner for StubGit<F> {
fn run(&self, _dest: &Path, args: &[&str]) -> io::Result<()> {
if args.first() == Some(&"worktree") && args.get(1) == Some(&"add") {
(self.on_worktree_add)(Path::new(args[args.len() - 1]));
} else if self.fail_commit && args.first() == Some(&"commit") {
return Err(io::Error::other("no identity"));
}
Ok(())
}
fn run_capture(&self, dest: &Path, args: &[&str]) -> io::Result<String> {
self.run(dest, args).map(|()| match args.first() {
Some(&"status") => "A version".to_string(),
_ => String::new(),
})
}
}
fn run_orphan<F: Fn(&Path)>(ws: &Path, no_pool: &Path, git: &StubGit<F>) -> Result<Pass, Error> {
author(ws, no_pool, "scratch", Origin::Orphan, noop, git)
}
#[test]
fn checkout_dir_collision_is_an_io_error() {
let (holder, ws) = workspace();
let git = StubGit {
on_worktree_add: |author: &Path| {
let _ = fs::write(author, b"squat");
},
fail_commit: false,
};
let err = run_orphan(&ws, &holder.path().join("no-pool"), &git).unwrap_err();
assert!(matches!(err, Error::Io(_)), "got {err:?}");
}
#[test]
fn template_extract_failure_is_an_io_error() {
let (holder, ws) = workspace();
let git = StubGit {
on_worktree_add: |author: &Path| {
fs::create_dir_all(author.join("version")).unwrap();
},
fail_commit: false,
};
let err = run_orphan(&ws, &holder.path().join("no-pool"), &git).unwrap_err();
assert!(matches!(err, Error::Io(_)), "got {err:?}");
}
#[test]
fn commit_step_failure_is_a_git_error() {
let (holder, ws) = workspace();
let git = StubGit {
on_worktree_add: |_author: &Path| {},
fail_commit: true,
};
let err = run_orphan(&ws, &holder.path().join("no-pool"), &git).unwrap_err();
assert!(matches!(err, Error::Git(_)), "got {err:?}");
}
#[test]
fn stub_run_capture_delegates_to_run() {
let git = StubGit {
on_worktree_add: |_author: &Path| {},
fail_commit: true,
};
let holder = TempDir::new().unwrap();
assert_eq!(
git.run_capture(holder.path(), &["status"]).unwrap(),
"A version"
);
assert_eq!(git.run_capture(holder.path(), &["add"]).unwrap(), "");
assert!(git.run_capture(holder.path(), &["commit"]).is_err());
}