Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions apps/code/src/main/services/archive/service.integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,20 @@ describe("ArchiveService integration", () => {
expect(archived.checkpointId).toBeTruthy();
expect(await pathExists(legacyPath)).toBe(false);
}));

it("archive succeeds when worktree was deleted externally", () =>
withTestContext({}, async (ctx) => {
const { worktreePath } = await ctx.setupWorktree("detached");

await fs.rm(worktreePath, { recursive: true, force: true });
expect(await pathExists(worktreePath)).toBe(false);

const archived = await ctx.service.archiveTask(ctx.archiveInput());

expect(archived.checkpointId).toBeNull();
expect(archived.branchName).toBeNull();
expect(ctx.archiveRepo.findAll()).toHaveLength(1);
}));
});

describe("local/cloud mode", () => {
Expand Down
59 changes: 38 additions & 21 deletions apps/code/src/main/services/archive/service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fs from "node:fs/promises";
import path from "node:path";
import { createGitClient } from "@posthog/git/client";
import { isGitRepository } from "@posthog/git/queries";
import {
CaptureCheckpointSaga,
deleteCheckpoint,
Expand Down Expand Up @@ -173,31 +174,47 @@ export class ArchiveService {

if (workspace.mode === "worktree" && worktree) {
const worktreePath = worktree.path;

const actualBranch = await this.getCurrentBranchName(worktreePath);
if (actualBranch && actualBranch !== "HEAD") {
archivedTask.branchName = actualBranch;
}

await step(
async () => {
if (!archivedTask.checkpointId) {
throw new Error("checkpointId must be set for worktree mode");
}
await this.captureWorktreeCheckpoint(
folderPath,
worktreePath,
archivedTask.checkpointId,
const worktreeIsValid = await isGitRepository(worktreePath).catch(
(error) => {
log.warn(
`Failed to check worktree at ${worktreePath}; treating as invalid`,
{ error },
);
},
async () => {
if (archivedTask.checkpointId) {
const git = createGitClient(folderPath);
await deleteCheckpoint(git, archivedTask.checkpointId);
}
return false;
},
);

if (!worktreeIsValid) {
log.warn(
`Worktree at ${worktreePath} is missing or not a git repository; skipping checkpoint capture`,
);
archivedTask.checkpointId = null;
} else {
const actualBranch = await this.getCurrentBranchName(worktreePath);
if (actualBranch && actualBranch !== "HEAD") {
archivedTask.branchName = actualBranch;
}

await step(
async () => {
if (!archivedTask.checkpointId) {
throw new Error("checkpointId must be set for worktree mode");
}
await this.captureWorktreeCheckpoint(
folderPath,
worktreePath,
archivedTask.checkpointId,
);
},
async () => {
if (archivedTask.checkpointId) {
const git = createGitClient(folderPath);
await deleteCheckpoint(git, archivedTask.checkpointId);
}
},
);
}
Comment on lines +187 to +216
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Prefer if/else over two separate if blocks

The two independent if (!worktreeIsValid) / if (worktreeIsValid) blocks are mutually exclusive and can be collapsed into a single if/else, removing the superfluous second condition check and making the intent clearer.

Suggested change
if (!worktreeIsValid) {
log.warn(
`Worktree at ${worktreePath} is missing or not a git repository; skipping checkpoint capture`,
);
archivedTask.checkpointId = null;
}
if (worktreeIsValid) {
const actualBranch = await this.getCurrentBranchName(worktreePath);
if (actualBranch && actualBranch !== "HEAD") {
archivedTask.branchName = actualBranch;
}
await step(
async () => {
if (!archivedTask.checkpointId) {
throw new Error("checkpointId must be set for worktree mode");
}
await this.captureWorktreeCheckpoint(
folderPath,
worktreePath,
archivedTask.checkpointId,
);
},
async () => {
if (archivedTask.checkpointId) {
const git = createGitClient(folderPath);
await deleteCheckpoint(git, archivedTask.checkpointId);
}
},
);
}
if (worktreeIsValid) {
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/code/src/main/services/archive/service.ts
Line: 187-218

Comment:
**Prefer `if/else` over two separate `if` blocks**

The two independent `if (!worktreeIsValid)` / `if (worktreeIsValid)` blocks are mutually exclusive and can be collapsed into a single `if/else`, removing the superfluous second condition check and making the intent clearer.

```suggestion
        if (worktreeIsValid) {
```

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit but +1


await step(
async () => {
await this.agentService.cancelSessionsByTaskId(taskId);
Expand Down
Loading