mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-14 13:22:37 +00:00
Show checkout patch lines with external Git diff commands configured (#6562)
* fix(server): parse Git patches without external diff commands * test(server): keep diff command checks aligned with parsed patches The external diff regression fix intentionally disables helper commands. Keep the existing large-file batching assertions aligned with that command while preserving their patch, omission, and concurrency checks. Co-authored-by: 见安 <73627805+Mar-garet@users.noreply.github.com> --------- Co-authored-by: 见安 <73627805+Mar-garet@users.noreply.github.com> Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { existsSync, mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { getCheckoutDiff, getCommitFileDiff } from "./checkout-git.js";
|
||||
|
||||
const repos: string[] = [];
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllEnvs();
|
||||
for (const repo of repos.splice(0)) rmSync(repo, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
@@ -62,6 +63,95 @@ function createChangedRepo(config: string): string {
|
||||
return cwd;
|
||||
}
|
||||
|
||||
function createExternalDiffCommand() {
|
||||
const directory = realpathSync.native(mkdtempSync(join(tmpdir(), "checkout-external-diff-")));
|
||||
repos.push(directory);
|
||||
const script = join(directory, "external-diff.cjs");
|
||||
const marker = join(directory, "invoked");
|
||||
writeFileSync(
|
||||
script,
|
||||
'require("node:fs").writeFileSync(process.argv[2], "invoked");\n' +
|
||||
'process.stdout.write("CUSTOM EXTERNAL DIFF\\n");\n',
|
||||
);
|
||||
const command = [process.execPath, script, marker]
|
||||
.map((argument) => `'${argument.replaceAll("'", "'\\''")}'`)
|
||||
.join(" ");
|
||||
return { command, marker };
|
||||
}
|
||||
|
||||
function createExternalDiffRepo() {
|
||||
vi.stubEnv("GIT_EXTERNAL_DIFF", undefined);
|
||||
const cwd = createChangedRepo("color.diff=always");
|
||||
const { command, marker } = createExternalDiffCommand();
|
||||
git(cwd, "config", "diff.external", command);
|
||||
expect(git(cwd, "diff", "HEAD", "--", "file.txt")).toBe("CUSTOM EXTERNAL DIFF\n");
|
||||
expect(existsSync(marker)).toBe(true);
|
||||
rmSync(marker);
|
||||
return { cwd, command, marker };
|
||||
}
|
||||
|
||||
function expectStandardPatch(result: Awaited<ReturnType<typeof getCheckoutDiff>>) {
|
||||
expect(result.structured).toMatchObject([
|
||||
{
|
||||
path: "file.txt",
|
||||
additions: 1,
|
||||
deletions: 1,
|
||||
status: "ok",
|
||||
hunks: [
|
||||
{
|
||||
lines: [
|
||||
{ type: "header", content: "@@ -1 +1 @@" },
|
||||
{ type: "remove", content: "before" },
|
||||
{ type: "add", content: "after" },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
it("returns Git patch hunks when a repository configures an external diff command", async () => {
|
||||
const { cwd, command, marker } = createExternalDiffRepo();
|
||||
|
||||
const result = await getCheckoutDiff(cwd, { mode: "uncommitted", includeStructured: true });
|
||||
|
||||
expectStandardPatch(result);
|
||||
expect(existsSync(marker)).toBe(false);
|
||||
expect(git(cwd, "config", "--get", "diff.external").trim()).toBe(command);
|
||||
});
|
||||
|
||||
it("returns Git patch hunks against the base branch with an external diff command", async () => {
|
||||
const { cwd, command, marker } = createExternalDiffRepo();
|
||||
git(cwd, "checkout", "-b", "feature");
|
||||
git(cwd, "add", ".");
|
||||
git(cwd, "-c", "commit.gpgsign=false", "commit", "-m", "edit");
|
||||
|
||||
const result = await getCheckoutDiff(cwd, {
|
||||
mode: "base",
|
||||
baseRef: "main",
|
||||
includeStructured: true,
|
||||
});
|
||||
|
||||
expectStandardPatch(result);
|
||||
expect(existsSync(marker)).toBe(false);
|
||||
expect(git(cwd, "config", "--get", "diff.external").trim()).toBe(command);
|
||||
});
|
||||
|
||||
it("returns Git patch hunks when GIT_EXTERNAL_DIFF configures the external command", async () => {
|
||||
const cwd = createChangedRepo("color.diff=always");
|
||||
const { command, marker } = createExternalDiffCommand();
|
||||
vi.stubEnv("GIT_EXTERNAL_DIFF", command);
|
||||
expect(git(cwd, "diff", "HEAD", "--", "file.txt")).toBe("CUSTOM EXTERNAL DIFF\n");
|
||||
expect(existsSync(marker)).toBe(true);
|
||||
rmSync(marker);
|
||||
|
||||
const result = await getCheckoutDiff(cwd, { mode: "uncommitted", includeStructured: true });
|
||||
|
||||
expectStandardPatch(result);
|
||||
expect(existsSync(marker)).toBe(false);
|
||||
expect(process.env.GIT_EXTERNAL_DIFF).toBe(command);
|
||||
});
|
||||
|
||||
describe.each(["diff.mnemonicPrefix=true", "color.diff=always"])(
|
||||
"patch format with %s",
|
||||
(config) => {
|
||||
|
||||
@@ -1627,9 +1627,11 @@ const x = 1;
|
||||
expect(diff.diff).toContain("# generated.js: diff too large omitted");
|
||||
expect(diff.diff).toContain(`-export const value = "old";`);
|
||||
expect(diff.diff).toContain(`+export const value = "new";`);
|
||||
expect(commands).toContain("diff --no-color --src-prefix=a/ --dst-prefix=b/ --numstat HEAD");
|
||||
expect(commands).toContain(
|
||||
"diff --no-color --src-prefix=a/ --dst-prefix=b/ HEAD -- :(literal)generated.js :(literal)small.ts",
|
||||
"diff --no-ext-diff --no-color --src-prefix=a/ --dst-prefix=b/ --numstat HEAD",
|
||||
);
|
||||
expect(commands).toContain(
|
||||
"diff --no-ext-diff --no-color --src-prefix=a/ --dst-prefix=b/ HEAD -- :(literal)generated.js :(literal)small.ts",
|
||||
);
|
||||
expect(metrics.maxConcurrent).toBeLessThanOrEqual(8);
|
||||
});
|
||||
|
||||
@@ -637,7 +637,7 @@ function normalizeNumstatPath(pathField: string): string {
|
||||
}
|
||||
|
||||
// Parsed patches need a stable wire format regardless of terminal presentation settings.
|
||||
const GIT_PATCH_FORMAT_ARGS = ["--no-color", "--src-prefix=a/", "--dst-prefix=b/"];
|
||||
const GIT_PATCH_FORMAT_ARGS = ["--no-ext-diff", "--no-color", "--src-prefix=a/", "--dst-prefix=b/"];
|
||||
|
||||
function buildGitDiffArgs(args: { ignoreWhitespace?: boolean; extra: string[] }): string[] {
|
||||
return [
|
||||
|
||||
Reference in New Issue
Block a user