fix(sidebar): preserve folder workspace owner identity

This commit is contained in:
Brennan Benson
2026-08-10 16:22:43 -07:00
parent 0c9cbcb678
commit de06dbb4f2
27 changed files with 663 additions and 129 deletions
+2 -2
View File
@@ -109,9 +109,9 @@ import {
buildProjectGroupOwnerIndex,
getFolderWorkspaceProjectGroupOwnerHostId,
getProjectGroupOwnerHostId,
resolveFolderWorkspaceProjectGroup,
resolveProjectGroupOwner
} from '../../shared/project-groups'
import { resolveFolderWorkspaceProjectGroupWithLegacySsh } from '../../shared/folder-workspace-project-group-resolution'
import { joinRemotePath } from '../ssh/ssh-remote-platform'
import {
assertFolderWorkspacePathUsable,
@@ -1571,7 +1571,7 @@ export function registerRepoHandlers(mainWindow: BrowserWindow, store: Store): v
}
const projectGroups = store.getProjectGroups()
const projectGroupIndex = buildProjectGroupOwnerIndex(projectGroups)
const group = resolveFolderWorkspaceProjectGroup(projectGroupIndex, workspace)
const group = resolveFolderWorkspaceProjectGroupWithLegacySsh(projectGroupIndex, workspace)
if (!group) {
return null
}
+50
View File
@@ -3809,6 +3809,56 @@ describe('Store', () => {
expect(store.getFolderWorkspace('same-folder', 'ssh:builder')?.name).toBe('Remote')
})
it('loads a persisted legacy SSH folder under one unstamped group', async () => {
writeDataFile({
schemaVersion: 1,
repos: [],
worktreeMeta: {},
settings: {},
ui: {},
githubCache: { pr: {}, issue: {} },
projectGroups: [
{
id: 'legacy-group',
name: 'Legacy',
parentPath: '/remote',
parentGroupId: null,
createdFrom: 'migration',
tabOrder: 0,
isCollapsed: false,
color: null,
createdAt: 1,
updatedAt: 1
}
],
folderWorkspaces: [
{
id: 'legacy-folder',
projectGroupId: 'legacy-group',
name: 'Legacy folder',
folderPath: '/remote/folder',
connectionId: 'builder',
linkedTask: null,
comment: '',
isArchived: false,
isUnread: false,
isPinned: false,
sortOrder: 0,
lastActivityAt: 1,
createdAt: 1,
updatedAt: 1
}
]
})
const store = await createStore()
expect(store.getProjectGroups()[0]?.connectionId).toBeUndefined()
expect(store.getFolderWorkspace('legacy-folder', 'ssh:builder')).toBeDefined()
expect(store.deleteProjectGroup('legacy-group', 'local')).toBe(true)
expect(store.getFolderWorkspace('legacy-folder', 'ssh:builder')).toBeUndefined()
})
it('adapts flat folder-scan groups into sparse nested folder scopes on load', async () => {
writeDataFile({
schemaVersion: 1,
+3 -3
View File
@@ -229,9 +229,9 @@ import {
normalizeProjectGroupName,
normalizeProjectGroups,
resolveProjectGroupMembership,
resolveProjectGroupOwner,
resolveFolderWorkspaceProjectGroup
resolveProjectGroupOwner
} from '../shared/project-groups'
import { resolveFolderWorkspaceProjectGroupWithLegacySsh } from '../shared/folder-workspace-project-group-resolution'
import { createNestedProjectGroupResolver } from './project-groups/nested-repo-import'
import {
mergeLegacyCommitMessageAiIntoSourceControlAi,
@@ -4491,7 +4491,7 @@ export class Store {
})
const folderWorkspaces = this.state.folderWorkspaces ?? []
const removedFolderWorkspaces = folderWorkspaces.filter((workspace) => {
const group = resolveFolderWorkspaceProjectGroup(projectGroupIndex, workspace)
const group = resolveFolderWorkspaceProjectGroupWithLegacySsh(projectGroupIndex, workspace)
return group && deletedGroupIdentities.has(getProjectGroupOwnerIdentity(group))
})
this.state.folderWorkspaces = folderWorkspaces.filter(
@@ -15,7 +15,7 @@ import {
import { getRepoExecutionHostId, type ExecutionHostId } from '../../shared/execution-host'
import type { FolderWorkspace, ProjectGroup, Repo } from '../../shared/types'
import {
resolveFolderWorkspaceCatalogOwnerHostId,
resolveFolderWorkspaceCatalogOwnerHostIdFromIndex,
resolveLegacySshFolderWorkspaceProjectGroup
} from '../../shared/folder-workspaces'
import type { IFilesystemProvider } from '../providers/types'
@@ -202,7 +202,8 @@ export function resolveFolderWorkspaceStatusPath(args: {
(entry) =>
entry.id === request.folderWorkspaceId &&
(!request.ownerHostId ||
resolveFolderWorkspaceCatalogOwnerHostId(entry, projectGroups) === request.ownerHostId)
resolveFolderWorkspaceCatalogOwnerHostIdFromIndex(entry, projectGroupIndex) ===
request.ownerHostId)
)
const workspace = matches.length === 1 ? matches[0] : null
if (!workspace) {