git-sync-tui 0.1.7 → 0.1.9
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 +53 -51
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
-
}) : x)(function(x) {
|
|
5
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
6
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
-
});
|
|
8
2
|
|
|
9
3
|
// src/cli.tsx
|
|
10
4
|
import { render } from "ink";
|
|
11
5
|
import meow from "meow";
|
|
12
6
|
|
|
13
7
|
// src/app.tsx
|
|
14
|
-
import { useState as useState9, useEffect as useEffect7, useRef as useRef5, useCallback as
|
|
8
|
+
import { useState as useState9, useEffect as useEffect7, useRef as useRef5, useCallback as useCallback4 } from "react";
|
|
15
9
|
import { Box as Box11, useApp } from "ink";
|
|
16
10
|
import { Spinner as Spinner7 } from "@inkjs/ui";
|
|
17
11
|
|
|
@@ -92,10 +86,14 @@ function StatusPanel({ type, title, children }) {
|
|
|
92
86
|
children
|
|
93
87
|
] });
|
|
94
88
|
}
|
|
95
|
-
function AppHeader({ step, stashed, noCommit }) {
|
|
89
|
+
function AppHeader({ step, stashed, noCommit, version }) {
|
|
96
90
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [
|
|
97
91
|
/* @__PURE__ */ jsxs(Box, { gap: 1, children: [
|
|
98
92
|
/* @__PURE__ */ jsx(Text, { backgroundColor: "cyan", color: "white", bold: true, children: " git-sync-tui " }),
|
|
93
|
+
version && /* @__PURE__ */ jsxs(Text, { color: "gray", dimColor: true, children: [
|
|
94
|
+
"v",
|
|
95
|
+
version
|
|
96
|
+
] }),
|
|
99
97
|
/* @__PURE__ */ jsxs(Text, { color: "gray", children: [
|
|
100
98
|
"cherry-pick",
|
|
101
99
|
noCommit ? " --no-commit" : ""
|
|
@@ -140,11 +138,13 @@ import { Spinner } from "@inkjs/ui";
|
|
|
140
138
|
// src/utils/git.ts
|
|
141
139
|
import simpleGit from "simple-git";
|
|
142
140
|
import { existsSync, writeFileSync, unlinkSync, readFileSync } from "fs";
|
|
141
|
+
import { execSync } from "child_process";
|
|
143
142
|
import { join } from "path";
|
|
144
143
|
var gitInstance = null;
|
|
145
144
|
function getGit(cwd) {
|
|
146
|
-
if (
|
|
147
|
-
|
|
145
|
+
if (cwd) return simpleGit(cwd);
|
|
146
|
+
if (!gitInstance) {
|
|
147
|
+
gitInstance = simpleGit();
|
|
148
148
|
}
|
|
149
149
|
return gitInstance;
|
|
150
150
|
}
|
|
@@ -227,13 +227,14 @@ async function getMultiCommitStat(hashes) {
|
|
|
227
227
|
if (hashes.length === 0) return "";
|
|
228
228
|
const git = getGit();
|
|
229
229
|
try {
|
|
230
|
-
const
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
${result.trim()}`
|
|
235
|
-
|
|
236
|
-
|
|
230
|
+
const results = await Promise.all(
|
|
231
|
+
hashes.map(async (hash) => {
|
|
232
|
+
const result = await git.raw(["diff-tree", "--stat", "--no-commit-id", "-r", hash]);
|
|
233
|
+
return result.trim() ? `${hash.substring(0, 7)}:
|
|
234
|
+
${result.trim()}` : "";
|
|
235
|
+
})
|
|
236
|
+
);
|
|
237
|
+
return results.filter(Boolean).join("\n\n");
|
|
237
238
|
} catch {
|
|
238
239
|
return "(\u65E0\u6CD5\u83B7\u53D6 stat \u4FE1\u606F)";
|
|
239
240
|
}
|
|
@@ -454,8 +455,7 @@ async function removeStashGuard() {
|
|
|
454
455
|
}
|
|
455
456
|
function removeStashGuardSync() {
|
|
456
457
|
try {
|
|
457
|
-
const
|
|
458
|
-
const gitDir = String(execSync2("git rev-parse --git-dir", { encoding: "utf-8" })).trim();
|
|
458
|
+
const gitDir = String(execSync("git rev-parse --git-dir", { encoding: "utf-8" })).trim();
|
|
459
459
|
const guardPath = join(gitDir, STASH_GUARD_FILE);
|
|
460
460
|
if (existsSync(guardPath)) {
|
|
461
461
|
unlinkSync(guardPath);
|
|
@@ -542,10 +542,12 @@ function useAsync(fn, deps = []) {
|
|
|
542
542
|
loading: true,
|
|
543
543
|
error: null
|
|
544
544
|
});
|
|
545
|
+
const fnRef = useRef(fn);
|
|
546
|
+
fnRef.current = fn;
|
|
545
547
|
const load = useCallback(async () => {
|
|
546
548
|
setState({ data: null, loading: true, error: null });
|
|
547
549
|
try {
|
|
548
|
-
const data = await
|
|
550
|
+
const data = await fnRef.current();
|
|
549
551
|
setState({ data, loading: false, error: null });
|
|
550
552
|
} catch (err) {
|
|
551
553
|
setState({ data: null, loading: false, error: err.message });
|
|
@@ -612,20 +614,23 @@ function useCommits(remote2, branch2, pageSize = 100) {
|
|
|
612
614
|
function useCommitStat(hashes) {
|
|
613
615
|
const [stat, setStat] = useState2("");
|
|
614
616
|
const [loading, setLoading] = useState2(false);
|
|
617
|
+
const hashKey = hashes.join(",");
|
|
618
|
+
const stableHashes = useRef(hashes);
|
|
619
|
+
stableHashes.current = hashes;
|
|
615
620
|
useEffect2(() => {
|
|
616
|
-
if (
|
|
621
|
+
if (stableHashes.current.length === 0) {
|
|
617
622
|
setStat("");
|
|
618
623
|
return;
|
|
619
624
|
}
|
|
620
625
|
setLoading(true);
|
|
621
|
-
getMultiCommitStat(
|
|
626
|
+
getMultiCommitStat(stableHashes.current).then((s) => {
|
|
622
627
|
setStat(s);
|
|
623
628
|
setLoading(false);
|
|
624
629
|
}).catch(() => {
|
|
625
630
|
setStat("(\u83B7\u53D6\u5931\u8D25)");
|
|
626
631
|
setLoading(false);
|
|
627
632
|
});
|
|
628
|
-
}, [
|
|
633
|
+
}, [hashKey]);
|
|
629
634
|
return { stat, loading };
|
|
630
635
|
}
|
|
631
636
|
|
|
@@ -1180,6 +1185,8 @@ function BranchCheck({ targetBranch, onContinue, onBack }) {
|
|
|
1180
1185
|
const [error2, setError] = useState6(null);
|
|
1181
1186
|
const [matched, setMatched] = useState6(false);
|
|
1182
1187
|
const autoCreated = useRef3(false);
|
|
1188
|
+
const onContinueRef = useRef3(onContinue);
|
|
1189
|
+
onContinueRef.current = onContinue;
|
|
1183
1190
|
useEffect4(() => {
|
|
1184
1191
|
getCurrentBranch().then((branch2) => {
|
|
1185
1192
|
setCurrentBranch(branch2);
|
|
@@ -1189,7 +1196,7 @@ function BranchCheck({ targetBranch, onContinue, onBack }) {
|
|
|
1189
1196
|
});
|
|
1190
1197
|
}, [targetBranch]);
|
|
1191
1198
|
useEffect4(() => {
|
|
1192
|
-
if (matched)
|
|
1199
|
+
if (matched) onContinueRef.current();
|
|
1193
1200
|
}, [matched]);
|
|
1194
1201
|
useEffect4(() => {
|
|
1195
1202
|
if (currentBranch === null || matched || autoCreated.current) return;
|
|
@@ -1197,7 +1204,7 @@ function BranchCheck({ targetBranch, onContinue, onBack }) {
|
|
|
1197
1204
|
autoCreated.current = true;
|
|
1198
1205
|
setCreating(true);
|
|
1199
1206
|
createBranchFrom(targetBranch, currentBranch).then(() => {
|
|
1200
|
-
|
|
1207
|
+
onContinueRef.current();
|
|
1201
1208
|
}).catch((err) => {
|
|
1202
1209
|
setCreating(false);
|
|
1203
1210
|
setError(err.message);
|
|
@@ -1333,7 +1340,7 @@ function ConfirmPanel({ commits: commits2, selectedHashes, hasMerge, useMainline
|
|
|
1333
1340
|
}
|
|
1334
1341
|
|
|
1335
1342
|
// src/components/result-panel.tsx
|
|
1336
|
-
import { useState as useState7, useEffect as useEffect5, useCallback as
|
|
1343
|
+
import { useState as useState7, useEffect as useEffect5, useCallback as useCallback3, useRef as useRef4 } from "react";
|
|
1337
1344
|
import { Box as Box9, Text as Text9, useInput as useInput8 } from "ink";
|
|
1338
1345
|
import { Spinner as Spinner6 } from "@inkjs/ui";
|
|
1339
1346
|
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
@@ -1349,7 +1356,7 @@ function ResultPanel({ selectedHashes, useMainline, noCommit, stashed, onStashRe
|
|
|
1349
1356
|
const remainingRef = useRef4([]);
|
|
1350
1357
|
const backupBranchRef = useRef4("");
|
|
1351
1358
|
const orderedHashes = useRef4([...selectedHashes].reverse());
|
|
1352
|
-
const tryRestoreStash =
|
|
1359
|
+
const tryRestoreStash = useCallback3(async () => {
|
|
1353
1360
|
if (!stashed) return true;
|
|
1354
1361
|
setPhase("restoring");
|
|
1355
1362
|
const ok = await stashPop();
|
|
@@ -1357,7 +1364,7 @@ function ResultPanel({ selectedHashes, useMainline, noCommit, stashed, onStashRe
|
|
|
1357
1364
|
if (ok) onStashRestored();
|
|
1358
1365
|
return ok;
|
|
1359
1366
|
}, [stashed, onStashRestored]);
|
|
1360
|
-
const finishAll =
|
|
1367
|
+
const finishAll = useCallback3(async () => {
|
|
1361
1368
|
if (noCommit) {
|
|
1362
1369
|
const stat = await getStagedStat();
|
|
1363
1370
|
setStagedStat(stat);
|
|
@@ -1368,7 +1375,7 @@ function ResultPanel({ selectedHashes, useMainline, noCommit, stashed, onStashRe
|
|
|
1368
1375
|
await tryRestoreStash();
|
|
1369
1376
|
setPhase("done");
|
|
1370
1377
|
}, [noCommit, tryRestoreStash]);
|
|
1371
|
-
const executeFrom =
|
|
1378
|
+
const executeFrom = useCallback3(async (startIndex) => {
|
|
1372
1379
|
const hashes = orderedHashes.current;
|
|
1373
1380
|
for (let i = startIndex; i < hashes.length; i++) {
|
|
1374
1381
|
setCurrentIndex(i);
|
|
@@ -1389,7 +1396,7 @@ function ResultPanel({ selectedHashes, useMainline, noCommit, stashed, onStashRe
|
|
|
1389
1396
|
executeFrom(0);
|
|
1390
1397
|
});
|
|
1391
1398
|
}, []);
|
|
1392
|
-
const continueRemaining =
|
|
1399
|
+
const continueRemaining = useCallback3(async () => {
|
|
1393
1400
|
const remaining = remainingRef.current;
|
|
1394
1401
|
if (remaining.length === 0) {
|
|
1395
1402
|
await finishAll();
|
|
@@ -1409,7 +1416,7 @@ function ResultPanel({ selectedHashes, useMainline, noCommit, stashed, onStashRe
|
|
|
1409
1416
|
}
|
|
1410
1417
|
await finishAll();
|
|
1411
1418
|
}, [useMainline, noCommit, finishAll]);
|
|
1412
|
-
const handleContinue =
|
|
1419
|
+
const handleContinue = useCallback3(async () => {
|
|
1413
1420
|
const conflicts = await getConflictFiles();
|
|
1414
1421
|
if (conflicts.length > 0) {
|
|
1415
1422
|
setConflictFiles(conflicts);
|
|
@@ -1442,14 +1449,14 @@ function ResultPanel({ selectedHashes, useMainline, noCommit, stashed, onStashRe
|
|
|
1442
1449
|
await continueRemaining();
|
|
1443
1450
|
}
|
|
1444
1451
|
}, [noCommit, continueRemaining]);
|
|
1445
|
-
const handleSkip =
|
|
1452
|
+
const handleSkip = useCallback3(async () => {
|
|
1446
1453
|
setPhase("continuing");
|
|
1447
1454
|
setErrorMsg("");
|
|
1448
1455
|
await skipCherryPick();
|
|
1449
1456
|
setSkippedCount((c) => c + 1);
|
|
1450
1457
|
await continueRemaining();
|
|
1451
1458
|
}, [continueRemaining]);
|
|
1452
|
-
const handleAbort =
|
|
1459
|
+
const handleAbort = useCallback3(async () => {
|
|
1453
1460
|
setPhase("aborting");
|
|
1454
1461
|
await abortCherryPick();
|
|
1455
1462
|
if (backupBranchRef.current) {
|
|
@@ -1741,11 +1748,9 @@ function UpdateBanner({ currentVersion }) {
|
|
|
1741
1748
|
}
|
|
1742
1749
|
|
|
1743
1750
|
// src/app.tsx
|
|
1744
|
-
import { execSync } from "child_process";
|
|
1745
|
-
import { createRequire } from "module";
|
|
1751
|
+
import { execSync as execSync2 } from "child_process";
|
|
1746
1752
|
import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1747
|
-
var
|
|
1748
|
-
var { version: APP_VERSION } = require2("../package.json");
|
|
1753
|
+
var APP_VERSION = "0.1.9";
|
|
1749
1754
|
var STEP_NUMBER = {
|
|
1750
1755
|
checking: 0,
|
|
1751
1756
|
"stash-recovery": 0,
|
|
@@ -1776,7 +1781,7 @@ function App({ initialRemote, initialBranch }) {
|
|
|
1776
1781
|
const stashRestoredRef = useRef5(false);
|
|
1777
1782
|
const mountedRef = useRef5(true);
|
|
1778
1783
|
const debounceTimer = useRef5(null);
|
|
1779
|
-
const setStep =
|
|
1784
|
+
const setStep = useCallback4((newStep) => {
|
|
1780
1785
|
setInputReady(false);
|
|
1781
1786
|
setStepRaw(newStep);
|
|
1782
1787
|
if (debounceTimer.current) clearTimeout(debounceTimer.current);
|
|
@@ -1784,10 +1789,10 @@ function App({ initialRemote, initialBranch }) {
|
|
|
1784
1789
|
if (mountedRef.current) setInputReady(true);
|
|
1785
1790
|
}, STEP_DEBOUNCE);
|
|
1786
1791
|
}, []);
|
|
1787
|
-
const restoreStashSync =
|
|
1792
|
+
const restoreStashSync = useCallback4(() => {
|
|
1788
1793
|
if (stashedRef.current && !stashRestoredRef.current) {
|
|
1789
1794
|
try {
|
|
1790
|
-
|
|
1795
|
+
execSync2("git stash pop", { stdio: "ignore" });
|
|
1791
1796
|
stashRestoredRef.current = true;
|
|
1792
1797
|
removeStashGuardSync();
|
|
1793
1798
|
} catch {
|
|
@@ -1798,7 +1803,7 @@ function App({ initialRemote, initialBranch }) {
|
|
|
1798
1803
|
}
|
|
1799
1804
|
}
|
|
1800
1805
|
}, []);
|
|
1801
|
-
const markStashRestored =
|
|
1806
|
+
const markStashRestored = useCallback4(() => {
|
|
1802
1807
|
stashRestoredRef.current = true;
|
|
1803
1808
|
removeStashGuard();
|
|
1804
1809
|
}, []);
|
|
@@ -1857,7 +1862,7 @@ function App({ initialRemote, initialBranch }) {
|
|
|
1857
1862
|
const clean = await isWorkingDirClean();
|
|
1858
1863
|
if (mountedRef.current) setStep(clean ? entryStep : "stash-prompt");
|
|
1859
1864
|
};
|
|
1860
|
-
const goBack =
|
|
1865
|
+
const goBack = useCallback4((fromStep) => {
|
|
1861
1866
|
const backMap = {
|
|
1862
1867
|
branch: "remote",
|
|
1863
1868
|
"branch-check": "branch",
|
|
@@ -1873,7 +1878,7 @@ function App({ initialRemote, initialBranch }) {
|
|
|
1873
1878
|
}
|
|
1874
1879
|
}, [setStep, restoreStashSync, exit]);
|
|
1875
1880
|
return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
|
|
1876
|
-
/* @__PURE__ */ jsx11(AppHeader, { step: STEP_NUMBER[step], stashed, noCommit }),
|
|
1881
|
+
/* @__PURE__ */ jsx11(AppHeader, { step: STEP_NUMBER[step], stashed, noCommit, version: APP_VERSION }),
|
|
1877
1882
|
step === "checking" && /* @__PURE__ */ jsx11(Spinner7, { label: "\u68C0\u67E5\u5DE5\u4F5C\u533A\u72B6\u6001..." }),
|
|
1878
1883
|
step === "stash-recovery" && inputReady && /* @__PURE__ */ jsx11(
|
|
1879
1884
|
StashRecovery,
|
|
@@ -1924,9 +1929,11 @@ function App({ initialRemote, initialBranch }) {
|
|
|
1924
1929
|
{
|
|
1925
1930
|
remote: remote2,
|
|
1926
1931
|
branch: branch2,
|
|
1927
|
-
onSelect: (hashes, loadedCommits) => {
|
|
1932
|
+
onSelect: async (hashes, loadedCommits) => {
|
|
1928
1933
|
setSelectedHashes(hashes);
|
|
1929
1934
|
setCommits(loadedCommits);
|
|
1935
|
+
const merge = await hasMergeCommits(hashes);
|
|
1936
|
+
setHasMerge(merge);
|
|
1930
1937
|
setStep("confirm");
|
|
1931
1938
|
},
|
|
1932
1939
|
onBack: () => goBack("commits")
|
|
@@ -1966,18 +1973,13 @@ function App({ initialRemote, initialBranch }) {
|
|
|
1966
1973
|
|
|
1967
1974
|
// src/cli-runner.ts
|
|
1968
1975
|
import { createInterface } from "readline";
|
|
1969
|
-
|
|
1970
|
-
var require3 = createRequire2(import.meta.url);
|
|
1971
|
-
var { version: APP_VERSION2 } = require3("../package.json");
|
|
1976
|
+
var APP_VERSION2 = "0.1.9";
|
|
1972
1977
|
function log(msg) {
|
|
1973
1978
|
process.stdout.write(msg + "\n");
|
|
1974
1979
|
}
|
|
1975
1980
|
function error(msg) {
|
|
1976
1981
|
process.stderr.write(msg + "\n");
|
|
1977
1982
|
}
|
|
1978
|
-
function padEnd(str, len) {
|
|
1979
|
-
return str.length >= len ? str : str + " ".repeat(len - str.length);
|
|
1980
|
-
}
|
|
1981
1983
|
async function confirm(message) {
|
|
1982
1984
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
1983
1985
|
return new Promise((resolve) => {
|
|
@@ -2039,7 +2041,7 @@ async function validateBranch(remote2, branch2) {
|
|
|
2039
2041
|
log(`\u2714 \u5206\u652F '${remote2}/${branch2}'`);
|
|
2040
2042
|
}
|
|
2041
2043
|
function formatCommitLine(c) {
|
|
2042
|
-
return ` ${c.shortHash} ${
|
|
2044
|
+
return ` ${c.shortHash} ${c.message.slice(0, 60).padEnd(62)} ${c.author.padEnd(16)} ${c.date}`;
|
|
2043
2045
|
}
|
|
2044
2046
|
async function runList(opts) {
|
|
2045
2047
|
await validateRemote(opts.remote);
|
package/package.json
CHANGED