refactor: share the git test fixtures through git-store test-support
commit
b9ab22crefactor: share the git test fixtures through git-store test-support
The tempdir-plus-init repo fixture, commit_all, head, and git_with_stdin each lived as verbatim copies across the workspace’s test modules; downstream crates now enable one copy from their dev-dependencies.
feat: add a test-support feature to git-store with shared fixtures Assisted-by: Claude:claude-fable-5
Reviews
No reviews of this commit yet — record a verdict below.
Start a review
Cargo.lock
@@ -1248,8 +1248,8 @@
version = "0.0.0"
dependencies = [
"facet",
+ "git-store",
"gix",
- "tempfile",
"thiserror 2.0.18",
]
@@ -1260,7 +1260,6 @@
"facet",
"git-anchor",
"git-store",
- "tempfile",
]
[[package]]
crates/git-anchor/Cargo.toml
@@ -11,7 +11,7 @@
thiserror = { workspace = true }
[dev-dependencies]
-tempfile = { workspace = true }
+git-store = { workspace = true, features = ["test-support"] }
[lints]
workspace = true
crates/git-comment/Cargo.toml
@@ -11,7 +11,7 @@
git-store = { workspace = true }
[dev-dependencies]
-tempfile = { workspace = true }
+git-store = { workspace = true, features = ["test-support"] }
[lints]
workspace = true
crates/git-ents/Cargo.toml
@@ -21,5 +21,8 @@
tokio-tungstenite = { version = "0.29.0", features = ["rustls-tls-webpki-roots"] }
ureq = "3.3.0"
+[dev-dependencies]
+git-store = { workspace = true, features = ["test-support"] }
+
[lints]
workspace = true
crates/git-store/Cargo.toml
@@ -9,10 +9,16 @@
facet = { workspace = true }
facet-git-tree = { workspace = true }
gix = { workspace = true }
+tempfile = { workspace = true, optional = true }
thiserror = { workspace = true }
[dev-dependencies]
tempfile = { workspace = true }
+[features]
+# Shared git test fixtures for the workspace's test suites; enable from a
+# downstream crate's dev-dependencies.
+test-support = ["dep:tempfile"]
+
[lints]
workspace = true
crates/git-anchor/src/lib.rs
@@ -364,60 +364,10 @@
reason = "unit test"
)]
- use std::path::Path;
- use std::process::Command;
+ use git_store::test_support::{commit_all, head, repo};
use super::*;
- fn repo() -> tempfile::TempDir {
- let dir = tempfile::tempdir().unwrap();
- let status = Command::new("git")
- .arg("-C")
- .arg(dir.path())
- .args(["init", "-q"])
- .status()
- .unwrap();
- assert!(status.success());
- dir
- }
-
- fn commit_all(dir: &Path, message: &str) {
- let status = Command::new("git")
- .arg("-C")
- .arg(dir)
- .args(["add", "-A"])
- .status()
- .unwrap();
- assert!(status.success());
- let status = Command::new("git")
- .arg("-C")
- .arg(dir)
- .args([
- "-c",
- "user.name=test",
- "-c",
- "user.email=test@example.com",
- "commit",
- "-q",
- "-m",
- message,
- ])
- .status()
- .unwrap();
- assert!(status.success());
- }
-
- fn head(dir: &Path) -> String {
- let output = Command::new("git")
- .arg("-C")
- .arg(dir)
- .args(["rev-parse", "HEAD"])
- .output()
- .unwrap();
- assert!(output.status.success());
- String::from_utf8(output.stdout).unwrap().trim().to_owned()
- }
-
fn numbered(range: std::ops::RangeInclusive<u32>) -> String {
range.map(|n| format!("line {n}\n")).collect()
}
crates/git-comment/src/lib.rs
@@ -107,25 +107,13 @@
reason = "unit test"
)]
- use std::io::Write as _;
- use std::process::{Command, Stdio};
+ use std::process::Command;
use git_anchor::LineRange;
+ use git_store::test_support::{commit_all, git_with_stdin, repo};
use super::*;
- fn repo() -> tempfile::TempDir {
- let dir = tempfile::tempdir().unwrap();
- let status = Command::new("git")
- .arg("-C")
- .arg(dir.path())
- .args(["init", "-q"])
- .status()
- .unwrap();
- assert!(status.success());
- dir
- }
-
fn comment(body: &str, issue: Option<&str>) -> Comment {
Comment {
body: body.to_owned(),
@@ -207,29 +195,7 @@
fn a_stored_comment_projects_onto_the_commit_it_was_written_against() {
let dir = repo();
std::fs::write(dir.path().join("file.txt"), "one\ntwo\nthree\n").unwrap();
- let status = Command::new("git")
- .arg("-C")
- .arg(dir.path())
- .args(["add", "-A"])
- .status()
- .unwrap();
- assert!(status.success());
- let status = Command::new("git")
- .arg("-C")
- .arg(dir.path())
- .args([
- "-c",
- "user.name=test",
- "-c",
- "user.email=test@example.com",
- "commit",
- "-q",
- "-m",
- "one",
- ])
- .status()
- .unwrap();
- assert!(status.success());
+ commit_all(dir.path(), "one");
let anchor = git_anchor::capture(
dir.path(),
@@ -257,28 +223,6 @@
);
}
- /// Run a git plumbing command in `repo` with `input` on stdin, returning
- /// its trimmed stdout.
- fn git_with_stdin(repo: &Path, args: &[&str], input: &str) -> String {
- let mut child = Command::new("git")
- .arg("-C")
- .arg(repo)
- .args(args)
- .stdin(Stdio::piped())
- .stdout(Stdio::piped())
- .spawn()
- .unwrap();
- child
- .stdin
- .as_mut()
- .unwrap()
- .write_all(input.as_bytes())
- .unwrap();
- let output = child.wait_with_output().unwrap();
- assert!(output.status.success());
- String::from_utf8(output.stdout).unwrap().trim().to_owned()
- }
-
#[test]
fn loads_the_on_disk_comment_format() {
// A fixture written as the real on-disk layout — a `body` blob, an
crates/git-ents/src/testutil.rs
@@ -14,9 +14,8 @@
reason = "test support"
)]
-use std::io::Write as _;
use std::path::{Path, PathBuf};
-use std::process::{Command, Stdio};
+use std::process::Command;
use std::sync::atomic::{AtomicUsize, Ordering};
/// A freshly initialized, uniquely named git repository under the temp dir.
@@ -377,21 +376,5 @@
/// Run git in `repo` with `input` on stdin, returning its trimmed stdout.
fn git_with_stdin(repo: &Path, args: &[&str], input: &str) -> String {
- let mut child = Command::new("git")
- .arg("-C")
- .arg(repo)
- .args(args)
- .stdin(Stdio::piped())
- .stdout(Stdio::piped())
- .spawn()
- .unwrap();
- child
- .stdin
- .take()
- .unwrap()
- .write_all(input.as_bytes())
- .unwrap();
- let output = child.wait_with_output().unwrap();
- assert!(output.status.success(), "git {args:?} failed");
- String::from_utf8(output.stdout).unwrap().trim().to_owned()
+ git_store::test_support::git_with_stdin(repo, args, input)
}
crates/git-store/src/lib.rs
@@ -574,20 +574,22 @@
author: Authorship,
}
-#[cfg(test)]
-mod tests {
- #![allow(
- clippy::unwrap_used,
- clippy::let_underscore_must_use,
- reason = "unit test"
- )]
+/// Shared git test fixtures: a throwaway repository and the plumbing helpers
+/// the workspace's test suites drive it with, kept here once instead of as a
+/// copy per crate. Compiled for this crate's own tests and under the
+/// `test-support` feature, which downstream crates enable from their
+/// dev-dependencies.
+#[cfg(any(test, feature = "test-support"))]
+pub mod test_support {
+ #![allow(clippy::unwrap_used, reason = "test fixture")]
- use std::collections::BTreeMap;
- use std::process::Command;
+ use std::io::Write as _;
+ use std::path::Path;
+ use std::process::{Command, Stdio};
- use super::*;
-
- fn repo() -> tempfile::TempDir {
+ /// A fresh temporary directory holding an initialized git repository.
+ #[must_use]
+ pub fn repo() -> tempfile::TempDir {
let dir = tempfile::tempdir().unwrap();
let status = Command::new("git")
.arg("-C")
@@ -599,6 +601,83 @@
dir
}
+ /// Stage everything in `dir` and commit it as `message` under the fixed
+ /// test identity.
+ pub fn commit_all(dir: &Path, message: &str) {
+ let status = Command::new("git")
+ .arg("-C")
+ .arg(dir)
+ .args(["add", "-A"])
+ .status()
+ .unwrap();
+ assert!(status.success());
+ let status = Command::new("git")
+ .arg("-C")
+ .arg(dir)
+ .args([
+ "-c",
+ "user.name=test",
+ "-c",
+ "user.email=test@example.com",
+ "commit",
+ "-q",
+ "-m",
+ message,
+ ])
+ .status()
+ .unwrap();
+ assert!(status.success());
+ }
+
+ /// The full hex id of `dir`'s `HEAD` commit.
+ #[must_use]
+ pub fn head(dir: &Path) -> String {
+ let output = Command::new("git")
+ .arg("-C")
+ .arg(dir)
+ .args(["rev-parse", "HEAD"])
+ .output()
+ .unwrap();
+ assert!(output.status.success());
+ String::from_utf8(output.stdout).unwrap().trim().to_owned()
+ }
+
+ /// Run git in `repo` with `input` on stdin, returning its trimmed stdout.
+ #[must_use]
+ pub fn git_with_stdin(repo: &Path, args: &[&str], input: &str) -> String {
+ let mut child = Command::new("git")
+ .arg("-C")
+ .arg(repo)
+ .args(args)
+ .stdin(Stdio::piped())
+ .stdout(Stdio::piped())
+ .spawn()
+ .unwrap();
+ child
+ .stdin
+ .take()
+ .unwrap()
+ .write_all(input.as_bytes())
+ .unwrap();
+ let output = child.wait_with_output().unwrap();
+ assert!(output.status.success(), "git {args:?} failed");
+ String::from_utf8(output.stdout).unwrap().trim().to_owned()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ #![allow(
+ clippy::unwrap_used,
+ clippy::let_underscore_must_use,
+ reason = "unit test"
+ )]
+
+ use std::collections::BTreeMap;
+
+ use super::*;
+ use crate::test_support::repo;
+
fn entries(pairs: &[(&str, &str)]) -> BTreeMap<String, String> {
pairs
.iter()