Skip to content

feat(delete): multi-target support with -i and --dry-run#100

Merged
DaveDev42 merged 17 commits intomainfrom
feat/cw-delete-multiple-worktree
Apr 23, 2026
Merged

feat(delete): multi-target support with -i and --dry-run#100
DaveDev42 merged 17 commits intomainfrom
feat/cw-delete-multiple-worktree

Conversation

@DaveDev42
Copy link
Copy Markdown
Owner

Summary

Extends gw delete to operate on multiple worktrees in a single invocation.

  • Accepts multiple positional targets: gw delete feat/a feat/b feat/c
  • New -i / --interactive multi-select TUI (arrow keys + Space + Enter; Esc/q cancels)
  • New --dry-run preview mode
  • Preserves the legacy gw delete (no args) path — still deletes the current worktree with the existing busy prompt
  • Flags (-k, -r, -f, --no-force, -w, -b) apply to every target

Single batch confirmation fires when the plan has >= 2 entries (TTY only); non-TTY invocations assume consent. -i and positional targets are mutually exclusive at parse time.

Exit codes

  • 0 — full success, --dry-run, or -i with nothing selected / no feature worktrees
  • 1 — user cancelled (batch prompt N, or -i Esc/q/Ctrl-C)
  • 2 — any target failed or was skipped (not found, busy without --force, remove error, pre-hook failure)

Note: single-target failures (e.g. gw delete <unknown>) previously exited 1 via the generic error handler. They now exit 2 under the new contract. Scripts pinning exit code 1 for "target not found" should be updated.

Implementation

  • src/cli.rsCommands::Delete { targets: Vec<String>, interactive, dry_run, ... } with clap conflicts_with.
  • src/operations/worktree.rs — split delete_worktree into per-target delete_one + legacy public shim. Existing clean.rs caller unchanged.
  • src/operations/delete_batch.rs (new) — plan types (Resolved, PlanEntry, ItemResult), orchestrator delete_worktrees, summary / confirm / execute / exit-code helpers.
  • src/tui/multi_select.rs (new) — arrow/checkbox TUI built on existing raw-mode plumbing from arrow_select.rs (now pub(crate)).
  • src/error.rs — new CwError::ExitCode(i32) variant for silent propagation of the orchestrator's exit code.

Test plan

  • cargo fmt --check
  • cargo clippy --all-targets -- -D warnings (zero warnings)
  • cargo test — 605 passed
  • New integration tests in tests/test_delete_multi.rs (6 scenarios: all-success, mix valid+missing → exit 2, dry-run, keep-branch on multiple, -i + positional conflict, legacy no-args from inside worktree)
  • CI: actions workflow .github/workflows/test.yml (subagent to verify)

Docs

  • docs/superpowers/specs/2026-04-23-delete-multiple-worktrees-design.md — design spec
  • docs/superpowers/plans/2026-04-23-delete-multiple-worktrees.md — implementation plan
  • README.md — command table row updated
  • src/cli.rsDelete variant long_about documents behavior + exit codes

Allows gw delete to accept multiple positional targets or an interactive
multi-select, with best-effort batch execution, single batch confirmation,
and non-zero exit on partial failure. Preserves all existing single-target
behavior and flags. Explicitly out of scope: sync/merge/change-base
multi-target, and clean/delete consolidation.
9 tasks: CLI surface change, delete_one extraction, plan types, summary/
confirm helpers, orchestrator + exit codes, multi-select TUI widget,
integration tests, doc polish, final verification. Preserves single-target
legacy behavior throughout.
Matches the summary/progress → stdout, errors/prompts → stderr convention
already used by gw clean and worktree progress output. Adds the
'(dry-run; nothing deleted)' trailer that the spec example calls for.
- exit_code_from uses iter::any for readability
- move_cwd_out_of_targets treats canonicalize failures as skip-compare
  to avoid asymmetric-path mis-classification
- busy-arm stderr mirror restores phrasing parity with the legacy flow
  (includes process count)
…flow

Spec prescribes:
- Nothing selected (or no worktrees) → exit 0
- Esc / q / Ctrl-C        → exit 1

Replace the boolean Ok(Vec::new()) convention with an InteractiveOutcome
enum (Selected / Nothing / Cancelled) and map each to the correct exit
code in delete_worktrees.
@DaveDev42 DaveDev42 merged commit 6713359 into main Apr 23, 2026
7 checks passed
@DaveDev42 DaveDev42 deleted the feat/cw-delete-multiple-worktree branch April 23, 2026 09:40
DaveDev42 added a commit that referenced this pull request Apr 23, 2026
- Drop volatile "0.0.38+" version label; link PR #100 instead.
- Clarify exit `0` covers the no-eligible-worktrees case in `-i`.
- Generalize the script-author guidance from "target not found" to
  any failure (Skipped also covers busy / remove errors).
DaveDev42 added a commit that referenced this pull request Apr 23, 2026
Single-target failures now exit with code 2 instead of 1, aligning with
the multi-target batch contract introduced in PR #100. Surface this in
README so users pinning exit codes in scripts can find it.
DaveDev42 added a commit that referenced this pull request Apr 23, 2026
- Drop volatile "0.0.38+" version label; link PR #100 instead.
- Clarify exit `0` covers the no-eligible-worktrees case in `-i`.
- Generalize the script-author guidance from "target not found" to
  any failure (Skipped also covers busy / remove errors).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant