diff --git a/bin/gs b/bin/gs index 6f869ed..d152a00 100755 --- a/bin/gs +++ b/bin/gs @@ -25,7 +25,7 @@ gs - gentle-shell on main, plus one disposable worktree per PR updated if it exists), then Pi on it for shell PRs gs issue [repo] One step to start issue : race check (stops if the issue is closed, assigned to someone other than you, - or referenced by a PR; GS_FORCE=1 skips it), + or referenced by an open PR; GS_FORCE=1 skips it), branch /- from origin/main, then Pi on it for shell issues @@ -239,8 +239,14 @@ cmd_issue() { [ -z "$others" ] || die "$gh_repo#$NUM is assigned to $others (GS_FORCE=1 to continue)" prs=$(gh pr list -R "$gh_repo" --state all --search "$NUM in:title,body" --json number,state,title \ --jq '.[] | " #\(.number) \(.state) \(.title)"') - [ -z "$prs" ] || die "PRs may already reference #$NUM (GS_FORCE=1 to continue): -$prs" + # Only open PRs mean someone may be working on it now; merged/closed ones + # are history (long issues ship in slices), so they are listed, not fatal. + local open_prs done_prs + open_prs=$(printf '%s\n' "$prs" | grep -E '^ *#[0-9]+ OPEN ' || true) + done_prs=$(printf '%s\n' "$prs" | grep -vE '^ *#[0-9]+ OPEN |^$' || true) + [ -z "$open_prs" ] || die "Open PRs may already work on #$NUM (GS_FORCE=1 to continue): +$open_prs" + [ -z "$done_prs" ] || printf 'gs: #%s already has merged or closed PRs:\n%s\n' "$NUM" "$done_prs" >&2 fi case ",$labels," in *,type:feature,*) prefix=feat ;; diff --git a/tests/gs_test.sh b/tests/gs_test.sh index a80a96d..93eecf6 100755 --- a/tests/gs_test.sh +++ b/tests/gs_test.sh @@ -151,7 +151,7 @@ race_stub() { case "\$1 \$2" in "issue view") printf 'OPEN\037$1\037fix: thing\037type:bug\n' ;; "api user") echo me ;; - "pr list") echo "pr list" >> "$CALLS" ;; + "pr list") echo "pr list" >> "$CALLS"; printf '%b' "${2:-}" ;; esac exit 0 EOF @@ -170,6 +170,16 @@ OUT=$("$GS" issue shell 9 2>&1); rc=$? check "workshop: gs issue shared with someone else stops and names only them" \ '[ "$rc" = 1 ] && [[ "$OUT" == *"#9 is assigned to other (GS_FORCE=1 to continue)"* ]]' +# PRs that mention the issue: only open ones block; merged/closed ones are listed. +setup workshop; race_stub "" ' #5 MERGED feat: slice one (#9)\n #6 CLOSED docs: dropped (#9)\n' +OUT=$("$GS" issue shell 9 2>&1); rc=$? +check "workshop: gs issue with only merged or closed PRs continues and lists them" \ + '[[ "$OUT" != *"GS_FORCE=1 to continue"* ]] && [[ "$OUT" == *"#9 already has merged or closed PRs"* ]] && [[ "$OUT" == *"#5 MERGED feat: slice one (#9)"* ]] && [[ "$OUT" == *"#6 CLOSED docs: dropped (#9)"* ]]' +setup workshop; race_stub "" ' #5 MERGED feat: slice one (#9)\n #7 OPEN feat: slice two (#9)\n' +OUT=$("$GS" issue shell 9 2>&1); rc=$? +check "workshop: gs issue with an open PR still stops and names only the open ones" \ + '[ "$rc" = 1 ] && [[ "$OUT" == *"Open PRs may already work on #9 (GS_FORCE=1 to continue):"* ]] && [[ "$OUT" == *"#7 OPEN feat: slice two (#9)"* ]] && [[ "$OUT" != *"#5 MERGED"* ]]' + # --- sync (workshop) ---------------------------------------------------------- setup workshop