mirror of
https://github.com/stablyai/orca.git
synced 2026-09-30 08:03:12 +00:00
fix: route folder deletion through runtime cleanup
This commit is contained in:
@@ -13,8 +13,13 @@ import { registerRepoFolderPickerHandlers } from './repos/repo-folder-picker-han
|
||||
import { registerRepoCloneHandlers } from './repos/repo-clone-lifecycle'
|
||||
import { registerRepoGitUsernameHandler } from './repos/repo-git-username-handler'
|
||||
import { registerBaseRefQueryHandlers } from './repos/base-ref-query-handlers'
|
||||
import type { OrcaRuntimeService } from '../runtime/orca-runtime'
|
||||
|
||||
export function registerRepoHandlers(mainWindow: BrowserWindow, store: Store): void {
|
||||
export function registerRepoHandlers(
|
||||
mainWindow: BrowserWindow,
|
||||
store: Store,
|
||||
runtime?: OrcaRuntimeService
|
||||
): void {
|
||||
// Remove previously registered handlers so we can re-register on macOS app re-activation (new window).
|
||||
ipcMain.removeHandler('repos:list')
|
||||
ipcMain.removeHandler('repos:listForExecutionHost')
|
||||
@@ -67,7 +72,7 @@ export function registerRepoHandlers(mainWindow: BrowserWindow, store: Store): v
|
||||
registerProjectHostSetupHandlers(mainWindow, store)
|
||||
registerRepoCreationHandlers(mainWindow, store)
|
||||
registerProjectGroupHandlers(mainWindow, store)
|
||||
registerFolderWorkspaceHandlers(mainWindow, store)
|
||||
registerFolderWorkspaceHandlers(mainWindow, store, runtime)
|
||||
registerNestedRepoImportHandler(mainWindow, store)
|
||||
registerRepoUpdateHandler(mainWindow, store)
|
||||
registerSparsePresetHandlers(mainWindow, store)
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
getFolderWorkspacePathStatusForPath
|
||||
} from '../../project-groups/folder-workspace-path-status'
|
||||
import { getSshFilesystemProvider } from '../../providers/ssh-filesystem-dispatch'
|
||||
import type { OrcaRuntimeService } from '../../runtime/orca-runtime'
|
||||
import { notifyReposChanged } from './repos-changed-notification'
|
||||
import {
|
||||
FolderWorkspaceCreateArgs,
|
||||
@@ -18,7 +19,11 @@ import {
|
||||
parseProjectGroupIpcArgs
|
||||
} from './repo-ipc-arg-schemas'
|
||||
|
||||
export function registerFolderWorkspaceHandlers(mainWindow: BrowserWindow, store: Store): void {
|
||||
export function registerFolderWorkspaceHandlers(
|
||||
mainWindow: BrowserWindow,
|
||||
store: Store,
|
||||
runtime?: OrcaRuntimeService
|
||||
): void {
|
||||
ipcMain.handle('folderWorkspaces:list', (): FolderWorkspace[] => store.getFolderWorkspaces())
|
||||
|
||||
ipcMain.handle('folderWorkspaces:getPathStatus', async (_event, rawArgs: unknown) => {
|
||||
@@ -107,13 +112,15 @@ export function registerFolderWorkspaceHandlers(mainWindow: BrowserWindow, store
|
||||
}
|
||||
)
|
||||
|
||||
ipcMain.handle('folderWorkspaces:delete', (_event, rawArgs: unknown): boolean => {
|
||||
ipcMain.handle('folderWorkspaces:delete', async (_event, rawArgs: unknown): Promise<boolean> => {
|
||||
const args = parseProjectGroupIpcArgs(
|
||||
FolderWorkspaceSelectorArgs,
|
||||
rawArgs,
|
||||
'invalid_folder_workspace_delete_args'
|
||||
)
|
||||
const deleted = store.removeFolderWorkspace(args.folderWorkspaceId)
|
||||
const deleted = runtime
|
||||
? (await runtime.deleteFolderWorkspace(args.folderWorkspaceId)).deleted
|
||||
: store.removeFolderWorkspace(args.folderWorkspaceId)
|
||||
if (deleted) {
|
||||
notifyReposChanged(mainWindow)
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ export function attachMainWindowServices(
|
||||
}
|
||||
): void {
|
||||
registerAppReloadHandler(mainWindow, options?.onBeforeRendererReload)
|
||||
registerRepoHandlers(mainWindow, store)
|
||||
registerRepoHandlers(mainWindow, store, runtime)
|
||||
// Why: repo IPC mutations must also invalidate paired clients' catalogs (#11994).
|
||||
setRepoRemoteClientNotifier(runtime)
|
||||
setWorktreeCatalogRemoteClientNotifier(runtime)
|
||||
|
||||
@@ -54,10 +54,15 @@ export function useWorktreeCardWorkspaceActions({
|
||||
event.stopPropagation()
|
||||
if (showDeleteQuickAction) {
|
||||
if (folderWorkspaceId) {
|
||||
void deleteFolderWorkspace(folderWorkspaceId).then((deleted) => {
|
||||
void deleteFolderWorkspace(
|
||||
folderWorkspaceId,
|
||||
worktree.hostId ? { executionHostId: worktree.hostId } : undefined
|
||||
).then((deleted) => {
|
||||
if (
|
||||
deleted &&
|
||||
useAppStore.getState().activeWorktreeId === folderWorkspaceKey(folderWorkspaceId)
|
||||
useAppStore.getState().activeWorktreeId === folderWorkspaceKey(folderWorkspaceId) &&
|
||||
(!worktree.hostId ||
|
||||
useAppStore.getState().activeWorkspaceExecutionHostId === worktree.hostId)
|
||||
) {
|
||||
setActiveWorktree(null)
|
||||
}
|
||||
@@ -72,9 +77,9 @@ export function useWorktreeCardWorkspaceActions({
|
||||
[
|
||||
deleteFolderWorkspace,
|
||||
folderWorkspaceId,
|
||||
worktree.hostId,
|
||||
setActiveWorktree,
|
||||
showDeleteQuickAction,
|
||||
worktree.hostId,
|
||||
worktree.id
|
||||
]
|
||||
)
|
||||
|
||||
@@ -47,6 +47,25 @@ describe('createWorktreeContextMenuDeleteIntent', () => {
|
||||
|
||||
expect(mocks.runBatchDelete).toHaveBeenCalledWith(worktrees)
|
||||
})
|
||||
|
||||
it('preserves the folder owner host in a context-menu delete intent', () => {
|
||||
const intent = createWorktreeContextMenuDeleteIntent({
|
||||
worktree: {
|
||||
id: 'folder:shared',
|
||||
instanceId: 'runtime-instance',
|
||||
hostId: 'runtime:env-owner'
|
||||
},
|
||||
batchDeleteWorktrees: [],
|
||||
isMultiContext: false,
|
||||
folderWorkspaceId: 'shared'
|
||||
})
|
||||
|
||||
expect(intent).toEqual({
|
||||
kind: 'folder',
|
||||
folderWorkspaceId: 'shared',
|
||||
executionHostId: 'runtime:env-owner'
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('deferWorktreeContextMenuDeleteIntent', () => {
|
||||
|
||||
@@ -3,11 +3,12 @@ import { folderWorkspaceKey } from '../../../../shared/workspace-scope'
|
||||
import { runWorktreeBatchDelete, runWorktreeDelete } from './delete-worktree-flow'
|
||||
import type { WorktreeDeleteIdentity } from './worktree-delete-request'
|
||||
import type { Worktree } from '../../../../shared/worktree/types'
|
||||
import type { ExecutionHostId } from '../../../../shared/execution-host'
|
||||
|
||||
export type WorktreeContextMenuDeleteIntent =
|
||||
| { kind: 'worktree'; worktree: WorktreeDeleteIdentity }
|
||||
| { kind: 'batch'; worktrees: readonly WorktreeDeleteIdentity[] }
|
||||
| { kind: 'folder'; folderWorkspaceId: string }
|
||||
| { kind: 'folder'; folderWorkspaceId: string; executionHostId?: ExecutionHostId }
|
||||
|
||||
export function createWorktreeContextMenuDeleteIntent(args: {
|
||||
worktree: Pick<Worktree, 'id' | 'instanceId' | 'hostId'>
|
||||
@@ -26,7 +27,11 @@ export function createWorktreeContextMenuDeleteIntent(args: {
|
||||
}
|
||||
}
|
||||
if (args.folderWorkspaceId) {
|
||||
return { kind: 'folder', folderWorkspaceId: args.folderWorkspaceId }
|
||||
return {
|
||||
kind: 'folder',
|
||||
folderWorkspaceId: args.folderWorkspaceId,
|
||||
...(args.worktree.hostId ? { executionHostId: args.worktree.hostId } : {})
|
||||
}
|
||||
}
|
||||
const { id, instanceId, hostId } = args.worktree
|
||||
return { kind: 'worktree', worktree: { id, instanceId, hostId } }
|
||||
@@ -45,12 +50,22 @@ export function runWorktreeContextMenuDeleteIntent(intent: WorktreeContextMenuDe
|
||||
return
|
||||
}
|
||||
const state = useAppStore.getState()
|
||||
void state.deleteFolderWorkspace(intent.folderWorkspaceId).then((deleted) => {
|
||||
const current = useAppStore.getState()
|
||||
if (deleted && current.activeWorktreeId === folderWorkspaceKey(intent.folderWorkspaceId)) {
|
||||
current.setActiveWorktree(null)
|
||||
}
|
||||
})
|
||||
void state
|
||||
.deleteFolderWorkspace(
|
||||
intent.folderWorkspaceId,
|
||||
intent.executionHostId ? { executionHostId: intent.executionHostId } : undefined
|
||||
)
|
||||
.then((deleted) => {
|
||||
const current = useAppStore.getState()
|
||||
if (
|
||||
deleted &&
|
||||
current.activeWorktreeId === folderWorkspaceKey(intent.folderWorkspaceId) &&
|
||||
(!intent.executionHostId ||
|
||||
current.activeWorkspaceExecutionHostId === intent.executionHostId)
|
||||
) {
|
||||
current.setActiveWorktree(null)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function deferWorktreeContextMenuDeleteIntent(
|
||||
|
||||
Reference in New Issue
Block a user