@stonepandastudio/cairn 0.4.1 → 0.4.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/README.md +1 -1
- package/lib/init.js +48 -14
- package/package.json +1 -1
package/README.md
CHANGED
package/lib/init.js
CHANGED
|
@@ -10,22 +10,25 @@ const {
|
|
|
10
10
|
record,
|
|
11
11
|
writeManifest,
|
|
12
12
|
manifestPath,
|
|
13
|
+
hashContent,
|
|
13
14
|
} = require('./manifest');
|
|
14
15
|
const { listProviders } = require('./tracker');
|
|
15
16
|
const { makePaint } = require('./paint');
|
|
16
17
|
|
|
17
18
|
// `cairn init` — make a repo cairn-managed.
|
|
18
19
|
//
|
|
19
|
-
// It writes
|
|
20
|
+
// It writes:
|
|
20
21
|
// cairn.config.json hand-editable from here on; cairn never rewrites it
|
|
22
|
+
// except with --force
|
|
21
23
|
// _cairn/scripts/jira.js vendored shim, tracked in the manifest
|
|
22
24
|
// _cairn/manifest.json the record of what was written
|
|
23
25
|
//
|
|
24
|
-
// Plus,
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
26
|
+
// Plus, for every copied client the repo still carries (jira.js / youtrack.js /
|
|
27
|
+
// task-tracker.js under ai/scripts/), that file is replaced by the same shim —
|
|
28
|
+
// replacing rather than deleting because dozens of prose references name the path
|
|
29
|
+
// and the shim reads the same argv. A file already holding the shim is skipped; a
|
|
30
|
+
// file hand-edited away from what cairn wrote is kept and reported unless
|
|
31
|
+
// --force-shims. cairn never invents one of these paths in a repo that lacked it.
|
|
29
32
|
|
|
30
33
|
const SHIM_SOURCE = 'shims/jira.js';
|
|
31
34
|
const SHIM_TARGET = '_cairn/scripts/jira.js';
|
|
@@ -55,6 +58,8 @@ Usage: cairn init [options]
|
|
|
55
58
|
(only when the repo's app reads JIRA_*/YOUTRACK_* itself)
|
|
56
59
|
--no-shim do not vendor or replace the ai/scripts/*.js client shims
|
|
57
60
|
--force overwrite an existing cairn.config.json
|
|
61
|
+
--force-shims also replace an ai/scripts/*.js shim that was hand-edited
|
|
62
|
+
since cairn wrote it (kept untouched otherwise)
|
|
58
63
|
--dry-run print what would be written, write nothing
|
|
59
64
|
`;
|
|
60
65
|
|
|
@@ -69,6 +74,7 @@ function parseArgs(argv) {
|
|
|
69
74
|
envPrefix: '',
|
|
70
75
|
shim: true,
|
|
71
76
|
force: false,
|
|
77
|
+
forceShims: false,
|
|
72
78
|
dryRun: false,
|
|
73
79
|
color: process.stdout.isTTY,
|
|
74
80
|
};
|
|
@@ -83,6 +89,7 @@ function parseArgs(argv) {
|
|
|
83
89
|
else if (a === '--env-prefix') args.envPrefix = argv[++i];
|
|
84
90
|
else if (a === '--no-shim') args.shim = false;
|
|
85
91
|
else if (a === '--force') args.force = true;
|
|
92
|
+
else if (a === '--force-shims') args.forceShims = args.force = true;
|
|
86
93
|
else if (a === '--dry-run') args.dryRun = true;
|
|
87
94
|
else if (a === '--no-color') args.color = false;
|
|
88
95
|
else if (a === '-h' || a === '--help') args.help = true;
|
|
@@ -148,29 +155,52 @@ function main(argv = process.argv.slice(2)) {
|
|
|
148
155
|
return 2;
|
|
149
156
|
}
|
|
150
157
|
|
|
158
|
+
const manifest = readManifest(repoPath) || emptyManifest();
|
|
159
|
+
|
|
151
160
|
const planned = [];
|
|
161
|
+
const kept = [];
|
|
152
162
|
const config = buildConfig(args);
|
|
153
163
|
planned.push([CONFIG_NAME, JSON.stringify(config, null, 2) + '\n', null]);
|
|
154
164
|
|
|
155
165
|
const shim = readTemplate(SHIM_SOURCE);
|
|
156
166
|
if (args.shim) {
|
|
157
167
|
planned.push([SHIM_TARGET, shim, SHIM_SOURCE]);
|
|
158
|
-
//
|
|
159
|
-
//
|
|
168
|
+
// Replace a legacy client only where one is actually present. A file already
|
|
169
|
+
// holding the shim is left alone; one hand-edited away from what cairn wrote
|
|
170
|
+
// is kept unless --force — never silently overwrite an edit.
|
|
160
171
|
for (const target of LEGACY_SHIM_TARGETS) {
|
|
161
|
-
|
|
162
|
-
|
|
172
|
+
const abs = path.join(repoPath, target);
|
|
173
|
+
if (!fs.existsSync(abs)) continue;
|
|
174
|
+
const current = fs.readFileSync(abs, 'utf8');
|
|
175
|
+
const entry = manifest.files[target];
|
|
176
|
+
|
|
177
|
+
// Already the shim and already tracked — nothing to do. If it holds the
|
|
178
|
+
// shim but isn't in the manifest (someone copied it by hand), fall through
|
|
179
|
+
// so this run records it.
|
|
180
|
+
if (current === shim && entry) continue;
|
|
181
|
+
|
|
182
|
+
const modified = entry && hashContent(current) !== entry.hash;
|
|
183
|
+
if (modified && !args.forceShims) {
|
|
184
|
+
kept.push(target);
|
|
185
|
+
continue;
|
|
163
186
|
}
|
|
187
|
+
const note =
|
|
188
|
+
current === shim ? 'recording existing shim' : entry ? null : `replacing ${current.split('\n').length} lines`;
|
|
189
|
+
planned.push([target, shim, SHIM_SOURCE, note]);
|
|
164
190
|
}
|
|
165
191
|
}
|
|
166
192
|
|
|
167
193
|
if (args.dryRun) {
|
|
168
194
|
console.log(paint.bold(`cairn init --dry-run ${repoPath}`));
|
|
169
|
-
for (const [rel] of planned)
|
|
195
|
+
for (const [rel, , , note] of planned) {
|
|
196
|
+
console.log(` would write ${rel}${note ? paint.dim(` (${note})`) : ''}`);
|
|
197
|
+
}
|
|
198
|
+
for (const rel of kept) {
|
|
199
|
+
console.log(paint.yellow(` would keep ${rel} (hand-edited — pass --force-shims to replace)`));
|
|
200
|
+
}
|
|
170
201
|
return 0;
|
|
171
202
|
}
|
|
172
203
|
|
|
173
|
-
const manifest = readManifest(repoPath) || emptyManifest();
|
|
174
204
|
for (const [rel, content, source] of planned) {
|
|
175
205
|
const abs = path.join(repoPath, rel);
|
|
176
206
|
fs.mkdirSync(path.dirname(abs), { recursive: true });
|
|
@@ -182,10 +212,14 @@ function main(argv = process.argv.slice(2)) {
|
|
|
182
212
|
writeManifest(repoPath, manifest);
|
|
183
213
|
|
|
184
214
|
console.log(paint.bold(`cairn init ${repoPath}`));
|
|
185
|
-
for (const [rel, , source] of planned) {
|
|
186
|
-
|
|
215
|
+
for (const [rel, , source, note] of planned) {
|
|
216
|
+
const tag = note || source;
|
|
217
|
+
console.log(` ${paint.green('wrote')} ${rel}${tag ? paint.dim(` (${tag})`) : ''}`);
|
|
187
218
|
}
|
|
188
219
|
console.log(` ${paint.green('wrote')} ${path.relative(repoPath, manifestPath(repoPath)).replace(/\\/g, '/')}`);
|
|
220
|
+
for (const rel of kept) {
|
|
221
|
+
console.log(paint.yellow(` kept ${rel} (hand-edited since cairn wrote it — pass --force-shims to replace)`));
|
|
222
|
+
}
|
|
189
223
|
|
|
190
224
|
const gitignore = path.join(repoPath, '.gitignore');
|
|
191
225
|
const hasIgnore = fs.existsSync(gitignore) && /^_cairn\b/m.test(fs.readFileSync(gitignore, 'utf8'));
|
package/package.json
CHANGED