Address workspace cleanup review nits

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
brennanb2025
2026-07-09 13:35:24 -07:00
committed by Brennan Benson
co-authored by Orca
parent 33b87c68e1
commit cfe4976759
5 changed files with 43 additions and 17 deletions
+11 -4
View File
@@ -7,6 +7,14 @@ import { toWindowsWslPath } from '../wsl'
type StatPath = (targetPath: string) => Promise<{ mtimeMs: number }>
type ReadTextFile = (targetPath: string) => Promise<string>
export function getPersistedWorkspaceCleanupActivityAt(
worktree: Pick<Worktree, 'createdAt' | 'lastActivityAt'>
): number {
const persistedActivityAt = Number.isFinite(worktree.lastActivityAt) ? worktree.lastActivityAt : 0
const createdAt = Number.isFinite(worktree.createdAt) ? (worktree.createdAt ?? 0) : 0
return Math.max(persistedActivityAt, createdAt)
}
export async function resolveWorkspaceCleanupActivityWorktree(
repo: Repo,
worktree: Worktree,
@@ -35,10 +43,9 @@ async function resolveWorkspaceCleanupActivityAt(
statPath: StatPath,
readTextFile: ReadTextFile
): Promise<number> {
const persistedActivityAt = Number.isFinite(worktree.lastActivityAt) ? worktree.lastActivityAt : 0
const createdAt = Number.isFinite(worktree.createdAt) ? (worktree.createdAt ?? 0) : 0
const persistedActivityAt = getPersistedWorkspaceCleanupActivityAt(worktree)
if (repo.connectionId) {
return Math.max(persistedActivityAt, createdAt)
return persistedActivityAt
}
const filesystemActivityAt = await getNewestLocalWorktreeStatMtime(
@@ -46,7 +53,7 @@ async function resolveWorkspaceCleanupActivityAt(
statPath,
readTextFile
)
return Math.max(persistedActivityAt, createdAt, filesystemActivityAt)
return Math.max(persistedActivityAt, filesystemActivityAt)
}
async function getNewestLocalWorktreeStatMtime(
+4 -9
View File
@@ -13,7 +13,10 @@ import type {
WorkspaceCleanupScanProgress,
WorkspaceCleanupScanResult
} from '../../shared/workspace-cleanup'
import { resolveWorkspaceCleanupActivityWorktree } from './workspace-cleanup-activity'
import {
getPersistedWorkspaceCleanupActivityAt,
resolveWorkspaceCleanupActivityWorktree
} from './workspace-cleanup-activity'
import {
buildWorkspaceCleanupCandidate,
buildWorkspaceCleanupCandidateFromError,
@@ -201,14 +204,6 @@ function shouldResolveBroadWorkspaceCleanupActivity(
)
}
function getPersistedWorkspaceCleanupActivityAt(
worktree: Pick<Worktree, 'createdAt' | 'lastActivityAt'>
): number {
const lastActivityAt = Number.isFinite(worktree.lastActivityAt) ? worktree.lastActivityAt : 0
const createdAt = Number.isFinite(worktree.createdAt) ? (worktree.createdAt ?? 0) : 0
return Math.max(lastActivityAt, createdAt)
}
async function listCleanupGitWorktrees(
repo: Repo,
repoIsFolder: boolean
@@ -28,6 +28,26 @@ describe('startWorkspaceCleanupBackgroundRemoval', () => {
vi.useRealTimers()
})
it('reports an empty result without starting removal when there are no candidates', async () => {
const removeCandidates = vi.fn()
const onProgress = vi.fn()
const onResult = vi.fn()
startWorkspaceCleanupBackgroundRemoval({
candidates: [],
removeCandidates,
onProgress,
onResult
})
await settleBackgroundRemoval()
expect(removeCandidates).not.toHaveBeenCalled()
expect(onProgress).not.toHaveBeenCalled()
expect(onResult).toHaveBeenCalledWith({ removedIds: [], failures: [] })
expect(toast.success).not.toHaveBeenCalled()
expect(toast.error).not.toHaveBeenCalled()
})
it('reports deletion progress while the slow removal promise is pending', async () => {
let resolveRemoval: (
result: Awaited<ReturnType<WorkspaceCleanupBackgroundRemovalArgs['removeCandidates']>>
@@ -37,6 +37,11 @@ export function startWorkspaceCleanupBackgroundRemoval({
removalTimeoutMs = DEFAULT_WORKSPACE_CLEANUP_REMOVAL_TIMEOUT_MS
}: WorkspaceCleanupBackgroundRemovalArgs): void {
if (candidates.length === 0) {
try {
onResult?.({ removedIds: [], failures: [] })
} catch (callbackError) {
console.error('Workspace cleanup result callback failed', callbackError)
}
return
}
@@ -1,12 +1,11 @@
import type { WorkspaceCleanupCandidate } from '../../../../shared/workspace-cleanup'
import type { WorktreeDeleteState } from '@/store/slices/worktrees'
type DeleteState = {
isDeleting?: boolean
}
type DeletionFlagState = Pick<WorktreeDeleteState, 'isDeleting'>
export function filterWorkspaceCleanupRemovalCandidates(
candidates: readonly WorkspaceCleanupCandidate[],
deleteStateByWorktreeId: Record<string, DeleteState | undefined>
deleteStateByWorktreeId: Record<string, DeletionFlagState | undefined>
): WorkspaceCleanupCandidate[] {
return candidates.filter(
(candidate) => deleteStateByWorktreeId[candidate.worktreeId]?.isDeleting !== true