aboutsummaryrefslogtreecommitdiff
path: root/internal/testgit
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-04-02 06:23:30 +0000
committerGravatar Runxi Yu2026-04-02 06:28:39 +0000
commita041d523de389b65b98a5373a8034041db2a8d83 (patch)
tree7b423dc735f463be616045f2c3c2095a7737aca7 /internal/testgit
parentresearch: Add dynamic pack resources (diff)
signatureNo signature
*: Remove
Diffstat (limited to 'internal/testgit')
-rw-r--r--internal/testgit/algorithms.go18
-rw-r--r--internal/testgit/repo.go11
-rw-r--r--internal/testgit/repo_cat_file.go14
-rw-r--r--internal/testgit/repo_commit_graph_write.go13
-rw-r--r--internal/testgit/repo_commit_tree.go29
-rw-r--r--internal/testgit/repo_commit_tree_env.go51
-rw-r--r--internal/testgit/repo_from_fixture.go36
-rw-r--r--internal/testgit/repo_fs.go86
-rw-r--r--internal/testgit/repo_hash_object.go20
-rw-r--r--internal/testgit/repo_make_commit.go16
-rw-r--r--internal/testgit/repo_make_many_objects_history.go83
-rw-r--r--internal/testgit/repo_make_single_file_tree.go18
-rw-r--r--internal/testgit/repo_mktree.go20
-rw-r--r--internal/testgit/repo_new.go64
-rw-r--r--internal/testgit/repo_open_commit_graph.go26
-rw-r--r--internal/testgit/repo_open_object_store.go29
-rw-r--r--internal/testgit/repo_open_repository.go25
-rw-r--r--internal/testgit/repo_open_root.go87
-rw-r--r--internal/testgit/repo_pack_objects_is_thin.go77
-rw-r--r--internal/testgit/repo_pack_objects_reader.go94
-rw-r--r--internal/testgit/repo_properties.go20
-rw-r--r--internal/testgit/repo_refs.go48
-rw-r--r--internal/testgit/repo_remove_loose_object.go22
-rw-r--r--internal/testgit/repo_repack.go13
-rw-r--r--internal/testgit/repo_rev_list.go37
-rw-r--r--internal/testgit/repo_rev_parse.go20
-rw-r--r--internal/testgit/repo_run.go95
-rw-r--r--internal/testgit/repo_run_extra_files.go55
-rw-r--r--internal/testgit/repo_tag_annotated.go15
29 files changed, 0 insertions, 1142 deletions
diff --git a/internal/testgit/algorithms.go b/internal/testgit/algorithms.go
deleted file mode 100644
index aea4dc12..00000000
--- a/internal/testgit/algorithms.go
+++ /dev/null
@@ -1,18 +0,0 @@
-package testgit
-
-import (
- "testing"
-
- objectid "codeberg.org/lindenii/furgit/object/id"
-)
-
-// ForEachAlgorithm runs a subtest for every supported algorithm.
-func ForEachAlgorithm(t *testing.T, fn func(t *testing.T, algo objectid.Algorithm)) {
- t.Helper()
-
- for _, algo := range objectid.SupportedAlgorithms() {
- t.Run(algo.String(), func(t *testing.T) {
- fn(t, algo)
- })
- }
-}
diff --git a/internal/testgit/repo.go b/internal/testgit/repo.go
deleted file mode 100644
index 72831bd6..00000000
--- a/internal/testgit/repo.go
+++ /dev/null
@@ -1,11 +0,0 @@
-// Package testgit provides helpers for integration tests with upstream git(1).
-package testgit
-
-import objectid "codeberg.org/lindenii/furgit/object/id"
-
-// TestRepo is a temporary git repository harness for integration tests.
-type TestRepo struct {
- dir string
- algo objectid.Algorithm
- env []string
-}
diff --git a/internal/testgit/repo_cat_file.go b/internal/testgit/repo_cat_file.go
deleted file mode 100644
index 7dbd2c43..00000000
--- a/internal/testgit/repo_cat_file.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package testgit
-
-import (
- "testing"
-
- objectid "codeberg.org/lindenii/furgit/object/id"
-)
-
-// CatFile returns raw output from git cat-file.
-func (testRepo *TestRepo) CatFile(tb testing.TB, mode string, id objectid.ObjectID) []byte {
- tb.Helper()
-
- return testRepo.RunBytes(tb, "cat-file", mode, id.String())
-}
diff --git a/internal/testgit/repo_commit_graph_write.go b/internal/testgit/repo_commit_graph_write.go
deleted file mode 100644
index 13221f87..00000000
--- a/internal/testgit/repo_commit_graph_write.go
+++ /dev/null
@@ -1,13 +0,0 @@
-package testgit
-
-import "testing"
-
-// CommitGraphWrite runs "git commit-graph write" with args in the repository.
-func (testRepo *TestRepo) CommitGraphWrite(tb testing.TB, args ...string) {
- tb.Helper()
-
- cmdArgs := make([]string, 0, len(args)+3)
- cmdArgs = append(cmdArgs, "commit-graph", "write")
- cmdArgs = append(cmdArgs, args...)
- _ = testRepo.Run(tb, cmdArgs...)
-}
diff --git a/internal/testgit/repo_commit_tree.go b/internal/testgit/repo_commit_tree.go
deleted file mode 100644
index 3a5a75ac..00000000
--- a/internal/testgit/repo_commit_tree.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package testgit
-
-import (
- "testing"
-
- objectid "codeberg.org/lindenii/furgit/object/id"
-)
-
-// CommitTree creates a commit from a tree and message, optionally with parents.
-func (testRepo *TestRepo) CommitTree(tb testing.TB, tree objectid.ObjectID, message string, parents ...objectid.ObjectID) objectid.ObjectID {
- tb.Helper()
-
- args := make([]string, 0, 2+2*len(parents)+2)
-
- args = append(args, "commit-tree", tree.String())
- for _, p := range parents {
- args = append(args, "-p", p.String())
- }
-
- args = append(args, "-m", message)
- hex := testRepo.Run(tb, args...)
-
- id, err := objectid.ParseHex(testRepo.algo, hex)
- if err != nil {
- tb.Fatalf("parse commit-tree output %q: %v", hex, err)
- }
-
- return id
-}
diff --git a/internal/testgit/repo_commit_tree_env.go b/internal/testgit/repo_commit_tree_env.go
deleted file mode 100644
index fbddf26f..00000000
--- a/internal/testgit/repo_commit_tree_env.go
+++ /dev/null
@@ -1,51 +0,0 @@
-package testgit
-
-import (
- "slices"
- "strings"
- "testing"
-
- objectid "codeberg.org/lindenii/furgit/object/id"
-)
-
-// CommitTreeWithEnv creates one commit from a tree and message, optionally with
-// parents, using additional environment variables for the git subprocess.
-func (testRepo *TestRepo) CommitTreeWithEnv(
- tb testing.TB,
- extraEnv []string,
- tree objectid.ObjectID,
- message string,
- parents ...objectid.ObjectID,
-) objectid.ObjectID {
- tb.Helper()
-
- args := make([]string, 0, 2+2*len(parents)+2)
-
- args = append(args, "commit-tree", tree.String())
- for _, parent := range parents {
- args = append(args, "-p", parent.String())
- }
-
- args = append(args, "-m", message)
- hex := testRepo.runWithExtraEnv(tb, extraEnv, args...)
-
- id, err := objectid.ParseHex(testRepo.algo, hex)
- if err != nil {
- tb.Fatalf("parse commit-tree output %q: %v", hex, err)
- }
-
- return id
-}
-
-func (testRepo *TestRepo) runWithExtraEnv(tb testing.TB, extraEnv []string, args ...string) string {
- tb.Helper()
-
- env := slices.Concat(testRepo.env, extraEnv)
-
- out, err := testRepo.runBytesWithEnv(tb, nil, testRepo.dir, env, args...)
- if err != nil {
- tb.Fatalf("git %v failed: %v\n%s", args, err, out)
- }
-
- return strings.TrimSpace(string(out))
-}
diff --git a/internal/testgit/repo_from_fixture.go b/internal/testgit/repo_from_fixture.go
deleted file mode 100644
index 632de12a..00000000
--- a/internal/testgit/repo_from_fixture.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package testgit
-
-import (
- "io/fs"
- "os"
- "testing"
-
- objectid "codeberg.org/lindenii/furgit/object/id"
-)
-
-// NewRepoFromFixture copies one existing repository fixture into a temp dir.
-func NewRepoFromFixture(tb testing.TB, algo objectid.Algorithm, fixtureDir string) *TestRepo {
- tb.Helper()
-
- if algo.Size() == 0 {
- tb.Fatalf("invalid algorithm: %v", algo)
- }
-
- dst := tb.TempDir()
- srcFS := os.DirFS(fixtureDir)
-
- err := copyFS(dst, srcFS)
- if err != nil {
- tb.Fatalf("copy fixture %q: %v", fixtureDir, err)
- }
-
- return &TestRepo{
- dir: dst,
- algo: algo,
- env: defaultEnv(),
- }
-}
-
-func copyFS(dst string, src fs.FS) error {
- return os.CopyFS(dst, src)
-}
diff --git a/internal/testgit/repo_fs.go b/internal/testgit/repo_fs.go
deleted file mode 100644
index 56acbfcf..00000000
--- a/internal/testgit/repo_fs.go
+++ /dev/null
@@ -1,86 +0,0 @@
-package testgit
-
-import (
- "os"
- "path/filepath"
- "testing"
-)
-
-// OpenFile opens one file relative to the repository root.
-func (testRepo *TestRepo) OpenFile(tb testing.TB, name string) *os.File {
- tb.Helper()
-
- root := testRepo.OpenRoot(tb)
-
- file, err := root.Open(name)
- if err != nil {
- tb.Fatalf("Open(%q): %v", name, err)
- }
-
- return file
-}
-
-// ReadFile reads one file relative to the repository root.
-func (testRepo *TestRepo) ReadFile(tb testing.TB, name string) []byte {
- tb.Helper()
-
- root := testRepo.OpenRoot(tb)
-
- data, err := root.ReadFile(name)
- if err != nil {
- tb.Fatalf("ReadFile(%q): %v", name, err)
- }
-
- return data
-}
-
-// WriteFile writes one file relative to the repository root.
-func (testRepo *TestRepo) WriteFile(tb testing.TB, name string, data []byte, perm os.FileMode) {
- tb.Helper()
-
- root := testRepo.OpenRoot(tb)
-
- err := root.WriteFile(name, data, perm)
- if err != nil {
- tb.Fatalf("WriteFile(%q): %v", name, err)
- }
-}
-
-// WriteFileAll writes one file relative to the repository root, creating any
-// missing parent directories first.
-func (testRepo *TestRepo) WriteFileAll(
- tb testing.TB,
- name string,
- data []byte,
- dirPerm os.FileMode,
- filePerm os.FileMode,
-) {
- tb.Helper()
-
- root := testRepo.OpenRoot(tb)
-
- dir := filepath.Dir(name)
- if dir != "." {
- err := root.MkdirAll(dir, dirPerm)
- if err != nil {
- tb.Fatalf("MkdirAll(%q): %v", dir, err)
- }
- }
-
- err := root.WriteFile(name, data, filePerm)
- if err != nil {
- tb.Fatalf("WriteFile(%q): %v", name, err)
- }
-}
-
-// Remove removes one path relative to the repository root.
-func (testRepo *TestRepo) Remove(tb testing.TB, name string) {
- tb.Helper()
-
- root := testRepo.OpenRoot(tb)
-
- err := root.Remove(name)
- if err != nil {
- tb.Fatalf("Remove(%q): %v", name, err)
- }
-}
diff --git a/internal/testgit/repo_hash_object.go b/internal/testgit/repo_hash_object.go
deleted file mode 100644
index 75f1a7ab..00000000
--- a/internal/testgit/repo_hash_object.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package testgit
-
-import (
- "testing"
-
- objectid "codeberg.org/lindenii/furgit/object/id"
-)
-
-// HashObject hashes and writes an object and returns its object ID.
-func (testRepo *TestRepo) HashObject(tb testing.TB, objType string, body []byte) objectid.ObjectID {
- tb.Helper()
- hex := testRepo.RunInput(tb, body, "hash-object", "-t", objType, "-w", "--stdin")
-
- id, err := objectid.ParseHex(testRepo.algo, hex)
- if err != nil {
- tb.Fatalf("parse git hash-object output %q: %v", hex, err)
- }
-
- return id
-}
diff --git a/internal/testgit/repo_make_commit.go b/internal/testgit/repo_make_commit.go
deleted file mode 100644
index 32a063f7..00000000
--- a/internal/testgit/repo_make_commit.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package testgit
-
-import (
- "testing"
-
- objectid "codeberg.org/lindenii/furgit/object/id"
-)
-
-// MakeCommit creates a commit over a single-file tree and returns (blobID, treeID, commitID).
-func (testRepo *TestRepo) MakeCommit(tb testing.TB, message string) (objectid.ObjectID, objectid.ObjectID, objectid.ObjectID) {
- tb.Helper()
- blobID, treeID := testRepo.MakeSingleFileTree(tb, "file.txt", []byte("commit-body\n"))
- commitID := testRepo.CommitTree(tb, treeID, message)
-
- return blobID, treeID, commitID
-}
diff --git a/internal/testgit/repo_make_many_objects_history.go b/internal/testgit/repo_make_many_objects_history.go
deleted file mode 100644
index f71ead2c..00000000
--- a/internal/testgit/repo_make_many_objects_history.go
+++ /dev/null
@@ -1,83 +0,0 @@
-package testgit
-
-import (
- "fmt"
- "strings"
- "testing"
-
- objectid "codeberg.org/lindenii/furgit/object/id"
-)
-
-const (
- manyObjectsMainCommits = 640
- manyObjectsDevCommits = 220
-)
-
-// MakeManyObjectsHistory creates a large commit graph.
-func (testRepo *TestRepo) MakeManyObjectsHistory(tb testing.TB) {
- tb.Helper()
-
- var (
- mainTip objectid.ObjectID
- devTip objectid.ObjectID
- hasMain bool
- hasDev bool
- )
-
- for i := range manyObjectsMainCommits {
- tree := testRepo.makeManyObjectsTree(tb, "main", i, 3)
-
- var commit objectid.ObjectID
- if hasMain {
- commit = testRepo.CommitTree(tb, tree, fmt.Sprintf("main-%04d", i), mainTip)
- } else {
- commit = testRepo.CommitTree(tb, tree, fmt.Sprintf("main-%04d", i))
- hasMain = true
- }
-
- mainTip = commit
- if i%64 == 0 {
- testRepo.TagAnnotated(tb, fmt.Sprintf("main-v%04d", i), mainTip, fmt.Sprintf("tag-main-%04d", i))
- }
- }
-
- devTip = mainTip
- hasDev = true
-
- for i := range manyObjectsDevCommits {
- tree := testRepo.makeManyObjectsTree(tb, "dev", i, 4)
- commit := testRepo.CommitTree(tb, tree, fmt.Sprintf("dev-%04d", i), devTip)
- devTip = commit
-
- if i > 0 && i%55 == 0 {
- mergeTree := testRepo.makeManyObjectsTree(tb, "merge", i, 2)
-
- mainTip = testRepo.CommitTree(tb, mergeTree, fmt.Sprintf("merge-%04d", i), mainTip, devTip)
- if i%110 == 0 {
- testRepo.TagAnnotated(tb, fmt.Sprintf("merge-v%04d", i), mainTip, fmt.Sprintf("tag-merge-%04d", i))
- }
- }
- }
-
- if hasMain {
- testRepo.UpdateRef(tb, "refs/heads/main", mainTip)
- }
-
- if hasDev {
- testRepo.UpdateRef(tb, "refs/heads/dev", devTip)
- }
-}
-
-// makeManyObjectsTree builds one synthetic tree with fanout blobs.
-func (testRepo *TestRepo) makeManyObjectsTree(tb testing.TB, prefix string, i int, files int) objectid.ObjectID {
- tb.Helper()
-
- lines := make([]string, 0, files)
- for j := range files {
- body := fmt.Appendf(nil, "%s-%04d-%02d\n%s\n", prefix, i, j, strings.Repeat("x", 160+(i+j)%96))
- blobID := testRepo.HashObject(tb, "blob", body)
- lines = append(lines, fmt.Sprintf("100644 blob %s\t%s_%04d_%02d.txt\n", blobID.String(), prefix, i, j))
- }
-
- return testRepo.Mktree(tb, strings.Join(lines, ""))
-}
diff --git a/internal/testgit/repo_make_single_file_tree.go b/internal/testgit/repo_make_single_file_tree.go
deleted file mode 100644
index ace98e8a..00000000
--- a/internal/testgit/repo_make_single_file_tree.go
+++ /dev/null
@@ -1,18 +0,0 @@
-package testgit
-
-import (
- "fmt"
- "testing"
-
- objectid "codeberg.org/lindenii/furgit/object/id"
-)
-
-// MakeSingleFileTree writes one blob and one tree entry for it and returns (blobID, treeID).
-func (testRepo *TestRepo) MakeSingleFileTree(tb testing.TB, fileName string, fileContent []byte) (objectid.ObjectID, objectid.ObjectID) {
- tb.Helper()
- blobID := testRepo.HashObject(tb, "blob", fileContent)
- treeInput := fmt.Sprintf("100644 blob %s\t%s\n", blobID.String(), fileName)
- treeID := testRepo.Mktree(tb, treeInput)
-
- return blobID, treeID
-}
diff --git a/internal/testgit/repo_mktree.go b/internal/testgit/repo_mktree.go
deleted file mode 100644
index 893d211e..00000000
--- a/internal/testgit/repo_mktree.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package testgit
-
-import (
- "testing"
-
- objectid "codeberg.org/lindenii/furgit/object/id"
-)
-
-// Mktree creates a tree from textual mktree input and returns its ID.
-func (testRepo *TestRepo) Mktree(tb testing.TB, input string) objectid.ObjectID {
- tb.Helper()
- hex := testRepo.RunInput(tb, []byte(input), "mktree")
-
- id, err := objectid.ParseHex(testRepo.algo, hex)
- if err != nil {
- tb.Fatalf("parse mktree output %q: %v", hex, err)
- }
-
- return id
-}
diff --git a/internal/testgit/repo_new.go b/internal/testgit/repo_new.go
deleted file mode 100644
index b7c9968b..00000000
--- a/internal/testgit/repo_new.go
+++ /dev/null
@@ -1,64 +0,0 @@
-package testgit
-
-import (
- "os"
- "testing"
-
- objectid "codeberg.org/lindenii/furgit/object/id"
-)
-
-// RepoOptions controls git-init options for test repositories.
-type RepoOptions struct {
- // ObjectFormat is the object ID algorithm used for repository objects.
- ObjectFormat objectid.Algorithm
- // Bare selects whether the repository is initialized as bare.
- Bare bool
- // RefFormat selects the git ref storage format (for example "files" or
- // "reftable"). Empty means git's default format.
- RefFormat string
-}
-
-// NewRepo creates a temporary repository initialized with the requested options.
-func NewRepo(tb testing.TB, opts RepoOptions) *TestRepo {
- tb.Helper()
-
- algo := opts.ObjectFormat
- if algo.Size() == 0 {
- tb.Fatalf("invalid algorithm: %v", algo)
- }
-
- dir := tb.TempDir()
-
- testRepo := &TestRepo{
- dir: dir,
- algo: algo,
- env: defaultEnv(),
- }
-
- args := []string{"init", "--object-format=" + algo.String()}
- if opts.Bare {
- args = append(args, "--bare")
- }
-
- if opts.RefFormat != "" {
- args = append(args, "--ref-format="+opts.RefFormat)
- }
-
- args = append(args, dir)
- testRepo.runBytes(tb, nil, "", args...)
-
- return testRepo
-}
-
-func defaultEnv() []string {
- return append(os.Environ(),
- "GIT_CONFIG_GLOBAL=/dev/null",
- "GIT_CONFIG_SYSTEM=/dev/null",
- "GIT_AUTHOR_NAME=Test Author",
- "GIT_AUTHOR_EMAIL=test@example.org",
- "GIT_COMMITTER_NAME=Test Committer",
- "GIT_COMMITTER_EMAIL=committer@example.org",
- "GIT_AUTHOR_DATE=1234567890 +0000",
- "GIT_COMMITTER_DATE=1234567890 +0000",
- )
-}
diff --git a/internal/testgit/repo_open_commit_graph.go b/internal/testgit/repo_open_commit_graph.go
deleted file mode 100644
index 4db7261b..00000000
--- a/internal/testgit/repo_open_commit_graph.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package testgit
-
-import (
- "testing"
-
- commitgraphread "codeberg.org/lindenii/furgit/format/commitgraph/read"
-)
-
-// OpenCommitGraph opens the repository commit-graph and registers cleanup on
-// the caller.
-func (testRepo *TestRepo) OpenCommitGraph(tb testing.TB) *commitgraphread.Reader {
- tb.Helper()
-
- objectsRoot := testRepo.OpenObjectsRoot(tb)
-
- graph, err := commitgraphread.Open(objectsRoot, testRepo.Algorithm(), commitgraphread.OpenSingle)
- if err != nil {
- tb.Fatalf("commitgraphread.Open: %v", err)
- }
-
- tb.Cleanup(func() {
- _ = graph.Close()
- })
-
- return graph
-}
diff --git a/internal/testgit/repo_open_object_store.go b/internal/testgit/repo_open_object_store.go
deleted file mode 100644
index 42dc370c..00000000
--- a/internal/testgit/repo_open_object_store.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package testgit
-
-import (
- "testing"
-
- objectstore "codeberg.org/lindenii/furgit/object/store"
- "codeberg.org/lindenii/furgit/repository"
-)
-
-// OpenObjectStore opens the repository object store and registers cleanup on
-// the caller.
-//
-//nolint:ireturn
-func (testRepo *TestRepo) OpenObjectStore(tb testing.TB) objectstore.Reader {
- tb.Helper()
-
- root := testRepo.OpenGitRoot(tb)
-
- repo, err := repository.Open(root)
- if err != nil {
- tb.Fatalf("repository.Open: %v", err)
- }
-
- tb.Cleanup(func() {
- _ = repo.Close()
- })
-
- return repo.Objects()
-}
diff --git a/internal/testgit/repo_open_repository.go b/internal/testgit/repo_open_repository.go
deleted file mode 100644
index fbc98383..00000000
--- a/internal/testgit/repo_open_repository.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package testgit
-
-import (
- "testing"
-
- "codeberg.org/lindenii/furgit/repository"
-)
-
-// OpenRepository opens the repository and registers cleanup on the caller.
-func (testRepo *TestRepo) OpenRepository(tb testing.TB) *repository.Repository {
- tb.Helper()
-
- root := testRepo.OpenGitRoot(tb)
-
- repo, err := repository.Open(root)
- if err != nil {
- tb.Fatalf("repository.Open: %v", err)
- }
-
- tb.Cleanup(func() {
- _ = repo.Close()
- })
-
- return repo
-}
diff --git a/internal/testgit/repo_open_root.go b/internal/testgit/repo_open_root.go
deleted file mode 100644
index 4530c604..00000000
--- a/internal/testgit/repo_open_root.go
+++ /dev/null
@@ -1,87 +0,0 @@
-package testgit
-
-import (
- "errors"
- "os"
- "testing"
-)
-
-// OpenRoot opens the repository root directory and registers cleanup on the
-// caller.
-func (testRepo *TestRepo) OpenRoot(tb testing.TB) *os.Root {
- tb.Helper()
-
- root, err := os.OpenRoot(testRepo.dir)
- if err != nil {
- tb.Fatalf("os.OpenRoot: %v", err)
- }
-
- tb.Cleanup(func() {
- _ = root.Close()
- })
-
- return root
-}
-
-// OpenGitRoot opens the repository gitdir and registers cleanup on the caller.
-//
-// For bare repositories, this is the repository root itself. For non-bare
-// repositories, this is the .git directory under the worktree root.
-func (testRepo *TestRepo) OpenGitRoot(tb testing.TB) *os.Root {
- tb.Helper()
-
- repoRoot := testRepo.OpenRoot(tb)
-
- gitRoot, err := repoRoot.OpenRoot(".git")
- if err == nil {
- tb.Cleanup(func() {
- _ = gitRoot.Close()
- })
-
- return gitRoot
- }
-
- if !errors.Is(err, os.ErrNotExist) {
- tb.Fatalf("OpenRoot(.git): %v", err)
- }
-
- return repoRoot
-}
-
-// OpenObjectsRoot opens the objects directory and registers cleanup on the
-// caller.
-func (testRepo *TestRepo) OpenObjectsRoot(tb testing.TB) *os.Root {
- tb.Helper()
-
- gitRoot := testRepo.OpenGitRoot(tb)
-
- objectsRoot, err := gitRoot.OpenRoot("objects")
- if err != nil {
- tb.Fatalf("OpenRoot(objects): %v", err)
- }
-
- tb.Cleanup(func() {
- _ = objectsRoot.Close()
- })
-
- return objectsRoot
-}
-
-// OpenPackRoot opens the objects/pack directory and registers cleanup on the
-// caller.
-func (testRepo *TestRepo) OpenPackRoot(tb testing.TB) *os.Root {
- tb.Helper()
-
- objectsRoot := testRepo.OpenObjectsRoot(tb)
-
- packRoot, err := objectsRoot.OpenRoot("pack")
- if err != nil {
- tb.Fatalf("OpenRoot(pack): %v", err)
- }
-
- tb.Cleanup(func() {
- _ = packRoot.Close()
- })
-
- return packRoot
-}
diff --git a/internal/testgit/repo_pack_objects_is_thin.go b/internal/testgit/repo_pack_objects_is_thin.go
deleted file mode 100644
index c37b6d27..00000000
--- a/internal/testgit/repo_pack_objects_is_thin.go
+++ /dev/null
@@ -1,77 +0,0 @@
-package testgit
-
-import (
- "os/exec"
- "strings"
- "testing"
-)
-
-// PackObjectsIsThin reports whether git emits one thin pack for the given revs.
-//
-// It streams `git pack-objects --stdout --revs --thin` into `git index-pack
-// --stdin` in one scratch bare repository. A failure in index-pack due to
-// unresolved deltas is treated as confirmation that the emitted pack is thin.
-func (testRepo *TestRepo) PackObjectsIsThin(tb testing.TB, revs []string) bool {
- tb.Helper()
-
- scratch := NewRepo(tb, RepoOptions{ObjectFormat: testRepo.algo, Bare: true})
-
- packArgs := []string{"pack-objects", "--stdout", "--revs", "--thin"}
- //nolint:noctx
- packCmd := exec.Command("git", packArgs...) //#nosec G204
- packCmd.Dir = testRepo.dir
- packCmd.Env = testRepo.env
- packCmd.Stdin = strings.NewReader(strings.Join(revs, "\n") + "\n")
- packStderr := &strings.Builder{}
- packCmd.Stderr = packStderr
-
- packStdout, err := packCmd.StdoutPipe()
- if err != nil {
- tb.Fatalf("git %v stdout pipe: %v", packArgs, err)
- }
-
- indexArgs := []string{"index-pack", "--stdin"}
- //nolint:noctx
- indexCmd := exec.Command("git", indexArgs...) //#nosec G204
- indexCmd.Dir = scratch.dir
- indexCmd.Env = scratch.env
- indexCmd.Stdin = packStdout
- indexStderr := &strings.Builder{}
- indexCmd.Stderr = indexStderr
-
- err = indexCmd.Start()
- if err != nil {
- tb.Fatalf("git %v start failed: %v", indexArgs, err)
- }
-
- err = packCmd.Start()
- if err != nil {
- _ = indexCmd.Process.Kill()
- _ = indexCmd.Wait()
-
- tb.Fatalf("git %v start failed: %v", packArgs, err)
- }
-
- packErr := packCmd.Wait()
- if packErr != nil {
- tb.Fatalf("git %v failed: %v\n%s", packArgs, packErr, packStderr.String())
- }
-
- indexErr := indexCmd.Wait()
- if indexErr == nil {
- return false
- }
-
- stderr := strings.ToLower(indexStderr.String())
- if strings.Contains(stderr, "unresolved") && strings.Contains(stderr, "delta") {
- return true
- }
-
- if strings.Contains(stderr, "missing") && strings.Contains(stderr, "base") {
- return true
- }
-
- tb.Fatalf("git %v failed unexpectedly: %v\n%s", indexArgs, indexErr, indexStderr.String())
-
- return false
-}
diff --git a/internal/testgit/repo_pack_objects_reader.go b/internal/testgit/repo_pack_objects_reader.go
deleted file mode 100644
index dc997514..00000000
--- a/internal/testgit/repo_pack_objects_reader.go
+++ /dev/null
@@ -1,94 +0,0 @@
-package testgit
-
-import (
- "fmt"
- "io"
- "os/exec"
- "strings"
- "sync"
- "testing"
-)
-
-// packObjectsReadCloser wraps a pipe reader and process wait fn.
-type packObjectsReadCloser struct {
- reader io.ReadCloser
- wait func() error
- once sync.Once
-}
-
-// Read proxies reads to the wrapped reader.
-func (reader *packObjectsReadCloser) Read(dst []byte) (int, error) {
- return reader.reader.Read(dst)
-}
-
-// Close closes the stream and waits for the underlying process.
-func (reader *packObjectsReadCloser) Close() error {
- var out error
-
- reader.once.Do(func() {
- errClose := reader.reader.Close()
- errWait := reader.wait()
-
- if errClose != nil {
- out = errClose
-
- return
- }
-
- out = errWait
- })
-
- return out
-}
-
-// PackObjectsReader streams `git pack-objects --stdout --revs` output.
-func (testRepo *TestRepo) PackObjectsReader(tb testing.TB, revs []string, thin bool) io.ReadCloser {
- tb.Helper()
-
- args := []string{"pack-objects", "--stdout", "--revs"}
- if thin {
- args = append(args, "--thin")
- }
-
- //nolint:noctx
- cmd := exec.Command("git", args...) //#nosec G204
- cmd.Dir = testRepo.dir
- cmd.Env = testRepo.env
- cmd.Stdin = strings.NewReader(strings.Join(revs, "\n") + "\n")
-
- pr, pw := io.Pipe()
- cmd.Stdout = pw
- stderr := &strings.Builder{}
- cmd.Stderr = stderr
-
- waitDone := make(chan error, 1)
-
- go func() {
- err := cmd.Start()
- if err != nil {
- _ = pw.CloseWithError(fmt.Errorf("git %v start failed: %w", args, err))
-
- waitDone <- nil
-
- return
- }
-
- err = cmd.Wait()
- if err != nil {
- _ = pw.CloseWithError(fmt.Errorf("git %v failed: %w\n%s", args, err, stderr.String()))
- } else {
- _ = pw.Close()
- }
-
- waitDone <- nil
- }()
-
- return &packObjectsReadCloser{
- reader: pr,
- wait: func() error {
- <-waitDone
-
- return nil
- },
- }
-}
diff --git a/internal/testgit/repo_properties.go b/internal/testgit/repo_properties.go
deleted file mode 100644
index d46e9030..00000000
--- a/internal/testgit/repo_properties.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package testgit
-
-import objectid "codeberg.org/lindenii/furgit/object/id"
-
-// Algorithm returns the object ID algorithm configured for this repository.
-func (testRepo *TestRepo) Algorithm() objectid.Algorithm {
- return testRepo.algo
-}
-
-// Env returns a copy of the environment used for git subprocesses.
-func (testRepo *TestRepo) Env() []string {
- return append([]string(nil), testRepo.env...)
-}
-
-// DirButYouShouldReallyNotUseThisYouShouldReallyConsiderUsingAProperCapabilityInterfaceInsteadAndIAmKeepingThisMethodIntentionallyLongToAnnoyYou returns the git dir of a repo.
-// Consider using a properly capability interface such as
-// os.Root instead; all uses of ambient path authority must be justified.
-func (testRepo *TestRepo) DirButYouShouldReallyNotUseThisYouShouldReallyConsiderUsingAProperCapabilityInterfaceInsteadAndIAmKeepingThisMethodIntentionallyLongToAnnoyYou() string {
- return testRepo.dir
-}
diff --git a/internal/testgit/repo_refs.go b/internal/testgit/repo_refs.go
deleted file mode 100644
index a92e1658..00000000
--- a/internal/testgit/repo_refs.go
+++ /dev/null
@@ -1,48 +0,0 @@
-package testgit
-
-import (
- "strings"
- "testing"
-
- objectid "codeberg.org/lindenii/furgit/object/id"
-)
-
-// UpdateRef updates a ref to point at id.
-func (testRepo *TestRepo) UpdateRef(tb testing.TB, name string, id objectid.ObjectID) {
- tb.Helper()
- testRepo.Run(tb, "update-ref", name, id.String())
-}
-
-// DeleteRef deletes a ref.
-func (testRepo *TestRepo) DeleteRef(tb testing.TB, name string) {
- tb.Helper()
- testRepo.Run(tb, "update-ref", "-d", name)
-}
-
-// SymbolicRef sets a symbolic reference target.
-func (testRepo *TestRepo) SymbolicRef(tb testing.TB, name, target string) {
- tb.Helper()
- testRepo.Run(tb, "symbolic-ref", name, target)
-}
-
-// PackRefs runs git pack-refs with args.
-func (testRepo *TestRepo) PackRefs(tb testing.TB, args ...string) {
- tb.Helper()
-
- cmd := append([]string{"pack-refs"}, args...)
- testRepo.Run(tb, cmd...)
-}
-
-// ShowRef returns lines from git show-ref output.
-func (testRepo *TestRepo) ShowRef(tb testing.TB, args ...string) []string {
- tb.Helper()
-
- cmd := append([]string{"show-ref"}, args...)
-
- out := testRepo.Run(tb, cmd...)
- if strings.TrimSpace(out) == "" {
- return nil
- }
-
- return strings.Split(strings.TrimSpace(out), "\n")
-}
diff --git a/internal/testgit/repo_remove_loose_object.go b/internal/testgit/repo_remove_loose_object.go
deleted file mode 100644
index 345d9db7..00000000
--- a/internal/testgit/repo_remove_loose_object.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package testgit
-
-import (
- "fmt"
- "testing"
-
- objectid "codeberg.org/lindenii/furgit/object/id"
-)
-
-// RemoveLooseObject removes one loose object file from the repository.
-func (testRepo *TestRepo) RemoveLooseObject(tb testing.TB, id objectid.ObjectID) {
- tb.Helper()
-
- root := testRepo.OpenObjectsRoot(tb)
- hex := id.String()
- path := fmt.Sprintf("%s/%s", hex[:2], hex[2:])
-
- err := root.Remove(path)
- if err != nil {
- tb.Fatalf("remove loose object %s: %v", id, err)
- }
-}
diff --git a/internal/testgit/repo_repack.go b/internal/testgit/repo_repack.go
deleted file mode 100644
index 7773ac13..00000000
--- a/internal/testgit/repo_repack.go
+++ /dev/null
@@ -1,13 +0,0 @@
-package testgit
-
-import "testing"
-
-// Repack runs "git repack" with args in the repository.
-func (testRepo *TestRepo) Repack(tb testing.TB, args ...string) {
- tb.Helper()
-
- cmdArgs := make([]string, 0, len(args)+1)
- cmdArgs = append(cmdArgs, "repack")
- cmdArgs = append(cmdArgs, args...)
- _ = testRepo.Run(tb, cmdArgs...)
-}
diff --git a/internal/testgit/repo_rev_list.go b/internal/testgit/repo_rev_list.go
deleted file mode 100644
index 6b0c4f76..00000000
--- a/internal/testgit/repo_rev_list.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package testgit
-
-import (
- "strings"
- "testing"
-
- objectid "codeberg.org/lindenii/furgit/object/id"
-)
-
-// RevList runs "git rev-list" with args and parses one object ID per line.
-func (testRepo *TestRepo) RevList(tb testing.TB, args ...string) []objectid.ObjectID {
- tb.Helper()
-
- cmdArgs := make([]string, 0, len(args)+1)
- cmdArgs = append(cmdArgs, "rev-list")
- cmdArgs = append(cmdArgs, args...)
- out := testRepo.Run(tb, cmdArgs...)
-
- lines := strings.Split(strings.TrimSpace(out), "\n")
-
- outIDs := make([]objectid.ObjectID, 0, len(lines))
- for _, line := range lines {
- line = strings.TrimSpace(line)
- if line == "" {
- continue
- }
-
- id, err := objectid.ParseHex(testRepo.algo, line)
- if err != nil {
- tb.Fatalf("parse rev-list oid %q: %v", line, err)
- }
-
- outIDs = append(outIDs, id)
- }
-
- return outIDs
-}
diff --git a/internal/testgit/repo_rev_parse.go b/internal/testgit/repo_rev_parse.go
deleted file mode 100644
index fcdee605..00000000
--- a/internal/testgit/repo_rev_parse.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package testgit
-
-import (
- "testing"
-
- objectid "codeberg.org/lindenii/furgit/object/id"
-)
-
-// RevParse resolves rev expressions to object IDs.
-func (testRepo *TestRepo) RevParse(tb testing.TB, spec string) objectid.ObjectID {
- tb.Helper()
- hex := testRepo.Run(tb, "rev-parse", spec)
-
- id, err := objectid.ParseHex(testRepo.algo, hex)
- if err != nil {
- tb.Fatalf("parse rev-parse output %q: %v", hex, err)
- }
-
- return id
-}
diff --git a/internal/testgit/repo_run.go b/internal/testgit/repo_run.go
deleted file mode 100644
index 448b88f0..00000000
--- a/internal/testgit/repo_run.go
+++ /dev/null
@@ -1,95 +0,0 @@
-package testgit
-
-import (
- "bytes"
- "os/exec"
- "strings"
- "testing"
-)
-
-// Run executes git and returns trimmed textual output.
-func (testRepo *TestRepo) Run(tb testing.TB, args ...string) string {
- tb.Helper()
- out := testRepo.runBytes(tb, nil, testRepo.dir, args...)
-
- return strings.TrimSpace(string(out))
-}
-
-// RunBytes executes git and returns raw output bytes.
-func (testRepo *TestRepo) RunBytes(tb testing.TB, args ...string) []byte {
- tb.Helper()
-
- return testRepo.runBytes(tb, nil, testRepo.dir, args...)
-}
-
-// RunE executes git and returns trimmed textual output plus any command error.
-func (testRepo *TestRepo) RunE(tb testing.TB, args ...string) (string, error) {
- tb.Helper()
-
- out, err := testRepo.runBytesE(nil, testRepo.dir, args...)
-
- return strings.TrimSpace(string(out)), err
-}
-
-// RunInput executes git with stdin and returns trimmed textual output.
-func (testRepo *TestRepo) RunInput(tb testing.TB, stdin []byte, args ...string) string {
- tb.Helper()
- out := testRepo.runBytes(tb, stdin, testRepo.dir, args...)
-
- return strings.TrimSpace(string(out))
-}
-
-// RunInputBytes executes git with stdin and returns raw output bytes.
-func (testRepo *TestRepo) RunInputBytes(tb testing.TB, stdin []byte, args ...string) []byte {
- tb.Helper()
-
- return testRepo.runBytes(tb, stdin, testRepo.dir, args...)
-}
-
-func (testRepo *TestRepo) runBytes(tb testing.TB, stdin []byte, dir string, args ...string) []byte {
- tb.Helper()
-
- out, err := testRepo.runBytesE(stdin, dir, args...)
- if err != nil {
- tb.Fatalf("git %v failed: %v\n%s", args, err, out)
- }
-
- return out
-}
-
-func (testRepo *TestRepo) runBytesE(stdin []byte, dir string, args ...string) ([]byte, error) {
- return testRepo.runBytesWithEnvNoHelper(stdin, dir, testRepo.env, args...)
-}
-
-// runBytesWithEnv executes git using the supplied environment.
-func (testRepo *TestRepo) runBytesWithEnv(
- tb testing.TB,
- stdin []byte,
- dir string,
- env []string,
- args ...string,
-) ([]byte, error) {
- tb.Helper()
-
- return testRepo.runBytesWithEnvNoHelper(stdin, dir, env, args...)
-}
-
-// runBytesWithEnvNoHelper executes git using the supplied environment without
-// touching testing helper state.
-func (testRepo *TestRepo) runBytesWithEnvNoHelper(
- stdin []byte,
- dir string,
- env []string,
- args ...string,
-) ([]byte, error) {
- //nolint:noctx
- cmd := exec.Command("git", args...) //#nosec G204
- cmd.Dir = dir
-
- cmd.Env = env
- if stdin != nil {
- cmd.Stdin = bytes.NewReader(stdin)
- }
-
- return cmd.CombinedOutput()
-}
diff --git a/internal/testgit/repo_run_extra_files.go b/internal/testgit/repo_run_extra_files.go
deleted file mode 100644
index 4629c872..00000000
--- a/internal/testgit/repo_run_extra_files.go
+++ /dev/null
@@ -1,55 +0,0 @@
-package testgit
-
-import (
- "bytes"
- "context"
- "os"
- "os/exec"
- "testing"
-)
-
-// RunWithExtraFilesE executes git with inherited extra files and returns split
-// stdout/stderr plus any command error.
-func (testRepo *TestRepo) RunWithExtraFilesE(
- tb testing.TB,
- extraFiles []*os.File,
- args ...string,
-) ([]byte, []byte, error) {
- tb.Helper()
-
- return testRepo.RunWithExtraFilesEnvContextE(
- tb,
- context.Background(),
- nil,
- extraFiles,
- args...,
- )
-}
-
-// RunWithExtraFilesEnvContextE executes git with inherited extra files, extra
-// environment, and context cancellation, returning split stdout/stderr plus any
-// command error.
-func (testRepo *TestRepo) RunWithExtraFilesEnvContextE(
- tb testing.TB,
- ctx context.Context,
- extraEnv []string,
- extraFiles []*os.File,
- args ...string,
-) ([]byte, []byte, error) {
- tb.Helper()
-
- cmd := exec.CommandContext(ctx, "git", args...) //#nosec G204
- cmd.Dir = testRepo.dir
- cmd.Env = testRepo.env
- cmd.Env = append(cmd.Env, extraEnv...)
- cmd.ExtraFiles = append([]*os.File(nil), extraFiles...)
-
- var stdout, stderr bytes.Buffer
-
- cmd.Stdout = &stdout
- cmd.Stderr = &stderr
-
- err := cmd.Run()
-
- return stdout.Bytes(), stderr.Bytes(), err
-}
diff --git a/internal/testgit/repo_tag_annotated.go b/internal/testgit/repo_tag_annotated.go
deleted file mode 100644
index cf6e9b3d..00000000
--- a/internal/testgit/repo_tag_annotated.go
+++ /dev/null
@@ -1,15 +0,0 @@
-package testgit
-
-import (
- "testing"
-
- objectid "codeberg.org/lindenii/furgit/object/id"
-)
-
-// TagAnnotated creates an annotated tag object and returns the resulting tag object ID.
-func (testRepo *TestRepo) TagAnnotated(tb testing.TB, name string, target objectid.ObjectID, message string) objectid.ObjectID {
- tb.Helper()
- testRepo.Run(tb, "tag", "-a", name, target.String(), "-m", message)
-
- return testRepo.RevParse(tb, "refs/tags/"+name)
-}