@biffo/cli 0.213.0 → 0.214.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.
|
@@ -567,6 +567,7 @@ fi
|
|
|
567
567
|
if [ -f scripts/biffo.sh ]; then
|
|
568
568
|
run_check plugin-tf sh scripts/biffo.sh check plugin-terraform
|
|
569
569
|
run_check plugin-names sh scripts/biffo.sh check plugin-collisions
|
|
570
|
+
run_check adr-numbering sh scripts/biffo.sh check adr-numbering
|
|
570
571
|
else
|
|
571
572
|
skip biffo-guards "no scripts/biffo.sh in this repo"
|
|
572
573
|
fi
|
|
@@ -567,6 +567,7 @@ fi
|
|
|
567
567
|
if [ -f scripts/biffo.sh ]; then
|
|
568
568
|
run_check plugin-tf sh scripts/biffo.sh check plugin-terraform
|
|
569
569
|
run_check plugin-names sh scripts/biffo.sh check plugin-collisions
|
|
570
|
+
run_check adr-numbering sh scripts/biffo.sh check adr-numbering
|
|
570
571
|
else
|
|
571
572
|
skip biffo-guards "no scripts/biffo.sh in this repo"
|
|
572
573
|
fi
|
package/dist/index.js
CHANGED
|
@@ -9124,9 +9124,94 @@ siblingCommand.addCommand(siblingCheckIdentityCommand);
|
|
|
9124
9124
|
// src/commands/check.ts
|
|
9125
9125
|
import { Command as Command23 } from "commander";
|
|
9126
9126
|
|
|
9127
|
+
// src/scripts/check-adr-numbering.ts
|
|
9128
|
+
import { existsSync as existsSync32 } from "fs";
|
|
9129
|
+
import { join as join32 } from "path";
|
|
9130
|
+
import { execa as execa5 } from "execa";
|
|
9131
|
+
|
|
9132
|
+
// src/lib/adr-numbering-guard.ts
|
|
9133
|
+
import { existsSync as existsSync31, readdirSync as readdirSync13, readFileSync as readFileSync24 } from "fs";
|
|
9134
|
+
import { join as join31 } from "path";
|
|
9135
|
+
var ADR_FILENAME = /^(\d{4})-.+\.md$/;
|
|
9136
|
+
var ALLOWLIST_FILENAME = ".numbering-allowlist";
|
|
9137
|
+
function readAdrNumberingAllowlist(adrDir) {
|
|
9138
|
+
const path = join31(adrDir, ALLOWLIST_FILENAME);
|
|
9139
|
+
if (!existsSync31(path)) return /* @__PURE__ */ new Set();
|
|
9140
|
+
const numbers = /* @__PURE__ */ new Set();
|
|
9141
|
+
for (const rawLine of readFileSync24(path, "utf8").split("\n")) {
|
|
9142
|
+
const line = rawLine.split("#")[0].trim();
|
|
9143
|
+
if (line) numbers.add(line);
|
|
9144
|
+
}
|
|
9145
|
+
return numbers;
|
|
9146
|
+
}
|
|
9147
|
+
function adrNumbersIn(adrDir) {
|
|
9148
|
+
const claims = /* @__PURE__ */ new Map();
|
|
9149
|
+
if (!existsSync31(adrDir)) return claims;
|
|
9150
|
+
for (const entry of readdirSync13(adrDir).sort()) {
|
|
9151
|
+
const match = ADR_FILENAME.exec(entry);
|
|
9152
|
+
if (!match) continue;
|
|
9153
|
+
const number = match[1];
|
|
9154
|
+
claims.set(number, [...claims.get(number) ?? [], entry]);
|
|
9155
|
+
}
|
|
9156
|
+
return claims;
|
|
9157
|
+
}
|
|
9158
|
+
function findAdrNumberCollisions(adrDir) {
|
|
9159
|
+
const allowlist = readAdrNumberingAllowlist(adrDir);
|
|
9160
|
+
const collisions = [];
|
|
9161
|
+
for (const [number, files] of [...adrNumbersIn(adrDir).entries()].sort()) {
|
|
9162
|
+
if (files.length > 1 && !allowlist.has(number)) {
|
|
9163
|
+
collisions.push({ number, files: [...files].sort() });
|
|
9164
|
+
}
|
|
9165
|
+
}
|
|
9166
|
+
return collisions;
|
|
9167
|
+
}
|
|
9168
|
+
function findStaleAdrNumberingAllowlistEntries(adrDir) {
|
|
9169
|
+
const allowlist = readAdrNumberingAllowlist(adrDir);
|
|
9170
|
+
const claims = adrNumbersIn(adrDir);
|
|
9171
|
+
return [...allowlist].filter((number) => (claims.get(number)?.length ?? 0) < 2).sort();
|
|
9172
|
+
}
|
|
9173
|
+
function formatAdrNumberCollisions(collisions) {
|
|
9174
|
+
return collisions.map(
|
|
9175
|
+
(c) => ` ADR-${c.number} is claimed by: ${c.files.join(", ")}
|
|
9176
|
+
Pick a different number for the newer one \u2014 citing "ADR-${c.number}" is
|
|
9177
|
+
ambiguous while both exist.`
|
|
9178
|
+
).join("\n");
|
|
9179
|
+
}
|
|
9180
|
+
|
|
9181
|
+
// src/scripts/check-adr-numbering.ts
|
|
9182
|
+
async function runAdrNumberingCheck() {
|
|
9183
|
+
const root = (await execa5("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
|
|
9184
|
+
const adrDir = join32(root, "docs", "ADR");
|
|
9185
|
+
if (!existsSync32(adrDir)) {
|
|
9186
|
+
console.log("\u2713 ADR numbering guard: no docs/ADR/ directory \u2014 nothing to compare");
|
|
9187
|
+
return;
|
|
9188
|
+
}
|
|
9189
|
+
const collisions = findAdrNumberCollisions(adrDir);
|
|
9190
|
+
const stale = findStaleAdrNumberingAllowlistEntries(adrDir);
|
|
9191
|
+
let failed = false;
|
|
9192
|
+
if (collisions.length > 0) {
|
|
9193
|
+
failed = true;
|
|
9194
|
+
console.error("\u2717 ADR numbering guard: two ADRs in docs/ADR/ share a number\n");
|
|
9195
|
+
console.error(formatAdrNumberCollisions(collisions));
|
|
9196
|
+
console.error(
|
|
9197
|
+
`
|
|
9198
|
+
Already accepted? List it in docs/ADR/${ALLOWLIST_FILENAME} instead of leaving this red forever. See tabsii-platform#449 for how this class of collision happens.`
|
|
9199
|
+
);
|
|
9200
|
+
}
|
|
9201
|
+
if (stale.length > 0) {
|
|
9202
|
+
failed = true;
|
|
9203
|
+
console.error(
|
|
9204
|
+
`\u2717 ADR numbering guard: docs/ADR/${ALLOWLIST_FILENAME} names a number that no longer collides: ${stale.join(", ")}
|
|
9205
|
+
Remove the stale entry \u2014 an allowlist nothing checks against just hides the next real one.`
|
|
9206
|
+
);
|
|
9207
|
+
}
|
|
9208
|
+
if (failed) process.exit(1);
|
|
9209
|
+
console.log("\u2713 ADR numbering guard: OK");
|
|
9210
|
+
}
|
|
9211
|
+
|
|
9127
9212
|
// src/scripts/check-branch-protection.ts
|
|
9128
9213
|
import { Octokit as Octokit2 } from "@octokit/rest";
|
|
9129
|
-
import { execa as
|
|
9214
|
+
import { execa as execa6 } from "execa";
|
|
9130
9215
|
|
|
9131
9216
|
// src/lib/branch-protection-apply.ts
|
|
9132
9217
|
var CONTEXT_CONSISTENCY_THRESHOLD = 2 / 3;
|
|
@@ -9253,7 +9338,7 @@ async function resolveRepo(explicit) {
|
|
|
9253
9338
|
}
|
|
9254
9339
|
return { owner, repo };
|
|
9255
9340
|
}
|
|
9256
|
-
const { stdout } = await
|
|
9341
|
+
const { stdout } = await execa6("git", ["remote", "get-url", "origin"]);
|
|
9257
9342
|
const m = /github\.com[:/]([^/]+)\/(.+?)(?:\.git)?$/.exec(stdout.trim());
|
|
9258
9343
|
if (!m?.[1] || !m[2]) {
|
|
9259
9344
|
console.error(
|
|
@@ -9385,7 +9470,7 @@ async function runBranchProtectionCheck(explicitRepo, options = {}) {
|
|
|
9385
9470
|
}
|
|
9386
9471
|
|
|
9387
9472
|
// src/scripts/check-core-ownership.ts
|
|
9388
|
-
import { execa as
|
|
9473
|
+
import { execa as execa7 } from "execa";
|
|
9389
9474
|
var BOLD = "\x1B[1m";
|
|
9390
9475
|
var DIM = "\x1B[2m";
|
|
9391
9476
|
var RED = "\x1B[31m";
|
|
@@ -9396,7 +9481,7 @@ async function runOwnershipCheck(argv) {
|
|
|
9396
9481
|
const stagedFlag = args.indexOf("--staged");
|
|
9397
9482
|
const staged = stagedFlag !== -1;
|
|
9398
9483
|
const messageFile = staged ? args[stagedFlag + 1] : void 0;
|
|
9399
|
-
const root = (await
|
|
9484
|
+
const root = (await execa7("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
|
|
9400
9485
|
if (!isInstanceRepo(root)) {
|
|
9401
9486
|
console.log("\u2713 core ownership guard: skipped \u2014 this is the template, which owns these paths.");
|
|
9402
9487
|
return;
|
|
@@ -9405,11 +9490,11 @@ async function runOwnershipCheck(argv) {
|
|
|
9405
9490
|
let deletedFiles = [];
|
|
9406
9491
|
let commitMessage = "";
|
|
9407
9492
|
if (staged) {
|
|
9408
|
-
const { stdout } = await
|
|
9493
|
+
const { stdout } = await execa7("git", ["diff", "--cached", "--name-status"], { cwd: root });
|
|
9409
9494
|
({ changed: changedFiles, deleted: deletedFiles } = parseNameStatus(stdout));
|
|
9410
9495
|
if (messageFile) {
|
|
9411
|
-
const { readFileSync:
|
|
9412
|
-
if (
|
|
9496
|
+
const { readFileSync: readFileSync27, existsSync: existsSync37 } = await import("fs");
|
|
9497
|
+
if (existsSync37(messageFile)) commitMessage = readFileSync27(messageFile, "utf8");
|
|
9413
9498
|
}
|
|
9414
9499
|
} else {
|
|
9415
9500
|
const base = process.env["GITHUB_BASE_REF"] ?? args[0];
|
|
@@ -9417,18 +9502,18 @@ async function runOwnershipCheck(argv) {
|
|
|
9417
9502
|
console.error("No base ref: set GITHUB_BASE_REF or pass a base branch as the first argument.");
|
|
9418
9503
|
process.exit(2);
|
|
9419
9504
|
}
|
|
9420
|
-
await
|
|
9421
|
-
const { stdout } = await
|
|
9505
|
+
await execa7("git", ["fetch", "--quiet", "origin", base], { cwd: root, reject: false });
|
|
9506
|
+
const { stdout } = await execa7("git", ["diff", "--name-status", `origin/${base}...HEAD`], {
|
|
9422
9507
|
cwd: root
|
|
9423
9508
|
});
|
|
9424
9509
|
({ changed: changedFiles, deleted: deletedFiles } = parseNameStatus(stdout));
|
|
9425
|
-
const { stdout: log2 } = await
|
|
9510
|
+
const { stdout: log2 } = await execa7("git", ["log", "--format=%B", `origin/${base}..HEAD`], {
|
|
9426
9511
|
cwd: root,
|
|
9427
9512
|
reject: false
|
|
9428
9513
|
});
|
|
9429
9514
|
commitMessage = log2;
|
|
9430
9515
|
}
|
|
9431
|
-
const { stdout: gitBranch } = await
|
|
9516
|
+
const { stdout: gitBranch } = await execa7("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
|
|
9432
9517
|
cwd: root,
|
|
9433
9518
|
reject: false
|
|
9434
9519
|
});
|
|
@@ -9510,34 +9595,34 @@ ${BOLD}If the divergence is deliberate${OFF}
|
|
|
9510
9595
|
}
|
|
9511
9596
|
|
|
9512
9597
|
// src/scripts/check-plugin-collisions.ts
|
|
9513
|
-
import { existsSync as
|
|
9514
|
-
import { join as
|
|
9515
|
-
import { execa as
|
|
9598
|
+
import { existsSync as existsSync34 } from "fs";
|
|
9599
|
+
import { join as join34 } from "path";
|
|
9600
|
+
import { execa as execa8 } from "execa";
|
|
9516
9601
|
|
|
9517
9602
|
// src/lib/plugin-collision-guard.ts
|
|
9518
|
-
import { existsSync as
|
|
9519
|
-
import { join as
|
|
9603
|
+
import { existsSync as existsSync33, readdirSync as readdirSync14, statSync as statSync7 } from "fs";
|
|
9604
|
+
import { join as join33 } from "path";
|
|
9520
9605
|
var PYTEST_SPECIAL = /* @__PURE__ */ new Set(["conftest.py"]);
|
|
9521
9606
|
var IGNORED_DIRS = /* @__PURE__ */ new Set([".venv", "node_modules", "__pycache__", ".git", "dist", "build"]);
|
|
9522
9607
|
function subdirectories(dir) {
|
|
9523
|
-
if (!
|
|
9524
|
-
return
|
|
9608
|
+
if (!existsSync33(dir)) return [];
|
|
9609
|
+
return readdirSync14(dir).filter((entry) => {
|
|
9525
9610
|
if (IGNORED_DIRS.has(entry) || entry.startsWith(".")) return false;
|
|
9526
9611
|
try {
|
|
9527
|
-
return statSync7(
|
|
9612
|
+
return statSync7(join33(dir, entry)).isDirectory();
|
|
9528
9613
|
} catch {
|
|
9529
9614
|
return false;
|
|
9530
9615
|
}
|
|
9531
9616
|
});
|
|
9532
9617
|
}
|
|
9533
9618
|
function regularPackagesOf(pluginDir2) {
|
|
9534
|
-
return subdirectories(pluginDir2).filter((name) =>
|
|
9619
|
+
return subdirectories(pluginDir2).filter((name) => existsSync33(join33(pluginDir2, name, "__init__.py"))).sort();
|
|
9535
9620
|
}
|
|
9536
9621
|
function bareTestModulesOf(pluginDir2) {
|
|
9537
|
-
const testsDir =
|
|
9538
|
-
if (!
|
|
9539
|
-
if (
|
|
9540
|
-
return
|
|
9622
|
+
const testsDir = join33(pluginDir2, "tests");
|
|
9623
|
+
if (!existsSync33(testsDir)) return [];
|
|
9624
|
+
if (existsSync33(join33(testsDir, "__init__.py"))) return [];
|
|
9625
|
+
return readdirSync14(testsDir).filter((f) => f.endsWith(".py") && !PYTEST_SPECIAL.has(f)).sort();
|
|
9541
9626
|
}
|
|
9542
9627
|
function findCollisions(servicesDir, pluginDirs) {
|
|
9543
9628
|
const plugins = (pluginDirs ?? subdirectories(servicesDir)).filter((name) => !name.startsWith("_")).filter((name) => name !== "api").sort();
|
|
@@ -9545,7 +9630,7 @@ function findCollisions(servicesDir, pluginDirs) {
|
|
|
9545
9630
|
const gather = (kind, namesOf) => {
|
|
9546
9631
|
const claims = /* @__PURE__ */ new Map();
|
|
9547
9632
|
for (const plugin of plugins) {
|
|
9548
|
-
for (const name of namesOf(
|
|
9633
|
+
for (const name of namesOf(join33(servicesDir, plugin))) {
|
|
9549
9634
|
claims.set(name, [...claims.get(name) ?? [], plugin]);
|
|
9550
9635
|
}
|
|
9551
9636
|
}
|
|
@@ -9582,9 +9667,9 @@ function formatCollisions(collisions) {
|
|
|
9582
9667
|
|
|
9583
9668
|
// src/scripts/check-plugin-collisions.ts
|
|
9584
9669
|
async function runPluginCollisionCheck() {
|
|
9585
|
-
const root = (await
|
|
9586
|
-
const servicesDir =
|
|
9587
|
-
if (!
|
|
9670
|
+
const root = (await execa8("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
|
|
9671
|
+
const servicesDir = join34(root, "services");
|
|
9672
|
+
if (!existsSync34(servicesDir)) {
|
|
9588
9673
|
console.log("\u2713 plugin collision guard: no services/ directory \u2014 nothing to compare");
|
|
9589
9674
|
return;
|
|
9590
9675
|
}
|
|
@@ -9601,11 +9686,11 @@ async function runPluginCollisionCheck() {
|
|
|
9601
9686
|
}
|
|
9602
9687
|
|
|
9603
9688
|
// src/scripts/check-plugin-terraform.ts
|
|
9604
|
-
import { execa as
|
|
9689
|
+
import { execa as execa9 } from "execa";
|
|
9605
9690
|
|
|
9606
9691
|
// src/lib/plugin-terraform-guard.ts
|
|
9607
|
-
import { existsSync as
|
|
9608
|
-
import { dirname as dirname9, join as
|
|
9692
|
+
import { existsSync as existsSync35, readFileSync as readFileSync25, readdirSync as readdirSync15 } from "fs";
|
|
9693
|
+
import { dirname as dirname9, join as join35, relative as relative6, sep as sep3 } from "path";
|
|
9609
9694
|
var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", ".worktrees", "dist", ".venv", "__pycache__"]);
|
|
9610
9695
|
var PLUGIN_MANIFEST_FILE2 = "biffo.plugin.json";
|
|
9611
9696
|
function findPluginManifests(root) {
|
|
@@ -9613,16 +9698,16 @@ function findPluginManifests(root) {
|
|
|
9613
9698
|
const walk = (dir) => {
|
|
9614
9699
|
let entries;
|
|
9615
9700
|
try {
|
|
9616
|
-
entries =
|
|
9701
|
+
entries = readdirSync15(dir, { withFileTypes: true });
|
|
9617
9702
|
} catch {
|
|
9618
9703
|
return;
|
|
9619
9704
|
}
|
|
9620
9705
|
for (const entry of entries) {
|
|
9621
9706
|
if (entry.isDirectory()) {
|
|
9622
9707
|
if (SKIP_DIRS.has(entry.name)) continue;
|
|
9623
|
-
walk(
|
|
9708
|
+
walk(join35(dir, entry.name));
|
|
9624
9709
|
} else if (entry.isFile() && entry.name === PLUGIN_MANIFEST_FILE2) {
|
|
9625
|
-
found.push(relative6(root,
|
|
9710
|
+
found.push(relative6(root, join35(dir, entry.name)).split(sep3).join("/"));
|
|
9626
9711
|
}
|
|
9627
9712
|
}
|
|
9628
9713
|
};
|
|
@@ -9632,7 +9717,7 @@ function findPluginManifests(root) {
|
|
|
9632
9717
|
function readSubscriptions(absManifestPath) {
|
|
9633
9718
|
let parsed;
|
|
9634
9719
|
try {
|
|
9635
|
-
parsed = JSON.parse(
|
|
9720
|
+
parsed = JSON.parse(readFileSync25(absManifestPath, "utf8"));
|
|
9636
9721
|
} catch {
|
|
9637
9722
|
return null;
|
|
9638
9723
|
}
|
|
@@ -9647,14 +9732,14 @@ function readSubscriptions(absManifestPath) {
|
|
|
9647
9732
|
}
|
|
9648
9733
|
function checkPluginTerraform(root) {
|
|
9649
9734
|
const violations = [];
|
|
9650
|
-
const coreManifest =
|
|
9735
|
+
const coreManifest = existsSync35(join35(root, CORE_MANIFEST_FILE)) ? readCoreManifest(root) : null;
|
|
9651
9736
|
for (const manifest of findPluginManifests(root)) {
|
|
9652
9737
|
if (coreManifest && !isTemplateOwned(manifest, coreManifest)) continue;
|
|
9653
|
-
const absManifest =
|
|
9738
|
+
const absManifest = join35(root, manifest);
|
|
9654
9739
|
const subscriptions = readSubscriptions(absManifest);
|
|
9655
9740
|
if (subscriptions === null) continue;
|
|
9656
9741
|
const pluginDir2 = dirname9(absManifest);
|
|
9657
|
-
if (
|
|
9742
|
+
if (existsSync35(join35(pluginDir2, "terraform"))) continue;
|
|
9658
9743
|
const relPluginDir = relative6(root, pluginDir2).split(sep3).join("/");
|
|
9659
9744
|
violations.push({
|
|
9660
9745
|
manifest,
|
|
@@ -9674,7 +9759,7 @@ function formatViolations(violations) {
|
|
|
9674
9759
|
|
|
9675
9760
|
// src/scripts/check-plugin-terraform.ts
|
|
9676
9761
|
async function runPluginTerraformCheck() {
|
|
9677
|
-
const root = (await
|
|
9762
|
+
const root = (await execa9("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
|
|
9678
9763
|
const violations = checkPluginTerraform(root);
|
|
9679
9764
|
if (violations.length > 0) {
|
|
9680
9765
|
console.error("\u2717 plugin Terraform guard: event subscriptions with no infrastructure\n");
|
|
@@ -9685,7 +9770,7 @@ async function runPluginTerraformCheck() {
|
|
|
9685
9770
|
}
|
|
9686
9771
|
|
|
9687
9772
|
// src/scripts/check-release-subject.ts
|
|
9688
|
-
import { execa as
|
|
9773
|
+
import { execa as execa10 } from "execa";
|
|
9689
9774
|
|
|
9690
9775
|
// src/lib/release-version.ts
|
|
9691
9776
|
var MINOR_TYPES = /* @__PURE__ */ new Set(["feat"]);
|
|
@@ -9723,13 +9808,13 @@ async function runReleaseSubjectCheck(argv) {
|
|
|
9723
9808
|
console.error("No base ref: set GITHUB_BASE_REF or pass a base branch as the first argument.");
|
|
9724
9809
|
process.exit(2);
|
|
9725
9810
|
}
|
|
9726
|
-
const root = (await
|
|
9727
|
-
await
|
|
9728
|
-
const { stdout } = await
|
|
9811
|
+
const root = (await execa10("git", ["rev-parse", "--show-toplevel"])).stdout.trim();
|
|
9812
|
+
await execa10("git", ["fetch", "--quiet", "origin", base], { cwd: root, reject: false });
|
|
9813
|
+
const { stdout } = await execa10("git", ["diff", "--name-only", `origin/${base}...HEAD`], {
|
|
9729
9814
|
cwd: root
|
|
9730
9815
|
});
|
|
9731
9816
|
const changedFiles = stdout.split("\n").map((s) => s.trim()).filter(Boolean);
|
|
9732
|
-
const subject = process.env["PR_TITLE"]?.trim() || (await
|
|
9817
|
+
const subject = process.env["PR_TITLE"]?.trim() || (await execa10("git", ["log", "-1", "--format=%s"], { cwd: root })).stdout.trim();
|
|
9733
9818
|
const manifest = readCoreManifest(root);
|
|
9734
9819
|
const { unparseable, bump, templateOwnedChanges, skippedAsInstance } = checkReleaseSubject(
|
|
9735
9820
|
changedFiles,
|
|
@@ -9788,6 +9873,11 @@ checkCommand.command("plugin-collisions").description("Refuse two vendored plugi
|
|
|
9788
9873
|
checkCommand.command("plugin-terraform").description("Verify every template-owned plugin declaring infra ships a Terraform module").action(async () => {
|
|
9789
9874
|
await runPluginTerraformCheck();
|
|
9790
9875
|
});
|
|
9876
|
+
checkCommand.command("adr-numbering").description(
|
|
9877
|
+
"Refuse two ADRs in this repo's own docs/ADR/ claiming the same number (tabsii-platform#449)"
|
|
9878
|
+
).action(async () => {
|
|
9879
|
+
await runAdrNumberingCheck();
|
|
9880
|
+
});
|
|
9791
9881
|
checkCommand.command("branch-protection").description(
|
|
9792
9882
|
"Verify dev/staging/main are actually protected \u2014 scaffolding skips this on a 403 (#715)"
|
|
9793
9883
|
).option("--repo <owner/name>", "Repo to audit; defaults to this checkout's origin remote").option(
|
|
@@ -9802,8 +9892,8 @@ function rawArgsAfter(subcommand) {
|
|
|
9802
9892
|
}
|
|
9803
9893
|
|
|
9804
9894
|
// src/commands/doctor.ts
|
|
9805
|
-
import { existsSync as
|
|
9806
|
-
import { join as
|
|
9895
|
+
import { existsSync as existsSync36, readFileSync as readFileSync26 } from "fs";
|
|
9896
|
+
import { join as join36, resolve as resolve18 } from "path";
|
|
9807
9897
|
import chalk21 from "chalk";
|
|
9808
9898
|
import { Command as Command24 } from "commander";
|
|
9809
9899
|
|
|
@@ -9978,10 +10068,10 @@ async function runDoctor(options, deps = { git: new GitAdapter() }) {
|
|
|
9978
10068
|
return runDoctorChecks(facts);
|
|
9979
10069
|
}
|
|
9980
10070
|
function readLocalCoreVersion(cwd) {
|
|
9981
|
-
const path =
|
|
9982
|
-
if (!
|
|
10071
|
+
const path = join36(cwd, INSTANCE_CORE_FILE);
|
|
10072
|
+
if (!existsSync36(path)) return null;
|
|
9983
10073
|
try {
|
|
9984
|
-
return parseCoreRecord(
|
|
10074
|
+
return parseCoreRecord(readFileSync26(path, "utf8"));
|
|
9985
10075
|
} catch {
|
|
9986
10076
|
return null;
|
|
9987
10077
|
}
|
|
@@ -9996,10 +10086,10 @@ function parseCoreRecord(contents) {
|
|
|
9996
10086
|
}
|
|
9997
10087
|
}
|
|
9998
10088
|
function readFossil(cwd) {
|
|
9999
|
-
const path =
|
|
10000
|
-
if (!
|
|
10089
|
+
const path = join36(cwd, CORE_VERSION_FILE);
|
|
10090
|
+
if (!existsSync36(path)) return null;
|
|
10001
10091
|
try {
|
|
10002
|
-
const value =
|
|
10092
|
+
const value = readFileSync26(path, "utf8").trim();
|
|
10003
10093
|
return value === "" ? null : value;
|
|
10004
10094
|
} catch {
|
|
10005
10095
|
return null;
|