doc: factor out redirect logic from newPackage to gosrc.MaybeRedirect
This is a refactor to bring the redirect check into a small dedicated
function within gosrc. It can be tested more directly/easily.
Change-Id: Ib9c907bae00384c1f7fef74146b19b715976c546
Reviewed-on: https://go-review.googlesource.com/134475
Reviewed-by: Tuo Shan <shantuo@google.com>
diff --git a/doc/builder.go b/doc/builder.go
index e372d3d..0dac830 100644
--- a/doc/builder.go
+++ b/doc/builder.go
@@ -577,28 +577,11 @@
return pkg, nil
}
- switch {
- case bpkg.ImportComment != "":
- // Redirect to import path comment, if not already there.
- if dir.ImportPath != bpkg.ImportComment {
- return nil, gosrc.NotFoundError{
- Message: "not at canonical import path",
- Redirect: bpkg.ImportComment,
- }
- }
-
- // Redirect to GitHub's reported canonical casing when there's no import path comment,
- // and the import path differs from resolved GitHub path only in case.
- case bpkg.ImportComment == "" && dir.ResolvedGitHubPath != "" &&
- strings.EqualFold(dir.ImportPath, dir.ResolvedGitHubPath):
-
- // Redirect to resolved GitHub path, if not already there.
- if dir.ImportPath != dir.ResolvedGitHubPath {
- return nil, gosrc.NotFoundError{
- Message: "not at canonical import path",
- Redirect: dir.ResolvedGitHubPath,
- }
- }
+ // Use information we have by now (import comment and resolved GitHub path)
+ // to redirect to a canonical import path, when it's possible to do so reliably.
+ err = gosrc.MaybeRedirect(dir.ImportPath, bpkg.ImportComment, dir.ResolvedGitHubPath)
+ if err != nil {
+ return nil, err
}
// Parse the Go files
diff --git a/doc/builder_test.go b/doc/builder_test.go
index 763f9e4..7160cda 100644
--- a/doc/builder_test.go
+++ b/doc/builder_test.go
@@ -9,8 +9,6 @@
import (
"go/ast"
"testing"
-
- "github.com/golang/gddo/gosrc"
)
var badSynopsis = []string{
@@ -114,108 +112,3 @@
}
}
}
-
-// TestNewPackageRedirect tests that newPackage redirects
-// and does not redirect as expected, in various situations.
-// See https://github.com/golang/gddo/issues/507
-// and https://github.com/golang/gddo/issues/579.
-func TestNewPackageRedirect(t *testing.T) {
- // robpike.io/ivy package.
- // Vanity import path, hosted on GitHub, with import path comment.
- ivy := gosrc.Directory{
- Files: []*gosrc.File{
- {Name: "main.go", Data: []byte("package main // import \"robpike.io/ivy\"\n")},
- },
- ResolvedGitHubPath: "github.com/robpike/ivy",
- }
-
- // go4.org/sort package.
- // Vanity import path, hosted on GitHub, without import path comment.
- go4sort := gosrc.Directory{
- Files: []*gosrc.File{
- {Name: "main.go", Data: []byte("package sort\n")},
- },
- ResolvedGitHubPath: "github.com/go4org/go4/sort",
- }
-
- // github.com/teamwork/validate package.
- // Hosted on GitHub, with import path comment that doesn't match canonical GitHub case.
- // See issue https://github.com/golang/gddo/issues/507.
- gtv := gosrc.Directory{
- Files: []*gosrc.File{
- {Name: "main.go", Data: []byte("package validate // import \"github.com/teamwork/validate\"\n")},
- },
- ResolvedGitHubPath: "github.com/Teamwork/validate", // Note that this differs from import path comment.
- }
-
- tests := []struct {
- name string
- repo gosrc.Directory
- requestPath string
- wantRedirect string // Empty string means no redirect.
- }{
- // ivy.
- {
- repo: ivy, name: "ivy repo: access canonical path -> no redirect",
- requestPath: "robpike.io/ivy",
- },
- {
- repo: ivy, name: "ivy repo: access GitHub path -> redirect to import comment",
- requestPath: "github.com/robpike/ivy",
- wantRedirect: "robpike.io/ivy",
- },
- {
- repo: ivy, name: "ivy repo: access GitHub path with weird casing -> redirect to import comment",
- requestPath: "github.com/RoBpIkE/iVy",
- wantRedirect: "robpike.io/ivy",
- },
-
- // go4sort.
- {
- repo: go4sort, name: "go4sort repo: access canonical path -> no redirect",
- requestPath: "go4.org/sort",
- },
- {
- repo: go4sort, name: "go4sort repo: access GitHub path -> no redirect",
- requestPath: "github.com/go4org/go4/sort",
- },
- {
- repo: go4sort, name: "go4sort repo: access GitHub path with weird casing -> redirect to resolved GitHub case",
- requestPath: "github.com/gO4oRg/Go4/sort",
- wantRedirect: "github.com/go4org/go4/sort",
- },
-
- // gtv.
- {
- repo: gtv, name: "gtv repo: access canonical path -> no redirect",
- requestPath: "github.com/teamwork/validate",
- },
- {
- repo: gtv, name: "gtv repo: access canonical GitHub path -> redirect to import comment",
- requestPath: "github.com/Teamwork/validate",
- wantRedirect: "github.com/teamwork/validate",
- },
- {
- repo: gtv, name: "gtv repo: access GitHub path with weird casing -> redirect to import comment",
- requestPath: "github.com/tEaMwOrK/VaLiDaTe",
- wantRedirect: "github.com/teamwork/validate",
- },
- }
- for _, tt := range tests {
- dir := tt.repo
- dir.ImportPath = tt.requestPath
-
- var want error
- if tt.wantRedirect != "" {
- want = gosrc.NotFoundError{
- Message: "not at canonical import path",
- Redirect: tt.wantRedirect,
- }
- }
-
- _, got := newPackage(&dir)
- if got != want {
- t.Errorf("%s: got error %v, want %v", tt.name, got, want)
- }
- }
-}
diff --git a/gosrc/gosrc.go b/gosrc/gosrc.go
index 776bd45..d1a0be8 100644
--- a/gosrc/gosrc.go
+++ b/gosrc/gosrc.go
@@ -541,3 +541,35 @@
}
return nil, NotFoundError{Message: "path does not match registered service"}
}
+
+// MaybeRedirect uses the provided import path, import comment, and resolved GitHub path
+// to make a decision of whether to redirect to another, more canonical import path.
+// It returns nil error to indicate no redirect, or a NotFoundError error to redirect.
+func MaybeRedirect(importPath, importComment, resolvedGitHubPath string) error {
+ switch {
+ case importComment != "":
+ // Redirect to import comment, if not already there.
+ if importPath != importComment {
+ return NotFoundError{
+ Message: "not at canonical import path",
+ Redirect: importComment,
+ }
+ }
+
+ // Redirect to GitHub's reported canonical casing when there's no import comment,
+ // and the import path differs from resolved GitHub path only in case.
+ case importComment == "" && resolvedGitHubPath != "" &&
+ strings.EqualFold(importPath, resolvedGitHubPath):
+
+ // Redirect to resolved GitHub path, if not already there.
+ if importPath != resolvedGitHubPath {
+ return NotFoundError{
+ Message: "not at canonical import path",
+ Redirect: resolvedGitHubPath,
+ }
+ }
+ }
+
+ // No redirect.
+ return nil
+}
diff --git a/gosrc/gosrc_test.go b/gosrc/gosrc_test.go
index 723c73c..3349926 100644
--- a/gosrc/gosrc_test.go
+++ b/gosrc/gosrc_test.go
@@ -319,3 +319,103 @@
}
}
}
+
+// TestMaybeRedirect tests that MaybeRedirect redirects
+// and does not redirect as expected, in various situations.
+// See https://github.com/golang/gddo/issues/507
+// and https://github.com/golang/gddo/issues/579.
+func TestMaybeRedirect(t *testing.T) {
+ type repo struct {
+ ImportComment string
+ ResolvedGitHubPath string
+ }
+
+ // robpike.io/ivy package.
+ // Vanity import path, hosted on GitHub, with import comment.
+ ivy := repo{
+ ImportComment: "robpike.io/ivy",
+ ResolvedGitHubPath: "github.com/robpike/ivy",
+ }
+
+ // go4.org/sort package.
+ // Vanity import path, hosted on GitHub, without import comment.
+ go4sort := repo{
+ ResolvedGitHubPath: "github.com/go4org/go4/sort",
+ }
+
+ // github.com/teamwork/validate package.
+ // Hosted on GitHub, with import comment that doesn't match canonical GitHub case.
+ // See issue https://github.com/golang/gddo/issues/507.
+ gtv := repo{
+ ImportComment: "github.com/teamwork/validate",
+ ResolvedGitHubPath: "github.com/Teamwork/validate", // Note that this differs from import comment.
+ }
+
+ tests := []struct {
+ name string
+ repo repo
+ requestPath string
+ wantRedirect string // Empty string means no redirect.
+ }{
+ // ivy.
+ {
+ repo: ivy, name: "ivy repo: access canonical path -> no redirect",
+ requestPath: "robpike.io/ivy",
+ },
+ {
+ repo: ivy, name: "ivy repo: access GitHub path -> redirect to import comment",
+ requestPath: "github.com/robpike/ivy",
+ wantRedirect: "robpike.io/ivy",
+ },
+ {
+ repo: ivy, name: "ivy repo: access GitHub path with weird casing -> redirect to import comment",
+ requestPath: "github.com/RoBpIkE/iVy",
+ wantRedirect: "robpike.io/ivy",
+ },
+
+ // go4sort.
+ {
+ repo: go4sort, name: "go4sort repo: access canonical path -> no redirect",
+ requestPath: "go4.org/sort",
+ },
+ {
+ repo: go4sort, name: "go4sort repo: access GitHub path -> no redirect",
+ requestPath: "github.com/go4org/go4/sort",
+ },
+ {
+ repo: go4sort, name: "go4sort repo: access GitHub path with weird casing -> redirect to resolved GitHub case",
+ requestPath: "github.com/gO4oRg/Go4/sort",
+ wantRedirect: "github.com/go4org/go4/sort",
+ },
+
+ // gtv.
+ {
+ repo: gtv, name: "gtv repo: access canonical path -> no redirect",
+ requestPath: "github.com/teamwork/validate",
+ },
+ {
+ repo: gtv, name: "gtv repo: access canonical GitHub path -> redirect to import comment",
+ requestPath: "github.com/Teamwork/validate",
+ wantRedirect: "github.com/teamwork/validate",
+ },
+ {
+ repo: gtv, name: "gtv repo: access GitHub path with weird casing -> redirect to import comment",
+ requestPath: "github.com/tEaMwOrK/VaLiDaTe",
+ wantRedirect: "github.com/teamwork/validate",
+ },
+ }
+ for _, tt := range tests {
+ var want error
+ if tt.wantRedirect != "" {
+ want = NotFoundError{
+ Message: "not at canonical import path",
+ Redirect: tt.wantRedirect,
+ }
+ }
+
+ got := MaybeRedirect(tt.requestPath, tt.repo.ImportComment, tt.repo.ResolvedGitHubPath)
+ if got != want {
+ t.Errorf("%s: got error %v, want %v", tt.name, got, want)
+ }
+ }
+}