git-sync-tui 0.1.4 → 0.1.6
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 +881 -224
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -11,9 +11,9 @@ import { render } from "ink";
|
|
|
11
11
|
import meow from "meow";
|
|
12
12
|
|
|
13
13
|
// src/app.tsx
|
|
14
|
-
import { useState as
|
|
15
|
-
import { Box as
|
|
16
|
-
import { Spinner as
|
|
14
|
+
import { useState as useState8, useEffect as useEffect6, useRef as useRef5, useCallback as useCallback3 } from "react";
|
|
15
|
+
import { Box as Box10, useApp } from "ink";
|
|
16
|
+
import { Spinner as Spinner7 } from "@inkjs/ui";
|
|
17
17
|
|
|
18
18
|
// src/components/ui.tsx
|
|
19
19
|
import React from "react";
|
|
@@ -32,14 +32,18 @@ function StepProgress({ current }) {
|
|
|
32
32
|
" ",
|
|
33
33
|
isActive ? /* @__PURE__ */ jsx(Text, { bold: true, children: label }) : label
|
|
34
34
|
] }),
|
|
35
|
-
!isLast && /* @__PURE__ */
|
|
35
|
+
!isLast && /* @__PURE__ */ jsxs(Text, { color: isDone ? "green" : "gray", dimColor: !isDone, children: [
|
|
36
|
+
" ",
|
|
37
|
+
"\u2500\u2500\u2500",
|
|
38
|
+
" "
|
|
39
|
+
] })
|
|
36
40
|
] }, label);
|
|
37
41
|
}) });
|
|
38
42
|
}
|
|
39
43
|
function SectionHeader({ title, subtitle }) {
|
|
40
44
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
41
45
|
/* @__PURE__ */ jsxs(Text, { bold: true, color: "cyan", children: [
|
|
42
|
-
"\
|
|
46
|
+
"\u25BE ",
|
|
43
47
|
title
|
|
44
48
|
] }),
|
|
45
49
|
subtitle && /* @__PURE__ */ jsxs(Text, { color: "gray", dimColor: true, children: [
|
|
@@ -50,10 +54,8 @@ function SectionHeader({ title, subtitle }) {
|
|
|
50
54
|
}
|
|
51
55
|
function KeyHints({ hints }) {
|
|
52
56
|
return /* @__PURE__ */ jsx(Box, { gap: 1, flexWrap: "wrap", children: hints.map(({ key, label }) => /* @__PURE__ */ jsxs(Box, { children: [
|
|
53
|
-
/* @__PURE__ */ jsx(Text, {
|
|
54
|
-
/* @__PURE__ */
|
|
55
|
-
/* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: "]" }),
|
|
56
|
-
/* @__PURE__ */ jsxs(Text, { color: "gray", dimColor: true, children: [
|
|
57
|
+
/* @__PURE__ */ jsx(Text, { backgroundColor: "gray", color: "white", bold: true, children: ` ${key} ` }),
|
|
58
|
+
/* @__PURE__ */ jsxs(Text, { color: "gray", children: [
|
|
57
59
|
" ",
|
|
58
60
|
label
|
|
59
61
|
] })
|
|
@@ -61,7 +63,7 @@ function KeyHints({ hints }) {
|
|
|
61
63
|
}
|
|
62
64
|
function InlineKeys({ hints }) {
|
|
63
65
|
return /* @__PURE__ */ jsx(Box, { gap: 1, children: hints.map(({ key, label }, i) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
64
|
-
/* @__PURE__ */ jsxs(Text, { color: "green", children: [
|
|
66
|
+
/* @__PURE__ */ jsxs(Text, { color: "green", bold: true, children: [
|
|
65
67
|
"[",
|
|
66
68
|
key,
|
|
67
69
|
"]"
|
|
@@ -90,15 +92,17 @@ function StatusPanel({ type, title, children }) {
|
|
|
90
92
|
children
|
|
91
93
|
] });
|
|
92
94
|
}
|
|
93
|
-
function AppHeader({ step, stashed }) {
|
|
95
|
+
function AppHeader({ step, stashed, noCommit }) {
|
|
94
96
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
95
|
-
/* @__PURE__ */ jsxs(Box, { children: [
|
|
96
|
-
/* @__PURE__ */ jsx(Text, {
|
|
97
|
-
/* @__PURE__ */
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
/* @__PURE__ */ jsxs(Box, { gap: 1, children: [
|
|
98
|
+
/* @__PURE__ */ jsx(Text, { backgroundColor: "cyan", color: "white", bold: true, children: " git-sync-tui " }),
|
|
99
|
+
/* @__PURE__ */ jsxs(Text, { color: "gray", children: [
|
|
100
|
+
"cherry-pick",
|
|
101
|
+
noCommit ? " --no-commit" : ""
|
|
102
|
+
] }),
|
|
103
|
+
stashed && /* @__PURE__ */ jsx(Text, { backgroundColor: "yellow", color: "white", bold: true, children: " STASHED " })
|
|
100
104
|
] }),
|
|
101
|
-
/* @__PURE__ */ jsxs(Box, { children: [
|
|
105
|
+
/* @__PURE__ */ jsxs(Box, { marginTop: 0, children: [
|
|
102
106
|
/* @__PURE__ */ jsx(Text, { color: "gray", dimColor: true, children: " " }),
|
|
103
107
|
/* @__PURE__ */ jsx(StepProgress, { current: step })
|
|
104
108
|
] })
|
|
@@ -158,28 +162,20 @@ async function addRemote(name, url) {
|
|
|
158
162
|
}
|
|
159
163
|
async function getRemoteBranches(remote2) {
|
|
160
164
|
const git = getGit();
|
|
161
|
-
let fetchOk = false;
|
|
162
165
|
try {
|
|
163
|
-
await git.
|
|
164
|
-
|
|
166
|
+
const lsResult = await git.raw(["ls-remote", "--heads", remote2]);
|
|
167
|
+
if (lsResult.trim()) {
|
|
168
|
+
return lsResult.trim().split("\n").map((line) => line.replace(/^.*refs\/heads\//, "")).filter(Boolean).sort();
|
|
169
|
+
}
|
|
165
170
|
} catch {
|
|
166
171
|
}
|
|
167
172
|
const result = await git.branch(["-r"]);
|
|
168
173
|
const prefix = `${remote2}/`;
|
|
169
174
|
const branches = result.all.filter((b) => b.startsWith(prefix) && !b.includes("HEAD")).map((b) => b.replace(prefix, "")).sort();
|
|
170
175
|
if (branches.length > 0) return branches;
|
|
171
|
-
|
|
172
|
-
const lsResult = await git.raw(["ls-remote", "--heads", remote2]);
|
|
173
|
-
if (!lsResult.trim()) return [];
|
|
174
|
-
return lsResult.trim().split("\n").map((line) => line.replace(/^.*refs\/heads\//, "")).filter(Boolean).sort();
|
|
175
|
-
} catch {
|
|
176
|
-
if (!fetchOk) {
|
|
177
|
-
throw new Error(`\u65E0\u6CD5\u8FDE\u63A5\u8FDC\u7A0B\u4ED3\u5E93 '${remote2}'\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u6216\u4ED3\u5E93\u5730\u5740`);
|
|
178
|
-
}
|
|
179
|
-
return [];
|
|
180
|
-
}
|
|
176
|
+
throw new Error(`\u65E0\u6CD5\u83B7\u53D6\u8FDC\u7A0B\u4ED3\u5E93 '${remote2}' \u7684\u5206\u652F\u5217\u8868\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u6216\u4ED3\u5E93\u5730\u5740`);
|
|
181
177
|
}
|
|
182
|
-
async function getCommits(remote2, branch2, count2 =
|
|
178
|
+
async function getCommits(remote2, branch2, count2 = 100) {
|
|
183
179
|
const git = getGit();
|
|
184
180
|
const ref = `${remote2}/${branch2}`;
|
|
185
181
|
try {
|
|
@@ -194,6 +190,8 @@ async function getCommits(remote2, branch2, count2 = 30) {
|
|
|
194
190
|
const result = await git.raw([
|
|
195
191
|
"log",
|
|
196
192
|
ref,
|
|
193
|
+
"--first-parent",
|
|
194
|
+
"--no-merges",
|
|
197
195
|
`--max-count=${count2}`,
|
|
198
196
|
"--format=%H%n%h%n%s%n%an%n%ar%n---"
|
|
199
197
|
]);
|
|
@@ -204,6 +202,27 @@ async function getCommits(remote2, branch2, count2 = 30) {
|
|
|
204
202
|
return { hash, shortHash, message: message || "", author: author || "", date: date || "" };
|
|
205
203
|
});
|
|
206
204
|
}
|
|
205
|
+
async function getUnsyncedCommits(remote2, branch2, count2 = 100) {
|
|
206
|
+
const git = getGit();
|
|
207
|
+
const ref = `${remote2}/${branch2}`;
|
|
208
|
+
const allCommits = await getCommits(remote2, branch2, count2);
|
|
209
|
+
try {
|
|
210
|
+
const result = await git.raw([
|
|
211
|
+
"cherry",
|
|
212
|
+
"HEAD",
|
|
213
|
+
ref
|
|
214
|
+
]);
|
|
215
|
+
const unsyncedHashes = new Set(
|
|
216
|
+
result.trim().split("\n").filter((line) => line.startsWith("+ ")).map((line) => line.substring(2).trim())
|
|
217
|
+
);
|
|
218
|
+
return allCommits.map((c) => ({
|
|
219
|
+
...c,
|
|
220
|
+
synced: !unsyncedHashes.has(c.hash)
|
|
221
|
+
}));
|
|
222
|
+
} catch {
|
|
223
|
+
return allCommits;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
207
226
|
async function getMultiCommitStat(hashes) {
|
|
208
227
|
if (hashes.length === 0) return "";
|
|
209
228
|
const git = getGit();
|
|
@@ -267,6 +286,45 @@ async function getStagedStat() {
|
|
|
267
286
|
return "";
|
|
268
287
|
}
|
|
269
288
|
}
|
|
289
|
+
var BACKUP_BRANCH_PREFIX = "git-sync-backup";
|
|
290
|
+
async function createBackupBranch() {
|
|
291
|
+
const git = getGit();
|
|
292
|
+
const timestamp = Date.now();
|
|
293
|
+
const branchName = `${BACKUP_BRANCH_PREFIX}-${timestamp}`;
|
|
294
|
+
await git.raw(["branch", branchName]);
|
|
295
|
+
return branchName;
|
|
296
|
+
}
|
|
297
|
+
async function restoreFromBackup(backupBranch) {
|
|
298
|
+
const git = getGit();
|
|
299
|
+
try {
|
|
300
|
+
await git.raw(["rev-parse", "--verify", backupBranch]);
|
|
301
|
+
await git.raw(["reset", "--hard", backupBranch]);
|
|
302
|
+
await git.raw(["branch", "-D", backupBranch]);
|
|
303
|
+
return { success: true };
|
|
304
|
+
} catch (err) {
|
|
305
|
+
return {
|
|
306
|
+
success: false,
|
|
307
|
+
error: `\u56DE\u9000\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8\u6267\u884C: git reset --hard ${backupBranch}
|
|
308
|
+
${err.message}`
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
async function deleteBackupBranch(backupBranch) {
|
|
313
|
+
const git = getGit();
|
|
314
|
+
try {
|
|
315
|
+
await git.raw(["branch", "-D", backupBranch]);
|
|
316
|
+
} catch {
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
async function getCurrentBranch() {
|
|
320
|
+
const git = getGit();
|
|
321
|
+
const result = await git.raw(["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
322
|
+
return result.trim();
|
|
323
|
+
}
|
|
324
|
+
async function createBranchFrom(newBranch, baseBranch) {
|
|
325
|
+
const git = getGit();
|
|
326
|
+
await git.raw(["checkout", "-b", newBranch, baseBranch]);
|
|
327
|
+
}
|
|
270
328
|
async function isWorkingDirClean() {
|
|
271
329
|
const git = getGit();
|
|
272
330
|
const status = await git.status();
|
|
@@ -290,6 +348,87 @@ async function stashPop() {
|
|
|
290
348
|
return false;
|
|
291
349
|
}
|
|
292
350
|
}
|
|
351
|
+
async function abortCherryPick() {
|
|
352
|
+
const git = getGit();
|
|
353
|
+
try {
|
|
354
|
+
await git.raw(["cherry-pick", "--abort"]);
|
|
355
|
+
} catch {
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
async function getConflictFiles() {
|
|
359
|
+
const git = getGit();
|
|
360
|
+
const status = await git.status();
|
|
361
|
+
return status.conflicted;
|
|
362
|
+
}
|
|
363
|
+
async function continueCherryPick() {
|
|
364
|
+
const git = getGit();
|
|
365
|
+
try {
|
|
366
|
+
await git.raw(["cherry-pick", "--continue", "--no-edit"]);
|
|
367
|
+
return { success: true };
|
|
368
|
+
} catch (err) {
|
|
369
|
+
const msg = err.message || "";
|
|
370
|
+
if (msg.includes("nothing to commit") || msg.includes("empty") || msg.includes("allow-empty")) {
|
|
371
|
+
return { success: false, error: msg, empty: true };
|
|
372
|
+
}
|
|
373
|
+
try {
|
|
374
|
+
const status = await git.status();
|
|
375
|
+
const conflictFiles = status.conflicted;
|
|
376
|
+
return {
|
|
377
|
+
success: false,
|
|
378
|
+
error: msg,
|
|
379
|
+
conflictFiles: conflictFiles.length > 0 ? conflictFiles : void 0
|
|
380
|
+
};
|
|
381
|
+
} catch {
|
|
382
|
+
return { success: false, error: msg };
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
async function clearCherryPickState() {
|
|
387
|
+
try {
|
|
388
|
+
const gitDir = await getGitDir();
|
|
389
|
+
const cpHead = join(gitDir, "CHERRY_PICK_HEAD");
|
|
390
|
+
if (existsSync(cpHead)) {
|
|
391
|
+
unlinkSync(cpHead);
|
|
392
|
+
}
|
|
393
|
+
} catch {
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
async function cherryPickOne(hash, useMainline = false, noCommit = true) {
|
|
397
|
+
const git = getGit();
|
|
398
|
+
try {
|
|
399
|
+
const args = ["cherry-pick"];
|
|
400
|
+
if (noCommit) args.push("--no-commit");
|
|
401
|
+
if (useMainline) args.push("-m", "1");
|
|
402
|
+
args.push(hash);
|
|
403
|
+
await git.raw(args);
|
|
404
|
+
return { success: true };
|
|
405
|
+
} catch (err) {
|
|
406
|
+
try {
|
|
407
|
+
const status = await git.status();
|
|
408
|
+
const conflictFiles = status.conflicted;
|
|
409
|
+
return {
|
|
410
|
+
success: false,
|
|
411
|
+
error: err.message,
|
|
412
|
+
conflictFiles: conflictFiles.length > 0 ? conflictFiles : void 0
|
|
413
|
+
};
|
|
414
|
+
} catch {
|
|
415
|
+
return { success: false, error: err.message };
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
async function skipCherryPick() {
|
|
420
|
+
const git = getGit();
|
|
421
|
+
await git.raw(["cherry-pick", "--skip"]);
|
|
422
|
+
}
|
|
423
|
+
async function isCherryPickInProgress() {
|
|
424
|
+
const git = getGit();
|
|
425
|
+
try {
|
|
426
|
+
const gitDir = await getGitDir();
|
|
427
|
+
return existsSync(join(gitDir, "CHERRY_PICK_HEAD"));
|
|
428
|
+
} catch {
|
|
429
|
+
return false;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
293
432
|
var STASH_GUARD_FILE = "git-sync-tui-stash-guard";
|
|
294
433
|
async function getGitDir() {
|
|
295
434
|
const git = getGit();
|
|
@@ -393,10 +532,10 @@ function StashRecovery({ timestamp, onRecover, onSkip }) {
|
|
|
393
532
|
// src/components/remote-select.tsx
|
|
394
533
|
import { useState as useState3 } from "react";
|
|
395
534
|
import { Box as Box4, Text as Text4, useInput as useInput3 } from "ink";
|
|
396
|
-
import {
|
|
535
|
+
import { Spinner as Spinner2, TextInput } from "@inkjs/ui";
|
|
397
536
|
|
|
398
537
|
// src/hooks/use-git.ts
|
|
399
|
-
import { useState as useState2, useEffect as useEffect2, useCallback } from "react";
|
|
538
|
+
import { useState as useState2, useEffect as useEffect2, useCallback, useRef } from "react";
|
|
400
539
|
function useAsync(fn, deps = []) {
|
|
401
540
|
const [state, setState] = useState2({
|
|
402
541
|
data: null,
|
|
@@ -426,11 +565,49 @@ function useBranches(remote2) {
|
|
|
426
565
|
[remote2]
|
|
427
566
|
);
|
|
428
567
|
}
|
|
429
|
-
function useCommits(remote2, branch2,
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
);
|
|
568
|
+
function useCommits(remote2, branch2, pageSize = 100) {
|
|
569
|
+
const [data, setData] = useState2(null);
|
|
570
|
+
const [loading, setLoading] = useState2(true);
|
|
571
|
+
const [loadingMore, setLoadingMore] = useState2(false);
|
|
572
|
+
const [error2, setError] = useState2(null);
|
|
573
|
+
const [hasMore, setHasMore] = useState2(true);
|
|
574
|
+
const loadedRef = useRef(0);
|
|
575
|
+
useEffect2(() => {
|
|
576
|
+
if (!remote2 || !branch2) {
|
|
577
|
+
setData([]);
|
|
578
|
+
setLoading(false);
|
|
579
|
+
setHasMore(false);
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
setData(null);
|
|
583
|
+
setLoading(true);
|
|
584
|
+
setError(null);
|
|
585
|
+
setHasMore(true);
|
|
586
|
+
loadedRef.current = 0;
|
|
587
|
+
getUnsyncedCommits(remote2, branch2, pageSize).then((commits2) => {
|
|
588
|
+
setData(commits2);
|
|
589
|
+
setLoading(false);
|
|
590
|
+
loadedRef.current = commits2.length;
|
|
591
|
+
setHasMore(commits2.length >= pageSize);
|
|
592
|
+
}).catch((err) => {
|
|
593
|
+
setError(err.message);
|
|
594
|
+
setLoading(false);
|
|
595
|
+
});
|
|
596
|
+
}, [remote2, branch2, pageSize]);
|
|
597
|
+
const loadMore = useCallback(async () => {
|
|
598
|
+
if (!remote2 || !branch2 || loadingMore || !hasMore) return;
|
|
599
|
+
setLoadingMore(true);
|
|
600
|
+
try {
|
|
601
|
+
const nextCount = loadedRef.current + pageSize;
|
|
602
|
+
const allCommits = await getUnsyncedCommits(remote2, branch2, nextCount);
|
|
603
|
+
setData(allCommits);
|
|
604
|
+
setHasMore(allCommits.length >= nextCount);
|
|
605
|
+
loadedRef.current = allCommits.length;
|
|
606
|
+
} catch {
|
|
607
|
+
}
|
|
608
|
+
setLoadingMore(false);
|
|
609
|
+
}, [remote2, branch2, pageSize, loadingMore, hasMore]);
|
|
610
|
+
return { data, loading, loadingMore, error: error2, hasMore, loadMore };
|
|
434
611
|
}
|
|
435
612
|
function useCommitStat(hashes) {
|
|
436
613
|
const [stat, setStat] = useState2("");
|
|
@@ -462,16 +639,32 @@ function extractRemoteName(url) {
|
|
|
462
639
|
function RemoteSelect({ onSelect, onBack }) {
|
|
463
640
|
const { data: remotes, loading, error: error2, reload } = useRemotes();
|
|
464
641
|
const [phase, setPhase] = useState3("list");
|
|
642
|
+
const [cursorIndex, setCursorIndex] = useState3(0);
|
|
465
643
|
const [customUrl, setCustomUrl] = useState3("");
|
|
466
644
|
const [addError, setAddError] = useState3(null);
|
|
467
|
-
|
|
645
|
+
const totalItems = (remotes?.length || 0) + 1;
|
|
646
|
+
useInput3((input, key) => {
|
|
647
|
+
if (phase !== "list") {
|
|
648
|
+
if (key.escape) {
|
|
649
|
+
if (phase === "input-name") {
|
|
650
|
+
setPhase("input-url");
|
|
651
|
+
} else if (phase === "input-url") {
|
|
652
|
+
setPhase("list");
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
468
657
|
if (key.escape) {
|
|
469
|
-
|
|
658
|
+
onBack?.();
|
|
659
|
+
} else if (key.upArrow) {
|
|
660
|
+
setCursorIndex((prev) => Math.max(0, prev - 1));
|
|
661
|
+
} else if (key.downArrow) {
|
|
662
|
+
setCursorIndex((prev) => Math.min(totalItems - 1, prev + 1));
|
|
663
|
+
} else if (key.return) {
|
|
664
|
+
if (remotes && cursorIndex < remotes.length) {
|
|
665
|
+
onSelect(remotes[cursorIndex].name);
|
|
666
|
+
} else {
|
|
470
667
|
setPhase("input-url");
|
|
471
|
-
} else if (phase === "input-url") {
|
|
472
|
-
setPhase("list");
|
|
473
|
-
} else if (phase === "list") {
|
|
474
|
-
onBack?.();
|
|
475
668
|
}
|
|
476
669
|
}
|
|
477
670
|
});
|
|
@@ -480,7 +673,8 @@ function RemoteSelect({ onSelect, onBack }) {
|
|
|
480
673
|
}
|
|
481
674
|
if (error2) {
|
|
482
675
|
return /* @__PURE__ */ jsxs4(Text4, { color: "red", children: [
|
|
483
|
-
"\u2716
|
|
676
|
+
"\u2716 ",
|
|
677
|
+
"\u83B7\u53D6\u8FDC\u7A0B\u4ED3\u5E93\u5931\u8D25: ",
|
|
484
678
|
error2
|
|
485
679
|
] });
|
|
486
680
|
}
|
|
@@ -511,7 +705,10 @@ function RemoteSelect({ onSelect, onBack }) {
|
|
|
511
705
|
}
|
|
512
706
|
)
|
|
513
707
|
] }),
|
|
514
|
-
/* @__PURE__ */
|
|
708
|
+
/* @__PURE__ */ jsxs4(Text4, { color: "gray", dimColor: true, children: [
|
|
709
|
+
" ",
|
|
710
|
+
"\u652F\u6301 HTTPS / SSH \u5730\u5740"
|
|
711
|
+
] })
|
|
515
712
|
] });
|
|
516
713
|
}
|
|
517
714
|
if (phase === "input-name") {
|
|
@@ -555,99 +752,187 @@ function RemoteSelect({ onSelect, onBack }) {
|
|
|
555
752
|
] })
|
|
556
753
|
] });
|
|
557
754
|
}
|
|
558
|
-
const
|
|
559
|
-
|
|
560
|
-
label: `${r.name} ${r.fetchUrl}`,
|
|
561
|
-
value: r.name
|
|
562
|
-
})),
|
|
563
|
-
{
|
|
564
|
-
label: "+ \u6DFB\u52A0\u8FDC\u7A0B\u4ED3\u5E93...",
|
|
565
|
-
value: "__add_custom__"
|
|
566
|
-
}
|
|
567
|
-
];
|
|
568
|
-
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", gap: 1, children: [
|
|
755
|
+
const maxNameLen = Math.max(...(remotes || []).map((r) => r.name.length), 0);
|
|
756
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
569
757
|
/* @__PURE__ */ jsx4(SectionHeader, { title: "\u9009\u62E9\u8FDC\u7A0B\u4ED3\u5E93" }),
|
|
570
|
-
/* @__PURE__ */
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
758
|
+
/* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: 1, children: [
|
|
759
|
+
(remotes || []).map((r, i) => {
|
|
760
|
+
const isCursor = i === cursorIndex;
|
|
761
|
+
return /* @__PURE__ */ jsxs4(Box4, { children: [
|
|
762
|
+
/* @__PURE__ */ jsx4(Text4, { color: isCursor ? "cyan" : "gray", children: isCursor ? "\u203A" : " " }),
|
|
763
|
+
/* @__PURE__ */ jsx4(Text4, { children: " " }),
|
|
764
|
+
/* @__PURE__ */ jsx4(Text4, { color: isCursor ? "cyan" : "white", bold: isCursor, children: r.name.padEnd(maxNameLen + 2) }),
|
|
765
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray", dimColor: true, children: r.fetchUrl })
|
|
766
|
+
] }, r.name);
|
|
767
|
+
}),
|
|
768
|
+
/* @__PURE__ */ jsxs4(Box4, { children: [
|
|
769
|
+
/* @__PURE__ */ jsx4(Text4, { color: cursorIndex === (remotes?.length || 0) ? "cyan" : "gray", children: cursorIndex === (remotes?.length || 0) ? "\u203A" : " " }),
|
|
770
|
+
/* @__PURE__ */ jsx4(Text4, { children: " " }),
|
|
771
|
+
/* @__PURE__ */ jsx4(Text4, { color: "green", dimColor: cursorIndex !== (remotes?.length || 0), children: "+ \u6DFB\u52A0\u8FDC\u7A0B\u4ED3\u5E93..." })
|
|
772
|
+
] })
|
|
773
|
+
] })
|
|
583
774
|
] });
|
|
584
775
|
}
|
|
585
776
|
|
|
586
777
|
// src/components/branch-select.tsx
|
|
587
778
|
import { useState as useState4, useMemo } from "react";
|
|
588
779
|
import { Box as Box5, Text as Text5, useInput as useInput4 } from "ink";
|
|
589
|
-
import {
|
|
780
|
+
import { Spinner as Spinner3, TextInput as TextInput2 } from "@inkjs/ui";
|
|
590
781
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
591
782
|
function BranchSelect({ remote: remote2, onSelect, onBack }) {
|
|
592
783
|
const { data: branches, loading, error: error2 } = useBranches(remote2);
|
|
593
784
|
const [filter, setFilter] = useState4("");
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
});
|
|
597
|
-
const filteredOptions = useMemo(() => {
|
|
785
|
+
const [cursorIndex, setCursorIndex] = useState4(0);
|
|
786
|
+
const filteredBranches = useMemo(() => {
|
|
598
787
|
if (!branches) return [];
|
|
599
|
-
|
|
600
|
-
return filtered.map((b) => ({ label: b, value: b }));
|
|
788
|
+
return filter ? branches.filter((b) => b.toLowerCase().includes(filter.toLowerCase())) : branches;
|
|
601
789
|
}, [branches, filter]);
|
|
790
|
+
const visibleCount = 10;
|
|
791
|
+
const startIdx = Math.max(0, Math.min(cursorIndex - Math.floor(visibleCount / 2), filteredBranches.length - visibleCount));
|
|
792
|
+
const visibleBranches = filteredBranches.slice(startIdx, startIdx + visibleCount);
|
|
793
|
+
useInput4((input, key) => {
|
|
794
|
+
if (key.escape) {
|
|
795
|
+
onBack?.();
|
|
796
|
+
} else if (key.upArrow) {
|
|
797
|
+
setCursorIndex((prev) => Math.max(0, prev - 1));
|
|
798
|
+
} else if (key.downArrow) {
|
|
799
|
+
setCursorIndex((prev) => Math.min(filteredBranches.length - 1, prev + 1));
|
|
800
|
+
} else if (key.return) {
|
|
801
|
+
if (filteredBranches.length > 0) {
|
|
802
|
+
onSelect(filteredBranches[cursorIndex]);
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
});
|
|
602
806
|
if (loading) {
|
|
603
807
|
return /* @__PURE__ */ jsx5(Spinner3, { label: `\u83B7\u53D6 ${remote2} \u7684\u5206\u652F\u5217\u8868...` });
|
|
604
808
|
}
|
|
605
809
|
if (error2) {
|
|
606
810
|
return /* @__PURE__ */ jsxs5(Text5, { color: "red", children: [
|
|
607
|
-
"\u2716
|
|
811
|
+
"\u2716 ",
|
|
812
|
+
"\u83B7\u53D6\u5206\u652F\u5217\u8868\u5931\u8D25: ",
|
|
608
813
|
error2
|
|
609
814
|
] });
|
|
610
815
|
}
|
|
611
816
|
if (!branches || branches.length === 0) {
|
|
612
|
-
return /* @__PURE__ */
|
|
817
|
+
return /* @__PURE__ */ jsxs5(Text5, { color: "red", children: [
|
|
818
|
+
"\u2716 ",
|
|
819
|
+
"\u672A\u627E\u5230\u8FDC\u7A0B\u5206\u652F"
|
|
820
|
+
] });
|
|
613
821
|
}
|
|
614
|
-
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column",
|
|
615
|
-
/* @__PURE__ */ jsx5(SectionHeader, { title:
|
|
616
|
-
/* @__PURE__ */ jsxs5(Box5, { children: [
|
|
617
|
-
/* @__PURE__ */ jsx5(Text5, { color: "
|
|
822
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
823
|
+
/* @__PURE__ */ jsx5(SectionHeader, { title: "\u9009\u62E9\u5206\u652F", subtitle: `${remote2} \xB7 ${branches.length} \u4E2A\u5206\u652F` }),
|
|
824
|
+
/* @__PURE__ */ jsxs5(Box5, { marginTop: 1, children: [
|
|
825
|
+
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "/ " }),
|
|
618
826
|
/* @__PURE__ */ jsx5(
|
|
619
827
|
TextInput2,
|
|
620
828
|
{
|
|
621
829
|
placeholder: "\u8F93\u5165\u5173\u952E\u5B57\u8FC7\u6EE4...",
|
|
622
|
-
onChange:
|
|
830
|
+
onChange: (val) => {
|
|
831
|
+
setFilter(val);
|
|
832
|
+
setCursorIndex(0);
|
|
833
|
+
}
|
|
623
834
|
}
|
|
624
835
|
),
|
|
625
836
|
filter && /* @__PURE__ */ jsxs5(Text5, { color: "gray", dimColor: true, children: [
|
|
626
837
|
" \xB7 \u5339\u914D ",
|
|
627
|
-
|
|
838
|
+
filteredBranches.length
|
|
628
839
|
] })
|
|
629
840
|
] }),
|
|
630
|
-
|
|
841
|
+
filteredBranches.length > 0 ? /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginTop: 1, children: [
|
|
842
|
+
startIdx > 0 && /* @__PURE__ */ jsxs5(Text5, { color: "gray", dimColor: true, children: [
|
|
843
|
+
" ",
|
|
844
|
+
"\u2191 ",
|
|
845
|
+
startIdx,
|
|
846
|
+
" more"
|
|
847
|
+
] }),
|
|
848
|
+
visibleBranches.map((b, i) => {
|
|
849
|
+
const actualIdx = startIdx + i;
|
|
850
|
+
const isCursor = actualIdx === cursorIndex;
|
|
851
|
+
return /* @__PURE__ */ jsxs5(Box5, { children: [
|
|
852
|
+
/* @__PURE__ */ jsx5(Text5, { color: isCursor ? "cyan" : "gray", children: isCursor ? "\u203A" : " " }),
|
|
853
|
+
/* @__PURE__ */ jsx5(Text5, { children: " " }),
|
|
854
|
+
/* @__PURE__ */ jsx5(Text5, { color: isCursor ? "cyan" : "white", bold: isCursor, children: b })
|
|
855
|
+
] }, b);
|
|
856
|
+
}),
|
|
857
|
+
startIdx + visibleCount < filteredBranches.length && /* @__PURE__ */ jsxs5(Text5, { color: "gray", dimColor: true, children: [
|
|
858
|
+
" ",
|
|
859
|
+
"\u2193 ",
|
|
860
|
+
filteredBranches.length - startIdx - visibleCount,
|
|
861
|
+
" more"
|
|
862
|
+
] })
|
|
863
|
+
] }) : /* @__PURE__ */ jsxs5(Text5, { color: "yellow", children: [
|
|
864
|
+
"\u25B2 ",
|
|
865
|
+
"\u65E0\u5339\u914D\u5206\u652F"
|
|
866
|
+
] })
|
|
631
867
|
] });
|
|
632
868
|
}
|
|
633
869
|
|
|
634
870
|
// src/components/commit-list.tsx
|
|
635
|
-
import { useState as useState5, useMemo as useMemo2, useRef } from "react";
|
|
871
|
+
import { useState as useState5, useMemo as useMemo2, useRef as useRef2, useEffect as useEffect3 } from "react";
|
|
636
872
|
import { Box as Box6, Text as Text6, useInput as useInput5 } from "ink";
|
|
637
873
|
import { Spinner as Spinner4 } from "@inkjs/ui";
|
|
638
874
|
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
875
|
+
function StatPanel({ stat, loading, count: count2 }) {
|
|
876
|
+
const STAT_HEIGHT = 8;
|
|
877
|
+
const [scrollOffset, setScrollOffset] = useState5(0);
|
|
878
|
+
const lines = useMemo2(() => stat ? stat.split("\n") : [], [stat]);
|
|
879
|
+
const canScroll = lines.length > STAT_HEIGHT;
|
|
880
|
+
useEffect3(() => {
|
|
881
|
+
setScrollOffset(0);
|
|
882
|
+
}, [stat]);
|
|
883
|
+
useInput5((input) => {
|
|
884
|
+
if (!canScroll) return;
|
|
885
|
+
if (input === "j") {
|
|
886
|
+
setScrollOffset((prev) => Math.min(prev + 1, lines.length - STAT_HEIGHT));
|
|
887
|
+
} else if (input === "k") {
|
|
888
|
+
setScrollOffset((prev) => Math.max(0, prev - 1));
|
|
889
|
+
}
|
|
890
|
+
});
|
|
891
|
+
const visibleLines = canScroll ? lines.slice(scrollOffset, scrollOffset + STAT_HEIGHT) : lines;
|
|
892
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
893
|
+
/* @__PURE__ */ jsxs6(Box6, { justifyContent: "space-between", children: [
|
|
894
|
+
/* @__PURE__ */ jsxs6(Text6, { bold: true, color: "cyan", children: [
|
|
895
|
+
"\u25C6 ",
|
|
896
|
+
"\u5DF2\u9009 ",
|
|
897
|
+
count2,
|
|
898
|
+
" \u4E2A commit \xB7 diff --stat"
|
|
899
|
+
] }),
|
|
900
|
+
canScroll && /* @__PURE__ */ jsxs6(Text6, { color: "gray", dimColor: true, children: [
|
|
901
|
+
scrollOffset + 1,
|
|
902
|
+
"-",
|
|
903
|
+
Math.min(scrollOffset + STAT_HEIGHT, lines.length),
|
|
904
|
+
"/",
|
|
905
|
+
lines.length,
|
|
906
|
+
" [j/k]"
|
|
907
|
+
] })
|
|
908
|
+
] }),
|
|
909
|
+
/* @__PURE__ */ jsx6(Box6, { flexDirection: "column", height: STAT_HEIGHT, children: loading ? /* @__PURE__ */ jsx6(Spinner4, { label: "\u52A0\u8F7D\u4E2D..." }) : visibleLines.length > 0 ? visibleLines.map((line, i) => /* @__PURE__ */ jsx6(Text6, { color: "gray", children: line }, scrollOffset + i)) : /* @__PURE__ */ jsx6(Text6, { color: "gray", dimColor: true, children: "(\u65E0\u53D8\u66F4)" }) })
|
|
910
|
+
] });
|
|
911
|
+
}
|
|
639
912
|
function CommitList({ remote: remote2, branch: branch2, onSelect, onBack }) {
|
|
640
|
-
const { data: commits2, loading, error: error2 } = useCommits(remote2, branch2,
|
|
913
|
+
const { data: commits2, loading, loadingMore, error: error2, hasMore, loadMore } = useCommits(remote2, branch2, 100);
|
|
641
914
|
const [selectedIndex, setSelectedIndex] = useState5(0);
|
|
642
915
|
const [selectedHashes, setSelectedHashes] = useState5(/* @__PURE__ */ new Set());
|
|
643
916
|
const [shiftMode, setShiftMode] = useState5(false);
|
|
644
|
-
const anchorIndexRef =
|
|
917
|
+
const anchorIndexRef = useRef2(null);
|
|
645
918
|
const selectedKey = useMemo2(() => Array.from(selectedHashes).sort().join(","), [selectedHashes]);
|
|
646
919
|
const selectedArray = useMemo2(() => Array.from(selectedHashes), [selectedKey]);
|
|
647
920
|
const { stat, loading: statLoading } = useCommitStat(selectedArray);
|
|
921
|
+
const syncedCount = useMemo2(() => {
|
|
922
|
+
if (!commits2) return 0;
|
|
923
|
+
return commits2.filter((c) => c.synced).length;
|
|
924
|
+
}, [commits2]);
|
|
925
|
+
useEffect3(() => {
|
|
926
|
+
if (!commits2 || !hasMore || loadingMore) return;
|
|
927
|
+
if (selectedIndex >= commits2.length - 5) {
|
|
928
|
+
loadMore();
|
|
929
|
+
}
|
|
930
|
+
}, [selectedIndex, commits2?.length, hasMore, loadingMore, loadMore]);
|
|
648
931
|
const toggleCurrent = () => {
|
|
649
932
|
if (!commits2 || commits2.length === 0) return;
|
|
650
|
-
const
|
|
933
|
+
const commit = commits2[selectedIndex];
|
|
934
|
+
if (commit.synced) return;
|
|
935
|
+
const hash = commit.hash;
|
|
651
936
|
setSelectedHashes((prev) => {
|
|
652
937
|
const next = new Set(prev);
|
|
653
938
|
if (next.has(hash)) {
|
|
@@ -667,19 +952,22 @@ function CommitList({ remote: remote2, branch: branch2, onSelect, onBack }) {
|
|
|
667
952
|
setSelectedHashes((prev) => {
|
|
668
953
|
const next = new Set(prev);
|
|
669
954
|
for (let i = start; i <= end; i++) {
|
|
670
|
-
|
|
955
|
+
if (!commits2[i].synced) {
|
|
956
|
+
next.add(commits2[i].hash);
|
|
957
|
+
}
|
|
671
958
|
}
|
|
672
959
|
return next;
|
|
673
960
|
});
|
|
674
961
|
};
|
|
675
962
|
const toggleAll = () => {
|
|
676
963
|
if (!commits2 || commits2.length === 0) return;
|
|
964
|
+
const unsyncedCommits = commits2.filter((c) => !c.synced);
|
|
677
965
|
setSelectedHashes((prev) => {
|
|
678
|
-
if (prev.size ===
|
|
966
|
+
if (prev.size === unsyncedCommits.length) {
|
|
679
967
|
anchorIndexRef.current = null;
|
|
680
968
|
return /* @__PURE__ */ new Set();
|
|
681
969
|
}
|
|
682
|
-
return new Set(
|
|
970
|
+
return new Set(unsyncedCommits.map((c) => c.hash));
|
|
683
971
|
});
|
|
684
972
|
};
|
|
685
973
|
const invertSelection = () => {
|
|
@@ -687,7 +975,7 @@ function CommitList({ remote: remote2, branch: branch2, onSelect, onBack }) {
|
|
|
687
975
|
setSelectedHashes((prev) => {
|
|
688
976
|
const next = /* @__PURE__ */ new Set();
|
|
689
977
|
for (const c of commits2) {
|
|
690
|
-
if (!prev.has(c.hash)) next.add(c.hash);
|
|
978
|
+
if (!c.synced && !prev.has(c.hash)) next.add(c.hash);
|
|
691
979
|
}
|
|
692
980
|
return next;
|
|
693
981
|
});
|
|
@@ -697,7 +985,9 @@ function CommitList({ remote: remote2, branch: branch2, onSelect, onBack }) {
|
|
|
697
985
|
setSelectedHashes((prev) => {
|
|
698
986
|
const next = new Set(prev);
|
|
699
987
|
for (let i = 0; i <= selectedIndex; i++) {
|
|
700
|
-
|
|
988
|
+
if (!commits2[i].synced) {
|
|
989
|
+
next.add(commits2[i].hash);
|
|
990
|
+
}
|
|
701
991
|
}
|
|
702
992
|
return next;
|
|
703
993
|
});
|
|
@@ -754,16 +1044,21 @@ function CommitList({ remote: remote2, branch: branch2, onSelect, onBack }) {
|
|
|
754
1044
|
}
|
|
755
1045
|
if (error2) {
|
|
756
1046
|
return /* @__PURE__ */ jsxs6(Text6, { color: "red", children: [
|
|
757
|
-
"\u2716
|
|
1047
|
+
"\u2716 ",
|
|
1048
|
+
"\u83B7\u53D6 commit \u5217\u8868\u5931\u8D25: ",
|
|
758
1049
|
error2
|
|
759
1050
|
] });
|
|
760
1051
|
}
|
|
761
1052
|
if (!commits2 || commits2.length === 0) {
|
|
762
|
-
return /* @__PURE__ */
|
|
1053
|
+
return /* @__PURE__ */ jsxs6(Text6, { color: "yellow", children: [
|
|
1054
|
+
"\u25B2 ",
|
|
1055
|
+
"\u8BE5\u5206\u652F\u6CA1\u6709 commit"
|
|
1056
|
+
] });
|
|
763
1057
|
}
|
|
764
1058
|
const visibleCount = 10;
|
|
765
1059
|
const startIdx = Math.max(0, Math.min(selectedIndex - Math.floor(visibleCount / 2), commits2.length - visibleCount));
|
|
766
1060
|
const visibleCommits = commits2.slice(startIdx, startIdx + visibleCount);
|
|
1061
|
+
const unsyncedTotal = commits2.length - syncedCount;
|
|
767
1062
|
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", gap: 1, children: [
|
|
768
1063
|
/* @__PURE__ */ jsx6(SectionHeader, { title: "\u9009\u62E9\u8981\u540C\u6B65\u7684 commit" }),
|
|
769
1064
|
/* @__PURE__ */ jsxs6(Box6, { gap: 2, children: [
|
|
@@ -774,17 +1069,28 @@ function CommitList({ remote: remote2, branch: branch2, onSelect, onBack }) {
|
|
|
774
1069
|
] }),
|
|
775
1070
|
/* @__PURE__ */ jsxs6(Text6, { color: "gray", dimColor: true, children: [
|
|
776
1071
|
commits2.length,
|
|
777
|
-
" commits"
|
|
1072
|
+
" commits",
|
|
1073
|
+
hasMore ? "+" : ""
|
|
1074
|
+
] }),
|
|
1075
|
+
syncedCount > 0 && /* @__PURE__ */ jsxs6(Text6, { color: "gray", dimColor: true, children: [
|
|
1076
|
+
syncedCount,
|
|
1077
|
+
" \u5DF2\u540C\u6B65"
|
|
1078
|
+
] }),
|
|
1079
|
+
/* @__PURE__ */ jsxs6(Text6, { color: "green", children: [
|
|
1080
|
+
unsyncedTotal,
|
|
1081
|
+
" \u5F85\u540C\u6B65"
|
|
778
1082
|
] }),
|
|
779
1083
|
/* @__PURE__ */ jsxs6(Text6, { color: selectedHashes.size > 0 ? "cyan" : "gray", bold: selectedHashes.size > 0, children: [
|
|
780
1084
|
"\u5DF2\u9009 ",
|
|
781
1085
|
selectedHashes.size
|
|
782
1086
|
] }),
|
|
783
|
-
shiftMode && /* @__PURE__ */ jsx6(Text6, { color: "yellow", bold: true, children: "SHIFT" })
|
|
1087
|
+
shiftMode && /* @__PURE__ */ jsx6(Text6, { color: "yellow", bold: true, children: "SHIFT" }),
|
|
1088
|
+
loadingMore && /* @__PURE__ */ jsx6(Text6, { color: "gray", dimColor: true, children: "\u52A0\u8F7D\u4E2D..." })
|
|
784
1089
|
] }),
|
|
785
1090
|
/* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
786
1091
|
startIdx > 0 && /* @__PURE__ */ jsxs6(Text6, { color: "gray", dimColor: true, children: [
|
|
787
|
-
"
|
|
1092
|
+
" ",
|
|
1093
|
+
"\u2191 ",
|
|
788
1094
|
startIdx,
|
|
789
1095
|
" more"
|
|
790
1096
|
] }),
|
|
@@ -793,30 +1099,60 @@ function CommitList({ remote: remote2, branch: branch2, onSelect, onBack }) {
|
|
|
793
1099
|
const isSelected = selectedHashes.has(c.hash);
|
|
794
1100
|
const isCursor = actualIdx === selectedIndex;
|
|
795
1101
|
const isAnchor = actualIdx === anchorIndexRef.current;
|
|
1102
|
+
const isSynced = !!c.synced;
|
|
796
1103
|
return /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
797
|
-
/* @__PURE__ */ jsxs6(
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
1104
|
+
/* @__PURE__ */ jsxs6(
|
|
1105
|
+
Text6,
|
|
1106
|
+
{
|
|
1107
|
+
backgroundColor: isCursor ? isSynced ? "gray" : "blue" : void 0,
|
|
1108
|
+
color: isSynced ? "gray" : isSelected ? "green" : "white",
|
|
1109
|
+
dimColor: isSynced,
|
|
1110
|
+
children: [
|
|
1111
|
+
isCursor ? "\u25B8 " : " ",
|
|
1112
|
+
isSynced ? "\u2713" : isAnchor ? "\u2693" : isSelected ? "\u25CF" : "\u25CB",
|
|
1113
|
+
" "
|
|
1114
|
+
]
|
|
1115
|
+
}
|
|
1116
|
+
),
|
|
1117
|
+
/* @__PURE__ */ jsx6(
|
|
1118
|
+
Text6,
|
|
1119
|
+
{
|
|
1120
|
+
backgroundColor: isCursor ? isSynced ? "gray" : "blue" : void 0,
|
|
1121
|
+
color: isSynced ? "gray" : "yellow",
|
|
1122
|
+
dimColor: isSynced,
|
|
1123
|
+
children: c.shortHash
|
|
1124
|
+
}
|
|
1125
|
+
),
|
|
1126
|
+
/* @__PURE__ */ jsxs6(
|
|
1127
|
+
Text6,
|
|
1128
|
+
{
|
|
1129
|
+
backgroundColor: isCursor ? isSynced ? "gray" : "blue" : void 0,
|
|
1130
|
+
color: isSynced ? "gray" : isSelected ? "green" : "white",
|
|
1131
|
+
dimColor: isSynced,
|
|
1132
|
+
children: [
|
|
1133
|
+
" ",
|
|
1134
|
+
c.message
|
|
1135
|
+
]
|
|
1136
|
+
}
|
|
1137
|
+
),
|
|
807
1138
|
/* @__PURE__ */ jsxs6(Text6, { color: "gray", dimColor: true, children: [
|
|
808
1139
|
" ",
|
|
809
1140
|
c.author,
|
|
810
1141
|
" \xB7 ",
|
|
811
1142
|
c.date
|
|
812
|
-
] })
|
|
1143
|
+
] }),
|
|
1144
|
+
isSynced && /* @__PURE__ */ jsx6(Text6, { color: "gray", dimColor: true, children: " [\u5DF2\u540C\u6B65]" })
|
|
813
1145
|
] }, c.hash);
|
|
814
1146
|
}),
|
|
815
|
-
startIdx + visibleCount < commits2.length
|
|
816
|
-
"
|
|
1147
|
+
startIdx + visibleCount < commits2.length ? /* @__PURE__ */ jsxs6(Text6, { color: "gray", dimColor: true, children: [
|
|
1148
|
+
" ",
|
|
1149
|
+
"\u2193 ",
|
|
817
1150
|
commits2.length - startIdx - visibleCount,
|
|
818
1151
|
" more"
|
|
819
|
-
] })
|
|
1152
|
+
] }) : hasMore ? /* @__PURE__ */ jsxs6(Text6, { color: "gray", dimColor: true, children: [
|
|
1153
|
+
" ",
|
|
1154
|
+
"\u2193 \u6EDA\u52A8\u52A0\u8F7D\u66F4\u591A..."
|
|
1155
|
+
] }) : null
|
|
820
1156
|
] }),
|
|
821
1157
|
/* @__PURE__ */ jsx6(KeyHints, { hints: [
|
|
822
1158
|
{ key: "\u2191\u2193", label: "\u5BFC\u822A" },
|
|
@@ -828,15 +1164,111 @@ function CommitList({ remote: remote2, branch: branch2, onSelect, onBack }) {
|
|
|
828
1164
|
{ key: "Enter", label: "\u786E\u8BA4" },
|
|
829
1165
|
{ key: "Esc", label: "\u8FD4\u56DE" }
|
|
830
1166
|
] }),
|
|
831
|
-
selectedHashes.size > 0 && /* @__PURE__ */ jsx6(
|
|
1167
|
+
selectedHashes.size > 0 && /* @__PURE__ */ jsx6(StatPanel, { stat, loading: statLoading, count: selectedHashes.size })
|
|
832
1168
|
] });
|
|
833
1169
|
}
|
|
834
1170
|
|
|
835
|
-
// src/components/
|
|
1171
|
+
// src/components/branch-check.tsx
|
|
1172
|
+
import { useState as useState6, useEffect as useEffect4, useRef as useRef3 } from "react";
|
|
836
1173
|
import { Box as Box7, Text as Text7, useInput as useInput6 } from "ink";
|
|
1174
|
+
import { Spinner as Spinner5 } from "@inkjs/ui";
|
|
837
1175
|
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
838
|
-
|
|
1176
|
+
var BASE_BRANCHES = ["main", "master"];
|
|
1177
|
+
function BranchCheck({ targetBranch, onContinue, onBack }) {
|
|
1178
|
+
const [currentBranch, setCurrentBranch] = useState6(null);
|
|
1179
|
+
const [creating, setCreating] = useState6(false);
|
|
1180
|
+
const [error2, setError] = useState6(null);
|
|
1181
|
+
const [matched, setMatched] = useState6(false);
|
|
1182
|
+
const autoCreated = useRef3(false);
|
|
1183
|
+
useEffect4(() => {
|
|
1184
|
+
getCurrentBranch().then((branch2) => {
|
|
1185
|
+
setCurrentBranch(branch2);
|
|
1186
|
+
if (branch2 === targetBranch) {
|
|
1187
|
+
setMatched(true);
|
|
1188
|
+
}
|
|
1189
|
+
});
|
|
1190
|
+
}, [targetBranch]);
|
|
1191
|
+
useEffect4(() => {
|
|
1192
|
+
if (matched) onContinue();
|
|
1193
|
+
}, [matched]);
|
|
1194
|
+
useEffect4(() => {
|
|
1195
|
+
if (currentBranch === null || matched || autoCreated.current) return;
|
|
1196
|
+
if (!BASE_BRANCHES.includes(currentBranch)) return;
|
|
1197
|
+
autoCreated.current = true;
|
|
1198
|
+
setCreating(true);
|
|
1199
|
+
createBranchFrom(targetBranch, currentBranch).then(() => {
|
|
1200
|
+
onContinue();
|
|
1201
|
+
}).catch((err) => {
|
|
1202
|
+
setCreating(false);
|
|
1203
|
+
setError(err.message);
|
|
1204
|
+
});
|
|
1205
|
+
}, [currentBranch, matched, targetBranch]);
|
|
1206
|
+
const doCreate = () => {
|
|
1207
|
+
if (!currentBranch) return;
|
|
1208
|
+
setCreating(true);
|
|
1209
|
+
setError(null);
|
|
1210
|
+
createBranchFrom(targetBranch, currentBranch).then(() => {
|
|
1211
|
+
onContinue();
|
|
1212
|
+
}).catch((err) => {
|
|
1213
|
+
setCreating(false);
|
|
1214
|
+
setError(err.message);
|
|
1215
|
+
});
|
|
1216
|
+
};
|
|
839
1217
|
useInput6((input, key) => {
|
|
1218
|
+
if (creating || currentBranch === null || matched) return;
|
|
1219
|
+
if (BASE_BRANCHES.includes(currentBranch)) return;
|
|
1220
|
+
if (input === "y" || input === "Y") {
|
|
1221
|
+
doCreate();
|
|
1222
|
+
} else if (input === "n" || input === "N") {
|
|
1223
|
+
onContinue();
|
|
1224
|
+
} else if (key.escape) {
|
|
1225
|
+
onBack?.();
|
|
1226
|
+
}
|
|
1227
|
+
});
|
|
1228
|
+
if (currentBranch === null || matched) {
|
|
1229
|
+
return /* @__PURE__ */ jsx7(Spinner5, { label: "\u68C0\u67E5\u5F53\u524D\u5206\u652F..." });
|
|
1230
|
+
}
|
|
1231
|
+
if (creating) {
|
|
1232
|
+
return /* @__PURE__ */ jsx7(Spinner5, { label: `\u6B63\u5728\u4ECE ${currentBranch} \u521B\u5EFA\u5206\u652F ${targetBranch}...` });
|
|
1233
|
+
}
|
|
1234
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", gap: 1, children: [
|
|
1235
|
+
/* @__PURE__ */ jsx7(SectionHeader, { title: "\u5206\u652F\u68C0\u67E5" }),
|
|
1236
|
+
/* @__PURE__ */ jsxs7(StatusPanel, { type: "warn", title: "\u5F53\u524D\u5206\u652F\u4E0E\u76EE\u6807\u5206\u652F\u4E0D\u4E00\u81F4", children: [
|
|
1237
|
+
/* @__PURE__ */ jsxs7(Box7, { children: [
|
|
1238
|
+
/* @__PURE__ */ jsx7(Text7, { color: "gray", children: " \u5F53\u524D\u5206\u652F: " }),
|
|
1239
|
+
/* @__PURE__ */ jsx7(Text7, { color: "yellow", bold: true, children: currentBranch })
|
|
1240
|
+
] }),
|
|
1241
|
+
/* @__PURE__ */ jsxs7(Box7, { children: [
|
|
1242
|
+
/* @__PURE__ */ jsx7(Text7, { color: "gray", children: " \u76EE\u6807\u5206\u652F: " }),
|
|
1243
|
+
/* @__PURE__ */ jsx7(Text7, { color: "cyan", bold: true, children: targetBranch })
|
|
1244
|
+
] })
|
|
1245
|
+
] }),
|
|
1246
|
+
error2 && /* @__PURE__ */ jsxs7(Text7, { color: "red", children: [
|
|
1247
|
+
"\u2716 ",
|
|
1248
|
+
error2
|
|
1249
|
+
] }),
|
|
1250
|
+
/* @__PURE__ */ jsxs7(Box7, { children: [
|
|
1251
|
+
/* @__PURE__ */ jsxs7(Text7, { bold: true, children: [
|
|
1252
|
+
"\u4ECE ",
|
|
1253
|
+
currentBranch,
|
|
1254
|
+
" \u521B\u5EFA ",
|
|
1255
|
+
targetBranch,
|
|
1256
|
+
" \u5206\u652F? "
|
|
1257
|
+
] }),
|
|
1258
|
+
/* @__PURE__ */ jsx7(InlineKeys, { hints: [
|
|
1259
|
+
{ key: "y", label: "\u521B\u5EFA\u5E76\u5207\u6362" },
|
|
1260
|
+
{ key: "n", label: "\u8DF3\u8FC7" },
|
|
1261
|
+
{ key: "Esc", label: "\u8FD4\u56DE" }
|
|
1262
|
+
] })
|
|
1263
|
+
] })
|
|
1264
|
+
] });
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
// src/components/confirm-panel.tsx
|
|
1268
|
+
import { Box as Box8, Text as Text8, useInput as useInput7 } from "ink";
|
|
1269
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1270
|
+
function ConfirmPanel({ commits: commits2, selectedHashes, hasMerge, useMainline, noCommit, onToggleMainline, onToggleNoCommit, onConfirm, onCancel }) {
|
|
1271
|
+
useInput7((input, key) => {
|
|
840
1272
|
if (key.escape) {
|
|
841
1273
|
onCancel();
|
|
842
1274
|
} else if (input === "y" || input === "Y") {
|
|
@@ -845,43 +1277,54 @@ function ConfirmPanel({ commits: commits2, selectedHashes, hasMerge, useMainline
|
|
|
845
1277
|
onCancel();
|
|
846
1278
|
} else if (hasMerge && (input === "m" || input === "M")) {
|
|
847
1279
|
onToggleMainline();
|
|
1280
|
+
} else if (input === "c" || input === "C") {
|
|
1281
|
+
onToggleNoCommit();
|
|
848
1282
|
}
|
|
849
1283
|
});
|
|
850
1284
|
const selectedCommits = selectedHashes.map((hash) => commits2.find((c) => c.hash === hash)).filter(Boolean);
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
/* @__PURE__ */
|
|
854
|
-
|
|
1285
|
+
const modeLabel = noCommit ? "--no-commit" : "\u9010\u4E2A\u63D0\u4EA4";
|
|
1286
|
+
return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", gap: 1, children: [
|
|
1287
|
+
/* @__PURE__ */ jsx8(SectionHeader, { title: "\u786E\u8BA4\u6267\u884C" }),
|
|
1288
|
+
/* @__PURE__ */ jsx8(StatusPanel, { type: "info", title: `cherry-pick \xB7 ${modeLabel} \xB7 ${selectedCommits.length} \u4E2A commit`, children: selectedCommits.map((c) => /* @__PURE__ */ jsxs8(Box8, { children: [
|
|
1289
|
+
/* @__PURE__ */ jsxs8(Text8, { color: "yellow", children: [
|
|
855
1290
|
" ",
|
|
856
1291
|
c.shortHash
|
|
857
1292
|
] }),
|
|
858
|
-
/* @__PURE__ */
|
|
1293
|
+
/* @__PURE__ */ jsxs8(Text8, { children: [
|
|
859
1294
|
" ",
|
|
860
1295
|
c.message
|
|
861
1296
|
] }),
|
|
862
|
-
/* @__PURE__ */
|
|
1297
|
+
/* @__PURE__ */ jsxs8(Text8, { color: "gray", dimColor: true, children: [
|
|
863
1298
|
" ",
|
|
864
1299
|
c.author
|
|
865
1300
|
] })
|
|
866
1301
|
] }, c.hash)) }),
|
|
867
|
-
|
|
868
|
-
/* @__PURE__ */
|
|
869
|
-
/* @__PURE__ */
|
|
870
|
-
|
|
871
|
-
/* @__PURE__ */
|
|
872
|
-
/* @__PURE__ */
|
|
873
|
-
|
|
1302
|
+
/* @__PURE__ */ jsxs8(Box8, { children: [
|
|
1303
|
+
/* @__PURE__ */ jsx8(Text8, { color: "cyan", children: "[c]" }),
|
|
1304
|
+
/* @__PURE__ */ jsx8(Text8, { children: " \u63D0\u4EA4\u6A21\u5F0F: " }),
|
|
1305
|
+
noCommit ? /* @__PURE__ */ jsxs8(Box8, { children: [
|
|
1306
|
+
/* @__PURE__ */ jsx8(Text8, { color: "yellow", bold: true, children: "--no-commit" }),
|
|
1307
|
+
/* @__PURE__ */ jsx8(Text8, { color: "gray", dimColor: true, children: " (\u6539\u52A8\u6682\u5B58\u5230\u5DE5\u4F5C\u533A\uFF0C\u9700\u624B\u52A8 commit)" })
|
|
1308
|
+
] }) : /* @__PURE__ */ jsxs8(Box8, { children: [
|
|
1309
|
+
/* @__PURE__ */ jsx8(Text8, { color: "green", bold: true, children: "\u9010\u4E2A\u63D0\u4EA4" }),
|
|
1310
|
+
/* @__PURE__ */ jsx8(Text8, { color: "gray", dimColor: true, children: " (\u4FDD\u7559\u539F\u59CB commit \u4FE1\u606F)" })
|
|
874
1311
|
] })
|
|
875
1312
|
] }),
|
|
876
|
-
/* @__PURE__ */
|
|
877
|
-
/* @__PURE__ */
|
|
878
|
-
/* @__PURE__ */
|
|
1313
|
+
hasMerge && /* @__PURE__ */ jsxs8(StatusPanel, { type: "warn", title: "\u68C0\u6D4B\u5230 Merge Commit", children: [
|
|
1314
|
+
/* @__PURE__ */ jsx8(Text8, { color: "gray", children: " Cherry-pick \u5408\u5E76\u63D0\u4EA4\u9700\u8981\u6307\u5B9A\u7236\u8282\u70B9 (-m 1)" }),
|
|
1315
|
+
/* @__PURE__ */ jsxs8(Box8, { children: [
|
|
1316
|
+
/* @__PURE__ */ jsx8(Text8, { children: " " }),
|
|
1317
|
+
/* @__PURE__ */ jsx8(Text8, { color: "cyan", children: "[m]" }),
|
|
1318
|
+
/* @__PURE__ */ jsx8(Text8, { children: " \u5207\u6362 -m 1: " }),
|
|
1319
|
+
useMainline ? /* @__PURE__ */ jsx8(Text8, { color: "green", bold: true, children: "\u5DF2\u542F\u7528" }) : /* @__PURE__ */ jsx8(Text8, { color: "gray", children: "\u672A\u542F\u7528" })
|
|
1320
|
+
] })
|
|
879
1321
|
] }),
|
|
880
|
-
/* @__PURE__ */
|
|
881
|
-
/* @__PURE__ */
|
|
882
|
-
/* @__PURE__ */
|
|
1322
|
+
/* @__PURE__ */ jsxs8(Box8, { children: [
|
|
1323
|
+
/* @__PURE__ */ jsx8(Text8, { bold: true, children: "\u786E\u8BA4\u6267\u884C? " }),
|
|
1324
|
+
/* @__PURE__ */ jsx8(InlineKeys, { hints: [
|
|
883
1325
|
{ key: "y", label: "\u786E\u8BA4" },
|
|
884
1326
|
{ key: "n", label: "\u53D6\u6D88" },
|
|
1327
|
+
{ key: "c", label: "\u5207\u6362\u63D0\u4EA4\u6A21\u5F0F" },
|
|
885
1328
|
...hasMerge ? [{ key: "m", label: "\u5207\u6362 -m 1" }] : [],
|
|
886
1329
|
{ key: "Esc", label: "\u8FD4\u56DE" }
|
|
887
1330
|
] })
|
|
@@ -890,92 +1333,295 @@ function ConfirmPanel({ commits: commits2, selectedHashes, hasMerge, useMainline
|
|
|
890
1333
|
}
|
|
891
1334
|
|
|
892
1335
|
// src/components/result-panel.tsx
|
|
893
|
-
import { useState as
|
|
894
|
-
import { Box as
|
|
895
|
-
import { Spinner as
|
|
896
|
-
import { jsx as
|
|
897
|
-
function ResultPanel({ selectedHashes, useMainline, stashed, onStashRestored, onDone }) {
|
|
898
|
-
const [phase, setPhase] =
|
|
899
|
-
const [
|
|
900
|
-
const [
|
|
901
|
-
const [
|
|
902
|
-
const
|
|
1336
|
+
import { useState as useState7, useEffect as useEffect5, useCallback as useCallback2, useRef as useRef4 } from "react";
|
|
1337
|
+
import { Box as Box9, Text as Text9, useInput as useInput8 } from "ink";
|
|
1338
|
+
import { Spinner as Spinner6 } from "@inkjs/ui";
|
|
1339
|
+
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1340
|
+
function ResultPanel({ selectedHashes, useMainline, noCommit, stashed, onStashRestored, onDone }) {
|
|
1341
|
+
const [phase, setPhase] = useState7("executing");
|
|
1342
|
+
const [conflictFiles, setConflictFiles] = useState7([]);
|
|
1343
|
+
const [currentIndex, setCurrentIndex] = useState7(0);
|
|
1344
|
+
const [stagedStat, setStagedStat] = useState7("");
|
|
1345
|
+
const [stashRestored, setStashRestored] = useState7(null);
|
|
1346
|
+
const [errorMsg, setErrorMsg] = useState7("");
|
|
1347
|
+
const [completedCount, setCompletedCount] = useState7(0);
|
|
1348
|
+
const [skippedCount, setSkippedCount] = useState7(0);
|
|
1349
|
+
const remainingRef = useRef4([]);
|
|
1350
|
+
const backupBranchRef = useRef4("");
|
|
1351
|
+
const orderedHashes = useRef4([...selectedHashes].reverse());
|
|
1352
|
+
const tryRestoreStash = useCallback2(async () => {
|
|
903
1353
|
if (!stashed) return true;
|
|
904
1354
|
setPhase("restoring");
|
|
905
1355
|
const ok = await stashPop();
|
|
906
1356
|
setStashRestored(ok);
|
|
907
1357
|
if (ok) onStashRestored();
|
|
908
1358
|
return ok;
|
|
909
|
-
};
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
const
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
1359
|
+
}, [stashed, onStashRestored]);
|
|
1360
|
+
const finishAll = useCallback2(async () => {
|
|
1361
|
+
if (noCommit) {
|
|
1362
|
+
const stat = await getStagedStat();
|
|
1363
|
+
setStagedStat(stat);
|
|
1364
|
+
}
|
|
1365
|
+
if (backupBranchRef.current) {
|
|
1366
|
+
await deleteBackupBranch(backupBranchRef.current);
|
|
1367
|
+
}
|
|
1368
|
+
await tryRestoreStash();
|
|
1369
|
+
setPhase("done");
|
|
1370
|
+
}, [noCommit, tryRestoreStash]);
|
|
1371
|
+
const executeFrom = useCallback2(async (startIndex) => {
|
|
1372
|
+
const hashes = orderedHashes.current;
|
|
1373
|
+
for (let i = startIndex; i < hashes.length; i++) {
|
|
1374
|
+
setCurrentIndex(i);
|
|
1375
|
+
const res = await cherryPickOne(hashes[i], useMainline, noCommit);
|
|
1376
|
+
if (!res.success) {
|
|
1377
|
+
setConflictFiles(res.conflictFiles || []);
|
|
1378
|
+
remainingRef.current = hashes.slice(i + 1);
|
|
1379
|
+
setPhase("conflict");
|
|
1380
|
+
return;
|
|
922
1381
|
}
|
|
1382
|
+
setCompletedCount((c) => c + 1);
|
|
923
1383
|
}
|
|
924
|
-
|
|
1384
|
+
await finishAll();
|
|
1385
|
+
}, [useMainline, noCommit, finishAll]);
|
|
1386
|
+
useEffect5(() => {
|
|
1387
|
+
createBackupBranch().then((branch2) => {
|
|
1388
|
+
backupBranchRef.current = branch2;
|
|
1389
|
+
executeFrom(0);
|
|
1390
|
+
});
|
|
925
1391
|
}, []);
|
|
1392
|
+
const continueRemaining = useCallback2(async () => {
|
|
1393
|
+
const remaining = remainingRef.current;
|
|
1394
|
+
if (remaining.length === 0) {
|
|
1395
|
+
await finishAll();
|
|
1396
|
+
return;
|
|
1397
|
+
}
|
|
1398
|
+
setPhase("executing");
|
|
1399
|
+
for (let i = 0; i < remaining.length; i++) {
|
|
1400
|
+
setCurrentIndex(orderedHashes.current.length - remaining.length + i);
|
|
1401
|
+
const res = await cherryPickOne(remaining[i], useMainline, noCommit);
|
|
1402
|
+
if (!res.success) {
|
|
1403
|
+
setConflictFiles(res.conflictFiles || []);
|
|
1404
|
+
remainingRef.current = remaining.slice(i + 1);
|
|
1405
|
+
setPhase("conflict");
|
|
1406
|
+
return;
|
|
1407
|
+
}
|
|
1408
|
+
setCompletedCount((c) => c + 1);
|
|
1409
|
+
}
|
|
1410
|
+
await finishAll();
|
|
1411
|
+
}, [useMainline, noCommit, finishAll]);
|
|
1412
|
+
const handleContinue = useCallback2(async () => {
|
|
1413
|
+
const conflicts = await getConflictFiles();
|
|
1414
|
+
if (conflicts.length > 0) {
|
|
1415
|
+
setConflictFiles(conflicts);
|
|
1416
|
+
setErrorMsg("\u4ECD\u6709\u672A\u89E3\u51B3\u7684\u51B2\u7A81\u6587\u4EF6\uFF0C\u8BF7\u5148\u89E3\u51B3\u5E76 git add");
|
|
1417
|
+
return;
|
|
1418
|
+
}
|
|
1419
|
+
setPhase("continuing");
|
|
1420
|
+
setErrorMsg("");
|
|
1421
|
+
const inProgress = await isCherryPickInProgress();
|
|
1422
|
+
if (noCommit) {
|
|
1423
|
+
if (inProgress) await clearCherryPickState();
|
|
1424
|
+
setCompletedCount((c) => c + 1);
|
|
1425
|
+
await continueRemaining();
|
|
1426
|
+
} else if (!inProgress) {
|
|
1427
|
+
setCompletedCount((c) => c + 1);
|
|
1428
|
+
await continueRemaining();
|
|
1429
|
+
} else {
|
|
1430
|
+
const contResult = await continueCherryPick();
|
|
1431
|
+
if (contResult.empty) {
|
|
1432
|
+
setPhase("empty");
|
|
1433
|
+
return;
|
|
1434
|
+
}
|
|
1435
|
+
if (!contResult.success) {
|
|
1436
|
+
setConflictFiles(contResult.conflictFiles || []);
|
|
1437
|
+
setErrorMsg("cherry-pick --continue \u5931\u8D25: " + (contResult.error || "").substring(0, 100));
|
|
1438
|
+
setPhase("conflict");
|
|
1439
|
+
return;
|
|
1440
|
+
}
|
|
1441
|
+
setCompletedCount((c) => c + 1);
|
|
1442
|
+
await continueRemaining();
|
|
1443
|
+
}
|
|
1444
|
+
}, [noCommit, continueRemaining]);
|
|
1445
|
+
const handleSkip = useCallback2(async () => {
|
|
1446
|
+
setPhase("continuing");
|
|
1447
|
+
setErrorMsg("");
|
|
1448
|
+
await skipCherryPick();
|
|
1449
|
+
setSkippedCount((c) => c + 1);
|
|
1450
|
+
await continueRemaining();
|
|
1451
|
+
}, [continueRemaining]);
|
|
1452
|
+
const handleAbort = useCallback2(async () => {
|
|
1453
|
+
setPhase("aborting");
|
|
1454
|
+
await abortCherryPick();
|
|
1455
|
+
if (backupBranchRef.current) {
|
|
1456
|
+
const result = await restoreFromBackup(backupBranchRef.current);
|
|
1457
|
+
if (!result.success) {
|
|
1458
|
+
setErrorMsg(result.error || "");
|
|
1459
|
+
}
|
|
1460
|
+
backupBranchRef.current = "";
|
|
1461
|
+
}
|
|
1462
|
+
await tryRestoreStash();
|
|
1463
|
+
setPhase("aborted");
|
|
1464
|
+
}, [tryRestoreStash]);
|
|
1465
|
+
useInput8((input, key) => {
|
|
1466
|
+
if (phase === "conflict") {
|
|
1467
|
+
if (input === "c" || input === "C") {
|
|
1468
|
+
handleContinue();
|
|
1469
|
+
} else if (input === "a" || input === "A") {
|
|
1470
|
+
handleAbort();
|
|
1471
|
+
} else if (input === "q" || input === "Q") {
|
|
1472
|
+
onDone();
|
|
1473
|
+
}
|
|
1474
|
+
} else if (phase === "empty") {
|
|
1475
|
+
if (input === "s" || input === "S") {
|
|
1476
|
+
handleSkip();
|
|
1477
|
+
} else if (input === "a" || input === "A") {
|
|
1478
|
+
handleAbort();
|
|
1479
|
+
} else if (input === "q" || input === "Q") {
|
|
1480
|
+
onDone();
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
});
|
|
926
1484
|
if (phase === "executing") {
|
|
927
|
-
|
|
1485
|
+
const mode = noCommit ? "--no-commit" : "";
|
|
1486
|
+
return /* @__PURE__ */ jsx9(Spinner6, { label: `cherry-pick ${mode} (${currentIndex + 1}/${orderedHashes.current.length})...` });
|
|
1487
|
+
}
|
|
1488
|
+
if (phase === "continuing") {
|
|
1489
|
+
return /* @__PURE__ */ jsx9(Spinner6, { label: "\u7EE7\u7EED cherry-pick..." });
|
|
1490
|
+
}
|
|
1491
|
+
if (phase === "aborting") {
|
|
1492
|
+
return /* @__PURE__ */ jsx9(Spinner6, { label: "\u6B63\u5728\u653E\u5F03 cherry-pick..." });
|
|
928
1493
|
}
|
|
929
1494
|
if (phase === "restoring") {
|
|
930
|
-
return /* @__PURE__ */
|
|
1495
|
+
return /* @__PURE__ */ jsx9(Spinner6, { label: "\u6062\u590D\u5DE5\u4F5C\u533A (git stash pop)..." });
|
|
931
1496
|
}
|
|
932
|
-
if (phase === "
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
1497
|
+
if (phase === "empty") {
|
|
1498
|
+
const total2 = orderedHashes.current.length;
|
|
1499
|
+
const currentHash = orderedHashes.current[total2 - remainingRef.current.length - 1];
|
|
1500
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", gap: 1, children: [
|
|
1501
|
+
/* @__PURE__ */ jsx9(SectionHeader, { title: "\u7A7A\u63D0\u4EA4" }),
|
|
1502
|
+
/* @__PURE__ */ jsx9(StatusPanel, { type: "warn", title: `commit ${currentHash?.substring(0, 7)} \u89E3\u51B3\u51B2\u7A81\u540E\u65E0\u5B9E\u9645\u53D8\u66F4`, children: /* @__PURE__ */ jsx9(Text9, { color: "gray", children: " \u8BE5 commit \u7684\u6240\u6709\u66F4\u6539\u5728\u51B2\u7A81\u89E3\u51B3\u8FC7\u7A0B\u4E2D\u5DF2\u88AB\u4E22\u5F03" }) }),
|
|
1503
|
+
/* @__PURE__ */ jsx9(Box9, { children: /* @__PURE__ */ jsx9(InlineKeys, { hints: [
|
|
1504
|
+
{ key: "s", label: "\u8DF3\u8FC7\u6B64 commit (skip)" },
|
|
1505
|
+
{ key: "a", label: "\u653E\u5F03\u5168\u90E8 (abort)" },
|
|
1506
|
+
{ key: "q", label: "\u9000\u51FA (\u4FDD\u7559\u5F53\u524D\u72B6\u6001)" }
|
|
1507
|
+
] }) })
|
|
1508
|
+
] });
|
|
1509
|
+
}
|
|
1510
|
+
if (phase === "conflict") {
|
|
1511
|
+
const total2 = orderedHashes.current.length;
|
|
1512
|
+
const doneCount = total2 - remainingRef.current.length - 1;
|
|
1513
|
+
const currentHash = orderedHashes.current[total2 - remainingRef.current.length - 1];
|
|
1514
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", gap: 1, children: [
|
|
1515
|
+
/* @__PURE__ */ jsx9(SectionHeader, { title: "Cherry-pick \u9047\u5230\u51B2\u7A81" }),
|
|
1516
|
+
/* @__PURE__ */ jsxs9(Box9, { gap: 2, children: [
|
|
1517
|
+
/* @__PURE__ */ jsxs9(Text9, { color: "gray", dimColor: true, children: [
|
|
1518
|
+
"\u8FDB\u5EA6: ",
|
|
1519
|
+
doneCount,
|
|
1520
|
+
"/",
|
|
1521
|
+
total2
|
|
1522
|
+
] }),
|
|
1523
|
+
/* @__PURE__ */ jsxs9(Text9, { color: "yellow", children: [
|
|
1524
|
+
"\u51B2\u7A81 commit: ",
|
|
1525
|
+
currentHash?.substring(0, 7)
|
|
1526
|
+
] }),
|
|
1527
|
+
remainingRef.current.length > 0 && /* @__PURE__ */ jsxs9(Text9, { color: "gray", dimColor: true, children: [
|
|
1528
|
+
"\u5269\u4F59: ",
|
|
1529
|
+
remainingRef.current.length
|
|
1530
|
+
] })
|
|
1531
|
+
] }),
|
|
1532
|
+
conflictFiles.length > 0 && /* @__PURE__ */ jsx9(StatusPanel, { type: "error", title: "\u51B2\u7A81\u6587\u4EF6", children: conflictFiles.map((f) => /* @__PURE__ */ jsxs9(Text9, { color: "red", children: [
|
|
936
1533
|
" ",
|
|
937
1534
|
f
|
|
938
1535
|
] }, f)) }),
|
|
939
|
-
/* @__PURE__ */
|
|
940
|
-
/* @__PURE__ */
|
|
941
|
-
/* @__PURE__ */
|
|
1536
|
+
/* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
|
|
1537
|
+
/* @__PURE__ */ jsx9(Text9, { color: "yellow", children: "\u25B8 \u8BF7\u5728\u53E6\u4E00\u4E2A\u7EC8\u7AEF\u4E2D\u624B\u52A8\u89E3\u51B3\u51B2\u7A81" }),
|
|
1538
|
+
/* @__PURE__ */ jsxs9(Text9, { color: "gray", dimColor: true, children: [
|
|
1539
|
+
" 1. \u7F16\u8F91\u51B2\u7A81\u6587\u4EF6\uFF0C\u89E3\u51B3\u51B2\u7A81\u6807\u8BB0 ",
|
|
1540
|
+
"<<<<<<< / ======= / >>>>>>>"
|
|
1541
|
+
] }),
|
|
1542
|
+
/* @__PURE__ */ jsxs9(Text9, { color: "gray", dimColor: true, children: [
|
|
1543
|
+
" 2. \u6267\u884C git add ",
|
|
1544
|
+
"<file>",
|
|
1545
|
+
" \u6807\u8BB0\u5DF2\u89E3\u51B3"
|
|
1546
|
+
] }),
|
|
1547
|
+
/* @__PURE__ */ jsx9(Text9, { color: "gray", dimColor: true, children: " 3. \u56DE\u5230\u6B64\u5904\u6309 [c] \u7EE7\u7EED" })
|
|
942
1548
|
] }),
|
|
943
|
-
|
|
944
|
-
|
|
1549
|
+
errorMsg && /* @__PURE__ */ jsxs9(Text9, { color: "red", children: [
|
|
1550
|
+
"\u2716 ",
|
|
1551
|
+
errorMsg
|
|
1552
|
+
] }),
|
|
1553
|
+
/* @__PURE__ */ jsx9(Box9, { children: /* @__PURE__ */ jsx9(InlineKeys, { hints: [
|
|
1554
|
+
{ key: "c", label: "\u7EE7\u7EED (\u51B2\u7A81\u5DF2\u89E3\u51B3)" },
|
|
1555
|
+
{ key: "a", label: "\u653E\u5F03 (abort)" },
|
|
1556
|
+
{ key: "q", label: "\u9000\u51FA (\u4FDD\u7559\u5F53\u524D\u72B6\u6001)" }
|
|
1557
|
+
] }) })
|
|
945
1558
|
] });
|
|
946
1559
|
}
|
|
947
|
-
|
|
948
|
-
/* @__PURE__ */
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
/* @__PURE__ */
|
|
954
|
-
|
|
1560
|
+
if (phase === "aborted") {
|
|
1561
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", gap: 1, children: [
|
|
1562
|
+
/* @__PURE__ */ jsx9(SectionHeader, { title: "\u5DF2\u653E\u5F03\u64CD\u4F5C" }),
|
|
1563
|
+
errorMsg ? /* @__PURE__ */ jsx9(Box9, { flexDirection: "column", children: /* @__PURE__ */ jsxs9(Text9, { color: "red", children: [
|
|
1564
|
+
"\u2716 ",
|
|
1565
|
+
errorMsg
|
|
1566
|
+
] }) }) : /* @__PURE__ */ jsxs9(Text9, { color: "green", children: [
|
|
1567
|
+
"\u2714 ",
|
|
1568
|
+
"\u5DF2\u56DE\u9000\u5230 cherry-pick \u524D\u7684\u72B6\u6001"
|
|
1569
|
+
] }),
|
|
1570
|
+
stashed && stashRestored === false && /* @__PURE__ */ jsx9(Text9, { color: "yellow", children: "\u25B2 stash \u6062\u590D\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8 git stash pop" }),
|
|
1571
|
+
stashed && stashRestored === true && /* @__PURE__ */ jsxs9(Text9, { color: "green", children: [
|
|
1572
|
+
"\u2714 ",
|
|
1573
|
+
"\u5DF2\u6062\u590D\u5DE5\u4F5C\u533A\u53D8\u66F4 (stash pop)"
|
|
1574
|
+
] })
|
|
1575
|
+
] });
|
|
1576
|
+
}
|
|
1577
|
+
const total = orderedHashes.current.length;
|
|
1578
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", gap: 1, children: [
|
|
1579
|
+
/* @__PURE__ */ jsx9(SectionHeader, { title: "\u540C\u6B65\u5B8C\u6210" }),
|
|
1580
|
+
/* @__PURE__ */ jsxs9(Box9, { gap: 2, children: [
|
|
1581
|
+
/* @__PURE__ */ jsxs9(Text9, { color: "green", bold: true, children: [
|
|
1582
|
+
"\u2714 ",
|
|
1583
|
+
completedCount,
|
|
1584
|
+
" \u4E2A commit \u5DF2\u540C\u6B65"
|
|
1585
|
+
] }),
|
|
1586
|
+
skippedCount > 0 && /* @__PURE__ */ jsxs9(Text9, { color: "yellow", children: [
|
|
1587
|
+
skippedCount,
|
|
1588
|
+
" \u4E2A\u5DF2\u8DF3\u8FC7"
|
|
1589
|
+
] })
|
|
1590
|
+
] }),
|
|
1591
|
+
noCommit && /* @__PURE__ */ jsx9(StatusPanel, { type: "success", title: "\u6682\u5B58\u533A\u53D8\u66F4 (git diff --cached --stat)", children: /* @__PURE__ */ jsx9(Text9, { color: "gray", children: stagedStat || "(\u65E0\u53D8\u66F4)" }) }),
|
|
1592
|
+
stashed && (stashRestored ? /* @__PURE__ */ jsxs9(Text9, { color: "green", children: [
|
|
1593
|
+
"\u2714 ",
|
|
1594
|
+
"\u5DF2\u6062\u590D\u5DE5\u4F5C\u533A\u53D8\u66F4 (stash pop)"
|
|
1595
|
+
] }) : /* @__PURE__ */ jsx9(Text9, { color: "yellow", children: "\u25B2 stash pop \u5931\u8D25\uFF0C\u8BF7\u624B\u52A8 git stash pop" })),
|
|
1596
|
+
noCommit ? /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
|
|
1597
|
+
/* @__PURE__ */ jsx9(Text9, { color: "yellow", children: "\u25B2 \u6539\u52A8\u5DF2\u6682\u5B58\u5230\u5DE5\u4F5C\u533A (--no-commit \u6A21\u5F0F)" }),
|
|
1598
|
+
/* @__PURE__ */ jsx9(Text9, { color: "gray", dimColor: true, children: " \u5BA1\u67E5\u540E\u624B\u52A8\u6267\u884C:" }),
|
|
1599
|
+
/* @__PURE__ */ jsxs9(Text9, { color: "cyan", children: [
|
|
955
1600
|
" git diff --cached ",
|
|
956
|
-
/* @__PURE__ */
|
|
1601
|
+
/* @__PURE__ */ jsx9(Text9, { color: "gray", dimColor: true, children: "# \u67E5\u770B\u8BE6\u7EC6 diff" })
|
|
957
1602
|
] }),
|
|
958
|
-
/* @__PURE__ */
|
|
1603
|
+
/* @__PURE__ */ jsxs9(Text9, { color: "cyan", children: [
|
|
959
1604
|
' git commit -m "sync: ..." ',
|
|
960
|
-
/* @__PURE__ */
|
|
1605
|
+
/* @__PURE__ */ jsx9(Text9, { color: "gray", dimColor: true, children: "# \u63D0\u4EA4" })
|
|
961
1606
|
] }),
|
|
962
|
-
/* @__PURE__ */
|
|
1607
|
+
/* @__PURE__ */ jsxs9(Text9, { color: "cyan", children: [
|
|
963
1608
|
" git reset HEAD ",
|
|
964
|
-
/* @__PURE__ */
|
|
1609
|
+
/* @__PURE__ */ jsx9(Text9, { color: "gray", dimColor: true, children: "# \u6216\u653E\u5F03" })
|
|
965
1610
|
] })
|
|
966
|
-
] })
|
|
1611
|
+
] }) : /* @__PURE__ */ jsx9(Box9, { flexDirection: "column", children: /* @__PURE__ */ jsx9(Text9, { color: "gray", dimColor: true, children: " \u5DF2\u4FDD\u7559\u539F\u59CB commit \u4FE1\u606F\uFF0C\u53EF\u901A\u8FC7 git log \u67E5\u770B" }) })
|
|
967
1612
|
] });
|
|
968
1613
|
}
|
|
969
1614
|
|
|
970
1615
|
// src/app.tsx
|
|
971
1616
|
import { execSync } from "child_process";
|
|
972
|
-
import { jsx as
|
|
1617
|
+
import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
973
1618
|
var STEP_NUMBER = {
|
|
974
1619
|
checking: 0,
|
|
975
1620
|
"stash-recovery": 0,
|
|
976
1621
|
"stash-prompt": 0,
|
|
977
1622
|
remote: 1,
|
|
978
1623
|
branch: 2,
|
|
1624
|
+
"branch-check": 2,
|
|
979
1625
|
commits: 3,
|
|
980
1626
|
confirm: 4,
|
|
981
1627
|
result: 5
|
|
@@ -983,22 +1629,23 @@ var STEP_NUMBER = {
|
|
|
983
1629
|
var STEP_DEBOUNCE = 100;
|
|
984
1630
|
function App({ initialRemote, initialBranch }) {
|
|
985
1631
|
const { exit } = useApp();
|
|
986
|
-
const entryStep = initialRemote && initialBranch ? "
|
|
987
|
-
const [step, setStepRaw] =
|
|
988
|
-
const [inputReady, setInputReady] =
|
|
989
|
-
const [remote2, setRemote] =
|
|
990
|
-
const [branch2, setBranch] =
|
|
991
|
-
const [selectedHashes, setSelectedHashes] =
|
|
992
|
-
const [commits2, setCommits] =
|
|
993
|
-
const [hasMerge, setHasMerge] =
|
|
994
|
-
const [useMainline, setUseMainline] =
|
|
995
|
-
const [
|
|
996
|
-
const [
|
|
997
|
-
const
|
|
998
|
-
const
|
|
999
|
-
const
|
|
1000
|
-
const
|
|
1001
|
-
const
|
|
1632
|
+
const entryStep = initialRemote && initialBranch ? "branch-check" : initialRemote ? "branch" : "remote";
|
|
1633
|
+
const [step, setStepRaw] = useState8("checking");
|
|
1634
|
+
const [inputReady, setInputReady] = useState8(true);
|
|
1635
|
+
const [remote2, setRemote] = useState8(initialRemote || "");
|
|
1636
|
+
const [branch2, setBranch] = useState8(initialBranch || "");
|
|
1637
|
+
const [selectedHashes, setSelectedHashes] = useState8([]);
|
|
1638
|
+
const [commits2, setCommits] = useState8([]);
|
|
1639
|
+
const [hasMerge, setHasMerge] = useState8(false);
|
|
1640
|
+
const [useMainline, setUseMainline] = useState8(false);
|
|
1641
|
+
const [noCommit, setNoCommit] = useState8(false);
|
|
1642
|
+
const [stashed, setStashed] = useState8(false);
|
|
1643
|
+
const [guardTimestamp, setGuardTimestamp] = useState8();
|
|
1644
|
+
const stashedRef = useRef5(false);
|
|
1645
|
+
const stashRestoredRef = useRef5(false);
|
|
1646
|
+
const mountedRef = useRef5(true);
|
|
1647
|
+
const debounceTimer = useRef5(null);
|
|
1648
|
+
const setStep = useCallback3((newStep) => {
|
|
1002
1649
|
setInputReady(false);
|
|
1003
1650
|
setStepRaw(newStep);
|
|
1004
1651
|
if (debounceTimer.current) clearTimeout(debounceTimer.current);
|
|
@@ -1006,7 +1653,7 @@ function App({ initialRemote, initialBranch }) {
|
|
|
1006
1653
|
if (mountedRef.current) setInputReady(true);
|
|
1007
1654
|
}, STEP_DEBOUNCE);
|
|
1008
1655
|
}, []);
|
|
1009
|
-
const restoreStashSync =
|
|
1656
|
+
const restoreStashSync = useCallback3(() => {
|
|
1010
1657
|
if (stashedRef.current && !stashRestoredRef.current) {
|
|
1011
1658
|
try {
|
|
1012
1659
|
execSync("git stash pop", { stdio: "ignore" });
|
|
@@ -1020,11 +1667,11 @@ function App({ initialRemote, initialBranch }) {
|
|
|
1020
1667
|
}
|
|
1021
1668
|
}
|
|
1022
1669
|
}, []);
|
|
1023
|
-
const markStashRestored =
|
|
1670
|
+
const markStashRestored = useCallback3(() => {
|
|
1024
1671
|
stashRestoredRef.current = true;
|
|
1025
1672
|
removeStashGuard();
|
|
1026
1673
|
}, []);
|
|
1027
|
-
|
|
1674
|
+
useEffect6(() => {
|
|
1028
1675
|
mountedRef.current = true;
|
|
1029
1676
|
async function check() {
|
|
1030
1677
|
const guard = await checkStashGuard();
|
|
@@ -1079,9 +1726,10 @@ function App({ initialRemote, initialBranch }) {
|
|
|
1079
1726
|
const clean = await isWorkingDirClean();
|
|
1080
1727
|
if (mountedRef.current) setStep(clean ? entryStep : "stash-prompt");
|
|
1081
1728
|
};
|
|
1082
|
-
const goBack =
|
|
1729
|
+
const goBack = useCallback3((fromStep) => {
|
|
1083
1730
|
const backMap = {
|
|
1084
1731
|
branch: "remote",
|
|
1732
|
+
"branch-check": "branch",
|
|
1085
1733
|
commits: "branch",
|
|
1086
1734
|
confirm: "commits"
|
|
1087
1735
|
};
|
|
@@ -1093,10 +1741,10 @@ function App({ initialRemote, initialBranch }) {
|
|
|
1093
1741
|
exit();
|
|
1094
1742
|
}
|
|
1095
1743
|
}, [setStep, restoreStashSync, exit]);
|
|
1096
|
-
return /* @__PURE__ */
|
|
1097
|
-
/* @__PURE__ */
|
|
1098
|
-
step === "checking" && /* @__PURE__ */
|
|
1099
|
-
step === "stash-recovery" && inputReady && /* @__PURE__ */
|
|
1744
|
+
return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
|
|
1745
|
+
/* @__PURE__ */ jsx10(AppHeader, { step: STEP_NUMBER[step], stashed, noCommit }),
|
|
1746
|
+
step === "checking" && /* @__PURE__ */ jsx10(Spinner7, { label: "\u68C0\u67E5\u5DE5\u4F5C\u533A\u72B6\u6001..." }),
|
|
1747
|
+
step === "stash-recovery" && inputReady && /* @__PURE__ */ jsx10(
|
|
1100
1748
|
StashRecovery,
|
|
1101
1749
|
{
|
|
1102
1750
|
timestamp: guardTimestamp,
|
|
@@ -1104,14 +1752,14 @@ function App({ initialRemote, initialBranch }) {
|
|
|
1104
1752
|
onSkip: skipStashRecover
|
|
1105
1753
|
}
|
|
1106
1754
|
),
|
|
1107
|
-
step === "stash-prompt" && inputReady && /* @__PURE__ */
|
|
1755
|
+
step === "stash-prompt" && inputReady && /* @__PURE__ */ jsx10(
|
|
1108
1756
|
StashPrompt,
|
|
1109
1757
|
{
|
|
1110
1758
|
onConfirm: doStash,
|
|
1111
1759
|
onSkip: () => setStep(entryStep)
|
|
1112
1760
|
}
|
|
1113
1761
|
),
|
|
1114
|
-
step === "remote" && inputReady && /* @__PURE__ */
|
|
1762
|
+
step === "remote" && inputReady && /* @__PURE__ */ jsx10(
|
|
1115
1763
|
RemoteSelect,
|
|
1116
1764
|
{
|
|
1117
1765
|
onSelect: (r) => {
|
|
@@ -1121,49 +1769,58 @@ function App({ initialRemote, initialBranch }) {
|
|
|
1121
1769
|
onBack: () => goBack("remote")
|
|
1122
1770
|
}
|
|
1123
1771
|
),
|
|
1124
|
-
step === "branch" && inputReady && /* @__PURE__ */
|
|
1772
|
+
step === "branch" && inputReady && /* @__PURE__ */ jsx10(
|
|
1125
1773
|
BranchSelect,
|
|
1126
1774
|
{
|
|
1127
1775
|
remote: remote2,
|
|
1128
1776
|
onSelect: (b) => {
|
|
1129
1777
|
setBranch(b);
|
|
1130
|
-
setStep("
|
|
1778
|
+
setStep("branch-check");
|
|
1131
1779
|
},
|
|
1132
1780
|
onBack: () => goBack("branch")
|
|
1133
1781
|
}
|
|
1134
1782
|
),
|
|
1135
|
-
step === "
|
|
1783
|
+
step === "branch-check" && inputReady && /* @__PURE__ */ jsx10(
|
|
1784
|
+
BranchCheck,
|
|
1785
|
+
{
|
|
1786
|
+
targetBranch: branch2,
|
|
1787
|
+
onContinue: () => setStep("commits"),
|
|
1788
|
+
onBack: () => goBack("branch-check")
|
|
1789
|
+
}
|
|
1790
|
+
),
|
|
1791
|
+
step === "commits" && inputReady && /* @__PURE__ */ jsx10(
|
|
1136
1792
|
CommitList,
|
|
1137
1793
|
{
|
|
1138
1794
|
remote: remote2,
|
|
1139
1795
|
branch: branch2,
|
|
1140
|
-
onSelect:
|
|
1796
|
+
onSelect: (hashes, loadedCommits) => {
|
|
1141
1797
|
setSelectedHashes(hashes);
|
|
1142
1798
|
setCommits(loadedCommits);
|
|
1143
|
-
const merge = await hasMergeCommits(hashes);
|
|
1144
|
-
setHasMerge(merge);
|
|
1145
1799
|
setStep("confirm");
|
|
1146
1800
|
},
|
|
1147
1801
|
onBack: () => goBack("commits")
|
|
1148
1802
|
}
|
|
1149
1803
|
),
|
|
1150
|
-
step === "confirm" && inputReady && /* @__PURE__ */
|
|
1804
|
+
step === "confirm" && inputReady && /* @__PURE__ */ jsx10(
|
|
1151
1805
|
ConfirmPanel,
|
|
1152
1806
|
{
|
|
1153
1807
|
commits: commits2,
|
|
1154
1808
|
selectedHashes,
|
|
1155
1809
|
hasMerge,
|
|
1156
1810
|
useMainline,
|
|
1811
|
+
noCommit,
|
|
1157
1812
|
onToggleMainline: () => setUseMainline((v) => !v),
|
|
1813
|
+
onToggleNoCommit: () => setNoCommit((v) => !v),
|
|
1158
1814
|
onConfirm: () => setStep("result"),
|
|
1159
1815
|
onCancel: () => goBack("confirm")
|
|
1160
1816
|
}
|
|
1161
1817
|
),
|
|
1162
|
-
step === "result" && /* @__PURE__ */
|
|
1818
|
+
step === "result" && /* @__PURE__ */ jsx10(
|
|
1163
1819
|
ResultPanel,
|
|
1164
1820
|
{
|
|
1165
1821
|
selectedHashes,
|
|
1166
1822
|
useMainline,
|
|
1823
|
+
noCommit,
|
|
1167
1824
|
stashed,
|
|
1168
1825
|
onStashRestored: markStashRestored,
|
|
1169
1826
|
onDone: () => {
|
|
@@ -1340,7 +1997,7 @@ async function runCli(opts) {
|
|
|
1340
1997
|
}
|
|
1341
1998
|
|
|
1342
1999
|
// src/cli.tsx
|
|
1343
|
-
import { jsx as
|
|
2000
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
1344
2001
|
var cli = meow(
|
|
1345
2002
|
`
|
|
1346
2003
|
\u7528\u6CD5
|
|
@@ -1350,7 +2007,7 @@ var cli = meow(
|
|
|
1350
2007
|
-r, --remote <name> \u6307\u5B9A\u8FDC\u7A0B\u4ED3\u5E93\u540D\u79F0
|
|
1351
2008
|
-b, --branch <name> \u6307\u5B9A\u8FDC\u7A0B\u5206\u652F\u540D\u79F0
|
|
1352
2009
|
-c, --commits <hashes> \u6307\u5B9A commit hash\uFF08\u9017\u53F7\u5206\u9694\uFF09
|
|
1353
|
-
-n, --count <number> \u663E\u793A commit \u6570\u91CF\uFF08\u9ED8\u8BA4
|
|
2010
|
+
-n, --count <number> \u663E\u793A commit \u6570\u91CF\uFF08\u9ED8\u8BA4 100\uFF09
|
|
1354
2011
|
-m, --mainline \u5BF9 merge commit \u4F7F\u7528 -m 1
|
|
1355
2012
|
-y, --yes \u8DF3\u8FC7\u786E\u8BA4\u76F4\u63A5\u6267\u884C
|
|
1356
2013
|
--no-stash \u8DF3\u8FC7 stash \u63D0\u793A
|
|
@@ -1386,7 +2043,7 @@ var cli = meow(
|
|
|
1386
2043
|
remote: { type: "string", shortFlag: "r" },
|
|
1387
2044
|
branch: { type: "string", shortFlag: "b" },
|
|
1388
2045
|
commits: { type: "string", shortFlag: "c" },
|
|
1389
|
-
count: { type: "number", shortFlag: "n", default:
|
|
2046
|
+
count: { type: "number", shortFlag: "n", default: 100 },
|
|
1390
2047
|
mainline: { type: "boolean", shortFlag: "m", default: false },
|
|
1391
2048
|
yes: { type: "boolean", shortFlag: "y", default: false },
|
|
1392
2049
|
noStash: { type: "boolean", default: false },
|
|
@@ -1414,5 +2071,5 @@ if (isCliMode) {
|
|
|
1414
2071
|
process.exit(1);
|
|
1415
2072
|
});
|
|
1416
2073
|
} else {
|
|
1417
|
-
render(/* @__PURE__ */
|
|
2074
|
+
render(/* @__PURE__ */ jsx11(App, { initialRemote: remote, initialBranch: branch }));
|
|
1418
2075
|
}
|