fix(server): await git worktree creation before responding to client
Move createAgentWorktree() from the fire-and-forget background function into handleCreatePaseoWorktreeRequest so the worktree directory exists on disk before the client receives the response and navigates. Fixes ENOENT race when the app queries checkout status on a path that hasn't been created yet. Setup commands (npm install, etc.) remain background.
This commit is contained in:
@@ -173,7 +173,7 @@ import { ScheduleService } from "./schedule/service.js";
|
|||||||
import {
|
import {
|
||||||
assertSafeGitRef as assertWorktreeSafeGitRef,
|
assertSafeGitRef as assertWorktreeSafeGitRef,
|
||||||
buildAgentSessionConfig as buildWorktreeAgentSessionConfig,
|
buildAgentSessionConfig as buildWorktreeAgentSessionConfig,
|
||||||
createPaseoWorktreeInBackground as createWorktreeInBackgroundSession,
|
runWorktreeSetupInBackground as runWorktreeSetupInBackgroundSession,
|
||||||
handleCreatePaseoWorktreeRequest as handleCreateWorktreeRequest,
|
handleCreatePaseoWorktreeRequest as handleCreateWorktreeRequest,
|
||||||
handlePaseoWorktreeArchiveRequest as handleWorktreeArchiveRequest,
|
handlePaseoWorktreeArchiveRequest as handleWorktreeArchiveRequest,
|
||||||
handlePaseoWorktreeListRequest as handleWorktreeListRequest,
|
handlePaseoWorktreeListRequest as handleWorktreeListRequest,
|
||||||
@@ -6157,20 +6157,19 @@ export class Session {
|
|||||||
registerPendingWorktreeWorkspace: (options) =>
|
registerPendingWorktreeWorkspace: (options) =>
|
||||||
this.registerPendingWorktreeWorkspace(options),
|
this.registerPendingWorktreeWorkspace(options),
|
||||||
sessionLogger: this.sessionLogger,
|
sessionLogger: this.sessionLogger,
|
||||||
createPaseoWorktreeInBackground: (options) => this.createPaseoWorktreeInBackground(options),
|
runWorktreeSetupInBackground: (options) => this.runWorktreeSetupInBackground(options),
|
||||||
},
|
},
|
||||||
request,
|
request,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createPaseoWorktreeInBackground(options: {
|
private async runWorktreeSetupInBackground(options: {
|
||||||
requestCwd: string;
|
requestCwd: string;
|
||||||
repoRoot: string;
|
repoRoot: string;
|
||||||
baseBranch: string;
|
|
||||||
slug: string;
|
slug: string;
|
||||||
worktreePath: string;
|
worktreePath: string;
|
||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
return createWorktreeInBackgroundSession(
|
return runWorktreeSetupInBackgroundSession(
|
||||||
{
|
{
|
||||||
paseoHome: this.paseoHome,
|
paseoHome: this.paseoHome,
|
||||||
emitWorkspaceUpdateForCwd: (cwd) => this.emitWorkspaceUpdateForCwd(cwd),
|
emitWorkspaceUpdateForCwd: (cwd) => this.emitWorkspaceUpdateForCwd(cwd),
|
||||||
|
|||||||
@@ -109,10 +109,9 @@ type HandleCreatePaseoWorktreeRequestDependencies = {
|
|||||||
branchName: string;
|
branchName: string;
|
||||||
}) => Promise<PersistedWorkspaceRecord>;
|
}) => Promise<PersistedWorkspaceRecord>;
|
||||||
sessionLogger: Logger;
|
sessionLogger: Logger;
|
||||||
createPaseoWorktreeInBackground: (options: {
|
runWorktreeSetupInBackground: (options: {
|
||||||
requestCwd: string;
|
requestCwd: string;
|
||||||
repoRoot: string;
|
repoRoot: string;
|
||||||
baseBranch: string;
|
|
||||||
slug: string;
|
slug: string;
|
||||||
worktreePath: string;
|
worktreePath: string;
|
||||||
}) => Promise<void>;
|
}) => Promise<void>;
|
||||||
@@ -575,6 +574,15 @@ export async function handleCreatePaseoWorktreeRequest(
|
|||||||
worktreePath,
|
worktreePath,
|
||||||
branchName: normalizedSlug,
|
branchName: normalizedSlug,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await createAgentWorktree({
|
||||||
|
cwd: repoRoot,
|
||||||
|
branchName: normalizedSlug,
|
||||||
|
baseBranch,
|
||||||
|
worktreeSlug: normalizedSlug,
|
||||||
|
paseoHome: dependencies.paseoHome,
|
||||||
|
});
|
||||||
|
|
||||||
const descriptor = await dependencies.describeWorkspaceRecord(workspace);
|
const descriptor = await dependencies.describeWorkspaceRecord(workspace);
|
||||||
dependencies.emit({
|
dependencies.emit({
|
||||||
type: "create_paseo_worktree_response",
|
type: "create_paseo_worktree_response",
|
||||||
@@ -586,10 +594,9 @@ export async function handleCreatePaseoWorktreeRequest(
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
void dependencies.createPaseoWorktreeInBackground({
|
void dependencies.runWorktreeSetupInBackground({
|
||||||
requestCwd: request.cwd,
|
requestCwd: request.cwd,
|
||||||
repoRoot,
|
repoRoot,
|
||||||
baseBranch,
|
|
||||||
slug: normalizedSlug,
|
slug: normalizedSlug,
|
||||||
worktreePath,
|
worktreePath,
|
||||||
});
|
});
|
||||||
@@ -611,12 +618,11 @@ export async function handleCreatePaseoWorktreeRequest(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createPaseoWorktreeInBackground(
|
export async function runWorktreeSetupInBackground(
|
||||||
dependencies: CreatePaseoWorktreeInBackgroundDependencies,
|
dependencies: CreatePaseoWorktreeInBackgroundDependencies,
|
||||||
options: {
|
options: {
|
||||||
requestCwd: string;
|
requestCwd: string;
|
||||||
repoRoot: string;
|
repoRoot: string;
|
||||||
baseBranch: string;
|
|
||||||
slug: string;
|
slug: string;
|
||||||
worktreePath: string;
|
worktreePath: string;
|
||||||
},
|
},
|
||||||
@@ -624,14 +630,6 @@ export async function createPaseoWorktreeInBackground(
|
|||||||
let setupTerminalId: string | null = null;
|
let setupTerminalId: string | null = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await createAgentWorktree({
|
|
||||||
cwd: options.repoRoot,
|
|
||||||
branchName: options.slug,
|
|
||||||
baseBranch: options.baseBranch,
|
|
||||||
worktreeSlug: options.slug,
|
|
||||||
paseoHome: dependencies.paseoHome,
|
|
||||||
});
|
|
||||||
|
|
||||||
const setupCommands = getWorktreeSetupCommands(options.worktreePath);
|
const setupCommands = getWorktreeSetupCommands(options.worktreePath);
|
||||||
if (setupCommands.length > 0 && dependencies.terminalManager) {
|
if (setupCommands.length > 0 && dependencies.terminalManager) {
|
||||||
const runtimeEnv = await resolveWorktreeRuntimeEnv({
|
const runtimeEnv = await resolveWorktreeRuntimeEnv({
|
||||||
@@ -667,7 +665,7 @@ export async function createPaseoWorktreeInBackground(
|
|||||||
worktreePath: options.worktreePath,
|
worktreePath: options.worktreePath,
|
||||||
setupTerminalId,
|
setupTerminalId,
|
||||||
},
|
},
|
||||||
"Background worktree creation failed",
|
"Background worktree setup failed",
|
||||||
);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
await dependencies.emitWorkspaceUpdateForCwd(options.worktreePath);
|
await dependencies.emitWorkspaceUpdateForCwd(options.worktreePath);
|
||||||
|
|||||||
Reference in New Issue
Block a user