Skip to content

Commit 6c18861

Browse files
authored
feat: Add repository mismatch warning on folder select (#1181)
1. Detect repo from selected folder path via git.detectRepo tRPC query 2. Show warning UI when selected folder's repo doesn't match the task's linked repository 3. Allow user to go back or continue anyway with mismatched repo 4. Extract folder setup logic into proceedWithSetup callback for reuse
1 parent f473280 commit 6c18861

1 file changed

Lines changed: 68 additions & 5 deletions

File tree

apps/code/src/renderer/features/task-detail/components/WorkspaceSetupPrompt.tsx

Lines changed: 68 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { FolderPicker } from "@features/folder-picker/components/FolderPicker";
22
import { foldersApi } from "@features/folders/hooks/useFolders";
33
import { useEnsureWorkspace } from "@features/workspace/hooks/useWorkspace";
4-
import { Folder } from "@phosphor-icons/react";
5-
import { Box, Code, Flex, Spinner, Text } from "@radix-ui/themes";
4+
import { Folder, Warning } from "@phosphor-icons/react";
5+
import { Box, Button, Code, Flex, Spinner, Text } from "@radix-ui/themes";
6+
import { trpcVanilla } from "@renderer/trpc/client";
67
import type { Task } from "@shared/types";
78
import { logger } from "@utils/logger";
89
import { getTaskRepository } from "@utils/repository";
@@ -22,19 +23,21 @@ export function WorkspaceSetupPrompt({
2223
}: WorkspaceSetupPromptProps) {
2324
const [isSettingUp, setIsSettingUp] = useState(false);
2425
const [selectedPath, setSelectedPath] = useState("");
26+
const [pendingPath, setPendingPath] = useState<string | null>(null);
27+
const [detectedRepo, setDetectedRepo] = useState<string | null>(null);
2528
const repository = getTaskRepository(task);
2629
const { ensureWorkspace } = useEnsureWorkspace();
2730

28-
const handleFolderSelect = useCallback(
31+
const proceedWithSetup = useCallback(
2932
async (path: string) => {
33+
setPendingPath(null);
34+
setDetectedRepo(null);
3035
setSelectedPath(path);
3136
setIsSettingUp(true);
3237

3338
try {
3439
await foldersApi.addFolder(path);
35-
3640
await ensureWorkspace(taskId, path, "worktree");
37-
3841
log.info("Workspace setup complete", { taskId, path });
3942
} catch (error) {
4043
log.error("Failed to set up workspace", { error });
@@ -47,6 +50,47 @@ export function WorkspaceSetupPrompt({
4750
[taskId, ensureWorkspace],
4851
);
4952

53+
const handleFolderSelect = useCallback(
54+
async (path: string) => {
55+
if (repository) {
56+
let detected = null;
57+
try {
58+
detected = await trpcVanilla.git.detectRepo.query({
59+
directoryPath: path,
60+
});
61+
} catch (error) {
62+
log.warn("Failed to detect repo for mismatch check", {
63+
error,
64+
path,
65+
});
66+
}
67+
68+
if (detected) {
69+
const detectedFullName = `${detected.organization}/${detected.repository}`;
70+
if (detectedFullName !== repository) {
71+
setPendingPath(path);
72+
setDetectedRepo(detectedFullName);
73+
return;
74+
}
75+
}
76+
}
77+
78+
await proceedWithSetup(path);
79+
},
80+
[repository, proceedWithSetup],
81+
);
82+
83+
const handleConfirm = useCallback(async () => {
84+
if (pendingPath) {
85+
await proceedWithSetup(pendingPath);
86+
}
87+
}, [pendingPath, proceedWithSetup]);
88+
89+
const handleBack = useCallback(() => {
90+
setPendingPath(null);
91+
setDetectedRepo(null);
92+
}, []);
93+
5094
return (
5195
<Flex
5296
align="center"
@@ -62,6 +106,25 @@ export function WorkspaceSetupPrompt({
62106
Setting up workspace...
63107
</Text>
64108
</>
109+
) : pendingPath ? (
110+
<>
111+
<Warning size={32} weight="duotone" className="text-amber-9" />
112+
<Text size="3" weight="medium" className="text-gray-12">
113+
Repository mismatch
114+
</Text>
115+
<Text size="2" align="center" className="max-w-xs text-gray-11">
116+
This task is linked to <Code>{repository}</Code> but the selected
117+
folder belongs to <Code>{detectedRepo}</Code>.
118+
</Text>
119+
<Flex gap="2" mt="1">
120+
<Button variant="soft" color="gray" onClick={handleBack}>
121+
Go back
122+
</Button>
123+
<Button variant="solid" onClick={handleConfirm}>
124+
Continue anyway
125+
</Button>
126+
</Flex>
127+
</>
65128
) : (
66129
<>
67130
<Folder size={32} weight="duotone" className="text-gray-9" />

0 commit comments

Comments
 (0)