fix(worktree): gate sessions on bootstrap readiness (#1762)
Co-authored-by: Leonid Skorobogatyy <bash@opencode.itc.local> Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
This commit is contained in:
committed by
GitHub
co-authored by
Leonid Skorobogatyy
Bohdan Triapitsyn
parent
03e6f789a4
commit
8c1a24089d
@@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||
import { Icon } from "@/components/icon/Icon";
|
||||
@@ -9,7 +10,12 @@ import { useSessions } from '@/sync/sync-context';
|
||||
import { useDirectoryStore } from '@/stores/useDirectoryStore';
|
||||
import { useDeviceInfo } from '@/lib/device';
|
||||
import { checkIsGitRepository } from '@/lib/gitApi';
|
||||
import { getWorktreeSetupCommands, saveWorktreeSetupCommands } from '@/lib/openchamberConfig';
|
||||
import {
|
||||
getWorktreeSetupCommands,
|
||||
getWorktreeSetupWaitEnabled,
|
||||
saveWorktreeSetupCommands,
|
||||
saveWorktreeSetupWaitEnabled,
|
||||
} from '@/lib/openchamberConfig';
|
||||
import { listProjectWorktrees } from '@/lib/worktrees/worktreeManager';
|
||||
import { sessionEvents } from '@/lib/sessionEvents';
|
||||
import type { WorktreeMetadata } from '@/types/worktree';
|
||||
@@ -33,6 +39,7 @@ export const WorktreeSectionContent: React.FC<WorktreeSectionContentProps> = ({
|
||||
const homeDirectory = useDirectoryStore((state) => state.homeDirectory);
|
||||
|
||||
const [setupCommands, setSetupCommands] = React.useState<string[]>([]);
|
||||
const [waitForSetupCommands, setWaitForSetupCommands] = React.useState(false);
|
||||
const [isLoadingCommands, setIsLoadingCommands] = React.useState(false);
|
||||
const [isGitRepoLocal, setIsGitRepoLocal] = React.useState<boolean | null>(null);
|
||||
const [availableWorktrees, setAvailableWorktrees] = React.useState<WorktreeMetadata[]>([]);
|
||||
@@ -127,13 +134,18 @@ export const WorktreeSectionContent: React.FC<WorktreeSectionContentProps> = ({
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
const commands = await getWorktreeSetupCommands(projectRef);
|
||||
const [commands, waitForSetup] = await Promise.all([
|
||||
getWorktreeSetupCommands(projectRef),
|
||||
getWorktreeSetupWaitEnabled(projectRef),
|
||||
]);
|
||||
if (!cancelled) {
|
||||
setSetupCommands(commands.length > 0 ? commands : ['']);
|
||||
setWaitForSetupCommands(waitForSetup);
|
||||
}
|
||||
} catch {
|
||||
if (!cancelled) {
|
||||
setSetupCommands(['']);
|
||||
setWaitForSetupCommands(false);
|
||||
}
|
||||
} finally {
|
||||
if (!cancelled) {
|
||||
@@ -179,6 +191,13 @@ export const WorktreeSectionContent: React.FC<WorktreeSectionContentProps> = ({
|
||||
void persistSetupCommands(setupCommands);
|
||||
}, [persistSetupCommands, setupCommands]);
|
||||
|
||||
const handleWaitForSetupCommandsChange = React.useCallback((enabled: boolean) => {
|
||||
setWaitForSetupCommands(enabled);
|
||||
if (projectRef) {
|
||||
void saveWorktreeSetupWaitEnabled(projectRef, enabled);
|
||||
}
|
||||
}, [projectRef]);
|
||||
|
||||
// Delete worktree handler
|
||||
const handleDeleteWorktree = React.useCallback((worktree: WorktreeMetadata) => {
|
||||
const normalize = (value: string): string => value.replace(/\\/g, '/').replace(/\/+$/, '');
|
||||
@@ -322,6 +341,22 @@ export const WorktreeSectionContent: React.FC<WorktreeSectionContentProps> = ({
|
||||
<Icon name="add" className="h-3.5 w-3.5" />
|
||||
{t('settings.openchamber.worktrees.setup.addCommand')}
|
||||
</Button>
|
||||
<label
|
||||
data-settings-item="projects.worktree.setup.wait"
|
||||
className="flex cursor-pointer items-center gap-2 py-1.5"
|
||||
>
|
||||
<Checkbox
|
||||
checked={waitForSetupCommands}
|
||||
onChange={handleWaitForSetupCommandsChange}
|
||||
ariaLabel={t('settings.openchamber.worktrees.setup.waitForCommandsAria')}
|
||||
/>
|
||||
<span className={cn(
|
||||
'typography-ui-label font-normal',
|
||||
waitForSetupCommands ? 'text-foreground' : 'text-foreground/60'
|
||||
)}>
|
||||
{t('settings.openchamber.worktrees.setup.waitForCommands')}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -33,7 +33,8 @@ import * as sessionActions from '@/sync/session-actions';
|
||||
import { useConfigStore } from '@/stores/useConfigStore';
|
||||
import { validateWorktreeCreate, createWorktree } from '@/lib/worktrees/worktreeManager';
|
||||
import { withWorktreeUpstreamDefaults } from '@/lib/worktrees/worktreeCreate';
|
||||
import { getWorktreeSetupCommands } from '@/lib/openchamberConfig';
|
||||
import { waitForWorktreeBootstrap } from '@/lib/worktrees/worktreeBootstrap';
|
||||
import { getWorktreeSetupCommands, getWorktreeSetupWaitEnabled } from '@/lib/openchamberConfig';
|
||||
import { getRootBranch } from '@/lib/worktrees/worktreeStatus';
|
||||
import { generateBranchSlug } from '@/lib/git/branchNameGenerator';
|
||||
import { renderMagicPrompt } from '@/lib/magicPrompts';
|
||||
@@ -856,6 +857,10 @@ export function NewWorktreeDialog({
|
||||
let createdSessionId: string | null = null;
|
||||
|
||||
if (shouldCreateSession) {
|
||||
if (await getWorktreeSetupWaitEnabled(projectRef)) {
|
||||
await waitForWorktreeBootstrap(metadata.path);
|
||||
}
|
||||
|
||||
const sessionTitle = linkedIssue
|
||||
? `#${linkedIssue.number} ${linkedIssue.title}`.trim()
|
||||
: linkedPrState
|
||||
|
||||
Reference in New Issue
Block a user