Skip to content

worktree: release frees slots with a missing lease record or directory - #9759

Merged
TrapsterDK merged 2 commits into
mainfrom
fix-worktree-release
Nov 9, 2026
Merged

TrapsterDK merged 2 commits into
mainfrom
fix-worktree-release

Conversation

@TrapsterDK

@TrapsterDK TrapsterDK commented Nov 9, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #9755

release now frees a slot whose checkout is registered but whose lease record is missing (the usual dirty/unpushed checks still run), and returns success when the slot directory is already gone instead of failing with 'cannot start git'. Tests added for both. Ran //cli/worktree:dx_worktree_test; no nested-Bazel or consumer tests run.
A slot whose directory is gone is dropped before the lease-holder check, so any session can drop another session's record; nothing is left to lose there. A missing record leaves the holder unknown, so releasing needs a clean, pushed checkout or --force.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Xut2hwESun1HL2eSVd1d5B

@TrapsterDK TrapsterDK added the needs-review Touches review paths; needs a second-session Review: comment label Nov 9, 2026
@TrapsterDK

Copy link
Copy Markdown
Collaborator Author

Review: changes requested

CI: the only analysis failure is the @dx_elixir / elixir_toolchain one that #9760 fixed on main. I found no other failing check.

  1. cli/worktree/src/ops.rs:1004 (gone_slot): a free slot is locked in git with FREE_LOCK_REASON (set at ops.rs:1104), and git worktree prune skips locked worktrees. If the directory of a free slot is deleted, release drops the record and reports success, but git keeps the registration. next_slot then hands out the same number, because the record and the directory are both gone, and git worktree add for that path fails with "is a missing but locked worktree". Run worktree unlock <path> before prune, as teardown does at ops.rs:1154. release_succeeds_when_the_slot_directory_is_already_gone only covers a held slot, which is not locked. Please add a case for a free slot with its directory removed, followed by ops::add.
  2. cli/worktree/src/ops.rs:1020: orphan_record builds a record held by the caller. That makes record.held_by(who) true, so a missing record skips the "leased to another holder" refusal. The dirty and unpushed checks still protect the work, but stop_server still runs against a slot another live session may be using. Consider requiring --force, or leaving the holder unknown, when the record is missing and the checkout is not detached and clean.
  3. cli/worktree/src/ops.rs:1030: gone_slot runs before the held_by / slot_leased check. Any session can therefore drop another session's lease record when the directory is missing. This is probably fine, since nothing is left to lose, but it is a behaviour change worth stating in the PR description.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Xut2hwESun1HL2eSVd1d5B

@TrapsterDK
TrapsterDK force-pushed the fix-worktree-release branch from 50fcc2c to 873da87 Compare November 9, 2026 11:42
@TrapsterDK

Copy link
Copy Markdown
Collaborator Author

Fixed: (1) gone_slot now runs worktree unlock before prune, with a test releasing a free slot whose directory is gone followed by ops::add reusing it; (2) orphan_record no longer claims the releaser as holder (holder unknown), so the holder check stays: a record-less slot needs a clean pushed tree or --force, with a test; (3) stated the gone-directory behaviour in the PR description. Rebased on origin/main; dx_worktree_test passes.

🤖 Generated with Claude Code

@TrapsterDK

Copy link
Copy Markdown
Collaborator Author

Review: approve

All three earlier findings are fixed at head 873da87. CI is still pending, with no failure so far.

  1. cli/worktree/src/ops.rs:gone_slot now runs worktree unlock before prune. release_of_a_free_slot_with_its_directory_gone_lets_add_reuse_the_slot (tests.rs) releases a free slot with its directory removed, then runs ops::add on the same slot.
  2. orphan_record leaves session, agent and pid unset, so held_by is false and the holder check stays. hold_known then needs a clean, pushed tree, or --force. release_of_a_record_less_slot_keeps_the_holder_check covers the refusal and the forced release.
  3. The PR description now states the gone-directory behaviour.

The branch is 0 behind main and touches only ops.rs and tests.rs. I found no lines that main deleted and this branch re-adds.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Xut2hwESun1HL2eSVd1d5B

@TrapsterDK
TrapsterDK merged commit 34de2a3 into main Nov 9, 2026
1 check failed
@TrapsterDK
TrapsterDK deleted the fix-worktree-release branch November 9, 2026 11:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-review Touches review paths; needs a second-session Review: comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

dx worktree release fails with 'no lease record' and 'cannot start git'

1 participant