@rness/cli 0.7.0 → 0.8.1
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 +63 -11
- package/dist/bin/rness.js +1 -1
- package/dist/{chunk-VYP4L7BQ.js → chunk-ONLF4VFA.js} +419 -127
- package/dist/chunk-ONLF4VFA.js.map +1 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-VYP4L7BQ.js.map +0 -1
|
@@ -797,7 +797,7 @@ function classifyProbe(url, exitCode, stderr) {
|
|
|
797
797
|
var STDERR_FLUSH_MS = 200;
|
|
798
798
|
async function probeRemote(url, timeoutMs = 6e4, credentials) {
|
|
799
799
|
positional(url, "repository url");
|
|
800
|
-
return new Promise((
|
|
800
|
+
return new Promise((resolve6) => {
|
|
801
801
|
const auth = withCredentials(credentials);
|
|
802
802
|
const child = spawn(
|
|
803
803
|
"git",
|
|
@@ -816,7 +816,7 @@ async function probeRemote(url, timeoutMs = 6e4, credentials) {
|
|
|
816
816
|
settled = true;
|
|
817
817
|
clearTimeout(timer);
|
|
818
818
|
child.stderr?.destroy();
|
|
819
|
-
|
|
819
|
+
resolve6(probe);
|
|
820
820
|
};
|
|
821
821
|
const timer = setTimeout(() => {
|
|
822
822
|
child.kill("SIGKILL");
|
|
@@ -827,14 +827,14 @@ async function probeRemote(url, timeoutMs = 6e4, credentials) {
|
|
|
827
827
|
}, timeoutMs);
|
|
828
828
|
child.on("error", (e) => settle(classifyProbe(url, 1, e.message)));
|
|
829
829
|
child.on("exit", (code) => {
|
|
830
|
-
const
|
|
830
|
+
const finish2 = () => settle(classifyProbe(url, code ?? 1, chunks.join("")));
|
|
831
831
|
const stderr = child.stderr;
|
|
832
832
|
if (stderr === null || stderr.readableEnded || stderr.destroyed)
|
|
833
|
-
return
|
|
834
|
-
const flush = setTimeout(
|
|
833
|
+
return finish2();
|
|
834
|
+
const flush = setTimeout(finish2, STDERR_FLUSH_MS);
|
|
835
835
|
const done = () => {
|
|
836
836
|
clearTimeout(flush);
|
|
837
|
-
|
|
837
|
+
finish2();
|
|
838
838
|
};
|
|
839
839
|
stderr.once("end", done);
|
|
840
840
|
stderr.once("error", done);
|
|
@@ -1248,7 +1248,7 @@ async function detectGithubSsh(opts) {
|
|
|
1248
1248
|
...opts.interactive ? [] : ["-o", "BatchMode=yes"],
|
|
1249
1249
|
"git@github.com"
|
|
1250
1250
|
];
|
|
1251
|
-
return new Promise((
|
|
1251
|
+
return new Promise((resolve6) => {
|
|
1252
1252
|
const child = spawn2(opts.command ?? "ssh", args, {
|
|
1253
1253
|
stdio: [opts.interactive ? "inherit" : "ignore", "ignore", "pipe"]
|
|
1254
1254
|
});
|
|
@@ -1261,7 +1261,7 @@ async function detectGithubSsh(opts) {
|
|
|
1261
1261
|
settled = true;
|
|
1262
1262
|
clearTimeout(timer);
|
|
1263
1263
|
child.stderr?.destroy();
|
|
1264
|
-
|
|
1264
|
+
resolve6(access2);
|
|
1265
1265
|
};
|
|
1266
1266
|
const timer = setTimeout(() => {
|
|
1267
1267
|
child.kill("SIGKILL");
|
|
@@ -1269,7 +1269,7 @@ async function detectGithubSsh(opts) {
|
|
|
1269
1269
|
}, timeoutMs);
|
|
1270
1270
|
child.on("error", (e) => settle({ ok: false, reason: e.message }));
|
|
1271
1271
|
child.on("exit", (code) => {
|
|
1272
|
-
const
|
|
1272
|
+
const finish2 = () => {
|
|
1273
1273
|
const stderr2 = chunks.join("");
|
|
1274
1274
|
const login = parseSshGreeting(stderr2);
|
|
1275
1275
|
settle(
|
|
@@ -1281,11 +1281,11 @@ async function detectGithubSsh(opts) {
|
|
|
1281
1281
|
};
|
|
1282
1282
|
const stderr = child.stderr;
|
|
1283
1283
|
if (stderr === null || stderr.readableEnded || stderr.destroyed)
|
|
1284
|
-
return
|
|
1285
|
-
const flush = setTimeout(
|
|
1284
|
+
return finish2();
|
|
1285
|
+
const flush = setTimeout(finish2, STDERR_FLUSH_MS2);
|
|
1286
1286
|
const done = () => {
|
|
1287
1287
|
clearTimeout(flush);
|
|
1288
|
-
|
|
1288
|
+
finish2();
|
|
1289
1289
|
};
|
|
1290
1290
|
stderr.once("end", done);
|
|
1291
1291
|
stderr.once("error", done);
|
|
@@ -1390,7 +1390,7 @@ function reportError(e) {
|
|
|
1390
1390
|
}
|
|
1391
1391
|
|
|
1392
1392
|
// src/version.ts
|
|
1393
|
-
var VERSION = "0.
|
|
1393
|
+
var VERSION = "0.8.1";
|
|
1394
1394
|
|
|
1395
1395
|
// src/core/block.ts
|
|
1396
1396
|
import { createHash } from "crypto";
|
|
@@ -2030,12 +2030,12 @@ function sessionUi(p) {
|
|
|
2030
2030
|
},
|
|
2031
2031
|
async step(options, work, done) {
|
|
2032
2032
|
const label = options.sentence ?? tidy(options.doing);
|
|
2033
|
-
const
|
|
2033
|
+
const finish2 = (result) => done?.(result) ?? null;
|
|
2034
2034
|
const label_ = (line) => `${line[1]} ${line[0]}`;
|
|
2035
2035
|
if (options.git === true && !this.gitIsSilent) {
|
|
2036
2036
|
p.log.message(paint("idle", `${label}\u2026`));
|
|
2037
2037
|
const result = await work();
|
|
2038
|
-
const line =
|
|
2038
|
+
const line = finish2(result);
|
|
2039
2039
|
if (line !== null) say(line[0], label_(line));
|
|
2040
2040
|
return result;
|
|
2041
2041
|
}
|
|
@@ -2043,7 +2043,7 @@ function sessionUi(p) {
|
|
|
2043
2043
|
spin.start(label);
|
|
2044
2044
|
try {
|
|
2045
2045
|
const result = await work();
|
|
2046
|
-
const line =
|
|
2046
|
+
const line = finish2(result);
|
|
2047
2047
|
spin.stop(line === null ? label : label_(line));
|
|
2048
2048
|
return result;
|
|
2049
2049
|
} catch (e) {
|
|
@@ -2710,21 +2710,29 @@ function scaffoldDir() {
|
|
|
2710
2710
|
import { chmod as chmod2, mkdir as mkdir3, readFile as readFile7, stat as stat2, writeFile as writeFile2 } from "fs/promises";
|
|
2711
2711
|
import { dirname as dirname6, join as join14 } from "path";
|
|
2712
2712
|
var TOKENISED = /* @__PURE__ */ new Set(["package.json"]);
|
|
2713
|
-
async function
|
|
2714
|
-
const
|
|
2713
|
+
async function renderScaffold(source, tokens) {
|
|
2714
|
+
const files = [];
|
|
2715
2715
|
for (const rel of SCAFFOLD_FILES) {
|
|
2716
2716
|
if (rel === "rness.json") continue;
|
|
2717
2717
|
const from = join14(source, ...rel.split("/"));
|
|
2718
|
-
const targetRel = rel === "_gitignore" ? ".gitignore" : rel;
|
|
2719
|
-
const to = join14(dest, ...targetRel.split("/"));
|
|
2720
|
-
await mkdir3(dirname6(to), { recursive: true });
|
|
2721
2718
|
let content = await readFile7(from, "utf8");
|
|
2722
2719
|
if (TOKENISED.has(rel)) {
|
|
2723
2720
|
content = content.replaceAll("__RNESS_VERSION__", tokens.version).replaceAll("__RNESS_PM__", tokens.packageManager);
|
|
2724
2721
|
}
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2722
|
+
files.push({
|
|
2723
|
+
path: rel === "_gitignore" ? ".gitignore" : rel,
|
|
2724
|
+
content,
|
|
2725
|
+
executable: ((await stat2(from)).mode & 73) !== 0
|
|
2726
|
+
});
|
|
2727
|
+
}
|
|
2728
|
+
return files;
|
|
2729
|
+
}
|
|
2730
|
+
async function copyScaffold(dest, tokens) {
|
|
2731
|
+
for (const file of await renderScaffold(scaffoldDir(), tokens)) {
|
|
2732
|
+
const to = join14(dest, ...file.path.split("/"));
|
|
2733
|
+
await mkdir3(dirname6(to), { recursive: true });
|
|
2734
|
+
await writeFile2(to, file.content, "utf8");
|
|
2735
|
+
if (file.executable) await chmod2(to, 493);
|
|
2728
2736
|
}
|
|
2729
2737
|
}
|
|
2730
2738
|
|
|
@@ -2878,13 +2886,13 @@ function revokeUrl() {
|
|
|
2878
2886
|
}
|
|
2879
2887
|
|
|
2880
2888
|
// src/commands/create.ts
|
|
2881
|
-
import { mkdir as mkdir6, mkdtemp, rename as rename2, rm as
|
|
2882
|
-
import { tmpdir } from "os";
|
|
2883
|
-
import { join as
|
|
2889
|
+
import { mkdir as mkdir6, mkdtemp as mkdtemp2, rename as rename2, rm as rm6 } from "fs/promises";
|
|
2890
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
2891
|
+
import { join as join19, relative as relative4, resolve as resolve5 } from "path";
|
|
2884
2892
|
|
|
2885
2893
|
// src/core/new-workspace.ts
|
|
2886
|
-
import { mkdir as mkdir4, readdir as readdir2, rm as
|
|
2887
|
-
import { dirname as
|
|
2894
|
+
import { mkdir as mkdir4, readdir as readdir2, rm as rm5, stat as stat3 } from "fs/promises";
|
|
2895
|
+
import { dirname as dirname8, join as join17, relative as relative2 } from "path";
|
|
2888
2896
|
|
|
2889
2897
|
// src/core/pinned.ts
|
|
2890
2898
|
import { execFile as execFile4 } from "child_process";
|
|
@@ -3124,6 +3132,184 @@ async function syncPinned(root, shown, fallback) {
|
|
|
3124
3132
|
}
|
|
3125
3133
|
}
|
|
3126
3134
|
|
|
3135
|
+
// src/core/scaffold-git.ts
|
|
3136
|
+
import { execFile as execFile5 } from "child_process";
|
|
3137
|
+
import { mkdtemp, realpath as realpath2, rm as rm4, writeFile as writeFile3 } from "fs/promises";
|
|
3138
|
+
import { tmpdir } from "os";
|
|
3139
|
+
import { dirname as dirname7, join as join16, resolve as resolve3 } from "path";
|
|
3140
|
+
import { promisify as promisify5 } from "util";
|
|
3141
|
+
var execFileP5 = promisify5(execFile5);
|
|
3142
|
+
var CREATE_SUBJECT = "chore: rness workspace context";
|
|
3143
|
+
var SCAFFOLD_SUBJECT = /^chore: rness scaffold (\S+)$/;
|
|
3144
|
+
var SCAFFOLD_TRAILER = "Rness-Scaffold";
|
|
3145
|
+
async function run(dir, args, env = {}) {
|
|
3146
|
+
try {
|
|
3147
|
+
const { stdout, stderr } = await execFileP5("git", [...args], {
|
|
3148
|
+
cwd: dir,
|
|
3149
|
+
env: {
|
|
3150
|
+
...process.env,
|
|
3151
|
+
...env,
|
|
3152
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
3153
|
+
GIT_CEILING_DIRECTORIES: dirname7(resolve3(dir))
|
|
3154
|
+
},
|
|
3155
|
+
maxBuffer: 16 * 1024 * 1024
|
|
3156
|
+
});
|
|
3157
|
+
return { code: 0, stdout, stderr };
|
|
3158
|
+
} catch (e) {
|
|
3159
|
+
const err = e;
|
|
3160
|
+
return {
|
|
3161
|
+
code: typeof err.code === "number" ? err.code : 1,
|
|
3162
|
+
stdout: err.stdout ?? "",
|
|
3163
|
+
stderr: err.stderr ?? String(e)
|
|
3164
|
+
};
|
|
3165
|
+
}
|
|
3166
|
+
}
|
|
3167
|
+
async function must(dir, args, env = {}) {
|
|
3168
|
+
const r = await run(dir, args, env);
|
|
3169
|
+
if (r.code !== 0) {
|
|
3170
|
+
const first = r.stderr.split("\n").find((l) => l.trim() !== "") ?? "unknown error";
|
|
3171
|
+
throw new Error(`git ${args[0] ?? ""} failed: ${first.trim()}`);
|
|
3172
|
+
}
|
|
3173
|
+
return r.stdout.trim();
|
|
3174
|
+
}
|
|
3175
|
+
function scaffoldMessage(subject, version) {
|
|
3176
|
+
return `${subject}
|
|
3177
|
+
|
|
3178
|
+
${SCAFFOLD_TRAILER}: ${version}`;
|
|
3179
|
+
}
|
|
3180
|
+
async function findScaffoldBase(rnessDir) {
|
|
3181
|
+
const log = await run(rnessDir, [
|
|
3182
|
+
"log",
|
|
3183
|
+
"--topo-order",
|
|
3184
|
+
`--format=%H%x1f%P%x1f%s%x1f%(trailers:key=${SCAFFOLD_TRAILER},valueonly,separator=%x2C)%x1e`,
|
|
3185
|
+
"HEAD"
|
|
3186
|
+
]);
|
|
3187
|
+
if (log.code !== 0) return null;
|
|
3188
|
+
const commits = log.stdout.split("").map((r) => r.trim()).filter((r) => r !== "").map((r) => {
|
|
3189
|
+
const [hash = "", parents = "", subject = "", trailer = ""] = r.split("");
|
|
3190
|
+
return { hash, parents: parents.trim(), subject, trailer: trailer.trim() };
|
|
3191
|
+
});
|
|
3192
|
+
for (const c of commits) {
|
|
3193
|
+
const m = SCAFFOLD_SUBJECT.exec(c.subject);
|
|
3194
|
+
if (m !== null) return { commit: c.hash, version: m[1] ?? null };
|
|
3195
|
+
}
|
|
3196
|
+
const root = commits.find(
|
|
3197
|
+
(c) => c.parents === "" && c.subject === CREATE_SUBJECT
|
|
3198
|
+
);
|
|
3199
|
+
if (root === void 0) return null;
|
|
3200
|
+
return {
|
|
3201
|
+
commit: root.hash,
|
|
3202
|
+
version: root.trailer === "" ? null : root.trailer
|
|
3203
|
+
};
|
|
3204
|
+
}
|
|
3205
|
+
async function buildScaffoldCommit(rnessDir, base, files, version) {
|
|
3206
|
+
const scratch = await mkdtemp(join16(tmpdir(), "rness-scaffold-"));
|
|
3207
|
+
const env = { GIT_INDEX_FILE: join16(scratch, "index") };
|
|
3208
|
+
try {
|
|
3209
|
+
await must(
|
|
3210
|
+
rnessDir,
|
|
3211
|
+
["read-tree", ...base === null ? ["--empty"] : [base]],
|
|
3212
|
+
env
|
|
3213
|
+
);
|
|
3214
|
+
for (const [i, file] of files.entries()) {
|
|
3215
|
+
const tmp = join16(scratch, `blob-${i}`);
|
|
3216
|
+
await writeFile3(tmp, file.content, "utf8");
|
|
3217
|
+
const blob = await must(rnessDir, [
|
|
3218
|
+
"hash-object",
|
|
3219
|
+
"-w",
|
|
3220
|
+
"--no-filters",
|
|
3221
|
+
"--",
|
|
3222
|
+
tmp
|
|
3223
|
+
]);
|
|
3224
|
+
await must(
|
|
3225
|
+
rnessDir,
|
|
3226
|
+
[
|
|
3227
|
+
"update-index",
|
|
3228
|
+
"--add",
|
|
3229
|
+
"--cacheinfo",
|
|
3230
|
+
`${file.executable ? "100755" : "100644"},${blob},${file.path}`
|
|
3231
|
+
],
|
|
3232
|
+
env
|
|
3233
|
+
);
|
|
3234
|
+
}
|
|
3235
|
+
const tree = await must(rnessDir, ["write-tree"], env);
|
|
3236
|
+
return await must(rnessDir, [
|
|
3237
|
+
"commit-tree",
|
|
3238
|
+
tree,
|
|
3239
|
+
...base === null ? [] : ["-p", base],
|
|
3240
|
+
"-m",
|
|
3241
|
+
scaffoldMessage(`chore: rness scaffold ${version}`, version)
|
|
3242
|
+
]);
|
|
3243
|
+
} finally {
|
|
3244
|
+
await rm4(scratch, { recursive: true, force: true });
|
|
3245
|
+
}
|
|
3246
|
+
}
|
|
3247
|
+
async function blobAt(rnessDir, rev, path) {
|
|
3248
|
+
const r = await run(rnessDir, [
|
|
3249
|
+
"rev-parse",
|
|
3250
|
+
"--verify",
|
|
3251
|
+
"--quiet",
|
|
3252
|
+
`${rev}:${path}`
|
|
3253
|
+
]);
|
|
3254
|
+
return r.code === 0 ? r.stdout.trim() : null;
|
|
3255
|
+
}
|
|
3256
|
+
async function mergeScaffold(rnessDir, commit, base) {
|
|
3257
|
+
await run(rnessDir, [
|
|
3258
|
+
"merge",
|
|
3259
|
+
"--no-commit",
|
|
3260
|
+
"--no-ff",
|
|
3261
|
+
...base === null ? ["--allow-unrelated-histories"] : [],
|
|
3262
|
+
commit
|
|
3263
|
+
]);
|
|
3264
|
+
const conflicts = (await must(rnessDir, ["diff", "--name-only", "--diff-filter=U"])).split("\n").filter((l) => l !== "");
|
|
3265
|
+
const changes = [];
|
|
3266
|
+
const status2 = await must(rnessDir, [
|
|
3267
|
+
"diff",
|
|
3268
|
+
"--cached",
|
|
3269
|
+
"--name-status",
|
|
3270
|
+
"HEAD"
|
|
3271
|
+
]);
|
|
3272
|
+
for (const line of status2.split("\n")) {
|
|
3273
|
+
const [letter = "", path = ""] = line.split(" ");
|
|
3274
|
+
if (path === "" || conflicts.includes(path)) continue;
|
|
3275
|
+
if (letter === "A") changes.push(["added", path]);
|
|
3276
|
+
else if (letter === "D") changes.push(["removed", path]);
|
|
3277
|
+
else if (letter === "M") {
|
|
3278
|
+
const untouched = base !== null && await blobAt(rnessDir, "HEAD", path) === await blobAt(rnessDir, base, path);
|
|
3279
|
+
changes.push([untouched ? "updated" : "merged", path]);
|
|
3280
|
+
}
|
|
3281
|
+
}
|
|
3282
|
+
return { conflicts, changes };
|
|
3283
|
+
}
|
|
3284
|
+
async function isShallow(rnessDir) {
|
|
3285
|
+
const r = await run(rnessDir, ["rev-parse", "--is-shallow-repository"]);
|
|
3286
|
+
return r.code === 0 && r.stdout.trim() === "true";
|
|
3287
|
+
}
|
|
3288
|
+
async function isRepository2(rnessDir) {
|
|
3289
|
+
const r = await run(rnessDir, ["rev-parse", "--show-toplevel"]);
|
|
3290
|
+
if (r.code !== 0) return false;
|
|
3291
|
+
const real = (p) => realpath2(p).catch(() => resolve3(p));
|
|
3292
|
+
return await real(r.stdout.trim()) === await real(rnessDir);
|
|
3293
|
+
}
|
|
3294
|
+
async function withoutRedundantKeeps(rnessDir, files) {
|
|
3295
|
+
const kept = [];
|
|
3296
|
+
for (const file of files) {
|
|
3297
|
+
if (file.path.endsWith("/.gitkeep")) {
|
|
3298
|
+
const dir = file.path.slice(0, -"/.gitkeep".length);
|
|
3299
|
+
const listed = await run(rnessDir, [
|
|
3300
|
+
"ls-tree",
|
|
3301
|
+
"--name-only",
|
|
3302
|
+
"HEAD",
|
|
3303
|
+
"--",
|
|
3304
|
+
`${dir}/`
|
|
3305
|
+
]);
|
|
3306
|
+
if (listed.code === 0 && listed.stdout.trim() !== "") continue;
|
|
3307
|
+
}
|
|
3308
|
+
kept.push(file);
|
|
3309
|
+
}
|
|
3310
|
+
return kept;
|
|
3311
|
+
}
|
|
3312
|
+
|
|
3127
3313
|
// src/core/new-workspace.ts
|
|
3128
3314
|
async function isEmptyDir(dir) {
|
|
3129
3315
|
return (await readdir2(dir)).length === 0;
|
|
@@ -3138,11 +3324,11 @@ async function insideWorkspace(dir) {
|
|
|
3138
3324
|
}
|
|
3139
3325
|
async function targetProblem(cwd, root, pm) {
|
|
3140
3326
|
const shown = relative2(cwd, root) || ".";
|
|
3141
|
-
if (await insideWorkspace(cwd) || await insideWorkspace(
|
|
3327
|
+
if (await insideWorkspace(cwd) || await insideWorkspace(dirname8(root)))
|
|
3142
3328
|
return "already inside an rness workspace; create runs from outside one";
|
|
3143
3329
|
if (!await exists(root)) return null;
|
|
3144
|
-
if (await exists(
|
|
3145
|
-
if (!await exists(
|
|
3330
|
+
if (await exists(join17(root, ".rness", "rness.json"))) {
|
|
3331
|
+
if (!await exists(join17(root, ".rness", "node_modules")))
|
|
3146
3332
|
return `${shown} holds an rness workspace whose dependencies are not installed; cd ${shown}/.rness && ${pm} install, then ${rnessCommand()} sync`;
|
|
3147
3333
|
return `${shown} already holds an rness workspace (.rness/); run ${rnessCommand()} add inside it to add repositories`;
|
|
3148
3334
|
}
|
|
@@ -3165,7 +3351,7 @@ async function installContext(input) {
|
|
|
3165
3351
|
}
|
|
3166
3352
|
async function buildContext(input) {
|
|
3167
3353
|
const { ui, root, shown, pm } = input;
|
|
3168
|
-
const rnessDir =
|
|
3354
|
+
const rnessDir = join17(root, ".rness");
|
|
3169
3355
|
const pmVersion = await packageManagerVersion(pm);
|
|
3170
3356
|
await mkdir4(root, { recursive: true });
|
|
3171
3357
|
try {
|
|
@@ -3179,9 +3365,9 @@ async function buildContext(input) {
|
|
|
3179
3365
|
return true;
|
|
3180
3366
|
} catch (e) {
|
|
3181
3367
|
reportError(e);
|
|
3182
|
-
await
|
|
3368
|
+
await rm5(rnessDir, { recursive: true, force: true }).catch(() => void 0);
|
|
3183
3369
|
if (await isEmptyDir(root).catch(() => false))
|
|
3184
|
-
await
|
|
3370
|
+
await rm5(root, { recursive: true, force: true }).catch(() => void 0);
|
|
3185
3371
|
process.stderr.write(
|
|
3186
3372
|
`removed ${shown}/.rness after the failure; fix it and retry
|
|
3187
3373
|
`
|
|
@@ -3193,7 +3379,7 @@ async function commitContext(input) {
|
|
|
3193
3379
|
const { ui, rnessDir, shown } = input;
|
|
3194
3380
|
await init(rnessDir);
|
|
3195
3381
|
try {
|
|
3196
|
-
await commitAll(rnessDir,
|
|
3382
|
+
await commitAll(rnessDir, scaffoldMessage(CREATE_SUBJECT, VERSION));
|
|
3197
3383
|
ui.line("committed", `${shown}/.rness`);
|
|
3198
3384
|
} catch (e) {
|
|
3199
3385
|
ui.warn(
|
|
@@ -3234,7 +3420,7 @@ async function syncBlocks(ui, root, shown, inPlace, sshWorks) {
|
|
|
3234
3420
|
|
|
3235
3421
|
// src/commands/create-blank.ts
|
|
3236
3422
|
import { mkdir as mkdir5 } from "fs/promises";
|
|
3237
|
-
import { join as
|
|
3423
|
+
import { join as join18, relative as relative3, resolve as resolve4 } from "path";
|
|
3238
3424
|
var WORKSPACE_NAME = /^(?!\.{1,2}$)[A-Za-z0-9._][A-Za-z0-9._-]*$/;
|
|
3239
3425
|
function workspaceNameError(name) {
|
|
3240
3426
|
return `workspace name "${name}" may only contain letters, digits, '.', '_' and '-', not starting with '-'`;
|
|
@@ -3266,7 +3452,7 @@ async function createBlank(input) {
|
|
|
3266
3452
|
name = answer.trim();
|
|
3267
3453
|
prompted = true;
|
|
3268
3454
|
}
|
|
3269
|
-
const root =
|
|
3455
|
+
const root = resolve4(cwd, name);
|
|
3270
3456
|
const shown = relative3(cwd, root) || ".";
|
|
3271
3457
|
const problem = await targetProblem(cwd, root, pm);
|
|
3272
3458
|
if (problem !== null) {
|
|
@@ -3308,8 +3494,8 @@ async function createBlank(input) {
|
|
|
3308
3494
|
kind: "blank workspace"
|
|
3309
3495
|
});
|
|
3310
3496
|
if (!built) return 1;
|
|
3311
|
-
await mkdir5(
|
|
3312
|
-
await commitContext({ ui, rnessDir:
|
|
3497
|
+
await mkdir5(join18(root, "org"), { recursive: true });
|
|
3498
|
+
await commitContext({ ui, rnessDir: join18(root, ".rness"), shown });
|
|
3313
3499
|
const code = await syncBlocks(
|
|
3314
3500
|
ui,
|
|
3315
3501
|
root,
|
|
@@ -3469,7 +3655,7 @@ async function cloneSelection(input) {
|
|
|
3469
3655
|
{ doing: `cloning org/${repo}`, git: true },
|
|
3470
3656
|
() => clone(
|
|
3471
3657
|
entry.url,
|
|
3472
|
-
|
|
3658
|
+
join19(input.root, "org", repo),
|
|
3473
3659
|
input.provider.credentialsFor(entry.url)
|
|
3474
3660
|
),
|
|
3475
3661
|
() => ["cloned", `org/${repo}`]
|
|
@@ -3738,7 +3924,7 @@ async function createCommand(opts, deps = {}) {
|
|
|
3738
3924
|
org = answer.trim();
|
|
3739
3925
|
prompted = true;
|
|
3740
3926
|
}
|
|
3741
|
-
const root =
|
|
3927
|
+
const root = resolve5(cwd, org);
|
|
3742
3928
|
const shown = relative4(cwd, root) || ".";
|
|
3743
3929
|
const problem = await targetProblem(cwd, root, pm);
|
|
3744
3930
|
if (problem !== null) {
|
|
@@ -3793,8 +3979,8 @@ async function createCommand(opts, deps = {}) {
|
|
|
3793
3979
|
scopes: {}
|
|
3794
3980
|
};
|
|
3795
3981
|
const staged = async () => {
|
|
3796
|
-
staging ??= await
|
|
3797
|
-
return
|
|
3982
|
+
staging ??= await mkdtemp2(join19(tmpdir2(), "rness-join-"));
|
|
3983
|
+
return join19(staging, ".rness");
|
|
3798
3984
|
};
|
|
3799
3985
|
if (joining) {
|
|
3800
3986
|
const stagedDir = await staged();
|
|
@@ -3852,7 +4038,7 @@ async function createCommand(opts, deps = {}) {
|
|
|
3852
4038
|
});
|
|
3853
4039
|
if (p.isCancel(ok) || ok !== true) return cancelled(ui);
|
|
3854
4040
|
}
|
|
3855
|
-
const rnessDir =
|
|
4041
|
+
const rnessDir = join19(root, ".rness");
|
|
3856
4042
|
const install = () => installContext({ ui, pm, rnessDir, skip: opts.skipInstall === true });
|
|
3857
4043
|
if (joining) {
|
|
3858
4044
|
await mkdir6(root, { recursive: true });
|
|
@@ -3865,7 +4051,7 @@ async function createCommand(opts, deps = {}) {
|
|
|
3865
4051
|
ui.line("cloned", `${shown}/.rness (joined ${org})`);
|
|
3866
4052
|
if (opts.pm === void 0) pm = await workspacePackageManager(rnessDir);
|
|
3867
4053
|
await install();
|
|
3868
|
-
await mkdir6(
|
|
4054
|
+
await mkdir6(join19(root, "org"), { recursive: true });
|
|
3869
4055
|
const failures2 = await cloneSelection({
|
|
3870
4056
|
root,
|
|
3871
4057
|
rnessDir,
|
|
@@ -3918,7 +4104,7 @@ ${next2.map((l) => ` ${l}`).join("\n")}
|
|
|
3918
4104
|
kind: "new workspace"
|
|
3919
4105
|
});
|
|
3920
4106
|
if (!built) return 1;
|
|
3921
|
-
await mkdir6(
|
|
4107
|
+
await mkdir6(join19(root, "org"), { recursive: true });
|
|
3922
4108
|
const failures = await cloneSelection({
|
|
3923
4109
|
root,
|
|
3924
4110
|
rnessDir,
|
|
@@ -3985,7 +4171,7 @@ ${next2.map((l) => ` ${l}`).join("\n")}
|
|
|
3985
4171
|
return reportError(e);
|
|
3986
4172
|
} finally {
|
|
3987
4173
|
if (staging !== void 0)
|
|
3988
|
-
await
|
|
4174
|
+
await rm6(staging, { recursive: true, force: true }).catch(() => void 0);
|
|
3989
4175
|
}
|
|
3990
4176
|
}
|
|
3991
4177
|
|
|
@@ -4018,17 +4204,16 @@ async function logoutCommand() {
|
|
|
4018
4204
|
}
|
|
4019
4205
|
|
|
4020
4206
|
// src/commands/upgrade.ts
|
|
4021
|
-
import { execFile as
|
|
4022
|
-
import {
|
|
4023
|
-
import {
|
|
4024
|
-
import {
|
|
4025
|
-
|
|
4207
|
+
import { execFile as execFile6 } from "child_process";
|
|
4208
|
+
import { mkdtemp as mkdtemp3, readFile as readFile9, rm as rm7 } from "fs/promises";
|
|
4209
|
+
import { tmpdir as tmpdir3 } from "os";
|
|
4210
|
+
import { basename as basename5, join as join20, relative as relative5 } from "path";
|
|
4211
|
+
import { promisify as promisify6 } from "util";
|
|
4212
|
+
var execFileP6 = promisify6(execFile6);
|
|
4026
4213
|
var NOTES = "https://github.com/rness-dev/rness/tree/main/packages/cli#readme";
|
|
4027
|
-
var OLD_WORKFLOW_RUN = /npx --yes @rness\/cli@(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?) validate/;
|
|
4028
|
-
var WORKFLOW_RUN = `npx --yes "@rness/cli@$(node -p "require('./package.json').devDependencies['@rness/cli']")" validate`;
|
|
4029
4214
|
async function latestVersion() {
|
|
4030
4215
|
try {
|
|
4031
|
-
const { stdout } = await
|
|
4216
|
+
const { stdout } = await execFileP6(
|
|
4032
4217
|
"npm",
|
|
4033
4218
|
["view", "@rness/cli@latest", "version"],
|
|
4034
4219
|
{ timeout: 3e4 }
|
|
@@ -4039,7 +4224,70 @@ async function latestVersion() {
|
|
|
4039
4224
|
return null;
|
|
4040
4225
|
}
|
|
4041
4226
|
}
|
|
4042
|
-
async function
|
|
4227
|
+
async function scaffoldFor(version, rnessDir) {
|
|
4228
|
+
if (version === VERSION) return { dir: scaffoldDir() };
|
|
4229
|
+
const installed = await readPinnedCli(rnessDir);
|
|
4230
|
+
const inside = installed === null ? null : join20(installed.dir, "scaffold");
|
|
4231
|
+
if (installed?.version === version && inside !== null && await exists(join20(inside, "package.json")))
|
|
4232
|
+
return { dir: inside };
|
|
4233
|
+
const scratch = await mkdtemp3(join20(tmpdir3(), "rness-pack-"));
|
|
4234
|
+
const cleanup = () => rm7(scratch, { recursive: true, force: true });
|
|
4235
|
+
try {
|
|
4236
|
+
const { stdout } = await execFileP6(
|
|
4237
|
+
"npm",
|
|
4238
|
+
[
|
|
4239
|
+
"pack",
|
|
4240
|
+
`@rness/cli@${version}`,
|
|
4241
|
+
"--pack-destination",
|
|
4242
|
+
scratch,
|
|
4243
|
+
"--silent"
|
|
4244
|
+
],
|
|
4245
|
+
{ timeout: 6e4 }
|
|
4246
|
+
);
|
|
4247
|
+
const tarball = stdout.trim().split("\n").at(-1) ?? "";
|
|
4248
|
+
await execFileP6("tar", ["-xzf", join20(scratch, tarball), "-C", scratch]);
|
|
4249
|
+
return { dir: join20(scratch, "package", "scaffold"), cleanup };
|
|
4250
|
+
} catch (e) {
|
|
4251
|
+
await cleanup();
|
|
4252
|
+
throw new Error(
|
|
4253
|
+
`cannot get the @rness/cli ${version} scaffold (npm pack): ${e instanceof Error ? e.message.split("\n")[0] : String(e)}`,
|
|
4254
|
+
{ cause: e }
|
|
4255
|
+
);
|
|
4256
|
+
}
|
|
4257
|
+
}
|
|
4258
|
+
async function declaredManager(rnessDir, pm) {
|
|
4259
|
+
try {
|
|
4260
|
+
const pkg = JSON.parse(
|
|
4261
|
+
await readFile9(join20(rnessDir, "package.json"), "utf8")
|
|
4262
|
+
);
|
|
4263
|
+
if (typeof pkg.packageManager === "string") return pkg.packageManager;
|
|
4264
|
+
} catch {
|
|
4265
|
+
}
|
|
4266
|
+
return `${pm}@${await packageManagerVersion(pm)}`;
|
|
4267
|
+
}
|
|
4268
|
+
function finish(ui, cwd, rnessDir, label, target) {
|
|
4269
|
+
const rel = relative5(cwd, rnessDir) || ".";
|
|
4270
|
+
const next = [
|
|
4271
|
+
`git -C ${rel} add -A && git -C ${rel} commit -m "chore: rness ${target}"`,
|
|
4272
|
+
"# teammates: git pull \u2014 the next rness command installs it"
|
|
4273
|
+
];
|
|
4274
|
+
if (ui.session) {
|
|
4275
|
+
ui.note("Next steps", next);
|
|
4276
|
+
ui.outro(`${label} runs @rness/cli ${target}`);
|
|
4277
|
+
} else
|
|
4278
|
+
process.stdout.write(
|
|
4279
|
+
[
|
|
4280
|
+
"",
|
|
4281
|
+
status("upgraded", `${label} to @rness/cli ${target}`),
|
|
4282
|
+
"",
|
|
4283
|
+
"Next:",
|
|
4284
|
+
...next.map((line) => ` ${line}`),
|
|
4285
|
+
""
|
|
4286
|
+
].join("\n")
|
|
4287
|
+
);
|
|
4288
|
+
return 0;
|
|
4289
|
+
}
|
|
4290
|
+
async function upgradeCommand(version, opts, terminal = defaultTerminal, deps = {}) {
|
|
4043
4291
|
const cwd = opts.cwd ?? process.cwd();
|
|
4044
4292
|
if (version !== void 0 && !EXACT_VERSION.test(version)) {
|
|
4045
4293
|
process.stderr.write(
|
|
@@ -4081,7 +4329,21 @@ async function upgradeCommand(version, opts, terminal = defaultTerminal) {
|
|
|
4081
4329
|
return 1;
|
|
4082
4330
|
}
|
|
4083
4331
|
const installed = (await readPinnedCli(ws.rnessDir))?.version ?? null;
|
|
4084
|
-
if (
|
|
4332
|
+
if (!await isRepository2(ws.rnessDir)) {
|
|
4333
|
+
process.stderr.write(`${label} is not a git repository
|
|
4334
|
+
`);
|
|
4335
|
+
return 1;
|
|
4336
|
+
}
|
|
4337
|
+
if (!await isClean(ws.rnessDir)) {
|
|
4338
|
+
process.stderr.write(
|
|
4339
|
+
`${label} has uncommitted changes; commit or stash them, then ${rnessCommand()} upgrade
|
|
4340
|
+
`
|
|
4341
|
+
);
|
|
4342
|
+
return 1;
|
|
4343
|
+
}
|
|
4344
|
+
const base = await findScaffoldBase(ws.rnessDir);
|
|
4345
|
+
const scaffoldCurrent = base !== null && base.version === target;
|
|
4346
|
+
if (pin.spec === target && installed === target && scaffoldCurrent) {
|
|
4085
4347
|
if (ui.session) ui.outro(`Already at ${target}`);
|
|
4086
4348
|
else process.stdout.write(`already at ${target}
|
|
4087
4349
|
`);
|
|
@@ -4096,7 +4358,13 @@ async function upgradeCommand(version, opts, terminal = defaultTerminal) {
|
|
|
4096
4358
|
return 1;
|
|
4097
4359
|
}
|
|
4098
4360
|
const pm = await workspacePackageManager(ws.rnessDir);
|
|
4099
|
-
if (pin.spec === target)
|
|
4361
|
+
if (pin.spec === target && installed === target)
|
|
4362
|
+
ui.line(
|
|
4363
|
+
"scaffold",
|
|
4364
|
+
`@rness/cli ${target} \u2014 merging it into ${label}`,
|
|
4365
|
+
`Merging the @rness/cli ${target} scaffold into ${label}`
|
|
4366
|
+
);
|
|
4367
|
+
else if (pin.spec === target)
|
|
4100
4368
|
ui.line(
|
|
4101
4369
|
"install",
|
|
4102
4370
|
`@rness/cli ${target} in ${label} (${pm}) \u2014 ${installed ?? "nothing"} is installed`
|
|
@@ -4118,46 +4386,64 @@ async function upgradeCommand(version, opts, terminal = defaultTerminal) {
|
|
|
4118
4386
|
return 1;
|
|
4119
4387
|
}
|
|
4120
4388
|
}
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4389
|
+
let merged = false;
|
|
4390
|
+
if (!scaffoldCurrent) {
|
|
4391
|
+
const source = await (deps.scaffoldFor ?? scaffoldFor)(
|
|
4392
|
+
target,
|
|
4393
|
+
ws.rnessDir
|
|
4394
|
+
);
|
|
4395
|
+
try {
|
|
4396
|
+
const files = await renderScaffold(source.dir, {
|
|
4397
|
+
version: target,
|
|
4398
|
+
packageManager: await declaredManager(ws.rnessDir, pm)
|
|
4399
|
+
});
|
|
4400
|
+
if (base === null)
|
|
4401
|
+
ui.line(
|
|
4402
|
+
"adopting",
|
|
4403
|
+
`the @rness/cli ${target} scaffold (no scaffold commit in ${label} yet)`,
|
|
4404
|
+
`Adopting the @rness/cli ${target} scaffold \u2014 ${label} has no scaffold commit yet`
|
|
4405
|
+
);
|
|
4406
|
+
else
|
|
4407
|
+
ui.line(
|
|
4408
|
+
"merging",
|
|
4409
|
+
`the @rness/cli ${target} scaffold`,
|
|
4410
|
+
`Merging the @rness/cli ${target} scaffold`
|
|
4411
|
+
);
|
|
4412
|
+
const commit = await buildScaffoldCommit(
|
|
4413
|
+
ws.rnessDir,
|
|
4414
|
+
base?.commit ?? null,
|
|
4415
|
+
base === null ? await withoutRedundantKeeps(ws.rnessDir, files) : files,
|
|
4416
|
+
target
|
|
4138
4417
|
);
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4418
|
+
const result = await mergeScaffold(
|
|
4419
|
+
ws.rnessDir,
|
|
4420
|
+
commit,
|
|
4421
|
+
base?.commit ?? null
|
|
4142
4422
|
);
|
|
4143
|
-
|
|
4144
|
-
|
|
4423
|
+
for (const [change, path] of result.changes) ui.line(change, path);
|
|
4424
|
+
if (result.conflicts.length > 0) {
|
|
4425
|
+
for (const path of result.conflicts) ui.error(`conflict ${path}`);
|
|
4426
|
+
const rel = relative5(cwd, ws.rnessDir) || ".";
|
|
4427
|
+
ui.hint(
|
|
4428
|
+
`resolve them in ${rel} (git checkout --ours <file> keeps yours, --theirs takes the scaffold's, or edit), git add, git commit, then ${rnessCommand()} upgrade again`,
|
|
4429
|
+
"stderr"
|
|
4430
|
+
);
|
|
4431
|
+
return 1;
|
|
4432
|
+
}
|
|
4433
|
+
merged = true;
|
|
4434
|
+
} finally {
|
|
4435
|
+
await source.cleanup?.();
|
|
4145
4436
|
}
|
|
4146
4437
|
}
|
|
4147
|
-
const
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
);
|
|
4156
|
-
ui.line(
|
|
4157
|
-
"wrote",
|
|
4158
|
-
".rness/.github/dependabot.yml (@rness/cli now moves by pull request)"
|
|
4159
|
-
);
|
|
4160
|
-
}
|
|
4438
|
+
const packageFile = join20(ws.rnessDir, "package.json");
|
|
4439
|
+
const restore = /* @__PURE__ */ new Map([
|
|
4440
|
+
[packageFile, await readFile9(packageFile, "utf8")]
|
|
4441
|
+
]);
|
|
4442
|
+
const moved = await readPin(ws.rnessDir);
|
|
4443
|
+
if (moved !== null && moved.spec !== target)
|
|
4444
|
+
await writePin(ws.rnessDir, moved.spec, target);
|
|
4445
|
+
if (pin.spec === target && installed === target)
|
|
4446
|
+
return finish(ui, cwd, ws.rnessDir, label, target);
|
|
4161
4447
|
try {
|
|
4162
4448
|
await ui.step(
|
|
4163
4449
|
{ doing: `installing dependencies with ${pm}` },
|
|
@@ -4165,10 +4451,20 @@ async function upgradeCommand(version, opts, terminal = defaultTerminal) {
|
|
|
4165
4451
|
() => ["installed", `dependencies with ${pm}`]
|
|
4166
4452
|
);
|
|
4167
4453
|
} catch (e) {
|
|
4168
|
-
for (const [file, text] of restore) await writeFileAtomic(file, text);
|
|
4169
4454
|
const message = e instanceof Error ? e.message : String(e);
|
|
4170
4455
|
ui.error(message);
|
|
4171
|
-
|
|
4456
|
+
if (!merged) {
|
|
4457
|
+
for (const [file, text] of restore) await writeFileAtomic(file, text);
|
|
4458
|
+
ui.hint(
|
|
4459
|
+
`restored ${relative5(cwd, packageFile) || packageFile}`,
|
|
4460
|
+
"stderr"
|
|
4461
|
+
);
|
|
4462
|
+
}
|
|
4463
|
+
if (merged)
|
|
4464
|
+
ui.hint(
|
|
4465
|
+
`the scaffold merge is still staged; undo it with: git -C ${relative5(cwd, ws.rnessDir) || "."} merge --abort`,
|
|
4466
|
+
"stderr"
|
|
4467
|
+
);
|
|
4172
4468
|
if (/minimum.?release.?age|NO_MATURE/i.test(message))
|
|
4173
4469
|
ui.hint(
|
|
4174
4470
|
"pnpm refuses versions published less than 24 h ago: add '@rness/cli' under minimumReleaseAgeExclude in .rness/pnpm-workspace.yaml",
|
|
@@ -4187,33 +4483,14 @@ async function upgradeCommand(version, opts, terminal = defaultTerminal) {
|
|
|
4187
4483
|
ui.gitIsSilent = true;
|
|
4188
4484
|
const code = await syncBlocks(ui, ws.root, basename5(ws.root));
|
|
4189
4485
|
if (code !== 0) return code;
|
|
4190
|
-
|
|
4191
|
-
const next = [
|
|
4192
|
-
`git -C ${rel} add -A && git -C ${rel} commit -m "chore: rness ${target}"`,
|
|
4193
|
-
"# teammates: git pull \u2014 the next rness command installs it"
|
|
4194
|
-
];
|
|
4195
|
-
if (ui.session) {
|
|
4196
|
-
ui.note("Next steps", next);
|
|
4197
|
-
ui.outro(`${label} runs @rness/cli ${target}`);
|
|
4198
|
-
} else
|
|
4199
|
-
process.stdout.write(
|
|
4200
|
-
[
|
|
4201
|
-
"",
|
|
4202
|
-
status("upgraded", `${label} to @rness/cli ${target}`),
|
|
4203
|
-
"",
|
|
4204
|
-
"Next:",
|
|
4205
|
-
...next.map((line) => ` ${line}`),
|
|
4206
|
-
""
|
|
4207
|
-
].join("\n")
|
|
4208
|
-
);
|
|
4209
|
-
return 0;
|
|
4486
|
+
return finish(ui, cwd, ws.rnessDir, label, target);
|
|
4210
4487
|
} catch (e) {
|
|
4211
4488
|
return reportError(e);
|
|
4212
4489
|
}
|
|
4213
4490
|
}
|
|
4214
4491
|
|
|
4215
4492
|
// src/core/blocks.ts
|
|
4216
|
-
import { join as
|
|
4493
|
+
import { join as join21 } from "path";
|
|
4217
4494
|
var PROBLEM = /* @__PURE__ */ new Set(["stale", "malformed"]);
|
|
4218
4495
|
async function checkBlocks({
|
|
4219
4496
|
root,
|
|
@@ -4230,7 +4507,7 @@ async function checkBlocks({
|
|
|
4230
4507
|
warnings: checks.filter((c) => !PROBLEM.has(c.status) && c.message !== null).map((c) => c.message),
|
|
4231
4508
|
checks
|
|
4232
4509
|
});
|
|
4233
|
-
if (!await exists(
|
|
4510
|
+
if (!await exists(join21(root, "org"))) return derive();
|
|
4234
4511
|
const targets = [
|
|
4235
4512
|
{ scope: null, dir: root, depth: 0, file: "AGENTS.md", label: "AGENTS.md" },
|
|
4236
4513
|
{ scope: null, dir: root, depth: 0, file: "CLAUDE.md", label: "CLAUDE.md" }
|
|
@@ -4239,7 +4516,7 @@ async function checkBlocks({
|
|
|
4239
4516
|
const segments = entry.path.split("/");
|
|
4240
4517
|
targets.push({
|
|
4241
4518
|
scope: name,
|
|
4242
|
-
dir:
|
|
4519
|
+
dir: join21(root, ...segments),
|
|
4243
4520
|
depth: segments.length,
|
|
4244
4521
|
file: "AGENTS.md",
|
|
4245
4522
|
label: `${entry.path}/AGENTS.md`
|
|
@@ -4254,7 +4531,7 @@ async function checkBlocks({
|
|
|
4254
4531
|
);
|
|
4255
4532
|
continue;
|
|
4256
4533
|
}
|
|
4257
|
-
const text = await readOrNull(
|
|
4534
|
+
const text = await readOrNull(join21(t.dir, t.file));
|
|
4258
4535
|
const lines = text === null ? [] : text.split(/\r?\n/);
|
|
4259
4536
|
const found = findBlock(lines);
|
|
4260
4537
|
if (found.kind === "none") {
|
|
@@ -4294,7 +4571,7 @@ async function checkBlocks({
|
|
|
4294
4571
|
}
|
|
4295
4572
|
|
|
4296
4573
|
// src/core/contract.ts
|
|
4297
|
-
import { join as
|
|
4574
|
+
import { join as join22 } from "path";
|
|
4298
4575
|
var STATUSES = {
|
|
4299
4576
|
adr: ["Proposed", "Accepted", "Rejected", "Superseded"],
|
|
4300
4577
|
specs: [
|
|
@@ -4313,7 +4590,7 @@ async function checkContract(rnessDir) {
|
|
|
4313
4590
|
const problems = [];
|
|
4314
4591
|
for (const name of COLLECTIONS) {
|
|
4315
4592
|
const allowed = STATUSES[name];
|
|
4316
|
-
const items = await collectMarkdown(
|
|
4593
|
+
const items = await collectMarkdown(join22(rnessDir, name));
|
|
4317
4594
|
for (const item of items) {
|
|
4318
4595
|
const where = `${name}/${item.rel}`;
|
|
4319
4596
|
if (SKIP.has(where)) continue;
|
|
@@ -4375,11 +4652,25 @@ async function validateCommand(opts, deps = {}) {
|
|
|
4375
4652
|
);
|
|
4376
4653
|
else if (o.status === "invalid")
|
|
4377
4654
|
problems.push(`${o.label}: ${o.detail ?? "unreadable"}`);
|
|
4655
|
+
const scaffoldWarnings = [];
|
|
4656
|
+
if (await isRepository2(ws.rnessDir) && !await isShallow(ws.rnessDir)) {
|
|
4657
|
+
const pin = await readPin(ws.rnessDir);
|
|
4658
|
+
const base = await findScaffoldBase(ws.rnessDir);
|
|
4659
|
+
if (base === null || base.version === null)
|
|
4660
|
+
scaffoldWarnings.push(
|
|
4661
|
+
`the scaffold is not tracked in .rness yet: run ${rnessCommand()} upgrade`
|
|
4662
|
+
);
|
|
4663
|
+
else if (pin !== null && EXACT_VERSION.test(pin.spec) && pin.spec !== base.version)
|
|
4664
|
+
scaffoldWarnings.push(
|
|
4665
|
+
`the @rness/cli ${pin.spec} scaffold is not merged here: run ${rnessCommand()} upgrade`
|
|
4666
|
+
);
|
|
4667
|
+
}
|
|
4378
4668
|
const ui = await makeUi(deps.terminal ?? defaultTerminal);
|
|
4379
4669
|
if (!ui.session) {
|
|
4380
4670
|
for (const p of problems) process.stderr.write(`${p}
|
|
4381
4671
|
`);
|
|
4382
|
-
for (const w of blocks.warnings
|
|
4672
|
+
for (const w of [...blocks.warnings, ...scaffoldWarnings])
|
|
4673
|
+
process.stderr.write(`${warn(w)}
|
|
4383
4674
|
`);
|
|
4384
4675
|
if (problems.length > 0) return 1;
|
|
4385
4676
|
process.stdout.write("context ok\n");
|
|
@@ -4400,6 +4691,7 @@ async function validateCommand(opts, deps = {}) {
|
|
|
4400
4691
|
for (const o of targets)
|
|
4401
4692
|
if (o.status === "unchanged") ui.line("current", o.label);
|
|
4402
4693
|
for (const p of problems) if (!blocks.problems.includes(p)) ui.error(p);
|
|
4694
|
+
for (const w of scaffoldWarnings) ui.warn(w);
|
|
4403
4695
|
ui.outro(
|
|
4404
4696
|
problems.length > 0 ? "Context mismatch" : "Context OK",
|
|
4405
4697
|
problems.length > 0 ? "error" : "done"
|
|
@@ -4551,7 +4843,7 @@ function buildProgram(state) {
|
|
|
4551
4843
|
});
|
|
4552
4844
|
return program;
|
|
4553
4845
|
}
|
|
4554
|
-
async function
|
|
4846
|
+
async function run2(argv) {
|
|
4555
4847
|
const state = { code: 0 };
|
|
4556
4848
|
const program = buildProgram(state);
|
|
4557
4849
|
if (argv.length === 0) {
|
|
@@ -4678,8 +4970,8 @@ export {
|
|
|
4678
4970
|
STATUSES,
|
|
4679
4971
|
checkContract,
|
|
4680
4972
|
validateCommand,
|
|
4681
|
-
run,
|
|
4973
|
+
run2 as run,
|
|
4682
4974
|
OWN_COMMANDS,
|
|
4683
4975
|
catchUp
|
|
4684
4976
|
};
|
|
4685
|
-
//# sourceMappingURL=chunk-
|
|
4977
|
+
//# sourceMappingURL=chunk-ONLF4VFA.js.map
|