// Consider starting this as a background goroutine and retrieving the result
// asynchronously when we're actually ready to build the package, or when we
// actually need to evaluate whether the package's metadata is stale.
- p.setBuildInfo(ctx, opts.AutoVCS)
+ p.setBuildInfo(ctx, loaderstate.Fetcher(), opts.AutoVCS)
}
// If cgo is not enabled, ignore cgo supporting sources
//
// Note that the GoVersion field is not set here to avoid encoding it twice.
// It is stored separately in the binary, mostly for historical reasons.
-func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) {
+func (p *Package) setBuildInfo(ctx context.Context, f *modfetch.Fetcher, autoVCS bool) {
setPkgErrorf := func(format string, args ...any) {
if p.Error == nil {
p.Error = &PackageError{Err: fmt.Errorf(format, args...)}
if !ok {
goto omitVCS
}
- repo := modfetch.LookupLocal(ctx, codeRoot, p.Module.Path, repoDir)
+ repo := f.LookupLocal(ctx, codeRoot, p.Module.Path, repoDir)
revInfo, err := repo.Stat(ctx, st.Revision)
if err != nil {
goto omitVCS
// pmain won't have buildinfo set (since we copy it from the package under test). If the default GODEBUG
// used for the package under test is different from that of the test main, the BuildInfo assigned above from the package
// under test incorrect for the test main package. Either set or correct pmain's build info.
- pmain.setBuildInfo(ctx, opts.AutoVCS)
+ pmain.setBuildInfo(ctx, loaderstate.Fetcher(), opts.AutoVCS)
}
// The generated main also imports testing, regexp, and os.
if err != nil {
return nil, err
}
- if err := os.MkdirAll(filepath.Dir(path), 0777); err != nil {
+ if err := os.MkdirAll(filepath.Dir(path), 0o777); err != nil {
return nil, err
}
return lockedfile.MutexAt(path).Lock()
}
path := filepath.Join(cfg.GOMODCACHE, "cache", "lock")
- if err := os.MkdirAll(filepath.Dir(path), 0777); err != nil {
+ if err := os.MkdirAll(filepath.Dir(path), 0o777); err != nil {
return nil, fmt.Errorf("failed to create cache directory: %w", err)
}
once sync.Once
initRepo func(context.Context) (Repo, error)
r Repo
+ fetcher *Fetcher
}
-func newCachingRepo(ctx context.Context, path string, initRepo func(context.Context) (Repo, error)) *cachingRepo {
+func newCachingRepo(ctx context.Context, fetcher *Fetcher, path string, initRepo func(context.Context) (Repo, error)) *cachingRepo {
return &cachingRepo{
path: path,
initRepo: initRepo,
+ fetcher: fetcher,
}
}
v, err := r.versionsCache.Do(prefix, func() (*Versions, error) {
return r.repo(ctx).Versions(ctx, prefix)
})
-
if err != nil {
return nil, err
}
return r.repo(ctx).GoMod(ctx, version)
}
text, err := r.gomodCache.Do(version, func() ([]byte, error) {
- file, text, err := Fetcher_.readDiskGoMod(ctx, r.path, version)
+ file, text, err := r.fetcher.readDiskGoMod(ctx, r.path, version)
if err == nil {
// Note: readDiskGoMod already called checkGoMod.
return text, nil
text, err = r.repo(ctx).GoMod(ctx, version)
if err == nil {
- if err := checkGoMod(Fetcher_, r.path, version, text); err != nil {
+ if err := checkGoMod(r.fetcher, r.path, version, text); err != nil {
return text, err
}
if err := writeDiskGoMod(ctx, file, text); err != nil {
return nil
}
// Make sure directory for file exists.
- if err := os.MkdirAll(filepath.Dir(file), 0777); err != nil {
+ if err := os.MkdirAll(filepath.Dir(file), 0o777); err != nil {
return err
}
// Write the file to a temporary location, and then rename it to its final
// path to reduce the likelihood of a corrupt file existing at that final path.
- f, err := tempFile(ctx, filepath.Dir(file), filepath.Base(file), 0666)
+ f, err := tempFile(ctx, filepath.Dir(file), filepath.Base(file), 0o666)
if err != nil {
return err
}
statCacheErr = fmt.Errorf("could not create module cache: %w", err)
return
}
- if err := os.MkdirAll(cfg.GOMODCACHE, 0777); err != nil {
+ if err := os.MkdirAll(cfg.GOMODCACHE, 0o777); err != nil {
statCacheErr = fmt.Errorf("could not create module cache: %w", err)
return
}
}
func testMain(m *testing.M) (err error) {
-
cfg.GOPROXY = "direct"
// The sum database is populated using a released version of the go command,
}()
cfg.GOMODCACHE = filepath.Join(dir, "modcache")
- if err := os.Mkdir(cfg.GOMODCACHE, 0755); err != nil {
+ if err := os.Mkdir(cfg.GOMODCACHE, 0o755); err != nil {
return err
}
func TestCodeRepo(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
tmpdir := t.TempDir()
+ fetcher := NewFetcher()
for _, tt := range codeRepoTests {
f := func(tt codeRepoTest) func(t *testing.T) {
}
ctx := context.Background()
- repo := Fetcher_.Lookup(ctx, "direct", tt.path)
+ repo := fetcher.Lookup(ctx, "direct", tt.path)
if tt.mpath == "" {
tt.mpath = tt.path
func TestCodeRepoVersions(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
-
+ fetcher := NewFetcher()
for _, tt := range codeRepoVersionsTests {
tt := tt
t.Run(strings.ReplaceAll(tt.path, "/", "_"), func(t *testing.T) {
}
ctx := context.Background()
- repo := Fetcher_.Lookup(ctx, "direct", tt.path)
+ repo := fetcher.Lookup(ctx, "direct", tt.path)
list, err := repo.Versions(ctx, tt.prefix)
if err != nil {
t.Fatalf("Versions(%q): %v", tt.prefix, err)
func TestLatest(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
-
+ fetcher := NewFetcher()
for _, tt := range latestTests {
name := strings.ReplaceAll(tt.path, "/", "_")
t.Run(name, func(t *testing.T) {
}
ctx := context.Background()
- repo := Fetcher_.Lookup(ctx, "direct", tt.path)
+ repo := fetcher.Lookup(ctx, "direct", tt.path)
info, err := repo.Latest(ctx)
if err != nil {
if tt.err != "" {
sumState sumState
}
-var Fetcher_ *Fetcher = NewFetcher()
-
func NewFetcher() *Fetcher {
f := new(Fetcher)
f.lookupCache = new(par.Cache[lookupCacheKey, Repo])
// Reset resets globals in the modfetch package, so previous loads don't affect
// contents of go.sum files.
-func Reset() {
- SetState(NewFetcher())
+func (f *Fetcher) Reset() {
+ f.SetState(NewFetcher())
}
// SetState sets the global state of the modfetch package to the newState, and returns the previous
// global state. newState should have been returned by SetState, or be an empty State.
// There should be no concurrent calls to any of the exported functions of this package with
// a call to SetState because it will modify the global state in a non-thread-safe way.
-func SetState(newState *Fetcher) (oldState *Fetcher) {
+func (f *Fetcher) SetState(newState *Fetcher) (oldState *Fetcher) {
if newState.lookupCache == nil {
newState.lookupCache = new(par.Cache[lookupCacheKey, Repo])
}
newState.downloadCache = new(par.ErrCache[module.Version, string])
}
- Fetcher_.mu.Lock()
- defer Fetcher_.mu.Unlock()
+ f.mu.Lock()
+ defer f.mu.Unlock()
oldState = &Fetcher{
- goSumFile: Fetcher_.goSumFile,
- workspaceGoSumFiles: Fetcher_.workspaceGoSumFiles,
- lookupCache: Fetcher_.lookupCache,
- downloadCache: Fetcher_.downloadCache,
- sumState: Fetcher_.sumState,
+ goSumFile: f.goSumFile,
+ workspaceGoSumFiles: f.workspaceGoSumFiles,
+ lookupCache: f.lookupCache,
+ downloadCache: f.downloadCache,
+ sumState: f.sumState,
}
- Fetcher_.SetGoSumFile(newState.goSumFile)
- Fetcher_.workspaceGoSumFiles = newState.workspaceGoSumFiles
+ f.SetGoSumFile(newState.goSumFile)
+ f.workspaceGoSumFiles = newState.workspaceGoSumFiles
// Uses of lookupCache and downloadCache both can call checkModSum,
// which in turn sets the used bit on goSum.status for modules.
// Set (or reset) them so used can be computed properly.
- Fetcher_.lookupCache = newState.lookupCache
- Fetcher_.downloadCache = newState.downloadCache
+ f.lookupCache = newState.lookupCache
+ f.downloadCache = newState.downloadCache
// Set, or reset all fields on goSum. If being reset to empty, it will be initialized later.
- Fetcher_.sumState = newState.sumState
+ f.sumState = newState.sumState
return oldState
}
// The entry's hash must be generated with a known hash algorithm.
// mod.Version may have a "/go.mod" suffix to distinguish sums for
// .mod and .zip files.
-func RecordedSum(mod module.Version) (sum string, ok bool) {
- Fetcher_.mu.Lock()
- defer Fetcher_.mu.Unlock()
- inited, err := Fetcher_.initGoSum()
+func (f *Fetcher) RecordedSum(mod module.Version) (sum string, ok bool) {
+ f.mu.Lock()
+ defer f.mu.Unlock()
+ inited, err := f.initGoSum()
foundSum := ""
if err != nil || !inited {
return "", false
}
- for _, goSums := range Fetcher_.sumState.w {
+ for _, goSums := range f.sumState.w {
for _, h := range goSums[mod] {
if !strings.HasPrefix(h, "h1:") {
continue
}
- if !Fetcher_.sumState.status[modSum{mod, h}].dirty {
+ if !f.sumState.status[modSum{mod, h}].dirty {
if foundSum != "" && foundSum != h { // conflicting sums exist
return "", false
}
}
}
}
- for _, h := range Fetcher_.sumState.m[mod] {
+ for _, h := range f.sumState.m[mod] {
if !strings.HasPrefix(h, "h1:") {
continue
}
- if !Fetcher_.sumState.status[modSum{mod, h}].dirty {
+ if !f.sumState.status[modSum{mod, h}].dirty {
if foundSum != "" && foundSum != h { // conflicting sums exist
return "", false
}
// TidyGoSum returns a tidy version of the go.sum file.
// A missing go.sum file is treated as if empty.
-func TidyGoSum(keep map[module.Version]bool) (before, after []byte) {
- Fetcher_.mu.Lock()
- defer Fetcher_.mu.Unlock()
- before, err := lockedfile.Read(Fetcher_.goSumFile)
+func (f *Fetcher) TidyGoSum(keep map[module.Version]bool) (before, after []byte) {
+ f.mu.Lock()
+ defer f.mu.Unlock()
+ before, err := lockedfile.Read(f.goSumFile)
if err != nil && !errors.Is(err, fs.ErrNotExist) {
base.Fatalf("reading go.sum: %v", err)
}
- after = tidyGoSum(Fetcher_, before, keep)
+ after = tidyGoSum(f, before, keep)
return before, after
}
// keep is used to check whether a sum should be retained in go.mod. It should
// have entries for both module content sums and go.mod sums (version ends
// with "/go.mod").
-func TrimGoSum(keep map[module.Version]bool) {
- Fetcher_.mu.Lock()
- defer Fetcher_.mu.Unlock()
- inited, err := Fetcher_.initGoSum()
+func (f *Fetcher) TrimGoSum(keep map[module.Version]bool) {
+ f.mu.Lock()
+ defer f.mu.Unlock()
+ inited, err := f.initGoSum()
if err != nil {
base.Fatalf("%s", err)
}
return
}
- for m, hs := range Fetcher_.sumState.m {
+ for m, hs := range f.sumState.m {
if !keep[m] {
for _, h := range hs {
- Fetcher_.sumState.status[modSum{m, h}] = modSumStatus{used: false, dirty: true}
+ f.sumState.status[modSum{m, h}] = modSumStatus{used: false, dirty: true}
}
- Fetcher_.sumState.overwrite = true
+ f.sumState.overwrite = true
}
}
}
}
return f.lookupCache.Do(lookupCacheKey{proxy, path}, func() Repo {
- return newCachingRepo(ctx, path, func(ctx context.Context) (Repo, error) {
+ return newCachingRepo(ctx, f, path, func(ctx context.Context) (Repo, error) {
r, err := lookup(f, ctx, proxy, path)
if err == nil && traceRepo {
r = newLoggingRepo(r)
// codeRoot is the module path of the root module in the repository.
// path is the module path of the module being looked up.
// dir is the file system path of the repository containing the module.
-func LookupLocal(ctx context.Context, codeRoot string, path string, dir string) Repo {
+func (f *Fetcher) LookupLocal(ctx context.Context, codeRoot string, path string, dir string) Repo {
if traceRepo {
defer logCall("LookupLocal(%q)", path)()
}
return lookupLocalCache.Do(path, func() Repo {
- return newCachingRepo(ctx, path, func(ctx context.Context) (Repo, error) {
+ return newCachingRepo(ctx, f, path, func(ctx context.Context) (Repo, error) {
repoDir, vcsCmd, err := vcs.FromDir(dir, "")
if err != nil {
return nil, err
m.GoMod = gomod
}
}
- if gomodsum, ok := modfetch.RecordedSum(modkey(mod)); ok {
+ if gomodsum, ok := loaderstate.fetcher.RecordedSum(modkey(mod)); ok {
m.GoModSum = gomodsum
}
}
if err == nil {
m.Dir = dir
}
- if sum, ok := modfetch.RecordedSum(mod); ok {
+ if sum, ok := loaderstate.fetcher.RecordedSum(mod); ok {
m.Sum = sum
}
}
loaderstate.MainModules = nil // reset MainModules
loaderstate.requirements = nil
loaderstate.workFilePath = "" // Force module mode
- modfetch.Reset()
+ loaderstate.Fetcher().Reset()
loaderstate.modRoots = []string{enterModroot}
LoadModFile(loaderstate, ctx)
// The modfetch package's global state is used to compute
// the go.sum file, so save and restore it along with the
// modload state.
- s.fetcher = new.fetcher
- old.fetcher = modfetch.SetState(s.fetcher) // TODO(jitsu): remove after completing global state elimination
+ old.fetcher = s.fetcher.SetState(new.fetcher)
return old
}
func NewState() *State {
s := new(State)
- s.fetcher = modfetch.Fetcher_
+ s.fetcher = modfetch.NewFetcher()
return s
}
}
goModDiff := diff.Diff("current/go.mod", currentGoMod, "tidy/go.mod", updatedGoMod)
- modfetch.TrimGoSum(keep)
+ loaderstate.Fetcher().TrimGoSum(keep)
// Dropping compatibility for 1.16 may result in a strictly smaller go.sum.
// Update the keep map with only the loaded.requirements.
if gover.Compare(compatVersion, "1.16") > 0 {
keep = keepSums(loaderstate, ctx, loaded, loaderstate.requirements, addBuildListZipSums)
}
- currentGoSum, tidyGoSum := modfetch.TidyGoSum(keep)
+ currentGoSum, tidyGoSum := loaderstate.fetcher.TidyGoSum(keep)
goSumDiff := diff.Diff("current/go.sum", currentGoSum, "tidy/go.sum", tidyGoSum)
if len(goModDiff) > 0 {
}
if !ExplicitWriteGoMod {
- modfetch.TrimGoSum(keep)
+ loaderstate.Fetcher().TrimGoSum(keep)
// commitRequirements below will also call WriteGoSum, but the "keep" map
// we have here could be strictly larger: commitRequirements only commits