diff --git a/apps/desktop/src/lib/trpc/routers/workspaces/procedures/create.ts b/apps/desktop/src/lib/trpc/routers/workspaces/procedures/create.ts index a050b25fc87..72154634f12 100644 --- a/apps/desktop/src/lib/trpc/routers/workspaces/procedures/create.ts +++ b/apps/desktop/src/lib/trpc/routers/workspaces/procedures/create.ts @@ -267,6 +267,7 @@ export const createCreateProcedures = () => { branchName: z.string().optional(), baseBranch: z.string().optional(), useExistingBranch: z.boolean().optional(), + applyPrefix: z.boolean().optional().default(true), }), ) .mutation(async ({ input }) => { @@ -302,30 +303,36 @@ export const createCreateProcedures = () => { const { local, remote } = await listBranches(project.mainRepoPath); const existingBranches = [...local, ...remote]; - const globalSettings = localDb.select().from(settings).get(); - const projectOverrides = project.branchPrefixMode != null; - const prefixMode = projectOverrides - ? project.branchPrefixMode - : (globalSettings?.branchPrefixMode ?? "none"); - const customPrefix = projectOverrides - ? project.branchPrefixCustom - : globalSettings?.branchPrefixCustom; - - const rawPrefix = await getBranchPrefix({ - repoPath: project.mainRepoPath, - mode: prefixMode, - customPrefix, - }); - const rawAuthorPrefix = rawPrefix - ? sanitizeAuthorPrefix(rawPrefix) - : undefined; + let branchPrefix: string | undefined; + if (input.applyPrefix) { + const globalSettings = localDb.select().from(settings).get(); + const projectOverrides = project.branchPrefixMode != null; + const prefixMode = projectOverrides + ? project.branchPrefixMode + : (globalSettings?.branchPrefixMode ?? "none"); + const customPrefix = projectOverrides + ? project.branchPrefixCustom + : globalSettings?.branchPrefixCustom; + + const rawPrefix = await getBranchPrefix({ + repoPath: project.mainRepoPath, + mode: prefixMode, + customPrefix, + }); + const sanitizedPrefix = rawPrefix + ? sanitizeAuthorPrefix(rawPrefix) + : undefined; - const existingSet = new Set( - existingBranches.map((b) => b.toLowerCase()), - ); - const prefixWouldCollide = - rawAuthorPrefix && existingSet.has(rawAuthorPrefix.toLowerCase()); - const authorPrefix = prefixWouldCollide ? undefined : rawAuthorPrefix; + const existingSet = new Set( + existingBranches.map((b) => b.toLowerCase()), + ); + const prefixWouldCollide = + sanitizedPrefix && existingSet.has(sanitizedPrefix.toLowerCase()); + branchPrefix = prefixWouldCollide ? undefined : sanitizedPrefix; + } + + const withPrefix = (name: string): string => + branchPrefix ? `${branchPrefix}/${name}` : name; let branch: string; if (existingBranchName) { @@ -336,10 +343,12 @@ export const createCreateProcedures = () => { } branch = existingBranchName; } else if (input.branchName?.trim()) { - const sanitized = sanitizeBranchName(input.branchName); - branch = authorPrefix ? `${authorPrefix}/${sanitized}` : sanitized; + branch = withPrefix(sanitizeBranchName(input.branchName)); } else { - branch = generateBranchName({ existingBranches, authorPrefix }); + branch = generateBranchName({ + existingBranches, + authorPrefix: branchPrefix, + }); } const worktreePath = join( diff --git a/apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx b/apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx index 3c62c54a302..ce724970e92 100644 --- a/apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx +++ b/apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx @@ -47,17 +47,8 @@ import { } from "shared/utils/branch"; import { ExistingWorktreesList } from "./components/ExistingWorktreesList"; -function generateBranchFromTitle({ - title, - prefix, -}: { - title: string; - prefix: string | null; -}): string { - const slug = sanitizeSegment(title); - if (!slug) return ""; - - return prefix ? `${prefix}/${slug}` : slug; +function generateSlugFromTitle(title: string): string { + return sanitizeSegment(title); } type Mode = "existing" | "new" | "cloud"; @@ -139,13 +130,16 @@ export function NewWorkspaceModal() { setBaseBranch(null); }, [selectedProjectId]); - const generatedBranchName = generateBranchFromTitle({ - title, - prefix: resolvedPrefix, - }); - const branchNameToCreate = branchNameEdited + const branchSlug = branchNameEdited ? sanitizeBranchName(branchName) - : generatedBranchName; + : generateSlugFromTitle(title); + + const applyPrefix = !branchNameEdited; + + const branchPreview = + branchSlug && applyPrefix && resolvedPrefix + ? `${resolvedPrefix}/${branchSlug}` + : branchSlug; const resetForm = () => { setSelectedProjectId(null); @@ -229,8 +223,9 @@ export function NewWorkspaceModal() { const result = await createWorkspace.mutateAsync({ projectId: selectedProjectId, name: workspaceName, - branchName: branchNameToCreate || undefined, + branchName: branchSlug || undefined, baseBranch: effectiveBaseBranch || undefined, + applyPrefix, }); handleClose(); @@ -356,7 +351,7 @@ export function NewWorkspaceModal() {

- {branchNameToCreate || "branch-name"} + {branchPreview || "branch-name"} from {effectiveBaseBranch} @@ -386,9 +381,7 @@ export function NewWorkspaceModal() { id="branch" className="h-8 text-sm font-mono" placeholder="auto-generated" - value={ - branchNameEdited ? branchName : generatedBranchName - } + value={branchNameEdited ? branchName : branchPreview} onChange={(e) => handleBranchNameChange(e.target.value) }