all: use golang.org/x/mod

Use the semver and module packages from golang.org/x/mod.  Remove them
from internal/thirdparty.

We also rename Encode{Version,Path} to Escape{Version,Path} because
golang.org/x/module does that.

Fixes b/133841935.

Change-Id: I0e52c6dd7109fbd488a030c750cdc06736356868
Reviewed-on: https://team-review.git.corp.google.com/c/golang/discovery/+/619244
CI-Result: Cloud Build <devtools-proctor-result-processor@system.gserviceaccount.com>
Reviewed-by: Julie Qiu <julieqiu@google.com>
diff --git a/go.mod b/go.mod
index c88cc48..a7d6856 100644
--- a/go.mod
+++ b/go.mod
@@ -40,6 +40,7 @@
 	github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036 // indirect
 	go.opencensus.io v0.22.1
 	golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392
+	golang.org/x/mod v0.1.0
 	golang.org/x/net v0.0.0-20191007182048-72f939374954
 	golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
 	golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
diff --git a/go.sum b/go.sum
index 4371a19..53c5e07 100644
--- a/go.sum
+++ b/go.sum
@@ -349,6 +349,7 @@
 golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
 golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
 golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/mod v0.1.0 h1:sfUMP1Gu8qASkorDVjnMuvgJzwFbTZSeXFiGBYAVdl4=
 golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
 golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
diff --git a/internal/discovery.go b/internal/discovery.go
index d90eca3..349b331 100644
--- a/internal/discovery.go
+++ b/internal/discovery.go
@@ -9,7 +9,7 @@
 
 	"golang.org/x/discovery/internal/license"
 	"golang.org/x/discovery/internal/source"
-	"golang.org/x/discovery/internal/thirdparty/module"
+	"golang.org/x/mod/module"
 	"golang.org/x/discovery/internal/version"
 )
 
diff --git a/internal/frontend/details.go b/internal/frontend/details.go
index e387d32..a2a9a03 100644
--- a/internal/frontend/details.go
+++ b/internal/frontend/details.go
@@ -16,8 +16,8 @@
 	"golang.org/x/discovery/internal/license"
 	"golang.org/x/discovery/internal/log"
 	"golang.org/x/discovery/internal/stdlib"
-	"golang.org/x/discovery/internal/thirdparty/module"
-	"golang.org/x/discovery/internal/thirdparty/semver"
+	"golang.org/x/mod/module"
+	"golang.org/x/mod/semver"
 	"golang.org/x/xerrors"
 )
 
diff --git a/internal/frontend/header.go b/internal/frontend/header.go
index 720f3fd..ee58b03 100644
--- a/internal/frontend/header.go
+++ b/internal/frontend/header.go
@@ -16,7 +16,7 @@
 	"golang.org/x/discovery/internal/license"
 	"golang.org/x/discovery/internal/middleware"
 	"golang.org/x/discovery/internal/stdlib"
-	"golang.org/x/discovery/internal/thirdparty/module"
+	"golang.org/x/mod/module"
 )
 
 // Package contains information for an individual package.
diff --git a/internal/frontend/stdlib.go b/internal/frontend/stdlib.go
index ef3758b..e3a51c6 100644
--- a/internal/frontend/stdlib.go
+++ b/internal/frontend/stdlib.go
@@ -13,7 +13,7 @@
 	"golang.org/x/discovery/internal/derrors"
 	"golang.org/x/discovery/internal/log"
 	"golang.org/x/discovery/internal/stdlib"
-	"golang.org/x/discovery/internal/thirdparty/module"
+	"golang.org/x/mod/module"
 )
 
 // handleStdLib handles a request for a stdlib package or module.
diff --git a/internal/frontend/versions.go b/internal/frontend/versions.go
index 047148f..940cd1f 100644
--- a/internal/frontend/versions.go
+++ b/internal/frontend/versions.go
@@ -14,8 +14,8 @@
 	"golang.org/x/discovery/internal"
 	"golang.org/x/discovery/internal/log"
 	"golang.org/x/discovery/internal/stdlib"
-	"golang.org/x/discovery/internal/thirdparty/module"
-	"golang.org/x/discovery/internal/thirdparty/semver"
+	"golang.org/x/mod/module"
+	"golang.org/x/mod/semver"
 	"golang.org/x/discovery/internal/version"
 )
 
diff --git a/internal/license/detect.go b/internal/license/detect.go
index b2b7d25..ba128fe 100644
--- a/internal/license/detect.go
+++ b/internal/license/detect.go
@@ -14,7 +14,7 @@
 
 	"github.com/google/licensecheck"
 	"golang.org/x/discovery/internal/derrors"
-	"golang.org/x/discovery/internal/thirdparty/module"
+	"golang.org/x/mod/module"
 )
 
 const (
diff --git a/internal/postgres/insert_version.go b/internal/postgres/insert_version.go
index 5a40e67..745737d 100644
--- a/internal/postgres/insert_version.go
+++ b/internal/postgres/insert_version.go
@@ -19,8 +19,8 @@
 	"golang.org/x/discovery/internal/database"
 	"golang.org/x/discovery/internal/derrors"
 	"golang.org/x/discovery/internal/stdlib"
-	"golang.org/x/discovery/internal/thirdparty/module"
-	"golang.org/x/discovery/internal/thirdparty/semver"
+	"golang.org/x/mod/module"
+	"golang.org/x/mod/semver"
 	"golang.org/x/discovery/internal/version"
 	"golang.org/x/xerrors"
 )
diff --git a/internal/proxy/client.go b/internal/proxy/client.go
index 1581511..3f6350f 100644
--- a/internal/proxy/client.go
+++ b/internal/proxy/client.go
@@ -22,7 +22,7 @@
 	"go.opencensus.io/plugin/ochttp"
 	"golang.org/x/discovery/internal"
 	"golang.org/x/discovery/internal/derrors"
-	"golang.org/x/discovery/internal/thirdparty/module"
+	"golang.org/x/mod/module"
 	"golang.org/x/net/context/ctxhttp"
 	"golang.org/x/xerrors"
 )
@@ -62,7 +62,7 @@
 // transforms that data into a *VersionInfo.
 func (c *Client) GetInfo(ctx context.Context, modulePath, version string) (_ *VersionInfo, err error) {
 	defer derrors.Wrap(&err, "proxy.Client.GetInfo(%q, %q)", modulePath, version)
-	u, err := c.encodedURL(modulePath, version, "info")
+	u, err := c.escapedURL(modulePath, version, "info")
 	if err != nil {
 		return nil, err
 	}
@@ -90,7 +90,7 @@
 	if err != nil {
 		return nil, err
 	}
-	u, err := c.encodedURL(requestedPath, info.Version, "zip")
+	u, err := c.escapedURL(requestedPath, info.Version, "zip")
 	if err != nil {
 		return nil, err
 	}
@@ -113,15 +113,15 @@
 	return zipReader, nil
 }
 
-func (c *Client) encodedURL(modulePath, version, suffix string) (_ string, err error) {
+func (c *Client) escapedURL(modulePath, version, suffix string) (_ string, err error) {
 	defer func() {
-		derrors.Wrap(&err, "Client.encodedURL(%q, %q, %q)", modulePath, version, suffix)
+		derrors.Wrap(&err, "Client.escapedURL(%q, %q, %q)", modulePath, version, suffix)
 	}()
 
 	if suffix != "info" && suffix != "zip" {
 		return "", errors.New(`suffix must be "info" or "zip"`)
 	}
-	encodedPath, err := module.EncodePath(modulePath)
+	escapedPath, err := module.EscapePath(modulePath)
 	if err != nil {
 		return "", xerrors.Errorf("path: %v: %w", err, derrors.InvalidArgument)
 	}
@@ -129,23 +129,23 @@
 		if suffix != "info" {
 			return "", fmt.Errorf("cannot ask for latest with suffix %q", suffix)
 		}
-		return fmt.Sprintf("%s/%s/@latest", c.url, encodedPath), nil
+		return fmt.Sprintf("%s/%s/@latest", c.url, escapedPath), nil
 	}
-	encodedVersion, err := module.EncodeVersion(version)
+	escapedVersion, err := module.EscapeVersion(version)
 	if err != nil {
 		return "", xerrors.Errorf("version: %v: %w", err, derrors.InvalidArgument)
 	}
-	return fmt.Sprintf("%s/%s/@v/%s.%s", c.url, encodedPath, encodedVersion, suffix), nil
+	return fmt.Sprintf("%s/%s/@v/%s.%s", c.url, escapedPath, escapedVersion, suffix), nil
 }
 
 // ListVersions makes a request to $GOPROXY/<path>/@v/list and returns the
 // resulting version strings.
 func (c *Client) ListVersions(ctx context.Context, modulePath string) ([]string, error) {
-	encodedPath, err := module.EncodePath(modulePath)
+	escapedPath, err := module.EscapePath(modulePath)
 	if err != nil {
-		return nil, xerrors.Errorf("module.EncodePath(%q): %w", modulePath, derrors.InvalidArgument)
+		return nil, xerrors.Errorf("module.EscapePath(%q): %w", modulePath, derrors.InvalidArgument)
 	}
-	u := fmt.Sprintf("%s/%s/@v/list", c.url, encodedPath)
+	u := fmt.Sprintf("%s/%s/@v/list", c.url, escapedPath)
 	var versions []string
 	collect := func(body io.Reader) error {
 		scanner := bufio.NewScanner(body)
diff --git a/internal/proxy/client_test.go b/internal/proxy/client_test.go
index e58da52..a226cd4 100644
--- a/internal/proxy/client_test.go
+++ b/internal/proxy/client_test.go
@@ -227,7 +227,7 @@
 			"", // only "info" or "zip"
 		},
 	} {
-		got, err := c.encodedURL(test.path, test.version, test.suffix)
+		got, err := c.escapedURL(test.path, test.version, test.suffix)
 		if got != test.want || (err != nil) != (test.want == "") {
 			t.Errorf("%s, %s, %s: got (%q, %v), want %q", test.path, test.version, test.suffix, got, err, test.want)
 		}
diff --git a/internal/proxy/test_helper.go b/internal/proxy/test_helper.go
index 9434b8b..c8fe25d 100644
--- a/internal/proxy/test_helper.go
+++ b/internal/proxy/test_helper.go
@@ -19,7 +19,7 @@
 	"time"
 
 	"golang.org/x/discovery/internal/testing/testhelper"
-	"golang.org/x/discovery/internal/thirdparty/semver"
+	"golang.org/x/mod/semver"
 )
 
 // TestVersion represents a module version to host in the fake proxy.
diff --git a/internal/proxydatasource/datasource.go b/internal/proxydatasource/datasource.go
index 4c9e274..8765084 100644
--- a/internal/proxydatasource/datasource.go
+++ b/internal/proxydatasource/datasource.go
@@ -18,7 +18,7 @@
 	"golang.org/x/discovery/internal/etl"
 	"golang.org/x/discovery/internal/license"
 	"golang.org/x/discovery/internal/proxy"
-	"golang.org/x/discovery/internal/thirdparty/semver"
+	"golang.org/x/mod/semver"
 	"golang.org/x/discovery/internal/version"
 	"golang.org/x/xerrors"
 )
diff --git a/internal/stdlib/stdlib.go b/internal/stdlib/stdlib.go
index 15dabc9..9b9adb0 100644
--- a/internal/stdlib/stdlib.go
+++ b/internal/stdlib/stdlib.go
@@ -23,7 +23,7 @@
 
 	"golang.org/x/discovery/internal/derrors"
 	"golang.org/x/discovery/internal/testing/testhelper"
-	"golang.org/x/discovery/internal/thirdparty/semver"
+	"golang.org/x/mod/semver"
 
 	"gopkg.in/src-d/go-billy.v4/osfs"
 	"gopkg.in/src-d/go-git.v4"
diff --git a/internal/stdlib/stdlib_test.go b/internal/stdlib/stdlib_test.go
index a116cba..5ceda9c 100644
--- a/internal/stdlib/stdlib_test.go
+++ b/internal/stdlib/stdlib_test.go
@@ -9,7 +9,7 @@
 	"strings"
 	"testing"
 
-	"golang.org/x/discovery/internal/thirdparty/semver"
+	"golang.org/x/mod/semver"
 )
 
 func TestTagForVersion(t *testing.T) {
diff --git a/internal/thirdparty/modfile/rule.go b/internal/thirdparty/modfile/rule.go
index f0b3093..9d3fba2 100644
--- a/internal/thirdparty/modfile/rule.go
+++ b/internal/thirdparty/modfile/rule.go
@@ -19,8 +19,8 @@
 	"strings"
 	"unicode"
 
-	"golang.org/x/discovery/internal/thirdparty/module"
-	"golang.org/x/discovery/internal/thirdparty/semver"
+	"golang.org/x/mod/module"
+	"golang.org/x/mod/semver"
 )
 
 // A File is the parsed, interpreted form of a go.mod file.
diff --git a/internal/thirdparty/module/module.go b/internal/thirdparty/module/module.go
deleted file mode 100644
index 8e11496..0000000
--- a/internal/thirdparty/module/module.go
+++ /dev/null
@@ -1,544 +0,0 @@
-// DO NOT EDIT. This file was copied from
-// https://go.googlesource.com/go/+/db7e7469/src/cmd/go/internal/module.
-// generated by internal/thirdparty/download.go -pkg=module
-
-// 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
-
-// IMPORTANT NOTE
-//
-// This file essentially defines the set of valid import paths for the go command.
-// 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 (
-	"fmt"
-	"sort"
-	"strings"
-	"unicode"
-	"unicode/utf8"
-
-	"golang.org/x/discovery/internal/thirdparty/semver"
-)
-
-// A Version is defined by a module path and version pair.
-type Version struct {
-	Path string
-
-	// Version is usually a semantic version in canonical form.
-	// There are two exceptions to this general rule.
-	// First, the top-level target of a build has no specific version
-	// and uses Version = "".
-	// Second, during MVS calculations the version "none" is used
-	// to represent the decision to take no version of a given module.
-	Version string `json:",omitempty"`
-}
-
-// 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)
-	}
-	_, pathMajor, _ := SplitPathVersion(path)
-	if !MatchPathMajor(version, pathMajor) {
-		if pathMajor == "" {
-			pathMajor = "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 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.
-// To avoid case ambiguity, the domain name must be entirely lower case.
-func firstPathOK(r rune) bool {
-	return r == '-' || r == '.' ||
-		'0' <= r && r <= '9' ||
-		'a' <= r && r <= 'z'
-}
-
-// pathOK reports whether r can appear in an import path element.
-// Paths can be ASCII letters, ASCII digits, and limited ASCII punctuation: + - . _ and ~.
-// This matches what "go get" has historically recognized in import paths.
-// TODO(rsc): We would like to allow Unicode letters, but that requires additional
-// care in the safe encoding (see note below).
-func pathOK(r rune) bool {
-	if r < utf8.RuneSelf {
-		return r == '+' || r == '-' || r == '.' || r == '_' || r == '~' ||
-			'0' <= r && r <= '9' ||
-			'A' <= r && r <= 'Z' ||
-			'a' <= r && r <= 'z'
-	}
-	return false
-}
-
-// fileNameOK reports whether r can appear in a file name.
-// For now we allow all Unicode letters but otherwise limit to pathOK plus a few more punctuation characters.
-// If we expand the set of allowed characters here, we have to
-// work harder at detecting potential case-folding and normalization collisions.
-// See note about "safe encoding" below.
-func fileNameOK(r rune) bool {
-	if r < utf8.RuneSelf {
-		// Entire set of ASCII punctuation, from which we remove characters:
-		//     ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
-		// We disallow some shell special characters: " ' * < > ? ` |
-		// (Note that some of those are disallowed by the Windows file system as well.)
-		// We also disallow path separators / : and \ (fileNameOK is only called on path element characters).
-		// We allow spaces (U+0020) in file names.
-		const allowed = "!#$%&()+,-.=@[]^_{}~ "
-		if '0' <= r && r <= '9' || 'A' <= r && r <= 'Z' || 'a' <= r && r <= 'z' {
-			return true
-		}
-		for i := 0; i < len(allowed); i++ {
-			if rune(allowed[i]) == r {
-				return true
-			}
-		}
-		return false
-	}
-	// It may be OK to add more ASCII punctuation here, but only carefully.
-	// For example Windows disallows < > \, and macOS disallows :, so we must not allow those.
-	return unicode.IsLetter(r)
-}
-
-// CheckPath checks that a module path is valid.
-func CheckPath(path string) error {
-	if err := checkPath(path, false); err != nil {
-		return fmt.Errorf("malformed module path %q: %v", path, err)
-	}
-	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[0] == '-' {
-		return fmt.Errorf("malformed module path %q: leading dash in first path element", 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 _, _, ok := SplitPathVersion(path); !ok {
-		return fmt.Errorf("malformed module path %q: invalid version", path)
-	}
-	return nil
-}
-
-// CheckImportPath checks that an import path is valid.
-func CheckImportPath(path string) error {
-	if err := checkPath(path, false); err != nil {
-		return fmt.Errorf("malformed import path %q: %v", path, err)
-	}
-	return nil
-}
-
-// checkPath checks that a general path is valid.
-// It returns an error describing why but not mentioning path.
-// Because these checks apply to both module paths and import paths,
-// the caller is expected to add the "malformed ___ path %q: " prefix.
-// fileName indicates whether the final element of the path is a file name
-// (as opposed to a directory name).
-func checkPath(path string, fileName bool) error {
-	if !utf8.ValidString(path) {
-		return fmt.Errorf("invalid UTF-8")
-	}
-	if path == "" {
-		return fmt.Errorf("empty string")
-	}
-	if strings.Contains(path, "..") {
-		return fmt.Errorf("double dot")
-	}
-	if strings.Contains(path, "//") {
-		return fmt.Errorf("double slash")
-	}
-	if path[len(path)-1] == '/' {
-		return fmt.Errorf("trailing slash")
-	}
-	elemStart := 0
-	for i, r := range path {
-		if r == '/' {
-			if err := checkElem(path[elemStart:i], fileName); err != nil {
-				return err
-			}
-			elemStart = i + 1
-		}
-	}
-	if err := checkElem(path[elemStart:], fileName); err != nil {
-		return err
-	}
-	return nil
-}
-
-// checkElem checks whether an individual path element is valid.
-// fileName indicates whether the element is a file name (not a directory name).
-func checkElem(elem string, fileName bool) error {
-	if elem == "" {
-		return fmt.Errorf("empty path element")
-	}
-	if strings.Count(elem, ".") == len(elem) {
-		return fmt.Errorf("invalid path element %q", elem)
-	}
-	if elem[0] == '.' && !fileName {
-		return fmt.Errorf("leading dot in path element")
-	}
-	if elem[len(elem)-1] == '.' {
-		return fmt.Errorf("trailing dot in path element")
-	}
-	charOK := pathOK
-	if fileName {
-		charOK = fileNameOK
-	}
-	for _, r := range elem {
-		if !charOK(r) {
-			return fmt.Errorf("invalid char %q", r)
-		}
-	}
-
-	// Windows disallows a bunch of path elements, sadly.
-	// See https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file
-	short := elem
-	if i := strings.Index(short, "."); i >= 0 {
-		short = short[:i]
-	}
-	for _, bad := range badWindowsNames {
-		if strings.EqualFold(bad, short) {
-			return fmt.Errorf("%q disallowed as path element component on Windows", short)
-		}
-	}
-	return nil
-}
-
-// CheckFilePath checks whether a slash-separated file path is valid.
-func CheckFilePath(path string) error {
-	if err := checkPath(path, true); err != nil {
-		return fmt.Errorf("malformed file path %q: %v", path, err)
-	}
-	return nil
-}
-
-// badWindowsNames are the reserved file path elements on Windows.
-// See https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file
-var badWindowsNames = []string{
-	"CON",
-	"PRN",
-	"AUX",
-	"NUL",
-	"COM1",
-	"COM2",
-	"COM3",
-	"COM4",
-	"COM5",
-	"COM6",
-	"COM7",
-	"COM8",
-	"COM9",
-	"LPT1",
-	"LPT2",
-	"LPT3",
-	"LPT4",
-	"LPT5",
-	"LPT6",
-	"LPT7",
-	"LPT8",
-	"LPT9",
-}
-
-// SplitPathVersion returns prefix and major version such that prefix+pathMajor == path
-// and version is either empty or "/vN" for N >= 2.
-// As a special case, gopkg.in paths are recognized directly;
-// they require ".vN" instead of "/vN", and for all N, not just N >= 2.
-func SplitPathVersion(path string) (prefix, pathMajor string, ok bool) {
-	if strings.HasPrefix(path, "gopkg.in/") {
-		return splitGopkgIn(path)
-	}
-
-	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 || i == len(path) || path[i-1] != 'v' || path[i-2] != '/' {
-		return path, "", true
-	}
-	prefix, pathMajor = path[:i-2], path[i-2:]
-	if dot || len(pathMajor) <= 2 || pathMajor[2] == '0' || pathMajor == "/v1" {
-		return path, "", false
-	}
-	return prefix, pathMajor, true
-}
-
-// splitGopkgIn is like SplitPathVersion but only for gopkg.in paths.
-func splitGopkgIn(path string) (prefix, pathMajor string, ok bool) {
-	if !strings.HasPrefix(path, "gopkg.in/") {
-		return path, "", false
-	}
-	i := len(path)
-	if strings.HasSuffix(path, "-unstable") {
-		i -= len("-unstable")
-	}
-	for i > 0 && ('0' <= path[i-1] && path[i-1] <= '9') {
-		i--
-	}
-	if i <= 1 || path[i-1] != 'v' || path[i-2] != '.' {
-		// All gopkg.in paths must end in vN for some N.
-		return path, "", false
-	}
-	prefix, pathMajor = path[:i-2], path[i-2:]
-	if len(pathMajor) <= 2 || pathMajor[2] == '0' && pathMajor != ".v0" {
-		return path, "", false
-	}
-	return prefix, pathMajor, true
-}
-
-// MatchPathMajor reports whether the semantic version v
-// matches the path major version pathMajor.
-func MatchPathMajor(v, pathMajor string) bool {
-	if strings.HasPrefix(pathMajor, ".v") && strings.HasSuffix(pathMajor, "-unstable") {
-		pathMajor = strings.TrimSuffix(pathMajor, "-unstable")
-	}
-	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" || semver.Build(v) == "+incompatible"
-	}
-	return (pathMajor[0] == '/' || pathMajor[0] == '.') && m == pathMajor[1:]
-}
-
-// CanonicalVersion returns the canonical form of the version string v.
-// It is the same as semver.Canonical(v) except that it preserves the special build suffix "+incompatible".
-func CanonicalVersion(v string) string {
-	cv := semver.Canonical(v)
-	if semver.Build(v) == "+incompatible" {
-		cv += "+incompatible"
-	}
-	return cv
-}
-
-// Sort sorts the list by Path, breaking ties by comparing Versions.
-func Sort(list []Version) {
-	sort.Slice(list, func(i, j int) bool {
-		mi := list[i]
-		mj := list[j]
-		if mi.Path != mj.Path {
-			return mi.Path < mj.Path
-		}
-		// To help go.sum formatting, allow version/file.
-		// Compare semver prefix by semver rules,
-		// file by string order.
-		vi := mi.Version
-		vj := mj.Version
-		var fi, fj string
-		if k := strings.Index(vi, "/"); k >= 0 {
-			vi, fi = vi[:k], vi[k:]
-		}
-		if k := strings.Index(vj, "/"); k >= 0 {
-			vj, fj = vj[:k], vj[k:]
-		}
-		if vi != vj {
-			return semver.Compare(vi, vj) < 0
-		}
-		return fi < fj
-	})
-}
-
-// Safe encodings
-//
-// Module paths appear as substrings of file system paths
-// (in the download cache) and of web server URLs in the proxy protocol.
-// In general we cannot rely on file systems to be case-sensitive,
-// nor can we rely on web servers, since they read from file systems.
-// That is, we cannot rely on the file system to keep rsc.io/QUOTE
-// and rsc.io/quote separate. Windows and macOS don't.
-// Instead, we must never require two different casings of a file path.
-// Because we want the download cache to match the proxy protocol,
-// and because we want the proxy protocol to be possible to serve
-// from a tree of static files (which might be stored on a case-insensitive
-// file system), the proxy protocol must never require two different casings
-// of a URL path either.
-//
-// One possibility would be to make the safe encoding be the lowercase
-// hexadecimal encoding of the actual path bytes. This would avoid ever
-// needing different casings of a file path, but it would be fairly illegible
-// to most programmers when those paths appeared in the file system
-// (including in file paths in compiler errors and stack traces)
-// in web server logs, and so on. Instead, we want a safe encoding that
-// leaves most paths unaltered.
-//
-// The safe encoding is this:
-// replace every uppercase letter with an exclamation mark
-// followed by the letter's lowercase equivalent.
-//
-// For example,
-// github.com/Azure/azure-sdk-for-go ->  github.com/!azure/azure-sdk-for-go.
-// github.com/GoogleCloudPlatform/cloudsql-proxy -> github.com/!google!cloud!platform/cloudsql-proxy
-// github.com/Sirupsen/logrus -> github.com/!sirupsen/logrus.
-//
-// Import paths that avoid upper-case letters are left unchanged.
-// Note that because import paths are ASCII-only and avoid various
-// problematic punctuation (like : < and >), the safe encoding is also ASCII-only
-// and avoids the same problematic punctuation.
-//
-// Import paths have never allowed exclamation marks, so there is no
-// need to define how to encode a literal !.
-//
-// Although paths are disallowed from using Unicode (see pathOK above),
-// the eventual plan is to allow Unicode letters as well, to assume that
-// file systems and URLs are Unicode-safe (storing UTF-8), and apply
-// the !-for-uppercase convention. Note however that not all runes that
-// are different but case-fold equivalent are an upper/lower pair.
-// For example, U+004B ('K'), U+006B ('k'), and U+212A ('K' for Kelvin)
-// are considered to case-fold to each other. When we do add Unicode
-// letters, we must not assume that upper/lower are the only case-equivalent pairs.
-// Perhaps the Kelvin symbol would be disallowed entirely, for example.
-// Or perhaps it would encode as "!!k", or perhaps as "(212A)".
-//
-// Also, it would be nice to allow Unicode marks as well as letters,
-// but marks include combining marks, and then we must deal not
-// only with case folding but also normalization: both U+00E9 ('é')
-// and U+0065 U+0301 ('e' followed by combining acute accent)
-// look the same on the page and are treated by some file systems
-// as the same path. If we do allow Unicode marks in paths, there
-// must be some kind of normalization to allow only one canonical
-// encoding of any character used in an import path.
-
-// EncodePath returns the safe encoding of the given module path.
-// It fails if the module path is invalid.
-func EncodePath(path string) (encoding string, err error) {
-	if err := CheckPath(path); err != nil {
-		return "", err
-	}
-
-	return encodeString(path)
-}
-
-// EncodeVersion returns the safe encoding of the given module version.
-// Versions are allowed to be in non-semver form but must be valid file names
-// and not contain exclamation marks.
-func EncodeVersion(v string) (encoding string, err error) {
-	if err := checkElem(v, true); err != nil || strings.Contains(v, "!") {
-		return "", fmt.Errorf("disallowed version string %q", v)
-	}
-	return encodeString(v)
-}
-
-func encodeString(s string) (encoding string, err error) {
-	haveUpper := false
-	for _, r := range s {
-		if r == '!' || r >= utf8.RuneSelf {
-			// This should be disallowed by CheckPath, but diagnose anyway.
-			// The correctness of the encoding loop below depends on it.
-			return "", fmt.Errorf("internal error: inconsistency in EncodePath")
-		}
-		if 'A' <= r && r <= 'Z' {
-			haveUpper = true
-		}
-	}
-
-	if !haveUpper {
-		return s, nil
-	}
-
-	var buf []byte
-	for _, r := range s {
-		if 'A' <= r && r <= 'Z' {
-			buf = append(buf, '!', byte(r+'a'-'A'))
-		} else {
-			buf = append(buf, byte(r))
-		}
-	}
-	return string(buf), nil
-}
-
-// DecodePath returns the module path of the given safe encoding.
-// It fails if the encoding is invalid or encodes an invalid path.
-func DecodePath(encoding string) (path string, err error) {
-	path, ok := decodeString(encoding)
-	if !ok {
-		return "", fmt.Errorf("invalid module path encoding %q", encoding)
-	}
-	if err := CheckPath(path); err != nil {
-		return "", fmt.Errorf("invalid module path encoding %q: %v", encoding, err)
-	}
-	return path, nil
-}
-
-// DecodeVersion returns the version string for the given safe encoding.
-// It fails if the encoding is invalid or encodes an invalid version.
-// Versions are allowed to be in non-semver form but must be valid file names
-// and not contain exclamation marks.
-func DecodeVersion(encoding string) (v string, err error) {
-	v, ok := decodeString(encoding)
-	if !ok {
-		return "", fmt.Errorf("invalid version encoding %q", encoding)
-	}
-	if err := checkElem(v, true); err != nil {
-		return "", fmt.Errorf("disallowed version string %q", v)
-	}
-	return v, nil
-}
-
-func decodeString(encoding string) (string, bool) {
-	var buf []byte
-
-	bang := false
-	for _, r := range encoding {
-		if r >= utf8.RuneSelf {
-			return "", false
-		}
-		if bang {
-			bang = false
-			if r < 'a' || 'z' < r {
-				return "", false
-			}
-			buf = append(buf, byte(r+'A'-'a'))
-			continue
-		}
-		if r == '!' {
-			bang = true
-			continue
-		}
-		if 'A' <= r && r <= 'Z' {
-			return "", false
-		}
-		buf = append(buf, byte(r))
-	}
-	if bang {
-		return "", false
-	}
-	return string(buf), true
-}
diff --git a/internal/thirdparty/module/module_test.go b/internal/thirdparty/module/module_test.go
deleted file mode 100644
index 13057a9..0000000
--- a/internal/thirdparty/module/module_test.go
+++ /dev/null
@@ -1,323 +0,0 @@
-// DO NOT EDIT. This file was copied from
-// https://go.googlesource.com/go/+/db7e7469/src/cmd/go/internal/module.
-// generated by internal/thirdparty/download.go -pkg=module
-
-// 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},
-
-	{"gopkg.in/yaml.v0", "v0.8.0", true},
-	{"gopkg.in/yaml.v0", "v1.0.0", false},
-	{"gopkg.in/yaml.v0", "v2.0.0", false},
-	{"gopkg.in/yaml.v0", "v2.1.5", false},
-	{"gopkg.in/yaml.v0", "v3.0.0", false},
-
-	{"gopkg.in/yaml.v1", "v0.8.0", false},
-	{"gopkg.in/yaml.v1", "v1.0.0", true},
-	{"gopkg.in/yaml.v1", "v2.0.0", false},
-	{"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},
-	{"gopkg.in/yaml.v2", "v3.0.0", false},
-
-	{"rsc.io/quote", "v17.0.0", false},
-	{"rsc.io/quote", "v17.0.0+incompatible", true},
-}
-
-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
-	importOK bool
-	fileOK   bool
-}{
-	{"x.y/z", true, true, true},
-	{"x.y", true, true, true},
-
-	{"", false, false, false},
-	{"x.y/\xFFz", false, false, false},
-	{"/x.y/z", false, false, false},
-	{"x./z", false, false, false},
-	{".x/z", false, false, true},
-	{"-x/z", false, true, true},
-	{"x..y/z", false, false, false},
-	{"x.y/z/../../w", false, false, false},
-	{"x.y//z", false, false, false},
-	{"x.y/z//w", false, false, false},
-	{"x.y/z/", false, false, false},
-
-	{"x.y/z/v0", false, true, true},
-	{"x.y/z/v1", false, true, true},
-	{"x.y/z/v2", true, true, true},
-	{"x.y/z/v2.0", false, true, true},
-	{"X.y/z", false, true, true},
-
-	{"!x.y/z", false, false, true},
-	{"_x.y/z", false, true, true},
-	{"x.y!/z", false, false, true},
-	{"x.y\"/z", false, false, false},
-	{"x.y#/z", false, false, true},
-	{"x.y$/z", false, false, true},
-	{"x.y%/z", false, false, true},
-	{"x.y&/z", false, false, true},
-	{"x.y'/z", false, false, false},
-	{"x.y(/z", false, false, true},
-	{"x.y)/z", false, false, true},
-	{"x.y*/z", false, false, false},
-	{"x.y+/z", false, true, true},
-	{"x.y,/z", false, false, true},
-	{"x.y-/z", true, true, true},
-	{"x.y./zt", false, false, false},
-	{"x.y:/z", false, false, false},
-	{"x.y;/z", false, false, false},
-	{"x.y</z", false, false, false},
-	{"x.y=/z", false, false, true},
-	{"x.y>/z", false, false, false},
-	{"x.y?/z", false, false, false},
-	{"x.y@/z", false, false, true},
-	{"x.y[/z", false, false, true},
-	{"x.y\\/z", false, false, false},
-	{"x.y]/z", false, false, true},
-	{"x.y^/z", false, false, true},
-	{"x.y_/z", false, true, true},
-	{"x.y`/z", false, false, false},
-	{"x.y{/z", false, false, true},
-	{"x.y}/z", false, false, true},
-	{"x.y~/z", false, true, true},
-	{"x.y/z!", false, false, true},
-	{"x.y/z\"", false, false, false},
-	{"x.y/z#", false, false, true},
-	{"x.y/z$", false, false, true},
-	{"x.y/z%", false, false, true},
-	{"x.y/z&", false, false, true},
-	{"x.y/z'", false, false, false},
-	{"x.y/z(", false, false, true},
-	{"x.y/z)", false, false, true},
-	{"x.y/z*", false, false, false},
-	{"x.y/z+", true, true, true},
-	{"x.y/z,", false, false, true},
-	{"x.y/z-", true, true, true},
-	{"x.y/z.t", true, true, true},
-	{"x.y/z/t", true, true, true},
-	{"x.y/z:", false, false, false},
-	{"x.y/z;", false, false, false},
-	{"x.y/z<", false, false, false},
-	{"x.y/z=", false, false, true},
-	{"x.y/z>", false, false, false},
-	{"x.y/z?", false, false, false},
-	{"x.y/z@", false, false, true},
-	{"x.y/z[", false, false, true},
-	{"x.y/z\\", false, false, false},
-	{"x.y/z]", false, false, true},
-	{"x.y/z^", false, false, true},
-	{"x.y/z_", true, true, true},
-	{"x.y/z`", false, false, false},
-	{"x.y/z{", false, false, true},
-	{"x.y/z}", false, false, true},
-	{"x.y/z~", true, true, true},
-	{"x.y/x.foo", true, true, true},
-	{"x.y/aux.foo", false, false, false},
-	{"x.y/prn", false, false, false},
-	{"x.y/prn2", true, true, true},
-	{"x.y/com", true, true, true},
-	{"x.y/com1", false, false, false},
-	{"x.y/com1.txt", false, false, false},
-	{"x.y/calm1", true, true, true},
-	{"github.com/!123/logrus", false, false, true},
-
-	// TODO: CL 41822 allowed Unicode letters in old "go get"
-	// without due consideration of the implications, and only on github.com (!).
-	// For now, we disallow non-ASCII characters in module mode,
-	// in both module paths and general import paths,
-	// until we can get the implications right.
-	// When we do, we'll enable them everywhere, not just for GitHub.
-	{"github.com/user/unicode/испытание", false, false, true},
-
-	{"../x", false, false, false},
-	{"./y", false, false, false},
-	{"x:y", false, false, false},
-	{`\temp\foo`, false, false, false},
-	{".gitignore", false, false, true},
-	{".github/ISSUE_TEMPLATE", false, false, true},
-	{"x☺y", false, false, false},
-}
-
-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)
-		}
-
-		err = CheckImportPath(tt.path)
-		if tt.importOK && err != nil {
-			t.Errorf("CheckImportPath(%q) = %v, wanted nil error", tt.path, err)
-		} else if !tt.importOK && err == nil {
-			t.Errorf("CheckImportPath(%q) succeeded, wanted error", tt.path)
-		}
-
-		err = CheckFilePath(tt.path)
-		if tt.fileOK && err != nil {
-			t.Errorf("CheckFilePath(%q) = %v, wanted nil error", tt.path, err)
-		} else if !tt.fileOK && err == nil {
-			t.Errorf("CheckFilePath(%q) succeeded, wanted error", tt.path)
-		}
-	}
-}
-
-var splitPathVersionTests = []struct {
-	pathPrefix string
-	version    string
-}{
-	{"x.y/z", ""},
-	{"x.y/z", "/v2"},
-	{"x.y/z", "/v3"},
-	{"x.y/v", ""},
-	{"gopkg.in/yaml", ".v0"},
-	{"gopkg.in/yaml", ".v1"},
-	{"gopkg.in/yaml", ".v2"},
-	{"gopkg.in/yaml", ".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)
-		}
-	}
-}
-
-var encodeTests = []struct {
-	path string
-	enc  string // empty means same as path
-}{
-	{path: "ascii.com/abcdefghijklmnopqrstuvwxyz.-+/~_0123456789"},
-	{path: "github.com/GoogleCloudPlatform/omega", enc: "github.com/!google!cloud!platform/omega"},
-}
-
-func TestEncodePath(t *testing.T) {
-	// Check invalid paths.
-	for _, tt := range checkPathTests {
-		if !tt.ok {
-			_, err := EncodePath(tt.path)
-			if err == nil {
-				t.Errorf("EncodePath(%q): succeeded, want error (invalid path)", tt.path)
-			}
-		}
-	}
-
-	// Check encodings.
-	for _, tt := range encodeTests {
-		enc, err := EncodePath(tt.path)
-		if err != nil {
-			t.Errorf("EncodePath(%q): unexpected error: %v", tt.path, err)
-			continue
-		}
-		want := tt.enc
-		if want == "" {
-			want = tt.path
-		}
-		if enc != want {
-			t.Errorf("EncodePath(%q) = %q, want %q", tt.path, enc, want)
-		}
-	}
-}
-
-var badDecode = []string{
-	"github.com/GoogleCloudPlatform/omega",
-	"github.com/!google!cloud!platform!/omega",
-	"github.com/!0google!cloud!platform/omega",
-	"github.com/!_google!cloud!platform/omega",
-	"github.com/!!google!cloud!platform/omega",
-	"",
-}
-
-func TestDecodePath(t *testing.T) {
-	// Check invalid decodings.
-	for _, bad := range badDecode {
-		_, err := DecodePath(bad)
-		if err == nil {
-			t.Errorf("DecodePath(%q): succeeded, want error (invalid decoding)", bad)
-		}
-	}
-
-	// Check invalid paths (or maybe decodings).
-	for _, tt := range checkPathTests {
-		if !tt.ok {
-			path, err := DecodePath(tt.path)
-			if err == nil {
-				t.Errorf("DecodePath(%q) = %q, want error (invalid path)", tt.path, path)
-			}
-		}
-	}
-
-	// Check encodings.
-	for _, tt := range encodeTests {
-		enc := tt.enc
-		if enc == "" {
-			enc = tt.path
-		}
-		path, err := DecodePath(enc)
-		if err != nil {
-			t.Errorf("DecodePath(%q): unexpected error: %v", enc, err)
-			continue
-		}
-		if path != tt.path {
-			t.Errorf("DecodePath(%q) = %q, want %q", enc, path, tt.path)
-		}
-	}
-}
diff --git a/internal/thirdparty/semver/semver.go b/internal/thirdparty/semver/semver.go
deleted file mode 100644
index 456653f..0000000
--- a/internal/thirdparty/semver/semver.go
+++ /dev/null
@@ -1,392 +0,0 @@
-// DO NOT EDIT. This file was copied from
-// https://go.googlesource.com/go/+/6249ea2f/src/cmd/go/internal/semver.
-// generated by internal/thirdparty/download.go -pkg=semver
-
-// 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 semver implements comparison of semantic version strings.
-// In this package, semantic version strings must begin with a leading "v",
-// as in "v1.0.0".
-//
-// The general form of a semantic version string accepted by this package is
-//
-//	vMAJOR[.MINOR[.PATCH[-PRERELEASE][+BUILD]]]
-//
-// where square brackets indicate optional parts of the syntax;
-// MAJOR, MINOR, and PATCH are decimal integers without extra leading zeros;
-// PRERELEASE and BUILD are each a series of non-empty dot-separated identifiers
-// using only alphanumeric characters and hyphens; and
-// all-numeric PRERELEASE identifiers must not have leading zeros.
-//
-// This package follows Semantic Versioning 2.0.0 (see semver.org)
-// with two exceptions. First, it requires the "v" prefix. Second, it recognizes
-// vMAJOR and vMAJOR.MINOR (with no prerelease or build suffixes)
-// as shorthands for vMAJOR.0.0 and vMAJOR.MINOR.0.
-package semver
-
-// parsed returns the parsed form of a semantic version string.
-type parsed struct {
-	major      string
-	minor      string
-	patch      string
-	short      string
-	prerelease string
-	build      string
-	err        string
-}
-
-// IsValid reports whether v is a valid semantic version string.
-func IsValid(v string) bool {
-	_, ok := parse(v)
-	return ok
-}
-
-// Canonical returns the canonical formatting of the semantic version v.
-// It fills in any missing .MINOR or .PATCH and discards build metadata.
-// Two semantic versions compare equal only if their canonical formattings
-// are identical strings.
-// The canonical invalid semantic version is the empty string.
-func Canonical(v string) string {
-	p, ok := parse(v)
-	if !ok {
-		return ""
-	}
-	if p.build != "" {
-		return v[:len(v)-len(p.build)]
-	}
-	if p.short != "" {
-		return v + p.short
-	}
-	return v
-}
-
-// Major returns the major version prefix of the semantic version v.
-// For example, Major("v2.1.0") == "v2".
-// If v is an invalid semantic version string, Major returns the empty string.
-func Major(v string) string {
-	pv, ok := parse(v)
-	if !ok {
-		return ""
-	}
-	return v[:1+len(pv.major)]
-}
-
-// MajorMinor returns the major.minor version prefix of the semantic version v.
-// For example, MajorMinor("v2.1.0") == "v2.1".
-// If v is an invalid semantic version string, MajorMinor returns the empty string.
-func MajorMinor(v string) string {
-	pv, ok := parse(v)
-	if !ok {
-		return ""
-	}
-	i := 1 + len(pv.major)
-	if j := i + 1 + len(pv.minor); j <= len(v) && v[i] == '.' && v[i+1:j] == pv.minor {
-		return v[:j]
-	}
-	return v[:i] + "." + pv.minor
-}
-
-// Prerelease returns the prerelease suffix of the semantic version v.
-// For example, Prerelease("v2.1.0-pre+meta") == "-pre".
-// If v is an invalid semantic version string, Prerelease returns the empty string.
-func Prerelease(v string) string {
-	pv, ok := parse(v)
-	if !ok {
-		return ""
-	}
-	return pv.prerelease
-}
-
-// Build returns the build suffix of the semantic version v.
-// For example, Build("v2.1.0+meta") == "+meta".
-// If v is an invalid semantic version string, Build returns the empty string.
-func Build(v string) string {
-	pv, ok := parse(v)
-	if !ok {
-		return ""
-	}
-	return pv.build
-}
-
-// Compare returns an integer comparing two versions according to
-// according to semantic version precedence.
-// The result will be 0 if v == w, -1 if v < w, or +1 if v > w.
-//
-// An invalid semantic version string is considered less than a valid one.
-// All invalid semantic version strings compare equal to each other.
-func Compare(v, w string) int {
-	pv, ok1 := parse(v)
-	pw, ok2 := parse(w)
-	if !ok1 && !ok2 {
-		return 0
-	}
-	if !ok1 {
-		return -1
-	}
-	if !ok2 {
-		return +1
-	}
-	if c := compareInt(pv.major, pw.major); c != 0 {
-		return c
-	}
-	if c := compareInt(pv.minor, pw.minor); c != 0 {
-		return c
-	}
-	if c := compareInt(pv.patch, pw.patch); c != 0 {
-		return c
-	}
-	return comparePrerelease(pv.prerelease, pw.prerelease)
-}
-
-// Max canonicalizes its arguments and then returns the version string
-// that compares greater.
-func Max(v, w string) string {
-	v = Canonical(v)
-	w = Canonical(w)
-	if Compare(v, w) > 0 {
-		return v
-	}
-	return w
-}
-
-func parse(v string) (p parsed, ok bool) {
-	if v == "" || v[0] != 'v' {
-		p.err = "missing v prefix"
-		return
-	}
-	p.major, v, ok = parseInt(v[1:])
-	if !ok {
-		p.err = "bad major version"
-		return
-	}
-	if v == "" {
-		p.minor = "0"
-		p.patch = "0"
-		p.short = ".0.0"
-		return
-	}
-	if v[0] != '.' {
-		p.err = "bad minor prefix"
-		ok = false
-		return
-	}
-	p.minor, v, ok = parseInt(v[1:])
-	if !ok {
-		p.err = "bad minor version"
-		return
-	}
-	if v == "" {
-		p.patch = "0"
-		p.short = ".0"
-		return
-	}
-	if v[0] != '.' {
-		p.err = "bad patch prefix"
-		ok = false
-		return
-	}
-	p.patch, v, ok = parseInt(v[1:])
-	if !ok {
-		p.err = "bad patch version"
-		return
-	}
-	if len(v) > 0 && v[0] == '-' {
-		p.prerelease, v, ok = parsePrerelease(v)
-		if !ok {
-			p.err = "bad prerelease"
-			return
-		}
-	}
-	if len(v) > 0 && v[0] == '+' {
-		p.build, v, ok = parseBuild(v)
-		if !ok {
-			p.err = "bad build"
-			return
-		}
-	}
-	if v != "" {
-		p.err = "junk on end"
-		ok = false
-		return
-	}
-	ok = true
-	return
-}
-
-func parseInt(v string) (t, rest string, ok bool) {
-	if v == "" {
-		return
-	}
-	if v[0] < '0' || '9' < v[0] {
-		return
-	}
-	i := 1
-	for i < len(v) && '0' <= v[i] && v[i] <= '9' {
-		i++
-	}
-	if v[0] == '0' && i != 1 {
-		return
-	}
-	return v[:i], v[i:], true
-}
-
-func parsePrerelease(v string) (t, rest string, ok bool) {
-	// "A pre-release version MAY be denoted by appending a hyphen and
-	// a series of dot separated identifiers immediately following the patch version.
-	// Identifiers MUST comprise only ASCII alphanumerics and hyphen [0-9A-Za-z-].
-	// Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes."
-	if v == "" || v[0] != '-' {
-		return
-	}
-	i := 1
-	start := 1
-	for i < len(v) && v[i] != '+' {
-		if !isIdentChar(v[i]) && v[i] != '.' {
-			return
-		}
-		if v[i] == '.' {
-			if start == i || isBadNum(v[start:i]) {
-				return
-			}
-			start = i + 1
-		}
-		i++
-	}
-	if start == i || isBadNum(v[start:i]) {
-		return
-	}
-	return v[:i], v[i:], true
-}
-
-func parseBuild(v string) (t, rest string, ok bool) {
-	if v == "" || v[0] != '+' {
-		return
-	}
-	i := 1
-	start := 1
-	for i < len(v) {
-		if !isIdentChar(v[i]) && v[i] != '.' {
-			return
-		}
-		if v[i] == '.' {
-			if start == i {
-				return
-			}
-			start = i + 1
-		}
-		i++
-	}
-	if start == i {
-		return
-	}
-	return v[:i], v[i:], true
-}
-
-func isIdentChar(c byte) bool {
-	return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '-'
-}
-
-func isBadNum(v string) bool {
-	i := 0
-	for i < len(v) && '0' <= v[i] && v[i] <= '9' {
-		i++
-	}
-	return i == len(v) && i > 1 && v[0] == '0'
-}
-
-func isNum(v string) bool {
-	i := 0
-	for i < len(v) && '0' <= v[i] && v[i] <= '9' {
-		i++
-	}
-	return i == len(v)
-}
-
-func compareInt(x, y string) int {
-	if x == y {
-		return 0
-	}
-	if len(x) < len(y) {
-		return -1
-	}
-	if len(x) > len(y) {
-		return +1
-	}
-	if x < y {
-		return -1
-	} else {
-		return +1
-	}
-}
-
-func comparePrerelease(x, y string) int {
-	// "When major, minor, and patch are equal, a pre-release version has
-	// lower precedence than a normal version.
-	// Example: 1.0.0-alpha < 1.0.0.
-	// Precedence for two pre-release versions with the same major, minor,
-	// and patch version MUST be determined by comparing each dot separated
-	// identifier from left to right until a difference is found as follows:
-	// identifiers consisting of only digits are compared numerically and
-	// identifiers with letters or hyphens are compared lexically in ASCII
-	// sort order. Numeric identifiers always have lower precedence than
-	// non-numeric identifiers. A larger set of pre-release fields has a
-	// higher precedence than a smaller set, if all of the preceding
-	// identifiers are equal.
-	// Example: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta <
-	// 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0."
-	if x == y {
-		return 0
-	}
-	if x == "" {
-		return +1
-	}
-	if y == "" {
-		return -1
-	}
-	for x != "" && y != "" {
-		x = x[1:] // skip - or .
-		y = y[1:] // skip - or .
-		var dx, dy string
-		dx, x = nextIdent(x)
-		dy, y = nextIdent(y)
-		if dx != dy {
-			ix := isNum(dx)
-			iy := isNum(dy)
-			if ix != iy {
-				if ix {
-					return -1
-				} else {
-					return +1
-				}
-			}
-			if ix {
-				if len(dx) < len(dy) {
-					return -1
-				}
-				if len(dx) > len(dy) {
-					return +1
-				}
-			}
-			if dx < dy {
-				return -1
-			} else {
-				return +1
-			}
-		}
-	}
-	if x == "" {
-		return -1
-	} else {
-		return +1
-	}
-}
-
-func nextIdent(x string) (dx, rest string) {
-	i := 0
-	for i < len(x) && x[i] != '.' {
-		i++
-	}
-	return x[:i], x[i:]
-}
diff --git a/internal/thirdparty/semver/semver_test.go b/internal/thirdparty/semver/semver_test.go
deleted file mode 100644
index 2ef22ab..0000000
--- a/internal/thirdparty/semver/semver_test.go
+++ /dev/null
@@ -1,187 +0,0 @@
-// DO NOT EDIT. This file was copied from
-// https://go.googlesource.com/go/+/6249ea2f/src/cmd/go/internal/semver.
-// generated by internal/thirdparty/download.go -pkg=semver
-
-// 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 semver
-
-import (
-	"strings"
-	"testing"
-)
-
-var tests = []struct {
-	in  string
-	out string
-}{
-	{"bad", ""},
-	{"v1-alpha.beta.gamma", ""},
-	{"v1-pre", ""},
-	{"v1+meta", ""},
-	{"v1-pre+meta", ""},
-	{"v1.2-pre", ""},
-	{"v1.2+meta", ""},
-	{"v1.2-pre+meta", ""},
-	{"v1.0.0-alpha", "v1.0.0-alpha"},
-	{"v1.0.0-alpha.1", "v1.0.0-alpha.1"},
-	{"v1.0.0-alpha.beta", "v1.0.0-alpha.beta"},
-	{"v1.0.0-beta", "v1.0.0-beta"},
-	{"v1.0.0-beta.2", "v1.0.0-beta.2"},
-	{"v1.0.0-beta.11", "v1.0.0-beta.11"},
-	{"v1.0.0-rc.1", "v1.0.0-rc.1"},
-	{"v1", "v1.0.0"},
-	{"v1.0", "v1.0.0"},
-	{"v1.0.0", "v1.0.0"},
-	{"v1.2", "v1.2.0"},
-	{"v1.2.0", "v1.2.0"},
-	{"v1.2.3-456", "v1.2.3-456"},
-	{"v1.2.3-456.789", "v1.2.3-456.789"},
-	{"v1.2.3-456-789", "v1.2.3-456-789"},
-	{"v1.2.3-456a", "v1.2.3-456a"},
-	{"v1.2.3-pre", "v1.2.3-pre"},
-	{"v1.2.3-pre+meta", "v1.2.3-pre"},
-	{"v1.2.3-pre.1", "v1.2.3-pre.1"},
-	{"v1.2.3-zzz", "v1.2.3-zzz"},
-	{"v1.2.3", "v1.2.3"},
-	{"v1.2.3+meta", "v1.2.3"},
-	{"v1.2.3+meta-pre", "v1.2.3"},
-	{"v1.2.3+meta-pre.sha.256a", "v1.2.3"},
-}
-
-func TestIsValid(t *testing.T) {
-	for _, tt := range tests {
-		ok := IsValid(tt.in)
-		if ok != (tt.out != "") {
-			t.Errorf("IsValid(%q) = %v, want %v", tt.in, ok, !ok)
-		}
-	}
-}
-
-func TestCanonical(t *testing.T) {
-	for _, tt := range tests {
-		out := Canonical(tt.in)
-		if out != tt.out {
-			t.Errorf("Canonical(%q) = %q, want %q", tt.in, out, tt.out)
-		}
-	}
-}
-
-func TestMajor(t *testing.T) {
-	for _, tt := range tests {
-		out := Major(tt.in)
-		want := ""
-		if i := strings.Index(tt.out, "."); i >= 0 {
-			want = tt.out[:i]
-		}
-		if out != want {
-			t.Errorf("Major(%q) = %q, want %q", tt.in, out, want)
-		}
-	}
-}
-
-func TestMajorMinor(t *testing.T) {
-	for _, tt := range tests {
-		out := MajorMinor(tt.in)
-		var want string
-		if tt.out != "" {
-			want = tt.in
-			if i := strings.Index(want, "+"); i >= 0 {
-				want = want[:i]
-			}
-			if i := strings.Index(want, "-"); i >= 0 {
-				want = want[:i]
-			}
-			switch strings.Count(want, ".") {
-			case 0:
-				want += ".0"
-			case 1:
-				// ok
-			case 2:
-				want = want[:strings.LastIndex(want, ".")]
-			}
-		}
-		if out != want {
-			t.Errorf("MajorMinor(%q) = %q, want %q", tt.in, out, want)
-		}
-	}
-}
-
-func TestPrerelease(t *testing.T) {
-	for _, tt := range tests {
-		pre := Prerelease(tt.in)
-		var want string
-		if tt.out != "" {
-			if i := strings.Index(tt.out, "-"); i >= 0 {
-				want = tt.out[i:]
-			}
-		}
-		if pre != want {
-			t.Errorf("Prerelease(%q) = %q, want %q", tt.in, pre, want)
-		}
-	}
-}
-
-func TestBuild(t *testing.T) {
-	for _, tt := range tests {
-		build := Build(tt.in)
-		var want string
-		if tt.out != "" {
-			if i := strings.Index(tt.in, "+"); i >= 0 {
-				want = tt.in[i:]
-			}
-		}
-		if build != want {
-			t.Errorf("Build(%q) = %q, want %q", tt.in, build, want)
-		}
-	}
-}
-
-func TestCompare(t *testing.T) {
-	for i, ti := range tests {
-		for j, tj := range tests {
-			cmp := Compare(ti.in, tj.in)
-			var want int
-			if ti.out == tj.out {
-				want = 0
-			} else if i < j {
-				want = -1
-			} else {
-				want = +1
-			}
-			if cmp != want {
-				t.Errorf("Compare(%q, %q) = %d, want %d", ti.in, tj.in, cmp, want)
-			}
-		}
-	}
-}
-
-func TestMax(t *testing.T) {
-	for i, ti := range tests {
-		for j, tj := range tests {
-			max := Max(ti.in, tj.in)
-			want := Canonical(ti.in)
-			if i < j {
-				want = Canonical(tj.in)
-			}
-			if max != want {
-				t.Errorf("Max(%q, %q) = %q, want %q", ti.in, tj.in, max, want)
-			}
-		}
-	}
-}
-
-var (
-	v1 = "v1.0.0+metadata-dash"
-	v2 = "v1.0.0+metadata-dash1"
-)
-
-func BenchmarkCompare(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		if Compare(v1, v2) != 0 {
-			b.Fatalf("bad compare")
-		}
-	}
-}
diff --git a/internal/version/version.go b/internal/version/version.go
index 4cd4770..201b291 100644
--- a/internal/version/version.go
+++ b/internal/version/version.go
@@ -10,7 +10,7 @@
 	"regexp"
 	"strings"
 
-	"golang.org/x/discovery/internal/thirdparty/semver"
+	"golang.org/x/mod/semver"
 )
 
 // Type defines the version types a module can have.
diff --git a/internal/version/version_test.go b/internal/version/version_test.go
index 92ceab6..ac7546c 100644
--- a/internal/version/version_test.go
+++ b/internal/version/version_test.go
@@ -7,7 +7,7 @@
 import (
 	"testing"
 
-	"golang.org/x/discovery/internal/thirdparty/semver"
+	"golang.org/x/mod/semver"
 )
 
 func TestForSorting(t *testing.T) {