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)
+			}
+		})
+	}
+}