Fix workspace diff stat watch refresh
This commit is contained in:
@@ -731,9 +731,54 @@ describe("WorkspaceGitServiceImpl", () => {
|
|||||||
watchCallbacks[0]?.();
|
watchCallbacks[0]?.();
|
||||||
|
|
||||||
expect(listener).toHaveBeenCalledTimes(1);
|
expect(listener).toHaveBeenCalledTimes(1);
|
||||||
expect(refreshSpy).toHaveBeenCalledWith("/tmp/repo");
|
expect(refreshSpy).toHaveBeenCalledWith("/tmp/repo", {
|
||||||
|
force: true,
|
||||||
|
reason: "working-tree-watch",
|
||||||
|
});
|
||||||
|
|
||||||
subscription.unsubscribe();
|
subscription.unsubscribe();
|
||||||
service.dispose();
|
service.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("working tree changes force a fresh diff stat for workspace subscribers", async () => {
|
||||||
|
const watchCallbacks: Array<{ path: string; callback: () => void }> = [];
|
||||||
|
const watch = vi.fn(
|
||||||
|
(watchPath: string, _options: { recursive: boolean }, callback: () => void) => {
|
||||||
|
watchCallbacks.push({ path: watchPath, callback });
|
||||||
|
return createWatcher() as any;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const getCheckoutShortstat = vi
|
||||||
|
.fn()
|
||||||
|
.mockResolvedValueOnce({ additions: 1, deletions: 0 })
|
||||||
|
.mockResolvedValueOnce({ additions: 8, deletions: 3 });
|
||||||
|
const service = createService({ getCheckoutShortstat, watch });
|
||||||
|
const workspaceListener = vi.fn();
|
||||||
|
|
||||||
|
const workspaceSubscription = await service.subscribe({ cwd: "/tmp/repo" }, workspaceListener);
|
||||||
|
const diffSubscription = await service.requestWorkingTreeWatch("/tmp/repo", vi.fn());
|
||||||
|
|
||||||
|
expect(workspaceSubscription.initial.git.diffStat).toEqual({ additions: 1, deletions: 0 });
|
||||||
|
const repoRootWatch = watchCallbacks.find((entry) => entry.path === "/tmp/repo");
|
||||||
|
expect(repoRootWatch).toBeDefined();
|
||||||
|
|
||||||
|
repoRootWatch?.callback();
|
||||||
|
await vi.advanceTimersByTimeAsync(500);
|
||||||
|
await flushPromises();
|
||||||
|
|
||||||
|
expect(getCheckoutShortstat).toHaveBeenLastCalledWith(
|
||||||
|
"/tmp/repo",
|
||||||
|
{ paseoHome: "/tmp/paseo-test" },
|
||||||
|
{ force: true },
|
||||||
|
);
|
||||||
|
expect(workspaceListener).toHaveBeenCalledWith(
|
||||||
|
createSnapshot("/tmp/repo", {
|
||||||
|
git: { diffStat: { additions: 8, deletions: 3 } },
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
diffSubscription.unsubscribe();
|
||||||
|
workspaceSubscription.unsubscribe();
|
||||||
|
service.dispose();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -784,7 +784,10 @@ export class WorkspaceGitServiceImpl implements WorkspaceGitService {
|
|||||||
const missingRepoCoverage = repoRoot === null || !hasRecursiveRepoCoverage;
|
const missingRepoCoverage = repoRoot === null || !hasRecursiveRepoCoverage;
|
||||||
if (target.watchers.length === 0 || missingRepoCoverage) {
|
if (target.watchers.length === 0 || missingRepoCoverage) {
|
||||||
target.fallbackRefreshInterval = setInterval(() => {
|
target.fallbackRefreshInterval = setInterval(() => {
|
||||||
this.scheduleWorkspaceRefresh(cwd);
|
this.scheduleWorkspaceRefresh(cwd, {
|
||||||
|
force: true,
|
||||||
|
reason: "working-tree-watch-fallback",
|
||||||
|
});
|
||||||
for (const listener of target.listeners) {
|
for (const listener of target.listeners) {
|
||||||
listener();
|
listener();
|
||||||
}
|
}
|
||||||
@@ -894,7 +897,10 @@ export class WorkspaceGitServiceImpl implements WorkspaceGitService {
|
|||||||
void this.runRepoFetch(repoTarget);
|
void this.runRepoFetch(repoTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
private scheduleWorkspaceRefresh(targetOrCwd: WorkspaceGitTarget | string): void {
|
private scheduleWorkspaceRefresh(
|
||||||
|
targetOrCwd: WorkspaceGitTarget | string,
|
||||||
|
options?: { force?: boolean; reason?: string },
|
||||||
|
): void {
|
||||||
const target =
|
const target =
|
||||||
typeof targetOrCwd === "string"
|
typeof targetOrCwd === "string"
|
||||||
? this.workspaceTargets.get(normalizeWorkspaceId(targetOrCwd))
|
? this.workspaceTargets.get(normalizeWorkspaceId(targetOrCwd))
|
||||||
@@ -910,9 +916,9 @@ export class WorkspaceGitServiceImpl implements WorkspaceGitService {
|
|||||||
target.debounceTimer = setTimeout(() => {
|
target.debounceTimer = setTimeout(() => {
|
||||||
target.debounceTimer = null;
|
target.debounceTimer = null;
|
||||||
void this.refreshWorkspaceTarget(target, {
|
void this.refreshWorkspaceTarget(target, {
|
||||||
force: false,
|
force: options?.force === true,
|
||||||
includeGitHub: false,
|
includeGitHub: false,
|
||||||
reason: "watch",
|
reason: options?.reason ?? "watch",
|
||||||
notify: true,
|
notify: true,
|
||||||
});
|
});
|
||||||
}, WORKSPACE_GIT_WATCH_DEBOUNCE_MS);
|
}, WORKSPACE_GIT_WATCH_DEBOUNCE_MS);
|
||||||
@@ -990,7 +996,10 @@ export class WorkspaceGitServiceImpl implements WorkspaceGitService {
|
|||||||
if (process.platform === "linux" && target.repoWatchPath) {
|
if (process.platform === "linux" && target.repoWatchPath) {
|
||||||
void this.refreshLinuxRepoTreeWatchers(target);
|
void this.refreshLinuxRepoTreeWatchers(target);
|
||||||
}
|
}
|
||||||
this.scheduleWorkspaceRefresh(cwd);
|
this.scheduleWorkspaceRefresh(cwd, {
|
||||||
|
force: true,
|
||||||
|
reason: "working-tree-watch",
|
||||||
|
});
|
||||||
for (const listener of target.listeners) {
|
for (const listener of target.listeners) {
|
||||||
listener();
|
listener();
|
||||||
}
|
}
|
||||||
@@ -1264,7 +1273,8 @@ export class WorkspaceGitServiceImpl implements WorkspaceGitService {
|
|||||||
): Promise<WorkspaceGitRuntimeSnapshot> {
|
): Promise<WorkspaceGitRuntimeSnapshot> {
|
||||||
const now = this.deps.now();
|
const now = this.deps.now();
|
||||||
target.lastShellOutAtMs = now.getTime();
|
target.lastShellOutAtMs = now.getTime();
|
||||||
if (request.force) {
|
const forceGitHub = request.force && request.includeGitHub;
|
||||||
|
if (forceGitHub) {
|
||||||
this.deps.github.invalidate({ cwd: target.cwd });
|
this.deps.github.invalidate({ cwd: target.cwd });
|
||||||
}
|
}
|
||||||
const snapshot = await loadWorkspaceGitRuntimeSnapshot(
|
const snapshot = await loadWorkspaceGitRuntimeSnapshot(
|
||||||
@@ -1272,7 +1282,7 @@ export class WorkspaceGitServiceImpl implements WorkspaceGitService {
|
|||||||
{ paseoHome: this.paseoHome },
|
{ paseoHome: this.paseoHome },
|
||||||
now,
|
now,
|
||||||
this.deps,
|
this.deps,
|
||||||
{ force: request.force, reason: request.reason },
|
{ force: request.force, forceGitHub, reason: request.reason },
|
||||||
);
|
);
|
||||||
target.latestSnapshotLoadedAtMs = now.getTime();
|
target.latestSnapshotLoadedAtMs = now.getTime();
|
||||||
return snapshot;
|
return snapshot;
|
||||||
@@ -1430,7 +1440,7 @@ async function loadWorkspaceGitRuntimeSnapshot(
|
|||||||
WorkspaceGitServiceDependencies,
|
WorkspaceGitServiceDependencies,
|
||||||
"getCheckoutStatus" | "getCheckoutShortstat" | "getPullRequestStatus" | "github"
|
"getCheckoutStatus" | "getCheckoutShortstat" | "getPullRequestStatus" | "github"
|
||||||
>,
|
>,
|
||||||
options?: { force?: boolean; reason?: string },
|
options?: { force?: boolean; forceGitHub?: boolean; reason?: string },
|
||||||
): Promise<WorkspaceGitRuntimeSnapshot> {
|
): Promise<WorkspaceGitRuntimeSnapshot> {
|
||||||
const checkoutStatus = await deps.getCheckoutStatus(cwd, context);
|
const checkoutStatus = await deps.getCheckoutStatus(cwd, context);
|
||||||
if (!checkoutStatus.isGit) {
|
if (!checkoutStatus.isGit) {
|
||||||
@@ -1444,7 +1454,7 @@ async function loadWorkspaceGitRuntimeSnapshot(
|
|||||||
remoteUrl: checkoutStatus.remoteUrl,
|
remoteUrl: checkoutStatus.remoteUrl,
|
||||||
now,
|
now,
|
||||||
deps,
|
deps,
|
||||||
force: options?.force,
|
force: options?.forceGitHub,
|
||||||
reason: options?.reason,
|
reason: options?.reason,
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
|||||||
Reference in New Issue
Block a user