//! Tiny throwaway temporary-directory helper for tests.
//!
//! Avoids pulling in an external crate. Creates a uniquely-named directory
//! under the system temp dir and removes it (recursively) on drop.
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicU64, Ordering};
static COUNTER: AtomicU64 = AtomicU64::new(0);
/// A temporary directory that is deleted when dropped.
pub struct TempDir {
path: PathBuf,
}
impl TempDir {
/// Create a new uniquely-named temporary directory.
pub fn new(prefix: &str) -> Self {
let base = std::env::temp_dir();
let pid = std::process::id();
let n = COUNTER.fetch_add(1, Ordering::Relaxed);
let nanos = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map_or(0, |d| d.as_nanos());
let path = base.join(format!("{prefix}-{pid}-{nanos}-{n}"));
std::fs::create_dir_all(&path).expect("failed to create temp dir");
Self { path }
}
/// The path to the temporary directory.
pub fn path(&self) -> &Path {
&self.path
}
}
impl Drop for TempDir {
fn drop(&mut self) {
let _ = std::fs::remove_dir_all(&self.path);
}
}
/// Run a git command in `dir`, panicking on failure. Test-only helper.
#[cfg(test)]
fn git(dir: &Path, args: &[&str]) {
use std::process::Command;
let status = Command::new("git")
.args(args)
.current_dir(dir)
.env("GIT_AUTHOR_NAME", "Tester")
.env("GIT_AUTHOR_EMAIL", "tester@example.com")
.env("GIT_COMMITTER_NAME", "Tester")
.env("GIT_COMMITTER_EMAIL", "tester@example.com")
.status()
.expect("failed to spawn git");
assert!(status.success(), "git {args:?} failed");
}
/// Build a small repository with two tags (`v1`, `v2`) and two commits between
/// them, returning the owning `TempDir`. Test-only helper shared across modules.
#[cfg(test)]
pub fn make_git_repo_with_tags() -> TempDir {
let dir = TempDir::new("eris-git-test");
let p = dir.path();
git(p, &["init", "-q"]);
git(p, &["config", "commit.gpgsign", "false"]);
std::fs::write(p.join("a.txt"), "hello\n").unwrap();
git(p, &["add", "."]);
git(p, &["commit", "-q", "-m", "initial commit"]);
git(p, &["tag", "v1"]);
std::fs::write(p.join("a.txt"), "hello world\n").unwrap();
git(p, &["add", "."]);
git(
p,
&[
"commit",
"-q",
"-m",
"feat: add greeting\n\nMore detailed body text.",
],
);
std::fs::write(p.join("b.txt"), "second\n").unwrap();
git(p, &["add", "."]);
git(p, &["commit", "-q", "-m", "fix: correct typo"]);
git(p, &["tag", "v2"]);
dir
}