clawt 3.2.0 → 3.3.0
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/README.md +8 -0
- package/dist/index.js +45 -2
- package/dist/postinstall.js +15 -2
- package/docs/home.md +54 -0
- package/docs/spec.md +5 -2
- package/package.json +1 -1
- package/src/commands/home.ts +43 -0
- package/src/commands/remove.ts +13 -0
- package/src/constants/messages/home.ts +7 -0
- package/src/constants/messages/index.ts +2 -0
- package/src/constants/messages/remove.ts +6 -0
- package/src/index.ts +2 -0
- package/tests/unit/commands/remove.test.ts +9 -0
package/README.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -299,7 +299,11 @@ ${failures.map((f) => ` \u2717 ${f.path}: ${f.error}`).join("\n")}`,
|
|
|
299
299
|
/** 用户选择保留本地分支 */
|
|
300
300
|
REMOVE_BRANCHES_KEPT: "\u5DF2\u4FDD\u7559\u672C\u5730\u5206\u652F\uFF0C\u53EF\u7A0D\u540E\u4F7F\u7528 git branch -D <\u5206\u652F\u540D> \u624B\u52A8\u5220\u9664",
|
|
301
301
|
/** 确认删除本地分支和验证分支 */
|
|
302
|
-
REMOVE_CONFIRM_DELETE_BRANCHES: "\u662F\u5426\u540C\u65F6\u5220\u9664\u5BF9\u5E94\u7684\u672C\u5730\u5206\u652F\u548C\u9A8C\u8BC1\u5206\u652F\uFF1F"
|
|
302
|
+
REMOVE_CONFIRM_DELETE_BRANCHES: "\u662F\u5426\u540C\u65F6\u5220\u9664\u5BF9\u5E94\u7684\u672C\u5730\u5206\u652F\u548C\u9A8C\u8BC1\u5206\u652F\uFF1F",
|
|
303
|
+
/** 待移除的 worktree 的分支是主 worktree 当前所在分支 */
|
|
304
|
+
REMOVE_BRANCH_IS_CURRENT: (branch) => `\u65E0\u6CD5\u79FB\u9664\uFF1A\u5206\u652F ${branch} \u662F\u4E3B worktree \u5F53\u524D\u6240\u5728\u5206\u652F\uFF0C\u8BF7\u5148\u5207\u6362\u5230\u5176\u4ED6\u5206\u652F\u540E\u518D\u79FB\u9664`,
|
|
305
|
+
/** 待移除的 worktree 对应的验证分支是主 worktree 当前所在分支 */
|
|
306
|
+
REMOVE_VALIDATE_BRANCH_IS_CURRENT: (branch, validateBranch) => `\u65E0\u6CD5\u79FB\u9664\uFF1A\u5206\u652F ${branch} \u7684\u9A8C\u8BC1\u5206\u652F ${validateBranch} \u662F\u4E3B worktree \u5F53\u524D\u6240\u5728\u5206\u652F\uFF0C\u8BF7\u5148\u5207\u6362\u5230\u5176\u4ED6\u5206\u652F\u540E\u518D\u79FB\u9664`
|
|
303
307
|
};
|
|
304
308
|
|
|
305
309
|
// src/constants/messages/reset.ts
|
|
@@ -469,6 +473,14 @@ var INIT_MESSAGES = {
|
|
|
469
473
|
INIT_SET_SUCCESS: (key, value) => `\u2713 \u9879\u76EE\u914D\u7F6E ${key} \u5DF2\u8BBE\u7F6E\u4E3A ${value}`
|
|
470
474
|
};
|
|
471
475
|
|
|
476
|
+
// src/constants/messages/home.ts
|
|
477
|
+
var HOME_MESSAGES = {
|
|
478
|
+
/** 已在主工作分支上 */
|
|
479
|
+
HOME_ALREADY_ON_MAIN: (branch) => `\u5DF2\u5728\u4E3B\u5DE5\u4F5C\u5206\u652F ${branch} \u4E0A\uFF0C\u65E0\u9700\u5207\u6362`,
|
|
480
|
+
/** 切换成功 */
|
|
481
|
+
HOME_SWITCH_SUCCESS: (from, to) => `\u2713 \u5DF2\u4ECE ${from} \u5207\u6362\u5230\u4E3B\u5DE5\u4F5C\u5206\u652F ${to}`
|
|
482
|
+
};
|
|
483
|
+
|
|
472
484
|
// src/constants/messages/interactive-panel.ts
|
|
473
485
|
import chalk from "chalk";
|
|
474
486
|
|
|
@@ -541,7 +553,8 @@ var MESSAGES = {
|
|
|
541
553
|
...ALIAS_MESSAGES,
|
|
542
554
|
...PROJECTS_MESSAGES,
|
|
543
555
|
...COMPLETION_MESSAGES,
|
|
544
|
-
...INIT_MESSAGES
|
|
556
|
+
...INIT_MESSAGES,
|
|
557
|
+
...HOME_MESSAGES
|
|
545
558
|
};
|
|
546
559
|
|
|
547
560
|
// src/constants/exitCodes.ts
|
|
@@ -3811,6 +3824,16 @@ async function handleRemove(options) {
|
|
|
3811
3824
|
printInfo(MESSAGES.NO_WORKTREES);
|
|
3812
3825
|
return;
|
|
3813
3826
|
}
|
|
3827
|
+
const currentBranch = getCurrentBranch();
|
|
3828
|
+
for (const wt of worktreesToRemove) {
|
|
3829
|
+
if (wt.branch === currentBranch) {
|
|
3830
|
+
throw new ClawtError(MESSAGES.REMOVE_BRANCH_IS_CURRENT(wt.branch));
|
|
3831
|
+
}
|
|
3832
|
+
const validateBranch = getValidateBranchName(wt.branch);
|
|
3833
|
+
if (validateBranch === currentBranch) {
|
|
3834
|
+
throw new ClawtError(MESSAGES.REMOVE_VALIDATE_BRANCH_IS_CURRENT(wt.branch, validateBranch));
|
|
3835
|
+
}
|
|
3836
|
+
}
|
|
3814
3837
|
printInfo("\u5373\u5C06\u79FB\u9664\u4EE5\u4E0B worktree \u53CA\u672C\u5730\u5206\u652F\uFF1A\n");
|
|
3815
3838
|
worktreesToRemove.forEach((wt, index) => {
|
|
3816
3839
|
printInfo(` ${index + 1}. ${wt.path} \u2192 \u5206\u652F: ${wt.branch} \u9A8C\u8BC1\u5206\u652F: ${getValidateBranchName(wt.branch)}`);
|
|
@@ -5144,6 +5167,25 @@ async function handleInit(options) {
|
|
|
5144
5167
|
}
|
|
5145
5168
|
}
|
|
5146
5169
|
|
|
5170
|
+
// src/commands/home.ts
|
|
5171
|
+
function registerHomeCommand(program2) {
|
|
5172
|
+
program2.command("home").description("\u5207\u6362\u56DE\u4E3B\u5DE5\u4F5C\u5206\u652F").action(async () => {
|
|
5173
|
+
await handleHome();
|
|
5174
|
+
});
|
|
5175
|
+
}
|
|
5176
|
+
async function handleHome() {
|
|
5177
|
+
validateMainWorktree();
|
|
5178
|
+
requireProjectConfig();
|
|
5179
|
+
const mainBranch = getMainWorkBranch();
|
|
5180
|
+
const currentBranch = getCurrentBranch();
|
|
5181
|
+
if (currentBranch === mainBranch) {
|
|
5182
|
+
printInfo(MESSAGES.HOME_ALREADY_ON_MAIN(mainBranch));
|
|
5183
|
+
return;
|
|
5184
|
+
}
|
|
5185
|
+
await ensureOnMainWorkBranch();
|
|
5186
|
+
printSuccess(MESSAGES.HOME_SWITCH_SUCCESS(currentBranch, mainBranch));
|
|
5187
|
+
}
|
|
5188
|
+
|
|
5147
5189
|
// src/index.ts
|
|
5148
5190
|
var require2 = createRequire(import.meta.url);
|
|
5149
5191
|
var { version } = require2("../package.json");
|
|
@@ -5170,6 +5212,7 @@ registerAliasCommand(program);
|
|
|
5170
5212
|
registerProjectsCommand(program);
|
|
5171
5213
|
registerCompletionCommand(program);
|
|
5172
5214
|
registerInitCommand(program);
|
|
5215
|
+
registerHomeCommand(program);
|
|
5173
5216
|
var config = loadConfig();
|
|
5174
5217
|
applyAliases(program, config.aliases);
|
|
5175
5218
|
process.on("uncaughtException", (error) => {
|
package/dist/postinstall.js
CHANGED
|
@@ -290,7 +290,11 @@ ${failures.map((f) => ` \u2717 ${f.path}: ${f.error}`).join("\n")}`,
|
|
|
290
290
|
/** 用户选择保留本地分支 */
|
|
291
291
|
REMOVE_BRANCHES_KEPT: "\u5DF2\u4FDD\u7559\u672C\u5730\u5206\u652F\uFF0C\u53EF\u7A0D\u540E\u4F7F\u7528 git branch -D <\u5206\u652F\u540D> \u624B\u52A8\u5220\u9664",
|
|
292
292
|
/** 确认删除本地分支和验证分支 */
|
|
293
|
-
REMOVE_CONFIRM_DELETE_BRANCHES: "\u662F\u5426\u540C\u65F6\u5220\u9664\u5BF9\u5E94\u7684\u672C\u5730\u5206\u652F\u548C\u9A8C\u8BC1\u5206\u652F\uFF1F"
|
|
293
|
+
REMOVE_CONFIRM_DELETE_BRANCHES: "\u662F\u5426\u540C\u65F6\u5220\u9664\u5BF9\u5E94\u7684\u672C\u5730\u5206\u652F\u548C\u9A8C\u8BC1\u5206\u652F\uFF1F",
|
|
294
|
+
/** 待移除的 worktree 的分支是主 worktree 当前所在分支 */
|
|
295
|
+
REMOVE_BRANCH_IS_CURRENT: (branch) => `\u65E0\u6CD5\u79FB\u9664\uFF1A\u5206\u652F ${branch} \u662F\u4E3B worktree \u5F53\u524D\u6240\u5728\u5206\u652F\uFF0C\u8BF7\u5148\u5207\u6362\u5230\u5176\u4ED6\u5206\u652F\u540E\u518D\u79FB\u9664`,
|
|
296
|
+
/** 待移除的 worktree 对应的验证分支是主 worktree 当前所在分支 */
|
|
297
|
+
REMOVE_VALIDATE_BRANCH_IS_CURRENT: (branch, validateBranch) => `\u65E0\u6CD5\u79FB\u9664\uFF1A\u5206\u652F ${branch} \u7684\u9A8C\u8BC1\u5206\u652F ${validateBranch} \u662F\u4E3B worktree \u5F53\u524D\u6240\u5728\u5206\u652F\uFF0C\u8BF7\u5148\u5207\u6362\u5230\u5176\u4ED6\u5206\u652F\u540E\u518D\u79FB\u9664`
|
|
294
298
|
};
|
|
295
299
|
|
|
296
300
|
// src/constants/messages/reset.ts
|
|
@@ -446,6 +450,14 @@ var INIT_MESSAGES = {
|
|
|
446
450
|
INIT_SET_SUCCESS: (key, value) => `\u2713 \u9879\u76EE\u914D\u7F6E ${key} \u5DF2\u8BBE\u7F6E\u4E3A ${value}`
|
|
447
451
|
};
|
|
448
452
|
|
|
453
|
+
// src/constants/messages/home.ts
|
|
454
|
+
var HOME_MESSAGES = {
|
|
455
|
+
/** 已在主工作分支上 */
|
|
456
|
+
HOME_ALREADY_ON_MAIN: (branch) => `\u5DF2\u5728\u4E3B\u5DE5\u4F5C\u5206\u652F ${branch} \u4E0A\uFF0C\u65E0\u9700\u5207\u6362`,
|
|
457
|
+
/** 切换成功 */
|
|
458
|
+
HOME_SWITCH_SUCCESS: (from, to) => `\u2713 \u5DF2\u4ECE ${from} \u5207\u6362\u5230\u4E3B\u5DE5\u4F5C\u5206\u652F ${to}`
|
|
459
|
+
};
|
|
460
|
+
|
|
449
461
|
// src/constants/messages/interactive-panel.ts
|
|
450
462
|
import chalk from "chalk";
|
|
451
463
|
|
|
@@ -498,7 +510,8 @@ var MESSAGES = {
|
|
|
498
510
|
...ALIAS_MESSAGES,
|
|
499
511
|
...PROJECTS_MESSAGES,
|
|
500
512
|
...COMPLETION_MESSAGES,
|
|
501
|
-
...INIT_MESSAGES
|
|
513
|
+
...INIT_MESSAGES,
|
|
514
|
+
...HOME_MESSAGES
|
|
502
515
|
};
|
|
503
516
|
|
|
504
517
|
// src/constants/terminal.ts
|
package/docs/home.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
### 5.20 切换回主工作分支
|
|
2
|
+
|
|
3
|
+
**命令:**
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
clawt home
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
**参数:**
|
|
10
|
+
|
|
11
|
+
无参数。
|
|
12
|
+
|
|
13
|
+
**功能说明:**
|
|
14
|
+
|
|
15
|
+
快速切换回项目的主工作分支。当用户在主 worktree 中处于验证分支或其他分支时,可通过 `clawt home` 一键切换回 `clawtMainWorkBranch` 所记录的主工作分支。
|
|
16
|
+
|
|
17
|
+
**运行流程:**
|
|
18
|
+
|
|
19
|
+
1. **主 worktree 校验** (2.1)
|
|
20
|
+
2. **项目级配置校验**:调用 `requireProjectConfig()` 检查项目是否已初始化
|
|
21
|
+
3. **获取分支信息**:
|
|
22
|
+
- 通过 `getMainWorkBranch()` 获取主工作分支名
|
|
23
|
+
- 通过 `getCurrentBranch()` 获取当前所在分支名
|
|
24
|
+
4. **判断是否需要切换**:
|
|
25
|
+
- 当前分支 === 主工作分支 → 输出提示信息,无需切换
|
|
26
|
+
- 当前分支 !== 主工作分支 → 调用 `ensureOnMainWorkBranch()` 执行切换
|
|
27
|
+
5. **输出结果**
|
|
28
|
+
|
|
29
|
+
**输出格式:**
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
# 已在主工作分支上
|
|
33
|
+
ℹ 已在主工作分支 main 上,无需切换
|
|
34
|
+
|
|
35
|
+
# 切换成功
|
|
36
|
+
✓ 已从 clawt-validate-feat-login 切换到主工作分支 main
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**消息常量:**
|
|
40
|
+
|
|
41
|
+
定义在 `src/constants/messages/home.ts`:
|
|
42
|
+
|
|
43
|
+
| 常量 | 说明 |
|
|
44
|
+
| --- | --- |
|
|
45
|
+
| `HOME_ALREADY_ON_MAIN(branch)` | 已在主工作分支上,无需切换 |
|
|
46
|
+
| `HOME_SWITCH_SUCCESS(from, to)` | 切换成功提示,显示原分支和目标分支 |
|
|
47
|
+
|
|
48
|
+
**实现要点:**
|
|
49
|
+
|
|
50
|
+
- 命令注册函数 `registerHomeCommand` 位于 `src/commands/home.ts`
|
|
51
|
+
- 依赖 `validateMainWorktree`、`requireProjectConfig`、`ensureOnMainWorkBranch`、`getCurrentBranch`、`getMainWorkBranch` 等工具函数
|
|
52
|
+
- `requireProjectConfig()` 为显式调用,因为 home 命令不经过 `ensureOnMainWorkBranch()` 的隐式校验路径(仅在需要切换时才调用 `ensureOnMainWorkBranch()`)
|
|
53
|
+
|
|
54
|
+
---
|
package/docs/spec.md
CHANGED
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
- [5.17 自动更新检查](./update-check.md)
|
|
35
35
|
- [5.18 跨项目 Worktree 概览](./projects.md)
|
|
36
36
|
- [5.19 初始化项目级配置](./init.md)
|
|
37
|
+
- [5.20 切换回主工作分支](./home.md)
|
|
37
38
|
- [6. 验证架构规则](#6-验证架构规则)
|
|
38
39
|
- [7. 错误处理规范](#7-错误处理规范)
|
|
39
40
|
- [8. 非功能性需求](#8-非功能性需求)
|
|
@@ -292,6 +293,7 @@ async function interactiveConfigEditor<T extends object>(
|
|
|
292
293
|
| `clawt alias` | 管理命令别名(列出 / 设置 / 移除) | 5.15 |
|
|
293
294
|
| `clawt completion` | 为终端提供 shell 自动补全功能(bash/zsh) | 5.16 |
|
|
294
295
|
| `clawt projects` | 展示所有项目的 worktree 概览,或查看指定项目的 worktree 详情 | 5.17 |
|
|
296
|
+
| `clawt home` | 快速切换回主工作分支 | 5.20 |
|
|
295
297
|
|
|
296
298
|
**全局选项:**
|
|
297
299
|
|
|
@@ -325,6 +327,7 @@ async function interactiveConfigEditor<T extends object>(
|
|
|
325
327
|
- [5.17 自动更新检查](./update-check.md)
|
|
326
328
|
- [5.18 跨项目 Worktree 概览](./projects.md)
|
|
327
329
|
- [5.19 初始化项目级配置](./init.md)
|
|
330
|
+
- [5.20 切换回主工作分支](./home.md)
|
|
328
331
|
|
|
329
332
|
---
|
|
330
333
|
|
|
@@ -333,12 +336,12 @@ async function interactiveConfigEditor<T extends object>(
|
|
|
333
336
|
以下规则适用于验证分支架构的所有实现工作:
|
|
334
337
|
|
|
335
338
|
1. **不兼容旧版本**:本次重构不考虑旧版本数据、旧版本创建的 worktree 或旧版本配置的兼容性。所有命令均假定验证分支和项目级配置已按新架构存在。用户需删除旧 worktree 后重新创建。
|
|
336
|
-
2. **项目级配置前置校验**:仅对 create、run、validate、sync、remove、merge、reset 这
|
|
339
|
+
2. **项目级配置前置校验**:仅对 create、run、validate、sync、remove、merge、reset、home 这 8 个核心命令添加检测,执行时必须先检查项目级配置(`~/.clawt/projects/<projectName>/config.json`)是否存在且包含 `clawtMainWorkBranch`。如果不存在,直接报错退出并提示用户先执行 `clawt init`:
|
|
337
340
|
```
|
|
338
341
|
✗ 该项目尚未初始化,请先执行 clawt init -b<branchName>设置主工作分支
|
|
339
342
|
```
|
|
340
343
|
其他命令(list、resume、config、status、alias、projects、completion)不受影响,无需添加该校验。
|
|
341
|
-
> **实现细节**:`ensureOnMainWorkBranch()` 内部已通过 `getMainWorkBranch()` → `requireProjectConfig()` 完成了项目配置校验,因此调用了 `ensureOnMainWorkBranch` 的命令(create、run、validate、merge)**无需再显式调用 `requireProjectConfig()`**,避免重复校验。sync 和 remove 命令因不依赖主 worktree 的分支状态而不调用 `ensureOnMainWorkBranch`,需自行显式调用 `requireProjectConfig()`。reset 命令同理,也需自行调用 `requireProjectConfig()`。
|
|
344
|
+
> **实现细节**:`ensureOnMainWorkBranch()` 内部已通过 `getMainWorkBranch()` → `requireProjectConfig()` 完成了项目配置校验,因此调用了 `ensureOnMainWorkBranch` 的命令(create、run、validate、merge)**无需再显式调用 `requireProjectConfig()`**,避免重复校验。sync 和 remove 命令因不依赖主 worktree 的分支状态而不调用 `ensureOnMainWorkBranch`,需自行显式调用 `requireProjectConfig()`。reset 和 home 命令同理,也需自行调用 `requireProjectConfig()`。
|
|
342
345
|
3. **主分支名统一从项目级配置获取**:所有需要获取主分支名的场景(sync 中合并主分支、merge 中计算 merge-base、切回主分支等),统一使用项目级配置中的 `clawtMainWorkBranch`,不再通过 `getCurrentBranch(mainWorktreePath)` 动态获取。因为在新架构下,主 worktree 可能处于验证分支上,`getCurrentBranch` 会返回验证分支名而非真正的主工作分支名。
|
|
343
346
|
4. **测试文件全量更新**:本次重构涉及的所有命令(init、create、run、validate、sync、remove、merge、reset),其对应的测试文件必须同步更新,确保覆盖新增的验证分支逻辑、项目级配置逻辑和变更后的流程。
|
|
344
347
|
|
package/package.json
CHANGED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import { MESSAGES } from '../constants/index.js';
|
|
3
|
+
import {
|
|
4
|
+
validateMainWorktree,
|
|
5
|
+
requireProjectConfig,
|
|
6
|
+
ensureOnMainWorkBranch,
|
|
7
|
+
getCurrentBranch,
|
|
8
|
+
getMainWorkBranch,
|
|
9
|
+
printSuccess,
|
|
10
|
+
printInfo,
|
|
11
|
+
} from '../utils/index.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 注册 home 命令:快速切换回主工作分支
|
|
15
|
+
* @param {Command} program - Commander 实例
|
|
16
|
+
*/
|
|
17
|
+
export function registerHomeCommand(program: Command): void {
|
|
18
|
+
program
|
|
19
|
+
.command('home')
|
|
20
|
+
.description('切换回主工作分支')
|
|
21
|
+
.action(async () => {
|
|
22
|
+
await handleHome();
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 执行 home 命令:切换回主工作分支
|
|
28
|
+
*/
|
|
29
|
+
async function handleHome(): Promise<void> {
|
|
30
|
+
validateMainWorktree();
|
|
31
|
+
requireProjectConfig();
|
|
32
|
+
|
|
33
|
+
const mainBranch = getMainWorkBranch();
|
|
34
|
+
const currentBranch = getCurrentBranch();
|
|
35
|
+
|
|
36
|
+
if (currentBranch === mainBranch) {
|
|
37
|
+
printInfo(MESSAGES.HOME_ALREADY_ON_MAIN(mainBranch));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
await ensureOnMainWorkBranch();
|
|
42
|
+
printSuccess(MESSAGES.HOME_SWITCH_SUCCESS(currentBranch, mainBranch));
|
|
43
|
+
}
|
package/src/commands/remove.ts
CHANGED
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
getValidateBranchName,
|
|
25
25
|
deleteValidateBranch,
|
|
26
26
|
requireProjectConfig,
|
|
27
|
+
getCurrentBranch,
|
|
27
28
|
} from '../utils/index.js';
|
|
28
29
|
import type { WorktreeMultiResolveMessages } from '../utils/index.js';
|
|
29
30
|
|
|
@@ -77,6 +78,18 @@ async function handleRemove(options: RemoveOptions): Promise<void> {
|
|
|
77
78
|
return;
|
|
78
79
|
}
|
|
79
80
|
|
|
81
|
+
// 检查待移除的分支是否是主 worktree 当前所在分支
|
|
82
|
+
const currentBranch = getCurrentBranch();
|
|
83
|
+
for (const wt of worktreesToRemove) {
|
|
84
|
+
if (wt.branch === currentBranch) {
|
|
85
|
+
throw new ClawtError(MESSAGES.REMOVE_BRANCH_IS_CURRENT(wt.branch));
|
|
86
|
+
}
|
|
87
|
+
const validateBranch = getValidateBranchName(wt.branch);
|
|
88
|
+
if (validateBranch === currentBranch) {
|
|
89
|
+
throw new ClawtError(MESSAGES.REMOVE_VALIDATE_BRANCH_IS_CURRENT(wt.branch, validateBranch));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
80
93
|
// 列出即将移除的 worktree
|
|
81
94
|
printInfo('即将移除以下 worktree 及本地分支:\n');
|
|
82
95
|
worktreesToRemove.forEach((wt, index) => {
|
|
@@ -14,6 +14,7 @@ import { PROJECTS_MESSAGES } from './projects.js';
|
|
|
14
14
|
import { COMPLETION_MESSAGES } from './completion.js';
|
|
15
15
|
import { UPDATE_MESSAGES, UPDATE_COMMANDS } from './update.js';
|
|
16
16
|
import { INIT_MESSAGES } from './init.js';
|
|
17
|
+
import { HOME_MESSAGES } from './home.js';
|
|
17
18
|
import { PANEL_FOOTER_SHORTCUTS, PANEL_FOOTER_COUNTDOWN, PANEL_OVERFLOW_DOWN_HINT, PANEL_OVERFLOW_UP_HINT, PANEL_SNAPSHOT_SUMMARY, PANEL_NO_WORKTREES as PANEL_NO_WORKTREES_MSG, PANEL_PRESS_ENTER_TO_RETURN, PANEL_NOT_TTY, PANEL_TITLE } from './interactive-panel.js';
|
|
18
19
|
|
|
19
20
|
export { CONFIG_ALIAS_DISABLED_HINT };
|
|
@@ -40,4 +41,5 @@ export const MESSAGES = {
|
|
|
40
41
|
...PROJECTS_MESSAGES,
|
|
41
42
|
...COMPLETION_MESSAGES,
|
|
42
43
|
...INIT_MESSAGES,
|
|
44
|
+
...HOME_MESSAGES,
|
|
43
45
|
} as const;
|
|
@@ -16,4 +16,10 @@ export const REMOVE_MESSAGES = {
|
|
|
16
16
|
REMOVE_BRANCHES_KEPT: '已保留本地分支,可稍后使用 git branch -D <分支名> 手动删除',
|
|
17
17
|
/** 确认删除本地分支和验证分支 */
|
|
18
18
|
REMOVE_CONFIRM_DELETE_BRANCHES: '是否同时删除对应的本地分支和验证分支?',
|
|
19
|
+
/** 待移除的 worktree 的分支是主 worktree 当前所在分支 */
|
|
20
|
+
REMOVE_BRANCH_IS_CURRENT: (branch: string) =>
|
|
21
|
+
`无法移除:分支 ${branch} 是主 worktree 当前所在分支,请先切换到其他分支后再移除`,
|
|
22
|
+
/** 待移除的 worktree 对应的验证分支是主 worktree 当前所在分支 */
|
|
23
|
+
REMOVE_VALIDATE_BRANCH_IS_CURRENT: (branch: string, validateBranch: string) =>
|
|
24
|
+
`无法移除:分支 ${branch} 的验证分支 ${validateBranch} 是主 worktree 当前所在分支,请先切换到其他分支后再移除`,
|
|
19
25
|
} as const;
|
package/src/index.ts
CHANGED
|
@@ -19,6 +19,7 @@ import { registerAliasCommand } from './commands/alias.js';
|
|
|
19
19
|
import { registerProjectsCommand } from './commands/projects.js';
|
|
20
20
|
import { registerCompletionCommand } from './commands/completion.js';
|
|
21
21
|
import { registerInitCommand } from './commands/init.js';
|
|
22
|
+
import { registerHomeCommand } from './commands/home.js';
|
|
22
23
|
|
|
23
24
|
// 从 package.json 读取版本号,避免硬编码
|
|
24
25
|
const require = createRequire(import.meta.url);
|
|
@@ -58,6 +59,7 @@ registerAliasCommand(program);
|
|
|
58
59
|
registerProjectsCommand(program);
|
|
59
60
|
registerCompletionCommand(program);
|
|
60
61
|
registerInitCommand(program);
|
|
62
|
+
registerHomeCommand(program);
|
|
61
63
|
|
|
62
64
|
// 加载配置并应用命令别名
|
|
63
65
|
const config = loadConfig();
|
|
@@ -25,6 +25,10 @@ vi.mock('../../../src/constants/index.js', () => ({
|
|
|
25
25
|
REMOVE_MULTIPLE_MATCHES: (name: string) => `"${name}" 匹配到多个分支`,
|
|
26
26
|
REMOVE_NO_MATCH: (name: string, branches: string[]) => `未找到与 "${name}" 匹配的分支,可用:${branches.join(', ')}`,
|
|
27
27
|
REMOVE_BRANCHES_KEPT: '已保留本地分支,可稍后使用 git branch -D <分支名> 手动删除',
|
|
28
|
+
REMOVE_BRANCH_IS_CURRENT: (branch: string) =>
|
|
29
|
+
`无法移除:分支 ${branch} 是主 worktree 当前所在分支,请先切换到其他分支后再移除`,
|
|
30
|
+
REMOVE_VALIDATE_BRANCH_IS_CURRENT: (branch: string, validateBranch: string) =>
|
|
31
|
+
`无法移除:分支 ${branch} 的验证分支 ${validateBranch} 是主 worktree 当前所在分支,请先切换到其他分支后再移除`,
|
|
28
32
|
},
|
|
29
33
|
}));
|
|
30
34
|
|
|
@@ -49,6 +53,7 @@ vi.mock('../../../src/utils/index.js', () => ({
|
|
|
49
53
|
requireProjectConfig: vi.fn().mockReturnValue({ clawtMainWorkBranch: 'main' }),
|
|
50
54
|
getValidateBranchName: vi.fn((name: string) => `clawt-validate-${name}`),
|
|
51
55
|
deleteValidateBranch: vi.fn(),
|
|
56
|
+
getCurrentBranch: vi.fn(),
|
|
52
57
|
}));
|
|
53
58
|
|
|
54
59
|
import { registerRemoveCommand } from '../../../src/commands/remove.js';
|
|
@@ -66,6 +71,7 @@ import {
|
|
|
66
71
|
printError,
|
|
67
72
|
printHint,
|
|
68
73
|
resolveTargetWorktrees,
|
|
74
|
+
getCurrentBranch,
|
|
69
75
|
} from '../../../src/utils/index.js';
|
|
70
76
|
|
|
71
77
|
const mockedGetProjectName = vi.mocked(getProjectName);
|
|
@@ -80,6 +86,7 @@ const mockedPrintSuccess = vi.mocked(printSuccess);
|
|
|
80
86
|
const mockedPrintError = vi.mocked(printError);
|
|
81
87
|
const mockedPrintHint = vi.mocked(printHint);
|
|
82
88
|
const mockedResolveTargetWorktrees = vi.mocked(resolveTargetWorktrees);
|
|
89
|
+
const mockedGetCurrentBranch = vi.mocked(getCurrentBranch);
|
|
83
90
|
|
|
84
91
|
beforeEach(() => {
|
|
85
92
|
vi.mocked(validateMainWorktree).mockReset();
|
|
@@ -95,6 +102,8 @@ beforeEach(() => {
|
|
|
95
102
|
mockedPrintError.mockReset();
|
|
96
103
|
mockedPrintHint.mockReset();
|
|
97
104
|
mockedResolveTargetWorktrees.mockReset();
|
|
105
|
+
mockedGetCurrentBranch.mockReset();
|
|
106
|
+
mockedGetCurrentBranch.mockReturnValue('main');
|
|
98
107
|
});
|
|
99
108
|
|
|
100
109
|
describe('registerRemoveCommand', () => {
|