@ogpoyraz/wtx 0.9.1 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +513 -258
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -25503,20 +25503,22 @@ async function fetchWorktreeData(opts, scope) {
|
|
|
25503
25503
|
}
|
|
25504
25504
|
let repos;
|
|
25505
25505
|
try {
|
|
25506
|
-
|
|
25506
|
+
if (scope && scope.length > 0) {
|
|
25507
|
+
repos = resolveRepos(config2, scope);
|
|
25508
|
+
} else {
|
|
25509
|
+
repos = resolveRepos(config2, Object.keys(config2.repos));
|
|
25510
|
+
}
|
|
25507
25511
|
} catch (err) {
|
|
25508
25512
|
throw new Error(`Failed to resolve repos: ${errorMessage3(err)}`);
|
|
25509
25513
|
}
|
|
25510
|
-
if (scope) {
|
|
25511
|
-
const scopeSet = new Set(scope);
|
|
25512
|
-
repos = repos.filter((r) => scopeSet.has(r.name));
|
|
25513
|
-
}
|
|
25514
25514
|
const semaphore = new Semaphore(4);
|
|
25515
25515
|
const allRows = [];
|
|
25516
25516
|
const processRepo = async (repo) => {
|
|
25517
25517
|
await semaphore.acquire();
|
|
25518
|
+
let mainBranch = config2.default_main_branch;
|
|
25519
|
+
let hasMain = false;
|
|
25518
25520
|
try {
|
|
25519
|
-
|
|
25521
|
+
mainBranch = await resolveMainBranch(repo, config2);
|
|
25520
25522
|
const wts = await getWorktreeList(repo.mainPath);
|
|
25521
25523
|
let stackMetadata = { version: 1, branches: {} };
|
|
25522
25524
|
try {
|
|
@@ -25531,7 +25533,9 @@ async function fetchWorktreeData(opts, scope) {
|
|
|
25531
25533
|
if (wt.isBare)
|
|
25532
25534
|
continue;
|
|
25533
25535
|
let branch = wt.branch;
|
|
25534
|
-
const isMainCheckout = wt.path === repo.mainPath;
|
|
25536
|
+
const isMainCheckout = safeResolve(wt.path) === safeResolve(repo.mainPath);
|
|
25537
|
+
if (isMainCheckout)
|
|
25538
|
+
hasMain = true;
|
|
25535
25539
|
if (isMainCheckout && !branch) {
|
|
25536
25540
|
branch = mainBranch;
|
|
25537
25541
|
}
|
|
@@ -25562,6 +25566,7 @@ async function fetchWorktreeData(opts, scope) {
|
|
|
25562
25566
|
};
|
|
25563
25567
|
if (isMainCheckout) {
|
|
25564
25568
|
allRows.push(row);
|
|
25569
|
+
prRows.push(row);
|
|
25565
25570
|
continue;
|
|
25566
25571
|
}
|
|
25567
25572
|
await Promise.allSettled([
|
|
@@ -25622,8 +25627,56 @@ async function fetchWorktreeData(opts, scope) {
|
|
|
25622
25627
|
if (forge && branches.length > 0) {
|
|
25623
25628
|
prFetchJobs.push({ repo, forge, mainBranch, rows: prRows, branches, stackMetadata });
|
|
25624
25629
|
}
|
|
25630
|
+
if (!hasMain) {
|
|
25631
|
+
allRows.push({
|
|
25632
|
+
repoName: repo.name,
|
|
25633
|
+
branch: mainBranch,
|
|
25634
|
+
path: repo.mainPath,
|
|
25635
|
+
commitShort: "",
|
|
25636
|
+
isMainCheckout: true,
|
|
25637
|
+
isLocked: false,
|
|
25638
|
+
isPrunable: false,
|
|
25639
|
+
isBare: false,
|
|
25640
|
+
dirtyFiles: [],
|
|
25641
|
+
ahead: null,
|
|
25642
|
+
behind: null,
|
|
25643
|
+
prNumber: null,
|
|
25644
|
+
prState: null,
|
|
25645
|
+
prChecks: null,
|
|
25646
|
+
prUrl: null,
|
|
25647
|
+
owner: null,
|
|
25648
|
+
rebaseStatus: null,
|
|
25649
|
+
depsStrategy: "none",
|
|
25650
|
+
base: undefined,
|
|
25651
|
+
baseChanged: false
|
|
25652
|
+
});
|
|
25653
|
+
}
|
|
25625
25654
|
} catch (err) {
|
|
25626
25655
|
warnings.push({ repoName: repo.name, message: `Failed to process repo ${repo.name}: ${errorMessage3(err)}` });
|
|
25656
|
+
if (!hasMain) {
|
|
25657
|
+
allRows.push({
|
|
25658
|
+
repoName: repo.name,
|
|
25659
|
+
branch: mainBranch,
|
|
25660
|
+
path: repo.mainPath,
|
|
25661
|
+
commitShort: "",
|
|
25662
|
+
isMainCheckout: true,
|
|
25663
|
+
isLocked: false,
|
|
25664
|
+
isPrunable: false,
|
|
25665
|
+
isBare: false,
|
|
25666
|
+
dirtyFiles: [],
|
|
25667
|
+
ahead: null,
|
|
25668
|
+
behind: null,
|
|
25669
|
+
prNumber: null,
|
|
25670
|
+
prState: null,
|
|
25671
|
+
prChecks: null,
|
|
25672
|
+
prUrl: null,
|
|
25673
|
+
owner: null,
|
|
25674
|
+
rebaseStatus: null,
|
|
25675
|
+
depsStrategy: "none",
|
|
25676
|
+
base: undefined,
|
|
25677
|
+
baseChanged: false
|
|
25678
|
+
});
|
|
25679
|
+
}
|
|
25627
25680
|
} finally {
|
|
25628
25681
|
semaphore.release();
|
|
25629
25682
|
}
|
|
@@ -25650,6 +25703,7 @@ var init_data = __esm(() => {
|
|
|
25650
25703
|
init_owner();
|
|
25651
25704
|
init_types2();
|
|
25652
25705
|
init_stack();
|
|
25706
|
+
init_path_safety();
|
|
25653
25707
|
PR_CACHE_TTL_MS = 5 * 60 * 1000;
|
|
25654
25708
|
prCache = new Map;
|
|
25655
25709
|
});
|
|
@@ -25946,7 +26000,12 @@ var init_useWorktrees = __esm(() => {
|
|
|
25946
26000
|
import { RGBA } from "@opentui/core";
|
|
25947
26001
|
import { createContext, useContext } from "react";
|
|
25948
26002
|
function useTheme() {
|
|
25949
|
-
|
|
26003
|
+
try {
|
|
26004
|
+
const ctx = useContext(ThemeContext);
|
|
26005
|
+
return ctx ?? tokens;
|
|
26006
|
+
} catch {
|
|
26007
|
+
return tokens;
|
|
26008
|
+
}
|
|
25950
26009
|
}
|
|
25951
26010
|
function truncateBranch(name, max = 42) {
|
|
25952
26011
|
if (name.length <= max)
|
|
@@ -26101,18 +26160,18 @@ async function openInBrowser(url2) {
|
|
|
26101
26160
|
// src/tui/components/WorktreeTable.tsx
|
|
26102
26161
|
import { useEffect as useEffect2, useRef as useRef3 } from "react";
|
|
26103
26162
|
import { jsx, jsxs } from "@opentui/react/jsx-runtime";
|
|
26104
|
-
function statusBadge(row) {
|
|
26163
|
+
function statusBadge(row, theme) {
|
|
26105
26164
|
if (row.isMainCheckout)
|
|
26106
|
-
return { text: "[main]", fg:
|
|
26165
|
+
return { text: "[main]", fg: theme.accent };
|
|
26107
26166
|
if (row.isPrunable)
|
|
26108
|
-
return { text: "missing", fg:
|
|
26167
|
+
return { text: "missing", fg: theme.error };
|
|
26109
26168
|
if (row.isLocked)
|
|
26110
|
-
return { text: "locked", fg:
|
|
26169
|
+
return { text: "locked", fg: theme.error };
|
|
26111
26170
|
if (row.rebaseStatus)
|
|
26112
|
-
return { text: "rebasing", fg:
|
|
26171
|
+
return { text: "rebasing", fg: theme.warning };
|
|
26113
26172
|
if (row.dirtyFiles.length > 0)
|
|
26114
|
-
return { text: `dirty (${row.dirtyFiles.length})`, fg:
|
|
26115
|
-
return { text: "clean", fg:
|
|
26173
|
+
return { text: `dirty (${row.dirtyFiles.length})`, fg: theme.warning };
|
|
26174
|
+
return { text: "clean", fg: theme.dim };
|
|
26116
26175
|
}
|
|
26117
26176
|
function WorktreeItem({
|
|
26118
26177
|
row,
|
|
@@ -26125,6 +26184,7 @@ function WorktreeItem({
|
|
|
26125
26184
|
onRowClick,
|
|
26126
26185
|
onToggleSelect
|
|
26127
26186
|
}) {
|
|
26187
|
+
const theme = useTheme();
|
|
26128
26188
|
const prTap = useTapHandler(() => {
|
|
26129
26189
|
if (row.prUrl)
|
|
26130
26190
|
openInBrowser(row.prUrl);
|
|
@@ -26136,9 +26196,9 @@ function WorktreeItem({
|
|
|
26136
26196
|
e.stopPropagation();
|
|
26137
26197
|
onToggleSelect?.();
|
|
26138
26198
|
});
|
|
26139
|
-
const badge = indicator ? indicator.running ? { text: `${frame} ${indicator.verb}…`, fg:
|
|
26199
|
+
const badge = indicator ? indicator.running ? { text: `${frame} ${indicator.verb}…`, fg: theme.accent } : { text: `◌ ${indicator.verb}`, fg: theme.dim } : row.isPendingCreate ? { text: `${frame} creating…`, fg: theme.accent } : statusBadge(row, theme);
|
|
26140
26200
|
const disabled = indicator !== undefined || row.isPendingCreate === true;
|
|
26141
|
-
const primary = isSelected ?
|
|
26201
|
+
const primary = isSelected ? theme.bright : disabled ? theme.dim : theme.fg;
|
|
26142
26202
|
const divergence = row.ahead !== null && row.behind !== null && (row.ahead > 0 || row.behind > 0) ? ` · ↑${row.ahead} ↓${row.behind}` : "";
|
|
26143
26203
|
const ownerSegment = row.owner ? ` · by ${row.owner}` : "";
|
|
26144
26204
|
const baseSegment = row.base ? ` · base ${row.base}` : "";
|
|
@@ -26156,7 +26216,7 @@ function WorktreeItem({
|
|
|
26156
26216
|
return /* @__PURE__ */ jsxs("box", {
|
|
26157
26217
|
id,
|
|
26158
26218
|
flexDirection: "column",
|
|
26159
|
-
backgroundColor: isSelected ?
|
|
26219
|
+
backgroundColor: isSelected ? theme.selectionBg : undefined,
|
|
26160
26220
|
style: { paddingRight: 1 },
|
|
26161
26221
|
...isClickable && onRowClick ? rowTap : {},
|
|
26162
26222
|
children: [
|
|
@@ -26173,18 +26233,18 @@ function WorktreeItem({
|
|
|
26173
26233
|
width: 2,
|
|
26174
26234
|
...onToggleSelect ? gutterTap : {},
|
|
26175
26235
|
children: /* @__PURE__ */ jsx("text", {
|
|
26176
|
-
fg:
|
|
26236
|
+
fg: theme.accent,
|
|
26177
26237
|
children: isMultiSelected ? "✓ " : " "
|
|
26178
26238
|
})
|
|
26179
26239
|
}),
|
|
26180
26240
|
/* @__PURE__ */ jsxs("text", {
|
|
26181
26241
|
children: [
|
|
26182
26242
|
/* @__PURE__ */ jsx("span", {
|
|
26183
|
-
fg:
|
|
26243
|
+
fg: theme.dim,
|
|
26184
26244
|
children: hierarchyPrefix
|
|
26185
26245
|
}),
|
|
26186
26246
|
isWorkspaceMember && /* @__PURE__ */ jsx("span", {
|
|
26187
|
-
fg:
|
|
26247
|
+
fg: theme.accent,
|
|
26188
26248
|
children: "⬡ "
|
|
26189
26249
|
}),
|
|
26190
26250
|
/* @__PURE__ */ jsx("span", {
|
|
@@ -26205,11 +26265,11 @@ function WorktreeItem({
|
|
|
26205
26265
|
/* @__PURE__ */ jsxs("text", {
|
|
26206
26266
|
children: [
|
|
26207
26267
|
/* @__PURE__ */ jsx("span", {
|
|
26208
|
-
fg:
|
|
26268
|
+
fg: theme.dim,
|
|
26209
26269
|
children: secondary
|
|
26210
26270
|
}),
|
|
26211
26271
|
row.prNumber !== null && secondary ? /* @__PURE__ */ jsx("span", {
|
|
26212
|
-
fg:
|
|
26272
|
+
fg: theme.dim,
|
|
26213
26273
|
children: " · "
|
|
26214
26274
|
}) : null
|
|
26215
26275
|
]
|
|
@@ -26219,26 +26279,26 @@ function WorktreeItem({
|
|
|
26219
26279
|
children: /* @__PURE__ */ jsxs("text", {
|
|
26220
26280
|
children: [
|
|
26221
26281
|
/* @__PURE__ */ jsx("span", {
|
|
26222
|
-
fg:
|
|
26282
|
+
fg: theme.accent,
|
|
26223
26283
|
children: `#${row.prNumber}`
|
|
26224
26284
|
}),
|
|
26225
26285
|
row.prState && /* @__PURE__ */ jsx("span", {
|
|
26226
|
-
fg:
|
|
26286
|
+
fg: theme.dim,
|
|
26227
26287
|
children: ` ${row.prState}`
|
|
26228
26288
|
}),
|
|
26229
26289
|
row.prChecks && /* @__PURE__ */ jsx("span", {
|
|
26230
|
-
fg:
|
|
26290
|
+
fg: theme.dim,
|
|
26231
26291
|
children: ` (${row.prChecks})`
|
|
26232
26292
|
}),
|
|
26233
26293
|
row.prUrl && /* @__PURE__ */ jsx("span", {
|
|
26234
|
-
fg:
|
|
26294
|
+
fg: theme.dim,
|
|
26235
26295
|
children: " ↗"
|
|
26236
26296
|
})
|
|
26237
26297
|
]
|
|
26238
26298
|
})
|
|
26239
26299
|
}),
|
|
26240
26300
|
row.prNumber === null && row.prState === "FETCHING" && /* @__PURE__ */ jsxs("text", {
|
|
26241
|
-
fg:
|
|
26301
|
+
fg: theme.dim,
|
|
26242
26302
|
children: [
|
|
26243
26303
|
secondary ? " · " : "",
|
|
26244
26304
|
"PR …"
|
|
@@ -26247,11 +26307,11 @@ function WorktreeItem({
|
|
|
26247
26307
|
/* @__PURE__ */ jsxs("text", {
|
|
26248
26308
|
children: [
|
|
26249
26309
|
baseChangedSegment && /* @__PURE__ */ jsx("span", {
|
|
26250
|
-
fg:
|
|
26310
|
+
fg: theme.warning,
|
|
26251
26311
|
children: baseChangedSegment
|
|
26252
26312
|
}),
|
|
26253
26313
|
rebaseSegment && /* @__PURE__ */ jsx("span", {
|
|
26254
|
-
fg:
|
|
26314
|
+
fg: theme.error,
|
|
26255
26315
|
children: rebaseSegment
|
|
26256
26316
|
})
|
|
26257
26317
|
]
|
|
@@ -26262,6 +26322,7 @@ function WorktreeItem({
|
|
|
26262
26322
|
});
|
|
26263
26323
|
}
|
|
26264
26324
|
function WorktreeTable({ blocks, selectedIndex, selection = new Set, frame, repoVerbs, rowVerbs, favorites = [], workspaceMemberSet = null, activeWorkspaceName = null, onRowClick, onToggleSelect }) {
|
|
26325
|
+
const theme = useTheme();
|
|
26265
26326
|
const favoriteSet = new Set(favorites);
|
|
26266
26327
|
const scrollRef = useRef3(null);
|
|
26267
26328
|
useEffect2(() => {
|
|
@@ -26285,8 +26346,8 @@ function WorktreeTable({ blocks, selectedIndex, selection = new Set, frame, repo
|
|
|
26285
26346
|
width: "100%",
|
|
26286
26347
|
height: "100%",
|
|
26287
26348
|
border: true,
|
|
26288
|
-
borderColor:
|
|
26289
|
-
focusedBorderColor:
|
|
26349
|
+
borderColor: theme.border,
|
|
26350
|
+
focusedBorderColor: theme.border,
|
|
26290
26351
|
focusable: false,
|
|
26291
26352
|
title: activeWorkspaceName ? `Repositories · workspace: ${activeWorkspaceName}` : "Repositories",
|
|
26292
26353
|
paddingX: 1,
|
|
@@ -26295,7 +26356,7 @@ function WorktreeTable({ blocks, selectedIndex, selection = new Set, frame, repo
|
|
|
26295
26356
|
e.stopPropagation();
|
|
26296
26357
|
},
|
|
26297
26358
|
children: blocks.length === 0 ? /* @__PURE__ */ jsx("text", {
|
|
26298
|
-
fg:
|
|
26359
|
+
fg: theme.dim,
|
|
26299
26360
|
children: "No repositories configured."
|
|
26300
26361
|
}) : blocks.map((block) => {
|
|
26301
26362
|
const repoIndicator = repoVerbs.get(block.repoName);
|
|
@@ -26308,22 +26369,22 @@ function WorktreeTable({ blocks, selectedIndex, selection = new Set, frame, repo
|
|
|
26308
26369
|
children: /* @__PURE__ */ jsxs("text", {
|
|
26309
26370
|
children: [
|
|
26310
26371
|
favoriteSet.has(block.repoName) && /* @__PURE__ */ jsx("span", {
|
|
26311
|
-
fg:
|
|
26372
|
+
fg: theme.accent,
|
|
26312
26373
|
children: "★ "
|
|
26313
26374
|
}),
|
|
26314
26375
|
/* @__PURE__ */ jsx("span", {
|
|
26315
|
-
fg:
|
|
26376
|
+
fg: theme.bright,
|
|
26316
26377
|
children: block.repoName
|
|
26317
26378
|
}),
|
|
26318
26379
|
block.rows.length > 0 && /* @__PURE__ */ jsx("span", {
|
|
26319
|
-
fg:
|
|
26380
|
+
fg: theme.dim,
|
|
26320
26381
|
children: ` · ${block.rows.filter((r) => !r.isPendingCreate).length}`
|
|
26321
26382
|
}),
|
|
26322
26383
|
repoIndicator ? /* @__PURE__ */ jsx("span", {
|
|
26323
|
-
fg: repoIndicator.running ?
|
|
26384
|
+
fg: repoIndicator.running ? theme.accent : theme.dim,
|
|
26324
26385
|
children: repoIndicator.running ? ` ${frame} ${repoIndicator.verb}…` : ` ◌ ${repoIndicator.verb}`
|
|
26325
26386
|
}) : block.rows.length === 0 ? /* @__PURE__ */ jsx("span", {
|
|
26326
|
-
fg:
|
|
26387
|
+
fg: theme.accent,
|
|
26327
26388
|
children: ` ${frame} refreshing…`
|
|
26328
26389
|
}) : null
|
|
26329
26390
|
]
|
|
@@ -26357,6 +26418,7 @@ function WorktreeTable({ blocks, selectedIndex, selection = new Set, frame, repo
|
|
|
26357
26418
|
}
|
|
26358
26419
|
var SECONDARY_INDENT = " ";
|
|
26359
26420
|
var init_WorktreeTable = __esm(() => {
|
|
26421
|
+
init_theme();
|
|
26360
26422
|
init_theme();
|
|
26361
26423
|
init_use_tap();
|
|
26362
26424
|
init_utils();
|
|
@@ -26372,6 +26434,7 @@ function TabItem({
|
|
|
26372
26434
|
onSelect,
|
|
26373
26435
|
onClose
|
|
26374
26436
|
}) {
|
|
26437
|
+
const theme = useTheme();
|
|
26375
26438
|
const tap = useTapHandler(() => onSelect(id));
|
|
26376
26439
|
const closeTap = useTapHandler((e) => {
|
|
26377
26440
|
e.stopPropagation();
|
|
@@ -26383,15 +26446,15 @@ function TabItem({
|
|
|
26383
26446
|
...tap,
|
|
26384
26447
|
children: [
|
|
26385
26448
|
/* @__PURE__ */ jsx2("text", {
|
|
26386
|
-
fg: active ?
|
|
26449
|
+
fg: active ? theme.accent : theme.dim,
|
|
26387
26450
|
attributes: active ? 1 : 0,
|
|
26388
26451
|
children: label
|
|
26389
26452
|
}),
|
|
26390
26453
|
closable ? /* @__PURE__ */ jsx2("box", {
|
|
26391
26454
|
...closeTap,
|
|
26392
|
-
style: { marginLeft: 1 },
|
|
26455
|
+
style: { marginLeft: 1, paddingLeft: 1, paddingRight: 1 },
|
|
26393
26456
|
children: /* @__PURE__ */ jsx2("text", {
|
|
26394
|
-
fg:
|
|
26457
|
+
fg: theme.accent,
|
|
26395
26458
|
children: "✕"
|
|
26396
26459
|
})
|
|
26397
26460
|
}) : null,
|
|
@@ -26426,6 +26489,7 @@ var init_TabBar = __esm(() => {
|
|
|
26426
26489
|
import { useState as useState2, useEffect as useEffect3, useRef as useRef4, useCallback as useCallback3 } from "react";
|
|
26427
26490
|
import { jsx as jsx3, jsxs as jsxs3 } from "@opentui/react/jsx-runtime";
|
|
26428
26491
|
function TerminalView({ session, focused, onFocus, onSend, onResize, registerListener, unregisterListener }) {
|
|
26492
|
+
const theme = useTheme();
|
|
26429
26493
|
const [draft, setDraft] = useState2("");
|
|
26430
26494
|
const focusTap = useTapHandler(() => onFocus());
|
|
26431
26495
|
const termRef = useRef4(null);
|
|
@@ -26568,7 +26632,7 @@ function TerminalView({ session, focused, onFocus, onSend, onResize, registerLis
|
|
|
26568
26632
|
})
|
|
26569
26633
|
}),
|
|
26570
26634
|
session.exited !== null && /* @__PURE__ */ jsxs3("text", {
|
|
26571
|
-
fg:
|
|
26635
|
+
fg: theme.warning,
|
|
26572
26636
|
children: [
|
|
26573
26637
|
"— exited with code ",
|
|
26574
26638
|
session.exited,
|
|
@@ -26576,7 +26640,7 @@ function TerminalView({ session, focused, onFocus, onSend, onResize, registerLis
|
|
|
26576
26640
|
]
|
|
26577
26641
|
}),
|
|
26578
26642
|
!focused && /* @__PURE__ */ jsxs3("text", {
|
|
26579
|
-
fg:
|
|
26643
|
+
fg: theme.dim,
|
|
26580
26644
|
children: [
|
|
26581
26645
|
"Click to focus · Ctrl+G or click table to unfocus · ",
|
|
26582
26646
|
session.label,
|
|
@@ -26584,7 +26648,7 @@ function TerminalView({ session, focused, onFocus, onSend, onResize, registerLis
|
|
|
26584
26648
|
]
|
|
26585
26649
|
}),
|
|
26586
26650
|
focused && /* @__PURE__ */ jsx3("text", {
|
|
26587
|
-
fg:
|
|
26651
|
+
fg: theme.accent,
|
|
26588
26652
|
children: "Focused PTY — all keys go to shell · Ctrl+G to unfocus · scroll wheel to view history"
|
|
26589
26653
|
})
|
|
26590
26654
|
]
|
|
@@ -26602,12 +26666,12 @@ function TerminalView({ session, focused, onFocus, onSend, onResize, registerLis
|
|
|
26602
26666
|
children: [
|
|
26603
26667
|
spawnError && /* @__PURE__ */ jsx3("box", {
|
|
26604
26668
|
border: true,
|
|
26605
|
-
borderColor:
|
|
26669
|
+
borderColor: theme.error,
|
|
26606
26670
|
paddingX: 1,
|
|
26607
26671
|
paddingY: 0,
|
|
26608
26672
|
marginBottom: 1,
|
|
26609
26673
|
children: /* @__PURE__ */ jsx3("text", {
|
|
26610
|
-
fg:
|
|
26674
|
+
fg: theme.error,
|
|
26611
26675
|
children: spawnError
|
|
26612
26676
|
})
|
|
26613
26677
|
}),
|
|
@@ -26622,14 +26686,14 @@ function TerminalView({ session, focused, onFocus, onSend, onResize, registerLis
|
|
|
26622
26686
|
onMouseScroll: handlePipeScroll,
|
|
26623
26687
|
children: [
|
|
26624
26688
|
lines.length === 0 ? /* @__PURE__ */ jsx3("text", {
|
|
26625
|
-
fg:
|
|
26689
|
+
fg: theme.dim,
|
|
26626
26690
|
children: "No output yet — type a command below."
|
|
26627
26691
|
}) : lines.slice(-500).map((line, idx) => /* @__PURE__ */ jsx3("text", {
|
|
26628
|
-
fg: spawnError ?
|
|
26692
|
+
fg: spawnError ? theme.error : session.exited !== null ? theme.dim : theme.fg,
|
|
26629
26693
|
children: line || " "
|
|
26630
26694
|
}, idx)),
|
|
26631
26695
|
session.exited !== null && /* @__PURE__ */ jsxs3("text", {
|
|
26632
|
-
fg:
|
|
26696
|
+
fg: theme.warning,
|
|
26633
26697
|
children: [
|
|
26634
26698
|
"— exited with code ",
|
|
26635
26699
|
session.exited,
|
|
@@ -26644,7 +26708,7 @@ function TerminalView({ session, focused, onFocus, onSend, onResize, registerLis
|
|
|
26644
26708
|
width: "100%",
|
|
26645
26709
|
children: [
|
|
26646
26710
|
/* @__PURE__ */ jsx3("text", {
|
|
26647
|
-
fg:
|
|
26711
|
+
fg: theme.dim,
|
|
26648
26712
|
children: "$"
|
|
26649
26713
|
}),
|
|
26650
26714
|
/* @__PURE__ */ jsx3("box", {
|
|
@@ -26666,11 +26730,11 @@ function TerminalView({ session, focused, onFocus, onSend, onResize, registerLis
|
|
|
26666
26730
|
]
|
|
26667
26731
|
}),
|
|
26668
26732
|
!focused && /* @__PURE__ */ jsx3("text", {
|
|
26669
|
-
fg:
|
|
26733
|
+
fg: theme.dim,
|
|
26670
26734
|
children: "Click terminal or press 't' to focus · Ctrl+G or click table to unfocus"
|
|
26671
26735
|
}),
|
|
26672
26736
|
focused && /* @__PURE__ */ jsx3("text", {
|
|
26673
|
-
fg:
|
|
26737
|
+
fg: theme.accent,
|
|
26674
26738
|
children: "Focused — typing goes to shell · Ctrl+G to unfocus · max 5 per worktree persist across switches"
|
|
26675
26739
|
})
|
|
26676
26740
|
]
|
|
@@ -26694,12 +26758,16 @@ function TabPane({
|
|
|
26694
26758
|
onClose,
|
|
26695
26759
|
allSessionsFlat,
|
|
26696
26760
|
terminalFocused,
|
|
26761
|
+
changesFocused,
|
|
26762
|
+
onChangesFocus,
|
|
26697
26763
|
activeTabId,
|
|
26698
26764
|
recentSessionIds,
|
|
26699
26765
|
terminalSessions
|
|
26700
26766
|
}) {
|
|
26701
|
-
const
|
|
26767
|
+
const theme = useTheme();
|
|
26768
|
+
const borderColor = focused ? theme.accent : theme.border;
|
|
26702
26769
|
const mountedSessions = allSessionsFlat?.filter((s) => activeTabId === s.id || recentSessionIds?.has(s.id));
|
|
26770
|
+
const nonSessionTabs = tabs.filter((t) => !t.closable);
|
|
26703
26771
|
return /* @__PURE__ */ jsxs4("box", {
|
|
26704
26772
|
flexDirection: "column",
|
|
26705
26773
|
flexGrow: 1,
|
|
@@ -26724,13 +26792,28 @@ function TabPane({
|
|
|
26724
26792
|
width: "100%",
|
|
26725
26793
|
flexDirection: "column",
|
|
26726
26794
|
children: [
|
|
26727
|
-
|
|
26728
|
-
|
|
26729
|
-
|
|
26730
|
-
|
|
26731
|
-
|
|
26732
|
-
|
|
26733
|
-
|
|
26795
|
+
nonSessionTabs.map((t) => {
|
|
26796
|
+
const isChanges = t.id === "changes";
|
|
26797
|
+
const tabFocused = isChanges ? !!changesFocused : !terminalFocused && !changesFocused && t.id === activeId;
|
|
26798
|
+
const content = t.render({ worktree: selectedRow, isActive: t.id === activeId, focused: tabFocused });
|
|
26799
|
+
if (isChanges) {
|
|
26800
|
+
return /* @__PURE__ */ jsx4("box", {
|
|
26801
|
+
flexGrow: 1,
|
|
26802
|
+
width: "100%",
|
|
26803
|
+
flexDirection: "column",
|
|
26804
|
+
visible: t.id === activeId,
|
|
26805
|
+
onMouseDown: () => onChangesFocus?.(),
|
|
26806
|
+
children: content
|
|
26807
|
+
}, t.id);
|
|
26808
|
+
}
|
|
26809
|
+
return /* @__PURE__ */ jsx4("box", {
|
|
26810
|
+
flexGrow: 1,
|
|
26811
|
+
width: "100%",
|
|
26812
|
+
flexDirection: "column",
|
|
26813
|
+
visible: t.id === activeId,
|
|
26814
|
+
children: content
|
|
26815
|
+
}, t.id);
|
|
26816
|
+
}),
|
|
26734
26817
|
mountedSessions?.map((s) => /* @__PURE__ */ jsx4("box", {
|
|
26735
26818
|
flexGrow: 1,
|
|
26736
26819
|
width: "100%",
|
|
@@ -26747,8 +26830,8 @@ function TabPane({
|
|
|
26747
26830
|
unregisterListener: terminalSessions?.unregisterListener
|
|
26748
26831
|
})
|
|
26749
26832
|
}, s.id)),
|
|
26750
|
-
|
|
26751
|
-
fg:
|
|
26833
|
+
nonSessionTabs.length === 0 && (!mountedSessions || mountedSessions.length === 0) && /* @__PURE__ */ jsx4("text", {
|
|
26834
|
+
fg: theme.dim,
|
|
26752
26835
|
children: "No tab"
|
|
26753
26836
|
})
|
|
26754
26837
|
]
|
|
@@ -26765,6 +26848,7 @@ var init_TabPane = __esm(() => {
|
|
|
26765
26848
|
// src/tui/components/DetailsTab.tsx
|
|
26766
26849
|
import { jsx as jsx5, jsxs as jsxs5, Fragment } from "@opentui/react/jsx-runtime";
|
|
26767
26850
|
function DetailsContent({ selectedRow }) {
|
|
26851
|
+
const theme = useTheme();
|
|
26768
26852
|
const prTap = useTapHandler(() => {
|
|
26769
26853
|
if (selectedRow?.prUrl)
|
|
26770
26854
|
openInBrowser(selectedRow.prUrl);
|
|
@@ -26777,7 +26861,7 @@ function DetailsContent({ selectedRow }) {
|
|
|
26777
26861
|
justifyContent: "center",
|
|
26778
26862
|
alignItems: "center",
|
|
26779
26863
|
children: /* @__PURE__ */ jsx5("text", {
|
|
26780
|
-
fg:
|
|
26864
|
+
fg: theme.dim,
|
|
26781
26865
|
children: "No worktree selected"
|
|
26782
26866
|
})
|
|
26783
26867
|
});
|
|
@@ -26814,11 +26898,11 @@ function DetailsContent({ selectedRow }) {
|
|
|
26814
26898
|
/* @__PURE__ */ jsxs5("text", {
|
|
26815
26899
|
children: [
|
|
26816
26900
|
/* @__PURE__ */ jsx5("span", {
|
|
26817
|
-
fg:
|
|
26901
|
+
fg: theme.dim,
|
|
26818
26902
|
children: "Repo:"
|
|
26819
26903
|
}),
|
|
26820
26904
|
/* @__PURE__ */ jsxs5("span", {
|
|
26821
|
-
fg:
|
|
26905
|
+
fg: theme.fg,
|
|
26822
26906
|
children: [
|
|
26823
26907
|
" ",
|
|
26824
26908
|
repoName
|
|
@@ -26829,11 +26913,11 @@ function DetailsContent({ selectedRow }) {
|
|
|
26829
26913
|
/* @__PURE__ */ jsxs5("text", {
|
|
26830
26914
|
children: [
|
|
26831
26915
|
/* @__PURE__ */ jsx5("span", {
|
|
26832
|
-
fg:
|
|
26916
|
+
fg: theme.dim,
|
|
26833
26917
|
children: "Branch:"
|
|
26834
26918
|
}),
|
|
26835
26919
|
/* @__PURE__ */ jsxs5("span", {
|
|
26836
|
-
fg:
|
|
26920
|
+
fg: theme.fg,
|
|
26837
26921
|
children: [
|
|
26838
26922
|
" ",
|
|
26839
26923
|
branch,
|
|
@@ -26846,11 +26930,11 @@ function DetailsContent({ selectedRow }) {
|
|
|
26846
26930
|
/* @__PURE__ */ jsxs5("text", {
|
|
26847
26931
|
children: [
|
|
26848
26932
|
/* @__PURE__ */ jsx5("span", {
|
|
26849
|
-
fg:
|
|
26933
|
+
fg: theme.dim,
|
|
26850
26934
|
children: "Path:"
|
|
26851
26935
|
}),
|
|
26852
26936
|
/* @__PURE__ */ jsxs5("span", {
|
|
26853
|
-
fg:
|
|
26937
|
+
fg: theme.fg,
|
|
26854
26938
|
children: [
|
|
26855
26939
|
" ",
|
|
26856
26940
|
path37
|
|
@@ -26861,11 +26945,11 @@ function DetailsContent({ selectedRow }) {
|
|
|
26861
26945
|
/* @__PURE__ */ jsxs5("text", {
|
|
26862
26946
|
children: [
|
|
26863
26947
|
/* @__PURE__ */ jsx5("span", {
|
|
26864
|
-
fg:
|
|
26948
|
+
fg: theme.dim,
|
|
26865
26949
|
children: "Commit:"
|
|
26866
26950
|
}),
|
|
26867
26951
|
/* @__PURE__ */ jsxs5("span", {
|
|
26868
|
-
fg:
|
|
26952
|
+
fg: theme.fg,
|
|
26869
26953
|
children: [
|
|
26870
26954
|
" ",
|
|
26871
26955
|
commitShort
|
|
@@ -26876,11 +26960,11 @@ function DetailsContent({ selectedRow }) {
|
|
|
26876
26960
|
owner && /* @__PURE__ */ jsxs5("text", {
|
|
26877
26961
|
children: [
|
|
26878
26962
|
/* @__PURE__ */ jsx5("span", {
|
|
26879
|
-
fg:
|
|
26963
|
+
fg: theme.dim,
|
|
26880
26964
|
children: "Owner:"
|
|
26881
26965
|
}),
|
|
26882
26966
|
/* @__PURE__ */ jsxs5("span", {
|
|
26883
|
-
fg:
|
|
26967
|
+
fg: theme.fg,
|
|
26884
26968
|
children: [
|
|
26885
26969
|
" ",
|
|
26886
26970
|
owner
|
|
@@ -26891,11 +26975,11 @@ function DetailsContent({ selectedRow }) {
|
|
|
26891
26975
|
/* @__PURE__ */ jsxs5("text", {
|
|
26892
26976
|
children: [
|
|
26893
26977
|
/* @__PURE__ */ jsx5("span", {
|
|
26894
|
-
fg:
|
|
26978
|
+
fg: theme.dim,
|
|
26895
26979
|
children: "Status:"
|
|
26896
26980
|
}),
|
|
26897
26981
|
/* @__PURE__ */ jsxs5("span", {
|
|
26898
|
-
fg:
|
|
26982
|
+
fg: theme.fg,
|
|
26899
26983
|
children: [
|
|
26900
26984
|
" ",
|
|
26901
26985
|
isLocked ? "LOCKED" : isPrunable ? "PRUNABLE" : "Active"
|
|
@@ -26906,11 +26990,11 @@ function DetailsContent({ selectedRow }) {
|
|
|
26906
26990
|
base2 && /* @__PURE__ */ jsxs5("text", {
|
|
26907
26991
|
children: [
|
|
26908
26992
|
/* @__PURE__ */ jsx5("span", {
|
|
26909
|
-
fg:
|
|
26993
|
+
fg: theme.dim,
|
|
26910
26994
|
children: "Base:"
|
|
26911
26995
|
}),
|
|
26912
26996
|
/* @__PURE__ */ jsxs5("span", {
|
|
26913
|
-
fg:
|
|
26997
|
+
fg: theme.accent,
|
|
26914
26998
|
children: [
|
|
26915
26999
|
" ",
|
|
26916
27000
|
base2
|
|
@@ -26921,11 +27005,11 @@ function DetailsContent({ selectedRow }) {
|
|
|
26921
27005
|
baseChanged && /* @__PURE__ */ jsxs5("text", {
|
|
26922
27006
|
children: [
|
|
26923
27007
|
/* @__PURE__ */ jsx5("span", {
|
|
26924
|
-
fg:
|
|
27008
|
+
fg: theme.dim,
|
|
26925
27009
|
children: "Base state:"
|
|
26926
27010
|
}),
|
|
26927
27011
|
/* @__PURE__ */ jsx5("span", {
|
|
26928
|
-
fg:
|
|
27012
|
+
fg: theme.warning,
|
|
26929
27013
|
children: " moved since recorded"
|
|
26930
27014
|
})
|
|
26931
27015
|
]
|
|
@@ -26934,11 +27018,11 @@ function DetailsContent({ selectedRow }) {
|
|
|
26934
27018
|
style: { marginTop: 1 },
|
|
26935
27019
|
children: [
|
|
26936
27020
|
/* @__PURE__ */ jsx5("span", {
|
|
26937
|
-
fg:
|
|
27021
|
+
fg: theme.dim,
|
|
26938
27022
|
children: base2 ? "vs base:" : "vs main:"
|
|
26939
27023
|
}),
|
|
26940
27024
|
/* @__PURE__ */ jsxs5("span", {
|
|
26941
|
-
fg:
|
|
27025
|
+
fg: theme.fg,
|
|
26942
27026
|
children: [
|
|
26943
27027
|
" ",
|
|
26944
27028
|
aheadBehindStr
|
|
@@ -26949,11 +27033,11 @@ function DetailsContent({ selectedRow }) {
|
|
|
26949
27033
|
/* @__PURE__ */ jsxs5("text", {
|
|
26950
27034
|
children: [
|
|
26951
27035
|
/* @__PURE__ */ jsx5("span", {
|
|
26952
|
-
fg:
|
|
27036
|
+
fg: theme.dim,
|
|
26953
27037
|
children: "Deps:"
|
|
26954
27038
|
}),
|
|
26955
27039
|
/* @__PURE__ */ jsxs5("span", {
|
|
26956
|
-
fg:
|
|
27040
|
+
fg: theme.fg,
|
|
26957
27041
|
children: [
|
|
26958
27042
|
" ",
|
|
26959
27043
|
depsStrategy
|
|
@@ -26964,11 +27048,11 @@ function DetailsContent({ selectedRow }) {
|
|
|
26964
27048
|
rebaseStatus && /* @__PURE__ */ jsxs5("text", {
|
|
26965
27049
|
children: [
|
|
26966
27050
|
/* @__PURE__ */ jsx5("span", {
|
|
26967
|
-
fg:
|
|
27051
|
+
fg: theme.dim,
|
|
26968
27052
|
children: "Rebase:"
|
|
26969
27053
|
}),
|
|
26970
27054
|
/* @__PURE__ */ jsxs5("span", {
|
|
26971
|
-
fg:
|
|
27055
|
+
fg: theme.error,
|
|
26972
27056
|
children: [
|
|
26973
27057
|
" ",
|
|
26974
27058
|
rebaseStatus
|
|
@@ -26982,7 +27066,7 @@ function DetailsContent({ selectedRow }) {
|
|
|
26982
27066
|
style: { marginTop: 1 },
|
|
26983
27067
|
children: [
|
|
26984
27068
|
/* @__PURE__ */ jsxs5("span", {
|
|
26985
|
-
fg:
|
|
27069
|
+
fg: theme.accent,
|
|
26986
27070
|
children: [
|
|
26987
27071
|
"PR #",
|
|
26988
27072
|
prNumber,
|
|
@@ -26990,7 +27074,7 @@ function DetailsContent({ selectedRow }) {
|
|
|
26990
27074
|
]
|
|
26991
27075
|
}),
|
|
26992
27076
|
/* @__PURE__ */ jsxs5("span", {
|
|
26993
|
-
fg:
|
|
27077
|
+
fg: theme.dim,
|
|
26994
27078
|
children: [
|
|
26995
27079
|
" ",
|
|
26996
27080
|
prState
|
|
@@ -27001,11 +27085,11 @@ function DetailsContent({ selectedRow }) {
|
|
|
27001
27085
|
prChecks && /* @__PURE__ */ jsxs5("text", {
|
|
27002
27086
|
children: [
|
|
27003
27087
|
/* @__PURE__ */ jsx5("span", {
|
|
27004
|
-
fg:
|
|
27088
|
+
fg: theme.dim,
|
|
27005
27089
|
children: "Checks:"
|
|
27006
27090
|
}),
|
|
27007
27091
|
/* @__PURE__ */ jsxs5("span", {
|
|
27008
|
-
fg:
|
|
27092
|
+
fg: theme.fg,
|
|
27009
27093
|
children: [
|
|
27010
27094
|
" ",
|
|
27011
27095
|
prChecks
|
|
@@ -27019,15 +27103,15 @@ function DetailsContent({ selectedRow }) {
|
|
|
27019
27103
|
selectable: false,
|
|
27020
27104
|
children: [
|
|
27021
27105
|
/* @__PURE__ */ jsx5("span", {
|
|
27022
|
-
fg:
|
|
27106
|
+
fg: theme.dim,
|
|
27023
27107
|
children: "URL:"
|
|
27024
27108
|
}),
|
|
27025
27109
|
/* @__PURE__ */ jsx5("span", {
|
|
27026
|
-
fg:
|
|
27110
|
+
fg: theme.accent,
|
|
27027
27111
|
children: ` ${prUrl}`
|
|
27028
27112
|
}),
|
|
27029
27113
|
/* @__PURE__ */ jsx5("span", {
|
|
27030
|
-
fg:
|
|
27114
|
+
fg: theme.dim,
|
|
27031
27115
|
children: " ↗ click"
|
|
27032
27116
|
})
|
|
27033
27117
|
]
|
|
@@ -27040,7 +27124,7 @@ function DetailsContent({ selectedRow }) {
|
|
|
27040
27124
|
style: { marginTop: 1 },
|
|
27041
27125
|
children: [
|
|
27042
27126
|
/* @__PURE__ */ jsxs5("text", {
|
|
27043
|
-
fg:
|
|
27127
|
+
fg: theme.warning,
|
|
27044
27128
|
children: [
|
|
27045
27129
|
"Dirty Files (",
|
|
27046
27130
|
dirtyFiles.length,
|
|
@@ -27048,14 +27132,14 @@ function DetailsContent({ selectedRow }) {
|
|
|
27048
27132
|
]
|
|
27049
27133
|
}),
|
|
27050
27134
|
dirtyFiles.slice(0, 20).map((file2, idx) => /* @__PURE__ */ jsxs5("text", {
|
|
27051
|
-
fg:
|
|
27135
|
+
fg: theme.warning,
|
|
27052
27136
|
children: [
|
|
27053
27137
|
" ",
|
|
27054
27138
|
file2
|
|
27055
27139
|
]
|
|
27056
27140
|
}, idx)),
|
|
27057
27141
|
dirtyFiles.length > 20 && /* @__PURE__ */ jsxs5("text", {
|
|
27058
|
-
fg:
|
|
27142
|
+
fg: theme.warning,
|
|
27059
27143
|
children: [
|
|
27060
27144
|
" ...and ",
|
|
27061
27145
|
dirtyFiles.length - 20,
|
|
@@ -27069,13 +27153,13 @@ function DetailsContent({ selectedRow }) {
|
|
|
27069
27153
|
style: { marginTop: 1 },
|
|
27070
27154
|
children: [
|
|
27071
27155
|
/* @__PURE__ */ jsx5("text", {
|
|
27072
|
-
fg:
|
|
27156
|
+
fg: theme.dim,
|
|
27073
27157
|
children: "Actions:"
|
|
27074
27158
|
}),
|
|
27075
27159
|
!isMainCheckout && /* @__PURE__ */ jsxs5(Fragment, {
|
|
27076
27160
|
children: [
|
|
27077
27161
|
/* @__PURE__ */ jsxs5("text", {
|
|
27078
|
-
fg:
|
|
27162
|
+
fg: theme.dim,
|
|
27079
27163
|
children: [
|
|
27080
27164
|
" i install deps (",
|
|
27081
27165
|
depsStrategy,
|
|
@@ -27083,21 +27167,21 @@ function DetailsContent({ selectedRow }) {
|
|
|
27083
27167
|
]
|
|
27084
27168
|
}),
|
|
27085
27169
|
/* @__PURE__ */ jsx5("text", {
|
|
27086
|
-
fg:
|
|
27170
|
+
fg: theme.dim,
|
|
27087
27171
|
children: " m rename worktree"
|
|
27088
27172
|
})
|
|
27089
27173
|
]
|
|
27090
27174
|
}),
|
|
27091
27175
|
/* @__PURE__ */ jsx5("text", {
|
|
27092
|
-
fg:
|
|
27176
|
+
fg: theme.dim,
|
|
27093
27177
|
children: " p pull branch"
|
|
27094
27178
|
}),
|
|
27095
27179
|
/* @__PURE__ */ jsx5("text", {
|
|
27096
|
-
fg:
|
|
27180
|
+
fg: theme.dim,
|
|
27097
27181
|
children: " b rebase · s sync · o open in IDE · d remove"
|
|
27098
27182
|
}),
|
|
27099
27183
|
/* @__PURE__ */ jsx5("text", {
|
|
27100
|
-
fg:
|
|
27184
|
+
fg: theme.dim,
|
|
27101
27185
|
children: " t new terminal session (max 5)"
|
|
27102
27186
|
})
|
|
27103
27187
|
]
|
|
@@ -27111,6 +27195,8 @@ var init_DetailsTab = __esm(() => {
|
|
|
27111
27195
|
});
|
|
27112
27196
|
|
|
27113
27197
|
// src/lib/changes.ts
|
|
27198
|
+
import fs33 from "node:fs";
|
|
27199
|
+
import path37 from "node:path";
|
|
27114
27200
|
function cacheKey(opts, filePath) {
|
|
27115
27201
|
return [opts.repoPath, opts.branch, opts.scope, filePath ?? ""].join("\x00");
|
|
27116
27202
|
}
|
|
@@ -27214,7 +27300,7 @@ async function getChangedFiles(opts) {
|
|
|
27214
27300
|
return [];
|
|
27215
27301
|
const key = cacheKey(opts);
|
|
27216
27302
|
const cached2 = listCache.get(key);
|
|
27217
|
-
if (!opts.invalidate && cached2?.head === head)
|
|
27303
|
+
if (!opts.invalidate && cached2?.head === head && opts.scope !== "worktree")
|
|
27218
27304
|
return cached2.value;
|
|
27219
27305
|
try {
|
|
27220
27306
|
const baseArgs = await diffArgs(opts);
|
|
@@ -27231,6 +27317,29 @@ async function getChangedFiles(opts) {
|
|
|
27231
27317
|
if (!await isSubmodule(opts.repoPath, file2.path))
|
|
27232
27318
|
filtered.push(file2);
|
|
27233
27319
|
}
|
|
27320
|
+
if (opts.scope === "worktree") {
|
|
27321
|
+
try {
|
|
27322
|
+
const untrackedRaw = await gitExec(["-C", opts.repoPath, "ls-files", "--others", "--exclude-standard", "-z"]);
|
|
27323
|
+
const untrackedPaths = untrackedRaw.split("\x00").filter(Boolean);
|
|
27324
|
+
for (const p of untrackedPaths) {
|
|
27325
|
+
if (filtered.some((f) => f.path === p))
|
|
27326
|
+
continue;
|
|
27327
|
+
if (await isSubmodule(opts.repoPath, p))
|
|
27328
|
+
continue;
|
|
27329
|
+
try {
|
|
27330
|
+
const full = path37.join(opts.repoPath, p);
|
|
27331
|
+
const buf = fs33.readFileSync(full);
|
|
27332
|
+
const binary = buf.includes(0);
|
|
27333
|
+
const str = binary ? "" : buf.toString("utf8");
|
|
27334
|
+
const added = binary ? 0 : str.split(`
|
|
27335
|
+
`).length;
|
|
27336
|
+
filtered.push({ path: p, status: "A", added, removed: 0, binary });
|
|
27337
|
+
} catch {
|
|
27338
|
+
filtered.push({ path: p, status: "A", added: 1, removed: 0, binary: false });
|
|
27339
|
+
}
|
|
27340
|
+
}
|
|
27341
|
+
} catch {}
|
|
27342
|
+
}
|
|
27234
27343
|
listCache.set(key, { head, value: filtered });
|
|
27235
27344
|
return filtered;
|
|
27236
27345
|
} catch {
|
|
@@ -27266,7 +27375,26 @@ async function getFileDiff(opts) {
|
|
|
27266
27375
|
const args = await diffArgs(opts, opts.filePath);
|
|
27267
27376
|
if (!args)
|
|
27268
27377
|
return empty;
|
|
27269
|
-
|
|
27378
|
+
let rawDiff = await gitExec(args);
|
|
27379
|
+
if (!rawDiff && opts.scope === "worktree" && changedFile.status === "A") {
|
|
27380
|
+
try {
|
|
27381
|
+
const full = path37.join(opts.repoPath, opts.filePath);
|
|
27382
|
+
const buf = fs33.readFileSync(full);
|
|
27383
|
+
if (!buf.includes(0)) {
|
|
27384
|
+
const content = buf.toString("utf8");
|
|
27385
|
+
const lines = content.split(`
|
|
27386
|
+
`);
|
|
27387
|
+
const header = `diff --git a/${opts.filePath} b/${opts.filePath}
|
|
27388
|
+
new file mode 100644
|
|
27389
|
+
--- /dev/null
|
|
27390
|
+
+++ b/${opts.filePath}
|
|
27391
|
+
@@ -0,0 +1,${lines.length} @@
|
|
27392
|
+
`;
|
|
27393
|
+
rawDiff = header + lines.map((l) => `+${l}`).join(`
|
|
27394
|
+
`);
|
|
27395
|
+
}
|
|
27396
|
+
} catch {}
|
|
27397
|
+
}
|
|
27270
27398
|
const { diff, truncated } = truncateDiff(rawDiff);
|
|
27271
27399
|
const value = { ...empty, diff, truncated };
|
|
27272
27400
|
diffCache.set(key, { head, value });
|
|
@@ -27932,7 +28060,9 @@ var init_Divider = __esm(() => {
|
|
|
27932
28060
|
|
|
27933
28061
|
// src/tui/components/Overlay.tsx
|
|
27934
28062
|
import { jsx as jsx9 } from "@opentui/react/jsx-runtime";
|
|
27935
|
-
function Overlay({ title, borderColor
|
|
28063
|
+
function Overlay({ title, borderColor, width = 64, children }) {
|
|
28064
|
+
const theme = useTheme();
|
|
28065
|
+
const resolvedBorder = borderColor ?? theme.border;
|
|
27936
28066
|
return /* @__PURE__ */ jsx9("box", {
|
|
27937
28067
|
id: "overlay-scrim",
|
|
27938
28068
|
position: "absolute",
|
|
@@ -27940,7 +28070,7 @@ function Overlay({ title, borderColor = tokens.border, width = 64, children }) {
|
|
|
27940
28070
|
height: "100%",
|
|
27941
28071
|
top: 0,
|
|
27942
28072
|
left: 0,
|
|
27943
|
-
backgroundColor:
|
|
28073
|
+
backgroundColor: theme.scrim,
|
|
27944
28074
|
zIndex: 100,
|
|
27945
28075
|
flexDirection: "row",
|
|
27946
28076
|
justifyContent: "center",
|
|
@@ -27949,13 +28079,13 @@ function Overlay({ title, borderColor = tokens.border, width = 64, children }) {
|
|
|
27949
28079
|
id: "overlay-panel",
|
|
27950
28080
|
width,
|
|
27951
28081
|
border: true,
|
|
27952
|
-
borderColor,
|
|
28082
|
+
borderColor: resolvedBorder,
|
|
27953
28083
|
title,
|
|
27954
|
-
titleColor:
|
|
28084
|
+
titleColor: resolvedBorder,
|
|
27955
28085
|
paddingX: 2,
|
|
27956
28086
|
paddingY: 1,
|
|
27957
28087
|
flexDirection: "column",
|
|
27958
|
-
backgroundColor:
|
|
28088
|
+
backgroundColor: theme.panelBg,
|
|
27959
28089
|
children
|
|
27960
28090
|
})
|
|
27961
28091
|
});
|
|
@@ -27967,85 +28097,132 @@ var init_Overlay = __esm(() => {
|
|
|
27967
28097
|
// src/tui/components/HelpOverlay.tsx
|
|
27968
28098
|
import { jsx as jsx10, jsxs as jsxs8 } from "@opentui/react/jsx-runtime";
|
|
27969
28099
|
function HelpOverlay() {
|
|
28100
|
+
const theme = useTheme();
|
|
27970
28101
|
return /* @__PURE__ */ jsxs8(Overlay, {
|
|
27971
28102
|
title: "Help",
|
|
27972
|
-
borderColor:
|
|
27973
|
-
width:
|
|
28103
|
+
borderColor: theme.border,
|
|
28104
|
+
width: 100,
|
|
27974
28105
|
children: [
|
|
27975
28106
|
/* @__PURE__ */ jsx10("box", {
|
|
27976
28107
|
flexDirection: "column",
|
|
27977
|
-
style: { maxHeight:
|
|
28108
|
+
style: { maxHeight: 38 },
|
|
27978
28109
|
children: /* @__PURE__ */ jsx10("scrollbox", {
|
|
27979
28110
|
flexGrow: 1,
|
|
27980
|
-
children:
|
|
27981
|
-
flexDirection: "
|
|
27982
|
-
|
|
28111
|
+
children: HELP_GROUPS.map((group) => /* @__PURE__ */ jsxs8("box", {
|
|
28112
|
+
flexDirection: "column",
|
|
28113
|
+
style: { marginBottom: 1 },
|
|
27983
28114
|
children: [
|
|
27984
28115
|
/* @__PURE__ */ jsx10("box", {
|
|
27985
|
-
|
|
27986
|
-
flexShrink: 0,
|
|
27987
|
-
justifyContent: "flex-end",
|
|
28116
|
+
style: { marginBottom: 1 },
|
|
27988
28117
|
children: /* @__PURE__ */ jsx10("text", {
|
|
27989
|
-
fg:
|
|
27990
|
-
|
|
28118
|
+
fg: theme.accent,
|
|
28119
|
+
attributes: 1,
|
|
28120
|
+
children: group.title
|
|
27991
28121
|
})
|
|
27992
28122
|
}),
|
|
27993
|
-
/* @__PURE__ */
|
|
27994
|
-
|
|
27995
|
-
|
|
27996
|
-
|
|
27997
|
-
|
|
27998
|
-
|
|
27999
|
-
|
|
28000
|
-
|
|
28001
|
-
|
|
28002
|
-
|
|
28003
|
-
|
|
28123
|
+
group.entries.map(([key, desc]) => /* @__PURE__ */ jsxs8("box", {
|
|
28124
|
+
flexDirection: "row",
|
|
28125
|
+
gap: 1,
|
|
28126
|
+
children: [
|
|
28127
|
+
/* @__PURE__ */ jsx10("box", {
|
|
28128
|
+
width: 22,
|
|
28129
|
+
flexShrink: 0,
|
|
28130
|
+
justifyContent: "flex-end",
|
|
28131
|
+
children: /* @__PURE__ */ jsx10("text", {
|
|
28132
|
+
fg: theme.accent,
|
|
28133
|
+
children: key
|
|
28134
|
+
})
|
|
28135
|
+
}),
|
|
28136
|
+
/* @__PURE__ */ jsx10("text", {
|
|
28137
|
+
fg: theme.dim,
|
|
28138
|
+
children: "-"
|
|
28139
|
+
}),
|
|
28140
|
+
/* @__PURE__ */ jsx10("box", {
|
|
28141
|
+
flexGrow: 1,
|
|
28142
|
+
children: /* @__PURE__ */ jsx10("text", {
|
|
28143
|
+
fg: theme.fg,
|
|
28144
|
+
children: desc
|
|
28145
|
+
})
|
|
28146
|
+
})
|
|
28147
|
+
]
|
|
28148
|
+
}, key))
|
|
28004
28149
|
]
|
|
28005
|
-
},
|
|
28150
|
+
}, group.title))
|
|
28006
28151
|
})
|
|
28007
28152
|
}),
|
|
28008
28153
|
/* @__PURE__ */ jsx10("text", {
|
|
28009
|
-
style: { marginTop: 1, fg:
|
|
28154
|
+
style: { marginTop: 1, fg: theme.dim },
|
|
28010
28155
|
children: "Press any key to close"
|
|
28011
28156
|
})
|
|
28012
28157
|
]
|
|
28013
28158
|
});
|
|
28014
28159
|
}
|
|
28015
|
-
var
|
|
28160
|
+
var HELP_GROUPS;
|
|
28016
28161
|
var init_HelpOverlay = __esm(() => {
|
|
28017
28162
|
init_Overlay();
|
|
28018
28163
|
init_theme();
|
|
28019
|
-
|
|
28020
|
-
|
|
28021
|
-
|
|
28022
|
-
|
|
28023
|
-
|
|
28024
|
-
|
|
28025
|
-
|
|
28026
|
-
|
|
28027
|
-
|
|
28028
|
-
|
|
28029
|
-
|
|
28030
|
-
|
|
28031
|
-
|
|
28032
|
-
|
|
28033
|
-
|
|
28034
|
-
|
|
28035
|
-
|
|
28036
|
-
|
|
28037
|
-
|
|
28038
|
-
|
|
28039
|
-
|
|
28040
|
-
|
|
28041
|
-
|
|
28042
|
-
|
|
28043
|
-
|
|
28044
|
-
|
|
28045
|
-
|
|
28046
|
-
|
|
28047
|
-
|
|
28048
|
-
|
|
28164
|
+
HELP_GROUPS = [
|
|
28165
|
+
{
|
|
28166
|
+
title: "Navigation & Filtering",
|
|
28167
|
+
entries: [
|
|
28168
|
+
["↑/↓, k/j", "Navigate list"],
|
|
28169
|
+
["/", "Filter list"],
|
|
28170
|
+
["Space", "Multi-select"],
|
|
28171
|
+
["q/esc", "Quit"]
|
|
28172
|
+
]
|
|
28173
|
+
},
|
|
28174
|
+
{
|
|
28175
|
+
title: "Worktree Lifecycle",
|
|
28176
|
+
entries: [
|
|
28177
|
+
["n", "Create new worktree (pick dependency strategy)"],
|
|
28178
|
+
["d", "Remove selected worktree(s)"],
|
|
28179
|
+
["m", "Rename selected worktree (branch + directory)"],
|
|
28180
|
+
["o", "Open selected in IDE"],
|
|
28181
|
+
["f", "Fetch main for selected repo(s)"],
|
|
28182
|
+
["p", "Pull latest changes for selected branch(es)"],
|
|
28183
|
+
["P (shift+p)", "Pull PR by link (force-override if exists)"],
|
|
28184
|
+
["b", "Rebase selected onto base (or main)"],
|
|
28185
|
+
["s", "Sync selected (env files + hooks)"],
|
|
28186
|
+
["i", "Install dependencies in selection (worktrees and main)"]
|
|
28187
|
+
]
|
|
28188
|
+
},
|
|
28189
|
+
{
|
|
28190
|
+
title: "Favorites & Workspaces",
|
|
28191
|
+
entries: [
|
|
28192
|
+
["F (shift+f)", "Pin/unpin selected repo (favorites float to top)"],
|
|
28193
|
+
["W (shift+w)", "Scope list to a workspace's members (press again to clear)"]
|
|
28194
|
+
]
|
|
28195
|
+
},
|
|
28196
|
+
{
|
|
28197
|
+
title: "Terminal & Tabs",
|
|
28198
|
+
entries: [
|
|
28199
|
+
["t", "New terminal session (max 5 per worktree)"],
|
|
28200
|
+
["click tab", "Switch Details / Changes / Session tabs"],
|
|
28201
|
+
["Ctrl+G / click table", "Leave terminal focus — focused terminal gets all keys"]
|
|
28202
|
+
]
|
|
28203
|
+
},
|
|
28204
|
+
{
|
|
28205
|
+
title: "Changes Explorer (only for dirty worktrees)",
|
|
28206
|
+
entries: [
|
|
28207
|
+
["click Changes", "Focus pane — j/k navigates files, s/Tab cycles scope"],
|
|
28208
|
+
["s / Tab", "Cycle scope: worktree (dirty+untracked) → staged → base (vs base branch)"],
|
|
28209
|
+
["j / k, ↑/↓", "Navigate files (when Changes focused, Ctrl+G/Esc to unfocus)"]
|
|
28210
|
+
]
|
|
28211
|
+
},
|
|
28212
|
+
{
|
|
28213
|
+
title: "View & System",
|
|
28214
|
+
entries: [
|
|
28215
|
+
["T (shift+t)", "Cycle theme presets"],
|
|
28216
|
+
["c", "Open configuration"],
|
|
28217
|
+
["e", "View data warnings (when count > 0)"],
|
|
28218
|
+
["r", "Refresh data"],
|
|
28219
|
+
["H", "Action history"],
|
|
28220
|
+
["?", "Toggle help"],
|
|
28221
|
+
["mouse drag", "Select text — copied to clipboard automatically"],
|
|
28222
|
+
["ctrl+shift+c", "Copy selection again (terminals reserve cmd+c)"],
|
|
28223
|
+
["click PR #/URL", "Open pull request in browser"]
|
|
28224
|
+
]
|
|
28225
|
+
}
|
|
28049
28226
|
];
|
|
28050
28227
|
});
|
|
28051
28228
|
|
|
@@ -28231,38 +28408,38 @@ var init_ActionLogModal = __esm(() => {
|
|
|
28231
28408
|
});
|
|
28232
28409
|
|
|
28233
28410
|
// src/lib/history.ts
|
|
28234
|
-
import
|
|
28235
|
-
import
|
|
28411
|
+
import fs34 from "fs";
|
|
28412
|
+
import path38 from "path";
|
|
28236
28413
|
import os4 from "os";
|
|
28237
28414
|
function getHistoryDir() {
|
|
28238
|
-
const stateHome = process.env.XDG_STATE_HOME ??
|
|
28239
|
-
return
|
|
28415
|
+
const stateHome = process.env.XDG_STATE_HOME ?? path38.join(os4.homedir(), ".local", "state");
|
|
28416
|
+
return path38.join(stateHome, "wtx");
|
|
28240
28417
|
}
|
|
28241
28418
|
function getHistoryPath() {
|
|
28242
|
-
return
|
|
28419
|
+
return path38.join(getHistoryDir(), "history.jsonl");
|
|
28243
28420
|
}
|
|
28244
28421
|
function rotateHistory(maxBytes = HISTORY_MAX_BYTES, keepLines = HISTORY_ROTATE_KEEP_LINES) {
|
|
28245
28422
|
const historyPath = getHistoryPath();
|
|
28246
28423
|
let size = 0;
|
|
28247
28424
|
try {
|
|
28248
|
-
size =
|
|
28425
|
+
size = fs34.statSync(historyPath).size;
|
|
28249
28426
|
} catch {
|
|
28250
28427
|
return;
|
|
28251
28428
|
}
|
|
28252
28429
|
if (size <= maxBytes)
|
|
28253
28430
|
return;
|
|
28254
|
-
const lines =
|
|
28431
|
+
const lines = fs34.readFileSync(historyPath, "utf-8").split(`
|
|
28255
28432
|
`).filter(Boolean);
|
|
28256
28433
|
const kept = lines.slice(-keepLines);
|
|
28257
28434
|
const tmpPath = `${historyPath}.tmp.${process.pid}`;
|
|
28258
28435
|
try {
|
|
28259
|
-
|
|
28436
|
+
fs34.writeFileSync(tmpPath, kept.length > 0 ? `${kept.join(`
|
|
28260
28437
|
`)}
|
|
28261
28438
|
` : "", "utf-8");
|
|
28262
|
-
|
|
28439
|
+
fs34.renameSync(tmpPath, historyPath);
|
|
28263
28440
|
} catch (err) {
|
|
28264
|
-
if (
|
|
28265
|
-
|
|
28441
|
+
if (fs34.existsSync(tmpPath)) {
|
|
28442
|
+
fs34.unlinkSync(tmpPath);
|
|
28266
28443
|
}
|
|
28267
28444
|
throw err;
|
|
28268
28445
|
}
|
|
@@ -28270,18 +28447,18 @@ function rotateHistory(maxBytes = HISTORY_MAX_BYTES, keepLines = HISTORY_ROTATE_
|
|
|
28270
28447
|
function appendHistory(entry) {
|
|
28271
28448
|
try {
|
|
28272
28449
|
const dir = getHistoryDir();
|
|
28273
|
-
if (!
|
|
28274
|
-
|
|
28450
|
+
if (!fs34.existsSync(dir)) {
|
|
28451
|
+
fs34.mkdirSync(dir, { recursive: true });
|
|
28275
28452
|
}
|
|
28276
28453
|
rotateHistory();
|
|
28277
|
-
|
|
28454
|
+
fs34.appendFileSync(getHistoryPath(), `${JSON.stringify(entry)}
|
|
28278
28455
|
`, "utf-8");
|
|
28279
28456
|
} catch {}
|
|
28280
28457
|
}
|
|
28281
28458
|
function readRecentHistory(limit = 50) {
|
|
28282
28459
|
let content;
|
|
28283
28460
|
try {
|
|
28284
|
-
content =
|
|
28461
|
+
content = fs34.readFileSync(getHistoryPath(), "utf-8");
|
|
28285
28462
|
} catch {
|
|
28286
28463
|
return [];
|
|
28287
28464
|
}
|
|
@@ -28419,13 +28596,19 @@ function InputModal({ title, placeholder, initialValue, errorMessage: errorMessa
|
|
|
28419
28596
|
borderColor: tokens.accent,
|
|
28420
28597
|
children: /* @__PURE__ */ jsxs12("box", {
|
|
28421
28598
|
flexDirection: "column",
|
|
28599
|
+
width: "100%",
|
|
28422
28600
|
children: [
|
|
28423
|
-
/* @__PURE__ */ jsx14("
|
|
28424
|
-
|
|
28425
|
-
|
|
28426
|
-
|
|
28427
|
-
|
|
28428
|
-
|
|
28601
|
+
/* @__PURE__ */ jsx14("box", {
|
|
28602
|
+
flexGrow: 1,
|
|
28603
|
+
width: "100%",
|
|
28604
|
+
children: /* @__PURE__ */ jsx14("input", {
|
|
28605
|
+
focused: true,
|
|
28606
|
+
value,
|
|
28607
|
+
placeholder,
|
|
28608
|
+
onInput: (val) => setValue(val),
|
|
28609
|
+
onSubmit: () => onSubmit(value),
|
|
28610
|
+
width: "100%"
|
|
28611
|
+
})
|
|
28429
28612
|
}),
|
|
28430
28613
|
errorMessage4 ? /* @__PURE__ */ jsx14("text", {
|
|
28431
28614
|
fg: tokens.error,
|
|
@@ -28992,8 +29175,8 @@ function hasDirectStdinWrite(proc) {
|
|
|
28992
29175
|
function hasWritableStreamStdin(proc) {
|
|
28993
29176
|
return !!proc && proc.stdin instanceof WritableStream;
|
|
28994
29177
|
}
|
|
28995
|
-
function worktreeKeyFor(repoName, branch,
|
|
28996
|
-
return
|
|
29178
|
+
function worktreeKeyFor(repoName, branch, path39) {
|
|
29179
|
+
return path39 || `${repoName}:${branch}`;
|
|
28997
29180
|
}
|
|
28998
29181
|
function nextTerminalSessionLabel(existingCount) {
|
|
28999
29182
|
return `Session ${existingCount + 1}`;
|
|
@@ -29011,13 +29194,13 @@ function useTerminalSessions() {
|
|
|
29011
29194
|
const [sessionsByKey, setSessionsByKey] = useState10(() => new Map);
|
|
29012
29195
|
const procsRef = useRef7(new Map);
|
|
29013
29196
|
const listenersRef = useRef7(new Map);
|
|
29014
|
-
const getSessions = useCallback6((repoName, branch,
|
|
29015
|
-
const key = worktreeKeyFor(repoName, branch,
|
|
29197
|
+
const getSessions = useCallback6((repoName, branch, path39) => {
|
|
29198
|
+
const key = worktreeKeyFor(repoName, branch, path39);
|
|
29016
29199
|
return sessionsByKey.get(key) ?? [];
|
|
29017
29200
|
}, [sessionsByKey]);
|
|
29018
|
-
const getKey = useCallback6((repoName, branch,
|
|
29019
|
-
const createSession = useCallback6((repoName, branch,
|
|
29020
|
-
const key = worktreeKeyFor(repoName, branch,
|
|
29201
|
+
const getKey = useCallback6((repoName, branch, path39) => worktreeKeyFor(repoName, branch, path39), []);
|
|
29202
|
+
const createSession = useCallback6((repoName, branch, path39, opts) => {
|
|
29203
|
+
const key = worktreeKeyFor(repoName, branch, path39);
|
|
29021
29204
|
const existing = sessionsByKey.get(key) ?? [];
|
|
29022
29205
|
if (existing.length >= MAX_TERMINAL_SESSIONS) {
|
|
29023
29206
|
return { session: null, error: `Max ${MAX_TERMINAL_SESSIONS} sessions per worktree` };
|
|
@@ -29030,7 +29213,7 @@ function useTerminalSessions() {
|
|
|
29030
29213
|
id,
|
|
29031
29214
|
label,
|
|
29032
29215
|
worktreeKey: key,
|
|
29033
|
-
worktreePath:
|
|
29216
|
+
worktreePath: path39,
|
|
29034
29217
|
repoName,
|
|
29035
29218
|
branch,
|
|
29036
29219
|
lines: [],
|
|
@@ -29115,7 +29298,7 @@ function useTerminalSessions() {
|
|
|
29115
29298
|
throw new Error("pty not available");
|
|
29116
29299
|
}
|
|
29117
29300
|
const proc = Bun.spawn([shell], {
|
|
29118
|
-
cwd:
|
|
29301
|
+
cwd: path39 || process.cwd(),
|
|
29119
29302
|
env: { ...process.env, TERM: "xterm-256color", COLORTERM: "truecolor", WTX_SESSION: label },
|
|
29120
29303
|
terminal: {
|
|
29121
29304
|
cols,
|
|
@@ -29150,7 +29333,7 @@ function useTerminalSessions() {
|
|
|
29150
29333
|
session.usePty = false;
|
|
29151
29334
|
try {
|
|
29152
29335
|
const proc = Bun.spawn([shell], {
|
|
29153
|
-
cwd:
|
|
29336
|
+
cwd: path39 || process.cwd(),
|
|
29154
29337
|
stdin: "pipe",
|
|
29155
29338
|
stdout: "pipe",
|
|
29156
29339
|
stderr: "pipe",
|
|
@@ -29198,9 +29381,9 @@ function useTerminalSessions() {
|
|
|
29198
29381
|
} catch {}
|
|
29199
29382
|
}
|
|
29200
29383
|
if (session.usePty) {
|
|
29201
|
-
session.lines = [`${label} — ${
|
|
29384
|
+
session.lines = [`${label} — ${path39} (${shell}) [pty]`, ""];
|
|
29202
29385
|
} else if (!session.spawnError && session.lines.length === 0) {
|
|
29203
|
-
session.lines = [`${label} — ${
|
|
29386
|
+
session.lines = [`${label} — ${path39} (${shell})`, ""];
|
|
29204
29387
|
}
|
|
29205
29388
|
setSessionsByKey((prev) => {
|
|
29206
29389
|
const next = new Map(prev);
|
|
@@ -29210,8 +29393,8 @@ function useTerminalSessions() {
|
|
|
29210
29393
|
});
|
|
29211
29394
|
return { session };
|
|
29212
29395
|
}, [sessionsByKey]);
|
|
29213
|
-
const removeSession = useCallback6((repoName, branch,
|
|
29214
|
-
const key = worktreeKeyFor(repoName, branch,
|
|
29396
|
+
const removeSession = useCallback6((repoName, branch, path39, id) => {
|
|
29397
|
+
const key = worktreeKeyFor(repoName, branch, path39);
|
|
29215
29398
|
setSessionsByKey((prev) => {
|
|
29216
29399
|
const next = new Map(prev);
|
|
29217
29400
|
const list = next.get(key);
|
|
@@ -29240,8 +29423,8 @@ function useTerminalSessions() {
|
|
|
29240
29423
|
return next;
|
|
29241
29424
|
});
|
|
29242
29425
|
}, []);
|
|
29243
|
-
const sendInput = useCallback6((repoName, branch,
|
|
29244
|
-
const key = worktreeKeyFor(repoName, branch,
|
|
29426
|
+
const sendInput = useCallback6((repoName, branch, path39, id, data) => {
|
|
29427
|
+
const key = worktreeKeyFor(repoName, branch, path39);
|
|
29245
29428
|
const list = sessionsByKey.get(key) ?? [];
|
|
29246
29429
|
const sess = list.find((s) => s.id === id);
|
|
29247
29430
|
if (!sess?.proc)
|
|
@@ -29289,8 +29472,8 @@ function useTerminalSessions() {
|
|
|
29289
29472
|
}
|
|
29290
29473
|
}
|
|
29291
29474
|
}, [sessionsByKey]);
|
|
29292
|
-
const resizeSession = useCallback6((repoName, branch,
|
|
29293
|
-
const key = worktreeKeyFor(repoName, branch,
|
|
29475
|
+
const resizeSession = useCallback6((repoName, branch, path39, id, cols, rows) => {
|
|
29476
|
+
const key = worktreeKeyFor(repoName, branch, path39);
|
|
29294
29477
|
setSessionsByKey((prev) => {
|
|
29295
29478
|
const list = prev.get(key);
|
|
29296
29479
|
if (!list)
|
|
@@ -29682,6 +29865,7 @@ function App({ opts }) {
|
|
|
29682
29865
|
const [activeTabByWorktree, setActiveTabByWorktree] = useState11(() => new Map);
|
|
29683
29866
|
const [recentTerminalSessionIds, setRecentTerminalSessionIds] = useState11([]);
|
|
29684
29867
|
const [terminalFocused, setTerminalFocused] = useState11(false);
|
|
29868
|
+
const [changesFocused, setChangesFocused] = useState11(false);
|
|
29685
29869
|
const { width: termW, height: termH } = useTerminalDimensions();
|
|
29686
29870
|
const totalWidth = termW || renderer.width || 80;
|
|
29687
29871
|
const totalHeight = termH || renderer.terminalHeight || 24;
|
|
@@ -29799,7 +29983,17 @@ function App({ opts }) {
|
|
|
29799
29983
|
const baseFiltered = useMemo3(() => blocks.map((b) => ({
|
|
29800
29984
|
...b,
|
|
29801
29985
|
rows: b.rows.filter((r) => matchesFilter(r, filterText) && matchesWorkspace(r, workspaceMemberSet))
|
|
29802
|
-
})).filter((b) =>
|
|
29986
|
+
})).filter((b) => {
|
|
29987
|
+
if (b.rows.length > 0)
|
|
29988
|
+
return true;
|
|
29989
|
+
if (workspaceMemberSet !== null)
|
|
29990
|
+
return false;
|
|
29991
|
+
if (pendingRepos.includes(b.repoName))
|
|
29992
|
+
return true;
|
|
29993
|
+
if (!filterText)
|
|
29994
|
+
return true;
|
|
29995
|
+
return matchesFilter({ repoName: b.repoName, branch: "" }, filterText);
|
|
29996
|
+
}), [blocks, filterText, pendingRepos, workspaceMemberSet]);
|
|
29803
29997
|
const missingMemberWarnings = useMemo3(() => {
|
|
29804
29998
|
if (!activeWorkspace)
|
|
29805
29999
|
return [];
|
|
@@ -29818,7 +30012,7 @@ function App({ opts }) {
|
|
|
29818
30012
|
const displayBlocks = useMemo3(() => sortBlocks([
|
|
29819
30013
|
...withCreatePlaceholders(baseFiltered, ops.filter((o2) => o2.branch !== undefined).map((o2) => ({ repoName: o2.repoNames[0], branch: o2.branch }))),
|
|
29820
30014
|
...pendingBlocks
|
|
29821
|
-
]), [baseFiltered, ops, pendingBlocks]);
|
|
30015
|
+
], favorites), [baseFiltered, ops, pendingBlocks, favorites]);
|
|
29822
30016
|
const flatRows = useMemo3(() => displayBlocks.flatMap((b) => b.rows.filter((r) => !r.isPendingCreate)), [displayBlocks]);
|
|
29823
30017
|
const totalRows = blocks.flatMap((b) => b.rows).length;
|
|
29824
30018
|
const maxIndex = Math.max(0, flatRows.length - 1);
|
|
@@ -29843,7 +30037,15 @@ function App({ opts }) {
|
|
|
29843
30037
|
}
|
|
29844
30038
|
}, [worktreeKey, activeTabByWorktree]);
|
|
29845
30039
|
useEffect9(() => {
|
|
29846
|
-
if (
|
|
30040
|
+
if (activeTabId === "changes" && selectedRow && (selectedRow.isMainCheckout || selectedRow.dirtyFiles.length === 0)) {
|
|
30041
|
+
setActiveTabByWorktree((prev) => {
|
|
30042
|
+
const next = new Map(prev);
|
|
30043
|
+
next.set(worktreeKey, "details");
|
|
30044
|
+
return next;
|
|
30045
|
+
});
|
|
30046
|
+
return;
|
|
30047
|
+
}
|
|
30048
|
+
if (sessionsForSelected.length === 0 && activeTabId !== "details" && activeTabId !== "changes") {
|
|
29847
30049
|
setActiveTabByWorktree((prev) => {
|
|
29848
30050
|
const next = new Map(prev);
|
|
29849
30051
|
next.set(worktreeKey, "details");
|
|
@@ -29851,7 +30053,7 @@ function App({ opts }) {
|
|
|
29851
30053
|
});
|
|
29852
30054
|
setTerminalFocused(false);
|
|
29853
30055
|
} else if (sessionsForSelected.length > 0) {
|
|
29854
|
-
const exists = sessionsForSelected.some((s) => s.id === activeTabId) || activeTabId === "details";
|
|
30056
|
+
const exists = sessionsForSelected.some((s) => s.id === activeTabId) || activeTabId === "details" || selectedRow && !selectedRow.isMainCheckout && selectedRow.dirtyFiles.length > 0 && activeTabId === "changes";
|
|
29855
30057
|
if (!exists) {
|
|
29856
30058
|
setActiveTabByWorktree((prev) => {
|
|
29857
30059
|
const next = new Map(prev);
|
|
@@ -29860,7 +30062,15 @@ function App({ opts }) {
|
|
|
29860
30062
|
});
|
|
29861
30063
|
}
|
|
29862
30064
|
}
|
|
29863
|
-
}, [sessionsForSelected, activeTabId, worktreeKey]);
|
|
30065
|
+
}, [sessionsForSelected, activeTabId, worktreeKey, selectedRow]);
|
|
30066
|
+
useEffect9(() => {
|
|
30067
|
+
setChangesFocused(false);
|
|
30068
|
+
setTerminalFocused(false);
|
|
30069
|
+
}, [worktreeKey]);
|
|
30070
|
+
useEffect9(() => {
|
|
30071
|
+
if (activeTabId !== "changes")
|
|
30072
|
+
setChangesFocused(false);
|
|
30073
|
+
}, [activeTabId]);
|
|
29864
30074
|
usePaste((event) => {
|
|
29865
30075
|
if (!terminalFocused)
|
|
29866
30076
|
return;
|
|
@@ -29884,7 +30094,8 @@ function App({ opts }) {
|
|
|
29884
30094
|
return next;
|
|
29885
30095
|
});
|
|
29886
30096
|
setTerminalFocused(isSession);
|
|
29887
|
-
|
|
30097
|
+
setChangesFocused(id === "changes" && selectedRow != null && !selectedRow.isMainCheckout && selectedRow.dirtyFiles.length > 0);
|
|
30098
|
+
}, [activeTabId, renderer, worktreeKey, sessionsForSelected, selectedRow]);
|
|
29888
30099
|
const handleAddSession = useCallback7(() => {
|
|
29889
30100
|
if (!selectedRow) {
|
|
29890
30101
|
flash("No worktree selected");
|
|
@@ -29908,13 +30119,31 @@ function App({ opts }) {
|
|
|
29908
30119
|
return next;
|
|
29909
30120
|
});
|
|
29910
30121
|
setTerminalFocused(true);
|
|
30122
|
+
setChangesFocused(false);
|
|
29911
30123
|
flash(`Session ${session.label} created`, 2000);
|
|
29912
30124
|
}, [selectedRow, terminalSessions, flash, totalWidth, splitRatio, totalHeight, activeTabId, sessionsForSelected]);
|
|
29913
30125
|
const handleCloseSession = useCallback7((id) => {
|
|
29914
|
-
|
|
29915
|
-
|
|
29916
|
-
|
|
29917
|
-
const
|
|
30126
|
+
let targetRepo;
|
|
30127
|
+
let targetBranch;
|
|
30128
|
+
let targetPath;
|
|
30129
|
+
for (const sessions of terminalSessions.sessionsByKey.values()) {
|
|
30130
|
+
const found = sessions.find((s) => s.id === id);
|
|
30131
|
+
if (found) {
|
|
30132
|
+
targetRepo = found.repoName;
|
|
30133
|
+
targetBranch = found.branch;
|
|
30134
|
+
targetPath = found.worktreePath;
|
|
30135
|
+
break;
|
|
30136
|
+
}
|
|
30137
|
+
}
|
|
30138
|
+
if (!targetRepo || !targetBranch || !targetPath) {
|
|
30139
|
+
if (!selectedRow)
|
|
30140
|
+
return;
|
|
30141
|
+
targetRepo = selectedRow.repoName;
|
|
30142
|
+
targetBranch = selectedRow.branch;
|
|
30143
|
+
targetPath = selectedRow.path;
|
|
30144
|
+
}
|
|
30145
|
+
terminalSessions.removeSession(targetRepo, targetBranch, targetPath, id);
|
|
30146
|
+
const key = terminalSessions.getKey(targetRepo, targetBranch, targetPath);
|
|
29918
30147
|
setActiveTabByWorktree((prev) => {
|
|
29919
30148
|
const next = new Map(prev);
|
|
29920
30149
|
const current = next.get(key);
|
|
@@ -29950,8 +30179,10 @@ function App({ opts }) {
|
|
|
29950
30179
|
render: ({ worktree }) => /* @__PURE__ */ jsx18(DetailsContent, {
|
|
29951
30180
|
selectedRow: worktree
|
|
29952
30181
|
})
|
|
29953
|
-
}
|
|
29954
|
-
|
|
30182
|
+
}
|
|
30183
|
+
];
|
|
30184
|
+
if (selectedRow != null && !selectedRow.isMainCheckout && selectedRow.dirtyFiles.length > 0) {
|
|
30185
|
+
base2.push({
|
|
29955
30186
|
id: "changes",
|
|
29956
30187
|
label: "Changes",
|
|
29957
30188
|
render: ({ worktree, isActive, focused }) => /* @__PURE__ */ jsx18(ChangesContent, {
|
|
@@ -29960,8 +30191,8 @@ function App({ opts }) {
|
|
|
29960
30191
|
focused,
|
|
29961
30192
|
worktreeKey
|
|
29962
30193
|
})
|
|
29963
|
-
}
|
|
29964
|
-
|
|
30194
|
+
});
|
|
30195
|
+
}
|
|
29965
30196
|
for (const s of sessionsForSelected) {
|
|
29966
30197
|
base2.push({
|
|
29967
30198
|
id: s.id,
|
|
@@ -29975,7 +30206,7 @@ function App({ opts }) {
|
|
|
29975
30206
|
});
|
|
29976
30207
|
}
|
|
29977
30208
|
return base2;
|
|
29978
|
-
}, [sessionsForSelected, worktreeKey]);
|
|
30209
|
+
}, [selectedRow, sessionsForSelected, worktreeKey]);
|
|
29979
30210
|
const { repoVerbs, rowVerbs } = useMemo3(() => {
|
|
29980
30211
|
const rv = new Map;
|
|
29981
30212
|
const nv = new Map;
|
|
@@ -30279,6 +30510,15 @@ function App({ opts }) {
|
|
|
30279
30510
|
}
|
|
30280
30511
|
}, [selectedRow, selection, combinedWarnings, busyRepos, busyRowPaths, doRefresh, flash, blocks, terminalSessions]);
|
|
30281
30512
|
useKeyboard4((key) => {
|
|
30513
|
+
if (changesFocused) {
|
|
30514
|
+
if (key.ctrl && key.name === "g" || key.name === "escape") {
|
|
30515
|
+
setChangesFocused(false);
|
|
30516
|
+
return;
|
|
30517
|
+
}
|
|
30518
|
+
if (["j", "k", "down", "up", "s", "tab"].includes(key.name)) {
|
|
30519
|
+
return;
|
|
30520
|
+
}
|
|
30521
|
+
}
|
|
30282
30522
|
if (terminalFocused) {
|
|
30283
30523
|
if (key.ctrl && key.name === "g") {
|
|
30284
30524
|
setTerminalFocused(false);
|
|
@@ -30720,6 +30960,7 @@ function App({ opts }) {
|
|
|
30720
30960
|
useEffect9(() => () => terminalResizeSchedulerRef.current?.flush(), []);
|
|
30721
30961
|
useEffect9(() => {
|
|
30722
30962
|
setTerminalFocused(false);
|
|
30963
|
+
setChangesFocused(false);
|
|
30723
30964
|
}, [selectedIndex]);
|
|
30724
30965
|
return /* @__PURE__ */ jsx18(ThemeContext.Provider, {
|
|
30725
30966
|
value: currentTheme,
|
|
@@ -30737,7 +30978,10 @@ function App({ opts }) {
|
|
|
30737
30978
|
width: leftCols,
|
|
30738
30979
|
height: "100%",
|
|
30739
30980
|
flexDirection: "column",
|
|
30740
|
-
onMouseDown: () =>
|
|
30981
|
+
onMouseDown: () => {
|
|
30982
|
+
setTerminalFocused(false);
|
|
30983
|
+
setChangesFocused(false);
|
|
30984
|
+
},
|
|
30741
30985
|
children: /* @__PURE__ */ jsx18(WorktreeTable, {
|
|
30742
30986
|
blocks: displayBlocks,
|
|
30743
30987
|
selectedIndex,
|
|
@@ -30750,9 +30994,10 @@ function App({ opts }) {
|
|
|
30750
30994
|
activeWorkspaceName: activeWorkspace?.name ?? null,
|
|
30751
30995
|
onRowClick: (idx) => {
|
|
30752
30996
|
setTerminalFocused(false);
|
|
30997
|
+
setChangesFocused(false);
|
|
30753
30998
|
setSelectedIndex(idx);
|
|
30754
30999
|
},
|
|
30755
|
-
onToggleSelect: (
|
|
31000
|
+
onToggleSelect: (path39) => setSelection((prev) => toggleSelection(prev, path39))
|
|
30756
31001
|
})
|
|
30757
31002
|
}),
|
|
30758
31003
|
/* @__PURE__ */ jsx18(Divider, {
|
|
@@ -30769,13 +31014,18 @@ function App({ opts }) {
|
|
|
30769
31014
|
selectedRow,
|
|
30770
31015
|
tabs: tabsForSelected,
|
|
30771
31016
|
activeId: activeTabId,
|
|
30772
|
-
focused: terminalFocused
|
|
31017
|
+
focused: (terminalFocused || changesFocused) && activeTabId !== "details",
|
|
30773
31018
|
canAdd: sessionsForSelected.length < MAX_TERMINAL_SESSIONS,
|
|
30774
31019
|
onSelect: handleSelectTab,
|
|
30775
31020
|
onAdd: handleAddSession,
|
|
30776
31021
|
onClose: handleCloseSession,
|
|
30777
31022
|
allSessionsFlat,
|
|
30778
31023
|
terminalFocused,
|
|
31024
|
+
changesFocused,
|
|
31025
|
+
onChangesFocus: () => {
|
|
31026
|
+
setChangesFocused(true);
|
|
31027
|
+
setTerminalFocused(false);
|
|
31028
|
+
},
|
|
30779
31029
|
activeTabId,
|
|
30780
31030
|
recentSessionIds: mountedRecentSessionIds,
|
|
30781
31031
|
terminalSessions
|
|
@@ -30788,15 +31038,20 @@ function App({ opts }) {
|
|
|
30788
31038
|
paddingX: 1,
|
|
30789
31039
|
border: true,
|
|
30790
31040
|
borderColor: "magenta",
|
|
31041
|
+
width: "100%",
|
|
30791
31042
|
children: [
|
|
30792
31043
|
/* @__PURE__ */ jsx18("text", {
|
|
30793
31044
|
children: "filter: "
|
|
30794
31045
|
}),
|
|
30795
|
-
/* @__PURE__ */ jsx18("
|
|
30796
|
-
|
|
30797
|
-
|
|
30798
|
-
|
|
30799
|
-
|
|
31046
|
+
/* @__PURE__ */ jsx18("box", {
|
|
31047
|
+
flexGrow: 1,
|
|
31048
|
+
children: /* @__PURE__ */ jsx18("input", {
|
|
31049
|
+
focused: true,
|
|
31050
|
+
value: filterText,
|
|
31051
|
+
placeholder: "Type to filter...",
|
|
31052
|
+
onInput: (v) => setFilterText(v),
|
|
31053
|
+
width: "100%"
|
|
31054
|
+
})
|
|
30800
31055
|
})
|
|
30801
31056
|
]
|
|
30802
31057
|
}),
|
|
@@ -36145,8 +36400,8 @@ function registerSkillCommand(program2) {
|
|
|
36145
36400
|
|
|
36146
36401
|
// src/commands/terminal.ts
|
|
36147
36402
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
36148
|
-
import
|
|
36149
|
-
import
|
|
36403
|
+
import fs35 from "node:fs";
|
|
36404
|
+
import path39 from "node:path";
|
|
36150
36405
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
36151
36406
|
function findEntry() {
|
|
36152
36407
|
const candidates = [];
|
|
@@ -36155,26 +36410,26 @@ function findEntry() {
|
|
|
36155
36410
|
try {
|
|
36156
36411
|
const thisPath = fileURLToPath4(import.meta.url);
|
|
36157
36412
|
candidates.push(thisPath);
|
|
36158
|
-
candidates.push(
|
|
36159
|
-
candidates.push(
|
|
36413
|
+
candidates.push(path39.resolve(path39.dirname(thisPath), "../../dist/cli.mjs"));
|
|
36414
|
+
candidates.push(path39.resolve(path39.dirname(thisPath), "../cli.mjs"));
|
|
36160
36415
|
} catch {}
|
|
36161
36416
|
for (const p of candidates) {
|
|
36162
36417
|
try {
|
|
36163
36418
|
if (p.endsWith(".mjs") || p.endsWith(".js")) {
|
|
36164
|
-
if (
|
|
36419
|
+
if (fs35.existsSync(p) && fs35.statSync(p).isFile())
|
|
36165
36420
|
return p;
|
|
36166
|
-
} else if (
|
|
36167
|
-
const stat =
|
|
36421
|
+
} else if (fs35.existsSync(p)) {
|
|
36422
|
+
const stat = fs35.statSync(p);
|
|
36168
36423
|
if (stat.isFile()) {
|
|
36169
|
-
const head =
|
|
36424
|
+
const head = fs35.readFileSync(p, "utf8").slice(0, 1024);
|
|
36170
36425
|
if (head.includes("cli.mjs") || head.includes("#!/usr/bin/env node")) {
|
|
36171
36426
|
if (p.endsWith("wtx") || p.endsWith("cli.mjs")) {
|
|
36172
|
-
const dir =
|
|
36173
|
-
const cli =
|
|
36174
|
-
if (
|
|
36427
|
+
const dir = path39.dirname(fs35.realpathSync(p));
|
|
36428
|
+
const cli = path39.join(dir, "cli.mjs");
|
|
36429
|
+
if (fs35.existsSync(cli))
|
|
36175
36430
|
return cli;
|
|
36176
|
-
const cli2 =
|
|
36177
|
-
if (
|
|
36431
|
+
const cli2 = path39.resolve(dir, "../dist/cli.mjs");
|
|
36432
|
+
if (fs35.existsSync(cli2))
|
|
36178
36433
|
return cli2;
|
|
36179
36434
|
if (head.includes("import") || head.includes("commander"))
|
|
36180
36435
|
return p;
|
|
@@ -36186,9 +36441,9 @@ function findEntry() {
|
|
|
36186
36441
|
}
|
|
36187
36442
|
try {
|
|
36188
36443
|
const thisPath = fileURLToPath4(import.meta.url);
|
|
36189
|
-
const pkgRoot =
|
|
36190
|
-
const cli =
|
|
36191
|
-
if (
|
|
36444
|
+
const pkgRoot = path39.resolve(path39.dirname(thisPath), "../..");
|
|
36445
|
+
const cli = path39.join(pkgRoot, "dist", "cli.mjs");
|
|
36446
|
+
if (fs35.existsSync(cli))
|
|
36192
36447
|
return cli;
|
|
36193
36448
|
} catch {}
|
|
36194
36449
|
return null;
|
|
@@ -36292,7 +36547,7 @@ init_deps();
|
|
|
36292
36547
|
import readline3 from "readline";
|
|
36293
36548
|
init_path_safety();
|
|
36294
36549
|
init_stack();
|
|
36295
|
-
import
|
|
36550
|
+
import fs36 from "fs";
|
|
36296
36551
|
async function runMcpServer(opts = {}) {
|
|
36297
36552
|
const input = opts.input ?? process.stdin;
|
|
36298
36553
|
const output = opts.output ?? process.stdout;
|
|
@@ -36475,7 +36730,7 @@ async function handleToolCall(name, args, config2, _opts) {
|
|
|
36475
36730
|
for (const wt of wts) {
|
|
36476
36731
|
if (!wt.path.startsWith(repo.wtRoot))
|
|
36477
36732
|
continue;
|
|
36478
|
-
const dirtyCount =
|
|
36733
|
+
const dirtyCount = fs36.existsSync(wt.path) ? (await getDirtyFiles(wt.path)).length : 0;
|
|
36479
36734
|
items.push({
|
|
36480
36735
|
repo: repo.name,
|
|
36481
36736
|
branch: wt.branch || null,
|
|
@@ -36503,7 +36758,7 @@ async function handleToolCall(name, args, config2, _opts) {
|
|
|
36503
36758
|
}
|
|
36504
36759
|
const repo = resolveRepos(config2, [args.repo])[0];
|
|
36505
36760
|
const wtPath = getWorktreePath(repo, args.branch);
|
|
36506
|
-
if (!
|
|
36761
|
+
if (!fs36.existsSync(wtPath)) {
|
|
36507
36762
|
throw { isToolError: true, message: `Worktree not found for branch ${args.branch}` };
|
|
36508
36763
|
}
|
|
36509
36764
|
const mainBranch = await resolveMainBranch(repo, config2);
|
|
@@ -36622,7 +36877,7 @@ async function handleToolCall(name, args, config2, _opts) {
|
|
|
36622
36877
|
if (children.length > 0 && args.force !== true) {
|
|
36623
36878
|
throw { isToolError: true, message: `Branch has dependent worktrees: ${children.join(", ")}. Use force:true to override.` };
|
|
36624
36879
|
}
|
|
36625
|
-
if (!args.force &&
|
|
36880
|
+
if (!args.force && fs36.existsSync(wtPath)) {
|
|
36626
36881
|
const dirty = await getDirtyFiles(wtPath);
|
|
36627
36882
|
if (dirty.length > 0) {
|
|
36628
36883
|
throw { isToolError: true, message: `Worktree is dirty. Use force:true to remove it.` };
|
|
@@ -36641,7 +36896,7 @@ async function handleToolCall(name, args, config2, _opts) {
|
|
|
36641
36896
|
}
|
|
36642
36897
|
const repo = resolveRepos(config2, [args.repo])[0];
|
|
36643
36898
|
const wtPath = getWorktreePath(repo, args.branch);
|
|
36644
|
-
if (!
|
|
36899
|
+
if (!fs36.existsSync(wtPath)) {
|
|
36645
36900
|
throw { isToolError: true, message: `Worktree not found for branch ${args.branch}` };
|
|
36646
36901
|
}
|
|
36647
36902
|
const mainBranch = await resolveMainBranch(repo, config2);
|
|
@@ -36863,8 +37118,8 @@ init_config();
|
|
|
36863
37118
|
init_log();
|
|
36864
37119
|
init_git();
|
|
36865
37120
|
init_resolver();
|
|
36866
|
-
import
|
|
36867
|
-
import
|
|
37121
|
+
import fs37 from "fs";
|
|
37122
|
+
import path40 from "path";
|
|
36868
37123
|
init_workspace();
|
|
36869
37124
|
var DEPS_STRATEGIES2 = ["auto", "link", "symlink", "install", "off"];
|
|
36870
37125
|
function errorMessage4(err) {
|
|
@@ -36874,7 +37129,7 @@ function workspaceRootFor(config2) {
|
|
|
36874
37129
|
return getWorkspaceRoot(config2);
|
|
36875
37130
|
}
|
|
36876
37131
|
function workspacePathFor2(config2, name) {
|
|
36877
|
-
return
|
|
37132
|
+
return path40.join(workspaceRootFor(config2), name);
|
|
36878
37133
|
}
|
|
36879
37134
|
async function resolveWorktreePathForMember(config2, repoName, branch) {
|
|
36880
37135
|
const repos = resolveRepos(config2, [repoName]);
|
|
@@ -36886,7 +37141,7 @@ async function resolveWorktreePathForMember(config2, repoName, branch) {
|
|
|
36886
37141
|
if (match)
|
|
36887
37142
|
return match.path;
|
|
36888
37143
|
const candidate = getWorktreePath(repo, branch);
|
|
36889
|
-
if (
|
|
37144
|
+
if (fs37.existsSync(candidate))
|
|
36890
37145
|
return candidate;
|
|
36891
37146
|
return null;
|
|
36892
37147
|
}
|
|
@@ -36944,7 +37199,7 @@ function registerCreateSub(workspace) {
|
|
|
36944
37199
|
process.exit(1);
|
|
36945
37200
|
}
|
|
36946
37201
|
const wsPath = workspacePathFor2(config2, name);
|
|
36947
|
-
if (
|
|
37202
|
+
if (fs37.existsSync(wsPath)) {
|
|
36948
37203
|
stepError("Workspace already exists", wsPath);
|
|
36949
37204
|
process.exit(1);
|
|
36950
37205
|
}
|
|
@@ -37045,7 +37300,7 @@ function registerAddSub(workspace) {
|
|
|
37045
37300
|
const globalOpts = workspace.parent.opts();
|
|
37046
37301
|
const config2 = loadConfig();
|
|
37047
37302
|
const wsPath = workspacePathFor2(config2, name);
|
|
37048
|
-
if (!
|
|
37303
|
+
if (!fs37.existsSync(wsPath)) {
|
|
37049
37304
|
stepError("Workspace not found", wsPath);
|
|
37050
37305
|
process.exit(1);
|
|
37051
37306
|
}
|
|
@@ -37081,7 +37336,7 @@ function registerRmSub(workspace) {
|
|
|
37081
37336
|
const globalOpts = workspace.parent.opts();
|
|
37082
37337
|
const config2 = loadConfig();
|
|
37083
37338
|
const wsPath = workspacePathFor2(config2, name);
|
|
37084
|
-
if (!
|
|
37339
|
+
if (!fs37.existsSync(wsPath)) {
|
|
37085
37340
|
stepError("Workspace not found", wsPath);
|
|
37086
37341
|
process.exit(1);
|
|
37087
37342
|
}
|
|
@@ -37103,7 +37358,7 @@ function registerRemoveSub(workspace) {
|
|
|
37103
37358
|
const globalOpts = workspace.parent.opts();
|
|
37104
37359
|
const config2 = loadConfig();
|
|
37105
37360
|
const wsPath = workspacePathFor2(config2, name);
|
|
37106
|
-
if (!
|
|
37361
|
+
if (!fs37.existsSync(wsPath)) {
|
|
37107
37362
|
stepError("Workspace not found", wsPath);
|
|
37108
37363
|
process.exit(1);
|
|
37109
37364
|
}
|
|
@@ -37117,7 +37372,7 @@ function registerRemoveSub(workspace) {
|
|
|
37117
37372
|
return;
|
|
37118
37373
|
}
|
|
37119
37374
|
try {
|
|
37120
|
-
|
|
37375
|
+
fs37.rmSync(wsPath, { recursive: true, force: true });
|
|
37121
37376
|
stepSuccess("Workspace removed", wsPath);
|
|
37122
37377
|
summary(`Done — workspace ${name} deleted (member worktrees preserved)`);
|
|
37123
37378
|
} catch (err) {
|
|
@@ -37130,7 +37385,7 @@ function registerVerifySub(workspace) {
|
|
|
37130
37385
|
workspace.command("verify <name>").description("Verify that every workspace member link resolves").action(async (name) => {
|
|
37131
37386
|
const config2 = loadConfig();
|
|
37132
37387
|
const wsPath = workspacePathFor2(config2, name);
|
|
37133
|
-
if (!
|
|
37388
|
+
if (!fs37.existsSync(wsPath)) {
|
|
37134
37389
|
stepError("Workspace not found", wsPath);
|
|
37135
37390
|
process.exit(1);
|
|
37136
37391
|
}
|
|
@@ -37165,7 +37420,7 @@ init_config();
|
|
|
37165
37420
|
init_resolver();
|
|
37166
37421
|
init_log();
|
|
37167
37422
|
init_history();
|
|
37168
|
-
import
|
|
37423
|
+
import fs38 from "fs";
|
|
37169
37424
|
var program2 = new Command;
|
|
37170
37425
|
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);
|
|
37171
37426
|
var MUTATING_COMMANDS = new Set([
|
|
@@ -37275,7 +37530,7 @@ program2.command("_resolve-path <repo> <branch>", { hidden: true }).description(
|
|
|
37275
37530
|
}
|
|
37276
37531
|
const repo = repos[0];
|
|
37277
37532
|
const wtPath = getWorktreePath(repo, branch);
|
|
37278
|
-
if (!
|
|
37533
|
+
if (!fs38.existsSync(wtPath)) {
|
|
37279
37534
|
process.stderr.write(`✗ No worktree at ${wtPath}
|
|
37280
37535
|
`);
|
|
37281
37536
|
process.exit(1);
|