@tablation/crew 0.25.0 → 0.26.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/crew.example.yaml +6 -0
- package/dist/cli.js +88 -24
- package/package.json +1 -1
package/crew.example.yaml
CHANGED
|
@@ -76,6 +76,12 @@ routes:
|
|
|
76
76
|
|
|
77
77
|
worktreePrefix: "myproject-issue-"
|
|
78
78
|
|
|
79
|
+
# A repo may also be written as an object to name its worktree directory
|
|
80
|
+
# for this ship only (CREW-1504) — a template over {dir} {issue} {number}
|
|
81
|
+
# {key} {slug} {tag} {prefix} {role}. Outranks the repo's own
|
|
82
|
+
# `worktrees.name`, which outranks worktreePrefix; see docs/REPO_SPEC.md.
|
|
83
|
+
# My Product: { dir: "/home/me/src/my-product", worktreeName: "{dir}-{issue}" }
|
|
84
|
+
|
|
79
85
|
# Opt this route's ship into Host Passengers for this route's workspace
|
|
80
86
|
# (ISSUE-644): `crew connect` syncs this onto that workspace's own Ships
|
|
81
87
|
# row. Config-truth lives here, on the machine — never edit a Ships row
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { resolve as resolve4, dirname as dirname11, join as join20, basename as
|
|
4
|
+
import { resolve as resolve4, dirname as dirname11, join as join20, basename as basename8 } from "path";
|
|
5
5
|
import { fileURLToPath } from "url";
|
|
6
6
|
import { hostname as hostname2, homedir as homedir5 } from "os";
|
|
7
7
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
@@ -84,6 +84,27 @@ var TOP_LEVEL = /* @__PURE__ */ new Set([
|
|
|
84
84
|
]);
|
|
85
85
|
var BRANCH_KEYS = /* @__PURE__ */ new Set(["base", "name", "push", "remote"]);
|
|
86
86
|
var PLACEHOLDER = /\{(key|number|slug|role|prefix|tag)\}/g;
|
|
87
|
+
var WORKTREE_PLACEHOLDERS = ["dir", "issue", "number", "key", "slug", "role", "prefix", "tag"];
|
|
88
|
+
function worktreeNameProblem(template) {
|
|
89
|
+
const valid = `Valid placeholders: ${WORKTREE_PLACEHOLDERS.map((p) => `{${p}}`).join(" ")}.`;
|
|
90
|
+
if (template.trim() === "") return `must be a non-empty string. ${valid}`;
|
|
91
|
+
if (/[/\\]/.test(template)) {
|
|
92
|
+
return "must not contain a path separator \u2014 a worktree is cut beside the checkout, not inside a directory of its own";
|
|
93
|
+
}
|
|
94
|
+
const stripped = template.replace(/\{([^{}]*)\}/g, (_m, name) => {
|
|
95
|
+
if (!WORKTREE_PLACEHOLDERS.includes(name)) return "\0";
|
|
96
|
+
return "";
|
|
97
|
+
});
|
|
98
|
+
if (stripped.includes("\0")) {
|
|
99
|
+
const bad = [...template.matchAll(/\{([^{}]*)\}/g)].map((m) => m[1] ?? "").filter((n) => !WORKTREE_PLACEHOLDERS.includes(n));
|
|
100
|
+
return `names unknown placeholder ${bad.map((b) => `{${b}}`).join(", ")}. ${valid}`;
|
|
101
|
+
}
|
|
102
|
+
if (/[{}]/.test(stripped)) return `has an unbalanced brace. ${valid}`;
|
|
103
|
+
if (!/\{(issue|number|key|slug|tag)\}/.test(template)) {
|
|
104
|
+
return "names no per-ticket placeholder \u2014 every ticket would get the same worktree. Use at least one of {issue} {number} {key} {slug} {tag}.";
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
87
108
|
var RELEASE_KEYS = /* @__PURE__ */ new Set([
|
|
88
109
|
"mode",
|
|
89
110
|
"ship",
|
|
@@ -132,7 +153,7 @@ function parseRepoConfig(text, file) {
|
|
|
132
153
|
rejectUnknown(raw.release?.ci, CI_KEYS, "release.ci", file);
|
|
133
154
|
rejectUnknown(raw.release?.verify, VERIFY_KEYS, "release.verify", file);
|
|
134
155
|
rejectUnknown(raw.branch, BRANCH_KEYS, "branch", file);
|
|
135
|
-
rejectUnknown(raw.worktrees, /* @__PURE__ */ new Set(["copy", "prefix"]), "worktrees", file);
|
|
156
|
+
rejectUnknown(raw.worktrees, /* @__PURE__ */ new Set(["copy", "prefix", "name"]), "worktrees", file);
|
|
136
157
|
rejectUnknown(raw.docs, /* @__PURE__ */ new Set(["triagePolicy", "designGuide"]), "docs", file);
|
|
137
158
|
if (raw.version === void 0) throw new RepoConfigError(`${file}: version is required`);
|
|
138
159
|
if (raw.version !== SPEC_VERSION) {
|
|
@@ -167,7 +188,13 @@ function parseRepoConfig(text, file) {
|
|
|
167
188
|
`${file}: worktrees.prefix ("${prefixRaw}") must not contain a path separator \u2014 a worktree is cut beside the checkout, not inside a directory of its own`
|
|
168
189
|
);
|
|
169
190
|
}
|
|
191
|
+
const nameRaw = raw.worktrees?.name;
|
|
192
|
+
if (nameRaw !== void 0) {
|
|
193
|
+
const problem = typeof nameRaw === "string" ? worktreeNameProblem(nameRaw) : "must be a string";
|
|
194
|
+
if (problem) throw new RepoConfigError(`${file}: worktrees.name ("${String(nameRaw)}") ${problem}`);
|
|
195
|
+
}
|
|
170
196
|
const worktrees2 = {
|
|
197
|
+
...nameRaw !== void 0 ? { name: String(nameRaw) } : {},
|
|
171
198
|
copy: (copyRaw ?? []).map((c) => String(c)),
|
|
172
199
|
// Empty means "not declared" here; the effective config fills it in, since
|
|
173
200
|
// only that layer knows the ship's setting and the checkout's directory.
|
|
@@ -358,6 +385,10 @@ function renderBranchName(template, ctx) {
|
|
|
358
385
|
}
|
|
359
386
|
});
|
|
360
387
|
}
|
|
388
|
+
function renderWorktreeName(template, ctx) {
|
|
389
|
+
const issue = (ctx.tag ?? ctx.key).toLowerCase();
|
|
390
|
+
return renderBranchName(template.replace(/\{dir\}/g, ctx.dir).replace(/\{issue\}/g, issue), ctx);
|
|
391
|
+
}
|
|
361
392
|
function defaultWorktreePrefix(dir) {
|
|
362
393
|
const name = basename(dir.replace(/[/\\]+$/, ""));
|
|
363
394
|
return name ? `${name}-issue-` : "issue-";
|
|
@@ -389,6 +420,10 @@ function resolveRepoConfig(repo, ship, dir) {
|
|
|
389
420
|
provenance[key] = "default";
|
|
390
421
|
return fallback;
|
|
391
422
|
};
|
|
423
|
+
if (ship?.worktrees?.nameOverride) {
|
|
424
|
+
if (repo?.worktrees.name) shadowed.push("worktrees.name");
|
|
425
|
+
provenance["worktrees.name"] = "ship";
|
|
426
|
+
} else if (repo?.worktrees.name) provenance["worktrees.name"] = "repo";
|
|
392
427
|
const hooks = {};
|
|
393
428
|
const labels = {};
|
|
394
429
|
for (const h of HOOK_NAMES) {
|
|
@@ -424,7 +459,8 @@ function resolveRepoConfig(repo, ship, dir) {
|
|
|
424
459
|
repo?.worktrees.prefix || void 0,
|
|
425
460
|
ship?.worktrees?.prefix,
|
|
426
461
|
defaultWorktreePrefix(dir)
|
|
427
|
-
)
|
|
462
|
+
),
|
|
463
|
+
...ship?.worktrees?.nameOverride || repo?.worktrees.name ? { name: ship?.worktrees?.nameOverride || repo?.worktrees.name } : {}
|
|
428
464
|
},
|
|
429
465
|
docs: repo?.docs ?? {},
|
|
430
466
|
branch: {
|
|
@@ -525,7 +561,8 @@ function effectiveBranchTemplate(cfg, prefix) {
|
|
|
525
561
|
if (cfg.provenance["branch.name"] !== "default") return cfg.branch.name;
|
|
526
562
|
return prefix ? "{prefix}-{number}" : "issue-{number}";
|
|
527
563
|
}
|
|
528
|
-
function effectiveWorktreeDirName(cfg, dir, branchName, number) {
|
|
564
|
+
function effectiveWorktreeDirName(cfg, dir, branchName, number, renderName) {
|
|
565
|
+
if (cfg.worktrees.name && renderName) return renderName(cfg.worktrees.name);
|
|
529
566
|
if (cfg.provenance["worktrees.prefix"] !== "default") return `${cfg.worktrees.prefix}${number}`;
|
|
530
567
|
return `${basename(dir.replace(/[/\\]+$/, ""))}-${branchName}`;
|
|
531
568
|
}
|
|
@@ -623,7 +660,12 @@ var ROUTE_KEYS = /* @__PURE__ */ new Set([
|
|
|
623
660
|
"promptSet",
|
|
624
661
|
"hostPassengers"
|
|
625
662
|
]);
|
|
626
|
-
|
|
663
|
+
function parseWorktreeName(v, where, file) {
|
|
664
|
+
const problem = typeof v === "string" ? worktreeNameProblem(v) : "must be a string";
|
|
665
|
+
if (problem) throw new ConfigError(`${file}: ${where}.worktreeName ("${String(v)}") ${problem}`);
|
|
666
|
+
return String(v);
|
|
667
|
+
}
|
|
668
|
+
var REPO_ENTRY_KEYS = /* @__PURE__ */ new Set(["dir", "hooks", "labels", "release", "branch", "hostPassengers", "worktreeName"]);
|
|
627
669
|
var BRANCH_OVERRIDE_KEYS = /* @__PURE__ */ new Set(["base", "name", "push", "remote"]);
|
|
628
670
|
var RELEASE_OVERRIDE_KEYS = /* @__PURE__ */ new Set([
|
|
629
671
|
"mode",
|
|
@@ -959,7 +1001,7 @@ function parseOneRoute(c, where, file, base, stateDir, raw, missing, crewHome) {
|
|
|
959
1001
|
const e = entry;
|
|
960
1002
|
rejectUnknownKeys(e, REPO_ENTRY_KEYS, `${where}.repos.${name}`, file);
|
|
961
1003
|
repoDirs[name] = expand(String(missing.req(e.dir, `${where}.repos.${name}.dir`) || ""), base);
|
|
962
|
-
if (e.hooks || e.labels || e.release || e.branch || e.hostPassengers !== void 0) {
|
|
1004
|
+
if (e.hooks || e.labels || e.release || e.branch || e.hostPassengers !== void 0 || e.worktreeName !== void 0) {
|
|
963
1005
|
repoOverrides[name] = {
|
|
964
1006
|
hooks: e.hooks,
|
|
965
1007
|
labels: e.labels,
|
|
@@ -969,7 +1011,8 @@ function parseOneRoute(c, where, file, base, stateDir, raw, missing, crewHome) {
|
|
|
969
1011
|
// shape as one that never had the key, and existing callers
|
|
970
1012
|
// compare this literally.
|
|
971
1013
|
...e.branch ? { branch: parseBranchOverride(e.branch, `${where}.repos.${name}`, file) } : {},
|
|
972
|
-
...e.hostPassengers !== void 0 ? { hostPassengers: e.hostPassengers === true } : {}
|
|
1014
|
+
...e.hostPassengers !== void 0 ? { hostPassengers: e.hostPassengers === true } : {},
|
|
1015
|
+
...e.worktreeName !== void 0 ? { worktreeName: parseWorktreeName(e.worktreeName, `${where}.repos.${name}`, file) } : {}
|
|
973
1016
|
};
|
|
974
1017
|
}
|
|
975
1018
|
} else {
|
|
@@ -4661,6 +4704,7 @@ ${waiting.map((t) => `| ${displayKey2(t)} | ${t.status} | ${blockers(t, i)} |`).
|
|
|
4661
4704
|
}
|
|
4662
4705
|
|
|
4663
4706
|
// src/ticket-branch.ts
|
|
4707
|
+
import { basename as basename4 } from "path";
|
|
4664
4708
|
function branchRenderer(t, role) {
|
|
4665
4709
|
const { tag, prefix } = ticketBranchContext(t);
|
|
4666
4710
|
return (template) => renderBranchName(template, { key: t.issue_id, title: t.title ?? void 0, role, tag, prefix });
|
|
@@ -4669,7 +4713,15 @@ function worktreeForTicket(dir, cfg, t, role) {
|
|
|
4669
4713
|
const { prefix } = ticketBranchContext(t);
|
|
4670
4714
|
const branchName = branchRenderer(t, role)(effectiveBranchTemplate(cfg, prefix));
|
|
4671
4715
|
const number = t.issue_id.replace(/^\D+/, "");
|
|
4672
|
-
|
|
4716
|
+
const { tag } = ticketBranchContext(t);
|
|
4717
|
+
return effectiveWorktreeDirName(cfg, dir, branchName, number, (template) => renderWorktreeName(template, {
|
|
4718
|
+
dir: basename4(dir.replace(/[/\\]+$/, "")),
|
|
4719
|
+
key: t.issue_id,
|
|
4720
|
+
title: t.title ?? void 0,
|
|
4721
|
+
role,
|
|
4722
|
+
tag,
|
|
4723
|
+
prefix
|
|
4724
|
+
}));
|
|
4673
4725
|
}
|
|
4674
4726
|
function branchTemplates(cfg, t) {
|
|
4675
4727
|
const { prefix } = ticketBranchContext(t);
|
|
@@ -4985,7 +5037,9 @@ function writeDigest(o, d, role, stateDir) {
|
|
|
4985
5037
|
const repoFor = (dir) => {
|
|
4986
5038
|
const hit = repoCache.get(dir);
|
|
4987
5039
|
if (hit) return hit;
|
|
4988
|
-
const
|
|
5040
|
+
const target = reposOf(o.route).find((r) => r.dir === dir);
|
|
5041
|
+
const nameOverride = target ? o.route.repoOverrides[target.name]?.worktreeName : void 0;
|
|
5042
|
+
const cfg = resolveRepoConfig(loadRepoConfig(dir), nameOverride ? { worktrees: { nameOverride } } : void 0, dir);
|
|
4989
5043
|
repoCache.set(dir, cfg);
|
|
4990
5044
|
return cfg;
|
|
4991
5045
|
};
|
|
@@ -5350,7 +5404,7 @@ import { join as join7, dirname as dirname5 } from "path";
|
|
|
5350
5404
|
import { createHash as createHash2 } from "crypto";
|
|
5351
5405
|
|
|
5352
5406
|
// src/environment.ts
|
|
5353
|
-
import { basename as
|
|
5407
|
+
import { basename as basename5 } from "path";
|
|
5354
5408
|
var API_KEY_VAR = "CREW_API_KEY";
|
|
5355
5409
|
function authorshipBullets(a, contract) {
|
|
5356
5410
|
if (!a) return [];
|
|
@@ -5401,8 +5455,16 @@ function repoSection(r, key, heading) {
|
|
|
5401
5455
|
const repo = r.config;
|
|
5402
5456
|
const branchTemplate = effectiveBranchTemplate(repo, repoPrefix(repo));
|
|
5403
5457
|
const branchName = branchExample(repo, key);
|
|
5404
|
-
const
|
|
5405
|
-
const
|
|
5458
|
+
const checkoutName = basename5(r.dir.replace(/[/\\]+$/, ""));
|
|
5459
|
+
const worktreeName = effectiveWorktreeDirName(
|
|
5460
|
+
repo,
|
|
5461
|
+
r.dir,
|
|
5462
|
+
branchName,
|
|
5463
|
+
key.replace(/^\D+/, ""),
|
|
5464
|
+
// The example ticket has no tag of its own, so `{issue}` is the key.
|
|
5465
|
+
(template) => renderWorktreeName(template, { dir: checkoutName, key, title: "Fix the widget", role: "dev", prefix: repoPrefix(repo) })
|
|
5466
|
+
);
|
|
5467
|
+
const worktreePattern = repo.worktrees.name ?? (repo.provenance["worktrees.prefix"] !== "default" ? `${repo.worktrees.prefix}<number>` : `${checkoutName}-<branch>`);
|
|
5406
5468
|
const lines = [
|
|
5407
5469
|
"",
|
|
5408
5470
|
heading,
|
|
@@ -6375,7 +6437,8 @@ async function guardRunHandoff(route, ship, tracker, role, workingId, log) {
|
|
|
6375
6437
|
const cfg = resolveRepoConfig(loadRepoConfig(target.dir), {
|
|
6376
6438
|
hooks: { ...route.hooks, ...o?.hooks },
|
|
6377
6439
|
labels: { ...route.labels, ...o?.labels },
|
|
6378
|
-
branch: { ...route.branch, ...o?.branch }
|
|
6440
|
+
branch: { ...route.branch, ...o?.branch },
|
|
6441
|
+
worktrees: { nameOverride: o?.worktreeName }
|
|
6379
6442
|
}, target.dir);
|
|
6380
6443
|
if (role === "qa") {
|
|
6381
6444
|
await retireRunWorktree(tracker, target.dir, cfg, t, role, seatId, ship.name, log);
|
|
@@ -9032,7 +9095,7 @@ async function showLogEntry(route, entryId, opts = {}) {
|
|
|
9032
9095
|
|
|
9033
9096
|
// src/repos-cmd.ts
|
|
9034
9097
|
import { homedir as homedir3 } from "os";
|
|
9035
|
-
import { basename as
|
|
9098
|
+
import { basename as basename6, resolve as resolve3 } from "path";
|
|
9036
9099
|
import { isMap, isSeq, parseDocument, stringify as stringify2 } from "yaml";
|
|
9037
9100
|
var ReposError = class extends Error {
|
|
9038
9101
|
};
|
|
@@ -9104,7 +9167,7 @@ function configuredRepos(text, route, base) {
|
|
|
9104
9167
|
});
|
|
9105
9168
|
}
|
|
9106
9169
|
const dir = m.get("dir");
|
|
9107
|
-
return dir ? [{ name:
|
|
9170
|
+
return dir ? [{ name: basename6(String(dir)), dir: expandDir(String(dir), base) }] : [];
|
|
9108
9171
|
}
|
|
9109
9172
|
function planRepoAdd(i) {
|
|
9110
9173
|
const doc = parseDocument(i.text);
|
|
@@ -9116,7 +9179,7 @@ function planRepoAdd(i) {
|
|
|
9116
9179
|
throw new ReposError(`${target} is already configured on route ${i.route}`);
|
|
9117
9180
|
}
|
|
9118
9181
|
const matched = matchRepoName(i.origin, i.resolved);
|
|
9119
|
-
const name = matched ?? i.name ?? normalizeRemote(i.origin)?.split("/").pop() ??
|
|
9182
|
+
const name = matched ?? i.name ?? normalizeRemote(i.origin)?.split("/").pop() ?? basename6(target);
|
|
9120
9183
|
let warning;
|
|
9121
9184
|
if (!matched) {
|
|
9122
9185
|
const known = Object.values(i.resolved?.repoNames ?? {});
|
|
@@ -9280,14 +9343,14 @@ function schedulerInstalled(plan, exists, crontab) {
|
|
|
9280
9343
|
|
|
9281
9344
|
// src/worktree-sweep.ts
|
|
9282
9345
|
import { existsSync as existsSync15 } from "fs";
|
|
9283
|
-
import { basename as
|
|
9346
|
+
import { basename as basename7 } from "path";
|
|
9284
9347
|
function planWorktreeSweep(target, tickets, contract) {
|
|
9285
9348
|
const terminal = new Set(contract.statuses.resolved.filter((s) => s !== contract.statuses.verified));
|
|
9286
9349
|
const verified = contract.statuses.verified;
|
|
9287
9350
|
const byNumber = new Map(tickets.map((t) => [t.issue_id.replace(/^\D+/, ""), t]));
|
|
9288
9351
|
const actions = [];
|
|
9289
9352
|
for (const w of worktrees(target.dir)) {
|
|
9290
|
-
const m = /(?:^|-)(\d+)$/.exec(
|
|
9353
|
+
const m = /(?:^|-)(\d+)$/.exec(basename7(w.path));
|
|
9291
9354
|
if (!m) continue;
|
|
9292
9355
|
const ticket = byNumber.get(m[1]);
|
|
9293
9356
|
if (!ticket) continue;
|
|
@@ -10490,7 +10553,8 @@ async function buildEnvironment(route, ship, ticket) {
|
|
|
10490
10553
|
config: resolveRepoConfig(loadRepoConfig(t.dir), {
|
|
10491
10554
|
hooks: { ...route.hooks, ...o?.hooks },
|
|
10492
10555
|
labels: { ...route.labels, ...o?.labels },
|
|
10493
|
-
branch: { ...route.branch, ...o?.branch }
|
|
10556
|
+
branch: { ...route.branch, ...o?.branch },
|
|
10557
|
+
worktrees: { nameOverride: o?.worktreeName }
|
|
10494
10558
|
}, t.dir)
|
|
10495
10559
|
};
|
|
10496
10560
|
});
|
|
@@ -11085,7 +11149,7 @@ ${changed2.map((c) => ` - ${c}
|
|
|
11085
11149
|
// that declares its own `worktrees.prefix` shadows either, and
|
|
11086
11150
|
// `doctor` reports that the way it reports every other shadowed
|
|
11087
11151
|
// setting.
|
|
11088
|
-
worktrees: { prefix: shipWorktreePrefixFor(c) ?? await areaWorktreePrefix(c, id) }
|
|
11152
|
+
worktrees: { prefix: shipWorktreePrefixFor(c) ?? await areaWorktreePrefix(c, id), nameOverride: o?.worktreeName }
|
|
11089
11153
|
}, t.dir)
|
|
11090
11154
|
};
|
|
11091
11155
|
}));
|
|
@@ -11142,7 +11206,7 @@ ${changed2.map((c) => ` - ${c}
|
|
|
11142
11206
|
labels: { ...c.labels, ...o?.labels },
|
|
11143
11207
|
release: mergeRouteRelease(c.release, o?.release),
|
|
11144
11208
|
branch: { ...c.branch, ...o?.branch },
|
|
11145
|
-
worktrees: { prefix: shipWorktreePrefixFor(c) }
|
|
11209
|
+
worktrees: { prefix: shipWorktreePrefixFor(c), nameOverride: o?.worktreeName }
|
|
11146
11210
|
}, target.dir);
|
|
11147
11211
|
const problems = validateEffective(repo);
|
|
11148
11212
|
for (const p of problems) remit.warn(`${scope}: ${p}`);
|
|
@@ -13195,7 +13259,7 @@ Signed in as ${result.identity.email} \u2014 minted an API key in workspace "${r
|
|
|
13195
13259
|
// `synthesis-tabl-123`. `worktreePrefix` above is kept for
|
|
13196
13260
|
// config-provenance display; this is the field that actually
|
|
13197
13261
|
// describes where a worktree lands by default.
|
|
13198
|
-
worktreeDirPattern: r.config.provenance["worktrees.prefix"] !== "default" ? `${r.config.worktrees.prefix}<number>` : `${
|
|
13262
|
+
worktreeDirPattern: r.config.worktrees.name ?? (r.config.provenance["worktrees.prefix"] !== "default" ? `${r.config.worktrees.prefix}<number>` : `${basename8(r.dir.replace(/[/\\]+$/, ""))}-<branch>`),
|
|
13199
13263
|
worktreeParent: resolvePath(r.dir, "..")
|
|
13200
13264
|
})),
|
|
13201
13265
|
waiting: waiting ? { ticket: waiting.ticket, since: waiting.since, streak: fairness.streak() } : null
|
|
@@ -13294,10 +13358,10 @@ routes: ${cfg.routes.map((c) => c.route).join(", ")}
|
|
|
13294
13358
|
);
|
|
13295
13359
|
for (const r of await resolvedRepos(route)) {
|
|
13296
13360
|
const { config } = r;
|
|
13297
|
-
const worktreePattern = config.provenance["worktrees.prefix"] !== "default" ? `${config.worktrees.prefix}<number>` : `${
|
|
13361
|
+
const worktreePattern = config.worktrees.name ?? (config.provenance["worktrees.prefix"] !== "default" ? `${config.worktrees.prefix}<number>` : `${basename8(r.dir.replace(/[/\\]+$/, ""))}-${effectiveBranchTemplate(config, void 0)}`);
|
|
13298
13362
|
process.stdout.write(
|
|
13299
13363
|
`${`repo ${r.name}:`.padEnd(19)}${r.dir}
|
|
13300
|
-
worktrees at ../${worktreePattern} (${config.provenance["worktrees.prefix"] ?? "default"}), branch ${config.branch.name}
|
|
13364
|
+
worktrees at ../${worktreePattern} (${config.provenance["worktrees.name"] ?? config.provenance["worktrees.prefix"] ?? "default"}), branch ${config.branch.name}
|
|
13301
13365
|
requires ${config.platform} \u2014 ${satisfies(host, config.platform) ? "OK" : "MISMATCH"}
|
|
13302
13366
|
`
|
|
13303
13367
|
);
|
package/package.json
CHANGED