Skip to content

Commit

Permalink
Checkout the branch you were on if an error happens.
Browse files Browse the repository at this point in the history
When you do `opp pr` and we need to rebase and the rebase fails,
it's better if opp checks out the commit you were on before.
  • Loading branch information
cupcicm committed Feb 18, 2024
1 parent e5a4ae0 commit 8719575
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 7 deletions.
31 changes: 26 additions & 5 deletions cmd/pr.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ func PrCommand(repo *core.Repo, gh func(context.Context) core.Gh) *cli.Command {
},
},
Action: func(cCtx *cli.Context) error {
initialRef, err := repo.Head()
if err != nil {
return err
}
pr := create{Repo: repo, Github: gh(cCtx.Context)}
args, err := pr.SanitizeArgs(cCtx)
if err != nil {
Expand All @@ -83,6 +87,7 @@ func PrCommand(repo *core.Repo, gh func(context.Context) core.Gh) *cli.Command {
if args.NeedsRebase {
newArgs, err := pr.RebasePrCommits(cCtx.Context, args)
if err != nil {
repo.CheckoutRef(initialRef)
return err
}
args = newArgs
Expand All @@ -95,7 +100,7 @@ func PrCommand(repo *core.Repo, gh func(context.Context) core.Gh) *cli.Command {
if args.CheckoutPr {
return repo.Checkout(localPr)
}
return nil
return repo.CheckoutRef(initialRef)
},
}

Expand Down Expand Up @@ -202,12 +207,15 @@ func HeadCommit(repo *core.Repo, args cli.Args) (plumbing.Hash, error) {
// since HEAD will be detached after the rebase.
func (c *create) RebasePrCommits(ctx context.Context, previousArgs *args) (*args, error) {
// Careful ! The first commit is the child-most one, not the other way around.
err := c.Repo.DetachHead(ctx)
if err != nil {
return nil, fmt.Errorf("could not detach head: %w", err)
}
if previousArgs.Interactive {
fmt.Println("Choose what commits you want to include in this PR")
if !c.Repo.TryRebaseOntoSilently(
ctx,
previousArgs.Commits[len(previousArgs.Commits)-1].Hash,
previousArgs.Commits[0].Hash,
previousArgs.AncestorBranch,
true,
) {
Expand All @@ -221,7 +229,6 @@ func (c *create) RebasePrCommits(ctx context.Context, previousArgs *args) (*args
if !c.Repo.TryRebaseOntoSilently(
ctx,
previousArgs.Commits[len(previousArgs.Commits)-1].Hash,
previousArgs.Commits[0].Hash,
previousArgs.AncestorBranch,
false,
) {
Expand Down Expand Up @@ -300,7 +307,14 @@ func (c *create) createLocalBranchForPr(number int, hash plumbing.Hash, ancestor
c.Repo.Storer.SetReference(plumbing.NewHashReference(ref, hash))
}

func (c *create) create(ctx context.Context, hash plumbing.Hash, ancestor core.Branch, title string, body string, draft bool) (int, error) {
func (c *create) create(
ctx context.Context,
hash plumbing.Hash,
ancestor core.Branch,
title string,
body string,
draft bool,
) (int, error) {
for attempts := 0; attempts < 3; attempts++ {
pr, err := c.createOnce(ctx, hash, ancestor, title, body, draft)
if err == nil {
Expand All @@ -316,7 +330,14 @@ func (c *create) create(ctx context.Context, hash plumbing.Hash, ancestor core.B
return 0, ErrLostPrCreationRaceConditionMultipleTimes
}

func (c *create) createOnce(ctx context.Context, hash plumbing.Hash, ancestor core.Branch, title string, body string, draft bool) (int, error) {
func (c *create) createOnce(
ctx context.Context,
hash plumbing.Hash,
ancestor core.Branch,
title string,
body string,
draft bool,
) (int, error) {
ctx, cancel := context.WithTimeoutCause(
ctx, core.GetGithubTimeout(),
fmt.Errorf("creating PR too slow, increase github.timeout"),
Expand Down
21 changes: 19 additions & 2 deletions core/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,18 @@ func (r *Repo) Checkout(branch Branch) error {
return cmd.Run()
}

func (r *Repo) CheckoutRef(ref *plumbing.Reference) error {
checkout := ref.Hash().String()
if ref.Name().IsBranch() {
checkout = ref.Name().Short()
}
cmd := r.GitExec(context.Background(), "checkout %s", checkout)
cmd.Stderr = nil
cmd.Stdout = nil
cmd.Stdin = os.Stdin
return cmd.Run()
}

func (r *Repo) GitExec(ctx context.Context, format string, args ...any) *exec.Cmd {
cmd := exec.CommandContext(ctx, "bash", "-c", "git "+fmt.Sprintf(format, args...))
cmd.Dir = r.Path()
Expand Down Expand Up @@ -215,12 +227,12 @@ func (r *Repo) TryRebaseCurrentBranchSilently(ctx context.Context, branch Branch
return false
}

func (r *Repo) TryRebaseOntoSilently(ctx context.Context, first plumbing.Hash, last plumbing.Hash, onto Branch, interactive bool) bool {
func (r *Repo) TryRebaseOntoSilently(ctx context.Context, first plumbing.Hash, onto Branch, interactive bool) bool {
interactiveString := ""
if interactive {
interactiveString = "--interactive"
}
cmd := r.GitExec(ctx, "rebase %s --onto %s/%s %s^ %s", interactiveString, GetRemoteName(), onto.RemoteName(), first.String(), last.String())
cmd := r.GitExec(ctx, "rebase %s --onto %s/%s %s^", interactiveString, GetRemoteName(), onto.RemoteName(), first.String())
err := cmd.Run()
if err == nil {
return true
Expand Down Expand Up @@ -378,3 +390,8 @@ func (r *Repo) DeleteRemoteBranch(ctx context.Context, branch Branch) error {
cmd := r.GitExec(ctx, "push %s :%s", GetRemoteName(), branch.RemoteName())
return cmd.Run()
}

func (r *Repo) DetachHead(ctx context.Context) error {
cmd := r.GitExec(ctx, "checkout --detach HEAD")
return cmd.Run()
}

0 comments on commit 8719575

Please sign in to comment.