git-sync-tui 0.1.5 → 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 +558 -112
- 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";
|
|
@@ -92,11 +92,14 @@ function StatusPanel({ type, title, children }) {
|
|
|
92
92
|
children
|
|
93
93
|
] });
|
|
94
94
|
}
|
|
95
|
-
function AppHeader({ step, stashed }) {
|
|
95
|
+
function AppHeader({ step, stashed, noCommit }) {
|
|
96
96
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
97
97
|
/* @__PURE__ */ jsxs(Box, { gap: 1, children: [
|
|
98
98
|
/* @__PURE__ */ jsx(Text, { backgroundColor: "cyan", color: "white", bold: true, children: " git-sync-tui " }),
|
|
99
|
-
/* @__PURE__ */
|
|
99
|
+
/* @__PURE__ */ jsxs(Text, { color: "gray", children: [
|
|
100
|
+
"cherry-pick",
|
|
101
|
+
noCommit ? " --no-commit" : ""
|
|
102
|
+
] }),
|
|
100
103
|
stashed && /* @__PURE__ */ jsx(Text, { backgroundColor: "yellow", color: "white", bold: true, children: " STASHED " })
|
|
101
104
|
] }),
|
|
102
105
|
/* @__PURE__ */ jsxs(Box, { marginTop: 0, children: [
|
|
@@ -187,6 +190,8 @@ async function getCommits(remote2, branch2, count2 = 100) {
|
|
|
187
190
|
const result = await git.raw([
|
|
188
191
|
"log",
|
|
189
192
|
ref,
|
|
193
|
+
"--first-parent",
|
|
194
|
+
"--no-merges",
|
|
190
195
|
`--max-count=${count2}`,
|
|
191
196
|
"--format=%H%n%h%n%s%n%an%n%ar%n---"
|
|
192
197
|
]);
|
|
@@ -281,6 +286,45 @@ async function getStagedStat() {
|
|
|
281
286
|
return "";
|
|
282
287
|
}
|
|
283
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
|
+
}
|
|
284
328
|
async function isWorkingDirClean() {
|
|
285
329
|
const git = getGit();
|
|
286
330
|
const status = await git.status();
|
|
@@ -304,6 +348,87 @@ async function stashPop() {
|
|
|
304
348
|
return false;
|
|
305
349
|
}
|
|
306
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
|
+
}
|
|
307
432
|
var STASH_GUARD_FILE = "git-sync-tui-stash-guard";
|
|
308
433
|
async function getGitDir() {
|
|
309
434
|
const git = getGit();
|
|
@@ -1043,11 +1168,107 @@ function CommitList({ remote: remote2, branch: branch2, onSelect, onBack }) {
|
|
|
1043
1168
|
] });
|
|
1044
1169
|
}
|
|
1045
1170
|
|
|
1046
|
-
// src/components/
|
|
1171
|
+
// src/components/branch-check.tsx
|
|
1172
|
+
import { useState as useState6, useEffect as useEffect4, useRef as useRef3 } from "react";
|
|
1047
1173
|
import { Box as Box7, Text as Text7, useInput as useInput6 } from "ink";
|
|
1174
|
+
import { Spinner as Spinner5 } from "@inkjs/ui";
|
|
1048
1175
|
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1049
|
-
|
|
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
|
+
};
|
|
1050
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) => {
|
|
1051
1272
|
if (key.escape) {
|
|
1052
1273
|
onCancel();
|
|
1053
1274
|
} else if (input === "y" || input === "Y") {
|
|
@@ -1056,43 +1277,54 @@ function ConfirmPanel({ commits: commits2, selectedHashes, hasMerge, useMainline
|
|
|
1056
1277
|
onCancel();
|
|
1057
1278
|
} else if (hasMerge && (input === "m" || input === "M")) {
|
|
1058
1279
|
onToggleMainline();
|
|
1280
|
+
} else if (input === "c" || input === "C") {
|
|
1281
|
+
onToggleNoCommit();
|
|
1059
1282
|
}
|
|
1060
1283
|
});
|
|
1061
1284
|
const selectedCommits = selectedHashes.map((hash) => commits2.find((c) => c.hash === hash)).filter(Boolean);
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
/* @__PURE__ */
|
|
1065
|
-
|
|
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: [
|
|
1066
1290
|
" ",
|
|
1067
1291
|
c.shortHash
|
|
1068
1292
|
] }),
|
|
1069
|
-
/* @__PURE__ */
|
|
1293
|
+
/* @__PURE__ */ jsxs8(Text8, { children: [
|
|
1070
1294
|
" ",
|
|
1071
1295
|
c.message
|
|
1072
1296
|
] }),
|
|
1073
|
-
/* @__PURE__ */
|
|
1297
|
+
/* @__PURE__ */ jsxs8(Text8, { color: "gray", dimColor: true, children: [
|
|
1074
1298
|
" ",
|
|
1075
1299
|
c.author
|
|
1076
1300
|
] })
|
|
1077
1301
|
] }, c.hash)) }),
|
|
1078
|
-
|
|
1079
|
-
/* @__PURE__ */
|
|
1080
|
-
/* @__PURE__ */
|
|
1081
|
-
|
|
1082
|
-
/* @__PURE__ */
|
|
1083
|
-
/* @__PURE__ */
|
|
1084
|
-
|
|
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)" })
|
|
1085
1311
|
] })
|
|
1086
1312
|
] }),
|
|
1087
|
-
/* @__PURE__ */
|
|
1088
|
-
/* @__PURE__ */
|
|
1089
|
-
/* @__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
|
+
] })
|
|
1090
1321
|
] }),
|
|
1091
|
-
/* @__PURE__ */
|
|
1092
|
-
/* @__PURE__ */
|
|
1093
|
-
/* @__PURE__ */
|
|
1322
|
+
/* @__PURE__ */ jsxs8(Box8, { children: [
|
|
1323
|
+
/* @__PURE__ */ jsx8(Text8, { bold: true, children: "\u786E\u8BA4\u6267\u884C? " }),
|
|
1324
|
+
/* @__PURE__ */ jsx8(InlineKeys, { hints: [
|
|
1094
1325
|
{ key: "y", label: "\u786E\u8BA4" },
|
|
1095
1326
|
{ key: "n", label: "\u53D6\u6D88" },
|
|
1327
|
+
{ key: "c", label: "\u5207\u6362\u63D0\u4EA4\u6A21\u5F0F" },
|
|
1096
1328
|
...hasMerge ? [{ key: "m", label: "\u5207\u6362 -m 1" }] : [],
|
|
1097
1329
|
{ key: "Esc", label: "\u8FD4\u56DE" }
|
|
1098
1330
|
] })
|
|
@@ -1101,92 +1333,295 @@ function ConfirmPanel({ commits: commits2, selectedHashes, hasMerge, useMainline
|
|
|
1101
1333
|
}
|
|
1102
1334
|
|
|
1103
1335
|
// src/components/result-panel.tsx
|
|
1104
|
-
import { useState as
|
|
1105
|
-
import { Box as
|
|
1106
|
-
import { Spinner as
|
|
1107
|
-
import { jsx as
|
|
1108
|
-
function ResultPanel({ selectedHashes, useMainline, stashed, onStashRestored, onDone }) {
|
|
1109
|
-
const [phase, setPhase] =
|
|
1110
|
-
const [
|
|
1111
|
-
const [
|
|
1112
|
-
const [
|
|
1113
|
-
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 () => {
|
|
1114
1353
|
if (!stashed) return true;
|
|
1115
1354
|
setPhase("restoring");
|
|
1116
1355
|
const ok = await stashPop();
|
|
1117
1356
|
setStashRestored(ok);
|
|
1118
1357
|
if (ok) onStashRestored();
|
|
1119
1358
|
return ok;
|
|
1120
|
-
};
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
const
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
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;
|
|
1133
1381
|
}
|
|
1382
|
+
setCompletedCount((c) => c + 1);
|
|
1134
1383
|
}
|
|
1135
|
-
|
|
1384
|
+
await finishAll();
|
|
1385
|
+
}, [useMainline, noCommit, finishAll]);
|
|
1386
|
+
useEffect5(() => {
|
|
1387
|
+
createBackupBranch().then((branch2) => {
|
|
1388
|
+
backupBranchRef.current = branch2;
|
|
1389
|
+
executeFrom(0);
|
|
1390
|
+
});
|
|
1136
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
|
+
});
|
|
1137
1484
|
if (phase === "executing") {
|
|
1138
|
-
|
|
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..." });
|
|
1139
1493
|
}
|
|
1140
1494
|
if (phase === "restoring") {
|
|
1141
|
-
return /* @__PURE__ */
|
|
1495
|
+
return /* @__PURE__ */ jsx9(Spinner6, { label: "\u6062\u590D\u5DE5\u4F5C\u533A (git stash pop)..." });
|
|
1496
|
+
}
|
|
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
|
+
] });
|
|
1142
1509
|
}
|
|
1143
|
-
if (phase === "
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
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: [
|
|
1147
1533
|
" ",
|
|
1148
1534
|
f
|
|
1149
1535
|
] }, f)) }),
|
|
1150
|
-
/* @__PURE__ */
|
|
1151
|
-
/* @__PURE__ */
|
|
1152
|
-
/* @__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" })
|
|
1153
1548
|
] }),
|
|
1154
|
-
|
|
1155
|
-
|
|
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
|
+
] }) })
|
|
1156
1558
|
] });
|
|
1157
1559
|
}
|
|
1158
|
-
|
|
1159
|
-
/* @__PURE__ */
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
/* @__PURE__ */
|
|
1165
|
-
|
|
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: [
|
|
1166
1600
|
" git diff --cached ",
|
|
1167
|
-
/* @__PURE__ */
|
|
1601
|
+
/* @__PURE__ */ jsx9(Text9, { color: "gray", dimColor: true, children: "# \u67E5\u770B\u8BE6\u7EC6 diff" })
|
|
1168
1602
|
] }),
|
|
1169
|
-
/* @__PURE__ */
|
|
1603
|
+
/* @__PURE__ */ jsxs9(Text9, { color: "cyan", children: [
|
|
1170
1604
|
' git commit -m "sync: ..." ',
|
|
1171
|
-
/* @__PURE__ */
|
|
1605
|
+
/* @__PURE__ */ jsx9(Text9, { color: "gray", dimColor: true, children: "# \u63D0\u4EA4" })
|
|
1172
1606
|
] }),
|
|
1173
|
-
/* @__PURE__ */
|
|
1607
|
+
/* @__PURE__ */ jsxs9(Text9, { color: "cyan", children: [
|
|
1174
1608
|
" git reset HEAD ",
|
|
1175
|
-
/* @__PURE__ */
|
|
1609
|
+
/* @__PURE__ */ jsx9(Text9, { color: "gray", dimColor: true, children: "# \u6216\u653E\u5F03" })
|
|
1176
1610
|
] })
|
|
1177
|
-
] })
|
|
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" }) })
|
|
1178
1612
|
] });
|
|
1179
1613
|
}
|
|
1180
1614
|
|
|
1181
1615
|
// src/app.tsx
|
|
1182
1616
|
import { execSync } from "child_process";
|
|
1183
|
-
import { jsx as
|
|
1617
|
+
import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1184
1618
|
var STEP_NUMBER = {
|
|
1185
1619
|
checking: 0,
|
|
1186
1620
|
"stash-recovery": 0,
|
|
1187
1621
|
"stash-prompt": 0,
|
|
1188
1622
|
remote: 1,
|
|
1189
1623
|
branch: 2,
|
|
1624
|
+
"branch-check": 2,
|
|
1190
1625
|
commits: 3,
|
|
1191
1626
|
confirm: 4,
|
|
1192
1627
|
result: 5
|
|
@@ -1194,22 +1629,23 @@ var STEP_NUMBER = {
|
|
|
1194
1629
|
var STEP_DEBOUNCE = 100;
|
|
1195
1630
|
function App({ initialRemote, initialBranch }) {
|
|
1196
1631
|
const { exit } = useApp();
|
|
1197
|
-
const entryStep = initialRemote && initialBranch ? "
|
|
1198
|
-
const [step, setStepRaw] =
|
|
1199
|
-
const [inputReady, setInputReady] =
|
|
1200
|
-
const [remote2, setRemote] =
|
|
1201
|
-
const [branch2, setBranch] =
|
|
1202
|
-
const [selectedHashes, setSelectedHashes] =
|
|
1203
|
-
const [commits2, setCommits] =
|
|
1204
|
-
const [hasMerge, setHasMerge] =
|
|
1205
|
-
const [useMainline, setUseMainline] =
|
|
1206
|
-
const [
|
|
1207
|
-
const [
|
|
1208
|
-
const
|
|
1209
|
-
const
|
|
1210
|
-
const
|
|
1211
|
-
const
|
|
1212
|
-
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) => {
|
|
1213
1649
|
setInputReady(false);
|
|
1214
1650
|
setStepRaw(newStep);
|
|
1215
1651
|
if (debounceTimer.current) clearTimeout(debounceTimer.current);
|
|
@@ -1217,7 +1653,7 @@ function App({ initialRemote, initialBranch }) {
|
|
|
1217
1653
|
if (mountedRef.current) setInputReady(true);
|
|
1218
1654
|
}, STEP_DEBOUNCE);
|
|
1219
1655
|
}, []);
|
|
1220
|
-
const restoreStashSync =
|
|
1656
|
+
const restoreStashSync = useCallback3(() => {
|
|
1221
1657
|
if (stashedRef.current && !stashRestoredRef.current) {
|
|
1222
1658
|
try {
|
|
1223
1659
|
execSync("git stash pop", { stdio: "ignore" });
|
|
@@ -1231,11 +1667,11 @@ function App({ initialRemote, initialBranch }) {
|
|
|
1231
1667
|
}
|
|
1232
1668
|
}
|
|
1233
1669
|
}, []);
|
|
1234
|
-
const markStashRestored =
|
|
1670
|
+
const markStashRestored = useCallback3(() => {
|
|
1235
1671
|
stashRestoredRef.current = true;
|
|
1236
1672
|
removeStashGuard();
|
|
1237
1673
|
}, []);
|
|
1238
|
-
|
|
1674
|
+
useEffect6(() => {
|
|
1239
1675
|
mountedRef.current = true;
|
|
1240
1676
|
async function check() {
|
|
1241
1677
|
const guard = await checkStashGuard();
|
|
@@ -1290,9 +1726,10 @@ function App({ initialRemote, initialBranch }) {
|
|
|
1290
1726
|
const clean = await isWorkingDirClean();
|
|
1291
1727
|
if (mountedRef.current) setStep(clean ? entryStep : "stash-prompt");
|
|
1292
1728
|
};
|
|
1293
|
-
const goBack =
|
|
1729
|
+
const goBack = useCallback3((fromStep) => {
|
|
1294
1730
|
const backMap = {
|
|
1295
1731
|
branch: "remote",
|
|
1732
|
+
"branch-check": "branch",
|
|
1296
1733
|
commits: "branch",
|
|
1297
1734
|
confirm: "commits"
|
|
1298
1735
|
};
|
|
@@ -1304,10 +1741,10 @@ function App({ initialRemote, initialBranch }) {
|
|
|
1304
1741
|
exit();
|
|
1305
1742
|
}
|
|
1306
1743
|
}, [setStep, restoreStashSync, exit]);
|
|
1307
|
-
return /* @__PURE__ */
|
|
1308
|
-
/* @__PURE__ */
|
|
1309
|
-
step === "checking" && /* @__PURE__ */
|
|
1310
|
-
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(
|
|
1311
1748
|
StashRecovery,
|
|
1312
1749
|
{
|
|
1313
1750
|
timestamp: guardTimestamp,
|
|
@@ -1315,14 +1752,14 @@ function App({ initialRemote, initialBranch }) {
|
|
|
1315
1752
|
onSkip: skipStashRecover
|
|
1316
1753
|
}
|
|
1317
1754
|
),
|
|
1318
|
-
step === "stash-prompt" && inputReady && /* @__PURE__ */
|
|
1755
|
+
step === "stash-prompt" && inputReady && /* @__PURE__ */ jsx10(
|
|
1319
1756
|
StashPrompt,
|
|
1320
1757
|
{
|
|
1321
1758
|
onConfirm: doStash,
|
|
1322
1759
|
onSkip: () => setStep(entryStep)
|
|
1323
1760
|
}
|
|
1324
1761
|
),
|
|
1325
|
-
step === "remote" && inputReady && /* @__PURE__ */
|
|
1762
|
+
step === "remote" && inputReady && /* @__PURE__ */ jsx10(
|
|
1326
1763
|
RemoteSelect,
|
|
1327
1764
|
{
|
|
1328
1765
|
onSelect: (r) => {
|
|
@@ -1332,49 +1769,58 @@ function App({ initialRemote, initialBranch }) {
|
|
|
1332
1769
|
onBack: () => goBack("remote")
|
|
1333
1770
|
}
|
|
1334
1771
|
),
|
|
1335
|
-
step === "branch" && inputReady && /* @__PURE__ */
|
|
1772
|
+
step === "branch" && inputReady && /* @__PURE__ */ jsx10(
|
|
1336
1773
|
BranchSelect,
|
|
1337
1774
|
{
|
|
1338
1775
|
remote: remote2,
|
|
1339
1776
|
onSelect: (b) => {
|
|
1340
1777
|
setBranch(b);
|
|
1341
|
-
setStep("
|
|
1778
|
+
setStep("branch-check");
|
|
1342
1779
|
},
|
|
1343
1780
|
onBack: () => goBack("branch")
|
|
1344
1781
|
}
|
|
1345
1782
|
),
|
|
1346
|
-
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(
|
|
1347
1792
|
CommitList,
|
|
1348
1793
|
{
|
|
1349
1794
|
remote: remote2,
|
|
1350
1795
|
branch: branch2,
|
|
1351
|
-
onSelect:
|
|
1796
|
+
onSelect: (hashes, loadedCommits) => {
|
|
1352
1797
|
setSelectedHashes(hashes);
|
|
1353
1798
|
setCommits(loadedCommits);
|
|
1354
|
-
const merge = await hasMergeCommits(hashes);
|
|
1355
|
-
setHasMerge(merge);
|
|
1356
1799
|
setStep("confirm");
|
|
1357
1800
|
},
|
|
1358
1801
|
onBack: () => goBack("commits")
|
|
1359
1802
|
}
|
|
1360
1803
|
),
|
|
1361
|
-
step === "confirm" && inputReady && /* @__PURE__ */
|
|
1804
|
+
step === "confirm" && inputReady && /* @__PURE__ */ jsx10(
|
|
1362
1805
|
ConfirmPanel,
|
|
1363
1806
|
{
|
|
1364
1807
|
commits: commits2,
|
|
1365
1808
|
selectedHashes,
|
|
1366
1809
|
hasMerge,
|
|
1367
1810
|
useMainline,
|
|
1811
|
+
noCommit,
|
|
1368
1812
|
onToggleMainline: () => setUseMainline((v) => !v),
|
|
1813
|
+
onToggleNoCommit: () => setNoCommit((v) => !v),
|
|
1369
1814
|
onConfirm: () => setStep("result"),
|
|
1370
1815
|
onCancel: () => goBack("confirm")
|
|
1371
1816
|
}
|
|
1372
1817
|
),
|
|
1373
|
-
step === "result" && /* @__PURE__ */
|
|
1818
|
+
step === "result" && /* @__PURE__ */ jsx10(
|
|
1374
1819
|
ResultPanel,
|
|
1375
1820
|
{
|
|
1376
1821
|
selectedHashes,
|
|
1377
1822
|
useMainline,
|
|
1823
|
+
noCommit,
|
|
1378
1824
|
stashed,
|
|
1379
1825
|
onStashRestored: markStashRestored,
|
|
1380
1826
|
onDone: () => {
|
|
@@ -1551,7 +1997,7 @@ async function runCli(opts) {
|
|
|
1551
1997
|
}
|
|
1552
1998
|
|
|
1553
1999
|
// src/cli.tsx
|
|
1554
|
-
import { jsx as
|
|
2000
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
1555
2001
|
var cli = meow(
|
|
1556
2002
|
`
|
|
1557
2003
|
\u7528\u6CD5
|
|
@@ -1625,5 +2071,5 @@ if (isCliMode) {
|
|
|
1625
2071
|
process.exit(1);
|
|
1626
2072
|
});
|
|
1627
2073
|
} else {
|
|
1628
|
-
render(/* @__PURE__ */
|
|
2074
|
+
render(/* @__PURE__ */ jsx11(App, { initialRemote: remote, initialBranch: branch }));
|
|
1629
2075
|
}
|
package/package.json
CHANGED