fix(cli): read the migration history with -z rather than core.quotePath

`core.quotePath=false` only stops git C-quoting non-ASCII bytes. A path holding
`"`, `\` or a control character comes back quoted regardless, so it still
matches nothing the caller holds and still reads as never recorded. `-z` emits
every path raw, NUL-separated, which covers all three.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
hugocasa
2026-08-28 16:43:05 +02:00
co-authored by Claude Opus 5
parent da129416f1
commit 16a13d510e
2 changed files with 18 additions and 18 deletions
+5 -13
View File
@@ -170,20 +170,12 @@ export function gitRecordedDatatableMigrationPaths(): RecordedMigrationPaths {
};
}
// `core.quotePath` (on by default) C-quotes any path with a non-ASCII byte, which
// matches nothing the caller holds and reads as "never tracked".
// `-z`, not `core.quotePath=false`: that setting only stops git C-quoting non-ASCII
// bytes, leaving a path holding `"`, `\` or a control character quoted and matching
// nothing the caller holds. `-z` emits every path raw, NUL-separated.
const r = spawnSync(
"git",
[
"-c",
"core.quotePath=false",
"log",
"HEAD",
"--format=",
"--name-only",
"--",
"migrations/datatable",
],
["log", "HEAD", "--format=", "--name-only", "-z", "--", "migrations/datatable"],
{ encoding: "utf8", stdio: "pipe", maxBuffer: 64 * 1024 * 1024 },
);
if ((r.status ?? 1) !== 0) {
@@ -195,7 +187,7 @@ export function gitRecordedDatatableMigrationPaths(): RecordedMigrationPaths {
};
}
const paths = new Set<string>();
for (const line of (r.stdout ?? "").split("\n")) {
for (const line of (r.stdout ?? "").split("\0")) {
const p = line.trim();
if (p.length === 0) continue;
if (prefix.length > 0) {
+13 -5
View File
@@ -55,15 +55,23 @@ describe("gitRecordedDatatableMigrationPaths", () => {
}
});
test("records a path with a non-ASCII byte unquoted", () => {
// core.quotePath would return "migrations/datatable/dt/1_caf\303\251.up.sql",
// which matches no path the caller holds and reads as never recorded.
const rel = commitMigration("20260101000000_café.up.sql");
test("records paths git would otherwise C-quote", () => {
// Non-ASCII is what `core.quotePath=false` covers; `"` and `\` stay quoted under
// it and need `-z`. All three read as never recorded when quoted.
const rels = [
commitMigration("20260101000000_café.up.sql"),
commitMigration('20260101000001_a"b.up.sql'),
commitMigration("20260101000002_a\\b.up.sql"),
];
const r = gitRecordedDatatableMigrationPaths();
expect(r.kind).toBe("known");
if (r.kind === "known") expect(r.paths.has(rel)).toBe(true);
if (r.kind === "known") {
for (const rel of rels) expect(r.paths.has(rel)).toBe(true);
}
});
// Guards the `-z` parser, not the pre-existing behaviour: the split moved from
// newline to NUL, and a deletion still has to leave the path listed.
test("a committed migration stays recorded after its deletion is committed", () => {
const rel = commitMigration("20260101000000_a.up.sql");
fs.rmSync(path.join(dir, rel));