#[allow(dead_code)]
pub(crate) fn test_git_cmd() -> crate::policy::GitCommand {
crate::git::git_cmd()
}
#[allow(dead_code)]
pub(crate) fn test_commit_cmd() -> crate::policy::GitCommand {
let mut cmd = test_git_cmd();
cmd.args(["commit", "--no-verify"]);
cmd
}
#[cfg(test)]
#[allow(dead_code)]
static TEST_TEMPS: std::sync::OnceLock<std::sync::Mutex<Vec<tempfile::TempDir>>> =
std::sync::OnceLock::new();
#[cfg(test)]
fn keep_temp_alive(tmp: tempfile::TempDir) -> std::path::PathBuf {
let path = tmp.path().to_path_buf();
let mut registry = TEST_TEMPS
.get_or_init(|| std::sync::Mutex::new(Vec::new()))
.lock()
.expect("TEST_TEMPS lock poisoned");
registry.push(tmp); path
}
#[cfg(test)]
#[allow(dead_code)]
pub(crate) fn create_test_repo() -> std::path::PathBuf {
let tmp = tempfile::TempDir::new().expect("temp dir");
let repo = tmp.path().to_path_buf();
test_git_cmd()
.args(["init", "-q", &repo.to_string_lossy()])
.output()
.expect("git init");
std::fs::write(repo.join("f"), "content").expect("write file");
test_git_cmd()
.args(["add", "f"])
.current_dir(&repo)
.output()
.expect("git add");
test_commit_cmd()
.args(["-m", "init"])
.current_dir(&repo)
.output()
.expect("git commit");
keep_temp_alive(tmp)
}
#[cfg(test)]
#[allow(dead_code)]
pub(crate) fn create_test_repo_with_remote() -> (std::path::PathBuf, std::path::PathBuf) {
let tmp = tempfile::TempDir::new().expect("temp dir");
let bare = tmp.path().join("bare.git");
test_git_cmd()
.args(["init", "--bare", &bare.to_string_lossy()])
.output()
.expect("git init --bare");
let repo = tmp.path().join("repo");
test_git_cmd()
.args(["init", "-q", &repo.to_string_lossy()])
.output()
.expect("git init");
test_git_cmd()
.args(["remote", "add", "origin", &bare.to_string_lossy()])
.current_dir(&repo)
.output()
.expect("git remote add");
std::fs::write(repo.join("f"), "content").expect("write file");
test_git_cmd()
.args(["add", "f"])
.current_dir(&repo)
.output()
.expect("git add");
test_commit_cmd()
.args(["-m", "init"])
.current_dir(&repo)
.output()
.expect("git commit");
keep_temp_alive(tmp);
(repo, bare)
}
#[allow(dead_code)]
pub(crate) struct GitBinRestorer {
inner: EnvRestorer,
}
impl GitBinRestorer {
#[allow(dead_code)]
pub(crate) fn new(new_value: &str) -> Self {
Self {
inner: EnvRestorer::new("DRACON_SYNC_GIT_BIN", new_value),
}
}
#[allow(dead_code)]
pub(crate) fn remove() -> Self {
Self {
inner: EnvRestorer::remove("DRACON_SYNC_GIT_BIN"),
}
}
}
#[allow(dead_code)]
pub(crate) struct EnvRestorer {
key: String,
old_value: Option<String>,
}
#[allow(dead_code)]
impl EnvRestorer {
pub(crate) fn new(key: &str, new_value: &str) -> Self {
let old_value = std::env::var(key).ok();
std::env::set_var(key, new_value);
EnvRestorer {
key: key.to_string(),
old_value,
}
}
pub(crate) fn remove(key: &str) -> Self {
let old_value = std::env::var(key).ok();
std::env::remove_var(key);
EnvRestorer {
key: key.to_string(),
old_value,
}
}
}
impl Drop for EnvRestorer {
fn drop(&mut self) {
std::env::remove_var(&self.key);
if let Some(ref v) = self.old_value {
std::env::set_var(&self.key, v);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_create_test_repo_registers_temp_dir() {
let initial_count = TEST_TEMPS
.get()
.and_then(|m| m.lock().ok().map(|g| g.len()))
.unwrap_or(0);
let _repo = create_test_repo();
let after_count = TEST_TEMPS
.get()
.and_then(|m| m.lock().ok().map(|g| g.len()))
.expect("TEST_TEMPS must be initialised by create_test_repo");
assert!(
after_count > initial_count,
"create_test_repo did not register the temp dir: \
before={initial_count} after={after_count}; \
the F45 fix is missing"
);
}
#[test]
fn test_env_restorer_round_trip() {
let key = "DRACON_TEST_ROUND_TRIP_VAR";
std::env::set_var(key, "before");
{
let _guard = EnvRestorer::new(key, "during");
assert_eq!(std::env::var(key).as_deref().ok(), Some("during"));
}
assert_eq!(std::env::var(key).as_deref().ok(), Some("before"));
std::env::remove_var(key);
}
#[test]
fn test_env_restorer_remove_round_trip() {
let key = "DRACON_TEST_REMOVE_VAR";
std::env::set_var(key, "before");
{
let _guard = EnvRestorer::remove(key);
assert!(std::env::var(key).is_err(), "remove should unset");
}
assert_eq!(std::env::var(key).as_deref().ok(), Some("before"));
std::env::remove_var(key);
}
}