cmd/go/internal/modcmd: inject modfetch.Fetcher_ into DownloadModule

This commit continues the injection of the global Fetcher_ variable into
the various function calls that make use of it.  The purpose is to
prepare for the eventual removal of the global Fetcher_ variable and
eliminate global state within the modfetch package.

[git-generate]
cd src/cmd/go/internal/modcmd
rf '
 inject modfetch.Fetcher_ DownloadModule
'
cd ../modfetch
rf '
  add downloadZip:/f, err := tempFile.*/+0 _ = f \
    file, err := tempFile(ctx, filepath.Dir(zipfile), filepath.Base(zipfile), 0o666) \
    _ = file
'
rf '
  add downloadZip:/f.Close\(\)/+0 file.Close()
  rm downloadZip:/file.Close\(\)/-1
  add downloadZip:/os.Remove\(f.Name\(\)\)/+0 os.Remove(file.Name())
  rm downloadZip:/os.Remove\(file.Name\(\)\)/-1
'
sed -i '
  s/ f, err := tempFile(ctx, filepath.Dir(zipfile), filepath.Base(zipfile), 0o666)/file, err := tempFile(ctx, filepath.Dir(zipfile), filepath.Base(zipfile), 0o666)/
  s/err := repo.Zip(ctx, f, mod.Version)/err := repo.Zip(ctx, file, mod.Version)/
  s/if _, err := f.Seek(0, io.SeekStart); err != nil {/if _, err := file.Seek(0, io.SeekStart); err != nil {/
  s/if err := f.Truncate(0); err != nil {/if err := file.Truncate(0); err != nil {/
  s/fi, err := f.Stat()/fi, err := file.Stat()/
  s/z, err := zip.NewReader(f, fi.Size())/z, err := zip.NewReader(file, fi.Size())/
  s/for _, f := range z.File {/for _, zf := range z.File {/
  s/if !strings.HasPrefix(f.Name, prefix) {/if !strings.HasPrefix(zf.Name, prefix) {/
  s/return fmt.Errorf("zip for %s has unexpected file %s", prefix\[:len(prefix)-1\], f.Name)/return fmt.Errorf("zip for %s has unexpected file %s", prefix[:len(prefix)-1], zf.Name)/
  s/if err := f.Close(); err != nil {/if err := file.Close(); err != nil {/
  s/if err := hashZip(fetcher_, mod, f.Name(), ziphashfile); err != nil {/if err := hashZip(fetcher_, mod, file.Name(), ziphashfile); err != nil {/
  s/if err := os.Rename(f.Name(), zipfile); err != nil {/if err := os.Rename(file.Name(), zipfile); err != nil {/
' fetch.go
rf '
  rm downloadZip:/_ = file/-3 downloadZip:/_ = file/-2 downloadZip:/file, err := tempFile\(ctx, filepath.Dir\(zipfile\), filepath.Base\(zipfile\), 0o666\)/+1
'
rf '
  mv InfoFile.fetcher_ InfoFile.f
  mv InfoFile Fetcher.InfoFile
  mv GoModFile.fetcher_ GoModFile.f
  mv GoModFile Fetcher.GoModFile
  mv GoModSum.fetcher_ GoModSum.f
  mv GoModSum Fetcher.GoModSum
  mv Download.fetcher_ Download.f
  mv Download Fetcher.Download
  mv download.fetcher_ download.f
  mv download Fetcher.download
  mv DownloadZip.fetcher_ DownloadZip.f
  mv DownloadZip Fetcher.DownloadZip
  mv downloadZip.fetcher_ downloadZip.f
  mv downloadZip Fetcher.downloadZip
  mv checkMod.fetcher_ checkMod.f
  mv checkMod Fetcher.checkMod
  mv hashZip.fetcher_ hashZip.f
'

Change-Id: I1d2e09b8523f5ef2be04b91d858d98fb79c0a771
Reviewed-on: https://go-review.googlesource.com/c/go/+/724242
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Matloob <matloob@google.com>
Reviewed-by: Michael Matloob <matloob@golang.org>
This commit is contained in:
Ian Alexander 2025-11-24 16:53:11 -05:00
parent e96094402d
commit 07b10e97d6
7 changed files with 47 additions and 47 deletions

View file

@ -366,25 +366,25 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
// leaving the results (including any error) in m itself.
func DownloadModule(ctx context.Context, m *ModuleJSON) error {
var err error
_, file, err := modfetch.InfoFile(ctx, m.Path, m.Version)
_, file, err := modfetch.Fetcher_.InfoFile(ctx, m.Path, m.Version)
if err != nil {
return err
}
m.Info = file
m.GoMod, err = modfetch.GoModFile(ctx, m.Path, m.Version)
m.GoMod, err = modfetch.Fetcher_.GoModFile(ctx, m.Path, m.Version)
if err != nil {
return err
}
m.GoModSum, err = modfetch.GoModSum(ctx, m.Path, m.Version)
m.GoModSum, err = modfetch.Fetcher_.GoModSum(ctx, m.Path, m.Version)
if err != nil {
return err
}
mod := module.Version{Path: m.Path, Version: m.Version}
m.Zip, err = modfetch.DownloadZip(ctx, mod)
m.Zip, err = modfetch.Fetcher_.DownloadZip(ctx, mod)
if err != nil {
return err
}
m.Sum = modfetch.Sum(ctx, mod)
m.Dir, err = modfetch.Download(ctx, mod)
m.Dir, err = modfetch.Fetcher_.Download(ctx, mod)
return err
}

View file

@ -341,7 +341,7 @@ func (r *cachingRepo) Zip(ctx context.Context, dst io.Writer, version string) er
// InfoFile is like Lookup(ctx, path).Stat(version) but also returns the name of the file
// containing the cached information.
func InfoFile(ctx context.Context, path, version string) (*RevInfo, string, error) {
func (f *Fetcher) InfoFile(ctx context.Context, path, version string) (*RevInfo, string, error) {
if !gover.ModIsValid(path, version) {
return nil, "", fmt.Errorf("invalid version %q", version)
}
@ -353,7 +353,7 @@ func InfoFile(ctx context.Context, path, version string) (*RevInfo, string, erro
var info *RevInfo
var err2info map[error]*RevInfo
err := TryProxies(func(proxy string) error {
i, err := Fetcher_.Lookup(ctx, proxy, path).Stat(ctx, version)
i, err := f.Lookup(ctx, proxy, path).Stat(ctx, version)
if err == nil {
info = i
} else {
@ -416,11 +416,11 @@ func (f *Fetcher) GoMod(ctx context.Context, path, rev string) ([]byte, error) {
// GoModFile is like GoMod but returns the name of the file containing
// the cached information.
func GoModFile(ctx context.Context, path, version string) (string, error) {
func (f *Fetcher) GoModFile(ctx context.Context, path, version string) (string, error) {
if !gover.ModIsValid(path, version) {
return "", fmt.Errorf("invalid version %q", version)
}
if _, err := Fetcher_.GoMod(ctx, path, version); err != nil {
if _, err := f.GoMod(ctx, path, version); err != nil {
return "", err
}
// GoMod should have populated the disk cache for us.
@ -433,11 +433,11 @@ func GoModFile(ctx context.Context, path, version string) (string, error) {
// GoModSum returns the go.sum entry for the module version's go.mod file.
// (That is, it returns the entry listed in go.sum as "path version/go.mod".)
func GoModSum(ctx context.Context, path, version string) (string, error) {
func (f *Fetcher) GoModSum(ctx context.Context, path, version string) (string, error) {
if !gover.ModIsValid(path, version) {
return "", fmt.Errorf("invalid version %q", version)
}
data, err := Fetcher_.GoMod(ctx, path, version)
data, err := f.GoMod(ctx, path, version)
if err != nil {
return "", err
}

View file

@ -40,7 +40,7 @@ var ErrToolchain = errors.New("internal error: invalid operation on toolchain mo
// Download downloads the specific module version to the
// local download cache and returns the name of the directory
// corresponding to the root of the module's file tree.
func Download(ctx context.Context, mod module.Version) (dir string, err error) {
func (f *Fetcher) Download(ctx context.Context, mod module.Version) (dir string, err error) {
if gover.IsToolchain(mod.Path) {
return "", ErrToolchain
}
@ -49,12 +49,12 @@ func Download(ctx context.Context, mod module.Version) (dir string, err error) {
}
// The par.Cache here avoids duplicate work.
return Fetcher_.downloadCache.Do(mod, func() (string, error) {
dir, err := download(ctx, mod)
return f.downloadCache.Do(mod, func() (string, error) {
dir, err := f.download(ctx, mod)
if err != nil {
return "", err
}
checkMod(ctx, mod)
f.checkMod(ctx, mod)
// If go.mod exists (not an old legacy module), check version is not too new.
if data, err := os.ReadFile(filepath.Join(dir, "go.mod")); err == nil {
@ -94,7 +94,7 @@ func (f *Fetcher) Unzip(ctx context.Context, mod module.Version, zipfile string)
})
}
func download(ctx context.Context, mod module.Version) (dir string, err error) {
func (f *Fetcher) download(ctx context.Context, mod module.Version) (dir string, err error) {
ctx, span := trace.StartSpan(ctx, "modfetch.download "+mod.String())
defer span.Done()
@ -109,7 +109,7 @@ func download(ctx context.Context, mod module.Version) (dir string, err error) {
// To avoid cluttering the cache with extraneous files,
// DownloadZip uses the same lockfile as Download.
// Invoke DownloadZip before locking the file.
zipfile, err := DownloadZip(ctx, mod)
zipfile, err := f.DownloadZip(ctx, mod)
if err != nil {
return "", err
}
@ -198,7 +198,7 @@ var downloadZipCache par.ErrCache[module.Version, string]
// DownloadZip downloads the specific module version to the
// local zip cache and returns the name of the zip file.
func DownloadZip(ctx context.Context, mod module.Version) (zipfile string, err error) {
func (f *Fetcher) DownloadZip(ctx context.Context, mod module.Version) (zipfile string, err error) {
// The par.Cache here avoids duplicate work.
return downloadZipCache.Do(mod, func() (string, error) {
zipfile, err := CachePath(ctx, mod, "zip")
@ -210,8 +210,8 @@ func DownloadZip(ctx context.Context, mod module.Version) (zipfile string, err e
// Return early if the zip and ziphash files exist.
if _, err := os.Stat(zipfile); err == nil {
if _, err := os.Stat(ziphashfile); err == nil {
if !HaveSum(Fetcher_, mod) {
checkMod(ctx, mod)
if !HaveSum(f, mod) {
f.checkMod(ctx, mod)
}
return zipfile, nil
}
@ -238,14 +238,14 @@ func DownloadZip(ctx context.Context, mod module.Version) (zipfile string, err e
}
defer unlock()
if err := downloadZip(ctx, mod, zipfile); err != nil {
if err := f.downloadZip(ctx, mod, zipfile); err != nil {
return "", err
}
return zipfile, nil
})
}
func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err error) {
func (f *Fetcher) downloadZip(ctx context.Context, mod module.Version, zipfile string) (err error) {
ctx, span := trace.StartSpan(ctx, "modfetch.downloadZip "+zipfile)
defer span.Done()
@ -281,7 +281,7 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e
// If the zip file exists, the ziphash file must have been deleted
// or lost after a file system crash. Re-hash the zip without downloading.
if zipExists {
return hashZip(mod, zipfile, ziphashfile)
return hashZip(f, mod, zipfile, ziphashfile)
}
// From here to the os.Rename call below is functionally almost equivalent to
@ -289,14 +289,14 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e
// contents of the file (by hashing it) before we commit it. Because the file
// is zip-compressed, we need an actual file — or at least an io.ReaderAt — to
// validate it: we can't just tee the stream as we write it.
f, err := tempFile(ctx, filepath.Dir(zipfile), filepath.Base(zipfile), 0o666)
file, err := tempFile(ctx, filepath.Dir(zipfile), filepath.Base(zipfile), 0o666)
if err != nil {
return err
}
defer func() {
if err != nil {
f.Close()
os.Remove(f.Name())
file.Close()
os.Remove(file.Name())
}
}()
@ -305,18 +305,18 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e
if unrecoverableErr != nil {
return unrecoverableErr
}
repo := Fetcher_.Lookup(ctx, proxy, mod.Path)
err := repo.Zip(ctx, f, mod.Version)
repo := f.Lookup(ctx, proxy, mod.Path)
err := repo.Zip(ctx, file, mod.Version)
if err != nil {
// Zip may have partially written to f before failing.
// (Perhaps the server crashed while sending the file?)
// Since we allow fallback on error in some cases, we need to fix up the
// file to be empty again for the next attempt.
if _, err := f.Seek(0, io.SeekStart); err != nil {
if _, err := file.Seek(0, io.SeekStart); err != nil {
unrecoverableErr = err
return err
}
if err := f.Truncate(0); err != nil {
if err := file.Truncate(0); err != nil {
unrecoverableErr = err
return err
}
@ -330,30 +330,30 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e
// Double-check that the paths within the zip file are well-formed.
//
// TODO(bcmills): There is a similar check within the Unzip function. Can we eliminate one?
fi, err := f.Stat()
fi, err := file.Stat()
if err != nil {
return err
}
z, err := zip.NewReader(f, fi.Size())
z, err := zip.NewReader(file, fi.Size())
if err != nil {
return err
}
prefix := mod.Path + "@" + mod.Version + "/"
for _, f := range z.File {
if !strings.HasPrefix(f.Name, prefix) {
return fmt.Errorf("zip for %s has unexpected file %s", prefix[:len(prefix)-1], f.Name)
for _, zf := range z.File {
if !strings.HasPrefix(zf.Name, prefix) {
return fmt.Errorf("zip for %s has unexpected file %s", prefix[:len(prefix)-1], zf.Name)
}
}
if err := f.Close(); err != nil {
if err := file.Close(); err != nil {
return err
}
// Hash the zip file and check the sum before renaming to the final location.
if err := hashZip(mod, f.Name(), ziphashfile); err != nil {
if err := hashZip(f, mod, file.Name(), ziphashfile); err != nil {
return err
}
if err := os.Rename(f.Name(), zipfile); err != nil {
if err := os.Rename(file.Name(), zipfile); err != nil {
return err
}
@ -367,12 +367,12 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e
//
// If the hash does not match go.sum (or the sumdb if enabled), hashZip returns
// an error and does not write ziphashfile.
func hashZip(mod module.Version, zipfile, ziphashfile string) (err error) {
func hashZip(f *Fetcher, mod module.Version, zipfile, ziphashfile string) (err error) {
hash, err := dirhash.HashZip(zipfile, dirhash.DefaultHash)
if err != nil {
return err
}
if err := checkModSum(Fetcher_, mod, hash); err != nil {
if err := checkModSum(f, mod, hash); err != nil {
return err
}
hf, err := lockedfile.Create(ziphashfile)
@ -702,7 +702,7 @@ func RecordedSum(mod module.Version) (sum string, ok bool) {
}
// checkMod checks the given module's checksum and Go version.
func checkMod(ctx context.Context, mod module.Version) {
func (f *Fetcher) checkMod(ctx context.Context, mod module.Version) {
// Do the file I/O before acquiring the go.sum lock.
ziphash, err := CachePath(ctx, mod, "ziphash")
if err != nil {
@ -719,7 +719,7 @@ func checkMod(ctx context.Context, mod module.Version) {
if err != nil {
base.Fatalf("verifying %v", module.VersionError(mod, err))
}
err = hashZip(mod, zip, ziphash)
err = hashZip(f, mod, zip, ziphash)
if err != nil {
base.Fatalf("verifying %v", module.VersionError(mod, err))
}
@ -730,7 +730,7 @@ func checkMod(ctx context.Context, mod module.Version) {
base.Fatalf("verifying %v", module.VersionError(mod, fmt.Errorf("unexpected ziphash: %q", h)))
}
if err := checkModSum(Fetcher_, mod, h); err != nil {
if err := checkModSum(f, mod, h); err != nil {
base.Fatalf("%s", err)
}
}

View file

@ -119,7 +119,7 @@ func TestZipSums(t *testing.T) {
t.Parallel()
ctx := context.Background()
zipPath, err := modfetch.DownloadZip(ctx, test.m)
zipPath, err := modfetch.Fetcher_.DownloadZip(ctx, test.m)
if err != nil {
if *updateTestData {
t.Logf("%s: could not download module: %s (will remove from testdata)", test.m, err)

View file

@ -1792,7 +1792,7 @@ func (r *resolver) checkPackageProblems(loaderstate *modload.State, ctx context.
continue
}
r.work.Add(func() {
if _, err := modfetch.DownloadZip(ctx, mActual); err != nil {
if _, err := modfetch.Fetcher_.DownloadZip(ctx, mActual); err != nil {
verb := "upgraded"
if gover.ModCompare(m.Path, m.Version, old.Version) < 0 {
verb = "downgraded"

View file

@ -821,7 +821,7 @@ func fetch(loaderstate *State, ctx context.Context, mod module.Version) (dir str
return "", false, module.VersionError(mod, &sumMissingError{})
}
dir, err = modfetch.Download(ctx, mod)
dir, err = modfetch.Fetcher_.Download(ctx, mod)
return dir, false, err
}

View file

@ -360,7 +360,7 @@ func Exec(s *modload.State, gotoolchain string) {
Path: gotoolchainModule,
Version: gotoolchainVersion + "-" + gotoolchain + "." + runtime.GOOS + "-" + runtime.GOARCH,
}
dir, err := modfetch.Download(context.Background(), m)
dir, err := modfetch.Fetcher_.Download(context.Background(), m)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
toolVers := gover.FromToolchain(gotoolchain)