Import cucumber tests from Hub and get the pull_request.feature going a bit

This commit is contained in:
Jingwen Owen Ou 2013-12-06 10:50:19 -08:00
Родитель 65ba149f30
Коммит a270fd25f6
22 изменённых файлов: 487 добавлений и 93 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -2,3 +2,4 @@ gh
*.test
target
.vagrant
/tmp

6
Gemfile Normal file
Просмотреть файл

@ -0,0 +1,6 @@
source 'https://rubygems.org'
gem 'aruba', '~> 0.5.3'
gem 'cucumber', '~> 1.3.9'
gem 'sinatra'
gem 'rake'

42
Gemfile.lock Normal file
Просмотреть файл

@ -0,0 +1,42 @@
GEM
remote: https://rubygems.org/
specs:
aruba (0.5.3)
childprocess (>= 0.3.6)
cucumber (>= 1.1.1)
rspec-expectations (>= 2.7.0)
builder (3.2.2)
childprocess (0.3.9)
ffi (~> 1.0, >= 1.0.11)
cucumber (1.3.10)
builder (>= 2.1.2)
diff-lcs (>= 1.1.3)
gherkin (~> 2.12)
multi_json (>= 1.7.5, < 2.0)
multi_test (>= 0.0.2)
diff-lcs (1.2.5)
ffi (1.9.3)
gherkin (2.12.2)
multi_json (~> 1.3)
multi_json (1.8.2)
multi_test (0.0.2)
rack (1.5.2)
rack-protection (1.5.1)
rack
rake (10.1.0)
rspec-expectations (2.14.4)
diff-lcs (>= 1.1.3, < 2.0)
sinatra (1.4.4)
rack (~> 1.4)
rack-protection (~> 1.4)
tilt (~> 1.3, >= 1.3.4)
tilt (1.4.1)
PLATFORMS
ruby
DEPENDENCIES
aruba (~> 0.5.3)
cucumber (~> 1.3.9)
rake
sinatra

Просмотреть файл

@ -42,7 +42,7 @@ func fetch(command *Command, args *Args) {
func tranformFetchArgs(args *Args) error {
names := parseRemoteNames(args)
gh := github.New()
projects := []github.Project{}
projects := []*github.Project{}
ownerRegexp := regexp.MustCompile(OwnerRe)
for _, name := range names {
if ownerRegexp.MatchString(name) && !hasGitRemote(name) {

Просмотреть файл

@ -9,13 +9,14 @@ import (
"github.com/jingweno/gh/utils"
"io/ioutil"
"os"
"reflect"
"regexp"
"strings"
)
var cmdPullRequest = &Command{
Run: pullRequest,
Usage: "pull-request [-f] [-i ISSUE] [-b BASE] [-d HEAD] [TITLE]",
Usage: "pull-request [-f] [-i ISSUE] [-b BASE] [-d HEAD] [-m MESSAGE] [TITLE]",
Short: "Open a pull request on GitHub",
Long: `Opens a pull request on GitHub for the project that the "origin" remote
points to. The default head of the pull request is the current branch.
@ -34,12 +35,13 @@ of title you can paste a full URL to an issue on GitHub.
`,
}
var flagPullRequestBase, flagPullRequestHead, flagPullRequestIssue string
var flagPullRequestBase, flagPullRequestHead, flagPullRequestIssue, flagPullRequestMessage string
func init() {
cmdPullRequest.Flag.StringVar(&flagPullRequestBase, "b", "master", "BASE")
cmdPullRequest.Flag.StringVar(&flagPullRequestHead, "d", "", "HEAD")
cmdPullRequest.Flag.StringVar(&flagPullRequestIssue, "i", "", "ISSUE")
cmdPullRequest.Flag.StringVar(&flagPullRequestMessage, "m", "", "MESSAGE")
}
/*
@ -51,19 +53,95 @@ func init() {
# explicit pull base & head:
$ gh pull-request -b jingweno:master -h jingweno:feature
$ gh pull-request -m "title\n\nbody"
[ create pull request with title & body ]
$ gh pull-request -i 123
[ attached pull request to issue #123 ]
$ gh pull-request https://github.com/jingweno/gh/pull/123
[ attached pull request to issue #123 ]
*/
func pullRequest(cmd *Command, args *Args) {
var title, body string
if args.ParamsSize() == 1 {
title = args.RemoveParam(0)
localRepo := github.LocalRepo()
currentBranch, err := localRepo.CurrentBranch()
if err != nil {
utils.Check(fmt.Errorf("Aborted: not currently on any branch."))
}
gh := github.New()
repo := gh.Project.LocalRepoWith(flagPullRequestBase, flagPullRequestHead)
baseProject, err := localRepo.MainProject()
if err != nil {
utils.Check(fmt.Errorf("Aborted: the origin remote doesn't point to a GitHub repository."))
}
headProject, err := localRepo.CurrentProject()
utils.Check(err)
gh := github.NewWithoutProject()
gh.Project = baseProject
var base, head string
if flagPullRequestBase != "" {
base = flagPullRequestBase
}
if flagPullRequestHead != "" {
head = flagPullRequestHead
}
if args.ParamsSize() == 1 {
arg := args.RemoveParam(0)
u, e := github.ParseURL(arg)
r := regexp.MustCompile(`^issues\/(\d+)`)
p := u.ProjectPath()
if e == nil && r.MatchString(p) {
flagPullRequestIssue = r.FindStringSubmatch(p)[1]
}
}
if base == "" {
masterBranch, err := localRepo.MasterBranch()
utils.Check(err)
base = masterBranch.ShortName()
}
trackedBranch, tberr := currentBranch.Upstream()
if head == "" {
if err == nil {
if trackedBranch.IsRemote() {
if reflect.DeepEqual(baseProject, headProject) && base == trackedBranch.ShortName() {
e := fmt.Errorf(`Aborted: head branch is the same as base ("%s")`, base)
e = fmt.Errorf("%s\n(use `-h <branch>` to specify an explicit pull request head)", e)
utils.Check(e)
}
} else {
// the current branch tracking another branch
// pretend there's no upstream at all
tberr = fmt.Errorf("No upstream found for current branch")
}
}
if tberr == nil {
head = trackedBranch.ShortName()
} else {
head = currentBranch.ShortName()
}
}
// when no tracking, assume remote branch is published under active user's fork
if tberr != nil && gh.Config.User != headProject.Owner {
headProject = github.NewProjectFromNameAndOwner(headProject.Name, "")
}
var title, body string
if flagPullRequestMessage != "" {
title, body = readMsg(flagPullRequestMessage)
}
fullBase := fmt.Sprintf("%s:%s", baseProject.Owner, base)
fullHead := fmt.Sprintf("%s:%s", headProject.Owner, head)
if title == "" && flagPullRequestIssue == "" {
t, b, err := writePullRequestTitleAndBody(repo)
t, b, err := writePullRequestTitleAndBody(base, head, fullBase, fullHead)
utils.Check(err)
title = t
body = b
@ -75,17 +153,17 @@ func pullRequest(cmd *Command, args *Args) {
var pullRequestURL string
if args.Noop {
args.Before(fmt.Sprintf("Would request a pull request to %s from %s", repo.FullBase(), repo.FullHead()), "")
args.Before(fmt.Sprintf("Would request a pull request to %s from %s", fullBase, fullHead), "")
pullRequestURL = "PULL_REQUEST_URL"
} else {
if title != "" {
pr, err := gh.CreatePullRequest(repo.Base, repo.Head, title, body)
pr, err := gh.CreatePullRequest(base, fullHead, title, body)
utils.Check(err)
pullRequestURL = pr.HTMLURL
}
if flagPullRequestIssue != "" {
pr, err := gh.CreatePullRequestForIssue(repo.Base, repo.Head, flagPullRequestIssue)
pr, err := gh.CreatePullRequestForIssue(base, fullHead, flagPullRequestIssue)
utils.Check(err)
pullRequestURL = pr.HTMLURL
}
@ -94,13 +172,14 @@ func pullRequest(cmd *Command, args *Args) {
args.Replace("echo", "", pullRequestURL)
}
func writePullRequestTitleAndBody(repo *github.Repo) (title, body string, err error) {
func writePullRequestTitleAndBody(base, head, fullBase, fullHead string) (title, body string, err error) {
messageFile, err := git.PullReqMsgFile()
if err != nil {
return
}
defer os.Remove(messageFile)
err = writePullRequestChanges(repo, messageFile)
err = writePullRequestChanges(base, head, fullBase, fullHead, messageFile)
if err != nil {
return
}
@ -112,6 +191,7 @@ func writePullRequestTitleAndBody(repo *github.Repo) (title, body string, err er
err = editTitleAndBody(editor, messageFile)
if err != nil {
err = fmt.Errorf("error using text editor for pull request message")
return
}
@ -120,26 +200,21 @@ func writePullRequestTitleAndBody(repo *github.Repo) (title, body string, err er
return
}
err = os.Remove(messageFile)
return
}
func writePullRequestChanges(repo *github.Repo, messageFile string) error {
commits, err := git.RefList(repo.Base, repo.Head)
if err != nil {
return err
}
func writePullRequestChanges(base, head, fullBase, fullHead string, messageFile string) error {
commits, _ := git.RefList(base, head)
var defaultMsg, commitSummary string
if len(commits) == 1 {
defaultMsg, err = git.Show(commits[0])
defaultMsg, err := git.Show(commits[0])
if err != nil {
return err
}
defaultMsg = fmt.Sprintf("%s\n", defaultMsg)
} else if len(commits) > 1 {
commitLogs, err := git.Log(repo.Base, repo.Head)
commitLogs, err := git.Log(base, head)
if err != nil {
return err
}
@ -166,7 +241,7 @@ func writePullRequestChanges(repo *github.Repo, messageFile string) error {
# Write a message for this pull request. The first block
# of the text is the title and the rest is description.%s
`
message = fmt.Sprintf(message, defaultMsg, repo.FullBase(), repo.FullHead(), commitSummary)
message = fmt.Sprintf(message, defaultMsg, fullBase, fullHead, commitSummary)
return ioutil.WriteFile(messageFile, []byte(message), 0644)
}
@ -237,3 +312,13 @@ func readLine(r *bufio.Reader) (string, error) {
return string(ln), err
}
func readMsg(msg string) (title, body string) {
split := strings.SplitN(msg, "\n\n", 2)
title = strings.TrimSpace(split[0])
if len(split) > 1 {
body = strings.TrimSpace(split[1])
}
return
}

Просмотреть файл

@ -1,7 +1,7 @@
package commands
import (
"github.com/jingweno/gh/git"
"github.com/jingweno/gh/github"
"github.com/jingweno/gh/utils"
"strings"
)
@ -40,7 +40,8 @@ func transformPushArgs(args *Args) {
args.ReplaceParam(0, remotes[0])
if len(refs) == 0 {
head, err := git.Head()
localRepo := github.LocalRepo()
head, err := localRepo.CurrentBranch()
utils.Check(err)
refs = []string{head.ShortName()}
args.AppendParams(refs...)

Просмотреть файл

@ -1,14 +0,0 @@
package git
import (
"regexp"
)
type Branch struct {
Name string
}
func (b *Branch) ShortName() string {
reg := regexp.MustCompile("^refs/(remotes/)?.+?/")
return reg.ReplaceAllString(b.Name, "")
}

Просмотреть файл

@ -1,11 +0,0 @@
package git
import (
"github.com/bmizerany/assert"
"testing"
)
func TestShortName(t *testing.T) {
b := Branch{"refs/heads/master"}
assert.Equal(t, "master", b.ShortName())
}

Просмотреть файл

@ -50,13 +50,22 @@ func Editor() (string, error) {
return output[0], nil
}
func Head() (*Branch, error) {
func Head() (string, error) {
output, err := execGitCmd("symbolic-ref", "-q", "HEAD")
if err != nil {
return nil, errors.New("Can't load git HEAD")
return "", errors.New("Can't load git HEAD")
}
return &Branch{output[0]}, nil
return output[0], nil
}
func SymbolicFullName(name string) (string, error) {
output, err := execGitCmd("rev-parse", "--symbolic-full-name", name)
if err != nil {
return "", errors.New("Unknown revision or path not in the working tree: " + name)
}
return output[0], nil
}
func Ref(ref string) (string, error) {
@ -72,7 +81,7 @@ func RefList(a, b string) ([]string, error) {
ref := fmt.Sprintf("%s...%s", a, b)
output, err := execGitCmd("rev-list", "--cherry-pick", "--right-only", "--no-merges", ref)
if err != nil {
return nil, errors.New("Can't load rev-list for %s" + ref)
return []string{}, fmt.Errorf("Can't load rev-list for %s", ref)
}
return output, nil

Просмотреть файл

@ -26,7 +26,7 @@ func TestGitEditor(t *testing.T) {
func TestGitRemote(t *testing.T) {
gitRemote, _ := OriginRemote()
assert.Equal(t, "origin", gitRemote.Name)
assert.T(t, strings.Contains(gitRemote.URL, "gh"))
assert.T(t, strings.Contains(gitRemote.URL.String(), "gh"))
}
func TestGitHead(t *testing.T) {

Просмотреть файл

@ -2,37 +2,46 @@ package git
import (
"errors"
"net/url"
"regexp"
)
type GitRemote struct {
type Remote struct {
Name string
URL string
URL *url.URL
}
func Remotes() ([]*GitRemote, error) {
r := regexp.MustCompile("(.+)\t(.+github.com.+) \\(push\\)")
func Remotes() (remotes []Remote, err error) {
re := regexp.MustCompile(`(.+)\s+(.+)\s+\((push|fetch)\)`)
output, err := execGitCmd("remote", "-v")
if err != nil {
return nil, errors.New("Can't load git remote")
err = errors.New("Can't load git remote")
return
}
remotes := make([]*GitRemote, 0)
remotesMap := make(map[string]string)
for _, o := range output {
if r.MatchString(o) {
match := r.FindStringSubmatch(o)
remotes = append(remotes, &GitRemote{Name: match[1], URL: match[2]})
if re.MatchString(o) {
match := re.FindStringSubmatch(o)
remotesMap[match[1]] = match[2]
}
}
if len(remotes) == 0 {
return nil, errors.New("Can't find git remote (push)")
for k, v := range remotesMap {
url, e := ParseURL(v)
if e != nil {
err = e
return
}
remotes = append(remotes, Remote{Name: k, URL: url})
}
return remotes, nil
return
}
func OriginRemote() (*GitRemote, error) {
func OriginRemote() (*Remote, error) {
remotes, err := Remotes()
if err != nil {
return nil, err
@ -40,9 +49,9 @@ func OriginRemote() (*GitRemote, error) {
for _, r := range remotes {
if r.Name == "origin" {
return r, nil
return &r, nil
}
}
return nil, errors.New("Can't find git remote origin (push)")
return nil, errors.New("Can't find git remote origin")
}

21
git/url.go Normal file
Просмотреть файл

@ -0,0 +1,21 @@
package git
import (
"fmt"
"net/url"
"regexp"
)
func ParseURL(rawurl string) (u *url.URL, err error) {
sshGitRegexp := regexp.MustCompile(`(\w+)@([\w.]+):([\w\/]+)(\.git)?`)
if sshGitRegexp.MatchString(rawurl) {
match := sshGitRegexp.FindStringSubmatch(rawurl)
user := match[1]
host := match[2]
path := match[3]
ext := match[4]
rawurl = fmt.Sprintf("ssh://%s@%s/%s%s", user, host, path, ext)
}
return url.Parse(rawurl)
}

27
git/url_test.go Normal file
Просмотреть файл

@ -0,0 +1,27 @@
package git
import (
"github.com/bmizerany/assert"
"testing"
)
func TestURL_ParseURL(t *testing.T) {
u, err := ParseURL("https://github.com/jingweno/gh.git")
assert.Equal(t, nil, err)
assert.Equal(t, "github.com", u.Host)
assert.Equal(t, "https", u.Scheme)
assert.Equal(t, "/jingweno/gh.git", u.Path)
u, err = ParseURL("git://github.com/jingweno/gh.git")
assert.Equal(t, nil, err)
assert.Equal(t, "github.com", u.Host)
assert.Equal(t, "git", u.Scheme)
assert.Equal(t, "/jingweno/gh.git", u.Path)
u, err = ParseURL("git@github.com:jingweno/gh.git")
assert.Equal(t, nil, err)
assert.Equal(t, "github.com", u.Host)
assert.Equal(t, "ssh", u.Scheme)
assert.Equal(t, "git", u.User.Username())
assert.Equal(t, "/jingweno/gh.git", u.Path)
}

39
github/branch.go Normal file
Просмотреть файл

@ -0,0 +1,39 @@
package github
import (
"fmt"
"github.com/jingweno/gh/git"
"regexp"
"strings"
)
type Branch string
func (b Branch) ShortName() string {
reg := regexp.MustCompile("^refs/(remotes/)?.+?/")
return reg.ReplaceAllString(string(b), "")
}
func (b Branch) Upstream() (u Branch, err error) {
name, err := git.SymbolicFullName(fmt.Sprintf("%s@{upstream}", b.ShortName()))
if err != nil {
return
}
u = Branch(name)
return
}
func (b Branch) RemoteName() string {
reg := regexp.MustCompile("^refs/remotes/([^/]+)")
if reg.MatchString(string(b)) {
return reg.FindStringSubmatch(string(b))[1]
}
return ""
}
func (b Branch) IsRemote() bool {
return strings.HasPrefix(string(b), "refs/remotes")
}

21
github/branch_test.go Normal file
Просмотреть файл

@ -0,0 +1,21 @@
package github
import (
"github.com/bmizerany/assert"
"testing"
)
func TestBranch_ShortName(t *testing.T) {
b := Branch("refs/heads/master")
assert.Equal(t, "master", b.ShortName())
}
func TestBranch_RemoveName(t *testing.T) {
b := Branch("refs/remotes/origin/master")
assert.Equal(t, "origin", b.RemoteName())
}
func TestBranch_IsRemote(t *testing.T) {
b := Branch("refs/remotes/origin/master")
assert.T(t, b.IsRemote())
}

Просмотреть файл

@ -95,7 +95,11 @@ func CurrentConfig() *Config {
}
func loadConfig() (Config, error) {
return loadFrom(DefaultConfigFile)
configFile := os.Getenv("GH_CONFIG")
if configFile == "" {
configFile = DefaultConfigFile
}
return loadFrom(configFile)
}
func loadFrom(filename string) (Config, error) {

Просмотреть файл

@ -3,6 +3,7 @@ package github
import (
"fmt"
"github.com/jingweno/go-octokit/octokit"
"os"
)
const (
@ -62,7 +63,7 @@ func (gh *GitHub) CreatePullRequestForIssue(base, head, issue string) (pr *octok
return
}
func (gh *GitHub) Repository(project Project) (repo *octokit.Repository, err error) {
func (gh *GitHub) Repository(project *Project) (repo *octokit.Repository, err error) {
url, err := octokit.RepositoryURL.Expand(octokit.M{"owner": project.Owner, "repo": project.Name})
if err != nil {
return
@ -78,13 +79,13 @@ func (gh *GitHub) Repository(project Project) (repo *octokit.Repository, err err
}
// TODO: detach GitHub from Project
func (gh *GitHub) IsRepositoryExist(project Project) bool {
func (gh *GitHub) IsRepositoryExist(project *Project) bool {
repo, err := gh.Repository(project)
return err == nil && repo != nil
}
func (gh *GitHub) CreateRepository(project Project, description, homepage string, isPrivate bool) (repo *octokit.Repository, err error) {
func (gh *GitHub) CreateRepository(project *Project, description, homepage string, isPrivate bool) (repo *octokit.Repository, err error) {
var repoURL octokit.Hyperlink
if project.Owner != gh.Config.FetchUser() {
repoURL = octokit.OrgRepositoriesURL
@ -145,7 +146,7 @@ func (gh *GitHub) CIStatus(sha string) (status *octokit.Status, err error) {
func (gh *GitHub) ForkRepository(name, owner string, noRemote bool) (repo *octokit.Repository, err error) {
config := gh.Config
project := Project{Name: name, Owner: config.User}
project := &Project{Name: name, Owner: config.User}
r, err := gh.Repository(project)
if err == nil && r != nil {
err = fmt.Errorf("Error creating fork: %s exists on %s", r.FullName, GitHubHost)
@ -233,12 +234,19 @@ func findOrCreateToken(user, password, twoFactorCode string) (token string, err
return
}
func (gh *GitHub) octokit() *octokit.Client {
func (gh *GitHub) octokit() (c *octokit.Client) {
config := gh.Config
config.FetchCredentials()
tokenAuth := octokit.TokenAuth{AccessToken: config.Token}
return octokit.NewClient(tokenAuth)
host := os.Getenv("GH_API_HOST")
if host == "" {
c = octokit.NewClient(tokenAuth)
} else {
c = octokit.NewClientWith(host, nil, tokenAuth)
}
return
}
func New() *GitHub {

33
github/hosts.go Normal file
Просмотреть файл

@ -0,0 +1,33 @@
package github
import (
"fmt"
"os"
)
type Hosts []string
func (h Hosts) Include(host string) bool {
for _, hh := range h {
if hh == host {
return true
}
}
return false
}
func KnownHosts() (hosts Hosts) {
host := os.Getenv("GITHUB_HOST")
var mainHost string
if host != "" {
mainHost = host
} else {
mainHost = GitHubHost
}
hosts = append(hosts, mainHost)
hosts = append(hosts, fmt.Sprintf("ssh.%s", mainHost))
return
}

Просмотреть файл

@ -58,8 +58,10 @@ func (p *Project) LocalRepoWith(base, head string) *Repo {
}
if head == "" {
headBranch, err := git.Head()
utils.Check(err)
head = headBranch.ShortName()
if err != nil {
utils.Check(fmt.Errorf("Aborted: not currently on any branch."))
}
head = Branch(headBranch).ShortName()
}
return &Repo{base, head, p}
@ -73,13 +75,13 @@ func CurrentProject() *Project {
remote, err := git.OriginRemote()
utils.Check(err)
owner, name := parseOwnerAndName(remote.URL)
owner, name := parseOwnerAndName(remote.URL.String())
return &Project{name, owner}
}
func NewProjectFromURL(url *url.URL) (*Project, error) {
if url.Host != GitHubHost || url.Scheme != "https" {
if !KnownHosts().Include(url.Host) {
return nil, fmt.Errorf("Invalid GitHub URL: %s", url)
}
@ -88,10 +90,12 @@ func NewProjectFromURL(url *url.URL) (*Project, error) {
return nil, fmt.Errorf("Invalid GitHub URL: %s", url)
}
return &Project{Name: parts[2], Owner: parts[1]}, nil
name := strings.TrimRight(parts[2], ".git")
return &Project{Name: name, Owner: parts[1]}, nil
}
func NewProjectFromNameAndOwner(name, owner string) Project {
func NewProjectFromNameAndOwner(name, owner string) *Project {
if strings.Contains(owner, "/") {
result := strings.SplitN(owner, "/", 2)
owner = result[0]
@ -110,7 +114,7 @@ func NewProjectFromNameAndOwner(name, owner string) Project {
name, _ = utils.DirName()
}
return Project{Name: name, Owner: owner}
return &Project{Name: name, Owner: owner}
}
func parseOwnerAndName(remote string) (owner string, name string) {

Просмотреть файл

@ -2,6 +2,7 @@ package github
import (
"github.com/bmizerany/assert"
"net/url"
"os"
"path/filepath"
"testing"
@ -89,3 +90,26 @@ func TestMustMatchGitHubURL(t *testing.T) {
assert.Equal(t, "jingweno", url[1])
assert.Equal(t, "gh", url[2])
}
func TestNewProjectFromURL(t *testing.T) {
u, _ := url.Parse("ssh://git@github.com/jingweno/gh.git")
p, err := NewProjectFromURL(u)
assert.Equal(t, nil, err)
assert.Equal(t, "gh", p.Name)
assert.Equal(t, "jingweno", p.Owner)
u, _ = url.Parse("git://github.com/jingweno/gh.git")
p, err = NewProjectFromURL(u)
assert.Equal(t, nil, err)
assert.Equal(t, "gh", p.Name)
assert.Equal(t, "jingweno", p.Owner)
u, _ = url.Parse("https://github.com/jingweno/gh")
p, err = NewProjectFromURL(u)
assert.Equal(t, nil, err)
assert.Equal(t, "gh", p.Name)
assert.Equal(t, "jingweno", p.Owner)
}

Просмотреть файл

@ -1,9 +1,102 @@
package github
import (
"fmt"
"github.com/jingweno/gh/git"
"strings"
)
func LocalRepo() *GitHubRepo {
return &GitHubRepo{}
}
type GitHubRepo struct {
remotes []git.Remote
}
func (r *GitHubRepo) remotesByName(name string) (*git.Remote, error) {
if r.remotes == nil {
remotes, err := git.Remotes()
if err != nil {
return nil, err
}
r.remotes = remotes
}
for _, remote := range r.remotes {
if remote.Name == name {
return &remote, nil
}
}
return nil, fmt.Errorf("No git remote with name %s", name)
}
func (r *GitHubRepo) CurrentBranch() (branch Branch, err error) {
head, err := git.Head()
if err != nil {
return
}
branch = Branch(head)
return
}
func (r *GitHubRepo) MasterBranch() (branch Branch, err error) {
origin, err := r.remotesByName("origin")
if err != nil {
return
}
name, err := git.SymbolicFullName(origin.Name)
if err != nil {
return
}
branch = Branch(name)
return
}
func (r *GitHubRepo) MainProject() (project *Project, err error) {
origin, err := r.remotesByName("origin")
if err != nil {
return
}
return NewProjectFromURL(origin.URL)
}
func (r *GitHubRepo) CurrentProject() (project *Project, err error) {
project, err = r.UpstreamProject()
if err != nil {
project, err = r.MainProject()
}
return
}
func (r *GitHubRepo) UpstreamProject() (project *Project, err error) {
currentBranch, err := r.CurrentBranch()
if err != nil {
return
}
upstream, err := currentBranch.Upstream()
if err != nil {
return
}
remote, err := r.remotesByName(upstream.RemoteName())
if err != nil {
return
}
project, err = NewProjectFromURL(remote.URL)
return
}
type Repo struct {
Base string
Head string

Просмотреть файл

@ -26,12 +26,4 @@ func TestParseURL(t *testing.T) {
assert.Equal(t, "jingweno", url.Owner)
assert.Equal(t, "gh", url.Name)
assert.Equal(t, "", url.ProjectPath())
url, err =
ParseURL("http://github.com/jingweno/gh/")
assert.NotEqual(t, nil, err)
url, err =
ParseURL("http://github.com/jingweno/")
assert.NotEqual(t, nil, err)
}