From 09d58b923db0bc1255fbbaedf61e1f61ca63b34a Mon Sep 17 00:00:00 2001 From: nate smith Date: Thu, 10 Oct 2019 16:02:23 -0500 Subject: [PATCH] add GitHubRepository --- api/queries.go | 27 ++++--------- context/ghrepo.go | 100 ++++++++++++++++++++++++++++++++++++++++++++++ github/hosts.go | 2 +- github/project.go | 2 +- github/remote.go | 16 ++++++++ 5 files changed, 125 insertions(+), 22 deletions(-) create mode 100644 context/ghrepo.go diff --git a/api/queries.go b/api/queries.go index 72b9056e0..51fe5d700 100644 --- a/api/queries.go +++ b/api/queries.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/github/gh-cli/context" - "github.com/github/gh-cli/github" ) type PullRequestsPayload struct { @@ -80,9 +79,13 @@ func PullRequests() (PullRequestsPayload, error) { } ` - project := project() - owner := project.Owner - repo := project.Name + ghRepo, rerr := context.CurrentGitHubRepository() + if rerr != nil { + return PullRequestsPayload{}, nil + } + + owner := ghRepo.Owner + repo := ghRepo.Name currentBranch, cberr := context.CurrentBranch() if cberr != nil { return PullRequestsPayload{}, cberr @@ -132,19 +135,3 @@ func PullRequests() (PullRequestsPayload, error) { return payload, nil } - -// TODO: Everything below this line will be removed when Nate's context work is complete -func project() github.Project { - remotes, error := github.Remotes() - if error != nil { - panic(error) - } - - for _, remote := range remotes { - if project, error := remote.Project(); error == nil { - return *project - } - } - - panic("Could not get the project. What is a project? I don't know, it's kind of like a git repository I think?") -} diff --git a/context/ghrepo.go b/context/ghrepo.go new file mode 100644 index 000000000..a64425761 --- /dev/null +++ b/context/ghrepo.go @@ -0,0 +1,100 @@ +package context + +import ( + "fmt" + "net/url" + "os" + "strings" + + "github.com/github/gh-cli/github" +) + +type GitHubRepository struct { + Name string + Owner string + Host string + Protocol string +} + +func CurrentGitHubRepository() (*GitHubRepository, error) { + + var repoURL *url.URL + var err error + if repoFromEnv := os.Getenv("GH_REPO"); repoFromEnv != "" { + repoURL, err = url.Parse(fmt.Sprintf("https://github.com/%s.git", repoFromEnv)) + if err != nil { + return nil, err + } + } else { + remote, rerr := github.GuessRemote() + + if rerr != nil { + return nil, rerr + } + repoURL = remote.URL + } + + urlError := fmt.Errorf("invalid GitHub URL: %s", repoURL) + if !github.KnownGitHubHostsInclude(repoURL.Host) { + return nil, urlError + } + + parts := strings.SplitN(repoURL.Path, "/", 4) + if len(parts) <= 2 { + return nil, urlError + } + + name := strings.TrimSuffix(parts[2], ".git") + owner := parts[1] + host := repoURL.Host + protocol := repoURL.Scheme + + if strings.Contains(owner, "/") { + result := strings.SplitN(owner, "/", 2) + owner = result[0] + if name == "" { + name = result[1] + } + } else if strings.Contains(name, "/") { + result := strings.SplitN(name, "/", 2) + if owner == "" { + owner = result[0] + } + name = result[1] + } + + if host == "" { + host = github.DefaultGitHubHost() + } + if host == "ssh.github.com" { + host = github.GitHubHost + } + + if protocol != "http" && protocol != "https" { + protocol = "" + } + if protocol == "" { + h := github.CurrentConfig().Find(host) + if h != nil { + protocol = h.Protocol + } + } + if protocol == "" { + protocol = "https" + } + + if owner == "" { + h := github.CurrentConfig().Find(host) + if h != nil { + owner = h.User + } + } + + return &GitHubRepository{ + Name: name, + Owner: owner, + Host: host, + Protocol: protocol, + }, nil + +} diff --git a/github/hosts.go b/github/hosts.go index 5cf889c53..a74d9810c 100644 --- a/github/hosts.go +++ b/github/hosts.go @@ -22,7 +22,7 @@ func (e *GithubHostError) Error() string { return fmt.Sprintf("Invalid GitHub URL: %s", e.url) } -func knownGitHubHostsInclude(host string) bool { +func KnownGitHubHostsInclude(host string) bool { for _, hh := range knownGitHubHosts() { if hh == host { return true diff --git a/github/project.go b/github/project.go index 142532f2d..6e9fa3c41 100644 --- a/github/project.go +++ b/github/project.go @@ -47,7 +47,7 @@ func (p *Project) GitURL(name, owner string, isSSH bool) string { } func NewProjectFromURL(url *url.URL) (p *Project, err error) { - if !knownGitHubHostsInclude(url.Host) { + if !KnownGitHubHostsInclude(url.Host) { err = &GithubHostError{url} return } diff --git a/github/remote.go b/github/remote.go index 523b54d7f..80e4eaa55 100644 --- a/github/remote.go +++ b/github/remote.go @@ -99,3 +99,19 @@ func newRemote(name string, urlMap map[string]string) (Remote, error) { return r, nil } + +// GuessRemote attempts to select and return the remote a user likely wants to target when dealing with GitHub repositories. +func GuessRemote() (Remote, error) { + + remotes, err := Remotes() + if err != nil { + return Remote{}, err + } + + if len(remotes) == 0 { + return Remote{}, fmt.Errorf("unable to guess remote") + } + + // lol + return remotes[0], nil +}