diff options
| author | 2026-04-02 06:23:30 +0000 | |
|---|---|---|
| committer | 2026-04-02 06:28:39 +0000 | |
| commit | a041d523de389b65b98a5373a8034041db2a8d83 (patch) | |
| tree | 7b423dc735f463be616045f2c3c2095a7737aca7 /internal/testgit | |
| parent | research: Add dynamic pack resources (diff) | |
| signature | No signature | |
*: Remove
Diffstat (limited to 'internal/testgit')
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) -} |
