cmd/go/internal/modfetch: fix bug in parsing non-quoted module paths CL 105215 introduced "allow, prefer unquoted strings in mod files", so autogenerated go.mod files do not contain quotes in the module path. Before, `modPath` could only handle quoted module paths. This lead to bugs like `vgo install github.com/Kyroy/vgoversion2/v2` installing v1.0.0 instead of v2.1.0 because `isMajor` returned false instead of true due to the wrong return of modPath. Hence, `findDir` returned "missing go.mod" error. Now, `modPath` is able to parse quoted and non-quoted module paths. Change-Id: I24b0a4cd60ce928b123fb1b347edf84f018f01a6 Reviewed-on: https://go-review.googlesource.com/114058 Reviewed-by: Bryan C. Mills <bcmills@google.com> Reviewed-by: Russ Cox <rsc@golang.org> Run-TryBot: Bryan C. Mills <bcmills@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/vendor/cmd/go/internal/modfetch/coderepo.go b/vendor/cmd/go/internal/modfetch/coderepo.go index ffbd223..bb6e8ac 100644 --- a/vendor/cmd/go/internal/modfetch/coderepo.go +++ b/vendor/cmd/go/internal/modfetch/coderepo.go
@@ -234,7 +234,7 @@ if found1 { return rev, r.codeDir, gomod1, nil } - return "", "", nil, fmt.Errorf("missing go.mod") + return "", "", nil, fmt.Errorf("missing or invalid go.mod") } func isMajor(gomod []byte, pathMajor string) bool { @@ -257,25 +257,19 @@ line = line[len(moduleStr):] n := len(line) line = bytes.TrimSpace(line) - if len(line) == n || len(line) == 0 || line[0] != '"' && line[0] != '`' { + if len(line) == n || len(line) == 0 { continue } - q := line[0] - i := 1 - for i < len(line) && line[i] != q { - if q == '"' && line[i] == '\\' { - i++ + + if line[0] == '"' || line[0] == '`' { + p, err := strconv.Unquote(string(line)) + if err != nil { + return "" // malformed quoted string or multiline module path } - i++ + return p } - if i >= len(line) { - return "" // malformed quoted string or multiline module path - } - p, err := strconv.Unquote(string(line[:i+1])) - if err != nil { - return "" - } - return p + + return string(line) } return "" // missing module path }
diff --git a/vendor/cmd/go/internal/modfetch/coderepo_test.go b/vendor/cmd/go/internal/modfetch/coderepo_test.go index 8821b02..80415b4 100644 --- a/vendor/cmd/go/internal/modfetch/coderepo_test.go +++ b/vendor/cmd/go/internal/modfetch/coderepo_test.go
@@ -657,3 +657,39 @@ t.Fatal("unexpected versions returned:", v) } } + +var modPathTests = []struct { + input []byte + expected string +}{ + {input: []byte("module \"github.com/rsc/vgotest\""), expected: "github.com/rsc/vgotest"}, + {input: []byte("module github.com/rsc/vgotest"), expected: "github.com/rsc/vgotest"}, + {input: []byte("module \"github.com/rsc/vgotest\""), expected: "github.com/rsc/vgotest"}, + {input: []byte("module github.com/rsc/vgotest"), expected: "github.com/rsc/vgotest"}, + {input: []byte("module `github.com/rsc/vgotest`"), expected: "github.com/rsc/vgotest"}, + {input: []byte("module \"github.com/rsc/vgotest/v2\""), expected: "github.com/rsc/vgotest/v2"}, + {input: []byte("module github.com/rsc/vgotest/v2"), expected: "github.com/rsc/vgotest/v2"}, + {input: []byte("module \"gopkg.in/yaml.v2\""), expected: "gopkg.in/yaml.v2"}, + {input: []byte("module gopkg.in/yaml.v2"), expected: "gopkg.in/yaml.v2"}, + {input: []byte("module \"gopkg.in/check.v1\"\n"), expected: "gopkg.in/check.v1"}, + {input: []byte("module \"gopkg.in/check.v1\n\""), expected: ""}, + {input: []byte("module gopkg.in/check.v1\n"), expected: "gopkg.in/check.v1"}, + {input: []byte("module \"gopkg.in/check.v1\"\r\n"), expected: "gopkg.in/check.v1"}, + {input: []byte("module gopkg.in/check.v1\r\n"), expected: "gopkg.in/check.v1"}, + {input: []byte("module \"gopkg.in/check.v1\"\n\n"), expected: "gopkg.in/check.v1"}, + {input: []byte("module gopkg.in/check.v1\n\n"), expected: "gopkg.in/check.v1"}, + {input: []byte("module \n\"gopkg.in/check.v1\"\n\n"), expected: ""}, + {input: []byte("module \ngopkg.in/check.v1\n\n"), expected: ""}, + {input: []byte("module \"gopkg.in/check.v1\"asd"), expected: ""}, +} + +func TestModPath(t *testing.T) { + for _, test := range modPathTests { + t.Run(string(test.input), func(t *testing.T) { + result := modPath(test.input) + if result != test.expected { + t.Fatalf("modPath(%s): %s, want %s", string(test.input), result, test.expected) + } + }) + } +}