~bigbes/sr-ht-compare

ref: f18653603d66734b583b52d2fe0da7c59a7b1f32 sr-ht-compare/gitx/fixture_test.go -rw-r--r-- 4.8 KiB
f1865360 — bigbes ci: the family's build pipeline, and PKGVER by export 9 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package gitx

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

// The fixture builds a bare repository at <tmp>/~alice/demo with a history rich
// enough to exercise every command:
//
//	root ── c2 ── rename ── binary ─┐
//	          \                      merge   (branch: main, HEAD)
//	           feature ─────────────┘        (branch: feature/with-slash)
//
//	root    : add a.txt                       (root commit)
//	c2      : add b.txt, edit a.txt
//	rename  : git mv a.txt -> a-renamed.txt   (tag: v0.9.0)
//	binary  : add bin.dat (4 NUL-ish bytes)   (main^1)
//	feature : add feature.txt (from c2)       (branch feature/with-slash, main^2)
//	merge   : merge feature into main         (main, HEAD; tag: v1.0.0)
//
// The commit dates increase monotonically so tag creator-date ordering is
// deterministic (v1.0.0 newer than v0.9.0).

const (
	fxOwner = "alice"
	fxName  = "demo"
)

// gitTest runs git in dir with a hardened, deterministic environment, failing
// the test on error.
func gitTest(t *testing.T, dir string, date string, args ...string) string {
	t.Helper()
	cmd := exec.Command("git", args...)
	cmd.Dir = dir
	cmd.Env = append(os.Environ(),
		"GIT_CONFIG_GLOBAL=/dev/null",
		"GIT_CONFIG_SYSTEM=/dev/null",
		"GIT_TERMINAL_PROMPT=0",
		"LC_ALL=C",
		"GIT_AUTHOR_NAME=Alice Example",
		"GIT_AUTHOR_EMAIL=alice@example.com",
		"GIT_COMMITTER_NAME=Alice Example",
		"GIT_COMMITTER_EMAIL=alice@example.com",
		"GIT_AUTHOR_DATE="+date,
		"GIT_COMMITTER_DATE="+date,
	)
	out, err := cmd.CombinedOutput()
	if err != nil {
		t.Fatalf("git %s: %v\n%s", strings.Join(args, " "), err, out)
	}
	return string(out)
}

func writeFile(t *testing.T, dir, name string, data []byte) {
	t.Helper()
	p := filepath.Join(dir, name)
	if err := os.MkdirAll(filepath.Dir(p), 0o755); err != nil {
		t.Fatal(err)
	}
	if err := os.WriteFile(p, data, 0o644); err != nil {
		t.Fatal(err)
	}
}

// newFixtureRepo builds the bare fixture repository and returns reposRoot (the
// directory that Open takes). The bare repo lives at reposRoot/~alice/demo.
func newFixtureRepo(t *testing.T) string {
	t.Helper()
	if _, err := exec.LookPath("git"); err != nil {
		t.Skipf("git not available: %v", err)
	}

	reposRoot := t.TempDir()
	work := t.TempDir()

	d1 := "2024-01-01T00:00:00Z"
	d2 := "2024-01-02T00:00:00Z"
	d3 := "2024-01-03T00:00:00Z"
	d4 := "2024-01-04T00:00:00Z"
	d5 := "2024-01-05T00:00:00Z"
	d6 := "2024-01-06T00:00:00Z"

	gitTest(t, work, d1, "init", "-b", "main")

	// root: add a.txt
	writeFile(t, work, "a.txt", []byte("hello\nworld\n"))
	gitTest(t, work, d1, "add", "a.txt")
	gitTest(t, work, d1, "commit", "-m", "root: add a.txt")

	// c2: add b.txt, edit a.txt
	writeFile(t, work, "a.txt", []byte("hello\nworld\nmore\n"))
	writeFile(t, work, "b.txt", []byte("bee\n"))
	gitTest(t, work, d2, "add", "a.txt", "b.txt")
	gitTest(t, work, d2, "commit", "-m", "c2: add b, edit a")

	// feature branch from c2 (before rename/binary): add feature.txt
	gitTest(t, work, d5, "branch", "feature/with-slash")

	// rename: pure git mv a.txt -> a-renamed.txt
	gitTest(t, work, d3, "mv", "a.txt", "a-renamed.txt")
	gitTest(t, work, d3, "commit", "-m", "rename: a.txt -> a-renamed.txt")
	gitTest(t, work, d3, "tag", "-a", "-m", "release 0.9.0", "v0.9.0")

	// binary: add bin.dat (4 bytes, includes NUL)
	writeFile(t, work, "bin.dat", []byte{0x00, 0x01, 0x02, 0x03})
	gitTest(t, work, d4, "add", "bin.dat")
	gitTest(t, work, d4, "commit", "-m", "binary: add bin.dat")

	// build feature tip
	gitTest(t, work, d5, "checkout", "feature/with-slash")
	writeFile(t, work, "feature.txt", []byte("feature\n"))
	gitTest(t, work, d5, "add", "feature.txt")
	gitTest(t, work, d5, "commit", "-m", "feature: add feature.txt")

	// merge feature into main (no-ff so a merge commit is created)
	gitTest(t, work, d6, "checkout", "main")
	gitTest(t, work, d6, "merge", "--no-ff", "-m", "merge feature/with-slash", "feature/with-slash")
	gitTest(t, work, d6, "tag", "-a", "-m", "release 1.0.0", "v1.0.0")

	// bare clone into reposRoot/~alice/demo
	if err := os.MkdirAll(filepath.Join(reposRoot, "~"+fxOwner), 0o755); err != nil {
		t.Fatal(err)
	}
	bare := filepath.Join(reposRoot, "~"+fxOwner, fxName)
	gitTest(t, work, d6, "clone", "--bare", work, bare)

	return reposRoot
}

// fxRev resolves a revision inside the bare fixture repo to its full SHA. It is
// a test helper for landmark navigation (e.g. "main^1~1" for the rename
// commit); it is independent of the code under test.
func fxRev(t *testing.T, reposRoot, rev string) string {
	t.Helper()
	return fxRevIn(t, reposRoot, fxName, rev)
}

// openFixture opens the fixture repo through the code under test.
func openFixture(t *testing.T, reposRoot string) *Repo {
	t.Helper()
	repo, err := Open(reposRoot, fxOwner, fxName)
	if err != nil {
		t.Fatalf("Open: %v", err)
	}
	return repo
}