mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-04 15:57:33 +01:00
test(fixtures): leak scan skips Capy's git shim log in fixture homes
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
69c14b17d5
commit
69bd0399cf
3 files changed
+28
-2
No files matched your search
@@ -0,0 +1,5 @@
|
|||||||
|
**On a Capy machine, the git fixture tests no longer fail locally because of Capy's git shim log.** Capy's `/usr/bin/git` shim appends to `$HOME/.capy/git-shim.log`, so each fixture home that ran git during its template build ended up with a log naming the template. The leak scan in `test/helpers/git-fixture-template.ts` flagged it, and 34 tests in `test/train-backstop.test.ts`, `test/restamp-mentions.test.ts` and `test/pregate-user-policy.test.ts` failed on every Capy lane, though they passed on the remote gate.
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
- `templateReferences` skips `.capy/git-shim.log`. Nothing reads that file back, and every other file is still scanned.
|
||||||
|
- `test/git-fixture-template.test.ts` plants the shim log in a template's `home/.capy/` (the copy succeeds), and plants `home/.capy/state.json` as a control (the copy still throws).
|
||||||
@@ -71,6 +71,23 @@ describe('git fixture template', () => {
|
|||||||
expect(() => leaky.copy()).toThrow(/still references its template [^\n]*\n.*config/);
|
expect(() => leaky.copy()).toThrow(/still references its template [^\n]*\n.*config/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Capy's git shim log in a fixture home (home/.capy/git-shim.log) is not a leak; any other file naming the template still is", () => {
|
||||||
|
const plant = (rel: string) => gitFixtureTemplate({ prefix: 'gstack-fixture-template-shim-', build: (root) => {
|
||||||
|
const meta = build(root);
|
||||||
|
fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true });
|
||||||
|
fs.writeFileSync(path.join(root, rel), '# capy git shim v2: ts cwd ppid parent verb\n2026-11-02T02:15:30Z\t' + path.join(root, 'work') + '\t1\tbun\tcat-file\n');
|
||||||
|
return meta;
|
||||||
|
}, rebind: (copy, tpl) => rebindGitDir(path.join(copy, 'work', '.git'), tpl, copy) });
|
||||||
|
const shim = plant(path.join('home', '.capy', 'git-shim.log'));
|
||||||
|
const other = plant(path.join('home', '.capy', 'state.json'));
|
||||||
|
try {
|
||||||
|
const c = shim.copy();
|
||||||
|
roots.push(c.root);
|
||||||
|
expect(git(path.join(c.root, 'work'), 'remote', 'get-url', 'origin')).toBe(path.join(c.root, 'origin.git'));
|
||||||
|
expect(() => other.copy()).toThrow(/still references its template [^\n]*\n.*state\.json/);
|
||||||
|
} finally { shim.dispose(); other.dispose(); }
|
||||||
|
});
|
||||||
|
|
||||||
test('native, forward-slash, backslash-escaped and Git Bash spellings are each rewritten, and each one left behind is found', () => {
|
test('native, forward-slash, backslash-escaped and Git Bash spellings are each rewritten, and each one left behind is found', () => {
|
||||||
const to = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-fixture-spellings-'));
|
const to = fs.mkdtempSync(path.join(os.tmpdir(), 'gstack-fixture-spellings-'));
|
||||||
roots.push(to);
|
roots.push(to);
|
||||||
|
|||||||
@@ -52,7 +52,11 @@ export function rebindGitDir(gitDir: string, from: string, to: string): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Files and symlinks under dir (and the template's meta value) that still name templateRoot; zlib-compressed object storage is skipped. */
|
/**
|
||||||
|
* Files and symlinks under dir (and the template's meta value) that still name templateRoot. Skipped: zlib-compressed object
|
||||||
|
* storage, and the log Capy's /usr/bin/git shim appends to in whatever HOME it runs under (.capy/git-shim.log), which names
|
||||||
|
* the template whenever a fixture home ran git during build; nothing reads it back.
|
||||||
|
*/
|
||||||
export function templateReferences(dir: string, templateRoot: string, meta?: unknown): string[] {
|
export function templateReferences(dir: string, templateRoot: string, meta?: unknown): string[] {
|
||||||
const needles = pathSpellings(templateRoot).map(s => Buffer.from(s));
|
const needles = pathSpellings(templateRoot).map(s => Buffer.from(s));
|
||||||
const names = (buf: Buffer) => needles.some(n => buf.includes(n));
|
const names = (buf: Buffer) => needles.some(n => buf.includes(n));
|
||||||
@@ -62,7 +66,7 @@ export function templateReferences(dir: string, templateRoot: string, meta?: unk
|
|||||||
const p = path.join(d, entry.name);
|
const p = path.join(d, entry.name);
|
||||||
if (entry.isSymbolicLink()) { if (names(Buffer.from(fs.readlinkSync(p)))) hits.push(p); }
|
if (entry.isSymbolicLink()) { if (names(Buffer.from(fs.readlinkSync(p)))) hits.push(p); }
|
||||||
else if (entry.isDirectory()) { if (!(path.basename(d) === 'objects' && /^(pack|[0-9a-f]{2})$/.test(entry.name))) walk(p); }
|
else if (entry.isDirectory()) { if (!(path.basename(d) === 'objects' && /^(pack|[0-9a-f]{2})$/.test(entry.name))) walk(p); }
|
||||||
else if (entry.isFile() && names(fs.readFileSync(p))) hits.push(p);
|
else if (entry.isFile() && !(entry.name === 'git-shim.log' && path.basename(d) === '.capy') && names(fs.readFileSync(p))) hits.push(p);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
walk(dir);
|
walk(dir);
|
||||||
|
|||||||
Reference in new issue
Block a user