git-sync-tui 0.1.2 → 0.1.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.js +551 -296
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -1,17 +1,113 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
+
}) : x)(function(x) {
|
|
5
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
6
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
+
});
|
|
2
8
|
|
|
3
9
|
// src/cli.tsx
|
|
4
10
|
import { render } from "ink";
|
|
5
11
|
import meow from "meow";
|
|
6
12
|
|
|
7
13
|
// src/app.tsx
|
|
8
|
-
import { useState as
|
|
9
|
-
import { Box as
|
|
10
|
-
import { Spinner as
|
|
14
|
+
import { useState as useState7, useEffect as useEffect4, useRef as useRef2, useCallback as useCallback2 } from "react";
|
|
15
|
+
import { Box as Box9, useApp } from "ink";
|
|
16
|
+
import { Spinner as Spinner6 } from "@inkjs/ui";
|
|
11
17
|
|
|
12
|
-
// src/components/
|
|
13
|
-
import
|
|
18
|
+
// src/components/ui.tsx
|
|
19
|
+
import React from "react";
|
|
20
|
+
import { Box, Text } from "ink";
|
|
14
21
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
22
|
+
var STEP_LABELS = ["Remote", "Branch", "Commits", "Confirm", "Sync"];
|
|
23
|
+
function StepProgress({ current }) {
|
|
24
|
+
return /* @__PURE__ */ jsx(Box, { children: STEP_LABELS.map((label, i) => {
|
|
25
|
+
const step = i + 1;
|
|
26
|
+
const isActive = step === current;
|
|
27
|
+
const isDone = step < current;
|
|
28
|
+
const isLast = i === STEP_LABELS.length - 1;
|
|
29
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
30
|
+
/* @__PURE__ */ jsxs(Text, { color: isActive ? "cyan" : isDone ? "green" : "gray", dimColor: !isActive && !isDone, children: [
|
|
31
|
+
isDone ? "\u25CF" : isActive ? "\u25C6" : "\u25CB",
|
|
32
|
+
" ",
|
|
33
|
+
isActive ? /* @__PURE__ */ jsx(Text, { bold: true, children: label }) : label
|
|
34
|
+
] }),
|
|
35
|
+
!isLast && /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: " \u2500 " })
|
|
36
|
+
] }, label);
|
|
37
|
+
}) });
|
|
38
|
+
}
|
|
39
|
+
function SectionHeader({ title, subtitle }) {
|
|
40
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
41
|
+
/* @__PURE__ */ jsxs(Text, { bold: true, color: "cyan", children: [
|
|
42
|
+
"\u25B8 ",
|
|
43
|
+
title
|
|
44
|
+
] }),
|
|
45
|
+
subtitle && /* @__PURE__ */ jsxs(Text, { color: "gray", dimColor: true, children: [
|
|
46
|
+
" ",
|
|
47
|
+
subtitle
|
|
48
|
+
] })
|
|
49
|
+
] });
|
|
50
|
+
}
|
|
51
|
+
function KeyHints({ hints }) {
|
|
52
|
+
return /* @__PURE__ */ jsx(Box, { gap: 1, flexWrap: "wrap", children: hints.map(({ key, label }) => /* @__PURE__ */ jsxs(Box, { children: [
|
|
53
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "[" }),
|
|
54
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", children: key }),
|
|
55
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "]" }),
|
|
56
|
+
/* @__PURE__ */ jsxs(Text, { color: "gray", dimColor: true, children: [
|
|
57
|
+
" ",
|
|
58
|
+
label
|
|
59
|
+
] })
|
|
60
|
+
] }, key)) });
|
|
61
|
+
}
|
|
62
|
+
function InlineKeys({ hints }) {
|
|
63
|
+
return /* @__PURE__ */ jsx(Box, { gap: 1, children: hints.map(({ key, label }, i) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
64
|
+
/* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
65
|
+
"[",
|
|
66
|
+
key,
|
|
67
|
+
"]"
|
|
68
|
+
] }),
|
|
69
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
70
|
+
" ",
|
|
71
|
+
label
|
|
72
|
+
] }),
|
|
73
|
+
i < hints.length - 1 && /* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: " / " })
|
|
74
|
+
] }, key)) });
|
|
75
|
+
}
|
|
76
|
+
var PANEL_CONFIG = {
|
|
77
|
+
info: { icon: "\u25C6", color: "cyan", borderColor: "cyan" },
|
|
78
|
+
warn: { icon: "\u25B2", color: "yellow", borderColor: "yellow" },
|
|
79
|
+
error: { icon: "\u2716", color: "red", borderColor: "red" },
|
|
80
|
+
success: { icon: "\u2714", color: "green", borderColor: "green" }
|
|
81
|
+
};
|
|
82
|
+
function StatusPanel({ type, title, children }) {
|
|
83
|
+
const { icon, color, borderColor } = PANEL_CONFIG[type];
|
|
84
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor, paddingX: 1, children: [
|
|
85
|
+
/* @__PURE__ */ jsxs(Text, { bold: true, color, children: [
|
|
86
|
+
icon,
|
|
87
|
+
" ",
|
|
88
|
+
title
|
|
89
|
+
] }),
|
|
90
|
+
children
|
|
91
|
+
] });
|
|
92
|
+
}
|
|
93
|
+
function AppHeader({ step, stashed }) {
|
|
94
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
95
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
96
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "\u25C7 " }),
|
|
97
|
+
/* @__PURE__ */ jsx(Text, { bold: true, children: "git-sync-tui" }),
|
|
98
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: " cherry-pick --no-commit" }),
|
|
99
|
+
stashed && /* @__PURE__ */ jsx(Text, { color: "yellow", children: " \u25AA stashed" })
|
|
100
|
+
] }),
|
|
101
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
102
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: " " }),
|
|
103
|
+
/* @__PURE__ */ jsx(StepProgress, { current: step })
|
|
104
|
+
] })
|
|
105
|
+
] });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// src/components/stash-prompt.tsx
|
|
109
|
+
import { Box as Box2, Text as Text2, useInput } from "ink";
|
|
110
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
15
111
|
function StashPrompt({ onConfirm, onSkip }) {
|
|
16
112
|
useInput((input) => {
|
|
17
113
|
if (input === "y" || input === "Y") {
|
|
@@ -20,31 +116,27 @@ function StashPrompt({ onConfirm, onSkip }) {
|
|
|
20
116
|
onSkip();
|
|
21
117
|
}
|
|
22
118
|
});
|
|
23
|
-
return /* @__PURE__ */
|
|
24
|
-
/* @__PURE__ */
|
|
25
|
-
|
|
26
|
-
/* @__PURE__ */
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
/* @__PURE__ */ jsx(Text, { children: " \u662F / " }),
|
|
32
|
-
/* @__PURE__ */ jsx(Text, { color: "red", children: "[n]" }),
|
|
33
|
-
/* @__PURE__ */ jsx(Text, { children: " \u5426\uFF0C\u7EE7\u7EED\u64CD\u4F5C" })
|
|
119
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", gap: 1, children: [
|
|
120
|
+
/* @__PURE__ */ jsx2(StatusPanel, { type: "warn", title: "\u5DE5\u4F5C\u533A\u6709\u672A\u63D0\u4EA4\u7684\u53D8\u66F4", children: /* @__PURE__ */ jsx2(Text2, { color: "gray", children: " Cherry-pick \u64CD\u4F5C\u53EF\u80FD\u4F1A\u4E0E\u672A\u63D0\u4EA4\u7684\u5185\u5BB9\u51B2\u7A81" }) }),
|
|
121
|
+
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
122
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, children: "\u81EA\u52A8 stash \u4FDD\u5B58\u5F53\u524D\u53D8\u66F4? " }),
|
|
123
|
+
/* @__PURE__ */ jsx2(InlineKeys, { hints: [
|
|
124
|
+
{ key: "y", label: "\u662F" },
|
|
125
|
+
{ key: "n", label: "\u5426\uFF0C\u7EE7\u7EED" }
|
|
126
|
+
] })
|
|
34
127
|
] })
|
|
35
128
|
] });
|
|
36
129
|
}
|
|
37
130
|
|
|
38
|
-
// src/components/
|
|
39
|
-
import { useState
|
|
40
|
-
import { Box as
|
|
41
|
-
import {
|
|
42
|
-
|
|
43
|
-
// src/hooks/use-git.ts
|
|
44
|
-
import { useState, useEffect, useCallback } from "react";
|
|
131
|
+
// src/components/stash-recovery.tsx
|
|
132
|
+
import { useState, useEffect } from "react";
|
|
133
|
+
import { Box as Box3, Text as Text3, useInput as useInput2 } from "ink";
|
|
134
|
+
import { Spinner } from "@inkjs/ui";
|
|
45
135
|
|
|
46
136
|
// src/utils/git.ts
|
|
47
137
|
import simpleGit from "simple-git";
|
|
138
|
+
import { existsSync, writeFileSync, unlinkSync, readFileSync } from "fs";
|
|
139
|
+
import { join } from "path";
|
|
48
140
|
var gitInstance = null;
|
|
49
141
|
function getGit(cwd) {
|
|
50
142
|
if (!gitInstance || cwd) {
|
|
@@ -183,10 +275,115 @@ async function stashPop() {
|
|
|
183
275
|
return false;
|
|
184
276
|
}
|
|
185
277
|
}
|
|
278
|
+
var STASH_GUARD_FILE = "git-sync-tui-stash-guard";
|
|
279
|
+
async function getGitDir() {
|
|
280
|
+
const git = getGit();
|
|
281
|
+
const dir = await git.revparse(["--git-dir"]);
|
|
282
|
+
return dir.trim();
|
|
283
|
+
}
|
|
284
|
+
async function writeStashGuard() {
|
|
285
|
+
try {
|
|
286
|
+
const gitDir = await getGitDir();
|
|
287
|
+
writeFileSync(join(gitDir, STASH_GUARD_FILE), (/* @__PURE__ */ new Date()).toISOString(), "utf-8");
|
|
288
|
+
} catch {
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
async function removeStashGuard() {
|
|
292
|
+
try {
|
|
293
|
+
const gitDir = await getGitDir();
|
|
294
|
+
const guardPath = join(gitDir, STASH_GUARD_FILE);
|
|
295
|
+
if (existsSync(guardPath)) {
|
|
296
|
+
unlinkSync(guardPath);
|
|
297
|
+
}
|
|
298
|
+
} catch {
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
function removeStashGuardSync() {
|
|
302
|
+
try {
|
|
303
|
+
const { execSync: execSync2 } = __require("child_process");
|
|
304
|
+
const gitDir = String(execSync2("git rev-parse --git-dir", { encoding: "utf-8" })).trim();
|
|
305
|
+
const guardPath = join(gitDir, STASH_GUARD_FILE);
|
|
306
|
+
if (existsSync(guardPath)) {
|
|
307
|
+
unlinkSync(guardPath);
|
|
308
|
+
}
|
|
309
|
+
} catch {
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
async function checkStashGuard() {
|
|
313
|
+
try {
|
|
314
|
+
const gitDir = await getGitDir();
|
|
315
|
+
const guardPath = join(gitDir, STASH_GUARD_FILE);
|
|
316
|
+
if (existsSync(guardPath)) {
|
|
317
|
+
const timestamp = readFileSync(guardPath, "utf-8").trim();
|
|
318
|
+
return { exists: true, timestamp };
|
|
319
|
+
}
|
|
320
|
+
} catch {
|
|
321
|
+
}
|
|
322
|
+
return { exists: false };
|
|
323
|
+
}
|
|
324
|
+
async function findStashEntry() {
|
|
325
|
+
const git = getGit();
|
|
326
|
+
try {
|
|
327
|
+
const result = await git.stash(["list"]);
|
|
328
|
+
const lines = result.trim().split("\n");
|
|
329
|
+
for (const line of lines) {
|
|
330
|
+
if (line.includes("Auto-stash by git-sync-tui")) {
|
|
331
|
+
return line;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
} catch {
|
|
335
|
+
}
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// src/components/stash-recovery.tsx
|
|
340
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
341
|
+
function StashRecovery({ timestamp, onRecover, onSkip }) {
|
|
342
|
+
const [stashEntry, setStashEntry] = useState(void 0);
|
|
343
|
+
useEffect(() => {
|
|
344
|
+
findStashEntry().then(setStashEntry);
|
|
345
|
+
}, []);
|
|
346
|
+
useInput2((input) => {
|
|
347
|
+
if (input === "y" || input === "Y") {
|
|
348
|
+
onRecover();
|
|
349
|
+
} else if (input === "n" || input === "N") {
|
|
350
|
+
onSkip();
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
if (stashEntry === void 0) {
|
|
354
|
+
return /* @__PURE__ */ jsx3(Spinner, { label: "\u68C0\u67E5 stash \u8BB0\u5F55..." });
|
|
355
|
+
}
|
|
356
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", gap: 1, children: [
|
|
357
|
+
/* @__PURE__ */ jsxs3(StatusPanel, { type: "warn", title: "\u68C0\u6D4B\u5230\u4E0A\u6B21\u8FD0\u884C\u4E2D\u65AD", children: [
|
|
358
|
+
timestamp && /* @__PURE__ */ jsxs3(Text3, { color: "gray", children: [
|
|
359
|
+
" \u4E2D\u65AD\u65F6\u95F4: ",
|
|
360
|
+
timestamp
|
|
361
|
+
] }),
|
|
362
|
+
stashEntry && /* @__PURE__ */ jsxs3(Text3, { color: "gray", children: [
|
|
363
|
+
" Stash: ",
|
|
364
|
+
stashEntry
|
|
365
|
+
] }),
|
|
366
|
+
!stashEntry && /* @__PURE__ */ jsx3(Text3, { color: "red", children: " \u672A\u627E\u5230\u5BF9\u5E94\u7684 stash \u6761\u76EE\uFF08\u53EF\u80FD\u5DF2\u624B\u52A8\u6062\u590D\uFF09" })
|
|
367
|
+
] }),
|
|
368
|
+
/* @__PURE__ */ jsxs3(Box3, { children: [
|
|
369
|
+
/* @__PURE__ */ jsx3(Text3, { bold: true, children: stashEntry ? "\u6062\u590D stash? " : "\u6E05\u9664\u4E2D\u65AD\u6807\u8BB0? " }),
|
|
370
|
+
/* @__PURE__ */ jsx3(InlineKeys, { hints: [
|
|
371
|
+
{ key: "y", label: "\u662F" },
|
|
372
|
+
{ key: "n", label: "\u8DF3\u8FC7" }
|
|
373
|
+
] })
|
|
374
|
+
] })
|
|
375
|
+
] });
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// src/components/remote-select.tsx
|
|
379
|
+
import { useState as useState3 } from "react";
|
|
380
|
+
import { Box as Box4, Text as Text4, useInput as useInput3 } from "ink";
|
|
381
|
+
import { Select, Spinner as Spinner2, TextInput } from "@inkjs/ui";
|
|
186
382
|
|
|
187
383
|
// src/hooks/use-git.ts
|
|
384
|
+
import { useState as useState2, useEffect as useEffect2, useCallback } from "react";
|
|
188
385
|
function useAsync(fn, deps = []) {
|
|
189
|
-
const [state, setState] =
|
|
386
|
+
const [state, setState] = useState2({
|
|
190
387
|
data: null,
|
|
191
388
|
loading: true,
|
|
192
389
|
error: null
|
|
@@ -200,7 +397,7 @@ function useAsync(fn, deps = []) {
|
|
|
200
397
|
setState({ data: null, loading: false, error: err.message });
|
|
201
398
|
}
|
|
202
399
|
}, deps);
|
|
203
|
-
|
|
400
|
+
useEffect2(() => {
|
|
204
401
|
load();
|
|
205
402
|
}, [load]);
|
|
206
403
|
return { ...state, reload: load };
|
|
@@ -221,9 +418,9 @@ function useCommits(remote, branch, count = 30) {
|
|
|
221
418
|
);
|
|
222
419
|
}
|
|
223
420
|
function useCommitStat(hashes) {
|
|
224
|
-
const [stat, setStat] =
|
|
225
|
-
const [loading, setLoading] =
|
|
226
|
-
|
|
421
|
+
const [stat, setStat] = useState2("");
|
|
422
|
+
const [loading, setLoading] = useState2(false);
|
|
423
|
+
useEffect2(() => {
|
|
227
424
|
if (hashes.length === 0) {
|
|
228
425
|
setStat("");
|
|
229
426
|
return;
|
|
@@ -241,31 +438,50 @@ function useCommitStat(hashes) {
|
|
|
241
438
|
}
|
|
242
439
|
|
|
243
440
|
// src/components/remote-select.tsx
|
|
244
|
-
import { jsx as
|
|
245
|
-
function
|
|
441
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
442
|
+
function extractRemoteName(url) {
|
|
443
|
+
const trimmed = url.trim().replace(/\/+$/, "").replace(/\.git$/, "");
|
|
444
|
+
const lastSegment = trimmed.split(/[/\\:]+/).filter(Boolean).pop() || "";
|
|
445
|
+
return lastSegment;
|
|
446
|
+
}
|
|
447
|
+
function RemoteSelect({ onSelect, onBack }) {
|
|
246
448
|
const { data: remotes, loading, error, reload } = useRemotes();
|
|
247
|
-
const [phase, setPhase] =
|
|
248
|
-
const [customUrl, setCustomUrl] =
|
|
249
|
-
const [addError, setAddError] =
|
|
449
|
+
const [phase, setPhase] = useState3("list");
|
|
450
|
+
const [customUrl, setCustomUrl] = useState3("");
|
|
451
|
+
const [addError, setAddError] = useState3(null);
|
|
452
|
+
useInput3((_input, key) => {
|
|
453
|
+
if (key.escape) {
|
|
454
|
+
if (phase === "input-name") {
|
|
455
|
+
setPhase("input-url");
|
|
456
|
+
} else if (phase === "input-url") {
|
|
457
|
+
setPhase("list");
|
|
458
|
+
} else if (phase === "list") {
|
|
459
|
+
onBack?.();
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
});
|
|
250
463
|
if (loading) {
|
|
251
|
-
return /* @__PURE__ */
|
|
464
|
+
return /* @__PURE__ */ jsx4(Spinner2, { label: "\u83B7\u53D6\u8FDC\u7A0B\u4ED3\u5E93..." });
|
|
252
465
|
}
|
|
253
466
|
if (error) {
|
|
254
|
-
return /* @__PURE__ */
|
|
255
|
-
"\u83B7\u53D6\u8FDC\u7A0B\u4ED3\u5E93\u5931\u8D25: ",
|
|
467
|
+
return /* @__PURE__ */ jsxs4(Text4, { color: "red", children: [
|
|
468
|
+
"\u2716 \u83B7\u53D6\u8FDC\u7A0B\u4ED3\u5E93\u5931\u8D25: ",
|
|
256
469
|
error
|
|
257
470
|
] });
|
|
258
471
|
}
|
|
259
472
|
if (phase === "adding") {
|
|
260
|
-
return /* @__PURE__ */
|
|
473
|
+
return /* @__PURE__ */ jsx4(Spinner2, { label: "\u6DFB\u52A0\u8FDC\u7A0B\u4ED3\u5E93..." });
|
|
261
474
|
}
|
|
262
475
|
if (phase === "input-url") {
|
|
263
|
-
return /* @__PURE__ */
|
|
264
|
-
/* @__PURE__ */
|
|
265
|
-
addError && /* @__PURE__ */
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
476
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", gap: 1, children: [
|
|
477
|
+
/* @__PURE__ */ jsx4(SectionHeader, { title: "\u6DFB\u52A0\u8FDC\u7A0B\u4ED3\u5E93" }),
|
|
478
|
+
addError && /* @__PURE__ */ jsxs4(Text4, { color: "red", children: [
|
|
479
|
+
"\u2716 ",
|
|
480
|
+
addError
|
|
481
|
+
] }),
|
|
482
|
+
/* @__PURE__ */ jsxs4(Box4, { children: [
|
|
483
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray", children: "URL \u25B8 " }),
|
|
484
|
+
/* @__PURE__ */ jsx4(
|
|
269
485
|
TextInput,
|
|
270
486
|
{
|
|
271
487
|
placeholder: "https://github.com/user/repo.git",
|
|
@@ -280,23 +496,24 @@ function RemoteSelect({ onSelect }) {
|
|
|
280
496
|
}
|
|
281
497
|
)
|
|
282
498
|
] }),
|
|
283
|
-
/* @__PURE__ */
|
|
499
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray", dimColor: true, children: " \u652F\u6301 HTTPS / SSH \u5730\u5740" })
|
|
284
500
|
] });
|
|
285
501
|
}
|
|
286
502
|
if (phase === "input-name") {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
/* @__PURE__ */
|
|
290
|
-
|
|
291
|
-
|
|
503
|
+
const defaultName = extractRemoteName(customUrl);
|
|
504
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", gap: 1, children: [
|
|
505
|
+
/* @__PURE__ */ jsx4(SectionHeader, { title: "\u6DFB\u52A0\u8FDC\u7A0B\u4ED3\u5E93", subtitle: customUrl }),
|
|
506
|
+
addError && /* @__PURE__ */ jsxs4(Text4, { color: "red", children: [
|
|
507
|
+
"\u2716 ",
|
|
508
|
+
addError
|
|
292
509
|
] }),
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
/* @__PURE__ */
|
|
296
|
-
/* @__PURE__ */ jsx2(
|
|
510
|
+
/* @__PURE__ */ jsxs4(Box4, { children: [
|
|
511
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray", children: "\u540D\u79F0 \u25B8 " }),
|
|
512
|
+
/* @__PURE__ */ jsx4(
|
|
297
513
|
TextInput,
|
|
298
514
|
{
|
|
299
|
-
placeholder: "upstream",
|
|
515
|
+
placeholder: defaultName || "upstream",
|
|
516
|
+
defaultValue: defaultName,
|
|
300
517
|
onSubmit: async (name) => {
|
|
301
518
|
const remoteName = name.trim();
|
|
302
519
|
if (!remoteName) {
|
|
@@ -333,9 +550,9 @@ function RemoteSelect({ onSelect }) {
|
|
|
333
550
|
value: "__add_custom__"
|
|
334
551
|
}
|
|
335
552
|
];
|
|
336
|
-
return /* @__PURE__ */
|
|
337
|
-
/* @__PURE__ */
|
|
338
|
-
/* @__PURE__ */
|
|
553
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", gap: 1, children: [
|
|
554
|
+
/* @__PURE__ */ jsx4(SectionHeader, { title: "\u9009\u62E9\u8FDC\u7A0B\u4ED3\u5E93" }),
|
|
555
|
+
/* @__PURE__ */ jsx4(
|
|
339
556
|
Select,
|
|
340
557
|
{
|
|
341
558
|
options,
|
|
@@ -352,66 +569,63 @@ function RemoteSelect({ onSelect }) {
|
|
|
352
569
|
}
|
|
353
570
|
|
|
354
571
|
// src/components/branch-select.tsx
|
|
355
|
-
import { useState as
|
|
356
|
-
import { Box as
|
|
357
|
-
import { Select as Select2, Spinner as
|
|
358
|
-
import { jsx as
|
|
359
|
-
function BranchSelect({ remote, onSelect }) {
|
|
572
|
+
import { useState as useState4, useMemo } from "react";
|
|
573
|
+
import { Box as Box5, Text as Text5, useInput as useInput4 } from "ink";
|
|
574
|
+
import { Select as Select2, Spinner as Spinner3, TextInput as TextInput2 } from "@inkjs/ui";
|
|
575
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
576
|
+
function BranchSelect({ remote, onSelect, onBack }) {
|
|
360
577
|
const { data: branches, loading, error } = useBranches(remote);
|
|
361
|
-
const [filter, setFilter] =
|
|
578
|
+
const [filter, setFilter] = useState4("");
|
|
579
|
+
useInput4((_input, key) => {
|
|
580
|
+
if (key.escape) onBack?.();
|
|
581
|
+
});
|
|
362
582
|
const filteredOptions = useMemo(() => {
|
|
363
583
|
if (!branches) return [];
|
|
364
584
|
const filtered = filter ? branches.filter((b) => b.toLowerCase().includes(filter.toLowerCase())) : branches;
|
|
365
585
|
return filtered.map((b) => ({ label: b, value: b }));
|
|
366
586
|
}, [branches, filter]);
|
|
367
587
|
if (loading) {
|
|
368
|
-
return /* @__PURE__ */
|
|
588
|
+
return /* @__PURE__ */ jsx5(Spinner3, { label: `\u83B7\u53D6 ${remote} \u7684\u5206\u652F\u5217\u8868...` });
|
|
369
589
|
}
|
|
370
590
|
if (error) {
|
|
371
|
-
return /* @__PURE__ */
|
|
372
|
-
"\u83B7\u53D6\u5206\u652F\u5217\u8868\u5931\u8D25: ",
|
|
591
|
+
return /* @__PURE__ */ jsxs5(Text5, { color: "red", children: [
|
|
592
|
+
"\u2716 \u83B7\u53D6\u5206\u652F\u5217\u8868\u5931\u8D25: ",
|
|
373
593
|
error
|
|
374
594
|
] });
|
|
375
595
|
}
|
|
376
596
|
if (!branches || branches.length === 0) {
|
|
377
|
-
return /* @__PURE__ */
|
|
597
|
+
return /* @__PURE__ */ jsx5(Text5, { color: "red", children: "\u2716 \u672A\u627E\u5230\u8FDC\u7A0B\u5206\u652F" });
|
|
378
598
|
}
|
|
379
|
-
return /* @__PURE__ */
|
|
380
|
-
/* @__PURE__ */
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
] }),
|
|
385
|
-
/* @__PURE__ */ jsxs3(Box3, { children: [
|
|
386
|
-
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: "\u641C\u7D22: " }),
|
|
387
|
-
/* @__PURE__ */ jsx3(
|
|
599
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", gap: 1, children: [
|
|
600
|
+
/* @__PURE__ */ jsx5(SectionHeader, { title: `\u9009\u62E9\u5206\u652F`, subtitle: `${remote} \xB7 ${branches.length} \u4E2A\u5206\u652F` }),
|
|
601
|
+
/* @__PURE__ */ jsxs5(Box5, { children: [
|
|
602
|
+
/* @__PURE__ */ jsx5(Text5, { color: "gray", children: "/ " }),
|
|
603
|
+
/* @__PURE__ */ jsx5(
|
|
388
604
|
TextInput2,
|
|
389
605
|
{
|
|
390
|
-
placeholder: "\u8F93\u5165\u5173\u952E\u5B57\u8FC7\u6EE4
|
|
606
|
+
placeholder: "\u8F93\u5165\u5173\u952E\u5B57\u8FC7\u6EE4...",
|
|
391
607
|
onChange: setFilter
|
|
392
608
|
}
|
|
393
|
-
)
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
" \u4E2A\u5206\u652F",
|
|
399
|
-
filter ? `\uFF0C\u5339\u914D ${filteredOptions.length} \u4E2A` : ""
|
|
609
|
+
),
|
|
610
|
+
filter && /* @__PURE__ */ jsxs5(Text5, { color: "gray", dimColor: true, children: [
|
|
611
|
+
" \xB7 \u5339\u914D ",
|
|
612
|
+
filteredOptions.length
|
|
613
|
+
] })
|
|
400
614
|
] }),
|
|
401
|
-
filteredOptions.length > 0 ? /* @__PURE__ */
|
|
615
|
+
filteredOptions.length > 0 ? /* @__PURE__ */ jsx5(Select2, { options: filteredOptions, onChange: onSelect }) : /* @__PURE__ */ jsx5(Text5, { color: "yellow", children: "\u25B2 \u65E0\u5339\u914D\u5206\u652F" })
|
|
402
616
|
] });
|
|
403
617
|
}
|
|
404
618
|
|
|
405
619
|
// src/components/commit-list.tsx
|
|
406
|
-
import { useState as
|
|
407
|
-
import { Box as
|
|
408
|
-
import { Spinner as
|
|
409
|
-
import { jsx as
|
|
410
|
-
function CommitList({ remote, branch, onSelect }) {
|
|
620
|
+
import { useState as useState5, useMemo as useMemo2, useRef } from "react";
|
|
621
|
+
import { Box as Box6, Text as Text6, useInput as useInput5 } from "ink";
|
|
622
|
+
import { Spinner as Spinner4 } from "@inkjs/ui";
|
|
623
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
624
|
+
function CommitList({ remote, branch, onSelect, onBack }) {
|
|
411
625
|
const { data: commits, loading, error } = useCommits(remote, branch, 30);
|
|
412
|
-
const [selectedIndex, setSelectedIndex] =
|
|
413
|
-
const [selectedHashes, setSelectedHashes] =
|
|
414
|
-
const [shiftMode, setShiftMode] =
|
|
626
|
+
const [selectedIndex, setSelectedIndex] = useState5(0);
|
|
627
|
+
const [selectedHashes, setSelectedHashes] = useState5(/* @__PURE__ */ new Set());
|
|
628
|
+
const [shiftMode, setShiftMode] = useState5(false);
|
|
415
629
|
const anchorIndexRef = useRef(null);
|
|
416
630
|
const selectedKey = useMemo2(() => Array.from(selectedHashes).sort().join(","), [selectedHashes]);
|
|
417
631
|
const selectedArray = useMemo2(() => Array.from(selectedHashes), [selectedKey]);
|
|
@@ -458,9 +672,7 @@ function CommitList({ remote, branch, onSelect }) {
|
|
|
458
672
|
setSelectedHashes((prev) => {
|
|
459
673
|
const next = /* @__PURE__ */ new Set();
|
|
460
674
|
for (const c of commits) {
|
|
461
|
-
if (!prev.has(c.hash))
|
|
462
|
-
next.add(c.hash);
|
|
463
|
-
}
|
|
675
|
+
if (!prev.has(c.hash)) next.add(c.hash);
|
|
464
676
|
}
|
|
465
677
|
return next;
|
|
466
678
|
});
|
|
@@ -475,7 +687,7 @@ function CommitList({ remote, branch, onSelect }) {
|
|
|
475
687
|
return next;
|
|
476
688
|
});
|
|
477
689
|
};
|
|
478
|
-
|
|
690
|
+
useInput5((input, key) => {
|
|
479
691
|
if (!commits || commits.length === 0) return;
|
|
480
692
|
if (key.shift) {
|
|
481
693
|
if (!shiftMode) {
|
|
@@ -501,9 +713,7 @@ function CommitList({ remote, branch, onSelect }) {
|
|
|
501
713
|
}
|
|
502
714
|
return;
|
|
503
715
|
}
|
|
504
|
-
if (shiftMode)
|
|
505
|
-
setShiftMode(false);
|
|
506
|
-
}
|
|
716
|
+
if (shiftMode) setShiftMode(false);
|
|
507
717
|
if (key.upArrow) {
|
|
508
718
|
setSelectedIndex((prev) => Math.max(0, prev - 1));
|
|
509
719
|
} else if (key.downArrow) {
|
|
@@ -516,6 +726,8 @@ function CommitList({ remote, branch, onSelect }) {
|
|
|
516
726
|
invertSelection();
|
|
517
727
|
} else if (input === "r" || input === "R") {
|
|
518
728
|
selectToCurrent();
|
|
729
|
+
} else if (key.escape) {
|
|
730
|
+
onBack?.();
|
|
519
731
|
} else if (key.return) {
|
|
520
732
|
if (selectedHashes.size > 0) {
|
|
521
733
|
onSelect(Array.from(selectedHashes), commits);
|
|
@@ -523,120 +735,96 @@ function CommitList({ remote, branch, onSelect }) {
|
|
|
523
735
|
}
|
|
524
736
|
});
|
|
525
737
|
if (loading) {
|
|
526
|
-
return /* @__PURE__ */
|
|
738
|
+
return /* @__PURE__ */ jsx6(Spinner4, { label: `\u83B7\u53D6 ${remote}/${branch} \u7684 commit \u5217\u8868...` });
|
|
527
739
|
}
|
|
528
740
|
if (error) {
|
|
529
|
-
return /* @__PURE__ */
|
|
530
|
-
"\u83B7\u53D6 commit \u5217\u8868\u5931\u8D25: ",
|
|
741
|
+
return /* @__PURE__ */ jsxs6(Text6, { color: "red", children: [
|
|
742
|
+
"\u2716 \u83B7\u53D6 commit \u5217\u8868\u5931\u8D25: ",
|
|
531
743
|
error
|
|
532
744
|
] });
|
|
533
745
|
}
|
|
534
746
|
if (!commits || commits.length === 0) {
|
|
535
|
-
return /* @__PURE__ */
|
|
747
|
+
return /* @__PURE__ */ jsx6(Text6, { color: "yellow", children: "\u25B2 \u8BE5\u5206\u652F\u6CA1\u6709 commit" });
|
|
536
748
|
}
|
|
537
749
|
const visibleCount = 10;
|
|
538
750
|
const startIdx = Math.max(0, Math.min(selectedIndex - Math.floor(visibleCount / 2), commits.length - visibleCount));
|
|
539
751
|
const visibleCommits = commits.slice(startIdx, startIdx + visibleCount);
|
|
540
|
-
return /* @__PURE__ */
|
|
541
|
-
/* @__PURE__ */
|
|
542
|
-
/* @__PURE__ */
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
752
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", gap: 1, children: [
|
|
753
|
+
/* @__PURE__ */ jsx6(SectionHeader, { title: "\u9009\u62E9\u8981\u540C\u6B65\u7684 commit" }),
|
|
754
|
+
/* @__PURE__ */ jsxs6(Box6, { gap: 2, children: [
|
|
755
|
+
/* @__PURE__ */ jsxs6(Text6, { color: "gray", dimColor: true, children: [
|
|
756
|
+
remote,
|
|
757
|
+
"/",
|
|
758
|
+
branch
|
|
759
|
+
] }),
|
|
760
|
+
/* @__PURE__ */ jsxs6(Text6, { color: "gray", dimColor: true, children: [
|
|
761
|
+
commits.length,
|
|
762
|
+
" commits"
|
|
763
|
+
] }),
|
|
764
|
+
/* @__PURE__ */ jsxs6(Text6, { color: selectedHashes.size > 0 ? "cyan" : "gray", bold: selectedHashes.size > 0, children: [
|
|
765
|
+
"\u5DF2\u9009 ",
|
|
766
|
+
selectedHashes.size
|
|
767
|
+
] }),
|
|
768
|
+
shiftMode && /* @__PURE__ */ jsx6(Text6, { color: "yellow", bold: true, children: "SHIFT" })
|
|
552
769
|
] }),
|
|
553
|
-
/* @__PURE__ */
|
|
554
|
-
startIdx > 0 && /* @__PURE__ */
|
|
770
|
+
/* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
771
|
+
startIdx > 0 && /* @__PURE__ */ jsxs6(Text6, { color: "gray", dimColor: true, children: [
|
|
555
772
|
" \u2191 ",
|
|
556
773
|
startIdx,
|
|
557
|
-
" more
|
|
774
|
+
" more"
|
|
558
775
|
] }),
|
|
559
776
|
visibleCommits.map((c, i) => {
|
|
560
777
|
const actualIdx = startIdx + i;
|
|
561
778
|
const isSelected = selectedHashes.has(c.hash);
|
|
562
779
|
const isCursor = actualIdx === selectedIndex;
|
|
563
780
|
const isAnchor = actualIdx === anchorIndexRef.current;
|
|
564
|
-
return /* @__PURE__ */
|
|
565
|
-
/* @__PURE__ */
|
|
566
|
-
isCursor ? "\
|
|
567
|
-
isAnchor ? "\u2693
|
|
568
|
-
|
|
781
|
+
return /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
782
|
+
/* @__PURE__ */ jsxs6(Text6, { backgroundColor: isCursor ? "blue" : void 0, color: isSelected ? "green" : "white", children: [
|
|
783
|
+
isCursor ? "\u25B8 " : " ",
|
|
784
|
+
isAnchor ? "\u2693" : isSelected ? "\u25CF" : "\u25CB",
|
|
785
|
+
" "
|
|
786
|
+
] }),
|
|
787
|
+
/* @__PURE__ */ jsx6(Text6, { backgroundColor: isCursor ? "blue" : void 0, color: "yellow", children: c.shortHash }),
|
|
788
|
+
/* @__PURE__ */ jsxs6(Text6, { backgroundColor: isCursor ? "blue" : void 0, color: isSelected ? "green" : "white", children: [
|
|
569
789
|
" ",
|
|
570
790
|
c.message
|
|
571
791
|
] }),
|
|
572
|
-
/* @__PURE__ */
|
|
573
|
-
"
|
|
792
|
+
/* @__PURE__ */ jsxs6(Text6, { color: "gray", dimColor: true, children: [
|
|
793
|
+
" ",
|
|
574
794
|
c.author,
|
|
575
|
-
"
|
|
795
|
+
" \xB7 ",
|
|
796
|
+
c.date
|
|
576
797
|
] })
|
|
577
798
|
] }, c.hash);
|
|
578
799
|
}),
|
|
579
|
-
startIdx + visibleCount < commits.length && /* @__PURE__ */
|
|
800
|
+
startIdx + visibleCount < commits.length && /* @__PURE__ */ jsxs6(Text6, { color: "gray", dimColor: true, children: [
|
|
580
801
|
" \u2193 ",
|
|
581
802
|
commits.length - startIdx - visibleCount,
|
|
582
|
-
" more
|
|
803
|
+
" more"
|
|
583
804
|
] })
|
|
584
805
|
] }),
|
|
585
|
-
/* @__PURE__ */
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
] }),
|
|
595
|
-
/* @__PURE__ */ jsxs4(Text4, { children: [
|
|
596
|
-
/* @__PURE__ */ jsx4(Text4, { color: "cyan", children: "a" }),
|
|
597
|
-
" \u5168\u9009"
|
|
598
|
-
] }),
|
|
599
|
-
/* @__PURE__ */ jsxs4(Text4, { children: [
|
|
600
|
-
/* @__PURE__ */ jsx4(Text4, { color: "cyan", children: "i" }),
|
|
601
|
-
" \u53CD\u9009"
|
|
602
|
-
] }),
|
|
603
|
-
/* @__PURE__ */ jsxs4(Text4, { children: [
|
|
604
|
-
/* @__PURE__ */ jsx4(Text4, { color: "cyan", children: "Enter" }),
|
|
605
|
-
" \u786E\u8BA4"
|
|
606
|
-
] })
|
|
607
|
-
] }),
|
|
608
|
-
/* @__PURE__ */ jsxs4(Box4, { gap: 2, children: [
|
|
609
|
-
/* @__PURE__ */ jsxs4(Text4, { children: [
|
|
610
|
-
/* @__PURE__ */ jsx4(Text4, { color: "yellow", children: "Shift+\u2191/\u2193" }),
|
|
611
|
-
" \u8FDE\u7EED\u9009\u62E9"
|
|
612
|
-
] }),
|
|
613
|
-
/* @__PURE__ */ jsxs4(Text4, { children: [
|
|
614
|
-
/* @__PURE__ */ jsx4(Text4, { color: "yellow", children: "Shift+Space" }),
|
|
615
|
-
" \u8303\u56F4\u9009\u62E9"
|
|
616
|
-
] }),
|
|
617
|
-
/* @__PURE__ */ jsxs4(Text4, { children: [
|
|
618
|
-
/* @__PURE__ */ jsx4(Text4, { color: "cyan", children: "r" }),
|
|
619
|
-
" \u9009\u81F3\u5F00\u5934"
|
|
620
|
-
] })
|
|
621
|
-
] })
|
|
806
|
+
/* @__PURE__ */ jsx6(KeyHints, { hints: [
|
|
807
|
+
{ key: "\u2191\u2193", label: "\u5BFC\u822A" },
|
|
808
|
+
{ key: "Space", label: "\u9009\u62E9" },
|
|
809
|
+
{ key: "a", label: "\u5168\u9009" },
|
|
810
|
+
{ key: "i", label: "\u53CD\u9009" },
|
|
811
|
+
{ key: "r", label: "\u9009\u81F3\u5F00\u5934" },
|
|
812
|
+
{ key: "Shift+\u2191\u2193", label: "\u8FDE\u9009" },
|
|
813
|
+
{ key: "Enter", label: "\u786E\u8BA4" },
|
|
814
|
+
{ key: "Esc", label: "\u8FD4\u56DE" }
|
|
622
815
|
] }),
|
|
623
|
-
selectedHashes.size > 0 && /* @__PURE__ */
|
|
624
|
-
/* @__PURE__ */ jsxs4(Text4, { bold: true, color: "yellow", children: [
|
|
625
|
-
"\u5DF2\u9009 ",
|
|
626
|
-
selectedHashes.size,
|
|
627
|
-
" \u4E2A commit \u2014 diff --stat \u9884\u89C8:"
|
|
628
|
-
] }),
|
|
629
|
-
statLoading ? /* @__PURE__ */ jsx4(Spinner3, { label: "\u52A0\u8F7D\u4E2D..." }) : /* @__PURE__ */ jsx4(Text4, { color: "gray", children: stat || "(\u65E0\u53D8\u66F4)" })
|
|
630
|
-
] })
|
|
816
|
+
selectedHashes.size > 0 && /* @__PURE__ */ jsx6(StatusPanel, { type: "info", title: `\u5DF2\u9009 ${selectedHashes.size} \u4E2A commit \xB7 diff --stat`, children: statLoading ? /* @__PURE__ */ jsx6(Spinner4, { label: "\u52A0\u8F7D\u4E2D..." }) : /* @__PURE__ */ jsx6(Text6, { color: "gray", children: stat || "(\u65E0\u53D8\u66F4)" }) })
|
|
631
817
|
] });
|
|
632
818
|
}
|
|
633
819
|
|
|
634
820
|
// src/components/confirm-panel.tsx
|
|
635
|
-
import { Box as
|
|
636
|
-
import { jsx as
|
|
821
|
+
import { Box as Box7, Text as Text7, useInput as useInput6 } from "ink";
|
|
822
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
637
823
|
function ConfirmPanel({ commits, selectedHashes, hasMerge, useMainline, onToggleMainline, onConfirm, onCancel }) {
|
|
638
|
-
|
|
639
|
-
if (
|
|
824
|
+
useInput6((input, key) => {
|
|
825
|
+
if (key.escape) {
|
|
826
|
+
onCancel();
|
|
827
|
+
} else if (input === "y" || input === "Y") {
|
|
640
828
|
onConfirm();
|
|
641
829
|
} else if (input === "n" || input === "N" || input === "q") {
|
|
642
830
|
onCancel();
|
|
@@ -645,68 +833,57 @@ function ConfirmPanel({ commits, selectedHashes, hasMerge, useMainline, onToggle
|
|
|
645
833
|
}
|
|
646
834
|
});
|
|
647
835
|
const selectedCommits = selectedHashes.map((hash) => commits.find((c) => c.hash === hash)).filter(Boolean);
|
|
648
|
-
return /* @__PURE__ */
|
|
649
|
-
/* @__PURE__ */
|
|
650
|
-
/* @__PURE__ */
|
|
651
|
-
/* @__PURE__ */
|
|
652
|
-
"
|
|
653
|
-
|
|
654
|
-
" \u4E2A commit:"
|
|
836
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", gap: 1, children: [
|
|
837
|
+
/* @__PURE__ */ jsx7(SectionHeader, { title: "\u786E\u8BA4\u6267\u884C" }),
|
|
838
|
+
/* @__PURE__ */ jsx7(StatusPanel, { type: "info", title: `cherry-pick --no-commit \xB7 ${selectedCommits.length} \u4E2A commit`, children: selectedCommits.map((c) => /* @__PURE__ */ jsxs7(Box7, { children: [
|
|
839
|
+
/* @__PURE__ */ jsxs7(Text7, { color: "yellow", children: [
|
|
840
|
+
" ",
|
|
841
|
+
c.shortHash
|
|
655
842
|
] }),
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
] })
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
hasMerge && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", borderStyle: "single", borderColor: "red", paddingX: 1, children: [
|
|
673
|
-
/* @__PURE__ */ jsx5(Text5, { bold: true, color: "red", children: "\u68C0\u6D4B\u5230 Merge Commit" }),
|
|
674
|
-
/* @__PURE__ */ jsx5(Text5, { color: "yellow", children: "Cherry-pick \u5408\u5E76\u63D0\u4EA4\u9700\u8981\u6307\u5B9A\u7236\u8282\u70B9 (-m 1)" }),
|
|
675
|
-
/* @__PURE__ */ jsxs5(Text5, { children: [
|
|
676
|
-
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "[m]" }),
|
|
677
|
-
/* @__PURE__ */ jsx5(Text5, { children: " \u5207\u6362 -m 1: " }),
|
|
678
|
-
useMainline ? /* @__PURE__ */ jsx5(Text5, { color: "green", children: "\u5DF2\u542F\u7528" }) : /* @__PURE__ */ jsx5(Text5, { color: "gray", children: "\u672A\u542F\u7528" })
|
|
843
|
+
/* @__PURE__ */ jsxs7(Text7, { children: [
|
|
844
|
+
" ",
|
|
845
|
+
c.message
|
|
846
|
+
] }),
|
|
847
|
+
/* @__PURE__ */ jsxs7(Text7, { color: "gray", dimColor: true, children: [
|
|
848
|
+
" ",
|
|
849
|
+
c.author
|
|
850
|
+
] })
|
|
851
|
+
] }, c.hash)) }),
|
|
852
|
+
hasMerge && /* @__PURE__ */ jsxs7(StatusPanel, { type: "warn", title: "\u68C0\u6D4B\u5230 Merge Commit", children: [
|
|
853
|
+
/* @__PURE__ */ jsx7(Text7, { color: "gray", children: " Cherry-pick \u5408\u5E76\u63D0\u4EA4\u9700\u8981\u6307\u5B9A\u7236\u8282\u70B9 (-m 1)" }),
|
|
854
|
+
/* @__PURE__ */ jsxs7(Box7, { children: [
|
|
855
|
+
/* @__PURE__ */ jsx7(Text7, { children: " " }),
|
|
856
|
+
/* @__PURE__ */ jsx7(Text7, { color: "cyan", children: "[m]" }),
|
|
857
|
+
/* @__PURE__ */ jsx7(Text7, { children: " \u5207\u6362 -m 1: " }),
|
|
858
|
+
useMainline ? /* @__PURE__ */ jsx7(Text7, { color: "green", bold: true, children: "\u5DF2\u542F\u7528" }) : /* @__PURE__ */ jsx7(Text7, { color: "gray", children: "\u672A\u542F\u7528" })
|
|
679
859
|
] })
|
|
680
860
|
] }),
|
|
681
|
-
/* @__PURE__ */
|
|
682
|
-
/* @__PURE__ */
|
|
683
|
-
/* @__PURE__ */
|
|
861
|
+
/* @__PURE__ */ jsxs7(Box7, { children: [
|
|
862
|
+
/* @__PURE__ */ jsx7(Text7, { color: "yellow", children: "\u25B2 " }),
|
|
863
|
+
/* @__PURE__ */ jsx7(Text7, { color: "gray", children: "--no-commit \u6A21\u5F0F\uFF0C\u6539\u52A8\u5C06\u6682\u5B58\u5230\u5DE5\u4F5C\u533A\uFF0C\u9700\u624B\u52A8 commit" })
|
|
684
864
|
] }),
|
|
685
|
-
/* @__PURE__ */
|
|
686
|
-
/* @__PURE__ */
|
|
687
|
-
/* @__PURE__ */
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
" / ",
|
|
693
|
-
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "[m]" }),
|
|
694
|
-
" \u5207\u6362 -m 1"
|
|
865
|
+
/* @__PURE__ */ jsxs7(Box7, { children: [
|
|
866
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, children: "\u786E\u8BA4\u6267\u884C? " }),
|
|
867
|
+
/* @__PURE__ */ jsx7(InlineKeys, { hints: [
|
|
868
|
+
{ key: "y", label: "\u786E\u8BA4" },
|
|
869
|
+
{ key: "n", label: "\u53D6\u6D88" },
|
|
870
|
+
...hasMerge ? [{ key: "m", label: "\u5207\u6362 -m 1" }] : [],
|
|
871
|
+
{ key: "Esc", label: "\u8FD4\u56DE" }
|
|
695
872
|
] })
|
|
696
873
|
] })
|
|
697
874
|
] });
|
|
698
875
|
}
|
|
699
876
|
|
|
700
877
|
// src/components/result-panel.tsx
|
|
701
|
-
import { useState as
|
|
702
|
-
import { Box as
|
|
703
|
-
import { Spinner as
|
|
704
|
-
import { jsx as
|
|
878
|
+
import { useState as useState6, useEffect as useEffect3 } from "react";
|
|
879
|
+
import { Box as Box8, Text as Text8 } from "ink";
|
|
880
|
+
import { Spinner as Spinner5 } from "@inkjs/ui";
|
|
881
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
705
882
|
function ResultPanel({ selectedHashes, useMainline, stashed, onStashRestored, onDone }) {
|
|
706
|
-
const [phase, setPhase] =
|
|
707
|
-
const [result, setResult] =
|
|
708
|
-
const [stagedStat, setStagedStat] =
|
|
709
|
-
const [stashRestored, setStashRestored] =
|
|
883
|
+
const [phase, setPhase] = useState6("executing");
|
|
884
|
+
const [result, setResult] = useState6(null);
|
|
885
|
+
const [stagedStat, setStagedStat] = useState6("");
|
|
886
|
+
const [stashRestored, setStashRestored] = useState6(null);
|
|
710
887
|
const tryRestoreStash = async () => {
|
|
711
888
|
if (!stashed) return true;
|
|
712
889
|
setPhase("restoring");
|
|
@@ -715,7 +892,7 @@ function ResultPanel({ selectedHashes, useMainline, stashed, onStashRestored, on
|
|
|
715
892
|
if (ok) onStashRestored();
|
|
716
893
|
return ok;
|
|
717
894
|
};
|
|
718
|
-
|
|
895
|
+
useEffect3(() => {
|
|
719
896
|
async function run() {
|
|
720
897
|
const res = await cherryPick(selectedHashes, useMainline);
|
|
721
898
|
setResult(res);
|
|
@@ -732,62 +909,93 @@ function ResultPanel({ selectedHashes, useMainline, stashed, onStashRestored, on
|
|
|
732
909
|
run();
|
|
733
910
|
}, []);
|
|
734
911
|
if (phase === "executing") {
|
|
735
|
-
return /* @__PURE__ */
|
|
912
|
+
return /* @__PURE__ */ jsx8(Spinner5, { label: `cherry-pick --no-commit (${selectedHashes.length} \u4E2A commit)...` });
|
|
736
913
|
}
|
|
737
914
|
if (phase === "restoring") {
|
|
738
|
-
return /* @__PURE__ */
|
|
915
|
+
return /* @__PURE__ */ jsx8(Spinner5, { label: "\u6062\u590D\u5DE5\u4F5C\u533A (git stash pop)..." });
|
|
739
916
|
}
|
|
740
917
|
if (phase === "error" && result) {
|
|
741
|
-
return /* @__PURE__ */
|
|
742
|
-
/* @__PURE__ */
|
|
743
|
-
result.conflictFiles && result.conflictFiles.length > 0 && /* @__PURE__ */
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
918
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", gap: 1, children: [
|
|
919
|
+
/* @__PURE__ */ jsx8(SectionHeader, { title: "Cherry-pick \u9047\u5230\u51B2\u7A81" }),
|
|
920
|
+
result.conflictFiles && result.conflictFiles.length > 0 && /* @__PURE__ */ jsx8(StatusPanel, { type: "error", title: "\u51B2\u7A81\u6587\u4EF6", children: result.conflictFiles.map((f) => /* @__PURE__ */ jsxs8(Text8, { color: "red", children: [
|
|
921
|
+
" ",
|
|
922
|
+
f
|
|
923
|
+
] }, f)) }),
|
|
924
|
+
/* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
925
|
+
/* @__PURE__ */ jsx8(Text8, { color: "yellow", children: "\u25B8 \u624B\u52A8\u89E3\u51B3\u51B2\u7A81\u540E\u6267\u884C git add \u548C git commit" }),
|
|
926
|
+
/* @__PURE__ */ jsx8(Text8, { color: "gray", dimColor: true, children: "\u25B8 \u6216\u6267\u884C git cherry-pick --abort \u653E\u5F03\u64CD\u4F5C" })
|
|
749
927
|
] }),
|
|
750
|
-
/* @__PURE__ */
|
|
751
|
-
/* @__PURE__ */
|
|
752
|
-
stashed && stashRestored === false && /* @__PURE__ */ jsx6(Text6, { color: "yellow", children: "\u6CE8\u610F: stash \u6062\u590D\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8 git stash pop" }),
|
|
753
|
-
stashed && stashRestored === true && /* @__PURE__ */ jsx6(Text6, { color: "green", children: "\u5DF2\u6062\u590D\u5DE5\u4F5C\u533A\u53D8\u66F4 (stash pop)" })
|
|
928
|
+
stashed && stashRestored === false && /* @__PURE__ */ jsx8(Text8, { color: "yellow", children: "\u25B2 stash \u6062\u590D\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8 git stash pop" }),
|
|
929
|
+
stashed && stashRestored === true && /* @__PURE__ */ jsx8(Text8, { color: "green", children: "\u2714 \u5DF2\u6062\u590D\u5DE5\u4F5C\u533A\u53D8\u66F4 (stash pop)" })
|
|
754
930
|
] });
|
|
755
931
|
}
|
|
756
|
-
return /* @__PURE__ */
|
|
757
|
-
/* @__PURE__ */
|
|
758
|
-
/* @__PURE__ */
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
932
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", gap: 1, children: [
|
|
933
|
+
/* @__PURE__ */ jsx8(SectionHeader, { title: "\u540C\u6B65\u5B8C\u6210" }),
|
|
934
|
+
/* @__PURE__ */ jsx8(StatusPanel, { type: "success", title: "\u6682\u5B58\u533A\u53D8\u66F4 (git diff --cached --stat)", children: /* @__PURE__ */ jsx8(Text8, { color: "gray", children: stagedStat || "(\u65E0\u53D8\u66F4)" }) }),
|
|
935
|
+
stashed && (stashRestored ? /* @__PURE__ */ jsx8(Text8, { color: "green", children: "\u2714 \u5DF2\u6062\u590D\u5DE5\u4F5C\u533A\u53D8\u66F4 (stash pop)" }) : /* @__PURE__ */ jsx8(Text8, { color: "yellow", children: "\u25B2 stash pop \u5931\u8D25\uFF0C\u8BF7\u624B\u52A8 git stash pop" })),
|
|
936
|
+
/* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
937
|
+
/* @__PURE__ */ jsx8(Text8, { color: "yellow", children: "\u25B2 \u6539\u52A8\u5DF2\u6682\u5B58\u5230\u5DE5\u4F5C\u533A (--no-commit \u6A21\u5F0F)" }),
|
|
938
|
+
/* @__PURE__ */ jsx8(Text8, { color: "gray", dimColor: true, children: " \u5BA1\u67E5\u540E\u624B\u52A8\u6267\u884C:" }),
|
|
939
|
+
/* @__PURE__ */ jsxs8(Text8, { color: "cyan", children: [
|
|
940
|
+
" git diff --cached ",
|
|
941
|
+
/* @__PURE__ */ jsx8(Text8, { color: "gray", dimColor: true, children: "# \u67E5\u770B\u8BE6\u7EC6 diff" })
|
|
942
|
+
] }),
|
|
943
|
+
/* @__PURE__ */ jsxs8(Text8, { color: "cyan", children: [
|
|
944
|
+
' git commit -m "sync: ..." ',
|
|
945
|
+
/* @__PURE__ */ jsx8(Text8, { color: "gray", dimColor: true, children: "# \u63D0\u4EA4" })
|
|
946
|
+
] }),
|
|
947
|
+
/* @__PURE__ */ jsxs8(Text8, { color: "cyan", children: [
|
|
948
|
+
" git reset HEAD ",
|
|
949
|
+
/* @__PURE__ */ jsx8(Text8, { color: "gray", dimColor: true, children: "# \u6216\u653E\u5F03" })
|
|
950
|
+
] })
|
|
951
|
+
] })
|
|
768
952
|
] });
|
|
769
953
|
}
|
|
770
954
|
|
|
771
955
|
// src/app.tsx
|
|
772
956
|
import { execSync } from "child_process";
|
|
773
|
-
import { jsx as
|
|
957
|
+
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
958
|
+
var STEP_NUMBER = {
|
|
959
|
+
checking: 0,
|
|
960
|
+
"stash-recovery": 0,
|
|
961
|
+
"stash-prompt": 0,
|
|
962
|
+
remote: 1,
|
|
963
|
+
branch: 2,
|
|
964
|
+
commits: 3,
|
|
965
|
+
confirm: 4,
|
|
966
|
+
result: 5
|
|
967
|
+
};
|
|
968
|
+
var STEP_DEBOUNCE = 100;
|
|
774
969
|
function App() {
|
|
775
970
|
const { exit } = useApp();
|
|
776
|
-
const [step,
|
|
777
|
-
const [
|
|
778
|
-
const [
|
|
779
|
-
const [
|
|
780
|
-
const [
|
|
781
|
-
const [
|
|
782
|
-
const [
|
|
783
|
-
const [
|
|
971
|
+
const [step, setStepRaw] = useState7("checking");
|
|
972
|
+
const [inputReady, setInputReady] = useState7(true);
|
|
973
|
+
const [remote, setRemote] = useState7("");
|
|
974
|
+
const [branch, setBranch] = useState7("");
|
|
975
|
+
const [selectedHashes, setSelectedHashes] = useState7([]);
|
|
976
|
+
const [commits, setCommits] = useState7([]);
|
|
977
|
+
const [hasMerge, setHasMerge] = useState7(false);
|
|
978
|
+
const [useMainline, setUseMainline] = useState7(false);
|
|
979
|
+
const [stashed, setStashed] = useState7(false);
|
|
980
|
+
const [guardTimestamp, setGuardTimestamp] = useState7();
|
|
784
981
|
const stashedRef = useRef2(false);
|
|
785
982
|
const stashRestoredRef = useRef2(false);
|
|
983
|
+
const mountedRef = useRef2(true);
|
|
984
|
+
const debounceTimer = useRef2(null);
|
|
985
|
+
const setStep = useCallback2((newStep) => {
|
|
986
|
+
setInputReady(false);
|
|
987
|
+
setStepRaw(newStep);
|
|
988
|
+
if (debounceTimer.current) clearTimeout(debounceTimer.current);
|
|
989
|
+
debounceTimer.current = setTimeout(() => {
|
|
990
|
+
if (mountedRef.current) setInputReady(true);
|
|
991
|
+
}, STEP_DEBOUNCE);
|
|
992
|
+
}, []);
|
|
786
993
|
const restoreStashSync = useCallback2(() => {
|
|
787
994
|
if (stashedRef.current && !stashRestoredRef.current) {
|
|
788
995
|
try {
|
|
789
996
|
execSync("git stash pop", { stdio: "ignore" });
|
|
790
997
|
stashRestoredRef.current = true;
|
|
998
|
+
removeStashGuardSync();
|
|
791
999
|
} catch {
|
|
792
1000
|
try {
|
|
793
1001
|
process.stderr.write("\n\u26A0 stash \u81EA\u52A8\u6062\u590D\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8\u6267\u884C: git stash pop\n");
|
|
@@ -798,71 +1006,117 @@ function App() {
|
|
|
798
1006
|
}, []);
|
|
799
1007
|
const markStashRestored = useCallback2(() => {
|
|
800
1008
|
stashRestoredRef.current = true;
|
|
1009
|
+
removeStashGuard();
|
|
801
1010
|
}, []);
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
1011
|
+
useEffect4(() => {
|
|
1012
|
+
mountedRef.current = true;
|
|
1013
|
+
async function check() {
|
|
1014
|
+
const guard = await checkStashGuard();
|
|
1015
|
+
if (!mountedRef.current) return;
|
|
1016
|
+
if (guard.exists) {
|
|
1017
|
+
setGuardTimestamp(guard.timestamp);
|
|
1018
|
+
setStep("stash-recovery");
|
|
1019
|
+
return;
|
|
808
1020
|
}
|
|
809
|
-
|
|
1021
|
+
const clean = await isWorkingDirClean();
|
|
1022
|
+
if (!mountedRef.current) return;
|
|
1023
|
+
setStep(clean ? "remote" : "stash-prompt");
|
|
1024
|
+
}
|
|
1025
|
+
check();
|
|
810
1026
|
const onSignal = () => {
|
|
811
1027
|
restoreStashSync();
|
|
812
1028
|
process.exit(0);
|
|
813
1029
|
};
|
|
814
1030
|
process.on("SIGINT", onSignal);
|
|
815
1031
|
process.on("SIGTERM", onSignal);
|
|
816
|
-
process.on("
|
|
1032
|
+
process.on("SIGHUP", onSignal);
|
|
817
1033
|
return () => {
|
|
1034
|
+
mountedRef.current = false;
|
|
1035
|
+
if (debounceTimer.current) clearTimeout(debounceTimer.current);
|
|
818
1036
|
process.off("SIGINT", onSignal);
|
|
819
1037
|
process.off("SIGTERM", onSignal);
|
|
820
|
-
process.off("
|
|
1038
|
+
process.off("SIGHUP", onSignal);
|
|
821
1039
|
};
|
|
822
|
-
}, [restoreStashSync]);
|
|
1040
|
+
}, [restoreStashSync, setStep]);
|
|
823
1041
|
const doStash = async () => {
|
|
824
1042
|
const ok = await stash();
|
|
825
1043
|
if (ok) {
|
|
826
1044
|
setStashed(true);
|
|
827
1045
|
stashedRef.current = true;
|
|
1046
|
+
await writeStashGuard();
|
|
828
1047
|
}
|
|
829
|
-
setStep("remote");
|
|
1048
|
+
if (mountedRef.current) setStep("remote");
|
|
830
1049
|
};
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
1050
|
+
const doStashRecover = async () => {
|
|
1051
|
+
const entry = await findStashEntry();
|
|
1052
|
+
if (entry) {
|
|
1053
|
+
await stashPop();
|
|
1054
|
+
}
|
|
1055
|
+
await removeStashGuard();
|
|
1056
|
+
if (!mountedRef.current) return;
|
|
1057
|
+
const clean = await isWorkingDirClean();
|
|
1058
|
+
if (mountedRef.current) setStep(clean ? "remote" : "stash-prompt");
|
|
1059
|
+
};
|
|
1060
|
+
const skipStashRecover = async () => {
|
|
1061
|
+
await removeStashGuard();
|
|
1062
|
+
if (!mountedRef.current) return;
|
|
1063
|
+
const clean = await isWorkingDirClean();
|
|
1064
|
+
if (mountedRef.current) setStep(clean ? "remote" : "stash-prompt");
|
|
1065
|
+
};
|
|
1066
|
+
const goBack = useCallback2((fromStep) => {
|
|
1067
|
+
const backMap = {
|
|
1068
|
+
branch: "remote",
|
|
1069
|
+
commits: "branch",
|
|
1070
|
+
confirm: "commits"
|
|
1071
|
+
};
|
|
1072
|
+
const prev = backMap[fromStep];
|
|
1073
|
+
if (prev) {
|
|
1074
|
+
setStep(prev);
|
|
1075
|
+
} else {
|
|
1076
|
+
restoreStashSync();
|
|
1077
|
+
exit();
|
|
1078
|
+
}
|
|
1079
|
+
}, [setStep, restoreStashSync, exit]);
|
|
1080
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
|
|
1081
|
+
/* @__PURE__ */ jsx9(AppHeader, { step: STEP_NUMBER[step], stashed }),
|
|
1082
|
+
step === "checking" && /* @__PURE__ */ jsx9(Spinner6, { label: "\u68C0\u67E5\u5DE5\u4F5C\u533A\u72B6\u6001..." }),
|
|
1083
|
+
step === "stash-recovery" && inputReady && /* @__PURE__ */ jsx9(
|
|
1084
|
+
StashRecovery,
|
|
1085
|
+
{
|
|
1086
|
+
timestamp: guardTimestamp,
|
|
1087
|
+
onRecover: doStashRecover,
|
|
1088
|
+
onSkip: skipStashRecover
|
|
1089
|
+
}
|
|
1090
|
+
),
|
|
1091
|
+
step === "stash-prompt" && inputReady && /* @__PURE__ */ jsx9(
|
|
840
1092
|
StashPrompt,
|
|
841
1093
|
{
|
|
842
1094
|
onConfirm: doStash,
|
|
843
1095
|
onSkip: () => setStep("remote")
|
|
844
1096
|
}
|
|
845
1097
|
),
|
|
846
|
-
step === "remote" && /* @__PURE__ */
|
|
1098
|
+
step === "remote" && inputReady && /* @__PURE__ */ jsx9(
|
|
847
1099
|
RemoteSelect,
|
|
848
1100
|
{
|
|
849
1101
|
onSelect: (r) => {
|
|
850
1102
|
setRemote(r);
|
|
851
1103
|
setStep("branch");
|
|
852
|
-
}
|
|
1104
|
+
},
|
|
1105
|
+
onBack: () => goBack("remote")
|
|
853
1106
|
}
|
|
854
1107
|
),
|
|
855
|
-
step === "branch" && /* @__PURE__ */
|
|
1108
|
+
step === "branch" && inputReady && /* @__PURE__ */ jsx9(
|
|
856
1109
|
BranchSelect,
|
|
857
1110
|
{
|
|
858
1111
|
remote,
|
|
859
1112
|
onSelect: (b) => {
|
|
860
1113
|
setBranch(b);
|
|
861
1114
|
setStep("commits");
|
|
862
|
-
}
|
|
1115
|
+
},
|
|
1116
|
+
onBack: () => goBack("branch")
|
|
863
1117
|
}
|
|
864
1118
|
),
|
|
865
|
-
step === "commits" && /* @__PURE__ */
|
|
1119
|
+
step === "commits" && inputReady && /* @__PURE__ */ jsx9(
|
|
866
1120
|
CommitList,
|
|
867
1121
|
{
|
|
868
1122
|
remote,
|
|
@@ -873,10 +1127,11 @@ function App() {
|
|
|
873
1127
|
const merge = await hasMergeCommits(hashes);
|
|
874
1128
|
setHasMerge(merge);
|
|
875
1129
|
setStep("confirm");
|
|
876
|
-
}
|
|
1130
|
+
},
|
|
1131
|
+
onBack: () => goBack("commits")
|
|
877
1132
|
}
|
|
878
1133
|
),
|
|
879
|
-
step === "confirm" && /* @__PURE__ */
|
|
1134
|
+
step === "confirm" && inputReady && /* @__PURE__ */ jsx9(
|
|
880
1135
|
ConfirmPanel,
|
|
881
1136
|
{
|
|
882
1137
|
commits,
|
|
@@ -885,10 +1140,10 @@ function App() {
|
|
|
885
1140
|
useMainline,
|
|
886
1141
|
onToggleMainline: () => setUseMainline((v) => !v),
|
|
887
1142
|
onConfirm: () => setStep("result"),
|
|
888
|
-
onCancel: () =>
|
|
1143
|
+
onCancel: () => goBack("confirm")
|
|
889
1144
|
}
|
|
890
1145
|
),
|
|
891
|
-
step === "result" && /* @__PURE__ */
|
|
1146
|
+
step === "result" && /* @__PURE__ */ jsx9(
|
|
892
1147
|
ResultPanel,
|
|
893
1148
|
{
|
|
894
1149
|
selectedHashes,
|
|
@@ -905,7 +1160,7 @@ function App() {
|
|
|
905
1160
|
}
|
|
906
1161
|
|
|
907
1162
|
// src/cli.tsx
|
|
908
|
-
import { jsx as
|
|
1163
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
909
1164
|
var cli = meow(
|
|
910
1165
|
`
|
|
911
1166
|
\u7528\u6CD5
|
|
@@ -932,4 +1187,4 @@ var cli = meow(
|
|
|
932
1187
|
importMeta: import.meta
|
|
933
1188
|
}
|
|
934
1189
|
);
|
|
935
|
-
render(/* @__PURE__ */
|
|
1190
|
+
render(/* @__PURE__ */ jsx10(App, {}));
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "git-sync-tui",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.3",
|
|
5
5
|
"packageManager": "pnpm@10.32.1",
|
|
6
6
|
"description": "Interactive TUI tool for cross-repo git commit synchronization (cherry-pick --no-commit)",
|
|
7
7
|
"author": "KiWi233333",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|
|
33
33
|
"start": "tsx src/cli.tsx",
|
|
34
|
-
"dev": "tsx
|
|
34
|
+
"dev": "tsx src/cli.tsx",
|
|
35
35
|
"build": "tsup",
|
|
36
36
|
"prepublishOnly": "pnpm run build",
|
|
37
37
|
"release": "pnpm run release:patch",
|