Skip to content

Commit

Permalink
determine vcs automatically. GoogleCloudPlatform#26 and GoogleCloudPl…
Browse files Browse the repository at this point in the history
  • Loading branch information
davidnewhall committed Jul 18, 2019
1 parent 17664a4 commit 58cf8b5
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 34 deletions.
104 changes: 72 additions & 32 deletions handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ type Handler struct {
PathConfigs
}

// vcsPrefixMap provides defaults for VCS type if it's not provided.
// The list of strings is used in strings.HasPrefix().
var vcsPrefixMap = map[string][]string{
"git": []string{"https://git", "https://bitbucket"},
"bzr": []string{"https://bazaar"},
"hg": []string{"https://hg.", "https://mercurial"},
"svn": []string{"https://svn."},
}

// Config contains the config file data.
type Config struct {
Title string `yaml:"title,omitempty"`
Expand Down Expand Up @@ -81,47 +90,77 @@ func newHandler(configData []byte) (*Handler, error) {
if h.CacheAge != nil {
cacheControl = fmt.Sprintf("public, max-age=%d", *h.CacheAge)
}

for p, e := range h.Paths {
for p := range h.Paths {
h.Paths[p].Path = p

if len(e.RedirPaths) < 1 {
if len(h.Paths[p].RedirPaths) < 1 {
// was not provided, pass in global value.
e.RedirPaths = h.RedirPaths
h.Paths[p].RedirPaths = h.RedirPaths
}
h.Paths[p].cacheControl = cacheControl
if e.CacheAge != nil {
// provided, override global value.
h.Paths[p].cacheControl = fmt.Sprintf("public, max-age=%d", *e.CacheAge)
h.Paths[p].setRepoCacheControl(cacheControl)
h.Paths[p].setRepoDisplay()
if err := h.Paths[p].setRepoVCS(); err != nil {
return nil, err
}
h.PathConfigs = append(h.PathConfigs, h.Paths[p])
}
sort.Sort(h.PathConfigs)
return h, nil
}

func (p *PathConfig) setRepoCacheControl(cc string) {
p.cacheControl = cc
if p.CacheAge != nil {
// provided, override global value.
p.cacheControl = fmt.Sprintf("public, max-age=%d", *p.CacheAge)
}
}

switch {
case e.Display != "":
// Already filled in.
case strings.HasPrefix(e.Repo, "https://github.com/"):
h.Paths[p].Display = fmt.Sprintf("%v %v/tree/master{/dir} %v/blob/master{/dir}/{file}#L{line}", e.Repo, e.Repo, e.Repo)
case strings.HasPrefix(e.Repo, "https://bitbucket.org"):
h.Paths[p].Display = fmt.Sprintf("%v %v/src/default{/dir} %v/src/default{/dir}/{file}#{file}-{line}", e.Repo, e.Repo, e.Repo)
// Set display path.
func (p *PathConfig) setRepoDisplay() {
if p.Display != "" {
return
}
// github, gitlab, git, svn, hg, bzr - may need more tweaking for some of these.
p.Display = fmt.Sprintf("%v %v/tree/master{/dir} %v/blob/master{/dir}/{file}#L{line}", p.Repo, p.Repo, p.Repo)
if strings.HasPrefix(p.Repo, "https://bitbucket.org") {
// bitbucket is weird.
p.Display = fmt.Sprintf("%v %v/src/default{/dir} %v/src/default{/dir}/{file}#{file}-{line}", p.Repo, p.Repo, p.Repo)
}
}

// setRepoVCS makes sure the provides VCS type is supported,
// or sets it automatically based on the repo's prefix.
func (p *PathConfig) setRepoVCS() error {
// Check and set VCS type.
switch {
case p.Repo == "" && p.Redir != "":
// Redirect-only can go anywhere.
case p.VCS == "github" || p.VCS == "gitlab" || p.VCS == "bitbucket":
p.VCS = "git"
case p.VCS == "":
// Try to figure it out.
var err error
p.VCS, err = findRepoVCS(p.Repo)
return err
default:
// Already filled in, make sure it's supported.
if _, ok := vcsPrefixMap[p.VCS]; !ok {
return fmt.Errorf("configuration for %v: unknown VCS %s", p, p.VCS)
}
}
return nil
}

switch {
case e.VCS != "":
// Already filled in.
if e.VCS != "bzr" && e.VCS != "git" && e.VCS != "hg" && e.VCS != "svn" {
return nil, fmt.Errorf("configuration for %v: unknown VCS %s", p, e.VCS)
// findRepoVCS checks the vcsMapList for a supported vcs type based on a repo's prefix.
func findRepoVCS(repo string) (string, error) {
for vcs, prefixList := range vcsPrefixMap {
for _, prefix := range prefixList {
if strings.HasPrefix(repo, prefix) {
return vcs, nil
}
case strings.HasPrefix(e.Repo, "https://github.com/"):
h.Paths[p].VCS = "git"
case e.Repo == "" && e.Redir != "":
// Redirect-only can go anywhere.
default:
return nil, fmt.Errorf("configuration for %v: cannot infer VCS from %s", p, e.Repo)
}

h.PathConfigs = append(h.PathConfigs, e)
}
sort.Sort(h.PathConfigs)
return h, nil
return "", fmt.Errorf("cannot infer VCS from %s", repo)
}

func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -169,7 +208,8 @@ func (h *Handler) Hostname(r *http.Request) string {
}

// StringInSlices checks if a string exists in a list of strings.
// Used to determine if a sub path shouuld be redirected or not.
// Used to determine if a sub path should be redirected or not.
// Not used for normal vanity URLs, only used for `redir`.
func StringInSlices(str string, slice []string) bool {
for _, s := range slice {
if strings.Contains(str, s) {
Expand Down
25 changes: 23 additions & 2 deletions handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,27 @@ func TestHandler(t *testing.T) {
goImport: "example.com git https://github.com/rakyll/portmidi",
goSource: "example.com https://github.com/rakyll/portmidi _ _",
},
{
name: "display Gitlab inference",
config: "host: example.com\n" +
"paths:\n" +
" /portmidi:\n" +
" repo: https://gitlab.com/rakyll/portmidi\n",
path: "/portmidi",
goImport: "example.com/portmidi git https://gitlab.com/rakyll/portmidi",
goSource: "example.com/portmidi https://gitlab.com/rakyll/portmidi https://gitlab.com/rakyll/portmidi/tree/master{/dir} https://gitlab.com/rakyll/portmidi/blob/master{/dir}/{file}#L{line}",
},
{
name: "display Gitlab inference",
config: "host: example.com\n" +
"paths:\n" +
" /portmidi:\n" +
" vcs: gitlab\n" +
" repo: https://gitlab.com/rakyll/portmidi\n",
path: "/portmidi",
goImport: "example.com/portmidi git https://gitlab.com/rakyll/portmidi",
goSource: "example.com/portmidi https://gitlab.com/rakyll/portmidi https://gitlab.com/rakyll/portmidi/tree/master{/dir} https://gitlab.com/rakyll/portmidi/blob/master{/dir}/{file}#L{line}",
},
}
for _, test := range tests {
h, err := newHandler([]byte(test.config))
Expand Down Expand Up @@ -145,10 +166,10 @@ func TestBadConfigs(t *testing.T) {
badConfigs := []string{
"paths:\n" +
" /missingvcs:\n" +
" repo: https://bitbucket.org/zombiezen/gopdf\n",
" repo: https://unknownbucket.org/zombiezen/gopdf\n",
"paths:\n" +
" /unknownvcs:\n" +
" repo: https://bitbucket.org/zombiezen/gopdf\n" +
" repo: https://unknownbucket.org/zombiezen/gopdf\n" +
" vcs: xyzzy\n",
"cache_max_age: -1\n" +
"paths:\n" +
Expand Down

0 comments on commit 58cf8b5

Please sign in to comment.