Fix duplicate project worktree registration (#1024)

* Fix duplicate project worktree registration

* Update archive redirect test for project-aware routes
This commit is contained in:
Mohamed Boudra
2026-05-14 20:57:32 +08:00
committed by GitHub
parent 7e255a5249
commit fbeda4510e
16 changed files with 415 additions and 43 deletions
+8 -1
View File
@@ -2,10 +2,16 @@ import { useLocalSearchParams } from "expo-router";
import { NewWorkspaceScreen } from "@/screens/new-workspace-screen";
export default function HostNewWorkspaceRoute() {
const params = useLocalSearchParams<{ serverId?: string; dir?: string; name?: string }>();
const params = useLocalSearchParams<{
serverId?: string;
dir?: string;
name?: string;
projectId?: string;
}>();
const serverId = typeof params.serverId === "string" ? params.serverId : "";
const sourceDirectory = typeof params.dir === "string" ? params.dir : "";
const displayName = typeof params.name === "string" ? params.name : undefined;
const projectId = typeof params.projectId === "string" ? params.projectId : undefined;
if (!sourceDirectory) {
return null;
@@ -16,6 +22,7 @@ export default function HostNewWorkspaceRoute() {
serverId={serverId}
sourceDirectory={sourceDirectory}
displayName={displayName}
projectId={projectId}
/>
);
}
@@ -1173,10 +1173,13 @@ function ProjectHeaderRow({
return;
}
router.navigate(
buildHostNewWorkspaceRoute(serverId, project.iconWorkingDir, { displayName }) as Href,
buildHostNewWorkspaceRoute(serverId, project.iconWorkingDir, {
displayName,
projectId: project.projectKey,
}) as Href,
);
onWorkspacePress?.();
}, [displayName, onWorkspacePress, project.iconWorkingDir, serverId]);
}, [displayName, onWorkspacePress, project.iconWorkingDir, project.projectKey, serverId]);
const _mergeWorkspaces = useSessionStore((state) => state.mergeWorkspaces);
const _toast = useToast();
@@ -57,6 +57,7 @@ function resolveCheckoutRequest(
interface NewWorkspaceScreenProps {
serverId: string;
sourceDirectory: string;
projectId?: string;
displayName?: string;
}
@@ -496,6 +497,7 @@ function submitWorkspaceDraft(input: SubmitDraftInput): void {
export function NewWorkspaceScreen({
serverId,
sourceDirectory,
projectId,
displayName: displayNameProp,
}: NewWorkspaceScreenProps) {
const { theme } = useUnistyles();
@@ -711,6 +713,7 @@ export function NewWorkspaceScreen({
return {
cwd: input.cwd,
...(projectId ? { projectId } : {}),
worktreeSlug: createNameId(),
...(hasFirstAgentContext
? {
@@ -723,7 +726,7 @@ export function NewWorkspaceScreen({
...checkoutRequest,
};
},
[currentBranch, selectedItem],
[currentBranch, projectId, selectedItem],
);
const ensureWorkspace = useCallback(
+4 -1
View File
@@ -358,7 +358,7 @@ export function buildHostOpenProjectRoute(serverId: string) {
export function buildHostNewWorkspaceRoute(
serverId: string,
sourceDirectory: string,
options?: { displayName?: string },
options?: { displayName?: string; projectId?: string },
) {
const base = buildHostRootRoute(serverId);
if (base === "/") {
@@ -369,6 +369,9 @@ export function buildHostNewWorkspaceRoute(
if (options?.displayName) {
params.set("name", options.displayName);
}
if (options?.projectId) {
params.set("projectId", options.projectId);
}
return `${base}/new?${params.toString()}` as const;
}
@@ -47,7 +47,7 @@ describe("buildWorkspaceArchiveRedirectRoute", () => {
archivedWorkspaceId: "/repo/.paseo/worktrees/feature",
workspaces,
}),
).toBe("/h/server-1/new?dir=%2Frepo&name=Project");
).toBe("/h/server-1/new?dir=%2Frepo&name=Project&projectId=project-1");
});
it("redirects to the new workspace route when no sibling workspace target exists", () => {
@@ -65,7 +65,7 @@ describe("buildWorkspaceArchiveRedirectRoute", () => {
archivedWorkspaceId: "/repo/.paseo/worktrees/feature",
workspaces,
}),
).toBe("/h/server-1/new?dir=%2Frepo&name=Project");
).toBe("/h/server-1/new?dir=%2Frepo&name=Project&projectId=project-1");
});
it("redirects to the new workspace route instead of another workspace", () => {
@@ -85,7 +85,7 @@ describe("buildWorkspaceArchiveRedirectRoute", () => {
archivedWorkspaceId: "/notes",
workspaces,
}),
).toBe("/h/server-1/new?dir=%2Fnotes&name=Project");
).toBe("/h/server-1/new?dir=%2Fnotes&name=Project&projectId=notes");
});
});
@@ -132,6 +132,8 @@ describe("redirectIfArchivingActiveWorkspace", () => {
}),
).toBe(true);
expect(replaceMock).toHaveBeenCalledWith("/h/server-1/new?dir=%2Frepo&name=Project");
expect(replaceMock).toHaveBeenCalledWith(
"/h/server-1/new?dir=%2Frepo&name=Project&projectId=project-1",
);
});
});
@@ -24,5 +24,6 @@ export function buildWorkspaceArchiveRedirectRoute(input: {
return buildHostNewWorkspaceRoute(input.serverId, sourceDirectory, {
displayName: archivedWorkspace.projectDisplayName,
projectId: archivedWorkspace.projectId,
});
}