@steve31415/baselib 3.36.1 → 3.36.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/test-owners.js +42 -9
- package/package.json +1 -1
package/dist/test-owners.js
CHANGED
|
@@ -9,32 +9,65 @@
|
|
|
9
9
|
//
|
|
10
10
|
// Scope is `.ts` only; `.tsx` is out of scope by decision (docs/TESTING.md,
|
|
11
11
|
// "The src -> test mapping"). `.d.ts` files are declarations, not modules.
|
|
12
|
+
//
|
|
13
|
+
// Files git ignores are not part of the repo and are skipped in both
|
|
14
|
+
// directions. A long-lived deploy checkout can hold leftovers of a build step
|
|
15
|
+
// that no longer exists — games' clone kept a generated `src/build-version.ts`
|
|
16
|
+
// from 2026-07-15, gitignored once its generator was deleted, and verify
|
|
17
|
+
// failed on it in every deploy while passing in every fresh worktree
|
|
18
|
+
// (2026-10-12, Coder task 37e13f8e). Untracked files that are NOT ignored still
|
|
19
|
+
// count, so a new module is checked before its first `git add`. Outside a git
|
|
20
|
+
// work tree (or without git) nothing is filtered.
|
|
21
|
+
import { execFile } from 'node:child_process';
|
|
12
22
|
import { readdir } from 'node:fs/promises';
|
|
13
23
|
import { join } from 'node:path';
|
|
14
24
|
const MODULE_EXT = '.ts';
|
|
15
25
|
const TEST_EXT = '.test.ts';
|
|
16
|
-
/**
|
|
17
|
-
*
|
|
18
|
-
|
|
26
|
+
/** The subset of `paths` (relative to `root`) that git ignores. Tracked
|
|
27
|
+
* files are never reported, even when a pattern matches them. Empty when
|
|
28
|
+
* `root` is not in a git work tree or git is unavailable. */
|
|
29
|
+
function gitIgnored(root, paths) {
|
|
30
|
+
if (paths.length === 0)
|
|
31
|
+
return Promise.resolve(new Set());
|
|
32
|
+
return new Promise((resolve, reject) => {
|
|
33
|
+
const child = execFile('git', ['check-ignore', '-z', '--stdin'], { cwd: root, maxBuffer: 64 * 1024 * 1024 }, (err, stdout) => {
|
|
34
|
+
// Exit 1 means "none ignored"; 128 (not a repo) or a missing git
|
|
35
|
+
// binary means there is nothing to filter against.
|
|
36
|
+
const code = err?.code;
|
|
37
|
+
if (err && code !== 1 && code !== 128 && code !== 'ENOENT') {
|
|
38
|
+
reject(err);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
resolve(new Set(err ? [] : stdout.split('\0').filter((p) => p !== '')));
|
|
42
|
+
});
|
|
43
|
+
child.stdin?.on('error', () => { }); // git exited before reading: the callback reports it
|
|
44
|
+
child.stdin?.end(paths.join('\0') + '\0');
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/** Files under `root/dir` (recursively) ending in `ext` and not ignored by
|
|
48
|
+
* git, as paths relative to `dir` with forward slashes. A missing directory
|
|
49
|
+
* yields no files. */
|
|
50
|
+
async function listFiles(root, dir, ext) {
|
|
19
51
|
let entries;
|
|
20
52
|
try {
|
|
21
|
-
entries = await readdir(dir, { recursive: true });
|
|
53
|
+
entries = await readdir(join(root, dir), { recursive: true });
|
|
22
54
|
}
|
|
23
55
|
catch (err) {
|
|
24
56
|
if (err.code === 'ENOENT')
|
|
25
57
|
return [];
|
|
26
58
|
throw err;
|
|
27
59
|
}
|
|
28
|
-
|
|
60
|
+
const files = entries
|
|
29
61
|
.map((e) => e.split('\\').join('/'))
|
|
30
|
-
.filter((e) => e.endsWith(ext) && !e.endsWith('.d.ts'))
|
|
31
|
-
|
|
62
|
+
.filter((e) => e.endsWith(ext) && !e.endsWith('.d.ts'));
|
|
63
|
+
const ignored = await gitIgnored(root, files.map((f) => `${dir}/${f}`));
|
|
64
|
+
return files.filter((f) => !ignored.has(`${dir}/${f}`)).sort();
|
|
32
65
|
}
|
|
33
66
|
export async function checkTestOwners(opts) {
|
|
34
67
|
const srcDir = opts.srcDir ?? 'src';
|
|
35
68
|
const testDir = opts.testDir ?? 'test';
|
|
36
|
-
const modules = (await listFiles(
|
|
37
|
-
const tests = new Set(await listFiles(
|
|
69
|
+
const modules = (await listFiles(opts.root, srcDir, MODULE_EXT)).filter((m) => !m.endsWith(TEST_EXT));
|
|
70
|
+
const tests = new Set(await listFiles(opts.root, testDir, TEST_EXT));
|
|
38
71
|
const missing = [];
|
|
39
72
|
for (const mod of modules) {
|
|
40
73
|
const expected = `${mod.slice(0, -MODULE_EXT.length)}${TEST_EXT}`;
|
package/package.json
CHANGED