authorgravatar for 73941998+UtkarshUsername@users.noreply.github.comUtkarsh Patil <73941998+UtkarshUsername@users.noreply.github.com> 2026-07-29 21:54:11+05:30
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-07-29 18:24:11+02:00
logfaea70aebae41f1257140c6722f1d78f12f5eb74
treeddd51c42de41034e7908e0e863386936ee4caac2
parentd19039aeef6942e6eb204856c43b5354c0333e2d
signature Signed by PGP key B5690EEEBB952194

perf(server): merge separate staged/unstaged numstat calls into single diff HEAD --numstat (#4843)


2 files changed, 122 insertions(+), 28 deletions(-)

apps/server/src/vcs/GitVcsDriverCore.test.ts+46
......@@ -997,6 +997,52 @@ it.layer(TestLayer)("GitVcsDriver core integration", (it) => {
997997 assert.equal(status.aheadOfDefaultCount, 1);
998998 }),
999999 );
1000
1001 it.effect("reports combined staged and unstaged edits to the same file", () =>
1002 Effect.gen(function* () {
1003 const cwd = yield* makeTmpDir();
1004 yield* initRepoWithCommit(cwd);
1005 yield* writeTextFile(cwd, "feature.ts", "// line one\n");
1006 yield* git(cwd, ["add", "feature.ts"]);
1007 yield* git(cwd, ["commit", "-m", "add feature"]);
1008 yield* writeTextFile(cwd, "feature.ts", "// line one\n// line two\n");
1009 yield* git(cwd, ["add", "feature.ts"]);
1010 yield* writeTextFile(cwd, "feature.ts", "// line one\n// line two\n// line three\n");
1011
1012 const status = yield* (yield* GitVcsDriver.GitVcsDriver).statusDetails(cwd);
1013
1014 assert.equal(status.isRepo, true);
1015 assert.equal(status.hasWorkingTreeChanges, true);
1016 const file = status.workingTree.files.find((f) => f.path === "feature.ts");
1017 assert.ok(file);
1018 // HEAD has 1 line. Staged has 2 lines (+1). Unstaged has 3 lines (+2 from HEAD).
1019 // Combined net from HEAD: +2 insertions.
1020 assert.equal(file.insertions, 2);
1021 assert.equal(file.deletions, 0);
1022 }),
1023 );
1024
1025 it.effect("reports staged file counts on unborn HEAD without failing", () =>
1026 Effect.gen(function* () {
1027 const cwd = yield* makeTmpDir();
1028 const driver = yield* GitVcsDriver.GitVcsDriver;
1029 yield* driver.initRepo({ cwd });
1030 yield* git(cwd, ["config", "user.email", "test@test.com"]);
1031 yield* git(cwd, ["config", "user.name", "Test"]);
1032 yield* writeTextFile(cwd, "initial.ts", "// first file\n");
1033 yield* git(cwd, ["add", "initial.ts"]);
1034
1035 const status = yield* driver.statusDetails(cwd);
1036
1037 assert.equal(status.isRepo, true);
1038 assert.equal(status.workingTree.files.length, 1);
1039 const file = status.workingTree.files[0];
1040 if (file) {
1041 assert.equal(file.path, "initial.ts");
1042 assert.equal(file.insertions, 1);
1043 }
1044 }),
1045 );
10001046 });
10011047
10021048 describe("refName operations", () => {
apps/server/src/vcs/GitVcsDriverCore.ts+76-28
......@@ -415,6 +415,12 @@ function isMissingGitCwdError(error: GitCommandError): boolean {
415415function isNonRepositoryGitStderr(stderr: string): boolean {
416416 return stderr.toLowerCase().includes("not a git repository");
417417}
418function isUnbornHeadStderr(stderr: string): boolean {
419 return (
420 stderr.toLowerCase().includes("unknown revision") &&
421 stderr.toLowerCase().includes("path not in the working tree")
422 );
423}
418424
419425interface Trace2Monitor {
420426 readonly env: NodeJS.ProcessEnv;
......@@ -1511,27 +1517,73 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function*
15111517 });
15121518 }
15131519
1514 const [unstagedNumstatStdout, stagedNumstatStdout, defaultRefResult, hasPrimaryRemote] =
1515 yield* Effect.all(
1516 [
1517 runGitStdout("GitVcsDriver.statusDetails.unstagedNumstat", cwd, ["diff", "--numstat"]),
1518 runGitStdout("GitVcsDriver.statusDetails.stagedNumstat", cwd, [
1519 "diff",
1520 "--cached",
1521 "--numstat",
1522 ]),
1523 executeGit(
1524 "GitVcsDriver.statusDetails.defaultRef",
1525 cwd,
1526 ["symbolic-ref", "refs/remotes/origin/HEAD"],
1527 {
1528 allowNonZeroExit: true,
1529 },
1530 ),
1531 originRemoteExists(cwd).pipe(Effect.orElseSucceed(() => false)),
1532 ],
1533 { concurrency: "unbounded" },
1534 );
1520 const [numstatStdout, defaultRefResult, hasPrimaryRemote] = yield* Effect.all(
1521 [
1522 executeGitWithStableDiagnostics(
1523 "GitVcsDriver.statusDetails.numstat",
1524 cwd,
1525 ["diff", "HEAD", "--numstat"],
1526 { allowNonZeroExit: true },
1527 ).pipe(
1528 Effect.flatMap((result) => {
1529 if (result.exitCode === 0) return Effect.succeed(result.stdout);
1530 if (isUnbornHeadStderr(result.stderr)) {
1531 return Effect.map(
1532 Effect.all([
1533 runGitStdout("GitVcsDriver.statusDetails.numstat.unborn", cwd, [
1534 "diff",
1535 "--numstat",
1536 ]),
1537 runGitStdout("GitVcsDriver.statusDetails.numstat.unborn.staged", cwd, [
1538 "diff",
1539 "--cached",
1540 "--numstat",
1541 ]),
1542 ]),
1543 ([unstagedStdout, stagedStdout]) => {
1544 const staged = parseNumstatEntries(stagedStdout);
1545 const unstaged = parseNumstatEntries(unstagedStdout);
1546 const map = new Map<string, { insertions: number; deletions: number }>();
1547 for (const entry of [...staged, ...unstaged]) {
1548 const existing = map.get(entry.path) ?? {
1549 insertions: 0,
1550 deletions: 0,
1551 };
1552 existing.insertions += entry.insertions;
1553 existing.deletions += entry.deletions;
1554 map.set(entry.path, existing);
1555 }
1556 return Array.from(map.entries())
1557 .map(([p, s]) => `${s.insertions}\t${s.deletions}\t${p}`)
1558 .join("\n");
1559 },
1560 );
1561 }
1562 return Effect.fail(
1563 new GitCommandError({
1564 ...gitCommandContext({
1565 operation: "GitVcsDriver.statusDetails.numstat",
1566 cwd,
1567 args: ["diff", "HEAD", "--numstat"],
1568 }),
1569 detail: "git diff HEAD --numstat failed.",
1570 exitCode: result.exitCode,
1571 stdoutLength: result.stdout.length,
1572 stderrLength: result.stderr.length,
1573 }),
1574 );
1575 }),
1576 ),
1577 executeGit(
1578 "GitVcsDriver.statusDetails.defaultRef",
1579 cwd,
1580 ["symbolic-ref", "refs/remotes/origin/HEAD"],
1581 { allowNonZeroExit: true },
1582 ),
1583 originRemoteExists(cwd).pipe(Effect.orElseSucceed(() => false)),
1584 ],
1585 { concurrency: "unbounded" },
1586 );
15351587 const statusStdout = statusResult.stdout;
15361588 const defaultBranch =
15371589 defaultRefResult.exitCode === 0
......@@ -1592,14 +1644,10 @@ export const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function*
15921644 : yield* computeAheadCountAgainstBase(cwd, refName).pipe(Effect.orElseSucceed(() => 0));
15931645 }
15941646
1595 const stagedEntries = parseNumstatEntries(stagedNumstatStdout);
1596 const unstagedEntries = parseNumstatEntries(unstagedNumstatStdout);
1647 const numstatEntries = parseNumstatEntries(numstatStdout);
15971648 const fileStatMap = new Map<string, { insertions: number; deletions: number }>();
1598 for (const entry of [...stagedEntries, ...unstagedEntries]) {
1599 const existing = fileStatMap.get(entry.path) ?? { insertions: 0, deletions: 0 };
1600 existing.insertions += entry.insertions;
1601 existing.deletions += entry.deletions;
1602 fileStatMap.set(entry.path, existing);
1649 for (const entry of numstatEntries) {
1650 fileStatMap.set(entry.path, { insertions: entry.insertions, deletions: entry.deletions });
16031651 }
16041652
16051653 let insertions = 0;