From ff052737a946b5f9381dc054d61857ee4d500899 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 28 Sep 2020 20:59:47 -0400 Subject: cmd/go/internal/modload: allow 'go get' to use replaced versions 'go mod tidy' has been able to use replaced versions since CL 152739, but 'go get' failed for many of the same paths. Now that we are recommending 'go get' more aggressively due to #40728, we should make that work too. In the future, we might consider factoring out the new replacementRepo type so that 'go list' can report the new versions as well. For #41577 For #41416 For #37438 Updates #26241 Change-Id: I9140c556424b584fdd9bdd0a747842774664a7d8 Reviewed-on: https://go-review.googlesource.com/c/go/+/258220 Trust: Bryan C. Mills Trust: Jay Conrod Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Michael Matloob Reviewed-by: Jay Conrod --- src/cmd/go/internal/modload/modfile.go | 54 ++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 13 deletions(-) (limited to 'src/cmd/go/internal/modload/modfile.go') diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index 6457a7d968..d15da892e6 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -35,13 +35,14 @@ var modFile *modfile.File // A modFileIndex is an index of data corresponding to a modFile // at a specific point in time. type modFileIndex struct { - data []byte - dataNeedsFix bool // true if fixVersion applied a change while parsing data - module module.Version - goVersionV string // GoVersion with "v" prefix - require map[module.Version]requireMeta - replace map[module.Version]module.Version - exclude map[module.Version]bool + data []byte + dataNeedsFix bool // true if fixVersion applied a change while parsing data + module module.Version + goVersionV string // GoVersion with "v" prefix + require map[module.Version]requireMeta + replace map[module.Version]module.Version + highestReplaced map[string]string // highest replaced version of each module path; empty string for wildcard-only replacements + exclude map[module.Version]bool } // index is the index of the go.mod file as of when it was last read or written. @@ -117,7 +118,7 @@ func checkRetractions(ctx context.Context, m module.Version) error { // v2.0.0+incompatible is not "latest" if v1.0.0 is current. rev, err := Query(ctx, path, "latest", findCurrentVersion(path), nil) if err != nil { - return &entry{err: err} + return &entry{nil, err} } // Load go.mod for that version. @@ -138,13 +139,19 @@ func checkRetractions(ctx context.Context, m module.Version) error { } summary, err := rawGoModSummary(rm) if err != nil { - return &entry{err: err} + return &entry{nil, err} } - return &entry{retract: summary.retract} + return &entry{summary.retract, nil} }).(*entry) - if e.err != nil { - return fmt.Errorf("loading module retractions: %v", e.err) + if err := e.err; err != nil { + // Attribute the error to the version being checked, not the version from + // which the retractions were to be loaded. + var mErr *module.ModuleError + if errors.As(err, &mErr) { + err = mErr.Err + } + return &retractionLoadingError{m: m, err: err} } var rationale []string @@ -158,7 +165,7 @@ func checkRetractions(ctx context.Context, m module.Version) error { } } if isRetracted { - return &retractedError{rationale: rationale} + return module.VersionError(m, &retractedError{rationale: rationale}) } return nil } @@ -183,6 +190,19 @@ func (e *retractedError) Is(err error) bool { return err == ErrDisallowed } +type retractionLoadingError struct { + m module.Version + err error +} + +func (e *retractionLoadingError) Error() string { + return fmt.Sprintf("loading module retractions for %v: %v", e.m, e.err) +} + +func (e *retractionLoadingError) Unwrap() error { + return e.err +} + // ShortRetractionRationale returns a retraction rationale string that is safe // to print in a terminal. It returns hard-coded strings if the rationale // is empty, too long, or contains non-printable characters. @@ -255,6 +275,14 @@ func indexModFile(data []byte, modFile *modfile.File, needsFix bool) *modFileInd i.replace[r.Old] = r.New } + i.highestReplaced = make(map[string]string) + for _, r := range modFile.Replace { + v, ok := i.highestReplaced[r.Old.Path] + if !ok || semver.Compare(r.Old.Version, v) > 0 { + i.highestReplaced[r.Old.Path] = r.Old.Version + } + } + i.exclude = make(map[module.Version]bool, len(modFile.Exclude)) for _, x := range modFile.Exclude { i.exclude[x.Mod] = true -- cgit v1.2.1 From 41162be44a099803a870f9b6c147050594598d63 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 12 Oct 2020 15:32:49 -0400 Subject: cmd/go/internal/modload: avoid using the global build list in QueryPattern The Query function allows the caller to specify the current version of the requested module, but the QueryPattern function is missing that parameter: instead, it always assumes that the current version is the one selected from the global build list. This change removes that assumption, instead adding a callback function to determine the current version. (The callback is currently invoked once per candidate module, regardless of whether that module exists, but in a future change we can refactor it to invoke the callback only when needed.) For #36460 For #40775 Change-Id: I001a4a8ab24f5b4fcc66a670d9bd305b47e948ba Reviewed-on: https://go-review.googlesource.com/c/go/+/261640 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Jay Conrod Reviewed-by: Michael Matloob --- src/cmd/go/internal/modload/modfile.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/cmd/go/internal/modload/modfile.go') diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index d15da892e6..006db4f169 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -116,7 +116,7 @@ func checkRetractions(ctx context.Context, m module.Version) error { // Ignore exclusions from the main module's go.mod. // We may need to account for the current version: for example, // v2.0.0+incompatible is not "latest" if v1.0.0 is current. - rev, err := Query(ctx, path, "latest", findCurrentVersion(path), nil) + rev, err := Query(ctx, path, "latest", Selected(path), nil) if err != nil { return &entry{nil, err} } -- cgit v1.2.1 From 5cd4390f3853b8d0d2d962f7acdac87c0eba3d77 Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Tue, 13 Oct 2020 18:19:21 -0400 Subject: cmd/go: don't fetch files missing sums in readonly mode If the go command needs a .mod or .zip file in -mod=readonly mode (now the default), and that file doesn't have a hash in the main module's go.sum file, the go command will now report an error before fetching the file, rather than at the end when failing to update go.sum. The error says specifically which entry is missing. If this error is encountered when loading the build list, it will suggest 'go mod tidy'. If this error is encountered when loading a specific package (an import or command line argument), the error will mention that package and will suggest 'go mod tidy' or 'go get -d'. Fixes #41934 Fixes #41935 Change-Id: I96ec2ef9258bd4bade9915c43d47e6243c376a81 Reviewed-on: https://go-review.googlesource.com/c/go/+/262341 Reviewed-by: Bryan C. Mills Trust: Jay Conrod --- src/cmd/go/internal/modload/modfile.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src/cmd/go/internal/modload/modfile.go') diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index 006db4f169..7a8963246b 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -406,8 +406,11 @@ type retraction struct { // taking into account any replacements for m, exclusions of its dependencies, // and/or vendoring. // -// goModSummary cannot be used on the Target module, as its requirements -// may change. +// m must be a version in the module graph, reachable from the Target module. +// In readonly mode, the go.sum file must contain an entry for m's go.mod file +// (or its replacement). goModSummary must not be called for the Target module +// itself, as its requirements may change. Use rawGoModSummary for other +// module versions. // // The caller must not modify the returned summary. func goModSummary(m module.Version) (*modFileSummary, error) { @@ -442,6 +445,13 @@ func goModSummary(m module.Version) (*modFileSummary, error) { if actual.Path == "" { actual = m } + if cfg.BuildMod == "readonly" && actual.Version != "" { + key := module.Version{Path: actual.Path, Version: actual.Version + "/go.mod"} + if !modfetch.HaveSum(key) { + suggestion := fmt.Sprintf("; try 'go mod download %s' to add it", m.Path) + return nil, module.VersionError(actual, &sumMissingError{suggestion: suggestion}) + } + } summary, err := rawGoModSummary(actual) if err != nil { return nil, err -- cgit v1.2.1