@marcomigozzi/trailhead 0.14.0 → 0.15.0
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/README.it.md +118 -30
- package/README.md +107 -29
- package/bin/base-preflight-docs.test.js +65 -0
- package/bin/execute-split-docs.test.js +146 -0
- package/bin/isolation-answer-docs.test.js +41 -0
- package/bin/isolation-copy-docs.test.js +28 -0
- package/bin/lib/codex-projection.js +1 -1
- package/bin/lib/codex-projection.test.js +41 -0
- package/bin/report-status-docs.test.js +195 -0
- package/bin/resolve-helpers-docs.test.js +36 -0
- package/bin/scope-confirm-skip-docs.test.js +70 -0
- package/bin/trailhead.js +3 -3
- package/bin/trailhead.test.js +341 -1
- package/bin/uat-setup-docs.test.js +65 -0
- package/package.json +1 -1
- package/plugins/trailhead/.claude-plugin/plugin.json +1 -1
- package/plugins/trailhead/agents/trailhead-code-review.md +15 -2
- package/plugins/trailhead/agents/trailhead-codebase-map.md +20 -1
- package/plugins/trailhead/agents/trailhead-debug.md +20 -1
- package/plugins/trailhead/agents/trailhead-executor.md +29 -2
- package/plugins/trailhead/agents/trailhead-fix.md +29 -2
- package/plugins/trailhead/agents/trailhead-plan.md +20 -1
- package/plugins/trailhead/agents/trailhead-research.md +22 -3
- package/plugins/trailhead/agents/trailhead-verify.md +15 -2
- package/plugins/trailhead/hooks/lib/base-preflight.test.js +513 -0
- package/plugins/trailhead/hooks/lib/commit-message-check.js +1 -1
- package/plugins/trailhead/hooks/lib/commit-message-check.test.js +3 -2
- package/plugins/trailhead/hooks/lib/commit-msg-module-repo.test.js +116 -0
- package/plugins/trailhead/hooks/lib/commit-msg-sync.test.js +100 -9
- package/plugins/trailhead/hooks/lib/dashboard.test.js +409 -0
- package/plugins/trailhead/hooks/lib/fixtures/commit-msg-legacy-js +104 -0
- package/plugins/trailhead/hooks/lib/isolation-answer.test.js +258 -0
- package/plugins/trailhead/hooks/lib/isolation-copy.test.js +298 -0
- package/plugins/trailhead/hooks/lib/issue-body.test.js +470 -0
- package/plugins/trailhead/hooks/lib/report-status.test.js +366 -0
- package/plugins/trailhead/hooks/lib/shell-scan.js +36 -1
- package/plugins/trailhead/hooks/lib/shell-scan.test.js +14 -0
- package/plugins/trailhead/hooks/lib/uat-backfill.test.js +150 -0
- package/plugins/trailhead/hooks/lib/uat-setup.test.js +340 -0
- package/plugins/trailhead/hooks/lib/work-state.test.js +45 -0
- package/plugins/trailhead/hooks/mod/README.md +38 -6
- package/plugins/trailhead/hooks/mod/map-pane-view.ts +168 -15
- package/plugins/trailhead/hooks/mod/map-pane.tsx +275 -106
- package/plugins/trailhead/hooks/mod/register.tsx +15 -2
- package/plugins/trailhead/hooks/mod/work-state-view.ts +17 -0
- package/plugins/trailhead/hooks/trailhead-install-guard.js +169 -34
- package/plugins/trailhead/hooks/trailhead-install-guard.test.js +180 -1
- package/plugins/trailhead/hooks/trailhead-search-guard.js +43 -7
- package/plugins/trailhead/hooks/trailhead-search-guard.test.js +66 -2
- package/plugins/trailhead/skills/_shared/choices.md +4 -2
- package/plugins/trailhead/skills/_shared/configuration-reference.md +15 -3
- package/plugins/trailhead/skills/_shared/load-first.md +3 -3
- package/plugins/trailhead/skills/_shared/multi-map.md +2 -2
- package/plugins/trailhead/skills/_shared/session-handoff.md +1 -1
- package/plugins/trailhead/skills/_shared/substrate-commands.md +22 -11
- package/plugins/trailhead/skills/_shared/substrate.md +6 -4
- package/plugins/trailhead/skills/_shared/teamwork.md +16 -7
- package/plugins/trailhead/skills/_shared/techniques/acceptance-testing.md +17 -9
- package/plugins/trailhead/skills/_shared/techniques/code-review.md +1 -1
- package/plugins/trailhead/skills/_shared/techniques/codebase-map.md +1 -1
- package/plugins/trailhead/skills/_shared/techniques/debug.md +2 -0
- package/plugins/trailhead/skills/_shared/techniques/research.md +4 -2
- package/plugins/trailhead/skills/_shared/techniques/verify.md +1 -1
- package/plugins/trailhead/skills/_shared/techniques.md +12 -2
- package/plugins/trailhead/skills/trailhead/SKILL.md +1 -1
- package/plugins/trailhead/skills/trailhead-capture/SKILL.md +1 -1
- package/plugins/trailhead/skills/trailhead-capture/references/capture.md +2 -2
- package/plugins/trailhead/skills/trailhead-chart/SKILL.md +1 -1
- package/plugins/trailhead/skills/trailhead-chart/references/charting.md +1 -1
- package/plugins/trailhead/skills/trailhead-manage/SKILL.md +1 -1
- package/plugins/trailhead/skills/trailhead-manage/references/auditing.md +1 -1
- package/plugins/trailhead/skills/trailhead-view/SKILL.md +8 -6
- package/plugins/trailhead/skills/trailhead-work/SKILL.md +14 -12
- package/plugins/trailhead/skills/trailhead-work/references/auto.md +4 -4
- package/plugins/trailhead/skills/trailhead-work/references/executor-brief.md +29 -0
- package/plugins/trailhead/skills/trailhead-work/references/ticket-engines.md +26 -10
- package/plugins/trailhead/templates/trailhead-base-preflight.js +305 -0
- package/plugins/trailhead/templates/trailhead-commit-msg +38 -102
- package/plugins/trailhead/templates/trailhead-commit-msg-sync.js +58 -27
- package/plugins/trailhead/templates/trailhead-commit-msg.cjs +114 -0
- package/plugins/trailhead/templates/trailhead-dashboard.js +340 -0
- package/plugins/trailhead/templates/trailhead-isolation-answer.js +227 -0
- package/plugins/trailhead/templates/trailhead-isolation-copy.js +239 -0
- package/plugins/trailhead/templates/trailhead-issue-body.js +459 -0
- package/plugins/trailhead/templates/trailhead-report-status.js +274 -0
- package/plugins/trailhead/templates/trailhead-uat-backfill.js +114 -0
- package/plugins/trailhead/templates/trailhead-uat-setup.js +385 -0
- package/plugins/trailhead/templates/trailhead-work-state.js +25 -7
- package/plugins/trailhead/tests/map-pane-ui.test.ts +566 -19
- package/plugins/trailhead/tests/map-pane-view.test.ts +304 -16
- package/plugins/trailhead/tests/work-state-view.test.ts +25 -1
- package/plugins/trailhead/types/index.d.ts +37 -3
|
@@ -16,7 +16,10 @@ const os = require('os');
|
|
|
16
16
|
|
|
17
17
|
const scriptPath = path.resolve(__dirname, '..', '..', 'templates', 'trailhead-commit-msg-sync.js');
|
|
18
18
|
const templatePath = path.resolve(__dirname, '..', '..', 'templates', 'trailhead-commit-msg');
|
|
19
|
+
const cjsTemplatePath = path.resolve(__dirname, '..', '..', 'templates', 'trailhead-commit-msg.cjs');
|
|
19
20
|
const oldFixturePath = path.join(__dirname, 'fixtures', 'commit-msg-a319156');
|
|
21
|
+
// Hook JS monofile pre-#257 (extensionless CommonJS), da migrare al nuovo layout.
|
|
22
|
+
const legacyJsFixturePath = path.join(__dirname, 'fixtures', 'commit-msg-legacy-js');
|
|
20
23
|
|
|
21
24
|
const {
|
|
22
25
|
resolveHooksTarget,
|
|
@@ -29,7 +32,10 @@ let passed = 0;
|
|
|
29
32
|
const ok = (name, cond) => { assert.ok(cond, name); passed++; };
|
|
30
33
|
|
|
31
34
|
const templateText = fs.readFileSync(templatePath, 'utf8');
|
|
35
|
+
const cjsText = fs.readFileSync(cjsTemplatePath, 'utf8');
|
|
32
36
|
const oldHookText = fs.readFileSync(oldFixturePath, 'utf8');
|
|
37
|
+
const legacyJsText = fs.readFileSync(legacyJsFixturePath, 'utf8');
|
|
38
|
+
const CJS_NAME = 'trailhead-commit-msg.cjs';
|
|
33
39
|
|
|
34
40
|
function mktmp() {
|
|
35
41
|
return fs.mkdtempSync(path.join(os.tmpdir(), 'trailhead-commit-msg-sync-test-'));
|
|
@@ -38,6 +44,9 @@ function mktmp() {
|
|
|
38
44
|
// --- isTrailheadHook() unit cases -------------------------------------------
|
|
39
45
|
ok('isTrailheadHook: current template is recognised', isTrailheadHook(templateText));
|
|
40
46
|
ok('isTrailheadHook: old (a319156) hook is recognised', isTrailheadHook(oldHookText));
|
|
47
|
+
ok('isTrailheadHook: legacy single-file JS hook is recognised', isTrailheadHook(legacyJsText));
|
|
48
|
+
ok('isTrailheadHook: wrapper header is on a "#" line within the first 5', isTrailheadHook(templateText));
|
|
49
|
+
ok('isTrailheadHook: wrapper is a sh script', templateText.startsWith('#!/bin/sh\n'));
|
|
41
50
|
ok('isTrailheadHook: plain foreign script is not', !isTrailheadHook('#!/bin/sh\necho hi\n'));
|
|
42
51
|
ok('isTrailheadHook: mention outside the first 5 lines, not line-start, is not',
|
|
43
52
|
!isTrailheadHook('#!/bin/sh\necho hi\necho more\necho stuff\necho again\n# trailhead commit-msg hook (git). fake\n'));
|
|
@@ -55,13 +64,14 @@ function modeOf(p) { return fs.statSync(p).mode & 0o777; }
|
|
|
55
64
|
// absent -> installed, 0755
|
|
56
65
|
{
|
|
57
66
|
const dir = mktmp();
|
|
58
|
-
const result = syncCommitMsgHook({ hooksDir: dir, templateText, hooksPathSet: false, fs });
|
|
67
|
+
const result = syncCommitMsgHook({ hooksDir: dir, templateText, hooksPathSet: false, cjsText, fs });
|
|
59
68
|
const hookPath = path.join(dir, 'commit-msg');
|
|
60
69
|
ok('syncCommitMsgHook: absent -> installed', result.status === 'installed');
|
|
61
70
|
ok('syncCommitMsgHook: absent -> hook path returned', result.hook === hookPath);
|
|
62
71
|
ok('syncCommitMsgHook: absent -> file written', fs.existsSync(hookPath));
|
|
63
72
|
ok('syncCommitMsgHook: absent -> content matches template', fs.readFileSync(hookPath, 'utf8') === templateText);
|
|
64
73
|
ok('syncCommitMsgHook: absent -> mode 0755', modeOf(hookPath) === 0o755);
|
|
74
|
+
ok('syncCommitMsgHook: absent -> .cjs written beside it', fs.readFileSync(path.join(dir, CJS_NAME), 'utf8') === cjsText);
|
|
65
75
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
66
76
|
}
|
|
67
77
|
|
|
@@ -71,21 +81,77 @@ function modeOf(p) { return fs.statSync(p).mode & 0o777; }
|
|
|
71
81
|
const hookPath = path.join(dir, 'commit-msg');
|
|
72
82
|
fs.writeFileSync(hookPath, oldHookText);
|
|
73
83
|
fs.chmodSync(hookPath, 0o755);
|
|
74
|
-
const result = syncCommitMsgHook({ hooksDir: dir, templateText, hooksPathSet: false, fs });
|
|
84
|
+
const result = syncCommitMsgHook({ hooksDir: dir, templateText, hooksPathSet: false, cjsText, fs });
|
|
75
85
|
ok('syncCommitMsgHook: old -> upgraded', result.status === 'upgraded');
|
|
76
86
|
ok('syncCommitMsgHook: old -> bytes now match template', fs.readFileSync(hookPath, 'utf8') === templateText);
|
|
77
87
|
ok('syncCommitMsgHook: old -> mode 0755', modeOf(hookPath) === 0o755);
|
|
78
88
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
79
89
|
}
|
|
80
90
|
|
|
91
|
+
// legacy single-file JS hook -> upgraded to wrapper + .cjs
|
|
92
|
+
{
|
|
93
|
+
const dir = mktmp();
|
|
94
|
+
const hookPath = path.join(dir, 'commit-msg');
|
|
95
|
+
fs.writeFileSync(hookPath, legacyJsText);
|
|
96
|
+
fs.chmodSync(hookPath, 0o755);
|
|
97
|
+
const result = syncCommitMsgHook({ hooksDir: dir, templateText, cjsText, hooksPathSet: false, fs });
|
|
98
|
+
ok('syncCommitMsgHook: legacy JS -> upgraded', result.status === 'upgraded');
|
|
99
|
+
ok('syncCommitMsgHook: legacy JS -> wrapper now matches template', fs.readFileSync(hookPath, 'utf8') === templateText);
|
|
100
|
+
ok('syncCommitMsgHook: legacy JS -> .cjs written', fs.readFileSync(path.join(dir, CJS_NAME), 'utf8') === cjsText);
|
|
101
|
+
ok('syncCommitMsgHook: legacy JS -> wrapper mode 0755', modeOf(hookPath) === 0o755);
|
|
102
|
+
const again = syncCommitMsgHook({ hooksDir: dir, templateText, cjsText, hooksPathSet: false, fs });
|
|
103
|
+
ok('syncCommitMsgHook: legacy JS -> second run is current', again.status === 'current');
|
|
104
|
+
ok('syncCommitMsgHook: legacy JS -> no temp files left', fs.readdirSync(dir).sort().join(',') === `commit-msg,${CJS_NAME}`);
|
|
105
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// current wrapper but outdated .cjs -> upgraded, .cjs rewritten
|
|
109
|
+
{
|
|
110
|
+
const dir = mktmp();
|
|
111
|
+
const hookPath = path.join(dir, 'commit-msg');
|
|
112
|
+
fs.writeFileSync(hookPath, templateText);
|
|
113
|
+
fs.chmodSync(hookPath, 0o755);
|
|
114
|
+
fs.writeFileSync(path.join(dir, CJS_NAME), '// stale\n');
|
|
115
|
+
const result = syncCommitMsgHook({ hooksDir: dir, templateText, cjsText, hooksPathSet: false, fs });
|
|
116
|
+
ok('syncCommitMsgHook: outdated .cjs -> upgraded', result.status === 'upgraded');
|
|
117
|
+
ok('syncCommitMsgHook: outdated .cjs -> rewritten', fs.readFileSync(path.join(dir, CJS_NAME), 'utf8') === cjsText);
|
|
118
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// current wrapper but .cjs missing -> upgraded, .cjs restored
|
|
122
|
+
{
|
|
123
|
+
const dir = mktmp();
|
|
124
|
+
const hookPath = path.join(dir, 'commit-msg');
|
|
125
|
+
fs.writeFileSync(hookPath, templateText);
|
|
126
|
+
fs.chmodSync(hookPath, 0o755);
|
|
127
|
+
const result = syncCommitMsgHook({ hooksDir: dir, templateText, cjsText, hooksPathSet: false, fs });
|
|
128
|
+
ok('syncCommitMsgHook: missing .cjs -> upgraded', result.status === 'upgraded');
|
|
129
|
+
ok('syncCommitMsgHook: missing .cjs -> restored', fs.readFileSync(path.join(dir, CJS_NAME), 'utf8') === cjsText);
|
|
130
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// outdated wrapper (older sh wrapper text) + current .cjs -> upgraded wrapper
|
|
134
|
+
{
|
|
135
|
+
const dir = mktmp();
|
|
136
|
+
const hookPath = path.join(dir, 'commit-msg');
|
|
137
|
+
fs.writeFileSync(hookPath, '#!/bin/sh\n# trailhead commit-msg hook (git). older wrapper\nexit 0\n');
|
|
138
|
+
fs.chmodSync(hookPath, 0o755);
|
|
139
|
+
fs.writeFileSync(path.join(dir, CJS_NAME), cjsText);
|
|
140
|
+
const result = syncCommitMsgHook({ hooksDir: dir, templateText, cjsText, hooksPathSet: false, fs });
|
|
141
|
+
ok('syncCommitMsgHook: outdated wrapper -> upgraded', result.status === 'upgraded');
|
|
142
|
+
ok('syncCommitMsgHook: outdated wrapper -> now matches template', fs.readFileSync(hookPath, 'utf8') === templateText);
|
|
143
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
144
|
+
}
|
|
145
|
+
|
|
81
146
|
// CRLF current -> current, untouched
|
|
82
147
|
{
|
|
83
148
|
const dir = mktmp();
|
|
84
149
|
const hookPath = path.join(dir, 'commit-msg');
|
|
85
150
|
const crlfTemplate = templateText.replace(/\n/g, '\r\n');
|
|
151
|
+
fs.writeFileSync(path.join(dir, CJS_NAME), cjsText);
|
|
86
152
|
fs.writeFileSync(hookPath, crlfTemplate);
|
|
87
153
|
fs.chmodSync(hookPath, 0o755);
|
|
88
|
-
const result = syncCommitMsgHook({ hooksDir: dir, templateText, hooksPathSet: false, fs });
|
|
154
|
+
const result = syncCommitMsgHook({ hooksDir: dir, templateText, hooksPathSet: false, cjsText, fs });
|
|
89
155
|
ok('syncCommitMsgHook: CRLF current -> current', result.status === 'current');
|
|
90
156
|
ok('syncCommitMsgHook: CRLF current -> untouched bytes', fs.readFileSync(hookPath, 'utf8') === crlfTemplate);
|
|
91
157
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
@@ -96,8 +162,9 @@ function modeOf(p) { return fs.statSync(p).mode & 0o777; }
|
|
|
96
162
|
const dir = mktmp();
|
|
97
163
|
const hookPath = path.join(dir, 'commit-msg');
|
|
98
164
|
fs.writeFileSync(hookPath, templateText);
|
|
165
|
+
fs.writeFileSync(path.join(dir, CJS_NAME), cjsText);
|
|
99
166
|
fs.chmodSync(hookPath, 0o644);
|
|
100
|
-
const result = syncCommitMsgHook({ hooksDir: dir, templateText, hooksPathSet: false, fs });
|
|
167
|
+
const result = syncCommitMsgHook({ hooksDir: dir, templateText, hooksPathSet: false, cjsText, fs });
|
|
101
168
|
ok('syncCommitMsgHook: current 0644 -> status current', result.status === 'current');
|
|
102
169
|
ok('syncCommitMsgHook: current 0644 -> mode fixed to 0755', modeOf(hookPath) === 0o755);
|
|
103
170
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
@@ -110,10 +177,11 @@ function modeOf(p) { return fs.statSync(p).mode & 0o777; }
|
|
|
110
177
|
const foreign = '#!/bin/sh\necho hi\n';
|
|
111
178
|
fs.writeFileSync(hookPath, foreign);
|
|
112
179
|
fs.chmodSync(hookPath, 0o755);
|
|
113
|
-
const result = syncCommitMsgHook({ hooksDir: dir, templateText, hooksPathSet: false, fs });
|
|
180
|
+
const result = syncCommitMsgHook({ hooksDir: dir, templateText, hooksPathSet: false, cjsText, fs });
|
|
114
181
|
ok('syncCommitMsgHook: foreign shell -> foreign', result.status === 'foreign');
|
|
115
182
|
ok('syncCommitMsgHook: foreign shell -> bytes untouched', fs.readFileSync(hookPath, 'utf8') === foreign);
|
|
116
183
|
ok('syncCommitMsgHook: foreign shell -> mode untouched', modeOf(hookPath) === 0o755);
|
|
184
|
+
ok('syncCommitMsgHook: foreign shell -> no .cjs written', !fs.existsSync(path.join(dir, CJS_NAME)));
|
|
117
185
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
118
186
|
}
|
|
119
187
|
|
|
@@ -124,7 +192,7 @@ function modeOf(p) { return fs.statSync(p).mode & 0o777; }
|
|
|
124
192
|
const foreign = '#!/bin/sh\necho "trailhead commit-msg hook (git). not really"\nexit 0\n';
|
|
125
193
|
fs.writeFileSync(hookPath, foreign);
|
|
126
194
|
fs.chmodSync(hookPath, 0o755);
|
|
127
|
-
const result = syncCommitMsgHook({ hooksDir: dir, templateText, hooksPathSet: false, fs });
|
|
195
|
+
const result = syncCommitMsgHook({ hooksDir: dir, templateText, hooksPathSet: false, cjsText, fs });
|
|
128
196
|
ok('syncCommitMsgHook: foreign wrapper mentioning phrase -> foreign', result.status === 'foreign');
|
|
129
197
|
ok('syncCommitMsgHook: foreign wrapper -> bytes untouched', fs.readFileSync(hookPath, 'utf8') === foreign);
|
|
130
198
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
@@ -138,10 +206,11 @@ function modeOf(p) { return fs.statSync(p).mode & 0o777; }
|
|
|
138
206
|
const targetContent = '#!/bin/sh\necho real\n';
|
|
139
207
|
fs.writeFileSync(targetPath, targetContent);
|
|
140
208
|
fs.symlinkSync(targetPath, hookPath);
|
|
141
|
-
const result = syncCommitMsgHook({ hooksDir: dir, templateText, hooksPathSet: false, fs });
|
|
209
|
+
const result = syncCommitMsgHook({ hooksDir: dir, templateText, hooksPathSet: false, cjsText, fs });
|
|
142
210
|
ok('syncCommitMsgHook: symlink -> foreign', result.status === 'foreign');
|
|
143
211
|
ok('syncCommitMsgHook: symlink -> still a symlink', fs.lstatSync(hookPath).isSymbolicLink());
|
|
144
212
|
ok('syncCommitMsgHook: symlink target untouched', fs.readFileSync(targetPath, 'utf8') === targetContent);
|
|
213
|
+
ok('syncCommitMsgHook: symlink -> no .cjs written', !fs.existsSync(path.join(dir, CJS_NAME)));
|
|
145
214
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
146
215
|
}
|
|
147
216
|
|
|
@@ -149,9 +218,9 @@ function modeOf(p) { return fs.statSync(p).mode & 0o777; }
|
|
|
149
218
|
{
|
|
150
219
|
const dir = mktmp();
|
|
151
220
|
const hookPath = path.join(dir, 'commit-msg');
|
|
152
|
-
const result = syncCommitMsgHook({ hooksDir: dir, templateText, hooksPathSet: true, fs });
|
|
221
|
+
const result = syncCommitMsgHook({ hooksDir: dir, templateText, hooksPathSet: true, cjsText, fs });
|
|
153
222
|
ok('syncCommitMsgHook: absent + hooksPathSet -> skipped', result.status === 'skipped');
|
|
154
|
-
ok('syncCommitMsgHook: absent + hooksPathSet -> nothing created', !fs.existsSync(hookPath));
|
|
223
|
+
ok('syncCommitMsgHook: absent + hooksPathSet -> nothing created', !fs.existsSync(hookPath) && !fs.existsSync(path.join(dir, CJS_NAME)));
|
|
155
224
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
156
225
|
}
|
|
157
226
|
|
|
@@ -226,6 +295,7 @@ function assertSingleJsonLine(out, label) {
|
|
|
226
295
|
const hookPath = path.join(dir, '.git', 'hooks', 'commit-msg');
|
|
227
296
|
ok('e2e fresh repo: hook file exists', fs.existsSync(hookPath));
|
|
228
297
|
ok('e2e fresh repo: hook is executable', (modeOf(hookPath) & 0o111) !== 0);
|
|
298
|
+
ok('e2e fresh repo: .cjs installed beside it', fs.readFileSync(path.join(dir, '.git', 'hooks', CJS_NAME), 'utf8') === cjsText);
|
|
229
299
|
|
|
230
300
|
const out2 = runScript(['--repo', dir], { env: gitEnv() });
|
|
231
301
|
const parsed2 = assertSingleJsonLine(out2, 'e2e fresh repo (2nd run)');
|
|
@@ -246,6 +316,24 @@ function assertSingleJsonLine(out, label) {
|
|
|
246
316
|
const parsed = assertSingleJsonLine(out, 'e2e seeded old hook');
|
|
247
317
|
ok('e2e seeded old hook: status upgraded', parsed.status === 'upgraded');
|
|
248
318
|
ok('e2e seeded old hook: content now matches template', fs.readFileSync(hookPath, 'utf8') === templateText);
|
|
319
|
+
ok('e2e seeded old hook: .cjs installed', fs.readFileSync(path.join(hooksDir, CJS_NAME), 'utf8') === cjsText);
|
|
320
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// seeded legacy single-file JS hook -> upgraded to wrapper + .cjs
|
|
324
|
+
{
|
|
325
|
+
const dir = mktmp();
|
|
326
|
+
execFileSync('git', ['init', '-q'], { cwd: dir, env: gitEnv() });
|
|
327
|
+
const hooksDir = path.join(dir, '.git', 'hooks');
|
|
328
|
+
fs.mkdirSync(hooksDir, { recursive: true });
|
|
329
|
+
const hookPath = path.join(hooksDir, 'commit-msg');
|
|
330
|
+
fs.writeFileSync(hookPath, legacyJsText);
|
|
331
|
+
fs.chmodSync(hookPath, 0o755);
|
|
332
|
+
const out = runScript(['--repo', dir], { env: gitEnv() });
|
|
333
|
+
const parsed = assertSingleJsonLine(out, 'e2e seeded legacy JS hook');
|
|
334
|
+
ok('e2e seeded legacy JS hook: status upgraded', parsed.status === 'upgraded');
|
|
335
|
+
ok('e2e seeded legacy JS hook: wrapper installed', fs.readFileSync(hookPath, 'utf8') === templateText);
|
|
336
|
+
ok('e2e seeded legacy JS hook: .cjs installed', fs.readFileSync(path.join(hooksDir, CJS_NAME), 'utf8') === cjsText);
|
|
249
337
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
250
338
|
}
|
|
251
339
|
|
|
@@ -263,6 +351,7 @@ function assertSingleJsonLine(out, label) {
|
|
|
263
351
|
const parsed = assertSingleJsonLine(out, 'e2e seeded foreign hook');
|
|
264
352
|
ok('e2e seeded foreign hook: status foreign', parsed.status === 'foreign');
|
|
265
353
|
ok('e2e seeded foreign hook: bytes untouched', fs.readFileSync(hookPath, 'utf8') === foreign);
|
|
354
|
+
ok('e2e seeded foreign hook: no .cjs written', !fs.existsSync(path.join(hooksDir, CJS_NAME)));
|
|
266
355
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
267
356
|
}
|
|
268
357
|
|
|
@@ -293,6 +382,7 @@ function assertSingleJsonLine(out, label) {
|
|
|
293
382
|
const parsed = assertSingleJsonLine(out, 'e2e core.hooksPath old hook');
|
|
294
383
|
ok('e2e core.hooksPath old hook: status upgraded', parsed.status === 'upgraded');
|
|
295
384
|
ok('e2e core.hooksPath old hook: upgraded in .githooks', fs.readFileSync(hookPath, 'utf8') === templateText);
|
|
385
|
+
ok('e2e core.hooksPath old hook: .cjs lands in .githooks', fs.readFileSync(path.join(githooksDir, CJS_NAME), 'utf8') === cjsText);
|
|
296
386
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
297
387
|
}
|
|
298
388
|
|
|
@@ -311,6 +401,7 @@ function assertSingleJsonLine(out, label) {
|
|
|
311
401
|
const parsed = assertSingleJsonLine(out, 'e2e core.hooksPath foreign hook');
|
|
312
402
|
ok('e2e core.hooksPath foreign hook: status foreign', parsed.status === 'foreign');
|
|
313
403
|
ok('e2e core.hooksPath foreign hook: untouched', fs.readFileSync(hookPath, 'utf8') === foreign);
|
|
404
|
+
ok('e2e core.hooksPath foreign hook: no .cjs written', !fs.existsSync(path.join(githooksDir, CJS_NAME)));
|
|
314
405
|
fs.rmSync(dir, { recursive: true, force: true });
|
|
315
406
|
}
|
|
316
407
|
|