From 966cd6d893c0861a3037d2148d8f7d29c8d73887 Mon Sep 17 00:00:00 2001 From: John Murphy Date: Tue, 24 Feb 2026 13:34:23 +1100 Subject: [PATCH 1/2] fix: private gomod approach needs updating for mirror clones --- internal/strategy/gomod/private_fetcher.go | 42 +++++++++++++++------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/internal/strategy/gomod/private_fetcher.go b/internal/strategy/gomod/private_fetcher.go index 955a979..d309266 100644 --- a/internal/strategy/gomod/private_fetcher.go +++ b/internal/strategy/gomod/private_fetcher.go @@ -8,13 +8,17 @@ import ( "io" "io/fs" "log/slog" + "os" "os/exec" + "path/filepath" "sort" "strings" "time" "github.com/alecthomas/errors" + "golang.org/x/mod/module" "golang.org/x/mod/semver" + modzip "golang.org/x/mod/zip" "github.com/block/cachew/internal/gitclone" ) @@ -284,21 +288,35 @@ func (p *privateFetcher) generateMod(ctx context.Context, repo *gitclone.Reposit } func (p *privateFetcher) generateZip(ctx context.Context, repo *gitclone.Repository, modulePath, version string) (io.ReadSeekCloser, error) { - prefix := fmt.Sprintf("%s@%s/", modulePath, version) - output, err := gitclone.WithReadLockReturn(repo, func() ([]byte, error) { - // #nosec G204 - version and repo.Path() are controlled by this package, not user input - cmd := exec.CommandContext(ctx, "git", "-C", repo.Path(), "archive", - "--format=zip", - fmt.Sprintf("--prefix=%s", prefix), - version) - return cmd.CombinedOutput() - }) - + tmpDir, err := os.MkdirTemp("", "gomod-zip-*") if err != nil { - return nil, errors.Wrapf(err, "git archive failed: %s", string(output)) + return nil, errors.Wrap(err, "create temp dir") + } + defer os.RemoveAll(tmpDir) //nolint:errcheck + + cloneDir := filepath.Join(tmpDir, "repo") + + // Local clone from the mirror — git hardlinks objects by default. + // #nosec G204 - repo.Path() and cloneDir are controlled by us + cmd := exec.CommandContext(ctx, "git", "clone", repo.Path(), cloneDir) + if output, err := cmd.CombinedOutput(); err != nil { + return nil, errors.Wrapf(err, "git clone: %s", string(output)) + } + + // Checkout the requested version in the local clone. + // #nosec G204 - cloneDir and version are controlled by us + cmd = exec.CommandContext(ctx, "git", "-C", cloneDir, "checkout", version) + if output, err := cmd.CombinedOutput(); err != nil { + return nil, errors.Wrapf(err, "git checkout: %s", string(output)) + } + + var buf bytes.Buffer + m := module.Version{Path: modulePath, Version: version} + if err := modzip.CreateFromDir(&buf, m, cloneDir); err != nil { + return nil, errors.Wrap(err, "create module zip") } - return newReadSeekCloser(bytes.NewReader(output)), nil + return newReadSeekCloser(bytes.NewReader(buf.Bytes())), nil } type readSeekCloser struct { From 684c70c181329baa41a67ceccd7882dd06d502a2 Mon Sep 17 00:00:00 2001 From: John Murphy Date: Wed, 25 Feb 2026 08:11:34 +1100 Subject: [PATCH 2/2] fix: clone branch --- internal/strategy/gomod/private_fetcher.go | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/internal/strategy/gomod/private_fetcher.go b/internal/strategy/gomod/private_fetcher.go index d309266..6e02ad2 100644 --- a/internal/strategy/gomod/private_fetcher.go +++ b/internal/strategy/gomod/private_fetcher.go @@ -296,20 +296,13 @@ func (p *privateFetcher) generateZip(ctx context.Context, repo *gitclone.Reposit cloneDir := filepath.Join(tmpDir, "repo") - // Local clone from the mirror — git hardlinks objects by default. - // #nosec G204 - repo.Path() and cloneDir are controlled by us - cmd := exec.CommandContext(ctx, "git", "clone", repo.Path(), cloneDir) + // Local clone from the mirror at the requested version — git hardlinks objects by default. + // #nosec G204 - repo.Path(), version, and cloneDir are controlled by us + cmd := exec.CommandContext(ctx, "git", "clone", "--branch", version, repo.Path(), cloneDir) if output, err := cmd.CombinedOutput(); err != nil { return nil, errors.Wrapf(err, "git clone: %s", string(output)) } - // Checkout the requested version in the local clone. - // #nosec G204 - cloneDir and version are controlled by us - cmd = exec.CommandContext(ctx, "git", "-C", cloneDir, "checkout", version) - if output, err := cmd.CombinedOutput(); err != nil { - return nil, errors.Wrapf(err, "git checkout: %s", string(output)) - } - var buf bytes.Buffer m := module.Version{Path: modulePath, Version: version} if err := modzip.CreateFromDir(&buf, m, cloneDir); err != nil {