cmd/go/internal/module: basic definition of module.Version, module paths
diff --git a/vendor/cmd/go/internal/module/module.go b/vendor/cmd/go/internal/module/module.go
new file mode 100644
index 0000000..a5d28cc
--- /dev/null
+++ b/vendor/cmd/go/internal/module/module.go
@@ -0,0 +1,155 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package module defines the module.Version type
+// along with support code.
+package module
+
+import (
+	"fmt"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+
+	"cmd/go/internal/semver"
+)
+
+// A Version is defined by a module path and version pair.
+type Version struct {
+	Path    string
+	Version string
+}
+
+// Check checks that a given module path, version pair is valid.
+// In addition to the path being a valid module path
+// and the version being a valid semantic version,
+// the two must correspond.
+// For example, the path "yaml/v2" only corresponds to
+// semantic versions beginning with "v2.".
+func Check(path, version string) error {
+	if err := CheckPath(path); err != nil {
+		return err
+	}
+	if !semver.IsValid(version) {
+		return fmt.Errorf("malformed semantic version %v", version)
+	}
+	_, pathVersion, _ := SplitPathVersion(path)
+	pathVersion = strings.TrimPrefix(pathVersion, "/")
+	vm := semver.Major(version)
+	if vm == "v0" || vm == "v1" {
+		vm = ""
+	}
+	if vm != pathVersion {
+		if pathVersion == "" {
+			pathVersion = "v0 or v1"
+		}
+		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.
+// The first element of the path must be an LDH domain name, at least for now.
+func firstPathOK(r rune) bool {
+	return r == '-' || r == '.' ||
+		'0' <= r && r <= '9' ||
+		'A' <= r && r <= 'Z' ||
+		'a' <= r && r <= 'z'
+}
+
+// pathOK reports whether r can appear in a module path.
+// Paths must avoid potentially problematic ASCII punctuation
+// and control characters but otherwise can be any Unicode printable character,
+// as defined by Go's IsPrint.
+func pathOK(r rune) bool {
+	if r < utf8.RuneSelf {
+		return r == '+' || r == ',' || r == '-' || r == '.' || r == '/' || r == '_' || r == '~' ||
+			'0' <= r && r <= '9' ||
+			'A' <= r && r <= 'Z' ||
+			'a' <= r && r <= 'z'
+	}
+	return unicode.IsPrint(r)
+}
+
+// CheckPath checks that a module path is valid.
+func CheckPath(path string) error {
+	if !utf8.ValidString(path) {
+		return fmt.Errorf("malformed module path %q: invalid UTF-8", path)
+	}
+	if path == "" {
+		return fmt.Errorf("malformed module path %q: empty string", path)
+	}
+
+	i := strings.Index(path, "/")
+	if i < 0 {
+		i = len(path)
+	}
+	if i == 0 {
+		return fmt.Errorf("malformed module path %q: leading slash", path)
+	}
+	if !strings.Contains(path[:i], ".") {
+		return fmt.Errorf("malformed module path %q: missing dot in first path element", path)
+	}
+	if path[i-1] == '.' {
+		return fmt.Errorf("malformed module path %q: trailing dot in first path element", path)
+	}
+	if path[0] == '.' {
+		return fmt.Errorf("malformed module path %q: leading dot in first path element", path)
+	}
+	if path[0] == '-' {
+		return fmt.Errorf("malformed module path %q: leading dash in first path element", path)
+	}
+	if strings.Contains(path, "..") {
+		return fmt.Errorf("malformed module path %q: double dot", path)
+	}
+	if strings.Contains(path, "//") {
+		return fmt.Errorf("malformed module path %q: double slash", path)
+	}
+	for _, r := range path[:i] {
+		if !firstPathOK(r) {
+			return fmt.Errorf("malformed module path %q: invalid char %q in first path element", path, r)
+		}
+	}
+	if path[len(path)-1] == '/' {
+		return fmt.Errorf("malformed module path %q: trailing slash", path)
+	}
+	for _, r := range path {
+		if !pathOK(r) {
+			return fmt.Errorf("malformed module path %q: invalid char %q", path, r)
+		}
+	}
+	if _, _, ok := SplitPathVersion(path); !ok {
+		return fmt.Errorf("malformed module path %q: invalid version %s", path, path[strings.LastIndex(path, "/")+1:])
+	}
+	return nil
+}
+
+// SplitPathVersion returns pathPrefix and version such that pathPrefix+pathMajor == path
+// and version is either empty or "/vN" for N >= 2.
+func SplitPathVersion(path string) (pathPrefix, pathMajor string, ok bool) {
+	i := len(path)
+	dot := false
+	for i > 0 && ('0' <= path[i-1] && path[i-1] <= '9' || path[i-1] == '.') {
+		if path[i-1] == '.' {
+			dot = true
+		}
+		i--
+	}
+	if i <= 1 || path[i-1] != 'v' || path[i-2] != '/' {
+		return path, "", true
+	}
+	pathPrefix, pathMajor = path[:i-2], path[i-2:]
+	if dot || len(pathMajor) <= 2 || pathMajor[2] == '0' || pathMajor == "/v1" {
+		return path, "", false
+	}
+	return pathPrefix, pathMajor, true
+}
+
+func MatchPathMajor(v, pathMajor string) bool {
+	m := semver.Major(v)
+	if pathMajor == "" {
+		return m == "v0" || m == "v1"
+	}
+	return pathMajor[0] == '/' && m == pathMajor[1:]
+}
diff --git a/vendor/cmd/go/internal/module/module_test.go b/vendor/cmd/go/internal/module/module_test.go
new file mode 100644
index 0000000..a507fa1
--- /dev/null
+++ b/vendor/cmd/go/internal/module/module_test.go
@@ -0,0 +1,163 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package module
+
+import "testing"
+
+var checkTests = []struct {
+	path    string
+	version string
+	ok      bool
+}{
+	{"rsc.io/quote", "0.1.0", false},
+	{"rsc io/quote", "v1.0.0", false},
+
+	{"github.com/go-yaml/yaml", "v0.8.0", true},
+	{"github.com/go-yaml/yaml", "v1.0.0", true},
+	{"github.com/go-yaml/yaml", "v2.0.0", false},
+	{"github.com/go-yaml/yaml", "v2.1.5", false},
+	{"github.com/go-yaml/yaml", "v3.0.0", false},
+
+	{"github.com/go-yaml/yaml/v2", "v1.0.0", false},
+	{"github.com/go-yaml/yaml/v2", "v2.0.0", true},
+	{"github.com/go-yaml/yaml/v2", "v2.1.5", true},
+	{"github.com/go-yaml/yaml/v2", "v3.0.0", false},
+}
+
+func TestCheck(t *testing.T) {
+	for _, tt := range checkTests {
+		err := Check(tt.path, tt.version)
+		if tt.ok && err != nil {
+			t.Errorf("Check(%q, %q) = %v, wanted nil error", tt.path, tt.version, err)
+		} else if !tt.ok && err == nil {
+			t.Errorf("Check(%q, %q) succeeded, wanted error", tt.path, tt.version)
+		}
+	}
+}
+
+var checkPathTests = []struct {
+	path string
+	ok   bool
+}{
+	{"x.y/z", true},
+	{"x.y", true},
+
+	{"", false},
+	{"x.y/\xFFz", false},
+	{"/x.y/z", false},
+	{"x./z", false},
+	{".x/z", false},
+	{"-x/z", false},
+	{"x..y/z", false},
+	{"x.y/z/../../w", false},
+	{"x.y//z", false},
+	{"x.y/z//w", false},
+	{"x.y/z/", false},
+
+	{"x.y/z/v0", false},
+	{"x.y/z/v1", false},
+	{"x.y/z/v2", true},
+	{"x.y/z/v2.0", false},
+
+	{"!x.y/z", false},
+	{"_x.y/z", false},
+	{"x.y!/z", false},
+	{"x.y\"/z", false},
+	{"x.y#/z", false},
+	{"x.y$/z", false},
+	{"x.y%/z", false},
+	{"x.y&/z", false},
+	{"x.y'/z", false},
+	{"x.y(/z", false},
+	{"x.y)/z", false},
+	{"x.y*/z", false},
+	{"x.y+/z", false},
+	{"x.y,/z", false},
+	{"x.y-/z", true},
+	{"x.y./zt", false},
+	{"x.y:/z", false},
+	{"x.y;/z", false},
+	{"x.y</z", false},
+	{"x.y=/z", false},
+	{"x.y>/z", false},
+	{"x.y?/z", false},
+	{"x.y@/z", false},
+	{"x.y[/z", false},
+	{"x.y\\/z", false},
+	{"x.y]/z", false},
+	{"x.y^/z", false},
+	{"x.y_/z", false},
+	{"x.y`/z", false},
+	{"x.y{/z", false},
+	{"x.y}/z", false},
+	{"x.y~/z", false},
+	{"x.y/z!", false},
+	{"x.y/z\"", false},
+	{"x.y/z#", false},
+	{"x.y/z$", false},
+	{"x.y/z%", false},
+	{"x.y/z&", false},
+	{"x.y/z'", false},
+	{"x.y/z(", false},
+	{"x.y/z)", false},
+	{"x.y/z*", false},
+	{"x.y/z+", true},
+	{"x.y/z,", true},
+	{"x.y/z-", true},
+	{"x.y/z.t", true},
+	{"x.y/z/t", true},
+	{"x.y/z:", false},
+	{"x.y/z;", false},
+	{"x.y/z<", false},
+	{"x.y/z=", false},
+	{"x.y/z>", false},
+	{"x.y/z?", false},
+	{"x.y/z@", false},
+	{"x.y/z[", false},
+	{"x.y/z\\", false},
+	{"x.y/z]", false},
+	{"x.y/z^", false},
+	{"x.y/z_", true},
+	{"x.y/z`", false},
+	{"x.y/z{", false},
+	{"x.y/z}", false},
+	{"x.y/z~", true},
+}
+
+func TestCheckPath(t *testing.T) {
+	for _, tt := range checkPathTests {
+		err := CheckPath(tt.path)
+		if tt.ok && err != nil {
+			t.Errorf("CheckPath(%q) = %v, wanted nil error", tt.path, err)
+		} else if !tt.ok && err == nil {
+			t.Errorf("CheckPath(%q) succeeded, wanted error", tt.path)
+		}
+	}
+}
+
+var splitPathVersionTests = []struct {
+	pathPrefix string
+	version    string
+}{
+	{"x.y/z", ""},
+	{"x.y/z", "/v2"},
+	{"x.y/z", "/v3"},
+}
+
+func TestSplitPathVersion(t *testing.T) {
+	for _, tt := range splitPathVersionTests {
+		pathPrefix, version, ok := SplitPathVersion(tt.pathPrefix + tt.version)
+		if pathPrefix != tt.pathPrefix || version != tt.version || !ok {
+			t.Errorf("SplitPathVersion(%q) = %q, %q, %v, want %q, %q, true", tt.pathPrefix+tt.version, pathPrefix, version, ok, tt.pathPrefix, tt.version)
+		}
+	}
+
+	for _, tt := range checkPathTests {
+		pathPrefix, version, ok := SplitPathVersion(tt.path)
+		if pathPrefix+version != tt.path {
+			t.Errorf("SplitPathVersion(%q) = %q, %q, %v, doesn't add to input", tt.path, pathPrefix, version, ok)
+		}
+	}
+}