~bigbes/sr-ht-compare

ref: 2569ec406bf421320b30e404ccfa358179490bc3 sr-ht-compare/gitx/fixture_test.go -rw-r--r-- 4.8 KiB
2569ec40 — bigbes ci: publish the apk into artifacts.sr.ht as well 4 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
}