From dfe20bce3551f4b53f97362b14bd55a7ba0e0de0 Mon Sep 17 00:00:00 2001 From: Runxi Yu Date: Thu, 5 Mar 2026 17:01:31 +0800 Subject: testgit: Add pack object reader and many object maker --- internal/testgit/repo_pack_objects_reader.go | 94 ++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 internal/testgit/repo_pack_objects_reader.go (limited to 'internal/testgit/repo_pack_objects_reader.go') diff --git a/internal/testgit/repo_pack_objects_reader.go b/internal/testgit/repo_pack_objects_reader.go new file mode 100644 index 00000000..dc997514 --- /dev/null +++ b/internal/testgit/repo_pack_objects_reader.go @@ -0,0 +1,94 @@ +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 + }, + } +} -- cgit v1.3.1-10-gc9f91