@zjex/git-workflow 0.3.10 → 0.4.1

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/index.js CHANGED
@@ -94,7 +94,7 @@ import { execSync as execSync6 } from "child_process";
94
94
  import { readFileSync as readFileSync3, writeFileSync as writeFileSync4, existsSync as existsSync3, unlinkSync as unlinkSync2 } from "fs";
95
95
  import { homedir as homedir3 } from "os";
96
96
  import { join as join4 } from "path";
97
- import boxen from "boxen";
97
+ import boxen2 from "boxen";
98
98
  import { select as select7 } from "@inquirer/prompts";
99
99
  import ora5 from "ora";
100
100
  import semver from "semver";
@@ -180,7 +180,7 @@ function showSimpleNotification(current, latest) {
180
180
  "gw update"
181
181
  )} ${colors.dim("\u66F4\u65B0")}`;
182
182
  console.log(
183
- boxen(message, {
183
+ boxen2(message, {
184
184
  padding: { top: 0, bottom: 0, left: 2, right: 2 },
185
185
  margin: { top: 0, bottom: 0, left: 0, right: 0 },
186
186
  borderStyle: "round",
@@ -197,9 +197,9 @@ async function showUpdateMessage(current, latest, packageName) {
197
197
  ].join("\n");
198
198
  console.log("");
199
199
  console.log(
200
- boxen(message, {
200
+ boxen2(message, {
201
201
  padding: { top: 1, bottom: 1, left: 3, right: 3 },
202
- margin: 1,
202
+ margin: { top: 0, bottom: 0, left: 1, right: 1 },
203
203
  borderStyle: "round",
204
204
  borderColor: "yellow",
205
205
  align: "center",
@@ -252,7 +252,7 @@ async function performUpdate(packageName) {
252
252
  clearUpdateCache();
253
253
  console.log("");
254
254
  console.log(
255
- boxen(
255
+ boxen2(
256
256
  [
257
257
  colors.green(colors.bold("\u2728 \u66F4\u65B0\u5B8C\u6210\uFF01")),
258
258
  "",
@@ -1138,6 +1138,98 @@ async function updateTag() {
1138
1138
  }
1139
1139
  }
1140
1140
  }
1141
+ async function cleanInvalidTags() {
1142
+ const fetchSpinner = ora2("\u6B63\u5728\u83B7\u53D6 tags...").start();
1143
+ exec("git fetch --tags", true);
1144
+ fetchSpinner.stop();
1145
+ divider();
1146
+ const allTags = execOutput("git tag -l").split("\n").filter(Boolean);
1147
+ const invalidTags = allTags.filter((tag) => !/\d/.test(tag));
1148
+ if (invalidTags.length === 0) {
1149
+ console.log(colors.green("\u2705 \u6CA1\u6709\u627E\u5230\u65E0\u6548\u6807\u7B7E"));
1150
+ return;
1151
+ }
1152
+ console.log(colors.yellow(`\u274C \u627E\u5230 ${invalidTags.length} \u4E2A\u65E0\u6548\u6807\u7B7E\uFF1A`));
1153
+ console.log("");
1154
+ for (const tag of invalidTags) {
1155
+ try {
1156
+ const commitHash = execOutput(`git rev-list -n 1 "${tag}"`).trim();
1157
+ const commitDate = execOutput(`git log -1 --format=%ai "${tag}"`).trim();
1158
+ const commitMsg = execOutput(`git log -1 --format=%s "${tag}"`).trim();
1159
+ console.log(colors.red(` \u6807\u7B7E: ${tag}`));
1160
+ console.log(colors.dim(` Commit: ${commitHash}`));
1161
+ console.log(colors.dim(` \u65E5\u671F: ${commitDate}`));
1162
+ console.log(colors.dim(` \u6D88\u606F: ${commitMsg}`));
1163
+ console.log("");
1164
+ } catch {
1165
+ console.log(colors.red(` \u6807\u7B7E: ${tag}`));
1166
+ console.log(colors.dim(` (\u65E0\u6CD5\u83B7\u53D6\u63D0\u4EA4\u4FE1\u606F)`));
1167
+ console.log("");
1168
+ }
1169
+ }
1170
+ divider();
1171
+ const shouldClean = await select2({
1172
+ message: "\u662F\u5426\u5220\u9664\u8FD9\u4E9B\u65E0\u6548\u6807\u7B7E\uFF1F",
1173
+ choices: [
1174
+ { name: "\u662F\uFF0C\u5220\u9664\u6240\u6709\u65E0\u6548\u6807\u7B7E", value: true },
1175
+ { name: "\u5426\uFF0C\u53D6\u6D88\u64CD\u4F5C", value: false }
1176
+ ],
1177
+ theme
1178
+ });
1179
+ if (!shouldClean) {
1180
+ console.log(colors.yellow("\u5DF2\u53D6\u6D88"));
1181
+ return;
1182
+ }
1183
+ divider();
1184
+ const localSpinner = ora2("\u6B63\u5728\u5220\u9664\u672C\u5730\u65E0\u6548\u6807\u7B7E...").start();
1185
+ let localSuccess = 0;
1186
+ let localFailed = 0;
1187
+ for (const tag of invalidTags) {
1188
+ try {
1189
+ execSync3(`git tag -d "${tag}"`, { stdio: "pipe" });
1190
+ localSuccess++;
1191
+ } catch {
1192
+ localFailed++;
1193
+ }
1194
+ }
1195
+ if (localFailed === 0) {
1196
+ localSpinner.succeed(`\u672C\u5730\u6807\u7B7E\u5DF2\u5220\u9664: ${localSuccess} \u4E2A`);
1197
+ } else {
1198
+ localSpinner.warn(
1199
+ `\u672C\u5730\u6807\u7B7E\u5220\u9664: \u6210\u529F ${localSuccess} \u4E2A\uFF0C\u5931\u8D25 ${localFailed} \u4E2A`
1200
+ );
1201
+ }
1202
+ const deleteRemote = await select2({
1203
+ message: "\u662F\u5426\u540C\u65F6\u5220\u9664\u8FDC\u7A0B\u7684\u65E0\u6548\u6807\u7B7E\uFF1F",
1204
+ choices: [
1205
+ { name: "\u662F", value: true },
1206
+ { name: "\u5426", value: false }
1207
+ ],
1208
+ theme
1209
+ });
1210
+ if (deleteRemote) {
1211
+ const remoteSpinner = ora2("\u6B63\u5728\u5220\u9664\u8FDC\u7A0B\u65E0\u6548\u6807\u7B7E...").start();
1212
+ let remoteSuccess = 0;
1213
+ let remoteFailed = 0;
1214
+ for (const tag of invalidTags) {
1215
+ try {
1216
+ execSync3(`git push origin --delete "${tag}"`, { stdio: "pipe" });
1217
+ remoteSuccess++;
1218
+ } catch {
1219
+ remoteFailed++;
1220
+ }
1221
+ }
1222
+ if (remoteFailed === 0) {
1223
+ remoteSpinner.succeed(`\u8FDC\u7A0B\u6807\u7B7E\u5DF2\u5220\u9664: ${remoteSuccess} \u4E2A`);
1224
+ } else {
1225
+ remoteSpinner.warn(
1226
+ `\u8FDC\u7A0B\u6807\u7B7E\u5220\u9664: \u6210\u529F ${remoteSuccess} \u4E2A\uFF0C\u5931\u8D25 ${remoteFailed} \u4E2A`
1227
+ );
1228
+ }
1229
+ }
1230
+ console.log("");
1231
+ console.log(colors.green("\u2728 \u6E05\u7406\u5B8C\u6210\uFF01"));
1232
+ }
1141
1233
 
1142
1234
  // src/commands/release.ts
1143
1235
  init_utils();
@@ -1583,9 +1675,10 @@ async function init() {
1583
1675
 
1584
1676
  // src/commands/stash.ts
1585
1677
  init_utils();
1586
- import { execSync as execSync4 } from "child_process";
1678
+ import { execSync as execSync4, spawn } from "child_process";
1587
1679
  import { select as select5, input as input4 } from "@inquirer/prompts";
1588
1680
  import ora3 from "ora";
1681
+ import boxen from "boxen";
1589
1682
  function parseStashList() {
1590
1683
  const raw = execOutput('git stash list --format="%gd|%s|%ar"');
1591
1684
  if (!raw) return [];
@@ -1756,18 +1849,119 @@ function applyStash(index, pop) {
1756
1849
  }
1757
1850
  async function showDiff(index) {
1758
1851
  try {
1759
- execSync4(`git stash show -p --color=always stash@{${index}}`, {
1760
- stdio: "inherit"
1761
- });
1762
- console.log();
1852
+ const diffOutput = execOutput(
1853
+ `git stash show -p --no-color stash@{${index}}`
1854
+ );
1855
+ if (!diffOutput) {
1856
+ console.log(colors.yellow("\u6CA1\u6709\u5DEE\u5F02\u5185\u5BB9"));
1857
+ await input4({
1858
+ message: colors.dim("\u6309 Enter \u8FD4\u56DE\u83DC\u5355..."),
1859
+ theme
1860
+ });
1861
+ return;
1862
+ }
1863
+ const statsOutput = execOutput(`git stash show --stat stash@{${index}}`);
1864
+ const files = parseDiffByFile(diffOutput);
1865
+ let fullOutput = "";
1866
+ if (statsOutput) {
1867
+ const statsBox = boxen(statsOutput, {
1868
+ padding: { top: 0, bottom: 0, left: 1, right: 1 },
1869
+ margin: { top: 0, bottom: 1, left: 0, right: 0 },
1870
+ borderStyle: "double",
1871
+ borderColor: "yellow",
1872
+ title: `\u{1F4CA} Stash #${index} \u7EDF\u8BA1`,
1873
+ titleAlignment: "center"
1874
+ });
1875
+ fullOutput += statsBox + "\n";
1876
+ }
1877
+ for (const file of files) {
1878
+ const fileContent = formatFileDiff(file);
1879
+ const fileBox = boxen(fileContent, {
1880
+ padding: { top: 0, bottom: 0, left: 1, right: 1 },
1881
+ margin: { top: 0, bottom: 1, left: 0, right: 0 },
1882
+ borderStyle: "round",
1883
+ borderColor: "cyan",
1884
+ title: `\u{1F4C4} ${file.path}`,
1885
+ titleAlignment: "left"
1886
+ });
1887
+ fullOutput += fileBox + "\n";
1888
+ }
1889
+ await startPager(fullOutput);
1890
+ } catch (error) {
1891
+ console.log(colors.red("\u65E0\u6CD5\u663E\u793A\u5DEE\u5F02"));
1763
1892
  await input4({
1764
1893
  message: colors.dim("\u6309 Enter \u8FD4\u56DE\u83DC\u5355..."),
1765
1894
  theme
1766
1895
  });
1767
- } catch {
1768
- console.log(colors.red("\u65E0\u6CD5\u663E\u793A\u5DEE\u5F02"));
1769
1896
  }
1770
1897
  }
1898
+ function parseDiffByFile(diffOutput) {
1899
+ const files = [];
1900
+ const lines = diffOutput.split("\n");
1901
+ let currentFile = null;
1902
+ for (const line of lines) {
1903
+ if (line.startsWith("diff --git")) {
1904
+ if (currentFile && currentFile.lines.length > 0) {
1905
+ files.push(currentFile);
1906
+ }
1907
+ const match = line.match(/diff --git a\/(.*?) b\/(.*?)$/);
1908
+ const path = match ? match[2] : "unknown";
1909
+ currentFile = { path, lines: [] };
1910
+ } else if (currentFile) {
1911
+ if (line.startsWith("index ") || line.startsWith("--- ") || line.startsWith("+++ ")) {
1912
+ continue;
1913
+ }
1914
+ currentFile.lines.push(line);
1915
+ }
1916
+ }
1917
+ if (currentFile && currentFile.lines.length > 0) {
1918
+ files.push(currentFile);
1919
+ }
1920
+ return files;
1921
+ }
1922
+ function formatFileDiff(file) {
1923
+ const formattedLines = [];
1924
+ for (const line of file.lines) {
1925
+ if (line.startsWith("@@")) {
1926
+ formattedLines.push(colors.blue(line));
1927
+ } else if (line.startsWith("+")) {
1928
+ formattedLines.push(colors.green(line));
1929
+ } else if (line.startsWith("-")) {
1930
+ formattedLines.push(colors.red(line));
1931
+ } else {
1932
+ formattedLines.push(colors.dim(line));
1933
+ }
1934
+ }
1935
+ return formattedLines.join("\n");
1936
+ }
1937
+ function startPager(content) {
1938
+ return new Promise((resolve) => {
1939
+ const pager = process.env.PAGER || "less";
1940
+ try {
1941
+ const pagerProcess = spawn(pager, ["-R", "-S", "-F", "-X", "-i"], {
1942
+ stdio: ["pipe", "inherit", "inherit"],
1943
+ env: { ...process.env, LESS: "-R -S -F -X -i" }
1944
+ });
1945
+ pagerProcess.stdin.on("error", (err) => {
1946
+ if (err.code !== "EPIPE") {
1947
+ console.error(err);
1948
+ }
1949
+ });
1950
+ pagerProcess.stdin.write(content);
1951
+ pagerProcess.stdin.end();
1952
+ pagerProcess.on("exit", () => {
1953
+ resolve();
1954
+ });
1955
+ pagerProcess.on("error", () => {
1956
+ console.log(content);
1957
+ resolve();
1958
+ });
1959
+ } catch (error) {
1960
+ console.log(content);
1961
+ resolve();
1962
+ }
1963
+ });
1964
+ }
1771
1965
  async function createBranchFromStash(index) {
1772
1966
  const type = await select5({
1773
1967
  message: "\u9009\u62E9\u5206\u652F\u7C7B\u578B:",
@@ -2482,7 +2676,7 @@ init_update_notifier();
2482
2676
  init_utils();
2483
2677
  import { execSync as execSync7 } from "child_process";
2484
2678
  import ora6 from "ora";
2485
- import boxen2 from "boxen";
2679
+ import boxen3 from "boxen";
2486
2680
  import semver2 from "semver";
2487
2681
  import { existsSync as existsSync4, unlinkSync as unlinkSync3 } from "fs";
2488
2682
  import { homedir as homedir4 } from "os";
@@ -2534,7 +2728,7 @@ async function update(currentVersion) {
2534
2728
  spinner.stop();
2535
2729
  if (semver2.gte(currentVersion, latestVersion)) {
2536
2730
  console.log(
2537
- boxen2(
2731
+ boxen3(
2538
2732
  [
2539
2733
  colors.green(colors.bold("\u2705 \u5DF2\u662F\u6700\u65B0\u7248\u672C")),
2540
2734
  "",
@@ -2553,7 +2747,7 @@ async function update(currentVersion) {
2553
2747
  }
2554
2748
  const versionText = `${currentVersion} \u2192 ${latestVersion}`;
2555
2749
  console.log(
2556
- boxen2(
2750
+ boxen3(
2557
2751
  [
2558
2752
  colors.yellow(colors.bold("\u{1F389} \u53D1\u73B0\u65B0\u7248\u672C\uFF01")),
2559
2753
  "",
@@ -2581,7 +2775,7 @@ async function update(currentVersion) {
2581
2775
  clearUpdateCache2();
2582
2776
  console.log("");
2583
2777
  console.log(
2584
- boxen2(
2778
+ boxen3(
2585
2779
  [
2586
2780
  colors.green(colors.bold("\u2728 \u66F4\u65B0\u5B8C\u6210\uFF01")),
2587
2781
  "",
@@ -2617,8 +2811,8 @@ async function update(currentVersion) {
2617
2811
  // src/commands/log.ts
2618
2812
  init_utils();
2619
2813
  import { execSync as execSync8 } from "child_process";
2620
- import boxen3 from "boxen";
2621
- import { spawn } from "child_process";
2814
+ import boxen4 from "boxen";
2815
+ import { spawn as spawn2 } from "child_process";
2622
2816
  function parseGitLog(output) {
2623
2817
  const commits = [];
2624
2818
  const lines = output.trim().split("\n");
@@ -2822,7 +3016,7 @@ function formatTimelineStyle(commits) {
2822
3016
  }
2823
3017
  }
2824
3018
  }
2825
- const commitBox = boxen3(commitContent.join("\n"), {
3019
+ const commitBox = boxen4(commitContent.join("\n"), {
2826
3020
  padding: { top: 0, bottom: 0, left: 1, right: 1 },
2827
3021
  margin: { top: 0, bottom: 0, left: 0, right: 0 },
2828
3022
  borderStyle: "round",
@@ -2836,7 +3030,7 @@ function formatTimelineStyle(commits) {
2836
3030
  function startInteractivePager(content) {
2837
3031
  const pager = process.env.PAGER || "less";
2838
3032
  try {
2839
- const pagerProcess = spawn(pager, ["-R", "-S", "-F", "-X", "-i"], {
3033
+ const pagerProcess = spawn2(pager, ["-R", "-S", "-F", "-X", "-i"], {
2840
3034
  stdio: ["pipe", "inherit", "inherit"],
2841
3035
  env: { ...process.env, LESS: "-R -S -F -X -i" }
2842
3036
  });
@@ -2882,7 +3076,7 @@ function executeTimelineLog(options) {
2882
3076
  console.log(fullOutput);
2883
3077
  }
2884
3078
  } else {
2885
- const noCommitsMsg = "\n" + boxen3("\u{1F4ED} \u6CA1\u6709\u627E\u5230\u5339\u914D\u7684\u63D0\u4EA4\u8BB0\u5F55", {
3079
+ const noCommitsMsg = "\n" + boxen4("\u{1F4ED} \u6CA1\u6709\u627E\u5230\u5339\u914D\u7684\u63D0\u4EA4\u8BB0\u5F55", {
2886
3080
  padding: { top: 0, bottom: 0, left: 2, right: 2 },
2887
3081
  borderStyle: "round",
2888
3082
  borderColor: "yellow",
@@ -2901,7 +3095,7 @@ function executeTimelineLog(options) {
2901
3095
  } else {
2902
3096
  errorMessage = `\u274C \u6267\u884C\u5931\u8D25: ${error.message}`;
2903
3097
  }
2904
- const errorBox = "\n" + boxen3(errorMessage, {
3098
+ const errorBox = "\n" + boxen4(errorMessage, {
2905
3099
  padding: { top: 0, bottom: 0, left: 2, right: 2 },
2906
3100
  borderStyle: "round",
2907
3101
  borderColor: "red",
@@ -2949,7 +3143,7 @@ process.on("SIGTERM", () => {
2949
3143
  console.log("");
2950
3144
  process.exit(0);
2951
3145
  });
2952
- var version = true ? "0.3.10" : "0.0.0-dev";
3146
+ var version = true ? "0.4.1" : "0.0.0-dev";
2953
3147
  async function mainMenu() {
2954
3148
  console.log(
2955
3149
  colors.green(`
@@ -2975,7 +3169,7 @@ async function mainMenu() {
2975
3169
  value: "hotfix"
2976
3170
  },
2977
3171
  {
2978
- name: `[3] \u{1F5D1}\uFE0F \u5220\u9664\u5206\u652F ${colors.dim("gw d")}`,
3172
+ name: `[3] \u{1F5D1}\uFE0F \u5220\u9664\u5206\u652F ${colors.dim("gw brd")}`,
2979
3173
  value: "delete"
2980
3174
  },
2981
3175
  {
@@ -2999,15 +3193,15 @@ async function mainMenu() {
2999
3193
  value: "tags"
3000
3194
  },
3001
3195
  {
3002
- name: `[9] \u{1F4E6} \u53D1\u5E03\u7248\u672C ${colors.dim("gw r")}`,
3196
+ name: `[9] \uFFFD \u53D1\u5E03\u7248\u672C ${colors.dim("gw r")}`,
3003
3197
  value: "release"
3004
3198
  },
3005
3199
  {
3006
- name: `[a] \u{1F4BE} \u7BA1\u7406 stash ${colors.dim("gw s")}`,
3200
+ name: `[a] \uFFFD \u7BA1\u7406 stash ${colors.dim("gw s")}`,
3007
3201
  value: "stash"
3008
3202
  },
3009
3203
  {
3010
- name: `[b] \u{1F4CA} \u67E5\u770B\u65E5\u5FD7 ${colors.dim("gw log")}`,
3204
+ name: `[b] \uFFFD \u67E5\u770B\u65E5\u5FD7 ${colors.dim("gw log")}`,
3011
3205
  value: "log"
3012
3206
  },
3013
3207
  {
@@ -3089,7 +3283,7 @@ cli.command("hotfix", "\u521B\u5EFA hotfix \u5206\u652F").alias("fix").alias("h"
3089
3283
  checkGitRepo();
3090
3284
  return createBranch("hotfix", options.base);
3091
3285
  });
3092
- cli.command("delete [branch]", "\u5220\u9664\u672C\u5730/\u8FDC\u7A0B\u5206\u652F").alias("del").alias("d").action(async (branch) => {
3286
+ cli.command("br:del [branch]", "\u5220\u9664\u672C\u5730/\u8FDC\u7A0B\u5206\u652F").alias("brd").action(async (branch) => {
3093
3287
  await checkForUpdates(version, "@zjex/git-workflow");
3094
3288
  checkGitRepo();
3095
3289
  return deleteBranch(branch);
@@ -3104,7 +3298,7 @@ cli.command("tag [prefix]", "\u4EA4\u4E92\u5F0F\u9009\u62E9\u7248\u672C\u7C7B\u5
3104
3298
  checkGitRepo();
3105
3299
  return createTag(prefix);
3106
3300
  });
3107
- cli.command("tag:delete", "\u5220\u9664 tag").alias("td").action(async () => {
3301
+ cli.command("tag:del", "\u5220\u9664 tag").alias("td").action(async () => {
3108
3302
  await checkForUpdates(version, "@zjex/git-workflow");
3109
3303
  checkGitRepo();
3110
3304
  return deleteTag();
@@ -3114,6 +3308,11 @@ cli.command("tag:update", "\u91CD\u547D\u540D tag").alias("tu").action(async ()
3114
3308
  checkGitRepo();
3115
3309
  return updateTag();
3116
3310
  });
3311
+ cli.command("tag:clean", "\u6E05\u7406\u65E0\u6548 tag").alias("tc").action(async () => {
3312
+ await checkForUpdates(version, "@zjex/git-workflow");
3313
+ checkGitRepo();
3314
+ return cleanInvalidTags();
3315
+ });
3117
3316
  cli.command("release", "\u4EA4\u4E92\u5F0F\u9009\u62E9\u7248\u672C\u53F7\u5E76\u66F4\u65B0 package.json").alias("r").action(async () => {
3118
3317
  await checkForUpdates(version, "@zjex/git-workflow");
3119
3318
  return release();
@@ -3142,7 +3341,7 @@ cli.command("log", "\u4EA4\u4E92\u5F0FGit\u65E5\u5FD7\u67E5\u770B (\u5206\u9875\
3142
3341
  if (options.limit) logOptions.limit = parseInt(options.limit);
3143
3342
  return log(logOptions);
3144
3343
  });
3145
- cli.command("clean", "\u6E05\u7406\u7F13\u5B58\u548C\u4E34\u65F6\u6587\u4EF6").action(async () => {
3344
+ cli.command("clean", "\u6E05\u7406\u7F13\u5B58\u548C\u4E34\u65F6\u6587\u4EF6").alias("cc").action(async () => {
3146
3345
  const { clearUpdateCache: clearUpdateCache3 } = await Promise.resolve().then(() => (init_update_notifier(), update_notifier_exports));
3147
3346
  const { existsSync: existsSync5, unlinkSync: unlinkSync4, readdirSync } = await import("fs");
3148
3347
  const { homedir: homedir5, tmpdir: tmpdir2 } = await import("os");