Background
Re-running gem-contribute fix <gem>/<n> against an issue you've already started errors out instead of being a no-op-ending-in-the-same-place.
Repro:
$ gem-contribute fix -e gem-contribute/5 # first run: forks, clones, branches, opens editor
$ gem-contribute fix -e gem-contribute/5 # second run:
[⠴] Forking cdhagmann/gem-contribute...
fix failed: git -C /path/to/clone checkout -b gem-contribute/issue-5 failed:
fatal: a branch named 'gem-contribute/issue-5' already exists
The current behavior is documented in lib/gem_contribute/operations/branch.rb:11 as preserving pre-extraction behavior, with a forward-pointer to #10 — but #10 turned out to be a different concern (fork-when-you-own-upstream messaging), so this case has no tracking issue today.
Desired behavior
fix should be idempotent: running it a second time on the same <gem>/<n> lands you in exactly the same state as the first run, without errors.
Concretely:
- Fork already exists → skip fork (already does this).
- Clone already exists at
<clone_root>/<owner>/<repo> → skip clone (already does this — Operations::Clone::Result.new(reused: true)).
- Branch already exists locally →
git checkout it instead of git checkout -b. This is the new behavior.
- Announce comment already posted → don't re-post. The "👋 I've started working on this" comment shouldn't get duplicated on every re-run. (See
Operations::Announce for current behavior — needs a check before posting, presumably by querying issue comments for the marker we set on the first run.)
-e / -a hooks → run on every invocation. The whole point of re-running is "open my editor on this work-in-progress." Running them is the goal, not a side effect to skip.
End state of the second run should be: you're cd'd nowhere new, but the editor/AI tool you asked for is open on the existing clone with the existing branch checked out.
Acceptance
Files likely to touch
lib/gem_contribute/operations/branch.rb — replace git checkout -b with "create or switch" semantics; update the doc comment.
lib/gem_contribute/operations/announce.rb — add a "has the marker comment already been posted by us?" check.
lib/gem_contribute/operations/fix_pipeline.rb — may need to thread the announce-already-done signal through.
spec/gem_contribute/operations/branch_spec.rb, spec/gem_contribute/operations/announce_spec.rb — re-run path coverage.
Notes
Git#checkout_branch currently shells out to git checkout -b <name>. The fix is either a new Git#switch_or_create_branch method (git switch -c <name> falls back to git switch <name> if the branch exists), or a check-then-act pattern in Operations::Branch.
- Don't try to reconcile state if the branch exists but isn't checked out at the same base as
main/master. That's a "you have local work in progress" case and silently rebasing it would be bad. Just check it out where it is.
- Output messages should reflect what actually happened:
Reusing branch gem-contribute/issue-5 instead of Creating branch gem-contribute/issue-5 when reusing.
Background
Re-running
gem-contribute fix <gem>/<n>against an issue you've already started errors out instead of being a no-op-ending-in-the-same-place.Repro:
The current behavior is documented in
lib/gem_contribute/operations/branch.rb:11as preserving pre-extraction behavior, with a forward-pointer to #10 — but #10 turned out to be a different concern (fork-when-you-own-upstream messaging), so this case has no tracking issue today.Desired behavior
fixshould be idempotent: running it a second time on the same<gem>/<n>lands you in exactly the same state as the first run, without errors.Concretely:
<clone_root>/<owner>/<repo>→ skip clone (already does this —Operations::Clone::Result.new(reused: true)).git checkoutit instead ofgit checkout -b. This is the new behavior.Operations::Announcefor current behavior — needs a check before posting, presumably by querying issue comments for the marker we set on the first run.)-e/-ahooks → run on every invocation. The whole point of re-running is "open my editor on this work-in-progress." Running them is the goal, not a side effect to skip.End state of the second run should be: you're cd'd nowhere new, but the editor/AI tool you asked for is open on the existing clone with the existing branch checked out.
Acceptance
fixinvocation against an in-progress issue exits 0 and runs the post-clone hooks.fixfirst-run paths still work unchanged.Files likely to touch
lib/gem_contribute/operations/branch.rb— replacegit checkout -bwith "create or switch" semantics; update the doc comment.lib/gem_contribute/operations/announce.rb— add a "has the marker comment already been posted by us?" check.lib/gem_contribute/operations/fix_pipeline.rb— may need to thread the announce-already-done signal through.spec/gem_contribute/operations/branch_spec.rb,spec/gem_contribute/operations/announce_spec.rb— re-run path coverage.Notes
Git#checkout_branchcurrently shells out togit checkout -b <name>. The fix is either a newGit#switch_or_create_branchmethod (git switch -c <name>falls back togit switch <name>if the branch exists), or a check-then-act pattern inOperations::Branch.main/master. That's a "you have local work in progress" case and silently rebasing it would be bad. Just check it out where it is.Reusing branch gem-contribute/issue-5instead ofCreating branch gem-contribute/issue-5when reusing.