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
1 change: 1 addition & 0 deletions apps/server/src/environment/ServerEnvironment.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ it.layer(NodeServices.layer)("ServerEnvironmentLive", (it) => {
expect(first.environmentId).toBe(second.environmentId);
expect(second.capabilities.repositoryIdentity).toBe(true);
expect(second.capabilities.connectionProbe).toBe(true);
expect(second.capabilities.worktreeSourceControl).toBe(true);
}),
);

Expand Down
1 change: 1 addition & 0 deletions apps/server/src/environment/ServerEnvironment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ export const make = Effect.gen(function* () {
capabilities: {
repositoryIdentity: true,
connectionProbe: true,
worktreeSourceControl: true,
},
};

Expand Down
40 changes: 40 additions & 0 deletions apps/web/src/components/WorktreeSourceControl.logic.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { describe, expect, it } from "vite-plus/test";

import { resolveWorktreeDiffSource } from "./WorktreeSourceControl.logic";

describe("resolveWorktreeDiffSource", () => {
it("uses the exact index-aware source when available", () => {
const sources = [
{ id: "legacy", kind: "working-tree" as const },
{ id: "staged", kind: "staged" as const },
{ id: "unstaged", kind: "unstaged" as const },
];

expect(resolveWorktreeDiffSource(sources, "unstaged")?.id).toBe("unstaged");
expect(resolveWorktreeDiffSource(sources, "staged")?.id).toBe("staged");
});

it("falls back to the legacy working-tree source for unstaged changes", () => {
const sources = [
{ id: "legacy", kind: "working-tree" as const },
{ id: "branch", kind: "branch-range" as const },
];

expect(resolveWorktreeDiffSource(sources, "unstaged")?.id).toBe("legacy");
});

it("does not present a combined legacy diff as staged-only changes", () => {
const sources = [{ id: "legacy", kind: "working-tree" as const }];

expect(resolveWorktreeDiffSource(sources, "staged")).toBeUndefined();
});

it("does not mask a missing source in an index-aware response", () => {
const sources = [
{ id: "legacy", kind: "working-tree" as const },
{ id: "staged", kind: "staged" as const },
];

expect(resolveWorktreeDiffSource(sources, "unstaged")).toBeUndefined();
});
});
23 changes: 23 additions & 0 deletions apps/web/src/components/WorktreeSourceControl.logic.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { ReviewDiffPreviewSourceKind } from "@t3tools/contracts";

export type WorktreeChangeScope = "staged" | "unstaged";

/**
* Older environments only return the combined `working-tree` review source.
* Treat it as the unstaged source when no index-aware sources are present so
* mixed-version remote environments retain a useful read-only diff.
*/
export function resolveWorktreeDiffSource<T extends { readonly kind: ReviewDiffPreviewSourceKind }>(
sources: readonly T[],
selectedScope: WorktreeChangeScope,
): T | undefined {
const exactSource = sources.find((source) => source.kind === selectedScope);
if (exactSource || selectedScope !== "unstaged") return exactSource;

const hasIndexAwareSources = sources.some(
(source) => source.kind === "staged" || source.kind === "unstaged",
);
return hasIndexAwareSources
? undefined
: sources.find((source) => source.kind === "working-tree");
}
Loading
Loading