@zjex/git-workflow 0.4.5 → 0.4.7
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/CHANGELOG.md +135 -364
- package/README.md +1 -1
- package/dist/index.js +129 -30
- package/docs/.vitepress/config.ts +2 -0
- package/docs/guide/command-quotes-handling.md +279 -0
- package/docs/guide/debug-mode.md +384 -0
- package/package.json +1 -1
- package/scripts/generate-changelog-manual.js +15 -64
- package/src/commands/tag.ts +42 -10
- package/src/commands/update.ts +25 -9
- package/src/index.ts +11 -3
- package/src/utils.ts +93 -10
- package/tests/command-with-quotes.test.ts +378 -0
- package/tests/debug-mode.test.ts +503 -0
- package/tests/update.test.ts +85 -69
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
# Debug 模式
|
|
2
|
+
|
|
3
|
+
Debug 模式可以帮助你诊断命令执行失败的原因,显示详细的命令、输出和错误信息。
|
|
4
|
+
|
|
5
|
+
## 启用 Debug 模式
|
|
6
|
+
|
|
7
|
+
在任何命令后添加 `--debug` 或 `-d` 参数:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# 基本用法
|
|
11
|
+
gw tag --debug
|
|
12
|
+
gw tag -d
|
|
13
|
+
|
|
14
|
+
# 其他命令
|
|
15
|
+
gw f --debug
|
|
16
|
+
gw b --debug
|
|
17
|
+
gw c --debug
|
|
18
|
+
gw s --debug
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Debug 输出内容
|
|
22
|
+
|
|
23
|
+
启用 debug 模式后,你会看到:
|
|
24
|
+
|
|
25
|
+
### 1. 模式提示
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
🐛 Debug 模式已启用
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 2. 执行的命令
|
|
32
|
+
|
|
33
|
+
每次执行 Git 命令时,会显示完整的命令字符串:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
[DEBUG] 执行命令: git tag -a "v1.5.3" -m "Release v1.5.3"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 3. 退出码
|
|
40
|
+
|
|
41
|
+
命令执行完成后显示退出码:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
[DEBUG] 退出码: 0
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
- `0` 表示成功
|
|
48
|
+
- 非 `0` 表示失败
|
|
49
|
+
|
|
50
|
+
### 4. 标准输出
|
|
51
|
+
|
|
52
|
+
如果命令有标准输出,会显示:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
[DEBUG] 标准输出:
|
|
56
|
+
Counting objects: 3, done.
|
|
57
|
+
Writing objects: 100% (3/3), 256 bytes | 256.00 KiB/s, done.
|
|
58
|
+
Total 3 (delta 0), reused 0 (delta 0)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 5. 错误输出
|
|
62
|
+
|
|
63
|
+
如果命令失败,会显示详细的错误信息:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
[DEBUG] 错误输出:
|
|
67
|
+
fatal: Failed to resolve 'HEAD' as a valid ref.
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 6. 故障排查信息
|
|
71
|
+
|
|
72
|
+
命令失败时,还会显示额外的排查信息:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
[DEBUG] 故障排查信息:
|
|
76
|
+
命令: git tag -a "v1.5.3" -m "Release v1.5.3"
|
|
77
|
+
工作目录: /Users/username/project
|
|
78
|
+
Shell: /bin/zsh
|
|
79
|
+
建议: 尝试在终端中直接运行上述命令以获取更多信息
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## 使用场景
|
|
83
|
+
|
|
84
|
+
### 场景 1:Tag 创建失败
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
$ gw tag --debug
|
|
88
|
+
|
|
89
|
+
🐛 Debug 模式已启用
|
|
90
|
+
|
|
91
|
+
✔ 选择 tag 前缀: v (最新: v1.5.2)
|
|
92
|
+
当前最新 tag: v1.5.2
|
|
93
|
+
|
|
94
|
+
────────────────────────────────────────
|
|
95
|
+
|
|
96
|
+
✔ 选择版本类型: patch → v1.5.3
|
|
97
|
+
|
|
98
|
+
────────────────────────────────────────
|
|
99
|
+
|
|
100
|
+
[DEBUG] 执行命令: git tag -a "v1.5.3" -m "Release v1.5.3"
|
|
101
|
+
[DEBUG] 退出码: 128
|
|
102
|
+
[DEBUG] 错误输出:
|
|
103
|
+
fatal: Failed to resolve 'HEAD' as a valid ref.
|
|
104
|
+
|
|
105
|
+
✗ tag 创建失败
|
|
106
|
+
fatal: Failed to resolve 'HEAD' as a valid ref.
|
|
107
|
+
|
|
108
|
+
[DEBUG] 故障排查信息:
|
|
109
|
+
命令: git tag -a "v1.5.3" -m "Release v1.5.3"
|
|
110
|
+
工作目录: /Users/username/cmk-vue
|
|
111
|
+
Shell: /bin/zsh
|
|
112
|
+
建议: 尝试在终端中直接运行上述命令以获取更多信息
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
从这个输出可以看出:
|
|
116
|
+
|
|
117
|
+
- 命令本身是正确的(引号处理正常)
|
|
118
|
+
- 退出码 128 表示 Git 错误
|
|
119
|
+
- 错误原因:`HEAD` 无法解析(仓库没有提交)
|
|
120
|
+
|
|
121
|
+
### 场景 2:分支推送失败
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
$ gw f --debug
|
|
125
|
+
|
|
126
|
+
🐛 Debug 模式已启用
|
|
127
|
+
|
|
128
|
+
✔ 请输入需求ID: 123
|
|
129
|
+
✔ 请输入描述: add-feature
|
|
130
|
+
|
|
131
|
+
────────────────────────────────────────
|
|
132
|
+
|
|
133
|
+
[DEBUG] 执行命令: git fetch origin main
|
|
134
|
+
[DEBUG] 退出码: 0
|
|
135
|
+
|
|
136
|
+
[DEBUG] 执行命令: git checkout -b "feature/20240120-123-add-feature" origin/main
|
|
137
|
+
[DEBUG] 退出码: 0
|
|
138
|
+
[DEBUG] 标准输出:
|
|
139
|
+
Switched to a new branch 'feature/20240120-123-add-feature'
|
|
140
|
+
|
|
141
|
+
✔ 分支创建成功: feature/20240120-123-add-feature
|
|
142
|
+
|
|
143
|
+
────────────────────────────────────────
|
|
144
|
+
|
|
145
|
+
(自动推送已启用)
|
|
146
|
+
|
|
147
|
+
[DEBUG] 执行命令: git push -u origin "feature/20240120-123-add-feature"
|
|
148
|
+
[DEBUG] 退出码: 128
|
|
149
|
+
[DEBUG] 错误输出:
|
|
150
|
+
fatal: unable to access 'https://github.com/user/repo.git/': Could not resolve host: github.com
|
|
151
|
+
|
|
152
|
+
✗ 远程推送失败
|
|
153
|
+
fatal: unable to access 'https://github.com/user/repo.git/': Could not resolve host: github.com
|
|
154
|
+
|
|
155
|
+
[DEBUG] 故障排查信息:
|
|
156
|
+
命令: git push -u origin "feature/20240120-123-add-feature"
|
|
157
|
+
工作目录: /Users/username/project
|
|
158
|
+
Shell: /bin/zsh
|
|
159
|
+
建议: 尝试在终端中直接运行上述命令以获取更多信息
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
从这个输出可以看出:
|
|
163
|
+
|
|
164
|
+
- 分支创建成功
|
|
165
|
+
- 推送失败是因为网络问题(无法解析 github.com)
|
|
166
|
+
|
|
167
|
+
### 场景 3:Stash 创建失败
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
$ gw s --debug
|
|
171
|
+
|
|
172
|
+
🐛 Debug 模式已启用
|
|
173
|
+
|
|
174
|
+
没有 stash 记录
|
|
175
|
+
✔ 检测到未提交的变更,是否创建 stash? 是
|
|
176
|
+
✔ Stash 消息 (可选): 临时保存:修复bug
|
|
177
|
+
|
|
178
|
+
[DEBUG] 执行命令: git stash push -m "临时保存:修复bug"
|
|
179
|
+
[DEBUG] 退出码: 0
|
|
180
|
+
[DEBUG] 标准输出:
|
|
181
|
+
Saved working directory and index state On master: 临时保存:修复bug
|
|
182
|
+
|
|
183
|
+
✔ Stash 创建成功
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## 对比:普通模式 vs Debug 模式
|
|
187
|
+
|
|
188
|
+
### 普通模式
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
$ gw tag
|
|
192
|
+
|
|
193
|
+
✔ 选择 tag 前缀: v (最新: v1.5.2)
|
|
194
|
+
当前最新 tag: v1.5.2
|
|
195
|
+
|
|
196
|
+
────────────────────────────────────────
|
|
197
|
+
|
|
198
|
+
✔ 选择版本类型: patch → v1.5.3
|
|
199
|
+
|
|
200
|
+
────────────────────────────────────────
|
|
201
|
+
|
|
202
|
+
✗ tag 创建失败
|
|
203
|
+
fatal: Failed to resolve 'HEAD' as a valid ref.
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Debug 模式
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
$ gw tag --debug
|
|
210
|
+
|
|
211
|
+
🐛 Debug 模式已启用
|
|
212
|
+
|
|
213
|
+
✔ 选择 tag 前缀: v (最新: v1.5.2)
|
|
214
|
+
当前最新 tag: v1.5.2
|
|
215
|
+
|
|
216
|
+
────────────────────────────────────────
|
|
217
|
+
|
|
218
|
+
✔ 选择版本类型: patch → v1.5.3
|
|
219
|
+
|
|
220
|
+
────────────────────────────────────────
|
|
221
|
+
|
|
222
|
+
[DEBUG] 执行命令: git tag -a "v1.5.3" -m "Release v1.5.3"
|
|
223
|
+
[DEBUG] 退出码: 128
|
|
224
|
+
[DEBUG] 错误输出:
|
|
225
|
+
fatal: Failed to resolve 'HEAD' as a valid ref.
|
|
226
|
+
|
|
227
|
+
✗ tag 创建失败
|
|
228
|
+
fatal: Failed to resolve 'HEAD' as a valid ref.
|
|
229
|
+
|
|
230
|
+
[DEBUG] 故障排查信息:
|
|
231
|
+
命令: git tag -a "v1.5.3" -m "Release v1.5.3"
|
|
232
|
+
工作目录: /Users/username/cmk-vue
|
|
233
|
+
Shell: /bin/zsh
|
|
234
|
+
建议: 尝试在终端中直接运行上述命令以获取更多信息
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## 常见问题排查
|
|
238
|
+
|
|
239
|
+
### 问题 1:Failed to resolve 'HEAD'
|
|
240
|
+
|
|
241
|
+
**错误信息:**
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
fatal: Failed to resolve 'HEAD' as a valid ref.
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**原因:** 仓库没有任何提交
|
|
248
|
+
|
|
249
|
+
**解决方法:**
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
git add .
|
|
253
|
+
git commit -m "Initial commit"
|
|
254
|
+
gw tag
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### 问题 2:Tag already exists
|
|
258
|
+
|
|
259
|
+
**错误信息:**
|
|
260
|
+
|
|
261
|
+
```
|
|
262
|
+
fatal: tag 'v1.5.3' already exists
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
**原因:** Tag 已经存在
|
|
266
|
+
|
|
267
|
+
**解决方法:**
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
# 删除旧 tag
|
|
271
|
+
git tag -d v1.5.3
|
|
272
|
+
git push origin --delete v1.5.3
|
|
273
|
+
|
|
274
|
+
# 重新创建
|
|
275
|
+
gw tag
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### 问题 3:Network error
|
|
279
|
+
|
|
280
|
+
**错误信息:**
|
|
281
|
+
|
|
282
|
+
```
|
|
283
|
+
fatal: unable to access 'https://github.com/...': Could not resolve host
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**原因:** 网络连接问题
|
|
287
|
+
|
|
288
|
+
**解决方法:**
|
|
289
|
+
|
|
290
|
+
- 检查网络连接
|
|
291
|
+
- 检查代理设置
|
|
292
|
+
- 稍后重试
|
|
293
|
+
|
|
294
|
+
### 问题 4:Permission denied
|
|
295
|
+
|
|
296
|
+
**错误信息:**
|
|
297
|
+
|
|
298
|
+
```
|
|
299
|
+
fatal: could not read Username for 'https://github.com': terminal prompts disabled
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
**原因:** 没有配置 Git 凭据
|
|
303
|
+
|
|
304
|
+
**解决方法:**
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
# 配置 SSH
|
|
308
|
+
ssh-keygen -t ed25519 -C "your_email@example.com"
|
|
309
|
+
# 添加 SSH key 到 GitHub
|
|
310
|
+
|
|
311
|
+
# 或使用 HTTPS + token
|
|
312
|
+
git config --global credential.helper store
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## 提交 Bug 报告
|
|
316
|
+
|
|
317
|
+
如果你遇到问题需要提交 bug 报告,请:
|
|
318
|
+
|
|
319
|
+
1. **使用 debug 模式重现问题**
|
|
320
|
+
|
|
321
|
+
```bash
|
|
322
|
+
gw <command> --debug > debug.log 2>&1
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
2. **包含以下信息**
|
|
326
|
+
- 完整的 debug 输出
|
|
327
|
+
- 操作系统和 Shell 版本
|
|
328
|
+
- Git 版本:`git --version`
|
|
329
|
+
- gw 版本:`gw --version`
|
|
330
|
+
- 仓库状态:`git status`
|
|
331
|
+
|
|
332
|
+
3. **提交到 GitHub Issues**
|
|
333
|
+
- 附上 `debug.log` 文件
|
|
334
|
+
- 描述期望的行为
|
|
335
|
+
- 描述实际的行为
|
|
336
|
+
|
|
337
|
+
## 性能影响
|
|
338
|
+
|
|
339
|
+
Debug 模式会:
|
|
340
|
+
|
|
341
|
+
- ✅ 捕获额外的输出信息
|
|
342
|
+
- ✅ 显示更多日志
|
|
343
|
+
- ⚠️ 轻微增加执行时间(通常 < 100ms)
|
|
344
|
+
- ✅ 不影响命令的实际功能
|
|
345
|
+
|
|
346
|
+
建议:
|
|
347
|
+
|
|
348
|
+
- 日常使用:不启用 debug 模式
|
|
349
|
+
- 遇到问题:启用 debug 模式排查
|
|
350
|
+
- 提交 bug:必须提供 debug 输出
|
|
351
|
+
|
|
352
|
+
## 相关命令
|
|
353
|
+
|
|
354
|
+
```bash
|
|
355
|
+
# 查看版本
|
|
356
|
+
gw --version
|
|
357
|
+
gw -v
|
|
358
|
+
|
|
359
|
+
# 查看帮助
|
|
360
|
+
gw --help
|
|
361
|
+
gw -h
|
|
362
|
+
|
|
363
|
+
# 启用 debug
|
|
364
|
+
gw <command> --debug
|
|
365
|
+
gw <command> -d
|
|
366
|
+
|
|
367
|
+
# 组合使用(不支持)
|
|
368
|
+
# ❌ gw --version --debug # 不会显示 debug 信息
|
|
369
|
+
# ✅ gw tag --debug # 正确用法
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
## 实现细节
|
|
373
|
+
|
|
374
|
+
Debug 模式通过以下方式实现:
|
|
375
|
+
|
|
376
|
+
1. **全局标志**:在主入口设置全局 `DEBUG_MODE` 标志
|
|
377
|
+
2. **命令拦截**:在 `execAsync` 中检查 debug 模式
|
|
378
|
+
3. **输出捕获**:捕获 stdout 和 stderr
|
|
379
|
+
4. **格式化输出**:使用颜色和前缀标识 debug 信息
|
|
380
|
+
|
|
381
|
+
相关文件:
|
|
382
|
+
|
|
383
|
+
- `src/index.ts` - 解析 `--debug` 参数
|
|
384
|
+
- `src/utils.ts` - 实现 debug 输出逻辑
|
package/package.json
CHANGED
|
@@ -30,7 +30,7 @@ for (let i = 0; i < tags.length; i++) {
|
|
|
30
30
|
if (!previousTag) break;
|
|
31
31
|
|
|
32
32
|
changelog += `## [${currentTag}](https://github.com/iamzjt-front-end/git-workflow/compare/${previousTag}...${currentTag}) (${getTagDate(
|
|
33
|
-
currentTag
|
|
33
|
+
currentTag,
|
|
34
34
|
)})\n\n`;
|
|
35
35
|
|
|
36
36
|
// 获取该版本的提交
|
|
@@ -39,79 +39,30 @@ for (let i = 0; i < tags.length; i++) {
|
|
|
39
39
|
{
|
|
40
40
|
encoding: "utf8",
|
|
41
41
|
env: { ...process.env, LANG: "zh_CN.UTF-8", LC_ALL: "zh_CN.UTF-8" },
|
|
42
|
-
}
|
|
42
|
+
},
|
|
43
43
|
)
|
|
44
44
|
.trim()
|
|
45
45
|
.split("\n")
|
|
46
46
|
.filter(Boolean);
|
|
47
47
|
|
|
48
|
-
//
|
|
49
|
-
const
|
|
50
|
-
"
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
"
|
|
48
|
+
// 格式化消息:处理多行内容(用 - 分隔的子任务)
|
|
49
|
+
const formatMessage = (msg, commitLink) => {
|
|
50
|
+
const parts = msg.split(" - ");
|
|
51
|
+
if (parts.length === 1) {
|
|
52
|
+
// 没有子任务,直接返回
|
|
53
|
+
return `${msg} ${commitLink}`;
|
|
54
|
+
}
|
|
55
|
+
// 有子任务,主标题后面加 commit hash,子任务换行缩进
|
|
56
|
+
const mainTitle = parts[0];
|
|
57
|
+
const subTasks = parts.slice(1);
|
|
58
|
+
return `${mainTitle} ${commitLink}\n - ${subTasks.join("\n - ")}`;
|
|
59
59
|
};
|
|
60
60
|
|
|
61
|
+
// 直接输出提交信息,不分组
|
|
61
62
|
commits.forEach((commit) => {
|
|
62
63
|
const [message, hash] = commit.split("|");
|
|
63
64
|
const link = `([${hash}](https://github.com/iamzjt-front-end/git-workflow/commit/${hash}))`;
|
|
64
|
-
|
|
65
|
-
if (message.match(/^(feat|✨)/i)) {
|
|
66
|
-
groups["✨ Features"].push(
|
|
67
|
-
`- ${message.replace(/^(feat|✨)[:(]\w*\)?:?\s*/i, "")} ${link}`
|
|
68
|
-
);
|
|
69
|
-
} else if (message.match(/^(fix|🐛)/i)) {
|
|
70
|
-
groups["🐛 Bug Fixes"].push(
|
|
71
|
-
`- ${message.replace(/^(fix|🐛)[:(]\w*\)?:?\s*/i, "")} ${link}`
|
|
72
|
-
);
|
|
73
|
-
} else if (message.match(/^(docs|📖|📝)/i)) {
|
|
74
|
-
groups["📖 Documentation"].push(
|
|
75
|
-
`- ${message.replace(/^(docs|📖|📝)[:(]\w*\)?:?\s*/i, "")} ${link}`
|
|
76
|
-
);
|
|
77
|
-
} else if (message.match(/^(style|🎨)/i)) {
|
|
78
|
-
groups["🎨 Styles"].push(
|
|
79
|
-
`- ${message.replace(/^(style|🎨)[:(]\w*\)?:?\s*/i, "")} ${link}`
|
|
80
|
-
);
|
|
81
|
-
} else if (message.match(/^(refactor|♻️)/i)) {
|
|
82
|
-
groups["♻️ Refactors"].push(
|
|
83
|
-
`- ${message.replace(/^(refactor|♻️)[:(]\w*\)?:?\s*/i, "")} ${link}`
|
|
84
|
-
);
|
|
85
|
-
} else if (message.match(/^(perf|⚡)/i)) {
|
|
86
|
-
groups["⚡ Performance"].push(
|
|
87
|
-
`- ${message.replace(/^(perf|⚡)[:(]\w*\)?:?\s*/i, "")} ${link}`
|
|
88
|
-
);
|
|
89
|
-
} else if (message.match(/^(test|✅)/i)) {
|
|
90
|
-
groups["✅ Tests"].push(
|
|
91
|
-
`- ${message.replace(/^(test|✅)[:(]\w*\)?:?\s*/i, "")} ${link}`
|
|
92
|
-
);
|
|
93
|
-
} else if (message.match(/^(chore|🔧|🏡)/i)) {
|
|
94
|
-
groups["🔧 Chore"].push(
|
|
95
|
-
`- ${message.replace(/^(chore|🔧|🏡)[:(]\w*\)?:?\s*/i, "")} ${link}`
|
|
96
|
-
);
|
|
97
|
-
} else if (message.match(/^(ci|🤖)/i)) {
|
|
98
|
-
groups["🤖 CI"].push(
|
|
99
|
-
`- ${message.replace(/^(ci|🤖)[:(]\w*\)?:?\s*/i, "")} ${link}`
|
|
100
|
-
);
|
|
101
|
-
} else {
|
|
102
|
-
groups["🔧 Chore"].push(`- ${message} ${link}`);
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
// 输出各分组
|
|
107
|
-
Object.entries(groups).forEach(([title, items]) => {
|
|
108
|
-
if (items.length > 0) {
|
|
109
|
-
changelog += `### ${title}\n\n`;
|
|
110
|
-
items.forEach((item) => {
|
|
111
|
-
changelog += `${item}\n`;
|
|
112
|
-
});
|
|
113
|
-
changelog += "\n";
|
|
114
|
-
}
|
|
65
|
+
changelog += `- ${formatMessage(message, link)}\n`;
|
|
115
66
|
});
|
|
116
67
|
|
|
117
68
|
changelog += "\n";
|
package/src/commands/tag.ts
CHANGED
|
@@ -418,6 +418,29 @@ export async function createTag(inputPrefix?: string): Promise<void> {
|
|
|
418
418
|
async function doCreateTag(tagName: string): Promise<void> {
|
|
419
419
|
divider();
|
|
420
420
|
|
|
421
|
+
// 检查是否有提交
|
|
422
|
+
const hasCommits = execOutput("git rev-parse HEAD 2>/dev/null");
|
|
423
|
+
if (!hasCommits) {
|
|
424
|
+
console.log(colors.red("当前仓库没有任何提交"));
|
|
425
|
+
console.log("");
|
|
426
|
+
console.log(colors.dim(" 提示: 需要先创建至少一个提交才能打 tag:"));
|
|
427
|
+
console.log(colors.cyan(" git add ."));
|
|
428
|
+
console.log(colors.cyan(' git commit -m "Initial commit"'));
|
|
429
|
+
console.log(colors.cyan(" gw tag"));
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// 检查 tag 是否已存在
|
|
434
|
+
const existingTags = execOutput("git tag -l").split("\n").filter(Boolean);
|
|
435
|
+
if (existingTags.includes(tagName)) {
|
|
436
|
+
console.log(colors.red(`Tag ${tagName} 已存在`));
|
|
437
|
+
console.log("");
|
|
438
|
+
console.log(colors.dim(" 提示: 如需重新创建,请先删除旧 tag:"));
|
|
439
|
+
console.log(colors.cyan(` git tag -d ${tagName}`));
|
|
440
|
+
console.log(colors.cyan(` git push origin --delete ${tagName}`));
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
|
|
421
444
|
const spinner = ora(`正在创建 tag: ${tagName}`).start();
|
|
422
445
|
const success = await execWithSpinner(
|
|
423
446
|
`git tag -a "${tagName}" -m "Release ${tagName}"`,
|
|
@@ -614,9 +637,12 @@ export async function updateTag(): Promise<void> {
|
|
|
614
637
|
}
|
|
615
638
|
|
|
616
639
|
// 删除旧 tag
|
|
617
|
-
const
|
|
618
|
-
if (!
|
|
640
|
+
const deleteResult = await execAsync(`git tag -d "${oldTag}"`, spinner);
|
|
641
|
+
if (!deleteResult.success) {
|
|
619
642
|
spinner.fail("删除旧 tag 失败");
|
|
643
|
+
if (deleteResult.error) {
|
|
644
|
+
console.log(colors.dim(` ${deleteResult.error}`));
|
|
645
|
+
}
|
|
620
646
|
return;
|
|
621
647
|
}
|
|
622
648
|
|
|
@@ -635,26 +661,32 @@ export async function updateTag(): Promise<void> {
|
|
|
635
661
|
const pushSpinner = ora("正在同步到远程...").start();
|
|
636
662
|
|
|
637
663
|
// 推送新 tag
|
|
638
|
-
const
|
|
664
|
+
const pushNewResult = await execAsync(
|
|
639
665
|
`git push origin "${newTag}"`,
|
|
640
666
|
pushSpinner,
|
|
641
667
|
);
|
|
642
|
-
if (!
|
|
668
|
+
if (!pushNewResult.success) {
|
|
643
669
|
pushSpinner.warn(
|
|
644
670
|
`远程同步失败,可稍后手动执行:\n git push origin ${newTag}\n git push origin --delete ${oldTag}`,
|
|
645
671
|
);
|
|
672
|
+
if (pushNewResult.error) {
|
|
673
|
+
console.log(colors.dim(` ${pushNewResult.error}`));
|
|
674
|
+
}
|
|
646
675
|
return;
|
|
647
676
|
}
|
|
648
677
|
|
|
649
678
|
// 删除远程旧 tag
|
|
650
|
-
const
|
|
679
|
+
const deleteOldResult = await execAsync(
|
|
651
680
|
`git push origin --delete "${oldTag}"`,
|
|
652
681
|
pushSpinner,
|
|
653
682
|
);
|
|
654
|
-
if (!
|
|
683
|
+
if (!deleteOldResult.success) {
|
|
655
684
|
pushSpinner.warn(
|
|
656
685
|
`远程旧 tag 删除失败,可稍后手动执行: git push origin --delete ${oldTag}`,
|
|
657
686
|
);
|
|
687
|
+
if (deleteOldResult.error) {
|
|
688
|
+
console.log(colors.dim(` ${deleteOldResult.error}`));
|
|
689
|
+
}
|
|
658
690
|
return;
|
|
659
691
|
}
|
|
660
692
|
|
|
@@ -729,8 +761,8 @@ export async function cleanInvalidTags(): Promise<void> {
|
|
|
729
761
|
let localFailed = 0;
|
|
730
762
|
|
|
731
763
|
for (const tag of invalidTags) {
|
|
732
|
-
const
|
|
733
|
-
if (success) {
|
|
764
|
+
const result = await execAsync(`git tag -d "${tag}"`, localSpinner);
|
|
765
|
+
if (result.success) {
|
|
734
766
|
localSuccess++;
|
|
735
767
|
} else {
|
|
736
768
|
localFailed++;
|
|
@@ -761,11 +793,11 @@ export async function cleanInvalidTags(): Promise<void> {
|
|
|
761
793
|
let remoteFailed = 0;
|
|
762
794
|
|
|
763
795
|
for (const tag of invalidTags) {
|
|
764
|
-
const
|
|
796
|
+
const result = await execAsync(
|
|
765
797
|
`git push origin --delete "${tag}"`,
|
|
766
798
|
remoteSpinner,
|
|
767
799
|
);
|
|
768
|
-
if (success) {
|
|
800
|
+
if (result.success) {
|
|
769
801
|
remoteSuccess++;
|
|
770
802
|
} else {
|
|
771
803
|
remoteFailed++;
|
package/src/commands/update.ts
CHANGED
|
@@ -27,16 +27,32 @@ function clearUpdateCache(): void {
|
|
|
27
27
|
* 获取 npm 上的最新版本
|
|
28
28
|
*/
|
|
29
29
|
async function getLatestVersion(packageName: string): Promise<string | null> {
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
timeout:
|
|
34
|
-
stdio: ["pipe", "pipe", "ignore"],
|
|
30
|
+
return new Promise((resolve) => {
|
|
31
|
+
const npmView = spawn("npm", ["view", packageName, "version"], {
|
|
32
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
33
|
+
timeout: 5000,
|
|
35
34
|
});
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
|
|
36
|
+
let output = "";
|
|
37
|
+
|
|
38
|
+
if (npmView.stdout) {
|
|
39
|
+
npmView.stdout.on("data", (data) => {
|
|
40
|
+
output += data.toString();
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
npmView.on("close", (code) => {
|
|
45
|
+
if (code === 0 && output.trim()) {
|
|
46
|
+
resolve(output.trim());
|
|
47
|
+
} else {
|
|
48
|
+
resolve(null);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
npmView.on("error", () => {
|
|
53
|
+
resolve(null);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
40
56
|
}
|
|
41
57
|
|
|
42
58
|
/**
|
package/src/index.ts
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
import { cac } from "cac";
|
|
14
14
|
import { select } from "@inquirer/prompts";
|
|
15
15
|
import { ExitPromptError } from "@inquirer/core";
|
|
16
|
-
import { checkGitRepo, theme, colors } from "./utils.js";
|
|
16
|
+
import { checkGitRepo, theme, colors, setDebugMode } from "./utils.js";
|
|
17
17
|
import { createBranch, deleteBranch } from "./commands/branch.js";
|
|
18
18
|
import {
|
|
19
19
|
listTags,
|
|
@@ -488,12 +488,20 @@ cli
|
|
|
488
488
|
console.log("");
|
|
489
489
|
});
|
|
490
490
|
|
|
491
|
-
// 不使用 cac 的 version,手动处理 --version 和 --
|
|
491
|
+
// 不使用 cac 的 version,手动处理 --version、--help 和 --debug
|
|
492
492
|
cli.option("-v, --version", "显示版本号");
|
|
493
493
|
cli.option("-h, --help", "显示帮助信息");
|
|
494
|
+
cli.option("-d, --debug", "启用调试模式,显示详细的命令和错误信息");
|
|
494
495
|
|
|
495
|
-
// 在 parse 之前检查 --version 和 --
|
|
496
|
+
// 在 parse 之前检查 --version、--help 和 --debug
|
|
496
497
|
const processArgs = process.argv.slice(2);
|
|
498
|
+
|
|
499
|
+
// 检查是否启用 debug 模式
|
|
500
|
+
if (processArgs.includes("-d") || processArgs.includes("--debug")) {
|
|
501
|
+
setDebugMode(true);
|
|
502
|
+
console.log(colors.yellow("🐛 Debug 模式已启用\n"));
|
|
503
|
+
}
|
|
504
|
+
|
|
497
505
|
if (processArgs.includes("-v") || processArgs.includes("--version")) {
|
|
498
506
|
console.log(colors.yellow(`v${version}`));
|
|
499
507
|
process.exit(0);
|