socle

gitfixture_test.go

package main

import (
	"os"
	"os/exec"
	"path/filepath"
	"testing"
)

// fixtureEnv pins every input that could make fixture repo shas vary between runs or hosts:
// user and system git config are nulled, and authorship names, emails, and dates are fixed.
// With these pinned, fixture shas are byte-stable, so tests assert them as literals
// (the fixtureSha* consts); any drift in those assertions means the hermeticity broke.
var fixtureEnv = []string{
	"GIT_CONFIG_GLOBAL=/dev/null",
	"GIT_CONFIG_SYSTEM=/dev/null",
	"GIT_CONFIG_NOSYSTEM=1",
	"GIT_ATTR_NOSYSTEM=1",
	"GIT_AUTHOR_NAME=Ada Fixture",
	"GIT_AUTHOR_EMAIL=ada@fixture.example",
	"GIT_AUTHOR_DATE=2026-01-02T03:04:05Z",
	"GIT_COMMITTER_NAME=Ada Fixture",
	"GIT_COMMITTER_EMAIL=ada@fixture.example",
	"GIT_COMMITTER_DATE=2026-01-02T03:04:05Z",
}

// The shas of the fixture repo built by buildFixtureRepo, byte-stable by construction.
const (
	fixtureShaMain = "ced91a8519b59966124301e6383532f24223528b" // tip of main (the second commit); also what v1.0 peels to
	fixtureShaRoot = "64ac67a35d36079e167cb8f929fd57f859c8b5d1" // the first commit, parent of main
	fixtureShaDev  = "9b492196b444f712640f1755e048d90d8c51de2e" // tip of the dev branch
)

// fixtureReadme is the README content at the tip of main (dev's tip rewrites it).
const fixtureReadme = "# Fixturama\n\nA repo that exists to be looked at.\n"

// gitFixture runs one git command while building a fixture, failing the test on any problem.
func gitFixture(t *testing.T, dir string, args ...string) {
	t.Helper()
	cmd := exec.Command("git", args...)
	cmd.Dir = dir
	cmd.Env = append(os.Environ(), fixtureEnv...)
	if out, err := cmd.CombinedOutput(); err != nil {
		t.Fatalf("fixture git %v: %v\n%s", args, err, out)
	}
}

// writeFixtureFile writes one file into a fixture worktree, creating parent dirs as needed.
func writeFixtureFile(t *testing.T, dir, path, content string) {
	t.Helper()
	abs := filepath.Join(dir, path)
	if err := os.MkdirAll(filepath.Dir(abs), 0o755); err != nil {
		t.Fatal(err)
	}
	if err := os.WriteFile(abs, []byte(content), 0o644); err != nil {
		t.Fatal(err)
	}
}

// buildFixtureRepo creates the standard hermetic fixture repo and returns its worktree path.
//
// History: two commits on main (a README, then docs/ and src/), an annotated tag v1.0
// on main's tip, and a dev branch one commit ahead of main (rewriting the README).
// HEAD is left on main.  A filename with a space is included deliberately:
// path handling has to survive it.
// The src/ code files, vendor/, and .gitignore exist for language classification:
// Go dominant, Rust (an extension that needs a content sniff to classify), CSS (markup),
// and two paths the meter must skip (vendored, dotfile).
func buildFixtureRepo(t *testing.T) string {
	t.Helper()
	dir := t.TempDir()
	gitFixture(t, dir, "init", "-q", "-b", "main", "--object-format=sha1", ".")

	writeFixtureFile(t, dir, "README.md", fixtureReadme)
	gitFixture(t, dir, "add", "-A")
	gitFixture(t, dir, "commit", "-q", "-m", "inaugurate with a readme")

	writeFixtureFile(t, dir, "docs/notes.md", "Notes live here.\n")
	writeFixtureFile(t, dir, "docs/with space.txt", "even this filename works\n")
	writeFixtureFile(t, dir, "src/hello.txt", "hello from the fixture\n")
	writeFixtureFile(t, dir, "src/hello.go", "package hello\n\nimport \"fmt\"\n\n// Greet says hello from the fixture, at some length:\n// the meter wants Go to dominate this repo's composition.\nfunc Greet(name string) string {\n\treturn fmt.Sprintf(\"hello, %s, from the fixture\", name)\n}\n")
	writeFixtureFile(t, dir, "src/lib.rs", "pub fn greet(name: &str) -> String {\n    format!(\"hello, {name}\")\n}\n")
	writeFixtureFile(t, dir, "src/style.css", ".hello { color: rebeccapurple; }\n")
	writeFixtureFile(t, dir, "vendor/mini.js", "export const mini = () => 'vendored';\n")
	writeFixtureFile(t, dir, ".gitignore", "/dist/\n")
	gitFixture(t, dir, "add", "-A")
	gitFixture(t, dir, "commit", "-q", "-m", "add docs and src")
	gitFixture(t, dir, "tag", "-a", "v1.0", "-m", "the first showing")

	gitFixture(t, dir, "checkout", "-q", "-b", "dev")
	writeFixtureFile(t, dir, "README.md", "# Fixturama\n\nNow with more verve.\n")
	gitFixture(t, dir, "add", "-A")
	gitFixture(t, dir, "commit", "-q", "-m", "sharpen the readme")
	gitFixture(t, dir, "checkout", "-q", "main")

	return dir
}

// fixtureRepo builds the fixture and opens it, the common prelude of the read-op tests.
func fixtureRepo(t *testing.T) *repo {
	t.Helper()
	dir := buildFixtureRepo(t)
	r, err := openRepo("fixturama", repoConfig{Path: dir, Description: "the fixture"})
	if err != nil {
		t.Fatalf("opening fixture: %v", err)
	}
	return r
}

gitfixture_test.go · 4.6 KiB · 30aaaf206d