Skip to content

Commit b2b43be

Browse files
tris203shivamhwp
andauthored
fix(server): preserve racy edits in review diff previews (#12613)
Co-authored-by: shivam <91240327+shivamhwp@users.noreply.github.com>
1 parent e67abcf commit b2b43be

2 files changed

Lines changed: 54 additions & 1 deletion

File tree

‎apps/server/src/vcs/GitVcsDriverCore.test.ts‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,6 +1449,51 @@ it.layer(TestLayer)("GitVcsDriver core integration", (it) => {
14491449
}),
14501450
);
14511451

1452+
for (const [timestamp, splitIndex] of [
1453+
[1_700_000_000, false],
1454+
[1_700_000_000.9999, false],
1455+
[1_700_000_000, true],
1456+
[1_700_000_000.9999, true],
1457+
] as const) {
1458+
it.effect(
1459+
`preserves same-size edits with a racy review index (${timestamp}, split: ${splitIndex})`,
1460+
() =>
1461+
Effect.gen(function* () {
1462+
const cwd = yield* makeTmpDir();
1463+
yield* initRepoWithCommit(cwd);
1464+
const driver = yield* GitVcsDriver.GitVcsDriver;
1465+
const fileSystem = yield* FileSystem.FileSystem;
1466+
const path = yield* Path.Path;
1467+
const filePath = path.join(cwd, "tracked.txt");
1468+
const indexPath = path.join(cwd, ".git", "index");
1469+
// Reproduce a same-timestamp edit without relying on filesystem clock resolution.
1470+
yield* git(cwd, ["config", "core.trustctime", "false"]);
1471+
yield* writeTextFile(cwd, "tracked.txt", "before\n");
1472+
yield* fileSystem.utimes(filePath, timestamp, timestamp);
1473+
yield* git(cwd, ["add", "tracked.txt"]);
1474+
yield* git(cwd, ["commit", "-m", "record racy file"]);
1475+
if (splitIndex) yield* git(cwd, ["update-index", "--split-index"]);
1476+
yield* fileSystem.utimes(indexPath, timestamp, timestamp);
1477+
const originalIndex = yield* fileSystem.readFile(indexPath);
1478+
const originalIndexMtime = (yield* fileSystem.stat(indexPath)).mtime;
1479+
yield* writeTextFile(cwd, "tracked.txt", "after!\n");
1480+
yield* fileSystem.utimes(filePath, timestamp, timestamp);
1481+
yield* writeTextFile(cwd, "untracked.txt", "new\n");
1482+
1483+
const preview = yield* driver.getReviewDiffPreview({ cwd });
1484+
const dirty = preview.sources.find((source) => source.kind === "working-tree")!;
1485+
assert.deepStrictEqual(dirty.files, [
1486+
{ path: "tracked.txt", previousPath: null, additions: 1, deletions: 1 },
1487+
{ path: "untracked.txt", previousPath: null, additions: 1, deletions: 0 },
1488+
]);
1489+
assert.include(dirty.diff, "-before");
1490+
assert.include(dirty.diff, "+after!");
1491+
assert.deepStrictEqual(yield* fileSystem.readFile(indexPath), originalIndex);
1492+
assert.deepStrictEqual((yield* fileSystem.stat(indexPath)).mtime, originalIndexMtime);
1493+
}),
1494+
);
1495+
}
1496+
14521497
it.effect("keeps complete stats for files beyond the combined patch limit", () =>
14531498
Effect.gen(function* () {
14541499
const cwd = yield* makeTmpDir();

‎apps/server/src/vcs/GitVcsDriverCore.ts‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2360,7 +2360,15 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function*
23602360
prefix: `t3code-review-index-${process.pid}-`,
23612361
});
23622362
const indexExists = yield* fileSystem.exists(indexPath);
2363-
if (indexExists) yield* fileSystem.copyFile(indexPath, tempIndexPath);
2363+
if (indexExists) {
2364+
const { mtime } = yield* fileSystem.stat(indexPath);
2365+
yield* fileSystem.copyFile(indexPath, tempIndexPath);
2366+
// A newer copy timestamp hides racily clean edits. Round down before Git reads or rewrites it.
2367+
const indexTime = Option.isSome(mtime)
2368+
? Math.max(0, Math.floor((mtime.value.getTime() - 1) / 1000))
2369+
: 0;
2370+
yield* fileSystem.utimes(tempIndexPath, indexTime, indexTime);
2371+
}
23642372
const env = { GIT_INDEX_FILE: tempIndexPath } satisfies NodeJS.ProcessEnv;
23652373
const tempIndexConfig = [
23662374
"-c",

0 commit comments

Comments
 (0)