]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go/internal/module: allow v0.0.0 pseudoversion for gopkg.in/check.v1
authorRuss Cox <rsc@golang.org>
Tue, 17 Jul 2018 02:40:05 +0000 (22:40 -0400)
committerRuss Cox <rsc@golang.org>
Wed, 18 Jul 2018 02:09:03 +0000 (02:09 +0000)
It worked once. It needs to keep working.

Change-Id: Iaa43726e1c78f0c4a20b5805c7c2bfa76fab2489
Reviewed-on: https://go-review.googlesource.com/124383
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
src/cmd/go/internal/module/module.go
src/cmd/go/internal/module/module_test.go
src/cmd/go/mod_test.go
src/cmd/go/testdata/mod/rsc.io_badfile3_v1.0.0.txt

index 629aca1a1059d4ca05f491a7870723940aba4de7..11a45e092b08a7d415e4bd01f6dbc77dd95a1582 100644 (file)
@@ -12,6 +12,9 @@ package module
 // There are many subtle considerations, including Unicode ambiguity,
 // security, network, and file system representations.
 //
+// This file also defines the set of valid module path and version combinations,
+// another topic with many subtle considerations.
+//
 // Changes to the semantics in this file require approval from rsc.
 
 import (
@@ -50,31 +53,17 @@ func Check(path, version string) error {
        if !semver.IsValid(version) {
                return fmt.Errorf("malformed semantic version %v", version)
        }
-       vm := semver.Major(version)
-       _, pathVersion, _ := SplitPathVersion(path)
-
-       if strings.HasPrefix(pathVersion, ".") {
-               // Special-case gopkg.in path requirements.
-               pathVersion = pathVersion[1:] // cut .
-               if vm == pathVersion {
-                       return nil
-               }
-       } else {
-               // Standard path requirements.
-               if pathVersion != "" {
-                       pathVersion = pathVersion[1:] // cut /
-               }
-               if vm == "v0" || vm == "v1" {
-                       vm = ""
+       _, pathMajor, _ := SplitPathVersion(path)
+       if !MatchPathMajor(version, pathMajor) {
+               if pathMajor == "" {
+                       pathMajor = "v0 or v1"
                }
-               if vm == pathVersion {
-                       return nil
-               }
-               if pathVersion == "" {
-                       pathVersion = "v0 or v1"
+               if pathMajor[0] == '.' { // .v1
+                       pathMajor = pathMajor[1:]
                }
+               return fmt.Errorf("mismatched module path %v and version %v (want %v)", path, version, pathMajor)
        }
-       return fmt.Errorf("mismatched module path %v and version %v (want %v)", path, version, pathVersion)
+       return nil
 }
 
 // firstPathOK reports whether r can appear in the first element of a module path.
@@ -328,6 +317,11 @@ func splitGopkgIn(path string) (prefix, pathMajor string, ok bool) {
 // MatchPathMajor reports whether the semantic version v
 // matches the path major version pathMajor.
 func MatchPathMajor(v, pathMajor string) bool {
+       if strings.HasPrefix(v, "v0.0.0-") && pathMajor == ".v1" {
+               // Allow old bug in pseudo-versions that generated v0.0.0- pseudoversion for gopkg .v1.
+               // For example, gopkg.in/yaml.v2@v2.2.1's go.mod requires gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405.
+               return true
+       }
        m := semver.Major(v)
        if pathMajor == "" {
                return m == "v0" || m == "v1"
index 83e8d1af1b0354f3c325844cefea0552e1d222e5..686e2897ea05843d1ff755d84c1827c8ee23f19f 100644 (file)
@@ -37,6 +37,14 @@ var checkTests = []struct {
        {"gopkg.in/yaml.v1", "v2.1.5", false},
        {"gopkg.in/yaml.v1", "v3.0.0", false},
 
+       // For gopkg.in, .v1 means v1 only (not v0).
+       // But early versions of vgo still generated v0 pseudo-versions for it.
+       // Even though now we'd generate those as v1 pseudo-versions,
+       // we accept the old pseudo-versions to avoid breaking existing go.mod files.
+       // For example gopkg.in/yaml.v2@v2.2.1's go.mod requires check.v1 at a v0 pseudo-version.
+       {"gopkg.in/check.v1", "v0.0.0", false},
+       {"gopkg.in/check.v1", "v0.0.0-20160102150405-abcdef123456", true},
+
        {"gopkg.in/yaml.v2", "v1.0.0", false},
        {"gopkg.in/yaml.v2", "v2.0.0", true},
        {"gopkg.in/yaml.v2", "v2.1.5", true},
index 3e8a01090ba4214f8fa22757ae96ed1004f62b62..0199559fd2640ff2e1c180dcfaab059a93f7ab1f 100644 (file)
@@ -834,14 +834,12 @@ func TestModFileNames(t *testing.T) {
                "rsc.io/badfile3",
                "rsc.io/badfile4",
                "rsc.io/badfile5",
-               "rsc.io/badfile6",
        )
        tg.grepStderrNot(`unzip .*badfile1.*:`, "badfile1 should be OK")
        tg.grepStderr(`rsc.io/badfile2.*malformed file path "☺.go": invalid char '☺'`, "want diagnosed invalid character")
-       tg.grepStderr(`rsc.io/badfile3.*malformed file path "x@y.go": invalid char '@'`, "want diagnosed invalid character")
+       tg.grepStderr(`rsc.io/badfile3.*malformed file path "x\?y.go": invalid char '\?'`, "want diagnosed invalid character")
        tg.grepStderr(`rsc.io/badfile4.*case-insensitive file name collision: "x/Y.go" and "x/y.go"`, "want case collision")
        tg.grepStderr(`rsc.io/badfile5.*case-insensitive file name collision: "x/y" and "x/Y"`, "want case collision")
-       tg.grepStderr(`rsc.io/badfile6.*malformed file path "x/.gitignore/y": leading dot in path element`, "want leading dot in path element")
 }
 
 func TestModBadDomain(t *testing.T) {
index 91bd65f9036f8eaa1ade3cbf4627665ad404ec09..a008448c5fd27a32e81d5370536ae621611a089e 100644 (file)
@@ -7,6 +7,6 @@ module rsc.io/badfile3
 {"Version":"v1.0.0"}
 -- go.mod --
 module rsc.io/badfile3
--- x@y.go --
+-- x?y.go --
 package x