Skip to content
This repository has been archived by the owner on Jan 16, 2021. It is now read-only.

Commit

Permalink
improve redirection to canonical import path
Browse files Browse the repository at this point in the history
Problem:

Our GitHub organisation is named Teamwork, but for various hard to
change reasons we import packages as teamwork (lower case t). To enforce
this we add an import enforcement for our packages:

	package duck // import "github.com/teamwork/duck"

This works well, but godoc.org enforces users to use the canonical
GitHub path (Teamwork), but with the import statement the Go compiler
enforces a different path, leading to an error.

Fix:

Instead of immediately redirecting in the gosrc package, it will now
only store the canonical import path there. This is before the Go source
code is actually scanned, so we don't *actually* know what the real
canonical path should be.

In the doc.newPackage() function it will check for the canonical import
path, taking both the Go import path as well as the reported path from
the gosrc package in to account, and redirect as needed.

This seems to work for all the cases I can think of:

    github.com/Teamwork/validate    -> github.com/teamwork/validate
    github.com/pkg/ERRORS           -> github.com/pkg/errors
    github.com/Carpetsmoker/sconfig -> arp242.net/sconfig
    arp242.net/SCONFIG              -> not found (expected)
    bitbucket.org/pkg/inflect       -> works
    bitbucket.org/pkg/INFLECT       -> works (should probably redirect too)
    github.com/docker/docker/client -> works (#534)
    github.com/moby/moby/client     -> redirects (on master this actually seems to error out?)

It should also be easy to add a similar check for for some other repo
providers, such as BitBucket, GitLab, etc.

Fixes #507

Change-Id: I49c5ccb328694f95dd7a0e5d577297d56d88893f
GitHub-Last-Rev: 28efc37
GitHub-Pull-Request: #560
Reviewed-on: https://go-review.googlesource.com/120059
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
  • Loading branch information
arp242 authored and shantuo committed Aug 23, 2018
1 parent 3a2d59c commit 9d8ff1c
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 43 deletions.
21 changes: 17 additions & 4 deletions doc/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -576,10 +576,23 @@ func newPackage(dir *gosrc.Directory) (*Package, error) {
return pkg, nil
}

if bpkg.ImportComment != "" && bpkg.ImportComment != dir.ImportPath {
return nil, gosrc.NotFoundError{
Message: "not at canonical import path",
Redirect: bpkg.ImportComment,
switch {
case bpkg.ImportComment != "":
// Redirect to import path comment.
if dir.ImportPath != bpkg.ImportComment {
return nil, gosrc.NotFoundError{
Message: "not at canonical import path",
Redirect: bpkg.ImportComment,
}
}
case bpkg.ImportComment == "" && dir.ResolvedGitHubPath != "":
// Make sure to redirect to GitHub's reported canonical casing when
// there's no import path comment.
if dir.ImportPath != dir.ResolvedGitHubPath {
return nil, gosrc.NotFoundError{
Message: "not at canonical import path",
Redirect: dir.ResolvedGitHubPath,
}
}
}

Expand Down
53 changes: 14 additions & 39 deletions gosrc/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ func init() {
var (
gitHubRawHeader = http.Header{"Accept": {"application/vnd.github-blob.raw"}}
gitHubPreviewHeader = http.Header{"Accept": {"application/vnd.github.preview"}}
ownerRepoPat = regexp.MustCompile(`^https://api.github.com/repos/([^/]+/[^/]+)/`)
)

type githubCommit struct {
Expand All @@ -63,6 +62,7 @@ func getGitHubDir(ctx context.Context, client *http.Client, match map[string]str
c := &httpClient{client: client, errFn: gitHubError}

var repo struct {
FullName string `json:"full_name"`
Fork bool `json:"fork"`
Stars int `json:"stargazers_count"`
CreatedAt time.Time `json:"created_at"`
Expand Down Expand Up @@ -126,10 +126,6 @@ func getGitHubDir(ctx context.Context, client *http.Client, match map[string]str
return nil, NotFoundError{Message: "No files in directory."}
}

if err := validateGitHubProjectName(contents[0].GitURL, match); err != nil {
return nil, err
}

var files []*File
var dataURLs []string
var subdirs []string
Expand Down Expand Up @@ -158,43 +154,22 @@ func getGitHubDir(ctx context.Context, client *http.Client, match map[string]str
}

return &Directory{
BrowseURL: browseURL,
Etag: commits[0].ID,
Files: files,
LineFmt: "%s#L%d",
ProjectName: match["repo"],
ProjectRoot: expand("github.com/{owner}/{repo}", match),
ProjectURL: expand("https://github.com/{owner}/{repo}", match),
Subdirectories: subdirs,
VCS: "git",
Status: status,
Fork: repo.Fork,
Stars: repo.Stars,
ResolvedGitHubPath: "github.com/" + repo.FullName + match["dir"],
BrowseURL: browseURL,
Etag: commits[0].ID,
Files: files,
LineFmt: "%s#L%d",
ProjectName: match["repo"],
ProjectRoot: expand("github.com/{owner}/{repo}", match),
ProjectURL: expand("https://github.com/{owner}/{repo}", match),
Subdirectories: subdirs,
VCS: "git",
Status: status,
Fork: repo.Fork,
Stars: repo.Stars,
}, nil
}

// validateGitHubProjectName checks if the requested owner and repo names match
// the case of the canonical names returned by Github. GitHub owner and repo names
// are case-insensitive so they must be normalized to the canonical casing.
//
// Returns a not found error if the names are the same, but have different case.
// Returns nil if the names match exactly, or if the names are different,
// which will happen if the url is a github redirect to a new project name.
func validateGitHubProjectName(canonicalName string, requestMatch map[string]string) error {
m := ownerRepoPat.FindStringSubmatch(canonicalName)
if m == nil {
return nil
}
requestedName := requestMatch["owner"] + "/" + requestMatch["repo"]
if m[1] == requestedName || !strings.EqualFold(m[1], requestedName) {
return nil
}
return NotFoundError{
Message: "Github import path has incorrect case.",
Redirect: fmt.Sprintf("github.com/%s%s", m[1], requestMatch["dir"]),
}
}

// isQuickFork reports whether the repository is a "quick fork":
// it has fewer than 3 commits, all within a week of the repo creation, createdAt.
// Commits must be in reverse chronological order by Commit.Committer.Date.
Expand Down
7 changes: 7 additions & 0 deletions gosrc/gosrc.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ type Directory struct {
// Import path of package after resolving go-import meta tags, if any.
ResolvedPath string

// Import path of package with the canonical user/repo case as reported by
// the github.com server. Optional.
// If set, used to ensure canonical case is used when there's no import path
// comment (e.g., to redirect from "github.com/UsEr/rEpO/dir" to
// "github.com/User/Repo/dir").
ResolvedGitHubPath string

// Import path prefix for all packages in the project.
ProjectRoot string

Expand Down

0 comments on commit 9d8ff1c

Please sign in to comment.