add ability to force checkout

This commit is contained in:
Neel Redkar 2020-09-24 16:26:35 -07:00 committed by Mislav Marohnić
parent 77cc378ae0
commit a89fa1ebed
2 changed files with 65 additions and 3 deletions

View file

@ -30,6 +30,7 @@ type CheckoutOptions struct {
SelectorArg string
RecurseSubmodules bool
Force bool
}
func NewCmdCheckout(f *cmdutil.Factory, runF func(*CheckoutOptions) error) *cobra.Command {
@ -61,6 +62,7 @@ func NewCmdCheckout(f *cmdutil.Factory, runF func(*CheckoutOptions) error) *cobr
}
cmd.Flags().BoolVarP(&opts.RecurseSubmodules, "recurse-submodules", "", false, "Update all active submodules (recursively)")
cmd.Flags().BoolVarP(&opts.Force, "force", "f", false, "Force merge into local branch")
return cmd
}
@ -116,7 +118,12 @@ func checkoutRun(opts *CheckoutOptions) error {
// local branch already exists
if _, err := git.ShowRefs("refs/heads/" + newBranchName); err == nil {
cmdQueue = append(cmdQueue, []string{"git", "checkout", newBranchName})
cmdQueue = append(cmdQueue, []string{"git", "merge", "--ff-only", fmt.Sprintf("refs/remotes/%s", remoteBranch)})
// If forced reset to remote
if opts.Force {
cmdQueue = append(cmdQueue, []string{"git", "reset", "--hard", fmt.Sprintf("refs/remotes/%s", remoteBranch)})
} else {
cmdQueue = append(cmdQueue, []string{"git", "merge", "--ff-only", fmt.Sprintf("refs/remotes/%s", remoteBranch)})
}
} else {
cmdQueue = append(cmdQueue, []string{"git", "checkout", "-b", newBranchName, "--no-track", remoteBranch})
cmdQueue = append(cmdQueue, []string{"git", "config", fmt.Sprintf("branch.%s.remote", newBranchName), headRemote.Name})
@ -139,11 +146,24 @@ func checkoutRun(opts *CheckoutOptions) error {
ref := fmt.Sprintf("refs/pull/%d/head", pr.Number)
if newBranchName == currentBranch {
// PR head matches currently checked out branch
cmdQueue = append(cmdQueue, []string{"git", "fetch", baseURLOrName, ref})
cmdQueue = append(cmdQueue, []string{"git", "merge", "--ff-only", "FETCH_HEAD"})
// If forced reset to remote
if opts.Force {
cmdQueue = append(cmdQueue, []string{"git", "reset", "--hard", "FETCH_HEAD"})
} else {
cmdQueue = append(cmdQueue, []string{"git", "merge", "--ff-only", "FETCH_HEAD"})
}
} else {
// create a new branch
cmdQueue = append(cmdQueue, []string{"git", "fetch", baseURLOrName, fmt.Sprintf("%s:%s", ref, newBranchName)})
// If forced reset to remote
if opts.Force {
cmdQueue = append(cmdQueue, []string{"git", "fetch", baseURLOrName, fmt.Sprintf("%s:%s", ref, newBranchName), "--force"})
} else {
cmdQueue = append(cmdQueue, []string{"git", "fetch", baseURLOrName, fmt.Sprintf("%s:%s", ref, newBranchName)})
}
cmdQueue = append(cmdQueue, []string{"git", "checkout", newBranchName})
}

View file

@ -646,3 +646,45 @@ func TestPRCheckout_recurseSubmodules(t *testing.T) {
assert.Equal(t, "git submodule sync --recursive", strings.Join(ranCommands[3], " "))
assert.Equal(t, "git submodule update --init --recursive", strings.Join(ranCommands[4], " "))
}
func TestPRCheckout_force(t *testing.T) {
http := &httpmock.Registry{}
http.Register(httpmock.GraphQL(`query PullRequestByNumber\b`), httpmock.StringResponse(`
{ "data": { "repository": { "pullRequest": {
"number": 123,
"headRefName": "feature",
"headRepositoryOwner": {
"login": "hubot"
},
"headRepository": {
"name": "REPO"
},
"isCrossRepository": false,
"maintainerCanModify": false
} } } }
`))
ranCommands := [][]string{}
//nolint:staticcheck // SA1019 TODO: rewrite to use run.Stub
restoreCmd := run.SetPrepareCmd(func(cmd *exec.Cmd) run.Runnable {
switch strings.Join(cmd.Args, " ") {
case "git show-ref --verify -- refs/heads/feature":
return &test.OutputStub{}
default:
ranCommands = append(ranCommands, cmd.Args)
return &test.OutputStub{}
}
})
defer restoreCmd()
output, err := runCommand(http, nil, "master", `123 --force`)
assert.NoError(t, err)
assert.Equal(t, "", output.String())
assert.Equal(t, len(ranCommands), 3)
assert.Equal(t, "git fetch origin +refs/heads/feature:refs/remotes/origin/feature", strings.Join(ranCommands[0], " "))
assert.Equal(t, "git checkout feature", strings.Join(ranCommands[1], " "))
assert.Equal(t, "git reset --hard refs/remotes/origin/feature", strings.Join(ranCommands[2], " "))
}