mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
fix(server): bypass diff cache on working-tree watch refresh
CheckoutDiffManager.refreshTarget was calling workspaceGitService.getCheckoutDiff
without forcing a cache bypass, so watch-fired refreshes within the 15s consumer
TTL returned the pre-mutation cached diff — fingerprint matched, no
checkout_diff_update was emitted, and the sidebar diff appeared frozen while an
agent edited files. Route watch-fired refreshes through the service with
{ force: true, reason: "working-tree-watch" } so they always recompute.
This commit is contained in:
@@ -115,6 +115,7 @@ describe("CheckoutDiffManager", () => {
|
||||
expect(workspaceGitService.getCheckoutDiff).toHaveBeenCalledWith(
|
||||
"/tmp/repo",
|
||||
expect.objectContaining({ mode: "uncommitted", includeStructured: true }),
|
||||
undefined,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -157,6 +158,49 @@ describe("CheckoutDiffManager", () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("watch-triggered refresh forces a cache bypass on getCheckoutDiff", async () => {
|
||||
const getCheckoutDiff = vi
|
||||
.fn()
|
||||
.mockResolvedValueOnce({
|
||||
diff: "",
|
||||
structured: [{ path: "a.ts", additions: 1, deletions: 0, status: "modified" }],
|
||||
})
|
||||
.mockResolvedValueOnce({
|
||||
diff: "",
|
||||
structured: [{ path: "b.ts", additions: 2, deletions: 0, status: "modified" }],
|
||||
});
|
||||
|
||||
const { manager, getOnChange } = createManager({
|
||||
getCheckoutDiffImplementation: getCheckoutDiff,
|
||||
});
|
||||
|
||||
await manager.subscribe(
|
||||
{
|
||||
cwd: "/tmp/repo/packages/server",
|
||||
compare: { mode: "uncommitted" },
|
||||
},
|
||||
vi.fn(),
|
||||
);
|
||||
|
||||
expect(getCheckoutDiff).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
"/tmp/repo",
|
||||
expect.objectContaining({ mode: "uncommitted" }),
|
||||
undefined,
|
||||
);
|
||||
|
||||
const onChange = getOnChange();
|
||||
onChange?.();
|
||||
await vi.advanceTimersByTimeAsync(150);
|
||||
|
||||
expect(getCheckoutDiff).toHaveBeenCalledTimes(2);
|
||||
const watchFiredCall = getCheckoutDiff.mock.calls[1];
|
||||
expect(watchFiredCall[2]).toEqual({
|
||||
force: true,
|
||||
reason: expect.stringContaining("working-tree"),
|
||||
});
|
||||
});
|
||||
|
||||
test("falls back to cwd when the working tree watch returns no repo root", async () => {
|
||||
const { manager, workspaceGitService } = createManager({ repoRoot: null });
|
||||
|
||||
@@ -171,6 +215,7 @@ describe("CheckoutDiffManager", () => {
|
||||
expect(workspaceGitService.getCheckoutDiff).toHaveBeenCalledWith(
|
||||
"/tmp/plain",
|
||||
expect.objectContaining({ mode: "uncommitted", includeStructured: true }),
|
||||
undefined,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -164,16 +164,22 @@ export class CheckoutDiffManager {
|
||||
private async computeCheckoutDiffSnapshot(
|
||||
cwd: string,
|
||||
compare: CheckoutDiffCompareInput,
|
||||
options?: { diffCwd?: string },
|
||||
options?: { diffCwd?: string; force?: boolean; reason?: string },
|
||||
): Promise<CheckoutDiffSnapshotPayload> {
|
||||
const diffCwd = options?.diffCwd ?? cwd;
|
||||
try {
|
||||
const diffResult = await this.workspaceGitService.getCheckoutDiff(diffCwd, {
|
||||
mode: compare.mode,
|
||||
baseRef: compare.baseRef,
|
||||
ignoreWhitespace: compare.ignoreWhitespace,
|
||||
includeStructured: true,
|
||||
});
|
||||
const diffResult = await this.workspaceGitService.getCheckoutDiff(
|
||||
diffCwd,
|
||||
{
|
||||
mode: compare.mode,
|
||||
baseRef: compare.baseRef,
|
||||
ignoreWhitespace: compare.ignoreWhitespace,
|
||||
includeStructured: true,
|
||||
},
|
||||
options?.force
|
||||
? { force: true, reason: options.reason ?? "checkout-diff-refresh" }
|
||||
: undefined,
|
||||
);
|
||||
const files = [...(diffResult.structured ?? [])];
|
||||
files.sort((a, b) => {
|
||||
if (a.path === b.path) return 0;
|
||||
@@ -204,6 +210,8 @@ export class CheckoutDiffManager {
|
||||
target.refreshQueued = false;
|
||||
const snapshot = await this.computeCheckoutDiffSnapshot(target.cwd, target.compare, {
|
||||
diffCwd: target.diffCwd,
|
||||
force: true,
|
||||
reason: "working-tree-watch",
|
||||
});
|
||||
target.latestPayload = snapshot;
|
||||
const fingerprint = JSON.stringify(snapshot);
|
||||
|
||||
Reference in New Issue
Block a user