Skip to content

Commit 58cf8b5

Browse files
committed
determine vcs automatically. GoogleCloudPlatform#26 and GoogleCloudPlatform#27
1 parent 17664a4 commit 58cf8b5

File tree

2 files changed

+95
-34
lines changed

2 files changed

+95
-34
lines changed

handler.go

Lines changed: 72 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ type Handler struct {
3131
PathConfigs
3232
}
3333

34+
// vcsPrefixMap provides defaults for VCS type if it's not provided.
35+
// The list of strings is used in strings.HasPrefix().
36+
var vcsPrefixMap = map[string][]string{
37+
"git": []string{"https://git", "https://bitbucket"},
38+
"bzr": []string{"https://bazaar"},
39+
"hg": []string{"https://hg.", "https://mercurial"},
40+
"svn": []string{"https://svn."},
41+
}
42+
3443
// Config contains the config file data.
3544
type Config struct {
3645
Title string `yaml:"title,omitempty"`
@@ -81,47 +90,77 @@ func newHandler(configData []byte) (*Handler, error) {
8190
if h.CacheAge != nil {
8291
cacheControl = fmt.Sprintf("public, max-age=%d", *h.CacheAge)
8392
}
84-
85-
for p, e := range h.Paths {
93+
for p := range h.Paths {
8694
h.Paths[p].Path = p
87-
88-
if len(e.RedirPaths) < 1 {
95+
if len(h.Paths[p].RedirPaths) < 1 {
8996
// was not provided, pass in global value.
90-
e.RedirPaths = h.RedirPaths
97+
h.Paths[p].RedirPaths = h.RedirPaths
9198
}
92-
h.Paths[p].cacheControl = cacheControl
93-
if e.CacheAge != nil {
94-
// provided, override global value.
95-
h.Paths[p].cacheControl = fmt.Sprintf("public, max-age=%d", *e.CacheAge)
99+
h.Paths[p].setRepoCacheControl(cacheControl)
100+
h.Paths[p].setRepoDisplay()
101+
if err := h.Paths[p].setRepoVCS(); err != nil {
102+
return nil, err
96103
}
104+
h.PathConfigs = append(h.PathConfigs, h.Paths[p])
105+
}
106+
sort.Sort(h.PathConfigs)
107+
return h, nil
108+
}
109+
110+
func (p *PathConfig) setRepoCacheControl(cc string) {
111+
p.cacheControl = cc
112+
if p.CacheAge != nil {
113+
// provided, override global value.
114+
p.cacheControl = fmt.Sprintf("public, max-age=%d", *p.CacheAge)
115+
}
116+
}
97117

98-
switch {
99-
case e.Display != "":
100-
// Already filled in.
101-
case strings.HasPrefix(e.Repo, "https://github.com/"):
102-
h.Paths[p].Display = fmt.Sprintf("%v %v/tree/master{/dir} %v/blob/master{/dir}/{file}#L{line}", e.Repo, e.Repo, e.Repo)
103-
case strings.HasPrefix(e.Repo, "https://bitbucket.org"):
104-
h.Paths[p].Display = fmt.Sprintf("%v %v/src/default{/dir} %v/src/default{/dir}/{file}#{file}-{line}", e.Repo, e.Repo, e.Repo)
118+
// Set display path.
119+
func (p *PathConfig) setRepoDisplay() {
120+
if p.Display != "" {
121+
return
122+
}
123+
// github, gitlab, git, svn, hg, bzr - may need more tweaking for some of these.
124+
p.Display = fmt.Sprintf("%v %v/tree/master{/dir} %v/blob/master{/dir}/{file}#L{line}", p.Repo, p.Repo, p.Repo)
125+
if strings.HasPrefix(p.Repo, "https://bitbucket.org") {
126+
// bitbucket is weird.
127+
p.Display = fmt.Sprintf("%v %v/src/default{/dir} %v/src/default{/dir}/{file}#{file}-{line}", p.Repo, p.Repo, p.Repo)
128+
}
129+
}
130+
131+
// setRepoVCS makes sure the provides VCS type is supported,
132+
// or sets it automatically based on the repo's prefix.
133+
func (p *PathConfig) setRepoVCS() error {
134+
// Check and set VCS type.
135+
switch {
136+
case p.Repo == "" && p.Redir != "":
137+
// Redirect-only can go anywhere.
138+
case p.VCS == "github" || p.VCS == "gitlab" || p.VCS == "bitbucket":
139+
p.VCS = "git"
140+
case p.VCS == "":
141+
// Try to figure it out.
142+
var err error
143+
p.VCS, err = findRepoVCS(p.Repo)
144+
return err
145+
default:
146+
// Already filled in, make sure it's supported.
147+
if _, ok := vcsPrefixMap[p.VCS]; !ok {
148+
return fmt.Errorf("configuration for %v: unknown VCS %s", p, p.VCS)
105149
}
150+
}
151+
return nil
152+
}
106153

107-
switch {
108-
case e.VCS != "":
109-
// Already filled in.
110-
if e.VCS != "bzr" && e.VCS != "git" && e.VCS != "hg" && e.VCS != "svn" {
111-
return nil, fmt.Errorf("configuration for %v: unknown VCS %s", p, e.VCS)
154+
// findRepoVCS checks the vcsMapList for a supported vcs type based on a repo's prefix.
155+
func findRepoVCS(repo string) (string, error) {
156+
for vcs, prefixList := range vcsPrefixMap {
157+
for _, prefix := range prefixList {
158+
if strings.HasPrefix(repo, prefix) {
159+
return vcs, nil
112160
}
113-
case strings.HasPrefix(e.Repo, "https://github.com/"):
114-
h.Paths[p].VCS = "git"
115-
case e.Repo == "" && e.Redir != "":
116-
// Redirect-only can go anywhere.
117-
default:
118-
return nil, fmt.Errorf("configuration for %v: cannot infer VCS from %s", p, e.Repo)
119161
}
120-
121-
h.PathConfigs = append(h.PathConfigs, e)
122162
}
123-
sort.Sort(h.PathConfigs)
124-
return h, nil
163+
return "", fmt.Errorf("cannot infer VCS from %s", repo)
125164
}
126165

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

171210
// StringInSlices checks if a string exists in a list of strings.
172-
// Used to determine if a sub path shouuld be redirected or not.
211+
// Used to determine if a sub path should be redirected or not.
212+
// Not used for normal vanity URLs, only used for `redir`.
173213
func StringInSlices(str string, slice []string) bool {
174214
for _, s := range slice {
175215
if strings.Contains(str, s) {

handler_test.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,27 @@ func TestHandler(t *testing.T) {
108108
goImport: "example.com git https://github.com/rakyll/portmidi",
109109
goSource: "example.com https://github.com/rakyll/portmidi _ _",
110110
},
111+
{
112+
name: "display Gitlab inference",
113+
config: "host: example.com\n" +
114+
"paths:\n" +
115+
" /portmidi:\n" +
116+
" repo: https://gitlab.com/rakyll/portmidi\n",
117+
path: "/portmidi",
118+
goImport: "example.com/portmidi git https://gitlab.com/rakyll/portmidi",
119+
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}",
120+
},
121+
{
122+
name: "display Gitlab inference",
123+
config: "host: example.com\n" +
124+
"paths:\n" +
125+
" /portmidi:\n" +
126+
" vcs: gitlab\n" +
127+
" repo: https://gitlab.com/rakyll/portmidi\n",
128+
path: "/portmidi",
129+
goImport: "example.com/portmidi git https://gitlab.com/rakyll/portmidi",
130+
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}",
131+
},
111132
}
112133
for _, test := range tests {
113134
h, err := newHandler([]byte(test.config))
@@ -145,10 +166,10 @@ func TestBadConfigs(t *testing.T) {
145166
badConfigs := []string{
146167
"paths:\n" +
147168
" /missingvcs:\n" +
148-
" repo: https://bitbucket.org/zombiezen/gopdf\n",
169+
" repo: https://unknownbucket.org/zombiezen/gopdf\n",
149170
"paths:\n" +
150171
" /unknownvcs:\n" +
151-
" repo: https://bitbucket.org/zombiezen/gopdf\n" +
172+
" repo: https://unknownbucket.org/zombiezen/gopdf\n" +
152173
" vcs: xyzzy\n",
153174
"cache_max_age: -1\n" +
154175
"paths:\n" +

0 commit comments

Comments
 (0)