diff --git a/internal/ghrepo/repo.go b/internal/ghrepo/repo.go index f683d9249..a4bfa82d6 100644 --- a/internal/ghrepo/repo.go +++ b/internal/ghrepo/repo.go @@ -8,21 +8,26 @@ import ( const defaultHostname = "github.com" +// Interface describes an object that represents a GitHub repository type Interface interface { RepoName() string RepoOwner() string } +// New instantiates a GitHub repository from owner and name arguments func New(owner, repo string) Interface { return &ghRepo{ owner: owner, name: repo, } } + +// FullName serializes a GitHub repository into an "OWNER/REPO" string func FullName(r Interface) string { return fmt.Sprintf("%s/%s", r.RepoOwner(), r.RepoName()) } +// FromFullName extracts the GitHub repository inforation from an "OWNER/REPO" string func FromFullName(nwo string) Interface { var r ghRepo parts := strings.SplitN(nwo, "/", 2) @@ -32,8 +37,9 @@ func FromFullName(nwo string) Interface { return &r } +// FromURL extracts the GitHub repository information from a URL func FromURL(u *url.URL) (Interface, error) { - if !strings.EqualFold(u.Hostname(), defaultHostname) { + if !strings.EqualFold(u.Hostname(), defaultHostname) && !strings.EqualFold(u.Hostname(), "www."+defaultHostname) { return nil, fmt.Errorf("unsupported hostname: %s", u.Hostname()) } parts := strings.SplitN(strings.TrimPrefix(u.Path, "/"), "/", 3) @@ -43,6 +49,7 @@ func FromURL(u *url.URL) (Interface, error) { return New(parts[0], strings.TrimSuffix(parts[1], ".git")), nil } +// IsSame compares two GitHub repositories func IsSame(a, b Interface) bool { return strings.EqualFold(a.RepoOwner(), b.RepoOwner()) && strings.EqualFold(a.RepoName(), b.RepoName()) diff --git a/internal/ghrepo/repo_test.go b/internal/ghrepo/repo_test.go index 6ff775c84..fef04fb8c 100644 --- a/internal/ghrepo/repo_test.go +++ b/internal/ghrepo/repo_test.go @@ -1,40 +1,66 @@ package ghrepo import ( + "errors" + "fmt" "net/url" "testing" ) func Test_repoFromURL(t *testing.T) { - u, _ := url.Parse("http://github.com/monalisa/octo-cat.git") - repo, err := FromURL(u) - if err != nil { - t.Fatalf("got error %q", err) + tests := []struct { + name string + input string + result string + err error + }{ + { + name: "github.com URL", + input: "https://github.com/monalisa/octo-cat.git", + result: "monalisa/octo-cat", + err: nil, + }, + { + name: "www.github.com URL", + input: "http://www.GITHUB.com/monalisa/octo-cat.git", + result: "monalisa/octo-cat", + err: nil, + }, + { + name: "unsupported hostname", + input: "https://example.com/one/two", + result: "", + err: errors.New("unsupported hostname: example.com"), + }, + { + name: "filesystem path", + input: "/path/to/file", + result: "", + err: errors.New("unsupported hostname: "), + }, } - if repo.RepoOwner() != "monalisa" { - t.Errorf("got owner %q", repo.RepoOwner()) - } - if repo.RepoName() != "octo-cat" { - t.Errorf("got name %q", repo.RepoName()) - } -} -func Test_repoFromURL_invalid(t *testing.T) { - cases := [][]string{ - []string{ - "https://example.com/one/two", - "unsupported hostname: example.com", - }, - []string{ - "/path/to/disk", - "unsupported hostname: ", - }, - } - for _, c := range cases { - u, _ := url.Parse(c[0]) - _, err := FromURL(u) - if err == nil || err.Error() != c[1] { - t.Errorf("got %q", err) - } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + u, err := url.Parse(tt.input) + if err != nil { + t.Fatalf("got error %q", err) + } + + repo, err := FromURL(u) + if err != nil { + if tt.err == nil { + t.Fatalf("got error %q", err) + } else if tt.err.Error() == err.Error() { + return + } + t.Fatalf("got error %q", err) + } + + got := fmt.Sprintf("%s/%s", repo.RepoOwner(), repo.RepoName()) + if tt.result != got { + t.Errorf("expected %q, got %q", tt.result, got) + } + }) } }