momo-ai 1.0.20 → 1.0.21
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/.claude/skills/algorithmic-art/LICENSE.txt +202 -0
- package/.claude/skills/algorithmic-art/SKILL.md +405 -0
- package/.claude/skills/algorithmic-art/templates/generator_template.js +223 -0
- package/.claude/skills/algorithmic-art/templates/viewer.html +599 -0
- package/.claude/skills/r2mo-rad-lain/PROMPT.md +281 -0
- package/.claude/skills/r2mo-rad-lain/README.md +192 -0
- package/.claude/skills/r2mo-rad-lain/SKILL.md +412 -0
- package/.claude/skills/r2mo-rad-lain/examples/argument-parsing.js +154 -0
- package/.claude/skills/r2mo-rad-lain/examples/file-operations.js +182 -0
- package/.claude/skills/r2mo-rad-lain/file-utils-api.md +281 -0
- package/.claude/skills/r2mo-rad-lain/menu-api.md +187 -0
- package/.claude/skills/r2mo-rad-lain/scripts/file-utils.js +223 -0
- package/.claude/skills/r2mo-rad-lain/scripts/menu.js +289 -0
- package/.claude/skills/r2mo-rad-lain/scripts/yaml-parser.js +209 -0
- package/.claude/skills/r2mo-rad-lain/templates/command.json.template +13 -0
- package/.claude/skills/r2mo-rad-lain/templates/executor.js.template +32 -0
- package/.claude/skills/r2mo-rad-lain/templates/interactive-menu.js.template +221 -0
- package/.cursor/mcp.json +17 -0
- package/.obsidian/app.json +1 -0
- package/.obsidian/appearance.json +4 -0
- package/.obsidian/community-plugins.json +4 -0
- package/.obsidian/core-plugins.json +33 -0
- package/.obsidian/plugins/ai-agent/main.js +98495 -0
- package/.obsidian/plugins/ai-agent/manifest.json +11 -0
- package/.obsidian/plugins/ai-agent/styles.css +806 -0
- package/.obsidian/plugins/dataview/main.js +20876 -0
- package/.obsidian/plugins/dataview/manifest.json +11 -0
- package/.obsidian/plugins/dataview/styles.css +141 -0
- package/.obsidian/plugins/obsidian-excalidraw-plugin/main.js +10 -0
- package/.obsidian/plugins/obsidian-excalidraw-plugin/manifest.json +12 -0
- package/.obsidian/plugins/obsidian-excalidraw-plugin/styles.css +1 -0
- package/.obsidian/plugins/templater-obsidian/main.js +45 -0
- package/.obsidian/plugins/templater-obsidian/manifest.json +11 -0
- package/.obsidian/plugins/templater-obsidian/styles.css +226 -0
- package/.obsidian/plugins/terminal/main.js +200 -0
- package/.obsidian/plugins/terminal/manifest.json +14 -0
- package/.obsidian/plugins/terminal/styles.css +32 -0
- package/.obsidian/themes/AnuPpuccin/manifest.json +7 -0
- package/.obsidian/themes/AnuPpuccin/theme.css +9080 -0
- package/.obsidian/themes/Things/manifest.json +7 -0
- package/.obsidian/themes/Things/theme.css +1628 -0
- package/.obsidian/workspace.json +196 -0
- package/README.md +10 -123
- package/docs/images/logo.jpeg +0 -0
- package/install.sh +1 -0
- package/package.json +6 -2
- package/skills/r2mo-rad-lain/SKILL.md +101 -0
- package/src/_mcp/skills-server.mjs +70 -0
- package/src/_skill/repositories.json +16 -0
- package/src/commander/help.json +5 -0
- package/src/commander/mcp.json +13 -0
- package/src/commander/open.json +8 -2
- package/src/commander/skills.json +20 -0
- package/src/executor/executeEnv.js +48 -38
- package/src/executor/executeHelp.js +77 -16
- package/src/executor/executeInit.js +203 -149
- package/src/executor/executeMcp.js +290 -0
- package/src/executor/executeOpen.js +144 -125
- package/src/executor/executeSkills.js +747 -0
- package/src/executor/index.js +5 -39
- package/src/momo.js +2 -1
- package/src/utils/momo-args.js +39 -0
- package/src/utils/momo-file-utils.js +75 -0
- package/src/utils/momo-menu.js +54 -0
- package/src/commander/actor.json +0 -12
- package/src/commander/actors.json +0 -6
- package/src/commander/add.json +0 -12
- package/src/commander/agent.json +0 -12
- package/src/commander/agentcfg.json +0 -5
- package/src/commander/archive.json +0 -12
- package/src/commander/commit.json +0 -12
- package/src/commander/console.json +0 -7
- package/src/commander/lain.json +0 -7
- package/src/commander/list.json +0 -7
- package/src/commander/plan.json +0 -12
- package/src/commander/project.json +0 -12
- package/src/commander/pull.json +0 -6
- package/src/commander/push.json +0 -6
- package/src/commander/repo.json +0 -18
- package/src/commander/run.json +0 -18
- package/src/commander/show.json +0 -12
- package/src/commander/tasks.json +0 -18
- package/src/commander/unlock.json +0 -6
- package/src/commander/validate.json +0 -12
- package/src/executor/executeActor.js +0 -133
- package/src/executor/executeActors.js +0 -58
- package/src/executor/executeAdd.js +0 -307
- package/src/executor/executeAgent.js +0 -299
- package/src/executor/executeAgentCfg.js +0 -210
- package/src/executor/executeArchive.js +0 -124
- package/src/executor/executeCommit.js +0 -202
- package/src/executor/executeConsole.js +0 -142
- package/src/executor/executeList.js +0 -133
- package/src/executor/executePlan.js +0 -164
- package/src/executor/executeProject.js +0 -313
- package/src/executor/executePull.js +0 -127
- package/src/executor/executePush.js +0 -243
- package/src/executor/executeRepo.js +0 -238
- package/src/executor/executeRun.js +0 -644
- package/src/executor/executeShow.js +0 -164
- package/src/executor/executeTasks.js +0 -384
- package/src/executor/executeUnlock.js +0 -110
- package/src/executor/executeValidate.js +0 -210
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const { exec } = require('child_process');
|
|
4
|
-
const util = require('util');
|
|
5
|
-
const Ec = require('../epic');
|
|
6
|
-
|
|
7
|
-
// 将 exec 转换为 Promise 版本
|
|
8
|
-
const execAsync = util.promisify(exec);
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* 检查目录是否为 Git 仓库
|
|
12
|
-
* @param {string} dirPath 目录路径
|
|
13
|
-
* @returns {Promise<boolean>} 是否为 Git 仓库
|
|
14
|
-
*/
|
|
15
|
-
const _isGitRepo = async (dirPath) => {
|
|
16
|
-
try {
|
|
17
|
-
await execAsync('git rev-parse --git-dir', { cwd: dirPath });
|
|
18
|
-
return true;
|
|
19
|
-
} catch (error) {
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* 从远程拉取最新代码
|
|
26
|
-
* @param {string} dirPath 目录路径
|
|
27
|
-
*/
|
|
28
|
-
const _pullRepo = async (dirPath) => {
|
|
29
|
-
try {
|
|
30
|
-
Ec.waiting(`正在从远程拉取代码: ${dirPath}`);
|
|
31
|
-
const { stdout, stderr } = await execAsync('git pull', { cwd: dirPath });
|
|
32
|
-
|
|
33
|
-
if (stdout) {
|
|
34
|
-
Ec.waiting(`输出: ${stdout.trim()}`);
|
|
35
|
-
}
|
|
36
|
-
if (stderr) {
|
|
37
|
-
Ec.waiting(`进度: ${stderr.trim()}`);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
Ec.waiting(`✅ 成功拉取代码: ${dirPath}`);
|
|
41
|
-
} catch (error) {
|
|
42
|
-
Ec.error(`❌ 拉取代码失败 ${dirPath}: ${error.message}`);
|
|
43
|
-
throw error;
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* 更新 submodule
|
|
49
|
-
* @param {string} dirPath 目录路径
|
|
50
|
-
*/
|
|
51
|
-
const _updateSubmodules = async (dirPath) => {
|
|
52
|
-
try {
|
|
53
|
-
Ec.waiting(`正在更新 Submodule: ${dirPath}`);
|
|
54
|
-
const { stdout, stderr } = await execAsync('git submodule update --remote --merge', { cwd: dirPath });
|
|
55
|
-
|
|
56
|
-
if (stdout) {
|
|
57
|
-
Ec.waiting(`输出: ${stdout.trim()}`);
|
|
58
|
-
}
|
|
59
|
-
if (stderr) {
|
|
60
|
-
Ec.waiting(`进度: ${stderr.trim()}`);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
Ec.waiting(`✅ 成功更新 Submodule: ${dirPath}`);
|
|
64
|
-
} catch (error) {
|
|
65
|
-
Ec.error(`❌ 更新 Submodule 失败 ${dirPath}: ${error.message}`);
|
|
66
|
-
throw error;
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
module.exports = async (options) => {
|
|
71
|
-
// 参数提取
|
|
72
|
-
const parsed = Ec.parseArgument(options);
|
|
73
|
-
|
|
74
|
-
try {
|
|
75
|
-
// 获取 source 目录路径
|
|
76
|
-
const sourceDir = path.resolve(process.cwd(), 'source');
|
|
77
|
-
|
|
78
|
-
// 检查 source 目录是否存在
|
|
79
|
-
if (!fs.existsSync(sourceDir)) {
|
|
80
|
-
Ec.error("❌ 未找到 source 目录");
|
|
81
|
-
process.exit(1);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// 获取所有 develop-xx 目录
|
|
85
|
-
const files = fs.readdirSync(sourceDir);
|
|
86
|
-
const developDirs = files.filter(file =>
|
|
87
|
-
fs.statSync(path.join(sourceDir, file)).isDirectory() &&
|
|
88
|
-
file.match(/^develop-\d+$/)
|
|
89
|
-
).sort();
|
|
90
|
-
|
|
91
|
-
if (developDirs.length === 0) {
|
|
92
|
-
Ec.waiting("🔍 未找到任何 develop 副本目录");
|
|
93
|
-
process.exit(0);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
Ec.waiting(`共找到 ${developDirs.length} 个 develop 副本目录`);
|
|
97
|
-
|
|
98
|
-
// 遍历所有 develop 目录并拉取代码
|
|
99
|
-
for (const dir of developDirs) {
|
|
100
|
-
const fullPath = path.join(sourceDir, dir);
|
|
101
|
-
|
|
102
|
-
// 添加分割线
|
|
103
|
-
Ec.waiting("--------------------------------------------------");
|
|
104
|
-
|
|
105
|
-
// 检查是否为 Git 仓库
|
|
106
|
-
const isGitRepo = await _isGitRepo(fullPath);
|
|
107
|
-
if (!isGitRepo) {
|
|
108
|
-
Ec.waiting(`⚠️ ${fullPath} 不是 Git 仓库,跳过`);
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// 拉取最新代码
|
|
113
|
-
await _pullRepo(fullPath);
|
|
114
|
-
|
|
115
|
-
// 更新 submodule
|
|
116
|
-
await _updateSubmodules(fullPath);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// 添加结束分割线
|
|
120
|
-
Ec.waiting("--------------------------------------------------");
|
|
121
|
-
Ec.info('✅ 所有副本代码拉取完成!');
|
|
122
|
-
process.exit(0);
|
|
123
|
-
} catch (error) {
|
|
124
|
-
Ec.error(`❌ 执行过程中发生错误: ${error.message}`);
|
|
125
|
-
process.exit(1);
|
|
126
|
-
}
|
|
127
|
-
};
|
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const { exec } = require('child_process');
|
|
4
|
-
const util = require('util');
|
|
5
|
-
const Ec = require('../epic');
|
|
6
|
-
|
|
7
|
-
// 将 exec 转换为 Promise 版本
|
|
8
|
-
const execAsync = util.promisify(exec);
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* 检查目录是否为 Git 仓库
|
|
12
|
-
* @param {string} dirPath 目录路径
|
|
13
|
-
* @returns {Promise<boolean>} 是否为 Git 仓库
|
|
14
|
-
*/
|
|
15
|
-
const _isGitRepo = async (dirPath) => {
|
|
16
|
-
try {
|
|
17
|
-
await execAsync('git rev-parse --git-dir', { cwd: dirPath });
|
|
18
|
-
return true;
|
|
19
|
-
} catch (error) {
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* 检查是否有未合并的文件
|
|
26
|
-
* @param {string} dirPath 目录路径
|
|
27
|
-
* @returns {Promise<boolean>} 是否有未合并的文件
|
|
28
|
-
*/
|
|
29
|
-
const _hasUnmergedFiles = async (dirPath) => {
|
|
30
|
-
try {
|
|
31
|
-
const { stdout } = await execAsync('git diff --name-only --diff-filter=U', { cwd: dirPath });
|
|
32
|
-
return stdout.trim() !== '';
|
|
33
|
-
} catch (error) {
|
|
34
|
-
return false;
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* 执行 git merge 命令合并更改
|
|
40
|
-
* @param {string} dirPath 目录路径
|
|
41
|
-
*/
|
|
42
|
-
const _mergeChanges = async (dirPath) => {
|
|
43
|
-
try {
|
|
44
|
-
Ec.waiting(`正在合并更改: ${dirPath}`);
|
|
45
|
-
const { stdout, stderr } = await execAsync('git merge --no-edit', { cwd: dirPath });
|
|
46
|
-
|
|
47
|
-
if (stdout) {
|
|
48
|
-
Ec.waiting(`输出: ${stdout.trim()}`);
|
|
49
|
-
}
|
|
50
|
-
if (stderr) {
|
|
51
|
-
Ec.waiting(`进度: ${stderr.trim()}`);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
Ec.waiting(`✅ 成功合并更改: ${dirPath}`);
|
|
55
|
-
return true;
|
|
56
|
-
} catch (error) {
|
|
57
|
-
Ec.error(`❌ 合并更改失败 ${dirPath}: ${error.message}`);
|
|
58
|
-
return false;
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* 从远程拉取最新代码
|
|
64
|
-
* @param {string} dirPath 目录路径
|
|
65
|
-
*/
|
|
66
|
-
const _pullRepo = async (dirPath) => {
|
|
67
|
-
try {
|
|
68
|
-
Ec.waiting(`正在从远程拉取代码: ${dirPath}`);
|
|
69
|
-
const { stdout, stderr } = await execAsync('git pull', { cwd: dirPath });
|
|
70
|
-
|
|
71
|
-
if (stdout) {
|
|
72
|
-
Ec.waiting(`输出: ${stdout.trim()}`);
|
|
73
|
-
}
|
|
74
|
-
if (stderr) {
|
|
75
|
-
Ec.waiting(`进度: ${stderr.trim()}`);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
Ec.waiting(`✅ 成功拉取代码: ${dirPath}`);
|
|
79
|
-
return true;
|
|
80
|
-
} catch (error) {
|
|
81
|
-
// 检查是否是分支分歧错误
|
|
82
|
-
if (error.message.includes('Need to specify how to reconcile divergent branches')) {
|
|
83
|
-
try {
|
|
84
|
-
Ec.waiting(`检测到分支分歧错误,正在配置 pull.rebase=false: ${dirPath}`);
|
|
85
|
-
await execAsync('git config pull.rebase false', { cwd: dirPath });
|
|
86
|
-
Ec.waiting(`已设置 pull.rebase=false,重新尝试拉取代码: ${dirPath}`);
|
|
87
|
-
|
|
88
|
-
// 重新执行 pull 操作
|
|
89
|
-
const { stdout, stderr } = await execAsync('git pull', { cwd: dirPath });
|
|
90
|
-
|
|
91
|
-
if (stdout) {
|
|
92
|
-
Ec.waiting(`输出: ${stdout.trim()}`);
|
|
93
|
-
}
|
|
94
|
-
if (stderr) {
|
|
95
|
-
Ec.waiting(`进度: ${stderr.trim()}`);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
Ec.waiting(`✅ 成功拉取代码: ${dirPath}`);
|
|
99
|
-
return true;
|
|
100
|
-
} catch (retryError) {
|
|
101
|
-
Ec.error(`❌ 重新拉取代码失败 ${dirPath}: ${retryError.message}`);
|
|
102
|
-
return false;
|
|
103
|
-
}
|
|
104
|
-
} else {
|
|
105
|
-
Ec.error(`❌ 拉取代码失败 ${dirPath}: ${error.message}`);
|
|
106
|
-
return false;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* 推送更改到远程仓库
|
|
113
|
-
* @param {string} dirPath 目录路径
|
|
114
|
-
*/
|
|
115
|
-
const _pushRepo = async (dirPath) => {
|
|
116
|
-
try {
|
|
117
|
-
Ec.waiting(`正在推送更改到远程: ${dirPath}`);
|
|
118
|
-
const { stdout, stderr } = await execAsync('git push', { cwd: dirPath });
|
|
119
|
-
|
|
120
|
-
if (stdout) {
|
|
121
|
-
Ec.waiting(`输出: ${stdout.trim()}`);
|
|
122
|
-
}
|
|
123
|
-
if (stderr) {
|
|
124
|
-
Ec.waiting(`进度: ${stderr.trim()}`);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
Ec.waiting(`✅ 成功推送更改: ${dirPath}`);
|
|
128
|
-
return true;
|
|
129
|
-
} catch (error) {
|
|
130
|
-
Ec.error(`❌ 推送更改失败 ${dirPath}: ${error.message}`);
|
|
131
|
-
return false;
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* 推送 submodule 更改
|
|
137
|
-
* @param {string} dirPath 目录路径
|
|
138
|
-
*/
|
|
139
|
-
const _pushSubmodules = async (dirPath) => {
|
|
140
|
-
try {
|
|
141
|
-
Ec.waiting(`正在推送 Submodule 更改: ${dirPath}`);
|
|
142
|
-
const { stdout, stderr } = await execAsync('git push', { cwd: dirPath });
|
|
143
|
-
|
|
144
|
-
if (stdout) {
|
|
145
|
-
Ec.waiting(`输出: ${stdout.trim()}`);
|
|
146
|
-
}
|
|
147
|
-
if (stderr) {
|
|
148
|
-
Ec.waiting(`进度: ${stderr.trim()}`);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
Ec.waiting(`✅ 成功推送 Submodule 更改: ${dirPath}`);
|
|
152
|
-
return true;
|
|
153
|
-
} catch (error) {
|
|
154
|
-
Ec.error(`❌ 推送 Submodule 更改失败 ${dirPath}: ${error.message}`);
|
|
155
|
-
return false;
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
module.exports = async (options) => {
|
|
160
|
-
// 参数提取
|
|
161
|
-
const parsed = Ec.parseArgument(options);
|
|
162
|
-
|
|
163
|
-
try {
|
|
164
|
-
// 获取 source 目录路径
|
|
165
|
-
const sourceDir = path.resolve(process.cwd(), 'source');
|
|
166
|
-
|
|
167
|
-
// 检查 source 目录是否存在
|
|
168
|
-
if (!fs.existsSync(sourceDir)) {
|
|
169
|
-
Ec.error("❌ 未找到 source 目录");
|
|
170
|
-
process.exit(1);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// 获取所有 develop-xx 目录
|
|
174
|
-
const files = fs.readdirSync(sourceDir);
|
|
175
|
-
const developDirs = files.filter(file =>
|
|
176
|
-
fs.statSync(path.join(sourceDir, file)).isDirectory() &&
|
|
177
|
-
file.match(/^develop-\d+$/)
|
|
178
|
-
).sort();
|
|
179
|
-
|
|
180
|
-
if (developDirs.length === 0) {
|
|
181
|
-
Ec.waiting("🔍 未找到任何 develop 副本目录");
|
|
182
|
-
process.exit(0);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
Ec.waiting(`共找到 ${developDirs.length} 个 develop 副本目录`);
|
|
186
|
-
|
|
187
|
-
let successCount = 0;
|
|
188
|
-
let failCount = 0;
|
|
189
|
-
|
|
190
|
-
// 遍历所有 develop 目录并推送更改
|
|
191
|
-
for (const dir of developDirs) {
|
|
192
|
-
const fullPath = path.join(sourceDir, dir);
|
|
193
|
-
|
|
194
|
-
// 添加分割线
|
|
195
|
-
Ec.waiting("--------------------------------------------------");
|
|
196
|
-
|
|
197
|
-
// 检查是否为 Git 仓库
|
|
198
|
-
const isGitRepo = await _isGitRepo(fullPath);
|
|
199
|
-
if (!isGitRepo) {
|
|
200
|
-
Ec.waiting(`⚠️ ${fullPath} 不是 Git 仓库,跳过`);
|
|
201
|
-
continue;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// 先拉取最新代码
|
|
205
|
-
const pullSuccess = await _pullRepo(fullPath);
|
|
206
|
-
if (!pullSuccess) {
|
|
207
|
-
Ec.error(`❌ 拉取代码失败,跳过推送: ${fullPath}`);
|
|
208
|
-
failCount++;
|
|
209
|
-
continue;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// 推送更改
|
|
213
|
-
const pushSuccess = await _pushRepo(fullPath);
|
|
214
|
-
if (pushSuccess) {
|
|
215
|
-
successCount++;
|
|
216
|
-
} else {
|
|
217
|
-
failCount++;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// 添加分割线
|
|
222
|
-
Ec.waiting("--------------------------------------------------");
|
|
223
|
-
|
|
224
|
-
// 推送主仓库的 submodule 更新
|
|
225
|
-
const pushSubSuccess = await _pushSubmodules(process.cwd());
|
|
226
|
-
if (pushSubSuccess) {
|
|
227
|
-
successCount++;
|
|
228
|
-
} else {
|
|
229
|
-
failCount++;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
if (failCount === 0) {
|
|
233
|
-
Ec.info(`✅ 所有副本推送完成!成功: ${successCount}, 失败: ${failCount}`);
|
|
234
|
-
process.exit(0);
|
|
235
|
-
} else {
|
|
236
|
-
Ec.error(`❌ 推送完成,但有 ${failCount} 个副本失败!成功: ${successCount}, 失败: ${failCount}`);
|
|
237
|
-
process.exit(1);
|
|
238
|
-
}
|
|
239
|
-
} catch (error) {
|
|
240
|
-
Ec.error(`❌ 执行过程中发生错误: ${error.message}`);
|
|
241
|
-
process.exit(1);
|
|
242
|
-
}
|
|
243
|
-
};
|
|
@@ -1,238 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const {exec} = require('child_process');
|
|
4
|
-
const util = require('util');
|
|
5
|
-
const Ec = require('../epic');
|
|
6
|
-
|
|
7
|
-
// 将 exec 转换为 Promise 版本
|
|
8
|
-
const execAsync = util.promisify(exec);
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* 检查当前目录是否为 Git 仓库
|
|
12
|
-
* @returns {Promise<boolean>} 是否为 Git 仓库
|
|
13
|
-
*/
|
|
14
|
-
const _isGitRepo = async () => {
|
|
15
|
-
try {
|
|
16
|
-
await execAsync('git rev-parse --git-dir');
|
|
17
|
-
return true;
|
|
18
|
-
} catch (error) {
|
|
19
|
-
return false;
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* 初始化当前目录为 Git 仓库
|
|
25
|
-
*/
|
|
26
|
-
const _initGitRepo = async () => {
|
|
27
|
-
try {
|
|
28
|
-
Ec.waiting('正在初始化 Git 仓库');
|
|
29
|
-
// 在 Windows 上使用不同的命令格式
|
|
30
|
-
const command = process.platform === 'win32' ? 'git init' : 'git init -b master';
|
|
31
|
-
await execAsync(command);
|
|
32
|
-
Ec.waiting('✅ 成功初始化 Git 仓库');
|
|
33
|
-
} catch (error) {
|
|
34
|
-
Ec.error(`❌ 初始化 Git 仓库失败: ${error.message}`);
|
|
35
|
-
if (process.platform === 'win32') {
|
|
36
|
-
Ec.waiting('💡 Windows 用户提示: 请确保已安装 Git 并在 PATH 环境变量中');
|
|
37
|
-
}
|
|
38
|
-
throw error;
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* 添加远程仓库作为 submodule
|
|
44
|
-
* @param {string} repoUrl 远程仓库地址
|
|
45
|
-
* @param {string} targetDir 目标目录(相对路径)
|
|
46
|
-
*/
|
|
47
|
-
const _addSubmodule = async (repoUrl, targetDir) => {
|
|
48
|
-
try {
|
|
49
|
-
Ec.waiting(`正在添加 Submodule ${repoUrl} 到 ${targetDir}`);
|
|
50
|
-
// 使用相对路径添加 submodule
|
|
51
|
-
const command = `git submodule add ${repoUrl} ${targetDir}`;
|
|
52
|
-
|
|
53
|
-
// 使用 spawn 实现实时输出
|
|
54
|
-
const {spawn} = require('child_process');
|
|
55
|
-
const gitProcess = spawn('git', ['submodule', 'add', repoUrl, targetDir]);
|
|
56
|
-
|
|
57
|
-
// 实时输出 stdout
|
|
58
|
-
gitProcess.stdout.on('data', (data) => {
|
|
59
|
-
Ec.waiting(`Submodule 添加输出: ${data.toString().trim()}`);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
// 实时输出 stderr
|
|
63
|
-
gitProcess.stderr.on('data', (data) => {
|
|
64
|
-
Ec.waiting(`Submodule 添加进度: ${data.toString().trim()}`);
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
// 等待进程完成
|
|
68
|
-
await new Promise((resolve, reject) => {
|
|
69
|
-
gitProcess.on('close', (code) => {
|
|
70
|
-
if (code === 0) {
|
|
71
|
-
Ec.waiting(`✅ 成功添加 Submodule 到 ${targetDir}`);
|
|
72
|
-
resolve();
|
|
73
|
-
} else {
|
|
74
|
-
Ec.error(`❌ git submodule add 命令退出码: ${code}`);
|
|
75
|
-
reject(new Error(`git submodule add 命令退出码: ${code}`));
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
gitProcess.on('error', (error) => {
|
|
80
|
-
Ec.error(`❌ 添加 Submodule 失败: ${error.message}`);
|
|
81
|
-
reject(error);
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
} catch (error) {
|
|
85
|
-
Ec.error(`❌ 添加 Submodule 失败: ${error.message}`);
|
|
86
|
-
throw error;
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* 初始化并更新 submodule
|
|
92
|
-
*/
|
|
93
|
-
const _initAndUpdateSubmodules = async () => {
|
|
94
|
-
try {
|
|
95
|
-
Ec.waiting('正在初始化并更新所有 Submodule');
|
|
96
|
-
const command = 'git submodule update --init --recursive';
|
|
97
|
-
|
|
98
|
-
// 使用 spawn 实现实时输出
|
|
99
|
-
const {spawn} = require('child_process');
|
|
100
|
-
const gitProcess = spawn('git', ['submodule', 'update', '--init', '--recursive']);
|
|
101
|
-
|
|
102
|
-
// 实时输出 stdout
|
|
103
|
-
gitProcess.stdout.on('data', (data) => {
|
|
104
|
-
Ec.waiting(`Submodule 初始化输出: ${data.toString().trim()}`);
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
// 实时输出 stderr
|
|
108
|
-
gitProcess.stderr.on('data', (data) => {
|
|
109
|
-
Ec.waiting(`Submodule 初始化进度: ${data.toString().trim()}`);
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
// 等待进程完成
|
|
113
|
-
await new Promise((resolve, reject) => {
|
|
114
|
-
gitProcess.on('close', (code) => {
|
|
115
|
-
if (code === 0) {
|
|
116
|
-
Ec.waiting('✅ 成功初始化并更新所有 Submodule');
|
|
117
|
-
resolve();
|
|
118
|
-
} else {
|
|
119
|
-
Ec.error(`❌ git submodule update 命令退出码: ${code}`);
|
|
120
|
-
reject(new Error(`git submodule update 命令退出码: ${code}`));
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
gitProcess.on('error', (error) => {
|
|
125
|
-
Ec.error(`❌ 初始化并更新 Submodule 失败: ${error.message}`);
|
|
126
|
-
reject(error);
|
|
127
|
-
});
|
|
128
|
-
});
|
|
129
|
-
} catch (error) {
|
|
130
|
-
Ec.error(`❌ 初始化并更新 Submodule 失败: ${error.message}`);
|
|
131
|
-
throw error;
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* 创建目录(如果不存在)
|
|
137
|
-
* @param {string} dirPath 目录路径
|
|
138
|
-
*/
|
|
139
|
-
const _createDirIfNotExists = async (dirPath) => {
|
|
140
|
-
if (!fs.existsSync(dirPath)) {
|
|
141
|
-
await fs.promises.mkdir(dirPath, {recursive: true});
|
|
142
|
-
}
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* 获取下一个可用的 develop 目录编号
|
|
147
|
-
* @param {string} sourceDir source 目录路径
|
|
148
|
-
* @returns {number} 下一个可用的编号
|
|
149
|
-
*/
|
|
150
|
-
const _getNextDevelopNumber = (sourceDir) => {
|
|
151
|
-
if (!fs.existsSync(sourceDir)) {
|
|
152
|
-
return 1;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const files = fs.readdirSync(sourceDir);
|
|
156
|
-
const developDirs = files.filter(file =>
|
|
157
|
-
fs.statSync(path.join(sourceDir, file)).isDirectory() &&
|
|
158
|
-
file.startsWith('develop-')
|
|
159
|
-
);
|
|
160
|
-
|
|
161
|
-
if (developDirs.length === 0) {
|
|
162
|
-
return 1;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// 提取编号并找出最大值
|
|
166
|
-
const numbers = developDirs.map(dir => {
|
|
167
|
-
const match = dir.match(/^develop-(\d+)$/);
|
|
168
|
-
return match ? parseInt(match[1], 10) : 0;
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
return Math.max(...numbers) + 1;
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
module.exports = async (options) => {
|
|
175
|
-
// 参数提取
|
|
176
|
-
const parsed = Ec.parseArgument(options);
|
|
177
|
-
|
|
178
|
-
// 获取参数
|
|
179
|
-
const repoUrl = parsed.address;
|
|
180
|
-
const instanceCount = parsed.instance;
|
|
181
|
-
|
|
182
|
-
// 验证参数
|
|
183
|
-
if (!repoUrl) {
|
|
184
|
-
Ec.error("❌ 请提供远程仓库地址 (-a, --address)");
|
|
185
|
-
process.exit(1);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// 验证 instanceCount 范围(只能是2位数)
|
|
189
|
-
if (instanceCount < 1 || instanceCount > 99) {
|
|
190
|
-
Ec.error("❌ 实例数量必须在 1-99 之间");
|
|
191
|
-
process.exit(1);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
Ec.waiting(`准备添加 Submodule ${repoUrl},创建 ${instanceCount} 个实例副本...`);
|
|
195
|
-
|
|
196
|
-
try {
|
|
197
|
-
// 检查当前目录是否为 Git 仓库,如果不是则初始化
|
|
198
|
-
const isGitRepo = await _isGitRepo();
|
|
199
|
-
if (!isGitRepo) {
|
|
200
|
-
await _initGitRepo();
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// 确保 source 目录存在
|
|
204
|
-
const sourceDir = path.resolve(process.cwd(), 'source');
|
|
205
|
-
await _createDirIfNotExists(sourceDir);
|
|
206
|
-
|
|
207
|
-
// 获取起始编号
|
|
208
|
-
let startNumber = _getNextDevelopNumber(sourceDir);
|
|
209
|
-
|
|
210
|
-
// 添加指定数量的 submodule 实例
|
|
211
|
-
for (let i = 0; i < instanceCount; i++) {
|
|
212
|
-
const developNumber = startNumber + i;
|
|
213
|
-
// 格式化为两位数
|
|
214
|
-
const formattedNumber = developNumber.toString().padStart(2, '0');
|
|
215
|
-
// 使用相对路径
|
|
216
|
-
const targetDir = path.join('source', `develop-${formattedNumber}`);
|
|
217
|
-
|
|
218
|
-
// 如果目录已存在,跳过
|
|
219
|
-
const fullPath = path.join(process.cwd(), targetDir);
|
|
220
|
-
if (fs.existsSync(fullPath)) {
|
|
221
|
-
Ec.waiting(`⚠️ 目录 ${targetDir} 已存在,跳过`);
|
|
222
|
-
continue;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// 添加 submodule
|
|
226
|
-
await _addSubmodule(repoUrl, targetDir);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// 初始化并更新所有 submodule
|
|
230
|
-
await _initAndUpdateSubmodules();
|
|
231
|
-
|
|
232
|
-
Ec.info('✅ 所有 Submodule 添加完成!');
|
|
233
|
-
process.exit(0);
|
|
234
|
-
} catch (error) {
|
|
235
|
-
Ec.error(`❌ 执行过程中发生错误: ${error.message}`);
|
|
236
|
-
process.exit(1);
|
|
237
|
-
}
|
|
238
|
-
};
|