internal: add support for path@main

Support requests for path@main in addition to path@master.

For golang/go#41312

Change-Id: Ie7665fbb3906e366c784a9cc592ffe37ef347671
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/274244
Trust: Julie Qiu <julie@golang.org>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
diff --git a/internal/discovery.go b/internal/discovery.go
index 534d131..bd41a8f 100644
--- a/internal/discovery.go
+++ b/internal/discovery.go
@@ -20,9 +20,6 @@
 	// proxy client.
 	LatestVersion = "latest"
 
-	// MasterVersion signifies the version at master.
-	MasterVersion = "master"
-
 	// UnknownModulePath signifies that the module path for a given package
 	// path is ambiguous or not known. This is because requests to the
 	// frontend can come in the form of <import-path>[@<version>], and it is
@@ -30,6 +27,12 @@
 	UnknownModulePath = "unknownModulePath"
 )
 
+// DefaultBranches are default branches that are supported by pkgsite.
+var DefaultBranches = map[string]bool{
+	"main":   true,
+	"master": true,
+}
+
 // ModuleInfo holds metadata associated with a module.
 type ModuleInfo struct {
 	ModulePath        string
diff --git a/internal/frontend/fetch_test.go b/internal/frontend/fetch_test.go
index 7c10d87..7f92034 100644
--- a/internal/frontend/fetch_test.go
+++ b/internal/frontend/fetch_test.go
@@ -44,7 +44,12 @@
 		{
 			name:     "path at master package is in module root",
 			fullPath: testModulePath,
-			version:  internal.MasterVersion,
+			version:  "master",
+		},
+		{
+			name:     "path at main package is in module root",
+			fullPath: testModulePath,
+			version:  "main",
 		},
 		{
 			name:     "path at latest package is in module root",
@@ -64,7 +69,12 @@
 		{
 			name:     "directory at master package is not in module root",
 			fullPath: testModulePath + "/bar",
-			version:  internal.MasterVersion,
+			version:  "master",
+		},
+		{
+			name:     "directory at main package is not in module root",
+			fullPath: testModulePath + "/bar",
+			version:  "main",
 		},
 	} {
 		t.Run(test.name, func(t *testing.T) {
diff --git a/internal/frontend/unit.go b/internal/frontend/unit.go
index 591eab8..6320f4c 100644
--- a/internal/frontend/unit.go
+++ b/internal/frontend/unit.go
@@ -95,7 +95,7 @@
 	}
 
 	recordVersionTypeMetric(ctx, info.requestedVersion)
-	if info.requestedVersion == internal.MasterVersion {
+	if _, ok := internal.DefaultBranches[info.requestedVersion]; ok {
 		// Since path@master is a moving target, we don't want it to be stale.
 		// As a result, we enqueue every request of path@master to the frontend
 		// task queue, which will initiate a fetch request depending on the
@@ -106,7 +106,7 @@
 		go func() {
 			ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
 			defer cancel()
-			if _, err := s.queue.ScheduleFetch(ctx, info.modulePath, internal.MasterVersion, ""); err != nil {
+			if _, err := s.queue.ScheduleFetch(ctx, info.modulePath, info.requestedVersion, ""); err != nil {
 				log.Errorf(ctx, "serveDetails(%q): %v", r.URL.Path, err)
 			}
 		}()
diff --git a/internal/frontend/urlinfo.go b/internal/frontend/urlinfo.go
index f472a17..0db1485 100644
--- a/internal/frontend/urlinfo.go
+++ b/internal/frontend/urlinfo.go
@@ -170,13 +170,10 @@
 
 // isSupportedVersion reports whether the version is supported by the frontend.
 func isSupportedVersion(fullPath, requestedVersion string) bool {
-	if stdlib.Contains(fullPath) && requestedVersion == internal.MasterVersion {
-		return false
+	if _, ok := internal.DefaultBranches[requestedVersion]; ok {
+		return !stdlib.Contains(fullPath)
 	}
-	if requestedVersion == internal.LatestVersion || semver.IsValid(requestedVersion) {
-		return true
-	}
-	return requestedVersion == internal.MasterVersion
+	return requestedVersion == internal.LatestVersion || semver.IsValid(requestedVersion)
 }
 
 func setExperimentsFromQueryParam(ctx context.Context, r *http.Request) context.Context {
diff --git a/internal/frontend/urlinfo_test.go b/internal/frontend/urlinfo_test.go
index db1070d..209af0b 100644
--- a/internal/frontend/urlinfo_test.go
+++ b/internal/frontend/urlinfo_test.go
@@ -188,10 +188,12 @@
 		{sample.ModulePath, "v1.2.bad", false},
 		{sample.ModulePath, "latest", true},
 		{sample.ModulePath, "master", true},
+		{sample.ModulePath, "main", true},
 		{"net/http", "v1.2.3", true}, // isSupportedVersion expects the goTag is already converted to semver
 		{"net/http", "v1.2.3.bad", false},
 		{"net/http", "latest", true},
 		{"net/http", "master", false},
+		{"net/http", "main", false},
 	}
 	for _, test := range tests {
 		got := isSupportedVersion(test.path, test.version)
diff --git a/internal/postgres/path_test.go b/internal/postgres/path_test.go
index 9d75aaa..8dcb7b5 100644
--- a/internal/postgres/path_test.go
+++ b/internal/postgres/path_test.go
@@ -43,7 +43,7 @@
 		}
 		requested := m.Version
 		if testModule.isMaster {
-			requested = internal.MasterVersion
+			requested = "master"
 		}
 		if err := testDB.UpsertVersionMap(ctx, &internal.VersionMap{
 			ModulePath:       m.ModulePath,
@@ -224,7 +224,7 @@
 		}
 		requested := m.Version
 		if testModule.isMaster {
-			requested = internal.MasterVersion
+			requested = "master"
 		}
 		if err := bypassDB.UpsertVersionMap(ctx, &internal.VersionMap{
 			ModulePath:       m.ModulePath,
diff --git a/internal/postgres/unit.go b/internal/postgres/unit.go
index 9a88a33..49e9a15 100644
--- a/internal/postgres/unit.go
+++ b/internal/postgres/unit.go
@@ -47,11 +47,9 @@
 	if requestedModulePath != internal.UnknownModulePath {
 		query = query.Where(squirrel.Eq{"m.module_path": requestedModulePath})
 	}
-	switch requestedVersion {
-	case internal.LatestVersion:
-	case internal.MasterVersion:
-		query = query.Join("version_map vm ON m.id = vm.module_id").Where("vm.requested_version = 'master'")
-	default:
+	if _, ok := internal.DefaultBranches[requestedVersion]; ok {
+		query = query.Join("version_map vm ON m.id = vm.module_id").Where("vm.requested_version = ? ", requestedVersion)
+	} else if requestedVersion != internal.LatestVersion {
 		query = query.Where(squirrel.Eq{"version": requestedVersion})
 	}
 	var (
diff --git a/internal/proxy/server.go b/internal/proxy/server.go
index d59280c..51fffa1 100644
--- a/internal/proxy/server.go
+++ b/internal/proxy/server.go
@@ -118,8 +118,9 @@
 		s.handleList(m.ModulePath)
 		s.handleLatest(m.ModulePath, fmt.Sprintf("/%s/@latest", m.ModulePath))
 		// TODO(https://golang.org/issue/39985): Add endpoint for handling
-		// master version.
+		// master and main versions.
 		s.handleLatest(m.ModulePath, fmt.Sprintf("/%s/@v/master.info", m.ModulePath))
+		s.handleLatest(m.ModulePath, fmt.Sprintf("/%s/@v/main.info", m.ModulePath))
 	}
 	s.handleInfo(m.ModulePath, m.Version)
 	s.handleMod(m)