Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 32 additions & 16 deletions util/git/hosts.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,38 @@ type HostHandler interface {
}

var hostHandlers []struct {
exactHost string
handler HostHandler
host string
handler HostHandler
}

// RegisterHostHandler allows for the registration of a host handler
// that is triggered when the host of a URL exactly matches the given host,
// that is triggered when the host of a URL matches the given host,
// ignoring case.
//
// If host starts with a ".", it will be matched as a domain suffix.
// Exact host matches take precedence over suffix matches.
//
// This method is not thread-safe, and is expected to be called from init().
func RegisterHostHandler(exactHost string, handler HostHandler) {
func RegisterHostHandler(host string, handler HostHandler) {
hostHandlers = append(hostHandlers, struct {
exactHost string
handler HostHandler
host string
handler HostHandler
}{
exactHost: exactHost,
handler: handler,
host: strings.ToLower(host),
handler: handler,
})
}

// getHostHandler returns the registered handler for the host.
func getHostHandler(host string) HostHandler {
host = strings.ToLower(host)
for _, h := range hostHandlers {
if h.exactHost == host {
if h.host == host {
return h.handler
}
}
for _, h := range hostHandlers {
if strings.HasPrefix(h.host, ".") && strings.HasSuffix(host, h.host) {
return h.handler
}
}
Expand Down Expand Up @@ -143,9 +151,14 @@ func (h *StandardHostHandler) Canon(u *url.URL) *url.URL {
res.User = nil
}

// Always strip trailing slashes first so segment counting and .git suffix
// handling operate on the path without trailing slashes. If h.HasTrailingSlash
// is true, a trailing slash will be re-added at the end.
res.Path = strings.TrimRight(res.Path, "/")
Comment thread
cuixq marked this conversation as resolved.
Resolved

if h.LowerPathSegments != 0 {
// Strip the prefix and trailing slash so that we can count the remaining path segments correctly.
path := strings.TrimRight(res.Path, "/")
// Strip the prefix so that we can count the remaining path segments correctly.
path := res.Path
prefix := ""
if h.PathPrefix != "" {
prefix = "/" + strings.Trim(h.PathPrefix, "/")
Expand Down Expand Up @@ -184,11 +197,7 @@ func (h *StandardHostHandler) Canon(u *url.URL) *url.URL {
}

if h.HasTrailingSlash {
if !strings.HasSuffix(res.Path, "/") {
res.Path += "/"
}
} else {
res.Path = strings.TrimSuffix(res.Path, "/")
res.Path += "/"
}

return &res
Expand Down Expand Up @@ -232,4 +241,11 @@ func init() {
MinPathSegments: 2,
MaxPathSegments: 2,
})

RegisterHostHandler(".googlesource.com", &StandardHostHandler{
ForceScheme: "https",
StripUser: true,
HasDotGitSuffix: true,
MinPathSegments: 1,
})
}
31 changes: 31 additions & 0 deletions util/git/hosts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@ func TestGetHostHandler(t *testing.T) {
hostHandlers = nil

h1 := &StandardHostHandler{}
h2 := &StandardHostHandler{}
h3 := &StandardHostHandler{}

RegisterHostHandler("example.com", h1)
RegisterHostHandler(".other.com", h2)
RegisterHostHandler("special.other.com", h3)

tests := []struct {
host string
Expand All @@ -22,6 +26,9 @@ func TestGetHostHandler(t *testing.T) {
{"example.com", h1},
{"foo.example.com", noop},
{"other.com", noop},
{"foo.other.com", h2},
{"bar.foo.other.com", h2},
{"special.other.com", h3},
}

for _, tt := range tests {
Expand Down Expand Up @@ -179,12 +186,36 @@ func TestStandardHostHandler_Canon(t *testing.T) {
url: "https://example.com/foo/bar",
want: "https://example.com/foo/bar.git",
},
{
name: "add .git suffix when input has trailing slash",
handler: StandardHostHandler{HasDotGitSuffix: true},
url: "https://example.com/foo/bar/",
want: "https://example.com/foo/bar.git",
},
{
name: "keep .git suffix when input has trailing slash",
handler: StandardHostHandler{HasDotGitSuffix: true},
url: "https://example.com/foo/bar.git/",
want: "https://example.com/foo/bar.git",
},
{
name: "add .git suffix and keep trailing slash",
handler: StandardHostHandler{HasDotGitSuffix: true, HasTrailingSlash: true},
url: "https://example.com/foo/bar/",
want: "https://example.com/foo/bar.git/",
},
{
name: "has dot git suffix (remove)",
handler: StandardHostHandler{HasDotGitSuffix: false},
url: "https://example.com/foo/bar.git",
want: "https://example.com/foo/bar",
},
{
name: "remove .git suffix when input has trailing slash",
handler: StandardHostHandler{HasDotGitSuffix: false},
url: "https://example.com/foo/bar.git/",
want: "https://example.com/foo/bar",
},
{
name: "has trailing slash (add)",
handler: StandardHostHandler{HasTrailingSlash: true},
Expand Down
4 changes: 2 additions & 2 deletions util/git/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ func (r *Repo) ID() string {
host = "[" + host + "]"
}

path := strings.TrimSuffix(u.EscapedPath(), ".git")
path = strings.TrimSuffix(path, "/")
path := strings.TrimRight(u.EscapedPath(), "/")
path = strings.TrimSuffix(path, ".git")

return host + path
}
22 changes: 22 additions & 0 deletions util/git/repo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@ func TestParseRepo(t *testing.T) {
input: "https://github.com/only-one",
wantErr: ErrInvalidRepo, // defaultHostHandler requires 2 segments
},
{
name: "googlesource trailing slash",
input: "https://chromium.googlesource.com/chromium/src.git/",
wantCanon: "https://chromium.googlesource.com/chromium/src.git",
wantParsed: "https://chromium.googlesource.com/chromium/src.git/",
},
{
name: "googlesource preserves path case",
input: "https://android.googlesource.com/platform/packages/apps/Settings",
wantCanon: "https://android.googlesource.com/platform/packages/apps/Settings.git",
wantParsed: "https://android.googlesource.com/platform/packages/apps/Settings",
},
}

for _, tt := range tests {
Expand Down Expand Up @@ -114,6 +126,16 @@ func TestRepo_ID(t *testing.T) {
input: "https://github.com/user/repo/",
want: "github.com/user/repo",
},
{
name: "googlesource .git and trailing slash",
input: "https://chromium.googlesource.com/chromium/src.git/",
want: "chromium.googlesource.com/chromium/src",
},
{
name: "unregistered host .git and trailing slash",
input: "https://example.com/user/repo.git/",
want: "example.com/user/repo",
},
}

for _, tt := range tests {
Expand Down
Loading