@volter/twin-standard 1.0.29 → 1.0.30
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/src/gate.js +2 -1
- package/dist/src/pack-files.d.ts +2 -0
- package/dist/src/pack-files.js +4 -0
- package/dist/src/protocol-3.js +19 -6
- package/package.json +1 -1
- package/src/gate.ts +2 -1
- package/src/pack-files.ts +4 -0
- package/src/protocol-3.ts +17 -6
package/dist/src/gate.js
CHANGED
|
@@ -16,6 +16,7 @@ import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
|
16
16
|
import { join } from 'node:path';
|
|
17
17
|
import ts from 'typescript';
|
|
18
18
|
import { grade } from "./grade.js";
|
|
19
|
+
import { isPackArtifact } from "./pack-files.js";
|
|
19
20
|
/** Every unit of a pack repository: each pack (a directory with a package.json) and each lane in it (a directory with
|
|
20
21
|
* its own src/manifest.ts and no package.json). */
|
|
21
22
|
export function unitsOf(repo) {
|
|
@@ -50,7 +51,7 @@ export function laneRootFailures(dir) {
|
|
|
50
51
|
const lanes = readdirSync(dir).filter((n) => existsSync(join(dir, n, 'src', 'manifest.ts')));
|
|
51
52
|
if (!lanes.length)
|
|
52
53
|
return ['layout: no src/manifest.ts and no lane: not a Protocol 3 pack'];
|
|
53
|
-
const stray = readdirSync(dir).filter((n) => !n.startsWith('.') && !ROOT_ENTRIES.has(n) && !lanes.includes(n));
|
|
54
|
+
const stray = readdirSync(dir).filter((n) => !isPackArtifact(n) && !n.startsWith('.') && !ROOT_ENTRIES.has(n) && !lanes.includes(n));
|
|
54
55
|
const skip = ignored(dir, stray);
|
|
55
56
|
const outside = [
|
|
56
57
|
...stray.filter((n) => !skip.has(n)),
|
package/dist/src/protocol-3.js
CHANGED
|
@@ -21,6 +21,7 @@ import { gunzipSync } from 'node:zlib';
|
|
|
21
21
|
import ts from 'typescript';
|
|
22
22
|
import { fileURLToPath } from 'node:url';
|
|
23
23
|
import { sharingLanesIn } from "./lanes.js";
|
|
24
|
+
import { isPackArtifact } from "./pack-files.js";
|
|
24
25
|
/** The lanes over the unit's vendor's state, when the unit is one of them ("Pack layout"), else none: a lane over its
|
|
25
26
|
* vendor's state takes the vendor's states, shared helpers, manifest and engine from the vendor's src/, and nothing of
|
|
26
27
|
* another lane. */
|
|
@@ -56,24 +57,36 @@ function specFiles(unit) {
|
|
|
56
57
|
const dir = join(unit.dir, 'spec');
|
|
57
58
|
return filesUnder(dir).filter((f) => !SPEC_METADATA.test(f) && !SPEC_TOOL.test(f)).map((f) => join(dir, f));
|
|
58
59
|
}
|
|
59
|
-
/**
|
|
60
|
+
/** Files relative to a directory: Git's tree in a checkout, the disk tree of an unpacked package outside one. */
|
|
60
61
|
function filesUnder(dir, base = dir) {
|
|
61
62
|
if (!existsSync(dir))
|
|
62
63
|
return [];
|
|
64
|
+
const checkout = spawnSync('git', ['rev-parse', '--is-inside-work-tree'], { cwd: dir, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });
|
|
65
|
+
if (checkout.status !== 0 || checkout.error || checkout.stdout.trim() !== 'true') {
|
|
66
|
+
if (checkout.status !== null && checkout.status !== 0 && !checkout.error && !checkout.signal
|
|
67
|
+
&& /^fatal: not a git repository(?:[ (:]|$)/m.test(String(checkout.stderr ?? '')))
|
|
68
|
+
return allFilesUnder(dir, base, true);
|
|
69
|
+
throw new Error(`git rev-parse failed: directory=${JSON.stringify(dir)} status=${checkout.status} signal=${JSON.stringify(checkout.signal)} error=${JSON.stringify(checkout.error?.message ?? null)} stdout=${JSON.stringify(String(checkout.stdout ?? '').trim())} stderr=${JSON.stringify(String(checkout.stderr ?? '').trim())}`);
|
|
70
|
+
}
|
|
63
71
|
// tracked and not-yet-added files alike (T0 runs before the commit); ignored runtime state (.volter) never
|
|
64
|
-
const run = spawnSync('git', ['ls-files', '-z', '--cached', '--others', '--exclude-standard', '--', '.'], { cwd: dir, stdio: ['ignore', 'pipe', '
|
|
65
|
-
|
|
72
|
+
const run = spawnSync('git', ['ls-files', '-z', '--cached', '--others', '--exclude-standard', '--', '.'], { cwd: dir, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
73
|
+
if (run.status !== 0 || run.error) {
|
|
74
|
+
throw new Error(`git ls-files failed: directory=${JSON.stringify(dir)} status=${run.status} signal=${JSON.stringify(run.signal)} error=${JSON.stringify(run.error?.message ?? null)} stderr=${JSON.stringify(String(run.stderr ?? '').trim())}`);
|
|
75
|
+
}
|
|
76
|
+
const tracked = [...new Set(String(run.stdout).split('\0').filter(Boolean))];
|
|
66
77
|
return tracked.map((f) => relative(base, join(dir, f))).filter((f) => existsSync(join(base, f)));
|
|
67
78
|
}
|
|
68
|
-
/**
|
|
69
|
-
function allFilesUnder(dir, base = dir) {
|
|
79
|
+
/** Disk files outside a checkout, or the complete output of the grader's own derivation. */
|
|
80
|
+
function allFilesUnder(dir, base = dir, excludeArtifacts = false) {
|
|
70
81
|
if (!existsSync(dir))
|
|
71
82
|
return [];
|
|
72
83
|
const out = [];
|
|
73
84
|
for (const name of readdirSync(dir)) {
|
|
74
85
|
const path = join(dir, name);
|
|
86
|
+
if (excludeArtifacts && isPackArtifact(relative(base, path)))
|
|
87
|
+
continue;
|
|
75
88
|
if (statSync(path).isDirectory())
|
|
76
|
-
out.push(...allFilesUnder(path, base));
|
|
89
|
+
out.push(...allFilesUnder(path, base, excludeArtifacts));
|
|
77
90
|
else
|
|
78
91
|
out.push(relative(base, path));
|
|
79
92
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/twin-standard",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.30",
|
|
4
4
|
"description": "The Protocol 3 standard for Volter twin packs: the criteria a pack is graded by, the grader, the gate a pack repository and the twin catalog run on every change and submission, and the spec derivation the grade checks against. Pin a version: every place a pack is judged judges by that standard.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"twin",
|
package/src/gate.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
|
16
16
|
import { join } from 'node:path';
|
|
17
17
|
import ts from 'typescript';
|
|
18
18
|
import { grade } from './grade.ts';
|
|
19
|
+
import { isPackArtifact } from './pack-files.ts';
|
|
19
20
|
|
|
20
21
|
/** Every unit of a pack repository: each pack (a directory with a package.json) and each lane in it (a directory with
|
|
21
22
|
* its own src/manifest.ts and no package.json). */
|
|
@@ -48,7 +49,7 @@ function ignored(dir: string, names: string[]): Set<string> {
|
|
|
48
49
|
export function laneRootFailures(dir: string): string[] {
|
|
49
50
|
const lanes = readdirSync(dir).filter((n) => existsSync(join(dir, n, 'src', 'manifest.ts')));
|
|
50
51
|
if (!lanes.length) return ['layout: no src/manifest.ts and no lane: not a Protocol 3 pack'];
|
|
51
|
-
const stray = readdirSync(dir).filter((n) => !n.startsWith('.') && !ROOT_ENTRIES.has(n) && !lanes.includes(n));
|
|
52
|
+
const stray = readdirSync(dir).filter((n) => !isPackArtifact(n) && !n.startsWith('.') && !ROOT_ENTRIES.has(n) && !lanes.includes(n));
|
|
52
53
|
const skip = ignored(dir, stray);
|
|
53
54
|
const outside = [
|
|
54
55
|
...stray.filter((n) => !skip.has(n)),
|
package/src/protocol-3.ts
CHANGED
|
@@ -13,6 +13,7 @@ import { gunzipSync } from 'node:zlib';
|
|
|
13
13
|
import ts from 'typescript';
|
|
14
14
|
import { fileURLToPath } from 'node:url';
|
|
15
15
|
import { sharingLanesIn } from './lanes.ts';
|
|
16
|
+
import { isPackArtifact } from './pack-files.ts';
|
|
16
17
|
import type { Criterion, GradeUnit, Standard } from './types.ts';
|
|
17
18
|
|
|
18
19
|
/** The lanes over the unit's vendor's state, when the unit is one of them ("Pack layout"), else none: a lane over its
|
|
@@ -46,21 +47,31 @@ function specFiles(unit: GradeUnit): string[] {
|
|
|
46
47
|
return filesUnder(dir).filter((f) => !SPEC_METADATA.test(f) && !SPEC_TOOL.test(f)).map((f) => join(dir, f));
|
|
47
48
|
}
|
|
48
49
|
|
|
49
|
-
/**
|
|
50
|
+
/** Files relative to a directory: Git's tree in a checkout, the disk tree of an unpacked package outside one. */
|
|
50
51
|
function filesUnder(dir: string, base = dir): string[] {
|
|
51
52
|
if (!existsSync(dir)) return [];
|
|
53
|
+
const checkout = spawnSync('git', ['rev-parse', '--is-inside-work-tree'], { cwd: dir, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });
|
|
54
|
+
if (checkout.status !== 0 || checkout.error || checkout.stdout.trim() !== 'true') {
|
|
55
|
+
if (checkout.status !== null && checkout.status !== 0 && !checkout.error && !checkout.signal
|
|
56
|
+
&& /^fatal: not a git repository(?:[ (:]|$)/m.test(String(checkout.stderr ?? ''))) return allFilesUnder(dir, base, true);
|
|
57
|
+
throw new Error(`git rev-parse failed: directory=${JSON.stringify(dir)} status=${checkout.status} signal=${JSON.stringify(checkout.signal)} error=${JSON.stringify(checkout.error?.message ?? null)} stdout=${JSON.stringify(String(checkout.stdout ?? '').trim())} stderr=${JSON.stringify(String(checkout.stderr ?? '').trim())}`);
|
|
58
|
+
}
|
|
52
59
|
// tracked and not-yet-added files alike (T0 runs before the commit); ignored runtime state (.volter) never
|
|
53
|
-
const run = spawnSync('git', ['ls-files', '-z', '--cached', '--others', '--exclude-standard', '--', '.'], { cwd: dir, stdio: ['ignore', 'pipe', '
|
|
54
|
-
|
|
60
|
+
const run = spawnSync('git', ['ls-files', '-z', '--cached', '--others', '--exclude-standard', '--', '.'], { cwd: dir, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
61
|
+
if (run.status !== 0 || run.error) {
|
|
62
|
+
throw new Error(`git ls-files failed: directory=${JSON.stringify(dir)} status=${run.status} signal=${JSON.stringify(run.signal)} error=${JSON.stringify(run.error?.message ?? null)} stderr=${JSON.stringify(String(run.stderr ?? '').trim())}`);
|
|
63
|
+
}
|
|
64
|
+
const tracked = [...new Set(String(run.stdout).split('\0').filter(Boolean))];
|
|
55
65
|
return tracked.map((f) => relative(base, join(dir, f))).filter((f) => existsSync(join(base, f)));
|
|
56
66
|
}
|
|
57
|
-
/**
|
|
58
|
-
function allFilesUnder(dir: string, base = dir): string[] {
|
|
67
|
+
/** Disk files outside a checkout, or the complete output of the grader's own derivation. */
|
|
68
|
+
function allFilesUnder(dir: string, base = dir, excludeArtifacts = false): string[] {
|
|
59
69
|
if (!existsSync(dir)) return [];
|
|
60
70
|
const out: string[] = [];
|
|
61
71
|
for (const name of readdirSync(dir)) {
|
|
62
72
|
const path = join(dir, name);
|
|
63
|
-
if (
|
|
73
|
+
if (excludeArtifacts && isPackArtifact(relative(base, path))) continue;
|
|
74
|
+
if (statSync(path).isDirectory()) out.push(...allFilesUnder(path, base, excludeArtifacts));
|
|
64
75
|
else out.push(relative(base, path));
|
|
65
76
|
}
|
|
66
77
|
return out;
|