]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.16] cmd: upgrade golang.org/x/mod to fix go.mod parser
authorJay Conrod <jayconrod@google.com>
Wed, 24 Feb 2021 23:24:45 +0000 (18:24 -0500)
committerDmitri Shuralyov <dmitshur@golang.org>
Wed, 3 Mar 2021 17:58:27 +0000 (17:58 +0000)
modfile.Parse passed an empty string to the VersionFixer for the
module path. This caused errors for v2+ versions.

For #44496

Change-Id: I13b86b6ecf6815c4bc9a96ec0668284c9228c205
Reviewed-on: https://go-review.googlesource.com/c/go/+/296131
Trust: Jay Conrod <jayconrod@google.com>
Run-TryBot: Jay Conrod <jayconrod@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
(cherry picked from commit bcac57f89c0ec609e6fbebcbcd42bb73fdaef2f0)
Reviewed-on: https://go-review.googlesource.com/c/go/+/297990
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
src/cmd/go.mod
src/cmd/go.sum
src/cmd/go/testdata/script/mod_retract_fix_version.txt [new file with mode: 0644]
src/cmd/vendor/golang.org/x/mod/modfile/rule.go
src/cmd/vendor/modules.txt

index 0ec5e5c8ac98a1a5c60195718480462287165a7b..5b52a13a546bc37df82535cbb2f05ddffa06f77f 100644 (file)
@@ -6,7 +6,7 @@ require (
        github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2
        golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff
        golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
-       golang.org/x/mod v0.4.2-0.20210301183607-b038bf73c007
+       golang.org/x/mod v0.4.2-0.20210302225016-2823f815b3c9
        golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect
        golang.org/x/tools v0.0.0-20210107193943-4ed967dd8eff
 )
index 90f81a04147ae61272f8286f984b835ba2189d38..e0d6f84fec197f07354fe5ebe5da3534c27c0bab 100644 (file)
@@ -14,8 +14,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
 golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
 golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.2-0.20210301183607-b038bf73c007 h1:tz4qROOcnBtykU8oV3AkBPsGL0fKxBIIduvIReyUYnA=
-golang.org/x/mod v0.4.2-0.20210301183607-b038bf73c007/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.2-0.20210302225016-2823f815b3c9 h1:wqmbyuVn5unGTrBfqBTXWG8fCBY7eM1kldUTIrVRCiQ=
+golang.org/x/mod v0.4.2-0.20210302225016-2823f815b3c9/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
diff --git a/src/cmd/go/testdata/script/mod_retract_fix_version.txt b/src/cmd/go/testdata/script/mod_retract_fix_version.txt
new file mode 100644 (file)
index 0000000..f8099ec
--- /dev/null
@@ -0,0 +1,24 @@
+# retract must not be used without a module directive.
+! go list -m all
+stderr 'go.mod:3: no module directive found, so retract cannot be used$'
+
+# Commands that update go.mod should fix non-canonical versions in
+# retract directives.
+# Verifies #44494.
+go mod edit -module=rsc.io/quote/v2
+! go list -m all
+stderr '^go: updates to go.mod needed; to update it:\n\tgo mod tidy$'
+go mod tidy
+go list -m all
+cmp go.mod go.mod.want
+
+-- go.mod --
+go 1.16
+
+retract latest
+-- go.mod.want --
+go 1.16
+
+retract v2.0.1
+
+module rsc.io/quote/v2
index 8fcf96b713842761e45bdc3010b7ae12f265d794..f8c9384985985929e27cda4acba115db0381d64e 100644 (file)
@@ -125,6 +125,12 @@ func (f *File) AddComment(text string) {
 
 type VersionFixer func(path, version string) (string, error)
 
+// errDontFix is returned by a VersionFixer to indicate the version should be
+// left alone, even if it's not canonical.
+var dontFixRetract VersionFixer = func(_, vers string) (string, error) {
+       return vers, nil
+}
+
 // Parse parses the data, reported in errors as being from file,
 // into a File struct. It applies fix, if non-nil, to canonicalize all module versions found.
 func Parse(file string, data []byte, fix VersionFixer) (*File, error) {
@@ -142,7 +148,7 @@ func ParseLax(file string, data []byte, fix VersionFixer) (*File, error) {
        return parseToFile(file, data, fix, false)
 }
 
-func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (*File, error) {
+func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (parsed *File, err error) {
        fs, err := parse(file, data)
        if err != nil {
                return nil, err
@@ -150,8 +156,18 @@ func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (*File
        f := &File{
                Syntax: fs,
        }
-
        var errs ErrorList
+
+       // fix versions in retract directives after the file is parsed.
+       // We need the module path to fix versions, and it might be at the end.
+       defer func() {
+               oldLen := len(errs)
+               f.fixRetract(fix, &errs)
+               if len(errs) > oldLen {
+                       parsed, err = nil, errs
+               }
+       }()
+
        for _, x := range fs.Stmt {
                switch x := x.(type) {
                case *Line:
@@ -370,7 +386,7 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a
 
        case "retract":
                rationale := parseRetractRationale(block, line)
-               vi, err := parseVersionInterval(verb, &args, fix)
+               vi, err := parseVersionInterval(verb, "", &args, dontFixRetract)
                if err != nil {
                        if strict {
                                wrapError(err)
@@ -397,6 +413,47 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a
        }
 }
 
+// fixRetract applies fix to each retract directive in f, appending any errors
+// to errs.
+//
+// Most versions are fixed as we parse the file, but for retract directives,
+// the relevant module path is the one specified with the module directive,
+// and that might appear at the end of the file (or not at all).
+func (f *File) fixRetract(fix VersionFixer, errs *ErrorList) {
+       if fix == nil {
+               return
+       }
+       path := ""
+       if f.Module != nil {
+               path = f.Module.Mod.Path
+       }
+       var r *Retract
+       wrapError := func(err error) {
+               *errs = append(*errs, Error{
+                       Filename: f.Syntax.Name,
+                       Pos:      r.Syntax.Start,
+                       Err:      err,
+               })
+       }
+
+       for _, r = range f.Retract {
+               if path == "" {
+                       wrapError(errors.New("no module directive found, so retract cannot be used"))
+                       return // only print the first one of these
+               }
+
+               args := r.Syntax.Token
+               if args[0] == "retract" {
+                       args = args[1:]
+               }
+               vi, err := parseVersionInterval("retract", path, &args, fix)
+               if err != nil {
+                       wrapError(err)
+               }
+               r.VersionInterval = vi
+       }
+}
+
 // isIndirect reports whether line has a "// indirect" comment,
 // meaning it is in go.mod only for its effect on indirect dependencies,
 // so that it can be dropped entirely once the effective version of the
@@ -491,13 +548,13 @@ func AutoQuote(s string) string {
        return s
 }
 
-func parseVersionInterval(verb string, args *[]string, fix VersionFixer) (VersionInterval, error) {
+func parseVersionInterval(verb string, path string, args *[]string, fix VersionFixer) (VersionInterval, error) {
        toks := *args
        if len(toks) == 0 || toks[0] == "(" {
                return VersionInterval{}, fmt.Errorf("expected '[' or version")
        }
        if toks[0] != "[" {
-               v, err := parseVersion(verb, "", &toks[0], fix)
+               v, err := parseVersion(verb, path, &toks[0], fix)
                if err != nil {
                        return VersionInterval{}, err
                }
@@ -509,7 +566,7 @@ func parseVersionInterval(verb string, args *[]string, fix VersionFixer) (Versio
        if len(toks) == 0 {
                return VersionInterval{}, fmt.Errorf("expected version after '['")
        }
-       low, err := parseVersion(verb, "", &toks[0], fix)
+       low, err := parseVersion(verb, path, &toks[0], fix)
        if err != nil {
                return VersionInterval{}, err
        }
@@ -523,7 +580,7 @@ func parseVersionInterval(verb string, args *[]string, fix VersionFixer) (Versio
        if len(toks) == 0 {
                return VersionInterval{}, fmt.Errorf("expected version after ','")
        }
-       high, err := parseVersion(verb, "", &toks[0], fix)
+       high, err := parseVersion(verb, path, &toks[0], fix)
        if err != nil {
                return VersionInterval{}, err
        }
@@ -631,8 +688,7 @@ func parseVersion(verb string, path string, s *string, fix VersionFixer) (string
                }
        }
        if fix != nil {
-               var err error
-               t, err = fix(path, t)
+               fixed, err := fix(path, t)
                if err != nil {
                        if err, ok := err.(*module.ModuleError); ok {
                                return "", &Error{
@@ -643,19 +699,23 @@ func parseVersion(verb string, path string, s *string, fix VersionFixer) (string
                        }
                        return "", err
                }
+               t = fixed
+       } else {
+               cv := module.CanonicalVersion(t)
+               if cv == "" {
+                       return "", &Error{
+                               Verb:    verb,
+                               ModPath: path,
+                               Err: &module.InvalidVersionError{
+                                       Version: t,
+                                       Err:     errors.New("must be of the form v1.2.3"),
+                               },
+                       }
+               }
+               t = cv
        }
-       if v := module.CanonicalVersion(t); v != "" {
-               *s = v
-               return *s, nil
-       }
-       return "", &Error{
-               Verb:    verb,
-               ModPath: path,
-               Err: &module.InvalidVersionError{
-                       Version: t,
-                       Err:     errors.New("must be of the form v1.2.3"),
-               },
-       }
+       *s = t
+       return *s, nil
 }
 
 func modulePathMajor(path string) (string, error) {
index d961695a2b8195be07ba05601ae23077d16523cb..64caf62b8b3a8ad01b1664a6e807781f955be382 100644 (file)
@@ -28,7 +28,7 @@ golang.org/x/arch/x86/x86asm
 golang.org/x/crypto/ed25519
 golang.org/x/crypto/ed25519/internal/edwards25519
 golang.org/x/crypto/ssh/terminal
-# golang.org/x/mod v0.4.2-0.20210301183607-b038bf73c007
+# golang.org/x/mod v0.4.2-0.20210302225016-2823f815b3c9
 ## explicit
 golang.org/x/mod/internal/lazyregexp
 golang.org/x/mod/modfile