cmd/go/internal/get: simplify scheme lookup

Fixes #26123

Change-Id: If0dad65a3885d2146624f2aac42099e9eca9670e
Reviewed-on: https://go-review.googlesource.com/c/go/+/200758
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
diff --git a/src/cmd/go/internal/get/vcs.go b/src/cmd/go/internal/get/vcs.go
index 3ccfbb8..d73d114 100644
--- a/src/cmd/go/internal/get/vcs.go
+++ b/src/cmd/go/internal/get/vcs.go
@@ -531,12 +531,12 @@
 // A vcsPath describes how to convert an import path into a
 // version control system and repository name.
 type vcsPath struct {
-	prefix string                              // prefix this description applies to
-	regexp *lazyregexp.Regexp                  // compiled pattern for import path
-	repo   string                              // repository to use (expand with match of re)
-	vcs    string                              // version control system to use (expand with match of re)
-	check  func(match map[string]string) error // additional checks
-	ping   bool                                // ping for scheme to use to download repo
+	prefix         string                              // prefix this description applies to
+	regexp         *lazyregexp.Regexp                  // compiled pattern for import path
+	repo           string                              // repository to use (expand with match of re)
+	vcs            string                              // version control system to use (expand with match of re)
+	check          func(match map[string]string) error // additional checks
+	schemelessRepo bool                                // if true, the repo pattern lacks a scheme
 }
 
 // vcsFromDir inspects dir and its parents to determine the
@@ -657,7 +657,7 @@
 // RepoRootForImportPath analyzes importPath to determine the
 // version control system, and code repository to use.
 func RepoRootForImportPath(importPath string, mod ModuleMode, security web.SecurityMode) (*RepoRoot, error) {
-	rr, err := repoRootFromVCSPaths(importPath, "", security, vcsPaths)
+	rr, err := repoRootFromVCSPaths(importPath, security, vcsPaths)
 	if err == errUnknownSite {
 		rr, err = repoRootForImportDynamic(importPath, mod, security)
 		if err != nil {
@@ -665,7 +665,7 @@
 		}
 	}
 	if err != nil {
-		rr1, err1 := repoRootFromVCSPaths(importPath, "", security, vcsPathsAfterDynamic)
+		rr1, err1 := repoRootFromVCSPaths(importPath, security, vcsPathsAfterDynamic)
 		if err1 == nil {
 			rr = rr1
 			err = nil
@@ -685,8 +685,7 @@
 
 // repoRootFromVCSPaths attempts to map importPath to a repoRoot
 // using the mappings defined in vcsPaths.
-// If scheme is non-empty, that scheme is forced.
-func repoRootFromVCSPaths(importPath, scheme string, security web.SecurityMode, vcsPaths []*vcsPath) (*RepoRoot, error) {
+func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths []*vcsPath) (*RepoRoot, error) {
 	// A common error is to use https://packagepath because that's what
 	// hg and git require. Diagnose this helpfully.
 	if prefix := httpPrefix(importPath); prefix != "" {
@@ -731,26 +730,28 @@
 		if vcs == nil {
 			return nil, fmt.Errorf("unknown version control system %q", match["vcs"])
 		}
-		if srv.ping {
-			if scheme != "" {
-				match["repo"] = scheme + "://" + match["repo"]
-			} else {
-				for _, scheme := range vcs.scheme {
-					if security == web.SecureOnly && !vcs.isSecureScheme(scheme) {
+		var repoURL string
+		if !srv.schemelessRepo {
+			repoURL = match["repo"]
+		} else {
+			scheme := vcs.scheme[0] // default to first scheme
+			repo := match["repo"]
+			if vcs.pingCmd != "" {
+				// If we know how to test schemes, scan to find one.
+				for _, s := range vcs.scheme {
+					if security == web.SecureOnly && !vcs.isSecureScheme(s) {
 						continue
 					}
-					if vcs.pingCmd != "" && vcs.ping(scheme, match["repo"]) == nil {
-						match["repo"] = scheme + "://" + match["repo"]
-						goto Found
+					if vcs.ping(s, repo) == nil {
+						scheme = s
+						break
 					}
 				}
-				// No scheme found. Fall back to the first one.
-				match["repo"] = vcs.scheme[0] + "://" + match["repo"]
-			Found:
 			}
+			repoURL = scheme + "://" + repo
 		}
 		rr := &RepoRoot{
-			Repo: match["repo"],
+			Repo: repoURL,
 			Root: match["root"],
 			VCS:  vcs.cmd,
 			vcs:  vcs,
@@ -1075,8 +1076,8 @@
 	// General syntax for any server.
 	// Must be last.
 	{
-		regexp: lazyregexp.New(`(?P<root>(?P<repo>([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?(/~?[A-Za-z0-9_.\-]+)+?)\.(?P<vcs>bzr|fossil|git|hg|svn))(/~?[A-Za-z0-9_.\-]+)*$`),
-		ping:   true,
+		regexp:         lazyregexp.New(`(?P<root>(?P<repo>([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?(/~?[A-Za-z0-9_.\-]+)+?)\.(?P<vcs>bzr|fossil|git|hg|svn))(/~?[A-Za-z0-9_.\-]+)*$`),
+		schemelessRepo: true,
 	},
 }