From 4d929e30784ef38df704d70c5ec678f0bbb7bd38 Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Tue, 25 Aug 2026 00:30:51 -0700 Subject: [PATCH] test(git-watch): hold reserved inodes across root replacements Linux returns a released reservation to the free list, so the second replacement could land back on the first replacement's inode and look unchanged to reconciliation. Verified on ext4: releasing yields inodes [N, N+43, N+43] while holding yields [N, N+43, N+44]. macOS never recycles, which is why this only failed on CI. --- src/main/ipc/worktree-git-common-watch.test.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/ipc/worktree-git-common-watch.test.ts b/src/main/ipc/worktree-git-common-watch.test.ts index cea22f0b992..abe94d0b8d2 100644 --- a/src/main/ipc/worktree-git-common-watch.test.ts +++ b/src/main/ipc/worktree-git-common-watch.test.ts @@ -45,18 +45,22 @@ const alwaysVisible: WorktreePollerWindowVisibility = { onWindowBecameVisible: () => () => {} } +let inodeReservationCount = 0 + async function replaceWorktreesRoot( commonDir: string, worktreesDir: string, retainedEntry: string ): Promise { await rm(worktreesDir, { recursive: true }) - // Linux can reuse a just-deleted directory inode. Reserve that inode with a - // sibling before recreating the watched root so reconciliation sees a replacement. - const inodeReservation = join(commonDir, 'worktrees-replacement-inode') + // Linux reuses just-deleted directory inodes. Park each freed inode in a + // sibling that is HELD for the rest of the test — releasing it would return it + // to the free list, so a later replacement could land back on it and look + // unchanged to reconciliation. The dirs are siblings of `worktrees`, which no + // poll or watch path enumerates. + const inodeReservation = join(commonDir, `worktrees-replacement-inode-${++inodeReservationCount}`) await mkdir(inodeReservation) await mkdir(retainedEntry, { recursive: true }) - await rm(inodeReservation, { recursive: true, force: true }) } function createVisibilityHarness(): {