Previously, the repository owner+name component of the URL was ignored and only the pull request number was read. Now, the URL dictates which base repository will be used.
542 lines
14 KiB
Go
542 lines
14 KiB
Go
package command
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"io/ioutil"
|
|
"os/exec"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/cli/cli/context"
|
|
"github.com/cli/cli/test"
|
|
"github.com/cli/cli/utils"
|
|
)
|
|
|
|
func TestPRCheckout_sameRepo(t *testing.T) {
|
|
ctx := context.NewBlank()
|
|
ctx.SetBranch("master")
|
|
ctx.SetRemotes(map[string]string{
|
|
"origin": "OWNER/REPO",
|
|
})
|
|
initContext = func() context.Context {
|
|
return ctx
|
|
}
|
|
http := initFakeHTTP()
|
|
http.StubRepoResponse("OWNER", "REPO")
|
|
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": { "pullRequest": {
|
|
"number": 123,
|
|
"headRefName": "feature",
|
|
"headRepositoryOwner": {
|
|
"login": "hubot"
|
|
},
|
|
"headRepository": {
|
|
"name": "REPO",
|
|
"defaultBranchRef": {
|
|
"name": "master"
|
|
}
|
|
},
|
|
"isCrossRepository": false,
|
|
"maintainerCanModify": false
|
|
} } } }
|
|
`))
|
|
|
|
ranCommands := [][]string{}
|
|
restoreCmd := utils.SetPrepareCmd(func(cmd *exec.Cmd) utils.Runnable {
|
|
switch strings.Join(cmd.Args, " ") {
|
|
case "git show-ref --verify --quiet refs/heads/feature":
|
|
return &errorStub{"exit status: 1"}
|
|
default:
|
|
ranCommands = append(ranCommands, cmd.Args)
|
|
return &test.OutputStub{}
|
|
}
|
|
})
|
|
defer restoreCmd()
|
|
|
|
output, err := RunCommand(prCheckoutCmd, `pr checkout 123`)
|
|
eq(t, err, nil)
|
|
eq(t, output.String(), "")
|
|
|
|
eq(t, len(ranCommands), 4)
|
|
eq(t, strings.Join(ranCommands[0], " "), "git fetch origin +refs/heads/feature:refs/remotes/origin/feature")
|
|
eq(t, strings.Join(ranCommands[1], " "), "git checkout -b feature --no-track origin/feature")
|
|
eq(t, strings.Join(ranCommands[2], " "), "git config branch.feature.remote origin")
|
|
eq(t, strings.Join(ranCommands[3], " "), "git config branch.feature.merge refs/heads/feature")
|
|
}
|
|
|
|
func TestPRCheckout_urlArg(t *testing.T) {
|
|
ctx := context.NewBlank()
|
|
ctx.SetBranch("master")
|
|
ctx.SetRemotes(map[string]string{
|
|
"origin": "OWNER/REPO",
|
|
})
|
|
initContext = func() context.Context {
|
|
return ctx
|
|
}
|
|
http := initFakeHTTP()
|
|
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": { "pullRequest": {
|
|
"number": 123,
|
|
"headRefName": "feature",
|
|
"headRepositoryOwner": {
|
|
"login": "hubot"
|
|
},
|
|
"headRepository": {
|
|
"name": "REPO",
|
|
"defaultBranchRef": {
|
|
"name": "master"
|
|
}
|
|
},
|
|
"isCrossRepository": false,
|
|
"maintainerCanModify": false
|
|
} } } }
|
|
`))
|
|
|
|
ranCommands := [][]string{}
|
|
restoreCmd := utils.SetPrepareCmd(func(cmd *exec.Cmd) utils.Runnable {
|
|
switch strings.Join(cmd.Args, " ") {
|
|
case "git show-ref --verify --quiet refs/heads/feature":
|
|
return &errorStub{"exit status: 1"}
|
|
default:
|
|
ranCommands = append(ranCommands, cmd.Args)
|
|
return &test.OutputStub{}
|
|
}
|
|
})
|
|
defer restoreCmd()
|
|
|
|
output, err := RunCommand(prCheckoutCmd, `pr checkout https://github.com/OWNER/REPO/pull/123/files`)
|
|
eq(t, err, nil)
|
|
eq(t, output.String(), "")
|
|
|
|
eq(t, len(ranCommands), 4)
|
|
eq(t, strings.Join(ranCommands[1], " "), "git checkout -b feature --no-track origin/feature")
|
|
}
|
|
|
|
func TestPRCheckout_urlArg_differentBase(t *testing.T) {
|
|
ctx := context.NewBlank()
|
|
ctx.SetBranch("master")
|
|
ctx.SetRemotes(map[string]string{
|
|
"origin": "OWNER/REPO",
|
|
})
|
|
initContext = func() context.Context {
|
|
return ctx
|
|
}
|
|
http := initFakeHTTP()
|
|
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": { "pullRequest": {
|
|
"number": 123,
|
|
"headRefName": "feature",
|
|
"headRepositoryOwner": {
|
|
"login": "hubot"
|
|
},
|
|
"headRepository": {
|
|
"name": "POE",
|
|
"defaultBranchRef": {
|
|
"name": "master"
|
|
}
|
|
},
|
|
"isCrossRepository": false,
|
|
"maintainerCanModify": false
|
|
} } } }
|
|
`))
|
|
|
|
ranCommands := [][]string{}
|
|
restoreCmd := utils.SetPrepareCmd(func(cmd *exec.Cmd) utils.Runnable {
|
|
switch strings.Join(cmd.Args, " ") {
|
|
case "git show-ref --verify --quiet refs/heads/feature":
|
|
return &errorStub{"exit status: 1"}
|
|
default:
|
|
ranCommands = append(ranCommands, cmd.Args)
|
|
return &test.OutputStub{}
|
|
}
|
|
})
|
|
defer restoreCmd()
|
|
|
|
output, err := RunCommand(prCheckoutCmd, `pr checkout https://github.com/OTHER/POE/pull/123/files`)
|
|
eq(t, err, nil)
|
|
eq(t, output.String(), "")
|
|
|
|
bodyBytes, _ := ioutil.ReadAll(http.Requests[0].Body)
|
|
reqBody := struct {
|
|
Variables struct {
|
|
Owner string
|
|
Repo string
|
|
}
|
|
}{}
|
|
json.Unmarshal(bodyBytes, &reqBody)
|
|
|
|
eq(t, reqBody.Variables.Owner, "OTHER")
|
|
eq(t, reqBody.Variables.Repo, "POE")
|
|
|
|
eq(t, len(ranCommands), 5)
|
|
eq(t, strings.Join(ranCommands[1], " "), "git fetch https://github.com/OTHER/POE.git refs/pull/123/head:feature")
|
|
eq(t, strings.Join(ranCommands[3], " "), "git config branch.feature.remote https://github.com/OTHER/POE.git")
|
|
}
|
|
|
|
func TestPRCheckout_branchArg(t *testing.T) {
|
|
ctx := context.NewBlank()
|
|
ctx.SetBranch("master")
|
|
ctx.SetRemotes(map[string]string{
|
|
"origin": "OWNER/REPO",
|
|
})
|
|
initContext = func() context.Context {
|
|
return ctx
|
|
}
|
|
http := initFakeHTTP()
|
|
http.StubRepoResponse("OWNER", "REPO")
|
|
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": { "pullRequests": { "nodes": [
|
|
{ "number": 123,
|
|
"headRefName": "feature",
|
|
"headRepositoryOwner": {
|
|
"login": "hubot"
|
|
},
|
|
"headRepository": {
|
|
"name": "REPO",
|
|
"defaultBranchRef": {
|
|
"name": "master"
|
|
}
|
|
},
|
|
"isCrossRepository": true,
|
|
"maintainerCanModify": false }
|
|
] } } } }
|
|
`))
|
|
|
|
ranCommands := [][]string{}
|
|
restoreCmd := utils.SetPrepareCmd(func(cmd *exec.Cmd) utils.Runnable {
|
|
switch strings.Join(cmd.Args, " ") {
|
|
case "git show-ref --verify --quiet refs/heads/feature":
|
|
return &errorStub{"exit status: 1"}
|
|
default:
|
|
ranCommands = append(ranCommands, cmd.Args)
|
|
return &test.OutputStub{}
|
|
}
|
|
})
|
|
defer restoreCmd()
|
|
|
|
output, err := RunCommand(prCheckoutCmd, `pr checkout hubot:feature`)
|
|
eq(t, err, nil)
|
|
eq(t, output.String(), "")
|
|
|
|
eq(t, len(ranCommands), 5)
|
|
eq(t, strings.Join(ranCommands[1], " "), "git fetch origin refs/pull/123/head:feature")
|
|
}
|
|
|
|
func TestPRCheckout_existingBranch(t *testing.T) {
|
|
ctx := context.NewBlank()
|
|
ctx.SetBranch("master")
|
|
ctx.SetRemotes(map[string]string{
|
|
"origin": "OWNER/REPO",
|
|
})
|
|
initContext = func() context.Context {
|
|
return ctx
|
|
}
|
|
http := initFakeHTTP()
|
|
http.StubRepoResponse("OWNER", "REPO")
|
|
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": { "pullRequest": {
|
|
"number": 123,
|
|
"headRefName": "feature",
|
|
"headRepositoryOwner": {
|
|
"login": "hubot"
|
|
},
|
|
"headRepository": {
|
|
"name": "REPO",
|
|
"defaultBranchRef": {
|
|
"name": "master"
|
|
}
|
|
},
|
|
"isCrossRepository": false,
|
|
"maintainerCanModify": false
|
|
} } } }
|
|
`))
|
|
|
|
ranCommands := [][]string{}
|
|
restoreCmd := utils.SetPrepareCmd(func(cmd *exec.Cmd) utils.Runnable {
|
|
switch strings.Join(cmd.Args, " ") {
|
|
case "git show-ref --verify --quiet refs/heads/feature":
|
|
return &test.OutputStub{}
|
|
default:
|
|
ranCommands = append(ranCommands, cmd.Args)
|
|
return &test.OutputStub{}
|
|
}
|
|
})
|
|
defer restoreCmd()
|
|
|
|
output, err := RunCommand(prCheckoutCmd, `pr checkout 123`)
|
|
eq(t, err, nil)
|
|
eq(t, output.String(), "")
|
|
|
|
eq(t, len(ranCommands), 3)
|
|
eq(t, strings.Join(ranCommands[0], " "), "git fetch origin +refs/heads/feature:refs/remotes/origin/feature")
|
|
eq(t, strings.Join(ranCommands[1], " "), "git checkout feature")
|
|
eq(t, strings.Join(ranCommands[2], " "), "git merge --ff-only refs/remotes/origin/feature")
|
|
}
|
|
|
|
func TestPRCheckout_differentRepo_remoteExists(t *testing.T) {
|
|
ctx := context.NewBlank()
|
|
ctx.SetBranch("master")
|
|
ctx.SetRemotes(map[string]string{
|
|
"origin": "OWNER/REPO",
|
|
"robot-fork": "hubot/REPO",
|
|
})
|
|
initContext = func() context.Context {
|
|
return ctx
|
|
}
|
|
http := initFakeHTTP()
|
|
http.StubRepoResponse("OWNER", "REPO")
|
|
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": { "pullRequest": {
|
|
"number": 123,
|
|
"headRefName": "feature",
|
|
"headRepositoryOwner": {
|
|
"login": "hubot"
|
|
},
|
|
"headRepository": {
|
|
"name": "REPO",
|
|
"defaultBranchRef": {
|
|
"name": "master"
|
|
}
|
|
},
|
|
"isCrossRepository": true,
|
|
"maintainerCanModify": false
|
|
} } } }
|
|
`))
|
|
|
|
ranCommands := [][]string{}
|
|
restoreCmd := utils.SetPrepareCmd(func(cmd *exec.Cmd) utils.Runnable {
|
|
switch strings.Join(cmd.Args, " ") {
|
|
case "git show-ref --verify --quiet refs/heads/feature":
|
|
return &errorStub{"exit status: 1"}
|
|
default:
|
|
ranCommands = append(ranCommands, cmd.Args)
|
|
return &test.OutputStub{}
|
|
}
|
|
})
|
|
defer restoreCmd()
|
|
|
|
output, err := RunCommand(prCheckoutCmd, `pr checkout 123`)
|
|
eq(t, err, nil)
|
|
eq(t, output.String(), "")
|
|
|
|
eq(t, len(ranCommands), 4)
|
|
eq(t, strings.Join(ranCommands[0], " "), "git fetch robot-fork +refs/heads/feature:refs/remotes/robot-fork/feature")
|
|
eq(t, strings.Join(ranCommands[1], " "), "git checkout -b feature --no-track robot-fork/feature")
|
|
eq(t, strings.Join(ranCommands[2], " "), "git config branch.feature.remote robot-fork")
|
|
eq(t, strings.Join(ranCommands[3], " "), "git config branch.feature.merge refs/heads/feature")
|
|
}
|
|
|
|
func TestPRCheckout_differentRepo(t *testing.T) {
|
|
ctx := context.NewBlank()
|
|
ctx.SetBranch("master")
|
|
ctx.SetRemotes(map[string]string{
|
|
"origin": "OWNER/REPO",
|
|
})
|
|
initContext = func() context.Context {
|
|
return ctx
|
|
}
|
|
http := initFakeHTTP()
|
|
http.StubRepoResponse("OWNER", "REPO")
|
|
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": { "pullRequest": {
|
|
"number": 123,
|
|
"headRefName": "feature",
|
|
"headRepositoryOwner": {
|
|
"login": "hubot"
|
|
},
|
|
"headRepository": {
|
|
"name": "REPO",
|
|
"defaultBranchRef": {
|
|
"name": "master"
|
|
}
|
|
},
|
|
"isCrossRepository": true,
|
|
"maintainerCanModify": false
|
|
} } } }
|
|
`))
|
|
|
|
ranCommands := [][]string{}
|
|
restoreCmd := utils.SetPrepareCmd(func(cmd *exec.Cmd) utils.Runnable {
|
|
switch strings.Join(cmd.Args, " ") {
|
|
case "git config branch.feature.merge":
|
|
return &errorStub{"exit status 1"}
|
|
default:
|
|
ranCommands = append(ranCommands, cmd.Args)
|
|
return &test.OutputStub{}
|
|
}
|
|
})
|
|
defer restoreCmd()
|
|
|
|
output, err := RunCommand(prCheckoutCmd, `pr checkout 123`)
|
|
eq(t, err, nil)
|
|
eq(t, output.String(), "")
|
|
|
|
eq(t, len(ranCommands), 4)
|
|
eq(t, strings.Join(ranCommands[0], " "), "git fetch origin refs/pull/123/head:feature")
|
|
eq(t, strings.Join(ranCommands[1], " "), "git checkout feature")
|
|
eq(t, strings.Join(ranCommands[2], " "), "git config branch.feature.remote origin")
|
|
eq(t, strings.Join(ranCommands[3], " "), "git config branch.feature.merge refs/pull/123/head")
|
|
}
|
|
|
|
func TestPRCheckout_differentRepo_existingBranch(t *testing.T) {
|
|
ctx := context.NewBlank()
|
|
ctx.SetBranch("master")
|
|
ctx.SetRemotes(map[string]string{
|
|
"origin": "OWNER/REPO",
|
|
})
|
|
initContext = func() context.Context {
|
|
return ctx
|
|
}
|
|
http := initFakeHTTP()
|
|
http.StubRepoResponse("OWNER", "REPO")
|
|
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": { "pullRequest": {
|
|
"number": 123,
|
|
"headRefName": "feature",
|
|
"headRepositoryOwner": {
|
|
"login": "hubot"
|
|
},
|
|
"headRepository": {
|
|
"name": "REPO",
|
|
"defaultBranchRef": {
|
|
"name": "master"
|
|
}
|
|
},
|
|
"isCrossRepository": true,
|
|
"maintainerCanModify": false
|
|
} } } }
|
|
`))
|
|
|
|
ranCommands := [][]string{}
|
|
restoreCmd := utils.SetPrepareCmd(func(cmd *exec.Cmd) utils.Runnable {
|
|
switch strings.Join(cmd.Args, " ") {
|
|
case "git config branch.feature.merge":
|
|
return &test.OutputStub{[]byte("refs/heads/feature\n")}
|
|
default:
|
|
ranCommands = append(ranCommands, cmd.Args)
|
|
return &test.OutputStub{}
|
|
}
|
|
})
|
|
defer restoreCmd()
|
|
|
|
output, err := RunCommand(prCheckoutCmd, `pr checkout 123`)
|
|
eq(t, err, nil)
|
|
eq(t, output.String(), "")
|
|
|
|
eq(t, len(ranCommands), 2)
|
|
eq(t, strings.Join(ranCommands[0], " "), "git fetch origin refs/pull/123/head:feature")
|
|
eq(t, strings.Join(ranCommands[1], " "), "git checkout feature")
|
|
}
|
|
|
|
func TestPRCheckout_differentRepo_currentBranch(t *testing.T) {
|
|
ctx := context.NewBlank()
|
|
ctx.SetBranch("feature")
|
|
ctx.SetRemotes(map[string]string{
|
|
"origin": "OWNER/REPO",
|
|
})
|
|
initContext = func() context.Context {
|
|
return ctx
|
|
}
|
|
http := initFakeHTTP()
|
|
http.StubRepoResponse("OWNER", "REPO")
|
|
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": { "pullRequest": {
|
|
"number": 123,
|
|
"headRefName": "feature",
|
|
"headRepositoryOwner": {
|
|
"login": "hubot"
|
|
},
|
|
"headRepository": {
|
|
"name": "REPO",
|
|
"defaultBranchRef": {
|
|
"name": "master"
|
|
}
|
|
},
|
|
"isCrossRepository": true,
|
|
"maintainerCanModify": false
|
|
} } } }
|
|
`))
|
|
|
|
ranCommands := [][]string{}
|
|
restoreCmd := utils.SetPrepareCmd(func(cmd *exec.Cmd) utils.Runnable {
|
|
switch strings.Join(cmd.Args, " ") {
|
|
case "git config branch.feature.merge":
|
|
return &test.OutputStub{[]byte("refs/heads/feature\n")}
|
|
default:
|
|
ranCommands = append(ranCommands, cmd.Args)
|
|
return &test.OutputStub{}
|
|
}
|
|
})
|
|
defer restoreCmd()
|
|
|
|
output, err := RunCommand(prCheckoutCmd, `pr checkout 123`)
|
|
eq(t, err, nil)
|
|
eq(t, output.String(), "")
|
|
|
|
eq(t, len(ranCommands), 2)
|
|
eq(t, strings.Join(ranCommands[0], " "), "git fetch origin refs/pull/123/head")
|
|
eq(t, strings.Join(ranCommands[1], " "), "git merge --ff-only FETCH_HEAD")
|
|
}
|
|
|
|
func TestPRCheckout_maintainerCanModify(t *testing.T) {
|
|
ctx := context.NewBlank()
|
|
ctx.SetBranch("master")
|
|
ctx.SetRemotes(map[string]string{
|
|
"origin": "OWNER/REPO",
|
|
})
|
|
initContext = func() context.Context {
|
|
return ctx
|
|
}
|
|
http := initFakeHTTP()
|
|
http.StubRepoResponse("OWNER", "REPO")
|
|
|
|
http.StubResponse(200, bytes.NewBufferString(`
|
|
{ "data": { "repository": { "pullRequest": {
|
|
"number": 123,
|
|
"headRefName": "feature",
|
|
"headRepositoryOwner": {
|
|
"login": "hubot"
|
|
},
|
|
"headRepository": {
|
|
"name": "REPO",
|
|
"defaultBranchRef": {
|
|
"name": "master"
|
|
}
|
|
},
|
|
"isCrossRepository": true,
|
|
"maintainerCanModify": true
|
|
} } } }
|
|
`))
|
|
|
|
ranCommands := [][]string{}
|
|
restoreCmd := utils.SetPrepareCmd(func(cmd *exec.Cmd) utils.Runnable {
|
|
switch strings.Join(cmd.Args, " ") {
|
|
case "git config branch.feature.merge":
|
|
return &errorStub{"exit status 1"}
|
|
default:
|
|
ranCommands = append(ranCommands, cmd.Args)
|
|
return &test.OutputStub{}
|
|
}
|
|
})
|
|
defer restoreCmd()
|
|
|
|
output, err := RunCommand(prCheckoutCmd, `pr checkout 123`)
|
|
eq(t, err, nil)
|
|
eq(t, output.String(), "")
|
|
|
|
eq(t, len(ranCommands), 4)
|
|
eq(t, strings.Join(ranCommands[0], " "), "git fetch origin refs/pull/123/head:feature")
|
|
eq(t, strings.Join(ranCommands[1], " "), "git checkout feature")
|
|
eq(t, strings.Join(ranCommands[2], " "), "git config branch.feature.remote https://github.com/hubot/REPO.git")
|
|
eq(t, strings.Join(ranCommands[3], " "), "git config branch.feature.merge refs/heads/feature")
|
|
}
|