未验证 提交 fb5386f0 编写于 作者: M Mislav Marohnić 提交者: GitHub

Merge pull request #2284 from github/compare-upstream

Improve `compare` upstream detection & documentation
......@@ -13,8 +13,8 @@ import (
var cmdCompare = &Command{
Run: compare,
Usage: `
compare [-uc] [<USER>] [[<START>...]<END>]
compare [-uc] [-b <BASE>]
compare [-uc] [<OWNER>] [<BASE>...]<HEAD>
`,
Long: `Open a GitHub compare page in a web browser.
......@@ -28,22 +28,31 @@ compare [-uc] [-b <BASE>]
-b, --base <BASE>
Base branch to compare against in case no explicit arguments were given.
[<START>...]<END>
[<BASE>...]<HEAD>
Branch names, tag names, or commit SHAs specifying the range to compare.
<END> defaults to the current branch name.
If a range with two dots ('A..B') is given, it will be transformed into a
range with three dots.
The <BASE> portion defaults to the default branch of the repository.
The <HEAD> argument defaults to the current branch. If the current branch
is not pushed to a remote, the command will error.
<OWNER>
Optionally specify the owner of the repository for the compare page URL.
## Examples:
$ hub compare
> open https://github.com/OWNER/REPO/compare/BRANCH
$ hub compare refactor
> open https://github.com/USER/REPO/compare/refactor
> open https://github.com/OWNER/REPO/compare/refactor
$ hub compare v1.0..v1.1
> open https://github.com/USER/REPO/compare/v1.0...v1.1
> open https://github.com/OWNER/REPO/compare/v1.0...v1.1
$ hub compare -u jingweno feature
> echo https://github.com/jingweno/REPO/compare/feature
https://github.com/jingweno/REPO/compare/feature
## See also:
......@@ -59,58 +68,60 @@ func compare(command *Command, args *Args) {
localRepo, err := github.LocalRepo()
utils.Check(err)
var (
branch *github.Branch
project *github.Project
r string
)
mainProject, err := localRepo.MainProject()
utils.Check(err)
host, err := github.CurrentConfig().PromptForHost(mainProject.Host)
utils.Check(err)
var r string
flagCompareBase := args.Flag.Value("--base")
if args.IsParamsEmpty() {
branch, project, err = localRepo.RemoteBranchAndProject("", false)
utils.Check(err)
currentBranch, err := localRepo.CurrentBranch()
if err != nil {
utils.Check(command.UsageError(err.Error()))
}
if branch == nil ||
(branch.IsMaster() && flagCompareBase == "") ||
(flagCompareBase == branch.ShortName()) {
utils.Check(command.UsageError(""))
} else {
r = branch.ShortName()
if flagCompareBase != "" {
r = parseCompareRange(flagCompareBase + "..." + r)
var remoteBranch *github.Branch
var remoteProject *github.Project
remoteBranch, remoteProject, err = findPushTarget(currentBranch)
if err != nil {
if remoteProject, err = deducePushTarget(currentBranch, host.User); err == nil {
remoteBranch = currentBranch
} else {
utils.Check(fmt.Errorf("the current branch '%s' doesn't seem pushed to a remote", currentBranch.ShortName()))
}
}
r = remoteBranch.ShortName()
if remoteProject.SameAs(mainProject) {
if flagCompareBase == "" && remoteBranch.IsMaster() {
utils.Check(fmt.Errorf("the branch to compare '%s' is the default branch", remoteBranch.ShortName()))
}
} else {
r = fmt.Sprintf("%s:%s", remoteProject.Owner, r)
}
if flagCompareBase == r {
utils.Check(fmt.Errorf("the branch to compare '%s' is the same as --base", r))
} else if flagCompareBase != "" {
r = fmt.Sprintf("%s...%s", flagCompareBase, r)
}
} else {
if flagCompareBase != "" {
utils.Check(command.UsageError(""))
} else {
r = parseCompareRange(args.RemoveParam(args.ParamsSize() - 1))
project, err = localRepo.CurrentProject()
if args.IsParamsEmpty() {
utils.Check(err)
} else {
projectName := ""
projectHost := ""
if err == nil {
projectName = project.Name
projectHost = project.Host
}
project = github.NewProject(args.RemoveParam(args.ParamsSize()-1), projectName, projectHost)
if project.Name == "" {
utils.Check(fmt.Errorf("error: missing project name (owner: %q)\n", project.Owner))
}
if !args.IsParamsEmpty() {
owner := args.RemoveParam(args.ParamsSize() - 1)
mainProject = github.NewProject(owner, mainProject.Name, mainProject.Host)
}
}
}
if project == nil {
project, err = localRepo.CurrentProject()
utils.Check(err)
}
subpage := utils.ConcatPaths("compare", rangeQueryEscape(r))
url := project.WebURL("", "", subpage)
url := mainProject.WebURL("", "", "compare/"+rangeQueryEscape(r))
args.NoForward()
flagCompareURLOnly := args.Flag.Bool("--url")
......@@ -119,7 +130,7 @@ func compare(command *Command, args *Args) {
}
func parseCompareRange(r string) string {
shaOrTag := fmt.Sprintf("((?:%s:)?\\w(?:[\\w.-]*\\w)?)", OwnerRe)
shaOrTag := fmt.Sprintf("((?:%s:)?\\w(?:[\\w/.-]*\\w)?)", OwnerRe)
shaOrTagRange := fmt.Sprintf("^%s\\.\\.%s$", shaOrTag, shaOrTag)
shaOrTagRangeRegexp := regexp.MustCompile(shaOrTagRange)
return shaOrTagRangeRegexp.ReplaceAllString(r, "$1...$2")
......
......@@ -21,18 +21,14 @@ Feature: hub compare
Scenario: No args, no upstream
When I run `hub compare`
Then the exit status should be 1
And the stderr should contain:
"""
Usage: hub compare [-uc] [<USER>] [[<START>...]<END>]
hub compare [-uc] [-b <BASE>]
"""
And the stderr should contain exactly "the current branch 'master' doesn't seem pushed to a remote"
Scenario: Can't compare default branch to self
Given the default branch for "origin" is "develop"
And I am on the "develop" branch with upstream "origin/develop"
When I run `hub compare`
Then the exit status should be 1
And the stderr should contain "Usage: hub compare"
And the stderr should contain exactly "the branch to compare 'develop' is the default branch"
Scenario: No args, has upstream branch
Given I am on the "feature" branch with upstream "origin/experimental"
......@@ -48,6 +44,20 @@ Feature: hub compare
Then the output should not contain anything
And "open https://github.com/mislav/dotfiles/compare/my%23branch!with.special%2Bchars" should be run
Scenario: Current branch pushed to fork
Given I am "monalisa" on github.com with OAuth token "MONATOKEN"
And the "monalisa" remote has url "git@github.com:monalisa/dotfiles.git"
And I am on the "topic" branch pushed to "monalisa/topic"
When I successfully run `hub compare`
Then "open https://github.com/mislav/dotfiles/compare/monalisa:topic" should be run
Scenario: Current branch with full URL in upstream configuration
Given I am on the "local-topic" branch
When I successfully run `git config branch.local-topic.remote https://github.com/monalisa/dotfiles.git`
When I successfully run `git config branch.local-topic.merge refs/remotes/remote-topic`
When I successfully run `hub compare`
Then "open https://github.com/mislav/dotfiles/compare/monalisa:remote-topic" should be run
Scenario: Compare range
When I successfully run `hub compare 1.0...fix`
Then the output should not contain anything
......@@ -81,7 +91,7 @@ Feature: hub compare
When I run `hub compare -b experimental`
Then "open https://github.com/mislav/dotfiles/compare/experimental...experimental" should not be run
And the exit status should be 1
And the stderr should contain "Usage: hub compare"
And the stderr should contain exactly "the branch to compare 'experimental' is the same as --base\n"
Scenario: Compare base with parameters
Given I am on the "master" branch with upstream "origin/master"
......@@ -105,6 +115,11 @@ Feature: hub compare
Then the output should not contain anything
And "open https://github.com/mislav/dotfiles/compare/henrahmagix:master...2b10927" should be run
Scenario: Compare 2-dots range with slashes in branch names
When I successfully run `hub compare one/foo..two/bar/baz`
Then the output should not contain anything
And "open https://github.com/mislav/dotfiles/compare/one/foo...two/bar/baz" should be run
Scenario: Complex range is unchanged
When I successfully run `hub compare @{a..b}..@{c..d}`
Then the output should not contain anything
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册