diff --git a/src/main/worktree-trash.test.ts b/src/main/worktree-trash.test.ts index 550fd667278..d5f9784f075 100644 --- a/src/main/worktree-trash.test.ts +++ b/src/main/worktree-trash.test.ts @@ -56,8 +56,11 @@ describe('moveWorktreeDirectoryToTrash', () => { } }) - it('reports the rename as unavailable when the checkout is missing', async () => { - expect(await moveWorktreeDirectoryToTrash(join(scratchDir, 'repo', 'gone'))).toBeUndefined() + it('reports the rename as unavailable and leaves no trash root when the checkout is missing', async () => { + const worktreePath = join(scratchDir, 'repo', 'gone') + + expect(await moveWorktreeDirectoryToTrash(worktreePath)).toBeUndefined() + expect(existsSync(getWorktreeTrashRoot(worktreePath))).toBe(false) }) async function seededWorktree(name: string): Promise { diff --git a/src/main/worktree-trash.ts b/src/main/worktree-trash.ts index 58d3e45c9c6..d1e7b50747f 100644 --- a/src/main/worktree-trash.ts +++ b/src/main/worktree-trash.ts @@ -3,7 +3,7 @@ // is a metadata operation, and the recursive delete then runs after the IPC has already returned. import { randomBytes } from 'node:crypto' -import { mkdir, readdir, rename } from 'node:fs/promises' +import { mkdir, readdir, rename, rmdir } from 'node:fs/promises' import { dirname, join } from 'node:path' import { removeHostTree } from './host-tree-removal' import { isFolderRepo } from '../shared/repo-kind' @@ -46,6 +46,8 @@ export async function moveWorktreeDirectoryToTrash( `[worktrees] Deferred deletion unavailable for ${worktreePath}; deleting in place`, error ) + // Leave no empty trash root behind when the rename never happened; rmdir keeps queued entries. + await rmdir(trashRoot).catch(() => {}) return undefined } }