@ogpoyraz/wtx 0.9.2 → 0.9.3
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/dist/cli.mjs +177 -150
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -25068,7 +25068,7 @@ var init_owner = __esm(() => {
|
|
|
25068
25068
|
});
|
|
25069
25069
|
|
|
25070
25070
|
// src/lib/workspace.ts
|
|
25071
|
-
import
|
|
25071
|
+
import fs24 from "fs";
|
|
25072
25072
|
import path29 from "path";
|
|
25073
25073
|
function getWorkspaceRoot(config2) {
|
|
25074
25074
|
return path29.resolve(expandTilde(config2.workspace_root ?? path29.join(config2.root, "wtx-workspaces")));
|
|
@@ -25119,12 +25119,12 @@ function assertNoPathNesting(workspacePath, members) {
|
|
|
25119
25119
|
async function writeManifest(workspacePath, manifest) {
|
|
25120
25120
|
const manifestPath = path29.join(workspacePath, MANIFEST_FILE);
|
|
25121
25121
|
const tmpPath = path29.join(workspacePath, `${MANIFEST_FILE}.${process.pid}.${Date.now()}.tmp`);
|
|
25122
|
-
await
|
|
25122
|
+
await fs24.promises.writeFile(tmpPath, `${JSON.stringify(manifest, null, 2)}
|
|
25123
25123
|
`, "utf8");
|
|
25124
|
-
await
|
|
25124
|
+
await fs24.promises.rename(tmpPath, manifestPath);
|
|
25125
25125
|
}
|
|
25126
25126
|
async function readManifest(workspacePath) {
|
|
25127
|
-
const raw = await
|
|
25127
|
+
const raw = await fs24.promises.readFile(path29.join(workspacePath, MANIFEST_FILE), "utf8");
|
|
25128
25128
|
const parsed = JSON.parse(raw);
|
|
25129
25129
|
if (parsed.version !== 1) {
|
|
25130
25130
|
throw new Error(`Unsupported workspace manifest version: ${parsed.version}`);
|
|
@@ -25139,7 +25139,7 @@ async function writeAgentsFile(workspacePath, linkNames) {
|
|
|
25139
25139
|
...linkNames.map((name) => `- ${name}`),
|
|
25140
25140
|
""
|
|
25141
25141
|
];
|
|
25142
|
-
await
|
|
25142
|
+
await fs24.promises.writeFile(path29.join(workspacePath, AGENTS_FILE), lines.join(`
|
|
25143
25143
|
`), "utf8");
|
|
25144
25144
|
}
|
|
25145
25145
|
async function createMemberSymlinks(workspacePath, members) {
|
|
@@ -25149,13 +25149,13 @@ async function createMemberSymlinks(workspacePath, members) {
|
|
|
25149
25149
|
const linkName = memberLinkName(member, taken);
|
|
25150
25150
|
const linkPath = path29.join(workspacePath, linkName);
|
|
25151
25151
|
const target = path29.resolve(member.path);
|
|
25152
|
-
await
|
|
25152
|
+
await fs24.promises.symlink(target, linkPath, process.platform === "win32" ? "junction" : "dir");
|
|
25153
25153
|
linkNames.push(linkName);
|
|
25154
25154
|
}
|
|
25155
25155
|
return linkNames;
|
|
25156
25156
|
}
|
|
25157
25157
|
async function workspaceLinkNames(workspacePath) {
|
|
25158
|
-
const entries = await
|
|
25158
|
+
const entries = await fs24.promises.readdir(workspacePath, { withFileTypes: true });
|
|
25159
25159
|
return entries.filter((entry) => entry.name !== MANIFEST_FILE && entry.name !== AGENTS_FILE && entry.isSymbolicLink()).map((entry) => entry.name).sort();
|
|
25160
25160
|
}
|
|
25161
25161
|
async function rebuildAgentsFile(workspacePath) {
|
|
@@ -25165,7 +25165,7 @@ async function createWorkspace(opts) {
|
|
|
25165
25165
|
validateWorkspaceName(opts.name);
|
|
25166
25166
|
const workspacePath = workspacePathFor(opts.name, opts.config);
|
|
25167
25167
|
assertNoPathNesting(workspacePath, opts.members);
|
|
25168
|
-
await
|
|
25168
|
+
await fs24.promises.mkdir(workspacePath, { recursive: true });
|
|
25169
25169
|
const linkNames = await createMemberSymlinks(workspacePath, opts.members);
|
|
25170
25170
|
await writeManifest(workspacePath, {
|
|
25171
25171
|
version: 1,
|
|
@@ -25183,7 +25183,7 @@ async function addMember(opts) {
|
|
|
25183
25183
|
const taken = new Set(await workspaceLinkNames(opts.workspacePath));
|
|
25184
25184
|
const linkName = memberLinkName(opts.member, taken);
|
|
25185
25185
|
const target = path29.resolve(opts.member.path);
|
|
25186
|
-
await
|
|
25186
|
+
await fs24.promises.symlink(target, path29.join(opts.workspacePath, linkName), process.platform === "win32" ? "junction" : "dir");
|
|
25187
25187
|
manifest.members.push({ repo: opts.member.repo, branch: opts.member.branch });
|
|
25188
25188
|
await writeManifest(opts.workspacePath, manifest);
|
|
25189
25189
|
await rebuildAgentsFile(opts.workspacePath);
|
|
@@ -25197,7 +25197,7 @@ async function removeMember(opts) {
|
|
|
25197
25197
|
const linkNames = await workspaceLinkNames(opts.workspacePath);
|
|
25198
25198
|
for (const linkName of linkNames) {
|
|
25199
25199
|
if (linkName === opts.repo || linkName === `${opts.repo}-${opts.branch.replace(/[\\/]+/g, "-")}`) {
|
|
25200
|
-
await
|
|
25200
|
+
await fs24.promises.unlink(path29.join(opts.workspacePath, linkName));
|
|
25201
25201
|
break;
|
|
25202
25202
|
}
|
|
25203
25203
|
}
|
|
@@ -25206,7 +25206,7 @@ async function removeMember(opts) {
|
|
|
25206
25206
|
}
|
|
25207
25207
|
async function listWorkspaces(workspaceRoot) {
|
|
25208
25208
|
try {
|
|
25209
|
-
const entries = await
|
|
25209
|
+
const entries = await fs24.promises.readdir(path29.resolve(expandTilde(workspaceRoot)), { withFileTypes: true });
|
|
25210
25210
|
const workspaces = [];
|
|
25211
25211
|
for (const entry of entries) {
|
|
25212
25212
|
if (!entry.isDirectory())
|
|
@@ -25235,7 +25235,7 @@ async function verifyLink(linkPath, visited) {
|
|
|
25235
25235
|
visited.add(resolvedLink);
|
|
25236
25236
|
let stats;
|
|
25237
25237
|
try {
|
|
25238
|
-
stats = await
|
|
25238
|
+
stats = await fs24.promises.lstat(linkPath);
|
|
25239
25239
|
} catch {
|
|
25240
25240
|
return "broken";
|
|
25241
25241
|
}
|
|
@@ -25243,13 +25243,13 @@ async function verifyLink(linkPath, visited) {
|
|
|
25243
25243
|
return "ok";
|
|
25244
25244
|
let rawTarget;
|
|
25245
25245
|
try {
|
|
25246
|
-
rawTarget = await
|
|
25246
|
+
rawTarget = await fs24.promises.readlink(linkPath);
|
|
25247
25247
|
} catch {
|
|
25248
25248
|
return "broken";
|
|
25249
25249
|
}
|
|
25250
25250
|
const target = path29.isAbsolute(rawTarget) ? rawTarget : path29.resolve(path29.dirname(linkPath), rawTarget);
|
|
25251
25251
|
try {
|
|
25252
|
-
const targetStats = await
|
|
25252
|
+
const targetStats = await fs24.promises.lstat(target);
|
|
25253
25253
|
if (!targetStats.isSymbolicLink())
|
|
25254
25254
|
return "ok";
|
|
25255
25255
|
} catch {
|
|
@@ -25260,7 +25260,7 @@ async function verifyLink(linkPath, visited) {
|
|
|
25260
25260
|
async function verify(workspacePath) {
|
|
25261
25261
|
const result = { ok: true, broken: [], cycles: [] };
|
|
25262
25262
|
try {
|
|
25263
|
-
const entries = await
|
|
25263
|
+
const entries = await fs24.promises.readdir(workspacePath, { withFileTypes: true });
|
|
25264
25264
|
for (const entry of entries) {
|
|
25265
25265
|
if (entry.name === MANIFEST_FILE || entry.name === AGENTS_FILE || !entry.isSymbolicLink())
|
|
25266
25266
|
continue;
|
|
@@ -27195,7 +27195,7 @@ var init_DetailsTab = __esm(() => {
|
|
|
27195
27195
|
});
|
|
27196
27196
|
|
|
27197
27197
|
// src/lib/changes.ts
|
|
27198
|
-
import
|
|
27198
|
+
import fs34 from "node:fs";
|
|
27199
27199
|
import path37 from "node:path";
|
|
27200
27200
|
function cacheKey(opts, filePath) {
|
|
27201
27201
|
return [opts.repoPath, opts.branch, opts.scope, filePath ?? ""].join("\x00");
|
|
@@ -27328,7 +27328,7 @@ async function getChangedFiles(opts) {
|
|
|
27328
27328
|
continue;
|
|
27329
27329
|
try {
|
|
27330
27330
|
const full = path37.join(opts.repoPath, p);
|
|
27331
|
-
const buf =
|
|
27331
|
+
const buf = fs34.readFileSync(full);
|
|
27332
27332
|
const binary = buf.includes(0);
|
|
27333
27333
|
const str = binary ? "" : buf.toString("utf8");
|
|
27334
27334
|
const added = binary ? 0 : str.split(`
|
|
@@ -27379,7 +27379,7 @@ async function getFileDiff(opts) {
|
|
|
27379
27379
|
if (!rawDiff && opts.scope === "worktree" && changedFile.status === "A") {
|
|
27380
27380
|
try {
|
|
27381
27381
|
const full = path37.join(opts.repoPath, opts.filePath);
|
|
27382
|
-
const buf =
|
|
27382
|
+
const buf = fs34.readFileSync(full);
|
|
27383
27383
|
if (!buf.includes(0)) {
|
|
27384
27384
|
const content = buf.toString("utf8");
|
|
27385
27385
|
const lines = content.split(`
|
|
@@ -28408,7 +28408,7 @@ var init_ActionLogModal = __esm(() => {
|
|
|
28408
28408
|
});
|
|
28409
28409
|
|
|
28410
28410
|
// src/lib/history.ts
|
|
28411
|
-
import
|
|
28411
|
+
import fs35 from "fs";
|
|
28412
28412
|
import path38 from "path";
|
|
28413
28413
|
import os4 from "os";
|
|
28414
28414
|
function getHistoryDir() {
|
|
@@ -28422,24 +28422,24 @@ function rotateHistory(maxBytes = HISTORY_MAX_BYTES, keepLines = HISTORY_ROTATE_
|
|
|
28422
28422
|
const historyPath = getHistoryPath();
|
|
28423
28423
|
let size = 0;
|
|
28424
28424
|
try {
|
|
28425
|
-
size =
|
|
28425
|
+
size = fs35.statSync(historyPath).size;
|
|
28426
28426
|
} catch {
|
|
28427
28427
|
return;
|
|
28428
28428
|
}
|
|
28429
28429
|
if (size <= maxBytes)
|
|
28430
28430
|
return;
|
|
28431
|
-
const lines =
|
|
28431
|
+
const lines = fs35.readFileSync(historyPath, "utf-8").split(`
|
|
28432
28432
|
`).filter(Boolean);
|
|
28433
28433
|
const kept = lines.slice(-keepLines);
|
|
28434
28434
|
const tmpPath = `${historyPath}.tmp.${process.pid}`;
|
|
28435
28435
|
try {
|
|
28436
|
-
|
|
28436
|
+
fs35.writeFileSync(tmpPath, kept.length > 0 ? `${kept.join(`
|
|
28437
28437
|
`)}
|
|
28438
28438
|
` : "", "utf-8");
|
|
28439
|
-
|
|
28439
|
+
fs35.renameSync(tmpPath, historyPath);
|
|
28440
28440
|
} catch (err) {
|
|
28441
|
-
if (
|
|
28442
|
-
|
|
28441
|
+
if (fs35.existsSync(tmpPath)) {
|
|
28442
|
+
fs35.unlinkSync(tmpPath);
|
|
28443
28443
|
}
|
|
28444
28444
|
throw err;
|
|
28445
28445
|
}
|
|
@@ -28447,18 +28447,18 @@ function rotateHistory(maxBytes = HISTORY_MAX_BYTES, keepLines = HISTORY_ROTATE_
|
|
|
28447
28447
|
function appendHistory(entry) {
|
|
28448
28448
|
try {
|
|
28449
28449
|
const dir = getHistoryDir();
|
|
28450
|
-
if (!
|
|
28451
|
-
|
|
28450
|
+
if (!fs35.existsSync(dir)) {
|
|
28451
|
+
fs35.mkdirSync(dir, { recursive: true });
|
|
28452
28452
|
}
|
|
28453
28453
|
rotateHistory();
|
|
28454
|
-
|
|
28454
|
+
fs35.appendFileSync(getHistoryPath(), `${JSON.stringify(entry)}
|
|
28455
28455
|
`, "utf-8");
|
|
28456
28456
|
} catch {}
|
|
28457
28457
|
}
|
|
28458
28458
|
function readRecentHistory(limit = 50) {
|
|
28459
28459
|
let content;
|
|
28460
28460
|
try {
|
|
28461
|
-
content =
|
|
28461
|
+
content = fs35.readFileSync(getHistoryPath(), "utf-8");
|
|
28462
28462
|
} catch {
|
|
28463
28463
|
return [];
|
|
28464
28464
|
}
|
|
@@ -34137,8 +34137,66 @@ init_config();
|
|
|
34137
34137
|
init_log();
|
|
34138
34138
|
init_git();
|
|
34139
34139
|
init_resolver();
|
|
34140
|
-
import
|
|
34140
|
+
import fs23 from "fs";
|
|
34141
34141
|
import path28 from "path";
|
|
34142
|
+
|
|
34143
|
+
// src/lib/worktree-remove.ts
|
|
34144
|
+
init_git();
|
|
34145
|
+
import fs22 from "fs";
|
|
34146
|
+
function isSubmoduleWorktreeError(message) {
|
|
34147
|
+
return message.includes("submodule") || message.includes("containing submodules");
|
|
34148
|
+
}
|
|
34149
|
+
function isMissingWorktreePathError(message) {
|
|
34150
|
+
return message.includes("ENOENT") || message.includes("No such file") || message.includes("does not exist") || message.includes("not a git repository") || message.includes("cannot change to");
|
|
34151
|
+
}
|
|
34152
|
+
function isRecoverableWorktreeRemoveError(message) {
|
|
34153
|
+
return message.includes("not a working tree") || message.includes("already removed") || isSubmoduleWorktreeError(message) || isMissingWorktreePathError(message);
|
|
34154
|
+
}
|
|
34155
|
+
function removePathIfExists(wtPath, opts) {
|
|
34156
|
+
if (!opts.dryRun && fs22.existsSync(wtPath)) {
|
|
34157
|
+
fs22.rmSync(wtPath, { recursive: true, force: true });
|
|
34158
|
+
}
|
|
34159
|
+
}
|
|
34160
|
+
async function pruneWorktreeAdmin(mainPath, opts) {
|
|
34161
|
+
try {
|
|
34162
|
+
await gitExec(["-C", mainPath, "worktree", "prune"], opts);
|
|
34163
|
+
} catch {}
|
|
34164
|
+
}
|
|
34165
|
+
async function removeWorktreeSafely(params) {
|
|
34166
|
+
const { mainPath, wtPath, force, opts } = params;
|
|
34167
|
+
const args = ["-C", mainPath, "worktree", "remove", wtPath];
|
|
34168
|
+
if (force) {
|
|
34169
|
+
args.push("--force");
|
|
34170
|
+
}
|
|
34171
|
+
try {
|
|
34172
|
+
await gitExec(args, opts);
|
|
34173
|
+
return { usedForce: force, manualCleanup: false };
|
|
34174
|
+
} catch (err) {
|
|
34175
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
34176
|
+
if (isSubmoduleWorktreeError(msg) && !force) {
|
|
34177
|
+
try {
|
|
34178
|
+
await gitExec(["-C", mainPath, "worktree", "remove", "--force", wtPath], opts);
|
|
34179
|
+
return { usedForce: true, manualCleanup: false };
|
|
34180
|
+
} catch (forceErr) {
|
|
34181
|
+
const forceMsg = forceErr instanceof Error ? forceErr.message : String(forceErr);
|
|
34182
|
+
if (isRecoverableWorktreeRemoveError(forceMsg)) {
|
|
34183
|
+
await pruneWorktreeAdmin(mainPath, opts);
|
|
34184
|
+
removePathIfExists(wtPath, opts);
|
|
34185
|
+
return { usedForce: true, manualCleanup: true };
|
|
34186
|
+
}
|
|
34187
|
+
throw forceErr;
|
|
34188
|
+
}
|
|
34189
|
+
}
|
|
34190
|
+
if (isRecoverableWorktreeRemoveError(msg)) {
|
|
34191
|
+
await pruneWorktreeAdmin(mainPath, opts);
|
|
34192
|
+
removePathIfExists(wtPath, opts);
|
|
34193
|
+
return { usedForce: force, manualCleanup: true };
|
|
34194
|
+
}
|
|
34195
|
+
throw err;
|
|
34196
|
+
}
|
|
34197
|
+
}
|
|
34198
|
+
|
|
34199
|
+
// src/commands/pull.ts
|
|
34142
34200
|
init_forge();
|
|
34143
34201
|
init_stack();
|
|
34144
34202
|
function registerPullCommand(program2) {
|
|
@@ -34255,7 +34313,7 @@ function registerPullCommand(program2) {
|
|
|
34255
34313
|
const worktrees = await getWorktreeList(target.mainPath);
|
|
34256
34314
|
const existingWorktree = worktrees.find((w) => w.path === wtPath || w.branch === branch);
|
|
34257
34315
|
const localBranchFound = await localBranchExists(target.mainPath, branch, globalOpts);
|
|
34258
|
-
const dirExists = Boolean(existingWorktree) ||
|
|
34316
|
+
const dirExists = Boolean(existingWorktree) || fs23.existsSync(wtPath);
|
|
34259
34317
|
if (localBranchFound || dirExists) {
|
|
34260
34318
|
if (options.force) {
|
|
34261
34319
|
stepWarning(`Branch '${branch}' already exists — --force: will override`, dirExists ? wtPath : "local branch exists");
|
|
@@ -34268,17 +34326,22 @@ function registerPullCommand(program2) {
|
|
|
34268
34326
|
if (options.force && (localBranchFound || dirExists)) {
|
|
34269
34327
|
if (existingWorktree) {
|
|
34270
34328
|
try {
|
|
34271
|
-
await
|
|
34329
|
+
await removeWorktreeSafely({
|
|
34330
|
+
mainPath: target.mainPath,
|
|
34331
|
+
wtPath: existingWorktree.path,
|
|
34332
|
+
force: true,
|
|
34333
|
+
opts: { verbose: globalOpts.verbose, dryRun: globalOpts.dryRun }
|
|
34334
|
+
});
|
|
34272
34335
|
} catch (err) {
|
|
34273
34336
|
const message = err instanceof Error ? err.message : String(err);
|
|
34274
|
-
if (!message
|
|
34337
|
+
if (!isRecoverableWorktreeRemoveError(message)) {
|
|
34275
34338
|
stepWarning("Worktree removal failed", message.split(`
|
|
34276
34339
|
`)[0] ?? message);
|
|
34277
34340
|
}
|
|
34278
34341
|
}
|
|
34279
34342
|
}
|
|
34280
|
-
if (!globalOpts.dryRun &&
|
|
34281
|
-
|
|
34343
|
+
if (!globalOpts.dryRun && fs23.existsSync(wtPath)) {
|
|
34344
|
+
fs23.rmSync(wtPath, { recursive: true, force: true });
|
|
34282
34345
|
}
|
|
34283
34346
|
if (localBranchFound) {
|
|
34284
34347
|
try {
|
|
@@ -34322,7 +34385,7 @@ function registerPullCommand(program2) {
|
|
|
34322
34385
|
}
|
|
34323
34386
|
stepSuccess("Fetched");
|
|
34324
34387
|
if (!globalOpts.dryRun) {
|
|
34325
|
-
|
|
34388
|
+
fs23.mkdirSync(path28.dirname(wtPath), { recursive: true });
|
|
34326
34389
|
}
|
|
34327
34390
|
try {
|
|
34328
34391
|
const createBranchFlag = options.force ? "-B" : "-b";
|
|
@@ -34456,10 +34519,10 @@ function registerPullBranchCommand(program2) {
|
|
|
34456
34519
|
init_config();
|
|
34457
34520
|
init_log();
|
|
34458
34521
|
init_git();
|
|
34522
|
+
import fs25 from "fs";
|
|
34523
|
+
import path30 from "path";
|
|
34459
34524
|
init_resolver();
|
|
34460
34525
|
init_path_safety();
|
|
34461
|
-
import fs24 from "fs";
|
|
34462
|
-
import path30 from "path";
|
|
34463
34526
|
|
|
34464
34527
|
// src/lib/prompts.ts
|
|
34465
34528
|
import * as readline2 from "readline";
|
|
@@ -34507,15 +34570,9 @@ init_workspace();
|
|
|
34507
34570
|
function errorMessage2(err) {
|
|
34508
34571
|
return err instanceof Error ? err.message : String(err);
|
|
34509
34572
|
}
|
|
34510
|
-
function isMissingWorktreePathError(message) {
|
|
34511
|
-
return message.includes("ENOENT") || message.includes("No such file") || message.includes("does not exist") || message.includes("not a git repository") || message.includes("cannot change to");
|
|
34512
|
-
}
|
|
34513
|
-
function isRecoverableWorktreeRemoveError(message) {
|
|
34514
|
-
return message.includes("not a working tree") || message.includes("already removed") || message.includes("submodule") || message.includes("containing submodules") || isMissingWorktreePathError(message);
|
|
34515
|
-
}
|
|
34516
34573
|
function removeExistingPath(wtPath, opts) {
|
|
34517
|
-
if (!opts.dryRun &&
|
|
34518
|
-
|
|
34574
|
+
if (!opts.dryRun && fs25.existsSync(wtPath)) {
|
|
34575
|
+
fs25.rmSync(wtPath, { recursive: true, force: true });
|
|
34519
34576
|
}
|
|
34520
34577
|
}
|
|
34521
34578
|
async function removeLocalBranchIfExists(repoPath, branch, opts) {
|
|
@@ -34604,7 +34661,7 @@ function registerRemoveCommand(program2) {
|
|
|
34604
34661
|
const worktrees = await getWorktreeList(repo.mainPath);
|
|
34605
34662
|
const target = findWorktreeForBranch(worktrees, branch, repo.mainPath, candidatePath);
|
|
34606
34663
|
if (!target) {
|
|
34607
|
-
if (options.force && (
|
|
34664
|
+
if (options.force && (fs25.existsSync(candidatePath) || await localBranchExists(repo.mainPath, branch, globalOpts))) {
|
|
34608
34665
|
if (!await confirmDeletionIfNeeded(repo, candidatePath, options, globalOpts)) {
|
|
34609
34666
|
skipCount++;
|
|
34610
34667
|
continue;
|
|
@@ -34646,7 +34703,7 @@ function registerRemoveCommand(program2) {
|
|
|
34646
34703
|
}
|
|
34647
34704
|
} catch (err) {
|
|
34648
34705
|
const msg = errorMessage2(err);
|
|
34649
|
-
if (isMissingWorktreePathError(msg) || !
|
|
34706
|
+
if (isMissingWorktreePathError(msg) || !fs25.existsSync(wtPath)) {
|
|
34650
34707
|
stepWarning("Worktree path missing", "continuing with removal cleanup");
|
|
34651
34708
|
} else {
|
|
34652
34709
|
stepError("Failed to check for uncommitted changes", msg);
|
|
@@ -34655,7 +34712,7 @@ function registerRemoveCommand(program2) {
|
|
|
34655
34712
|
}
|
|
34656
34713
|
}
|
|
34657
34714
|
}
|
|
34658
|
-
if (options.force && !globalOpts.dryRun && !
|
|
34715
|
+
if (options.force && !globalOpts.dryRun && !fs25.existsSync(wtPath)) {
|
|
34659
34716
|
if (!await confirmDeletionIfNeeded(repo, wtPath, options, globalOpts)) {
|
|
34660
34717
|
skipCount++;
|
|
34661
34718
|
continue;
|
|
@@ -34679,52 +34736,16 @@ function registerRemoveCommand(program2) {
|
|
|
34679
34736
|
skipCount++;
|
|
34680
34737
|
continue;
|
|
34681
34738
|
}
|
|
34682
|
-
const
|
|
34683
|
-
|
|
34684
|
-
|
|
34685
|
-
|
|
34686
|
-
|
|
34687
|
-
|
|
34688
|
-
|
|
34689
|
-
|
|
34690
|
-
const msg = errorMessage2(err);
|
|
34691
|
-
const isSubmodule = msg.includes("submodule") || msg.includes("containing submodules");
|
|
34692
|
-
if (isSubmodule && !options.force && !args.includes("--force")) {
|
|
34693
|
-
stepWarning("Worktree contains submodules — retrying with --force", msg.split(`
|
|
34694
|
-
`)[0] ?? msg);
|
|
34695
|
-
try {
|
|
34696
|
-
await gitExec(["-C", repo.mainPath, "worktree", "remove", "--force", wtPath], globalOpts);
|
|
34697
|
-
stepSuccess("Worktree removed", wtPath);
|
|
34698
|
-
} catch (forceErr) {
|
|
34699
|
-
const forceMsg = errorMessage2(forceErr);
|
|
34700
|
-
if (isRecoverableWorktreeRemoveError(forceMsg)) {
|
|
34701
|
-
stepWarning("Worktree already removed or invalid", forceMsg);
|
|
34702
|
-
try {
|
|
34703
|
-
await gitExec(["-C", repo.mainPath, "worktree", "prune"], globalOpts);
|
|
34704
|
-
} catch (pruneErr) {
|
|
34705
|
-
stepWarning("Worktree prune failed", errorMessage2(pruneErr));
|
|
34706
|
-
}
|
|
34707
|
-
removeExistingPath(wtPath, globalOpts);
|
|
34708
|
-
await removeLocalBranchBestEffort(repo.mainPath, branch, globalOpts);
|
|
34709
|
-
stepSuccess("Worktree removed", wtPath);
|
|
34710
|
-
} else {
|
|
34711
|
-
throw forceErr;
|
|
34712
|
-
}
|
|
34713
|
-
}
|
|
34714
|
-
} else if (isRecoverableWorktreeRemoveError(msg)) {
|
|
34715
|
-
stepWarning("Worktree already removed or invalid", msg);
|
|
34716
|
-
try {
|
|
34717
|
-
await gitExec(["-C", repo.mainPath, "worktree", "prune"], globalOpts);
|
|
34718
|
-
} catch (pruneErr) {
|
|
34719
|
-
stepWarning("Worktree prune failed", errorMessage2(pruneErr));
|
|
34720
|
-
}
|
|
34721
|
-
removeExistingPath(wtPath, globalOpts);
|
|
34722
|
-
await removeLocalBranchBestEffort(repo.mainPath, branch, globalOpts);
|
|
34723
|
-
stepSuccess("Worktree removed", wtPath);
|
|
34724
|
-
} else {
|
|
34725
|
-
throw err;
|
|
34726
|
-
}
|
|
34739
|
+
const result = await removeWorktreeSafely({
|
|
34740
|
+
mainPath: repo.mainPath,
|
|
34741
|
+
wtPath,
|
|
34742
|
+
force: !!options.force,
|
|
34743
|
+
opts: globalOpts
|
|
34744
|
+
});
|
|
34745
|
+
if (result.manualCleanup) {
|
|
34746
|
+
await removeLocalBranchBestEffort(repo.mainPath, branch, globalOpts);
|
|
34727
34747
|
}
|
|
34748
|
+
stepSuccess("Worktree removed", wtPath);
|
|
34728
34749
|
await finishCleanup(repo, wtPath, branch, globalOpts);
|
|
34729
34750
|
await unlinkRemovedWorktreeFromWorkspaces({ workspaceRoot, repo: repo.name, branch });
|
|
34730
34751
|
if (children.length > 0) {
|
|
@@ -34751,9 +34772,9 @@ init_source();
|
|
|
34751
34772
|
init_config();
|
|
34752
34773
|
init_log();
|
|
34753
34774
|
init_git();
|
|
34775
|
+
import path31 from "path";
|
|
34754
34776
|
init_resolver();
|
|
34755
34777
|
init_forge();
|
|
34756
|
-
import path31 from "path";
|
|
34757
34778
|
|
|
34758
34779
|
// src/lib/prune.ts
|
|
34759
34780
|
function selectMergedCandidates(worktrees, mainPath, prMap) {
|
|
@@ -34890,16 +34911,17 @@ function registerPruneCommand(program2) {
|
|
|
34890
34911
|
repoHeader(repo.name);
|
|
34891
34912
|
currentRepo = repo.name;
|
|
34892
34913
|
}
|
|
34893
|
-
const args = ["-C", repo.mainPath, "worktree", "remove", candidate.path];
|
|
34894
|
-
if (options.force) {
|
|
34895
|
-
args.push("--force");
|
|
34896
|
-
}
|
|
34897
34914
|
try {
|
|
34898
|
-
await
|
|
34915
|
+
await removeWorktreeSafely({
|
|
34916
|
+
mainPath: repo.mainPath,
|
|
34917
|
+
wtPath: candidate.path,
|
|
34918
|
+
force: !!options.force,
|
|
34919
|
+
opts: globalOpts
|
|
34920
|
+
});
|
|
34899
34921
|
stepSuccess("Worktree removed", label);
|
|
34900
34922
|
} catch (err) {
|
|
34901
34923
|
const msg = err instanceof Error ? err.message : String(err);
|
|
34902
|
-
if (
|
|
34924
|
+
if (isRecoverableWorktreeRemoveError(msg)) {
|
|
34903
34925
|
stepWarning("Worktree already removed or invalid", msg);
|
|
34904
34926
|
skippedCount++;
|
|
34905
34927
|
continue;
|
|
@@ -35002,7 +35024,7 @@ init_source();
|
|
|
35002
35024
|
init_stack();
|
|
35003
35025
|
init_stack();
|
|
35004
35026
|
import path32 from "path";
|
|
35005
|
-
import
|
|
35027
|
+
import fs26 from "fs";
|
|
35006
35028
|
function buildLsJson(reposData) {
|
|
35007
35029
|
const result = [];
|
|
35008
35030
|
for (const repo of reposData) {
|
|
@@ -35112,7 +35134,7 @@ function registerLsCommand(program2) {
|
|
|
35112
35134
|
statusStr = source_default.blue("[main checkout]");
|
|
35113
35135
|
} else if (wt.isLocked) {
|
|
35114
35136
|
statusStr = source_default.red("locked \uD83D\uDD12");
|
|
35115
|
-
} else if (
|
|
35137
|
+
} else if (fs26.existsSync(wt.path)) {
|
|
35116
35138
|
try {
|
|
35117
35139
|
dirtyFiles = await getDirtyFiles(wt.path);
|
|
35118
35140
|
if (dirtyFiles.length > 0) {
|
|
@@ -35238,7 +35260,7 @@ end
|
|
|
35238
35260
|
init_config();
|
|
35239
35261
|
init_log();
|
|
35240
35262
|
init_git();
|
|
35241
|
-
import
|
|
35263
|
+
import fs27 from "fs";
|
|
35242
35264
|
init_resolver();
|
|
35243
35265
|
init_stack();
|
|
35244
35266
|
function registerRebaseCommand(program2) {
|
|
@@ -35253,7 +35275,7 @@ function registerRebaseCommand(program2) {
|
|
|
35253
35275
|
repoHeader(repo.name);
|
|
35254
35276
|
const mainBranch = await resolveMainBranch(repo, config2);
|
|
35255
35277
|
const wtPath = getWorktreePath(repo, branch);
|
|
35256
|
-
if (!
|
|
35278
|
+
if (!fs27.existsSync(wtPath)) {
|
|
35257
35279
|
stepError("No worktree found", `${wtPath} (skipped)`);
|
|
35258
35280
|
failCount++;
|
|
35259
35281
|
continue;
|
|
@@ -35379,7 +35401,7 @@ init_execa();
|
|
|
35379
35401
|
init_config();
|
|
35380
35402
|
init_log();
|
|
35381
35403
|
init_resolver();
|
|
35382
|
-
import
|
|
35404
|
+
import fs28 from "fs";
|
|
35383
35405
|
import path33 from "path";
|
|
35384
35406
|
function registerSyncCommand(program2) {
|
|
35385
35407
|
program2.command("sync <branch>").description("re-copy sync files + run post_sync").option("--repo <repos...>", "comma-separated list of repos to target").action(async (branch, _options, cmd) => {
|
|
@@ -35391,14 +35413,14 @@ function registerSyncCommand(program2) {
|
|
|
35391
35413
|
for (const repo of repos) {
|
|
35392
35414
|
repoHeader(repo.name);
|
|
35393
35415
|
const wtPath = getWorktreePath(repo, branch);
|
|
35394
|
-
if (!
|
|
35416
|
+
if (!fs28.existsSync(wtPath)) {
|
|
35395
35417
|
stepWarning("No worktree found", `${wtPath} (skipped)`);
|
|
35396
35418
|
continue;
|
|
35397
35419
|
}
|
|
35398
35420
|
try {
|
|
35399
35421
|
if (repo.config.sync_files) {
|
|
35400
35422
|
for (const file2 of repo.config.sync_files) {
|
|
35401
|
-
if (
|
|
35423
|
+
if (fs28.existsSync(path33.join(repo.mainPath, file2))) {
|
|
35402
35424
|
if (!opts.dryRun) {
|
|
35403
35425
|
syncEntry(repo.mainPath, wtPath, file2);
|
|
35404
35426
|
}
|
|
@@ -35451,14 +35473,14 @@ function registerSyncCommand(program2) {
|
|
|
35451
35473
|
}
|
|
35452
35474
|
}
|
|
35453
35475
|
const wtNodeModules = path33.join(wtPath, "node_modules");
|
|
35454
|
-
if (
|
|
35476
|
+
if (fs28.existsSync(wtNodeModules) && fs28.lstatSync(wtNodeModules).isSymbolicLink()) {
|
|
35455
35477
|
const lockfiles = ["yarn.lock", "package-lock.json", "pnpm-lock.yaml", "bun.lockb", "bun.lock"];
|
|
35456
35478
|
for (const lock of lockfiles) {
|
|
35457
35479
|
const mainLock = path33.join(repo.mainPath, lock);
|
|
35458
35480
|
const wtLock = path33.join(wtPath, lock);
|
|
35459
|
-
if (
|
|
35460
|
-
const mainContent =
|
|
35461
|
-
const wtContent =
|
|
35481
|
+
if (fs28.existsSync(mainLock) && fs28.existsSync(wtLock)) {
|
|
35482
|
+
const mainContent = fs28.readFileSync(mainLock);
|
|
35483
|
+
const wtContent = fs28.readFileSync(wtLock);
|
|
35462
35484
|
if (!mainContent.equals(wtContent)) {
|
|
35463
35485
|
stepWarning(`${lock} differs from main — node_modules is symlinked`);
|
|
35464
35486
|
indented(`Run: wtx deps ${branch} --repo ${repo.name} --install`);
|
|
@@ -35487,7 +35509,7 @@ init_config();
|
|
|
35487
35509
|
init_log();
|
|
35488
35510
|
init_resolver();
|
|
35489
35511
|
init_deps();
|
|
35490
|
-
import
|
|
35512
|
+
import fs29 from "fs";
|
|
35491
35513
|
function registerDepsCommand(program2) {
|
|
35492
35514
|
program2.command("deps [branch]").description("Manage node_modules strategy per worktree").option("-r, --repo <repos...>", "Target specific repo(s)").option("--install", "Switch to independent node_modules (run install)").option("--symlink", "Switch to legacy symlinked node_modules").option("--json", "Output machine-readable JSON state").action(async (branch, options) => {
|
|
35493
35515
|
const globalOpts = program2.opts();
|
|
@@ -35524,7 +35546,7 @@ function registerDepsCommand(program2) {
|
|
|
35524
35546
|
continue;
|
|
35525
35547
|
}
|
|
35526
35548
|
const wtPath = getWorktreePath(repo, branch);
|
|
35527
|
-
if (!
|
|
35549
|
+
if (!fs29.existsSync(wtPath)) {
|
|
35528
35550
|
if (options.json) {
|
|
35529
35551
|
jsonResults[repo.name] = { error: "No worktree found", branch };
|
|
35530
35552
|
} else {
|
|
@@ -35582,7 +35604,7 @@ function registerDepsCommand(program2) {
|
|
|
35582
35604
|
init_config();
|
|
35583
35605
|
init_log();
|
|
35584
35606
|
init_resolver();
|
|
35585
|
-
import
|
|
35607
|
+
import fs30 from "fs";
|
|
35586
35608
|
init_git();
|
|
35587
35609
|
async function resolveMainCheckoutPath(repoCtx, branch) {
|
|
35588
35610
|
try {
|
|
@@ -35607,7 +35629,7 @@ function registerOpenCommand(program2) {
|
|
|
35607
35629
|
for (const repo of repos) {
|
|
35608
35630
|
const wtPath = getWorktreePath(repo, branch);
|
|
35609
35631
|
let targetPath = wtPath;
|
|
35610
|
-
if (!
|
|
35632
|
+
if (!fs30.existsSync(wtPath)) {
|
|
35611
35633
|
const mainCheckoutPath = await resolveMainCheckoutPath(repo, branch);
|
|
35612
35634
|
if (!mainCheckoutPath) {
|
|
35613
35635
|
continue;
|
|
@@ -35643,7 +35665,7 @@ import path35 from "path";
|
|
|
35643
35665
|
init_git();
|
|
35644
35666
|
init_resolver();
|
|
35645
35667
|
init_path_safety();
|
|
35646
|
-
import
|
|
35668
|
+
import fs31 from "fs";
|
|
35647
35669
|
import path34 from "path";
|
|
35648
35670
|
init_workspace();
|
|
35649
35671
|
async function getUpstream(wtPath) {
|
|
@@ -35686,7 +35708,7 @@ async function planRename(repo, oldBranch, newBranch, opts) {
|
|
|
35686
35708
|
throw new Error(`Worktree '${oldBranch}' is locked — unlock it before renaming`);
|
|
35687
35709
|
}
|
|
35688
35710
|
const newPath = `${repo.wtRoot}/${newBranch}`;
|
|
35689
|
-
if (
|
|
35711
|
+
if (fs31.existsSync(newPath)) {
|
|
35690
35712
|
throw new Error(`Target path already exists: ${newPath}`);
|
|
35691
35713
|
}
|
|
35692
35714
|
if (!opts.dryRun && await localBranchExists(repo.mainPath, newBranch, opts)) {
|
|
@@ -35719,7 +35741,7 @@ async function renameWorktree(params) {
|
|
|
35719
35741
|
}
|
|
35720
35742
|
await gitExec(["-C", planned.worktreePath, "branch", "-m", oldBranch, newBranch], opts);
|
|
35721
35743
|
try {
|
|
35722
|
-
|
|
35744
|
+
fs31.mkdirSync(path34.dirname(planned.newPath), { recursive: true });
|
|
35723
35745
|
await gitExec(["-C", repo.mainPath, "worktree", "move", planned.worktreePath, planned.newPath], opts);
|
|
35724
35746
|
} catch (err) {
|
|
35725
35747
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -35738,10 +35760,10 @@ async function renameWorktree(params) {
|
|
|
35738
35760
|
const resyncedFiles = [];
|
|
35739
35761
|
const keptLocalSyncFiles = [];
|
|
35740
35762
|
for (const entry of repo.config.sync_files ?? []) {
|
|
35741
|
-
if (!
|
|
35763
|
+
if (!fs31.existsSync(path34.join(repo.mainPath, entry)))
|
|
35742
35764
|
continue;
|
|
35743
35765
|
const destPath = path34.join(planned.newPath, entry);
|
|
35744
|
-
if (!
|
|
35766
|
+
if (!fs31.existsSync(destPath)) {
|
|
35745
35767
|
if (syncEntry(repo.mainPath, planned.newPath, entry)) {
|
|
35746
35768
|
resyncedFiles.push(entry);
|
|
35747
35769
|
}
|
|
@@ -35880,7 +35902,7 @@ init_resolver();
|
|
|
35880
35902
|
init_deps();
|
|
35881
35903
|
init_forge();
|
|
35882
35904
|
init_types2();
|
|
35883
|
-
import
|
|
35905
|
+
import fs32 from "fs";
|
|
35884
35906
|
init_owner();
|
|
35885
35907
|
init_stack();
|
|
35886
35908
|
init_source();
|
|
@@ -35930,7 +35952,7 @@ function registerStatusCommand(program2) {
|
|
|
35930
35952
|
const jsonOutputs = [];
|
|
35931
35953
|
for (const repo of repos) {
|
|
35932
35954
|
const wtPath = getWorktreePath(repo, branch);
|
|
35933
|
-
if (!
|
|
35955
|
+
if (!fs32.existsSync(wtPath)) {
|
|
35934
35956
|
continue;
|
|
35935
35957
|
}
|
|
35936
35958
|
found++;
|
|
@@ -36230,7 +36252,7 @@ function registerPrsCommand(program2) {
|
|
|
36230
36252
|
|
|
36231
36253
|
// src/commands/skill.ts
|
|
36232
36254
|
init_log();
|
|
36233
|
-
import
|
|
36255
|
+
import fs33 from "fs";
|
|
36234
36256
|
import path36 from "path";
|
|
36235
36257
|
import { URL as URL2 } from "url";
|
|
36236
36258
|
var __dirname2 = new URL2(".", import.meta.url).pathname;
|
|
@@ -36387,7 +36409,7 @@ function registerSkillCommand(program2) {
|
|
|
36387
36409
|
}
|
|
36388
36410
|
let projectRoot = path36.resolve(__dirname2, "..", "..");
|
|
36389
36411
|
let skillPath = path36.join(projectRoot, "skills", `${platform2}.md`);
|
|
36390
|
-
if (
|
|
36412
|
+
if (fs33.existsSync(skillPath)) {
|
|
36391
36413
|
process.stdout.write(skillPath + `
|
|
36392
36414
|
`);
|
|
36393
36415
|
} else {
|
|
@@ -36400,7 +36422,7 @@ function registerSkillCommand(program2) {
|
|
|
36400
36422
|
|
|
36401
36423
|
// src/commands/terminal.ts
|
|
36402
36424
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
36403
|
-
import
|
|
36425
|
+
import fs36 from "node:fs";
|
|
36404
36426
|
import path39 from "node:path";
|
|
36405
36427
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
36406
36428
|
function findEntry() {
|
|
@@ -36416,20 +36438,20 @@ function findEntry() {
|
|
|
36416
36438
|
for (const p of candidates) {
|
|
36417
36439
|
try {
|
|
36418
36440
|
if (p.endsWith(".mjs") || p.endsWith(".js")) {
|
|
36419
|
-
if (
|
|
36441
|
+
if (fs36.existsSync(p) && fs36.statSync(p).isFile())
|
|
36420
36442
|
return p;
|
|
36421
|
-
} else if (
|
|
36422
|
-
const stat =
|
|
36443
|
+
} else if (fs36.existsSync(p)) {
|
|
36444
|
+
const stat = fs36.statSync(p);
|
|
36423
36445
|
if (stat.isFile()) {
|
|
36424
|
-
const head =
|
|
36446
|
+
const head = fs36.readFileSync(p, "utf8").slice(0, 1024);
|
|
36425
36447
|
if (head.includes("cli.mjs") || head.includes("#!/usr/bin/env node")) {
|
|
36426
36448
|
if (p.endsWith("wtx") || p.endsWith("cli.mjs")) {
|
|
36427
|
-
const dir = path39.dirname(
|
|
36449
|
+
const dir = path39.dirname(fs36.realpathSync(p));
|
|
36428
36450
|
const cli = path39.join(dir, "cli.mjs");
|
|
36429
|
-
if (
|
|
36451
|
+
if (fs36.existsSync(cli))
|
|
36430
36452
|
return cli;
|
|
36431
36453
|
const cli2 = path39.resolve(dir, "../dist/cli.mjs");
|
|
36432
|
-
if (
|
|
36454
|
+
if (fs36.existsSync(cli2))
|
|
36433
36455
|
return cli2;
|
|
36434
36456
|
if (head.includes("import") || head.includes("commander"))
|
|
36435
36457
|
return p;
|
|
@@ -36443,7 +36465,7 @@ function findEntry() {
|
|
|
36443
36465
|
const thisPath = fileURLToPath4(import.meta.url);
|
|
36444
36466
|
const pkgRoot = path39.resolve(path39.dirname(thisPath), "../..");
|
|
36445
36467
|
const cli = path39.join(pkgRoot, "dist", "cli.mjs");
|
|
36446
|
-
if (
|
|
36468
|
+
if (fs36.existsSync(cli))
|
|
36447
36469
|
return cli;
|
|
36448
36470
|
} catch {}
|
|
36449
36471
|
return null;
|
|
@@ -36547,7 +36569,7 @@ init_deps();
|
|
|
36547
36569
|
import readline3 from "readline";
|
|
36548
36570
|
init_path_safety();
|
|
36549
36571
|
init_stack();
|
|
36550
|
-
import
|
|
36572
|
+
import fs37 from "fs";
|
|
36551
36573
|
async function runMcpServer(opts = {}) {
|
|
36552
36574
|
const input = opts.input ?? process.stdin;
|
|
36553
36575
|
const output = opts.output ?? process.stdout;
|
|
@@ -36730,7 +36752,7 @@ async function handleToolCall(name, args, config2, _opts) {
|
|
|
36730
36752
|
for (const wt of wts) {
|
|
36731
36753
|
if (!wt.path.startsWith(repo.wtRoot))
|
|
36732
36754
|
continue;
|
|
36733
|
-
const dirtyCount =
|
|
36755
|
+
const dirtyCount = fs37.existsSync(wt.path) ? (await getDirtyFiles(wt.path)).length : 0;
|
|
36734
36756
|
items.push({
|
|
36735
36757
|
repo: repo.name,
|
|
36736
36758
|
branch: wt.branch || null,
|
|
@@ -36758,7 +36780,7 @@ async function handleToolCall(name, args, config2, _opts) {
|
|
|
36758
36780
|
}
|
|
36759
36781
|
const repo = resolveRepos(config2, [args.repo])[0];
|
|
36760
36782
|
const wtPath = getWorktreePath(repo, args.branch);
|
|
36761
|
-
if (!
|
|
36783
|
+
if (!fs37.existsSync(wtPath)) {
|
|
36762
36784
|
throw { isToolError: true, message: `Worktree not found for branch ${args.branch}` };
|
|
36763
36785
|
}
|
|
36764
36786
|
const mainBranch = await resolveMainBranch(repo, config2);
|
|
@@ -36877,13 +36899,18 @@ async function handleToolCall(name, args, config2, _opts) {
|
|
|
36877
36899
|
if (children.length > 0 && args.force !== true) {
|
|
36878
36900
|
throw { isToolError: true, message: `Branch has dependent worktrees: ${children.join(", ")}. Use force:true to override.` };
|
|
36879
36901
|
}
|
|
36880
|
-
if (!args.force &&
|
|
36902
|
+
if (!args.force && fs37.existsSync(wtPath)) {
|
|
36881
36903
|
const dirty = await getDirtyFiles(wtPath);
|
|
36882
36904
|
if (dirty.length > 0) {
|
|
36883
36905
|
throw { isToolError: true, message: `Worktree is dirty. Use force:true to remove it.` };
|
|
36884
36906
|
}
|
|
36885
36907
|
}
|
|
36886
|
-
await
|
|
36908
|
+
await removeWorktreeSafely({
|
|
36909
|
+
mainPath: repo.mainPath,
|
|
36910
|
+
wtPath,
|
|
36911
|
+
force: args.force === true,
|
|
36912
|
+
opts: { verbose: _opts.verbose === true, dryRun: false }
|
|
36913
|
+
});
|
|
36887
36914
|
cleanupEmptyParents(repo.wtRoot, repo.mainPath, wtPath);
|
|
36888
36915
|
await removeStackEntry(repo.mainPath, args.branch, { verbose: _opts.verbose === true, dryRun: false });
|
|
36889
36916
|
return {
|
|
@@ -36896,7 +36923,7 @@ async function handleToolCall(name, args, config2, _opts) {
|
|
|
36896
36923
|
}
|
|
36897
36924
|
const repo = resolveRepos(config2, [args.repo])[0];
|
|
36898
36925
|
const wtPath = getWorktreePath(repo, args.branch);
|
|
36899
|
-
if (!
|
|
36926
|
+
if (!fs37.existsSync(wtPath)) {
|
|
36900
36927
|
throw { isToolError: true, message: `Worktree not found for branch ${args.branch}` };
|
|
36901
36928
|
}
|
|
36902
36929
|
const mainBranch = await resolveMainBranch(repo, config2);
|
|
@@ -37118,7 +37145,7 @@ init_config();
|
|
|
37118
37145
|
init_log();
|
|
37119
37146
|
init_git();
|
|
37120
37147
|
init_resolver();
|
|
37121
|
-
import
|
|
37148
|
+
import fs38 from "fs";
|
|
37122
37149
|
import path40 from "path";
|
|
37123
37150
|
init_workspace();
|
|
37124
37151
|
var DEPS_STRATEGIES2 = ["auto", "link", "symlink", "install", "off"];
|
|
@@ -37141,7 +37168,7 @@ async function resolveWorktreePathForMember(config2, repoName, branch) {
|
|
|
37141
37168
|
if (match)
|
|
37142
37169
|
return match.path;
|
|
37143
37170
|
const candidate = getWorktreePath(repo, branch);
|
|
37144
|
-
if (
|
|
37171
|
+
if (fs38.existsSync(candidate))
|
|
37145
37172
|
return candidate;
|
|
37146
37173
|
return null;
|
|
37147
37174
|
}
|
|
@@ -37199,7 +37226,7 @@ function registerCreateSub(workspace) {
|
|
|
37199
37226
|
process.exit(1);
|
|
37200
37227
|
}
|
|
37201
37228
|
const wsPath = workspacePathFor2(config2, name);
|
|
37202
|
-
if (
|
|
37229
|
+
if (fs38.existsSync(wsPath)) {
|
|
37203
37230
|
stepError("Workspace already exists", wsPath);
|
|
37204
37231
|
process.exit(1);
|
|
37205
37232
|
}
|
|
@@ -37300,7 +37327,7 @@ function registerAddSub(workspace) {
|
|
|
37300
37327
|
const globalOpts = workspace.parent.opts();
|
|
37301
37328
|
const config2 = loadConfig();
|
|
37302
37329
|
const wsPath = workspacePathFor2(config2, name);
|
|
37303
|
-
if (!
|
|
37330
|
+
if (!fs38.existsSync(wsPath)) {
|
|
37304
37331
|
stepError("Workspace not found", wsPath);
|
|
37305
37332
|
process.exit(1);
|
|
37306
37333
|
}
|
|
@@ -37336,7 +37363,7 @@ function registerRmSub(workspace) {
|
|
|
37336
37363
|
const globalOpts = workspace.parent.opts();
|
|
37337
37364
|
const config2 = loadConfig();
|
|
37338
37365
|
const wsPath = workspacePathFor2(config2, name);
|
|
37339
|
-
if (!
|
|
37366
|
+
if (!fs38.existsSync(wsPath)) {
|
|
37340
37367
|
stepError("Workspace not found", wsPath);
|
|
37341
37368
|
process.exit(1);
|
|
37342
37369
|
}
|
|
@@ -37358,7 +37385,7 @@ function registerRemoveSub(workspace) {
|
|
|
37358
37385
|
const globalOpts = workspace.parent.opts();
|
|
37359
37386
|
const config2 = loadConfig();
|
|
37360
37387
|
const wsPath = workspacePathFor2(config2, name);
|
|
37361
|
-
if (!
|
|
37388
|
+
if (!fs38.existsSync(wsPath)) {
|
|
37362
37389
|
stepError("Workspace not found", wsPath);
|
|
37363
37390
|
process.exit(1);
|
|
37364
37391
|
}
|
|
@@ -37372,7 +37399,7 @@ function registerRemoveSub(workspace) {
|
|
|
37372
37399
|
return;
|
|
37373
37400
|
}
|
|
37374
37401
|
try {
|
|
37375
|
-
|
|
37402
|
+
fs38.rmSync(wsPath, { recursive: true, force: true });
|
|
37376
37403
|
stepSuccess("Workspace removed", wsPath);
|
|
37377
37404
|
summary(`Done — workspace ${name} deleted (member worktrees preserved)`);
|
|
37378
37405
|
} catch (err) {
|
|
@@ -37385,7 +37412,7 @@ function registerVerifySub(workspace) {
|
|
|
37385
37412
|
workspace.command("verify <name>").description("Verify that every workspace member link resolves").action(async (name) => {
|
|
37386
37413
|
const config2 = loadConfig();
|
|
37387
37414
|
const wsPath = workspacePathFor2(config2, name);
|
|
37388
|
-
if (!
|
|
37415
|
+
if (!fs38.existsSync(wsPath)) {
|
|
37389
37416
|
stepError("Workspace not found", wsPath);
|
|
37390
37417
|
process.exit(1);
|
|
37391
37418
|
}
|
|
@@ -37420,7 +37447,7 @@ init_config();
|
|
|
37420
37447
|
init_resolver();
|
|
37421
37448
|
init_log();
|
|
37422
37449
|
init_history();
|
|
37423
|
-
import
|
|
37450
|
+
import fs39 from "fs";
|
|
37424
37451
|
var program2 = new Command;
|
|
37425
37452
|
program2.name("wtx").description("Multi-repo git worktree manager").version(VERSION).option("-q, --quiet", "Suppress progress indicators", false).option("--verbose", "Show git commands as they run", false).option("--dry-run", "Show what would happen", false);
|
|
37426
37453
|
var MUTATING_COMMANDS = new Set([
|
|
@@ -37530,7 +37557,7 @@ program2.command("_resolve-path <repo> <branch>", { hidden: true }).description(
|
|
|
37530
37557
|
}
|
|
37531
37558
|
const repo = repos[0];
|
|
37532
37559
|
const wtPath = getWorktreePath(repo, branch);
|
|
37533
|
-
if (!
|
|
37560
|
+
if (!fs39.existsSync(wtPath)) {
|
|
37534
37561
|
process.stderr.write(`✗ No worktree at ${wtPath}
|
|
37535
37562
|
`);
|
|
37536
37563
|
process.exit(1);
|