Skip to main content

Crate vcs_testkit

Crate vcs_testkit 

Source
Expand description

vcs-testkit — throwaway git/jj sandboxes (and a bare remote) for integration tests.

Hands a #[test] a real repository to drive: a unique self-cleaning TempDir, a configured GitSandbox / JjSandbox to build scenarios in, and a seeded BareRemote to clone/fetch/push against. It is dependency-free (not even the wrapper crates, so it can be a dev-dependency of any of them without a cycle), synchronous (test setup needs no runtime — it shells out with std::process::Command, not the async client under test), and panics on failure (a broken fixture should fail loudly at the call site, not thread Results through scenario code).

Built for #[test] / #[ignore] integration tests that need a real repo: the helpers run the actual git / jj on PATH, so gate any test that touches one behind #[ignore = "requires the git binary"] — a hermetic CI with no binaries installed then stays green, and cargo test -- --ignored runs them locally. Every sandbox is isolated from the host’s VCS config (no system/global config, no init.templateDir hook leakage, a deterministic identity even on the commit jj git init creates) — see command.

§The surface

  • TempDir — a unique temporary directory, removed on drop. Uniqueness without a temp-dir crate: pid + a process-wide monotonic counter, so parallel tests in a run never collide. Every fixture owns one.
  • GitSandbox — a throwaway git repo on branch main with a deterministic identity. Build scenarios through the convenience steps (commit_file, branch, checkout, rev_parse) plus the raw git escape hatch for anything unmodelled.
  • JjSandbox — the same shape for a jj (git-backed) workspace: describe, new_change, bookmark, and the raw jj hatch.
  • BareRemote — a populated bare git repo, a local clone/fetch/push source with no network. BareRemote::seeded gives one commit on main containing seed.txt; url yields a string remote URL.
  • configure_identity — stamp a git repo with a deterministic identity and byte-stable behaviour (user.*, commit.gpgsign=false, core.autocrlf=false). Standalone, for tests whose subject is init.
  • Raw steps git / jj — run one command in any dir, panicking on failure: for scenario steps in directories no sandbox owns (linked worktrees, fresh clones, repos the code under test initialised).

§Recipes

These are sync — no async wrapper, no Result (fixtures panic). They are no_run: they really create temp dirs and shell out to git/jj, so they compile here but only run under a binary-equipped #[test].

Build a git scenario — write + stage + commit is one step:

use vcs_testkit::GitSandbox;
let repo = GitSandbox::init("scenario");
repo.commit_file("a.txt", "one\n", "first");   // write + add -A + commit
repo.branch("feature");
repo.checkout("feature");
repo.commit_file("sub/b.txt", "two\n", "second");

let head = repo.rev_parse("HEAD");
assert_eq!(head.len(), 40);
assert_ne!(head, repo.rev_parse("main"));       // feature has diverged

Seed a bare remote and fetch from it — drop to raw git for the remote wiring:

use vcs_testkit::{BareRemote, GitSandbox};
let repo = GitSandbox::init("local");
repo.commit_file("a.txt", "one\n", "first");

let remote = BareRemote::seeded("origin");
repo.git(&["remote", "add", "origin", remote.url().as_str()]);
repo.git(&["fetch", "-q", "origin"]);
assert_eq!(repo.rev_parse("origin/main").len(), 40); // seed commit fetched

§In-depth guide

Beyond this page, this crate ships a full how-to guide — rendered on docs.rs from docs/. See the guide module (and its cross-cutting testing sub-guide on the trait / mock / runner seams that let most tests skip real binaries entirely).

Modules§

guide
vcs-testkit — test fixtures guide

Structs§

BareRemote
A populated bare git repository — a local clone/fetch/push source for integration tests (no network). Seeded with one commit on main containing seed.txt.
GitSandbox
A throwaway git repository: owns its TempDir, initialised on branch main with a deterministic identity (see configure_identity).
JjSandbox
A throwaway jj repository (git-backed) with a repo-scoped identity.
TempDir
A unique temporary directory, removed on drop.

Functions§

configure_identity
Give the git repository at dir a deterministic identity and byte-stable behaviour: user.name/user.email, commit.gpgsign=false (no keychain prompts), and core.autocrlf=false (no CRLF rewriting under content assertions on Windows).
git
Run git <args> in dir, panicking on failure — for scenario steps in directories not owned by a GitSandbox (linked worktrees, fresh clones, repos initialised by the code under test).
jj
Run jj <args> in dir, panicking on failure (see git).