use std::process::{Command, Stdio};
fn git(path: &std::path::Path, args: &[&str]) {
let status = Command::new("git")
.arg("-C")
.arg(path)
.args(["-c", "user.email=test@example.com", "-c", "user.name=Test"])
.args(args)
.status()
.expect("run git");
assert!(status.success(), "git {args:?} failed");
}
fn init_repo(path: &std::path::Path) {
std::fs::create_dir_all(path).expect("create repo dir");
let status = Command::new("git")
.args(["init", "--quiet", "--initial-branch", "main"])
.arg(path)
.status()
.expect("run git init");
assert!(status.success());
git(path, &["commit", "--allow-empty", "-m", "first"]);
}
fn write_config(config_dir: &std::path::Path, root: &std::path::Path) {
let config_toml = format!(
"[[set]]\nname = \"test\"\nroots = [\"{}\"]\n",
root.display()
);
std::fs::write(config_dir.join("config.toml"), config_toml).expect("write config");
}
fn field<'a>(document: &'a serde_json::Value, name: &str) -> &'a serde_json::Value {
document
.get(name)
.unwrap_or_else(|| panic!("no top-level `{name}` field in {document}"))
}
#[test]
fn repon_status_on_a_dirty_repo_exits_zero_and_prints_the_schema() {
let config_dir = tempfile::tempdir().expect("create config dir");
let root = tempfile::tempdir().expect("create root");
let root_path = root.path().canonicalize().expect("canonicalize root");
init_repo(&root_path);
std::fs::write(root_path.join("untracked.txt"), "untracked\n").expect("write file");
write_config(config_dir.path(), &root_path);
let output = Command::new(env!("CARGO_BIN_EXE_repon"))
.arg("status")
.env("REPON_CONFIG", config_dir.path())
.stdin(Stdio::null())
.output()
.expect("run repon status");
assert!(
output.status.success(),
"expected a clean exit on a merely dirty tree, got: {output:?}"
);
let stdout = String::from_utf8_lossy(&output.stdout);
let document: serde_json::Value =
serde_json::from_str(&stdout).unwrap_or_else(|error| panic!("{error}: {stdout}"));
assert_eq!(field(&document, "schema"), 1);
assert_eq!(
field(&document, "entities")
.as_array()
.expect("entities is an array")
.len(),
1
);
}
#[test]
fn repon_status_on_a_repo_with_an_unreadable_head_exits_non_zero() {
let config_dir = tempfile::tempdir().expect("create config dir");
let root = tempfile::tempdir().expect("create root");
let root_path = root.path().canonicalize().expect("canonicalize root");
init_repo(&root_path);
std::fs::write(
root_path.join(".git").join("HEAD"),
"not a ref or an object id\n",
)
.expect("corrupt HEAD");
write_config(config_dir.path(), &root_path);
let output = Command::new(env!("CARGO_BIN_EXE_repon"))
.arg("status")
.env("REPON_CONFIG", config_dir.path())
.stdin(Stdio::null())
.output()
.expect("run repon status");
assert!(
!output.status.success(),
"expected a non-zero exit on a probe that never got an answer, got: {output:?}"
);
let stdout = String::from_utf8_lossy(&output.stdout);
let document: serde_json::Value =
serde_json::from_str(&stdout).unwrap_or_else(|error| panic!("{error}: {stdout}"));
assert_eq!(
field(&document, "schema"),
1,
"the document is still printed even though the process exits non-zero"
);
}