Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
github
hub
提交
8af17bce
H
hub
项目概览
github
/
hub
8 个月 前同步成功
通知
3
Star
22523
Fork
2406
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
H
hub
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
8af17bce
编写于
8月 02, 2020
作者:
M
Mislav Marohnić
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add functionality and tests to `pr merge`
上级
393e75af
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
340 addition
and
26 deletion
+340
-26
commands/merge.go
commands/merge.go
+3
-1
commands/pr.go
commands/pr.go
+80
-14
features/pr-merge.feature
features/pr-merge.feature
+215
-0
github/client.go
github/client.go
+30
-3
github/message_builder.go
github/message_builder.go
+12
-8
未找到文件。
commands/merge.go
浏览文件 @
8af17bce
...
...
@@ -19,6 +19,8 @@ change the state of the pull request. However, the pull request will get
auto-closed and marked as "merged" as soon as the newly created merge commit is
pushed to the default branch of the remote repository.
To merge a pull request remotely, use ''hub pr merge''.
## Examples:
$ hub merge https://github.com/jingweno/gh/pull/73
> git fetch origin refs/pull/73/head
...
...
@@ -26,7 +28,7 @@ pushed to the default branch of the remote repository.
## See also:
hub-checkout(1), hub(1), git-merge(1)
hub-
pr(1), hub-
checkout(1), hub(1), git-merge(1)
`
,
}
...
...
commands/pr.go
浏览文件 @
8af17bce
...
...
@@ -19,7 +19,7 @@ pr list [-s <STATE>] [-h <HEAD>] [-b <BASE>] [-o <SORT_KEY> [-^]] [-f <FORMAT>]
pr checkout <PR-NUMBER> [<BRANCH>]
pr show [-uc] [-f <FORMAT>] [-h <HEAD>]
pr show [-uc] [-f <FORMAT>] <PR-NUMBER>
pr merge
<PR-NUMBER>
pr merge
[-d] [--squash | --rebase] <PR-NUMBER> [-m <MESSAGE> | -F <FILE>] [--head-sha <COMMIT-SHA>]
`
,
Long
:
`Manage GitHub Pull Requests for the current repository.
...
...
@@ -40,7 +40,9 @@ pr merge <PR-NUMBER>
pull request instead of opening it.
* _merge_:
Merge a pull request in the current project.
Merge a pull request in the current repository remotely. Select an
alternate merge method with ''--squash'' or ''--rebase''. Change the
commit subject and body with ''--message'' or ''--file''.
## Options:
...
...
@@ -150,6 +152,29 @@ pr merge <PR-NUMBER>
-c, --copy
Put the pull request URL to clipboard instead of opening it.
-m, --message <MESSAGE>
The text up to the first blank line in <MESSAGE> is treated as the commit
subject for the merge commit, and the rest is used as commit body.
When multiple ''--message'' are passed, their values are concatenated with a
blank line in-between.
-F, --file <FILE>
Read the subject and body for the merge commit from <FILE>. Pass "-" to read
from standard input instead. See ''--message'' for the formatting rules.
--head-sha <COMMIT-SHA>
Ensure that the head of the pull request matches the commit SHA when merging.
--squash
Squash commits instead of creating a merge commit when merging a pull request.
--rebase
Rebase commits on top of the base branch when merging a pull request.
-d, --delete-branch
Delete the head branch after successfully merging a pull request.
## See also:
hub-issue(1), hub-pull-request(1), hub(1)
...
...
@@ -177,12 +202,20 @@ hub-issue(1), hub-pull-request(1), hub(1)
-c, --copy
-f, --format FORMAT
--color
`
,
`
,
}
cmdMergePr
=
&
Command
{
Key
:
"merge"
,
Run
:
mergePr
,
KnownFlags
:
`
-m, --message MESSAGE
-F, --file FILE
--head-sha COMMIT
--squash
--rebase
-d, --delete-branch
`
,
}
)
...
...
@@ -424,33 +457,66 @@ func deducePushTarget(branch *github.Branch, owner string) (*github.Project, err
}
func
mergePr
(
command
*
Command
,
args
*
Args
)
{
words
:=
args
.
Words
()
if
len
(
words
)
==
0
{
utils
.
Check
(
fmt
.
Errorf
(
"Error: No pull request number given"
))
}
prNumber
,
err
:=
strconv
.
Atoi
(
words
[
0
])
utils
.
Check
(
err
)
params
:=
map
[
string
]
interface
{}{
"merge_method"
:
"merge"
,
}
if
args
.
Flag
.
Bool
(
"--squash"
)
{
params
[
"merge_method"
]
=
"squash"
}
if
args
.
Flag
.
Bool
(
"--rebase"
)
{
params
[
"merge_method"
]
=
"rebase"
}
msgs
:=
args
.
Flag
.
AllValues
(
"--message"
)
if
len
(
msgs
)
>
0
{
params
[
"commit_title"
]
=
msgs
[
0
]
params
[
"commit_message"
]
=
strings
.
Join
(
msgs
[
1
:
],
"
\n\n
"
)
}
else
if
args
.
Flag
.
HasReceived
(
"--file"
)
{
content
,
err
:=
msgFromFile
(
args
.
Flag
.
Value
(
"--file"
))
utils
.
Check
(
err
)
params
[
"commit_title"
],
params
[
"commit_message"
]
=
github
.
SplitTitleBody
(
content
)
}
if
headSHA
:=
args
.
Flag
.
Value
(
"--head-sha"
);
headSHA
!=
""
{
params
[
"sha"
]
=
args
.
Flag
.
Value
(
"--head-sha"
)
}
localRepo
,
err
:=
github
.
LocalRepo
()
utils
.
Check
(
err
)
project
,
err
:=
localRepo
.
MainProject
()
utils
.
Check
(
err
)
gh
:=
github
.
NewClient
(
project
.
Host
)
args
.
NoForward
()
if
args
.
Noop
{
ui
.
Printf
(
"Would merge pull request
for %s
\n
"
,
project
)
ui
.
Printf
(
"Would merge pull request
#%d for %s
\n
"
,
prNumber
,
project
)
return
}
words
:=
args
.
Words
()
gh
:=
github
.
NewClient
(
project
.
Host
)
_
,
err
=
gh
.
MergePullRequest
(
project
,
prNumber
,
params
)
utils
.
Check
(
err
)
if
len
(
words
)
==
0
{
utils
.
Check
(
fmt
.
Errorf
(
"Error: No pull request number given"
))
if
!
args
.
Flag
.
Bool
(
"--delete-branch"
)
{
return
}
prNumberString
:=
words
[
0
]
prNumber
,
err
:=
strconv
.
Atoi
(
prNumberString
)
pr
,
err
:=
gh
.
PullRequest
(
project
,
strconv
.
Itoa
(
prNumber
))
utils
.
Check
(
err
)
if
!
pr
.
IsSameRepo
()
{
return
}
err
=
gh
.
MergePullRequest
(
project
,
prNumber
,
map
[
string
]
interface
{}{
"merge_method"
:
"merge"
,
})
branchName
:=
pr
.
Head
.
Ref
err
=
gh
.
DeleteBranch
(
project
,
branchName
)
utils
.
Check
(
err
)
}
...
...
features/pr-merge.feature
0 → 100644
浏览文件 @
8af17bce
Feature
:
hub pr merge
Background
:
Given I am in "git
:
//github.com/friederbluemle/hub.git"
git
repo
And
I am
"friederbluemle"
on github.com with OAuth token
"OTOKEN"
Scenario
:
Default merge
Given the GitHub API server
:
"""
put('/repos/friederbluemle/hub/pulls/12/merge'){
assert :merge_method => "merge",
:commit_title => :no,
:commit_message => :no,
:sha => :no
json :merged => true,
:sha => "MERGESHA",
:message => "All done!"
}
"""
When
I successfully run `hub pr merge 12`
Then
the output should contain exactly
""
Scenario
:
Squash merge
Given the GitHub API server
:
"""
put('/repos/friederbluemle/hub/pulls/12/merge'){
assert :merge_method => "squash",
:commit_title => :no,
:commit_message => :no,
:sha => :no
json :merged => true,
:sha => "MERGESHA",
:message => "All done!"
}
"""
When
I successfully run `hub pr merge --squash 12`
Then
the output should contain exactly
""
Scenario
:
Merge with rebase
Given the GitHub API server
:
"""
put('/repos/friederbluemle/hub/pulls/12/merge'){
assert :merge_method => "rebase",
:commit_title => :no,
:commit_message => :no,
:sha => :no
json :merged => true,
:sha => "MERGESHA",
:message => "All done!"
}
"""
When
I successfully run `hub pr merge --rebase 12`
Then
the output should contain exactly
""
Scenario
:
Merge with title
Given the GitHub API server
:
"""
put('/repos/friederbluemle/hub/pulls/12/merge'){
assert :commit_title => "mytitle",
:commit_message => ""
json :merged => true,
:sha => "MERGESHA",
:message => "All done!"
}
"""
When
I successfully run `hub pr merge 12 -m mytitle`
Then
the output should contain exactly
""
Scenario
:
Merge with title and body
Given the GitHub API server
:
"""
put('/repos/friederbluemle/hub/pulls/12/merge'){
assert :commit_title => "mytitle",
:commit_message => "msg1\n\nmsg2"
json :merged => true,
:sha => "MERGESHA",
:message => "All done!"
}
"""
When
I successfully run `hub pr merge 12 -m mytitle -m msg1 -m msg2`
Then
the output should contain exactly
""
Scenario
:
Merge with title and body from file
Given a file named "msg.txt" with
:
"""
mytitle
msg1
msg2
"""
Given the GitHub API server
:
"""
put('/repos/friederbluemle/hub/pulls/12/merge'){
assert :commit_title => "mytitle",
:commit_message => "msg1\n\nmsg2"
json :merged => true,
:sha => "MERGESHA",
:message => "All done!"
}
"""
When
I successfully run `hub pr merge 12 -F msg.txt`
Then
the output should contain exactly
""
Scenario
:
Merge with head SHA
Given the GitHub API server
:
"""
put('/repos/friederbluemle/hub/pulls/12/merge'){
assert :sha => "MYSHA"
json :merged => true,
:sha => "MERGESHA",
:message => "All done!"
}
"""
When
I successfully run `hub pr merge 12 --head-sha MYSHA`
Then
the output should contain exactly
""
Scenario
:
Delete branch
Given the GitHub API server
:
"""
put('/repos/friederbluemle/hub/pulls/12/merge'){
json :merged => true,
:sha => "MERGESHA",
:message => "All done!"
}
get('/repos/friederbluemle/hub/pulls/12'){
json \
:number => 12,
:state => "merged",
:base => {
:ref => "main",
:label => "friederbluemle:main",
:repo => { :owner => { :login => "friederbluemle" } }
},
:head => {
:ref => "patch-1",
:label => "friederbluemle:patch-1",
:repo => { :owner => { :login => "friederbluemle" } }
}
}
delete('/repos/friederbluemle/hub/git/refs/heads/patch-1'){
status 204
}
"""
When
I successfully run `hub pr merge -d 12`
Then
the output should contain exactly
""
Scenario
:
Delete already deleted branch
Given the GitHub API server
:
"""
put('/repos/friederbluemle/hub/pulls/12/merge'){
json :merged => true,
:sha => "MERGESHA",
:message => "All done!"
}
get('/repos/friederbluemle/hub/pulls/12'){
json \
:number => 12,
:state => "merged",
:base => {
:ref => "main",
:label => "friederbluemle:main",
:repo => { :owner => { :login => "friederbluemle" } }
},
:head => {
:ref => "patch-1",
:label => "friederbluemle:patch-1",
:repo => { :owner => { :login => "friederbluemle" } }
}
}
delete('/repos/friederbluemle/hub/git/refs/heads/patch-1'){
status 422
json :message => "Invalid branch name"
}
"""
When
I successfully run `hub pr merge -d 12`
Then
the output should contain exactly
""
Scenario
:
Delete branch on cross-repo PR
Given the GitHub API server
:
"""
put('/repos/friederbluemle/hub/pulls/12/merge'){
json :merged => true,
:sha => "MERGESHA",
:message => "All done!"
}
get('/repos/friederbluemle/hub/pulls/12'){
json \
:number => 12,
:state => "merged",
:base => {
:ref => "main",
:label => "friederbluemle:main",
:repo => { :owner => { :login => "friederbluemle" } }
},
:head => {
:ref => "patch-1",
:label => "monalisa:patch-1",
:repo => { :owner => { :login => "monalisa" } }
}
}
"""
When
I successfully run `hub pr merge -d 12`
Then
the output should contain exactly
""
github/client.go
浏览文件 @
8af17bce
...
...
@@ -146,8 +146,14 @@ func (client *Client) CreatePullRequest(project *Project, params map[string]inte
return
}
func
(
client
*
Client
)
MergePullRequest
(
project
*
Project
,
prNumber
int
,
params
map
[
string
]
interface
{})
(
err
error
)
{
api
,
err
:=
client
.
simpleApi
()
type
PullRequestMergeResponse
struct
{
SHA
string
Merged
bool
Message
string
}
func
(
client
*
Client
)
MergePullRequest
(
project
*
Project
,
prNumber
int
,
params
map
[
string
]
interface
{})
(
mr
PullRequestMergeResponse
,
err
error
)
{
api
,
err
:=
client
.
simpleAPI
()
if
err
!=
nil
{
return
}
...
...
@@ -156,8 +162,29 @@ func (client *Client) MergePullRequest(project *Project, prNumber int, params ma
if
err
=
checkStatus
(
200
,
"merging pull request"
,
res
,
err
);
err
!=
nil
{
return
}
defer
res
.
Body
.
Close
()
err
=
res
.
Unmarshal
(
&
mr
)
return
}
func
(
client
*
Client
)
DeleteBranch
(
project
*
Project
,
branchName
string
)
(
err
error
)
{
api
,
err
:=
client
.
simpleAPI
()
if
err
!=
nil
{
return
}
res
,
err
:=
api
.
Delete
(
fmt
.
Sprintf
(
"repos/%s/%s/git/refs/heads/%s"
,
project
.
Owner
,
project
.
Name
,
branchName
))
if
err
==
nil
{
defer
res
.
Body
.
Close
()
if
res
.
StatusCode
==
422
{
return
}
}
if
err
=
checkStatus
(
204
,
"deleting branch"
,
res
,
err
);
err
!=
nil
{
return
}
res
.
Body
.
Close
()
return
}
...
...
github/message_builder.go
浏览文件 @
8af17bce
...
...
@@ -38,14 +38,7 @@ func (b *MessageBuilder) Extract() (title, body string, err error) {
content
=
nl
.
ReplaceAllString
(
content
,
"
\n
"
)
}
parts
:=
strings
.
SplitN
(
content
,
"
\n\n
"
,
2
)
if
len
(
parts
)
>=
1
{
title
=
strings
.
TrimSpace
(
strings
.
Replace
(
parts
[
0
],
"
\n
"
,
" "
,
-
1
))
}
if
len
(
parts
)
>=
2
{
body
=
strings
.
TrimSpace
(
parts
[
1
])
}
title
,
body
=
SplitTitleBody
(
content
)
if
title
==
""
{
defer
b
.
Cleanup
()
}
...
...
@@ -58,3 +51,14 @@ func (b *MessageBuilder) Cleanup() {
b
.
editor
.
DeleteFile
()
}
}
func
SplitTitleBody
(
content
string
)
(
title
string
,
body
string
)
{
parts
:=
strings
.
SplitN
(
content
,
"
\n\n
"
,
2
)
if
len
(
parts
)
>=
1
{
title
=
strings
.
TrimSpace
(
strings
.
Replace
(
parts
[
0
],
"
\n
"
,
" "
,
-
1
))
}
if
len
(
parts
)
>=
2
{
body
=
strings
.
TrimSpace
(
parts
[
1
])
}
return
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录