mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.cmdgo] cmd/go: fold index and modFile into MainModules
For #45713 Change-Id: I5e4b0ae16dcc9ba5ac30683370a3a1d3416e24f2 Reviewed-on: https://go-review.googlesource.com/c/go/+/334935 Trust: Michael Matloob <matloob@golang.org> Run-TryBot: Michael Matloob <matloob@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Jay Conrod <jayconrod@google.com>
This commit is contained in:
parent
7ce257147f
commit
f05f5ceffa
5 changed files with 243 additions and 138 deletions
|
|
@ -414,69 +414,71 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M
|
||||||
func queryImport(ctx context.Context, path string, rs *Requirements) (module.Version, error) {
|
func queryImport(ctx context.Context, path string, rs *Requirements) (module.Version, error) {
|
||||||
// To avoid spurious remote fetches, try the latest replacement for each
|
// To avoid spurious remote fetches, try the latest replacement for each
|
||||||
// module (golang.org/issue/26241).
|
// module (golang.org/issue/26241).
|
||||||
if index != nil {
|
var mods []module.Version
|
||||||
var mods []module.Version
|
for _, v := range MainModules.Versions() {
|
||||||
for mp, mv := range index.highestReplaced {
|
if index := MainModules.Index(v); index != nil {
|
||||||
if !maybeInModule(path, mp) {
|
for mp, mv := range index.highestReplaced {
|
||||||
continue
|
if !maybeInModule(path, mp) {
|
||||||
}
|
continue
|
||||||
if mv == "" {
|
|
||||||
// The only replacement is a wildcard that doesn't specify a version, so
|
|
||||||
// synthesize a pseudo-version with an appropriate major version and a
|
|
||||||
// timestamp below any real timestamp. That way, if the main module is
|
|
||||||
// used from within some other module, the user will be able to upgrade
|
|
||||||
// the requirement to any real version they choose.
|
|
||||||
if _, pathMajor, ok := module.SplitPathVersion(mp); ok && len(pathMajor) > 0 {
|
|
||||||
mv = module.ZeroPseudoVersion(pathMajor[1:])
|
|
||||||
} else {
|
|
||||||
mv = module.ZeroPseudoVersion("v0")
|
|
||||||
}
|
}
|
||||||
|
if mv == "" {
|
||||||
|
// The only replacement is a wildcard that doesn't specify a version, so
|
||||||
|
// synthesize a pseudo-version with an appropriate major version and a
|
||||||
|
// timestamp below any real timestamp. That way, if the main module is
|
||||||
|
// used from within some other module, the user will be able to upgrade
|
||||||
|
// the requirement to any real version they choose.
|
||||||
|
if _, pathMajor, ok := module.SplitPathVersion(mp); ok && len(pathMajor) > 0 {
|
||||||
|
mv = module.ZeroPseudoVersion(pathMajor[1:])
|
||||||
|
} else {
|
||||||
|
mv = module.ZeroPseudoVersion("v0")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mg, err := rs.Graph(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return module.Version{}, err
|
||||||
|
}
|
||||||
|
if cmpVersion(mg.Selected(mp), mv) >= 0 {
|
||||||
|
// We can't resolve the import by adding mp@mv to the module graph,
|
||||||
|
// because the selected version of mp is already at least mv.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
mods = append(mods, module.Version{Path: mp, Version: mv})
|
||||||
}
|
}
|
||||||
mg, err := rs.Graph(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return module.Version{}, err
|
|
||||||
}
|
|
||||||
if cmpVersion(mg.Selected(mp), mv) >= 0 {
|
|
||||||
// We can't resolve the import by adding mp@mv to the module graph,
|
|
||||||
// because the selected version of mp is already at least mv.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
mods = append(mods, module.Version{Path: mp, Version: mv})
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Every module path in mods is a prefix of the import path.
|
// Every module path in mods is a prefix of the import path.
|
||||||
// As in QueryPattern, prefer the longest prefix that satisfies the import.
|
// As in QueryPattern, prefer the longest prefix that satisfies the import.
|
||||||
sort.Slice(mods, func(i, j int) bool {
|
sort.Slice(mods, func(i, j int) bool {
|
||||||
return len(mods[i].Path) > len(mods[j].Path)
|
return len(mods[i].Path) > len(mods[j].Path)
|
||||||
})
|
})
|
||||||
for _, m := range mods {
|
for _, m := range mods {
|
||||||
needSum := true
|
needSum := true
|
||||||
root, isLocal, err := fetch(ctx, m, needSum)
|
root, isLocal, err := fetch(ctx, m, needSum)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if sumErr := (*sumMissingError)(nil); errors.As(err, &sumErr) {
|
if sumErr := (*sumMissingError)(nil); errors.As(err, &sumErr) {
|
||||||
return module.Version{}, &ImportMissingSumError{importPath: path}
|
return module.Version{}, &ImportMissingSumError{importPath: path}
|
||||||
}
|
|
||||||
return module.Version{}, err
|
|
||||||
}
|
|
||||||
if _, ok, err := dirInModule(path, m.Path, root, isLocal); err != nil {
|
|
||||||
return m, err
|
|
||||||
} else if ok {
|
|
||||||
if cfg.BuildMod == "readonly" {
|
|
||||||
return module.Version{}, &ImportMissingError{Path: path, replaced: m}
|
|
||||||
}
|
|
||||||
return m, nil
|
|
||||||
}
|
}
|
||||||
|
return module.Version{}, err
|
||||||
}
|
}
|
||||||
if len(mods) > 0 && module.CheckPath(path) != nil {
|
if _, ok, err := dirInModule(path, m.Path, root, isLocal); err != nil {
|
||||||
// The package path is not valid to fetch remotely,
|
return m, err
|
||||||
// so it can only exist in a replaced module,
|
} else if ok {
|
||||||
// and we know from the above loop that it is not.
|
if cfg.BuildMod == "readonly" {
|
||||||
return module.Version{}, &PackageNotInModuleError{
|
return module.Version{}, &ImportMissingError{Path: path, replaced: m}
|
||||||
Mod: mods[0],
|
|
||||||
Query: "latest",
|
|
||||||
Pattern: path,
|
|
||||||
Replacement: Replacement(mods[0]),
|
|
||||||
}
|
}
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(mods) > 0 && module.CheckPath(path) != nil {
|
||||||
|
// The package path is not valid to fetch remotely,
|
||||||
|
// so it can only exist in a replaced module,
|
||||||
|
// and we know from the above loop that it is not.
|
||||||
|
return module.Version{}, &PackageNotInModuleError{
|
||||||
|
Mod: mods[0],
|
||||||
|
Query: "latest",
|
||||||
|
Pattern: path,
|
||||||
|
Replacement: Replacement(mods[0]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"cmd/go/internal/base"
|
"cmd/go/internal/base"
|
||||||
"cmd/go/internal/cfg"
|
"cmd/go/internal/cfg"
|
||||||
|
|
@ -85,6 +86,11 @@ type MainModuleSet struct {
|
||||||
// inGorootSrc caches whether modRoot is within GOROOT/src.
|
// inGorootSrc caches whether modRoot is within GOROOT/src.
|
||||||
// The "std" module is special within GOROOT/src, but not otherwise.
|
// The "std" module is special within GOROOT/src, but not otherwise.
|
||||||
inGorootSrc map[module.Version]bool
|
inGorootSrc map[module.Version]bool
|
||||||
|
|
||||||
|
modFiles map[module.Version]*modfile.File
|
||||||
|
|
||||||
|
indexMu sync.Mutex
|
||||||
|
indices map[module.Version]*modFileIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mms *MainModuleSet) PathPrefix(m module.Version) string {
|
func (mms *MainModuleSet) PathPrefix(m module.Version) string {
|
||||||
|
|
@ -141,6 +147,36 @@ func (mms *MainModuleSet) mustGetSingleMainModule() module.Version {
|
||||||
return mms.versions[0]
|
return mms.versions[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mms *MainModuleSet) GetSingleIndexOrNil() *modFileIndex {
|
||||||
|
if mms == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if len(mms.versions) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if len(mms.versions) != 1 {
|
||||||
|
_ = TODOWorkspaces("Check if we're in workspace mode before returning the below error.")
|
||||||
|
panic("internal error: mustGetSingleMainModule called in workspace mode")
|
||||||
|
}
|
||||||
|
return mms.indices[mms.versions[0]]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mms *MainModuleSet) Index(m module.Version) *modFileIndex {
|
||||||
|
mms.indexMu.Lock()
|
||||||
|
defer mms.indexMu.Unlock()
|
||||||
|
return mms.indices[m]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mms *MainModuleSet) SetIndex(m module.Version, index *modFileIndex) {
|
||||||
|
mms.indexMu.Lock()
|
||||||
|
defer mms.indexMu.Unlock()
|
||||||
|
mms.indices[m] = index
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mms *MainModuleSet) ModFile(m module.Version) *modfile.File {
|
||||||
|
return mms.modFiles[m]
|
||||||
|
}
|
||||||
|
|
||||||
func (mms *MainModuleSet) Len() int {
|
func (mms *MainModuleSet) Len() int {
|
||||||
if mms == nil {
|
if mms == nil {
|
||||||
return 0
|
return 0
|
||||||
|
|
@ -178,6 +214,7 @@ const (
|
||||||
// in go.mod, edit it before loading.
|
// in go.mod, edit it before loading.
|
||||||
func ModFile() *modfile.File {
|
func ModFile() *modfile.File {
|
||||||
Init()
|
Init()
|
||||||
|
modFile := MainModules.ModFile(MainModules.mustGetSingleMainModule())
|
||||||
if modFile == nil {
|
if modFile == nil {
|
||||||
die()
|
die()
|
||||||
}
|
}
|
||||||
|
|
@ -557,7 +594,7 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) {
|
||||||
if len(modRoots) == 0 {
|
if len(modRoots) == 0 {
|
||||||
_ = TODOWorkspaces("Instead of creating a fake module with an empty modroot, make MainModules.Len() == 0 mean that we're in module mode but not inside any module.")
|
_ = TODOWorkspaces("Instead of creating a fake module with an empty modroot, make MainModules.Len() == 0 mean that we're in module mode but not inside any module.")
|
||||||
mainModule := module.Version{Path: "command-line-arguments"}
|
mainModule := module.Version{Path: "command-line-arguments"}
|
||||||
MainModules = makeMainModules([]module.Version{mainModule}, []string{""})
|
MainModules = makeMainModules([]module.Version{mainModule}, []string{""}, []*modfile.File{nil}, []*modFileIndex{nil})
|
||||||
goVersion := LatestGoVersion()
|
goVersion := LatestGoVersion()
|
||||||
rawGoVersion.Store(mainModule, goVersion)
|
rawGoVersion.Store(mainModule, goVersion)
|
||||||
requirements = newRequirements(modDepthFromGoVersion(goVersion), nil, nil)
|
requirements = newRequirements(modDepthFromGoVersion(goVersion), nil, nil)
|
||||||
|
|
@ -566,6 +603,7 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) {
|
||||||
|
|
||||||
var modFiles []*modfile.File
|
var modFiles []*modfile.File
|
||||||
var mainModules []module.Version
|
var mainModules []module.Version
|
||||||
|
var indices []*modFileIndex
|
||||||
for _, modroot := range modRoots {
|
for _, modroot := range modRoots {
|
||||||
gomod := modFilePath(modroot)
|
gomod := modFilePath(modroot)
|
||||||
var data []byte
|
var data []byte
|
||||||
|
|
@ -593,11 +631,10 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) {
|
||||||
base.Fatalf("go: no module declaration in go.mod. To specify the module path:\n\tgo mod edit -module=example.com/mod")
|
base.Fatalf("go: no module declaration in go.mod. To specify the module path:\n\tgo mod edit -module=example.com/mod")
|
||||||
}
|
}
|
||||||
|
|
||||||
modFile = f // TODO(golang.org/cl/327329): remove the global modFile variable and replace it with multiple modfiles
|
|
||||||
modFiles = append(modFiles, f)
|
modFiles = append(modFiles, f)
|
||||||
mainModule := f.Module.Mod
|
mainModule := f.Module.Mod
|
||||||
mainModules = append(mainModules, mainModule)
|
mainModules = append(mainModules, mainModule)
|
||||||
index = indexModFile(data, f, mainModule, fixed)
|
indices = append(indices, indexModFile(data, f, mainModule, fixed))
|
||||||
|
|
||||||
if err := module.CheckImportPath(f.Module.Mod.Path); err != nil {
|
if err := module.CheckImportPath(f.Module.Mod.Path); err != nil {
|
||||||
if pathErr, ok := err.(*module.InvalidPathError); ok {
|
if pathErr, ok := err.(*module.InvalidPathError); ok {
|
||||||
|
|
@ -607,7 +644,7 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MainModules = makeMainModules(mainModules, modRoots)
|
MainModules = makeMainModules(mainModules, modRoots, modFiles, indices)
|
||||||
setDefaultBuildMod() // possibly enable automatic vendoring
|
setDefaultBuildMod() // possibly enable automatic vendoring
|
||||||
rs = requirementsFromModFiles(ctx, modFiles)
|
rs = requirementsFromModFiles(ctx, modFiles)
|
||||||
|
|
||||||
|
|
@ -623,14 +660,16 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) {
|
||||||
|
|
||||||
if cfg.BuildMod == "vendor" {
|
if cfg.BuildMod == "vendor" {
|
||||||
readVendorList()
|
readVendorList()
|
||||||
checkVendorConsistency()
|
index := MainModules.Index(mainModule)
|
||||||
|
modFile := MainModules.ModFile(mainModule)
|
||||||
|
checkVendorConsistency(index, modFile)
|
||||||
rs.initVendor(vendorList)
|
rs.initVendor(vendorList)
|
||||||
}
|
}
|
||||||
if index.goVersionV == "" {
|
if MainModules.Index(mainModule).goVersionV == "" {
|
||||||
// TODO(#45551): Do something more principled instead of checking
|
// TODO(#45551): Do something more principled instead of checking
|
||||||
// cfg.CmdName directly here.
|
// cfg.CmdName directly here.
|
||||||
if cfg.BuildMod == "mod" && cfg.CmdName != "mod graph" && cfg.CmdName != "mod why" {
|
if cfg.BuildMod == "mod" && cfg.CmdName != "mod graph" && cfg.CmdName != "mod why" {
|
||||||
addGoStmt(mainModule, LatestGoVersion())
|
addGoStmt(MainModules.ModFile(mainModule), mainModule, LatestGoVersion())
|
||||||
if go117EnableLazyLoading {
|
if go117EnableLazyLoading {
|
||||||
// We need to add a 'go' version to the go.mod file, but we must assume
|
// We need to add a 'go' version to the go.mod file, but we must assume
|
||||||
// that its existing contents match something between Go 1.11 and 1.16.
|
// that its existing contents match something between Go 1.11 and 1.16.
|
||||||
|
|
@ -689,12 +728,12 @@ func CreateModFile(ctx context.Context, modPath string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "go: creating new go.mod: module %s\n", modPath)
|
fmt.Fprintf(os.Stderr, "go: creating new go.mod: module %s\n", modPath)
|
||||||
modFile = new(modfile.File)
|
modFile := new(modfile.File)
|
||||||
modFile.AddModuleStmt(modPath)
|
modFile.AddModuleStmt(modPath)
|
||||||
MainModules = makeMainModules([]module.Version{modFile.Module.Mod}, []string{modRoot})
|
MainModules = makeMainModules([]module.Version{modFile.Module.Mod}, []string{modRoot}, []*modfile.File{modFile}, []*modFileIndex{nil})
|
||||||
addGoStmt(modFile.Module.Mod, LatestGoVersion()) // Add the go directive before converted module requirements.
|
addGoStmt(modFile, modFile.Module.Mod, LatestGoVersion()) // Add the go directive before converted module requirements.
|
||||||
|
|
||||||
convertedFrom, err := convertLegacyConfig(modPath)
|
convertedFrom, err := convertLegacyConfig(modFile, modPath)
|
||||||
if convertedFrom != "" {
|
if convertedFrom != "" {
|
||||||
fmt.Fprintf(os.Stderr, "go: copying requirements from %s\n", base.ShortPath(convertedFrom))
|
fmt.Fprintf(os.Stderr, "go: copying requirements from %s\n", base.ShortPath(convertedFrom))
|
||||||
}
|
}
|
||||||
|
|
@ -792,7 +831,7 @@ func AllowMissingModuleImports() {
|
||||||
|
|
||||||
// makeMainModules creates a MainModuleSet and associated variables according to
|
// makeMainModules creates a MainModuleSet and associated variables according to
|
||||||
// the given main modules.
|
// the given main modules.
|
||||||
func makeMainModules(ms []module.Version, rootDirs []string) *MainModuleSet {
|
func makeMainModules(ms []module.Version, rootDirs []string, modFiles []*modfile.File, indices []*modFileIndex) *MainModuleSet {
|
||||||
for _, m := range ms {
|
for _, m := range ms {
|
||||||
if m.Version != "" {
|
if m.Version != "" {
|
||||||
panic("mainModulesCalled with module.Version with non empty Version field: " + fmt.Sprintf("%#v", m))
|
panic("mainModulesCalled with module.Version with non empty Version field: " + fmt.Sprintf("%#v", m))
|
||||||
|
|
@ -803,10 +842,14 @@ func makeMainModules(ms []module.Version, rootDirs []string) *MainModuleSet {
|
||||||
inGorootSrc: map[module.Version]bool{},
|
inGorootSrc: map[module.Version]bool{},
|
||||||
pathPrefix: map[module.Version]string{},
|
pathPrefix: map[module.Version]string{},
|
||||||
modRoot: map[module.Version]string{},
|
modRoot: map[module.Version]string{},
|
||||||
|
modFiles: map[module.Version]*modfile.File{},
|
||||||
|
indices: map[module.Version]*modFileIndex{},
|
||||||
}
|
}
|
||||||
for i, m := range ms {
|
for i, m := range ms {
|
||||||
mainModules.pathPrefix[m] = m.Path
|
mainModules.pathPrefix[m] = m.Path
|
||||||
mainModules.modRoot[m] = rootDirs[i]
|
mainModules.modRoot[m] = rootDirs[i]
|
||||||
|
mainModules.modFiles[m] = modFiles[i]
|
||||||
|
mainModules.indices[m] = indices[i]
|
||||||
|
|
||||||
if rel := search.InDir(rootDirs[i], cfg.GOROOTsrc); rel != "" {
|
if rel := search.InDir(rootDirs[i], cfg.GOROOTsrc); rel != "" {
|
||||||
mainModules.inGorootSrc[m] = true
|
mainModules.inGorootSrc[m] = true
|
||||||
|
|
@ -840,15 +883,18 @@ func requirementsFromModFiles(ctx context.Context, modFiles []*modfile.File) *Re
|
||||||
}
|
}
|
||||||
direct := map[string]bool{}
|
direct := map[string]bool{}
|
||||||
for _, modFile := range modFiles {
|
for _, modFile := range modFiles {
|
||||||
// TODO(golang.org/cl/327329): Use the correct index here.
|
requirement:
|
||||||
for _, r := range modFile.Require {
|
for _, r := range modFile.Require {
|
||||||
if index != nil && index.exclude[r.Mod] {
|
// TODO(#45713): Maybe join
|
||||||
if cfg.BuildMod == "mod" {
|
for _, mainModule := range MainModules.Versions() {
|
||||||
fmt.Fprintf(os.Stderr, "go: dropping requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version)
|
if index := MainModules.Index(mainModule); index != nil && index.exclude[r.Mod] {
|
||||||
} else {
|
if cfg.BuildMod == "mod" {
|
||||||
fmt.Fprintf(os.Stderr, "go: ignoring requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version)
|
fmt.Fprintf(os.Stderr, "go: dropping requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(os.Stderr, "go: ignoring requirement on excluded version %s %s\n", r.Mod.Path, r.Mod.Version)
|
||||||
|
}
|
||||||
|
continue requirement
|
||||||
}
|
}
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
roots = append(roots, r.Mod)
|
roots = append(roots, r.Mod)
|
||||||
|
|
@ -908,6 +954,7 @@ func setDefaultBuildMod() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(modRoots) == 1 {
|
if len(modRoots) == 1 {
|
||||||
|
index := MainModules.GetSingleIndexOrNil()
|
||||||
if fi, err := fsys.Stat(filepath.Join(modRoots[0], "vendor")); err == nil && fi.IsDir() {
|
if fi, err := fsys.Stat(filepath.Join(modRoots[0], "vendor")); err == nil && fi.IsDir() {
|
||||||
modGo := "unspecified"
|
modGo := "unspecified"
|
||||||
if index != nil && index.goVersionV != "" {
|
if index != nil && index.goVersionV != "" {
|
||||||
|
|
@ -933,7 +980,7 @@ func setDefaultBuildMod() {
|
||||||
|
|
||||||
// convertLegacyConfig imports module requirements from a legacy vendoring
|
// convertLegacyConfig imports module requirements from a legacy vendoring
|
||||||
// configuration file, if one is present.
|
// configuration file, if one is present.
|
||||||
func convertLegacyConfig(modPath string) (from string, err error) {
|
func convertLegacyConfig(modFile *modfile.File, modPath string) (from string, err error) {
|
||||||
noneSelected := func(path string) (version string) { return "none" }
|
noneSelected := func(path string) (version string) { return "none" }
|
||||||
queryPackage := func(path, rev string) (module.Version, error) {
|
queryPackage := func(path, rev string) (module.Version, error) {
|
||||||
pkgMods, modOnly, err := QueryPattern(context.Background(), path, rev, noneSelected, nil)
|
pkgMods, modOnly, err := QueryPattern(context.Background(), path, rev, noneSelected, nil)
|
||||||
|
|
@ -967,7 +1014,7 @@ func convertLegacyConfig(modPath string) (from string, err error) {
|
||||||
// addGoStmt adds a go directive to the go.mod file if it does not already
|
// addGoStmt adds a go directive to the go.mod file if it does not already
|
||||||
// include one. The 'go' version added, if any, is the latest version supported
|
// include one. The 'go' version added, if any, is the latest version supported
|
||||||
// by this toolchain.
|
// by this toolchain.
|
||||||
func addGoStmt(mod module.Version, v string) {
|
func addGoStmt(modFile *modfile.File, mod module.Version, v string) {
|
||||||
if modFile.Go != nil && modFile.Go.Version != "" {
|
if modFile.Go != nil && modFile.Go.Version != "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -1231,8 +1278,11 @@ func commitRequirements(ctx context.Context, goVersion string, rs *Requirements)
|
||||||
if MainModules.Len() != 1 || MainModules.ModRoot(MainModules.Versions()[0]) == "" {
|
if MainModules.Len() != 1 || MainModules.ModRoot(MainModules.Versions()[0]) == "" {
|
||||||
_ = TODOWorkspaces("also check that workspace mode is off")
|
_ = TODOWorkspaces("also check that workspace mode is off")
|
||||||
// We aren't in a module, so we don't have anywhere to write a go.mod file.
|
// We aren't in a module, so we don't have anywhere to write a go.mod file.
|
||||||
|
_ = TODOWorkspaces("also check that workspace mode is off")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
mainModule := MainModules.Versions()[0]
|
||||||
|
modFile := MainModules.ModFile(mainModule)
|
||||||
|
|
||||||
var list []*modfile.Require
|
var list []*modfile.Require
|
||||||
for _, m := range rs.rootModules {
|
for _, m := range rs.rootModules {
|
||||||
|
|
@ -1251,6 +1301,7 @@ func commitRequirements(ctx context.Context, goVersion string, rs *Requirements)
|
||||||
}
|
}
|
||||||
modFile.Cleanup()
|
modFile.Cleanup()
|
||||||
|
|
||||||
|
index := MainModules.GetSingleIndexOrNil()
|
||||||
dirty := index.modFileIsDirty(modFile)
|
dirty := index.modFileIsDirty(modFile)
|
||||||
if dirty && cfg.BuildMod != "mod" {
|
if dirty && cfg.BuildMod != "mod" {
|
||||||
// If we're about to fail due to -mod=readonly,
|
// If we're about to fail due to -mod=readonly,
|
||||||
|
|
@ -1281,7 +1332,7 @@ func commitRequirements(ctx context.Context, goVersion string, rs *Requirements)
|
||||||
mainModule := MainModules.Versions()[0]
|
mainModule := MainModules.Versions()[0]
|
||||||
|
|
||||||
// At this point we have determined to make the go.mod file on disk equal to new.
|
// At this point we have determined to make the go.mod file on disk equal to new.
|
||||||
index = indexModFile(new, modFile, mainModule, false)
|
MainModules.SetIndex(mainModule, indexModFile(new, modFile, mainModule, false))
|
||||||
|
|
||||||
// Update go.sum after releasing the side lock and refreshing the index.
|
// Update go.sum after releasing the side lock and refreshing the index.
|
||||||
// 'go mod init' shouldn't write go.sum, since it will be incomplete.
|
// 'go mod init' shouldn't write go.sum, since it will be incomplete.
|
||||||
|
|
|
||||||
|
|
@ -54,11 +54,13 @@ const (
|
||||||
go117LazyTODO = false
|
go117LazyTODO = false
|
||||||
)
|
)
|
||||||
|
|
||||||
var modFile *modfile.File
|
|
||||||
|
|
||||||
// modFileGoVersion returns the (non-empty) Go version at which the requirements
|
// modFileGoVersion returns the (non-empty) Go version at which the requirements
|
||||||
// in modFile are intepreted, or the latest Go version if modFile is nil.
|
// in modFile are intepreted, or the latest Go version if modFile is nil.
|
||||||
func modFileGoVersion() string {
|
func modFileGoVersion() string {
|
||||||
|
_ = TODOWorkspaces("this is obviously wrong.")
|
||||||
|
// Yes we're picking arbitrarily, we'll have to pass through the version
|
||||||
|
// we care about
|
||||||
|
modFile := MainModules.ModFile(MainModules.Versions()[0])
|
||||||
if modFile == nil {
|
if modFile == nil {
|
||||||
return LatestGoVersion()
|
return LatestGoVersion()
|
||||||
}
|
}
|
||||||
|
|
@ -90,9 +92,6 @@ type modFileIndex struct {
|
||||||
exclude map[module.Version]bool
|
exclude map[module.Version]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// index is the index of the go.mod file as of when it was last read or written.
|
|
||||||
var index *modFileIndex
|
|
||||||
|
|
||||||
type requireMeta struct {
|
type requireMeta struct {
|
||||||
indirect bool
|
indirect bool
|
||||||
}
|
}
|
||||||
|
|
@ -135,8 +134,10 @@ var ErrDisallowed = errors.New("disallowed module version")
|
||||||
// CheckExclusions returns an error equivalent to ErrDisallowed if module m is
|
// CheckExclusions returns an error equivalent to ErrDisallowed if module m is
|
||||||
// excluded by the main module's go.mod file.
|
// excluded by the main module's go.mod file.
|
||||||
func CheckExclusions(ctx context.Context, m module.Version) error {
|
func CheckExclusions(ctx context.Context, m module.Version) error {
|
||||||
if index != nil && index.exclude[m] {
|
for _, mainModule := range MainModules.Versions() {
|
||||||
return module.VersionError(m, errExcluded)
|
if index := MainModules.Index(mainModule); index != nil && index.exclude[m] {
|
||||||
|
return module.VersionError(m, errExcluded)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -304,19 +305,37 @@ func CheckDeprecation(ctx context.Context, m module.Version) (deprecation string
|
||||||
return summary.deprecated, nil
|
return summary.deprecated, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func replacement(mod module.Version, index *modFileIndex) (fromVersion string, to module.Version, ok bool) {
|
||||||
|
if r, ok := index.replace[mod]; ok {
|
||||||
|
return mod.Version, r, true
|
||||||
|
}
|
||||||
|
if r, ok := index.replace[module.Version{Path: mod.Path}]; ok {
|
||||||
|
return "", r, true
|
||||||
|
}
|
||||||
|
return "", module.Version{}, false
|
||||||
|
}
|
||||||
|
|
||||||
// Replacement returns the replacement for mod, if any, from go.mod.
|
// Replacement returns the replacement for mod, if any, from go.mod.
|
||||||
// If there is no replacement for mod, Replacement returns
|
// If there is no replacement for mod, Replacement returns
|
||||||
// a module.Version with Path == "".
|
// a module.Version with Path == "".
|
||||||
func Replacement(mod module.Version) module.Version {
|
func Replacement(mod module.Version) module.Version {
|
||||||
if index != nil {
|
_ = TODOWorkspaces("support replaces in the go.work file")
|
||||||
if r, ok := index.replace[mod]; ok {
|
foundFrom, found, foundModRoot := "", module.Version{}, ""
|
||||||
return r
|
for _, v := range MainModules.Versions() {
|
||||||
}
|
if index := MainModules.Index(v); index != nil {
|
||||||
if r, ok := index.replace[module.Version{Path: mod.Path}]; ok {
|
if from, r, ok := replacement(mod, index); ok {
|
||||||
return r
|
modRoot := MainModules.ModRoot(v)
|
||||||
|
if foundModRoot != "" && foundFrom != from && found != r {
|
||||||
|
_ = TODOWorkspaces("once the go.work file supports replaces, recommend them as a way to override conflicts")
|
||||||
|
base.Errorf("conflicting replacements found for %v in workspace modules defined by %v and %v",
|
||||||
|
mod, modFilePath(foundModRoot), modFilePath(modRoot))
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
found, foundModRoot = r, modRoot
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return module.Version{}
|
return found
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolveReplacement returns the module actually used to load the source code
|
// resolveReplacement returns the module actually used to load the source code
|
||||||
|
|
@ -551,27 +570,29 @@ func goModSummary(m module.Version) (*modFileSummary, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if index != nil && len(index.exclude) > 0 {
|
for _, mainModule := range MainModules.Versions() {
|
||||||
// Drop any requirements on excluded versions.
|
if index := MainModules.Index(mainModule); index != nil && len(index.exclude) > 0 {
|
||||||
// Don't modify the cached summary though, since we might need the raw
|
// Drop any requirements on excluded versions.
|
||||||
// summary separately.
|
// Don't modify the cached summary though, since we might need the raw
|
||||||
haveExcludedReqs := false
|
// summary separately.
|
||||||
for _, r := range summary.require {
|
haveExcludedReqs := false
|
||||||
if index.exclude[r] {
|
|
||||||
haveExcludedReqs = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if haveExcludedReqs {
|
|
||||||
s := new(modFileSummary)
|
|
||||||
*s = *summary
|
|
||||||
s.require = make([]module.Version, 0, len(summary.require))
|
|
||||||
for _, r := range summary.require {
|
for _, r := range summary.require {
|
||||||
if !index.exclude[r] {
|
if index.exclude[r] {
|
||||||
s.require = append(s.require, r)
|
haveExcludedReqs = true
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
summary = s
|
if haveExcludedReqs {
|
||||||
|
s := new(modFileSummary)
|
||||||
|
*s = *summary
|
||||||
|
s.require = make([]module.Version, 0, len(summary.require))
|
||||||
|
for _, r := range summary.require {
|
||||||
|
if !index.exclude[r] {
|
||||||
|
s.require = append(s.require, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
summary = s
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return summary, nil
|
return summary, nil
|
||||||
|
|
|
||||||
|
|
@ -973,14 +973,18 @@ func lookupRepo(proxy, path string) (repo versionRepo, err error) {
|
||||||
repo = emptyRepo{path: path, err: err}
|
repo = emptyRepo{path: path, err: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
if index == nil {
|
// TODO(#45713): Join all the highestReplaced fields into a single value.
|
||||||
return repo, err
|
for _, mm := range MainModules.Versions() {
|
||||||
}
|
index := MainModules.Index(mm)
|
||||||
if _, ok := index.highestReplaced[path]; !ok {
|
if index == nil {
|
||||||
return repo, err
|
continue
|
||||||
|
}
|
||||||
|
if _, ok := index.highestReplaced[path]; ok {
|
||||||
|
return &replacementRepo{repo: repo}, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &replacementRepo{repo: repo}, nil
|
return repo, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// An emptyRepo is a versionRepo that contains no versions.
|
// An emptyRepo is a versionRepo that contains no versions.
|
||||||
|
|
@ -1019,11 +1023,13 @@ func (rr *replacementRepo) Versions(prefix string) ([]string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
versions := repoVersions
|
versions := repoVersions
|
||||||
if index != nil && len(index.replace) > 0 {
|
for _, mm := range MainModules.Versions() {
|
||||||
path := rr.ModulePath()
|
if index := MainModules.Index(mm); index != nil && len(index.replace) > 0 {
|
||||||
for m, _ := range index.replace {
|
path := rr.ModulePath()
|
||||||
if m.Path == path && strings.HasPrefix(m.Version, prefix) && m.Version != "" && !module.IsPseudoVersion(m.Version) {
|
for m, _ := range index.replace {
|
||||||
versions = append(versions, m.Version)
|
if m.Path == path && strings.HasPrefix(m.Version, prefix) && m.Version != "" && !module.IsPseudoVersion(m.Version) {
|
||||||
|
versions = append(versions, m.Version)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1041,7 +1047,16 @@ func (rr *replacementRepo) Versions(prefix string) ([]string, error) {
|
||||||
|
|
||||||
func (rr *replacementRepo) Stat(rev string) (*modfetch.RevInfo, error) {
|
func (rr *replacementRepo) Stat(rev string) (*modfetch.RevInfo, error) {
|
||||||
info, err := rr.repo.Stat(rev)
|
info, err := rr.repo.Stat(rev)
|
||||||
if err == nil || index == nil || len(index.replace) == 0 {
|
if err == nil {
|
||||||
|
return info, err
|
||||||
|
}
|
||||||
|
var hasReplacements bool
|
||||||
|
for _, v := range MainModules.Versions() {
|
||||||
|
if index := MainModules.Index(v); index != nil && len(index.replace) > 0 {
|
||||||
|
hasReplacements = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !hasReplacements {
|
||||||
return info, err
|
return info, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1068,27 +1083,42 @@ func (rr *replacementRepo) Stat(rev string) (*modfetch.RevInfo, error) {
|
||||||
|
|
||||||
func (rr *replacementRepo) Latest() (*modfetch.RevInfo, error) {
|
func (rr *replacementRepo) Latest() (*modfetch.RevInfo, error) {
|
||||||
info, err := rr.repo.Latest()
|
info, err := rr.repo.Latest()
|
||||||
|
path := rr.ModulePath()
|
||||||
|
|
||||||
if index != nil {
|
highestReplaced, found := "", false
|
||||||
path := rr.ModulePath()
|
for _, mm := range MainModules.Versions() {
|
||||||
if v, ok := index.highestReplaced[path]; ok {
|
if index := MainModules.Index(mm); index != nil {
|
||||||
if v == "" {
|
if v, ok := index.highestReplaced[path]; ok {
|
||||||
// The only replacement is a wildcard that doesn't specify a version, so
|
if !found {
|
||||||
// synthesize a pseudo-version with an appropriate major version and a
|
highestReplaced, found = v, true
|
||||||
// timestamp below any real timestamp. That way, if the main module is
|
continue
|
||||||
// used from within some other module, the user will be able to upgrade
|
}
|
||||||
// the requirement to any real version they choose.
|
if semver.Compare(v, highestReplaced) > 0 {
|
||||||
if _, pathMajor, ok := module.SplitPathVersion(path); ok && len(pathMajor) > 0 {
|
highestReplaced = v
|
||||||
v = module.PseudoVersion(pathMajor[1:], "", time.Time{}, "000000000000")
|
|
||||||
} else {
|
|
||||||
v = module.PseudoVersion("v0", "", time.Time{}, "000000000000")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil || semver.Compare(v, info.Version) > 0 {
|
if found {
|
||||||
return rr.replacementStat(v)
|
v := highestReplaced
|
||||||
|
|
||||||
|
if v == "" {
|
||||||
|
// The only replacement is a wildcard that doesn't specify a version, so
|
||||||
|
// synthesize a pseudo-version with an appropriate major version and a
|
||||||
|
// timestamp below any real timestamp. That way, if the main module is
|
||||||
|
// used from within some other module, the user will be able to upgrade
|
||||||
|
// the requirement to any real version they choose.
|
||||||
|
if _, pathMajor, ok := module.SplitPathVersion(path); ok && len(pathMajor) > 0 {
|
||||||
|
v = module.PseudoVersion(pathMajor[1:], "", time.Time{}, "000000000000")
|
||||||
|
} else {
|
||||||
|
v = module.PseudoVersion("v0", "", time.Time{}, "000000000000")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err != nil || semver.Compare(v, info.Version) > 0 {
|
||||||
|
return rr.replacementStat(v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return info, err
|
return info, err
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import (
|
||||||
|
|
||||||
"cmd/go/internal/base"
|
"cmd/go/internal/base"
|
||||||
|
|
||||||
|
"golang.org/x/mod/modfile"
|
||||||
"golang.org/x/mod/module"
|
"golang.org/x/mod/module"
|
||||||
"golang.org/x/mod/semver"
|
"golang.org/x/mod/semver"
|
||||||
)
|
)
|
||||||
|
|
@ -134,7 +135,7 @@ func readVendorList() {
|
||||||
// checkVendorConsistency verifies that the vendor/modules.txt file matches (if
|
// checkVendorConsistency verifies that the vendor/modules.txt file matches (if
|
||||||
// go 1.14) or at least does not contradict (go 1.13 or earlier) the
|
// go 1.14) or at least does not contradict (go 1.13 or earlier) the
|
||||||
// requirements and replacements listed in the main module's go.mod file.
|
// requirements and replacements listed in the main module's go.mod file.
|
||||||
func checkVendorConsistency() {
|
func checkVendorConsistency(index *modFileIndex, modFile *modfile.File) {
|
||||||
readVendorList()
|
readVendorList()
|
||||||
|
|
||||||
pre114 := false
|
pre114 := false
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue