coda-cli 1.0.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/LICENSE.md +9 -0
- package/README.md +76 -0
- package/package.json +45 -0
- package/src/bin/index.js +4 -0
- package/src/bin/index.ts +2 -0
- package/src/cli-api/cmd.js +86 -0
- package/src/cli-api/cmd.ts +104 -0
- package/src/cli-api/data.js +135 -0
- package/src/cli-api/data.ts +146 -0
- package/src/cli-api/date.js +23 -0
- package/src/cli-api/date.ts +22 -0
- package/src/cli-api/event.js +6 -0
- package/src/cli-api/event.ts +6 -0
- package/src/cli-api/fs.js +236 -0
- package/src/cli-api/fs.ts +213 -0
- package/src/cli-api/git.js +328 -0
- package/src/cli-api/git.ts +397 -0
- package/src/cli-api/index.js +22 -0
- package/src/cli-api/index.ts +10 -0
- package/src/cli-api/packages.js +69 -0
- package/src/cli-api/packages.ts +73 -0
- package/src/cli-api/request.js +55 -0
- package/src/cli-api/request.ts +67 -0
- package/src/cli-core/cli.js +135 -0
- package/src/cli-core/cli.ts +145 -0
- package/src/cli-core/index.js +51 -0
- package/src/cli-core/index.ts +58 -0
- package/src/cli-core/queue.js +60 -0
- package/src/cli-core/queue.ts +68 -0
- package/src/cli-core/watcher.js +31 -0
- package/src/cli-core/watcher.ts +31 -0
- package/src/config/commands.json +20 -0
- package/src/generator/cmd-create/index.js +170 -0
- package/src/generator/cmd-create/index.ts +164 -0
- package/src/generator/cmd-create/tmpl/index.js +39 -0
- package/src/generator/cmd-create/tmpl/index.ts +46 -0
- package/src/generator/cmd-delete/index.js +129 -0
- package/src/generator/cmd-delete/index.ts +122 -0
- package/src/generator/startup.js +253 -0
- package/src/generator/startup.ts +225 -0
- package/src/service/lang.js +73 -0
- package/src/service/lang.ts +71 -0
- package/src/service/util.js +120 -0
- package/src/service/util.ts +91 -0
- package/src/types/index.js +2 -0
- package/src/types/index.ts +29 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Git = void 0;
|
|
4
|
+
exports.asyncExecute = asyncExecute;
|
|
5
|
+
exports.getType = getType;
|
|
6
|
+
const child_process_1 = require("child_process");
|
|
7
|
+
/**
|
|
8
|
+
* 异步执行命令
|
|
9
|
+
* @param cmd 命令
|
|
10
|
+
* @param dir 运行命令的目录
|
|
11
|
+
* @returns Promise 对象,包含执行状态与输出结果
|
|
12
|
+
*/
|
|
13
|
+
function asyncExecute(cmd, dir = process.cwd()) {
|
|
14
|
+
const volidateCmdFailed = (status, reason) => {
|
|
15
|
+
if (!status) {
|
|
16
|
+
return {
|
|
17
|
+
status: false,
|
|
18
|
+
data: reason,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
return new Promise(resolve => {
|
|
23
|
+
const cp = (0, child_process_1.spawn)(cmd, {
|
|
24
|
+
cwd: dir,
|
|
25
|
+
stdio: 'pipe',
|
|
26
|
+
shell: true,
|
|
27
|
+
});
|
|
28
|
+
let dataOk = '';
|
|
29
|
+
let dataError = '';
|
|
30
|
+
cp.stdout?.on('data', (data) => {
|
|
31
|
+
dataOk += data.toString().trim();
|
|
32
|
+
});
|
|
33
|
+
cp.stderr?.on('data', (data) => {
|
|
34
|
+
dataError += data.toString().trim();
|
|
35
|
+
});
|
|
36
|
+
cp.on('close', () => {
|
|
37
|
+
let status = true;
|
|
38
|
+
if ((dataOk.length === 0 && dataError.indexOf('error:') > -1) ||
|
|
39
|
+
dataError.indexOf('fatal:') > -1) {
|
|
40
|
+
status = false;
|
|
41
|
+
}
|
|
42
|
+
const data = dataOk.length !== 0 ? dataOk : dataError;
|
|
43
|
+
volidateCmdFailed(status, data);
|
|
44
|
+
resolve({
|
|
45
|
+
status,
|
|
46
|
+
data,
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 获取数据的精确类型
|
|
53
|
+
* @param variable 任意变量
|
|
54
|
+
* @returns 类型字符串
|
|
55
|
+
*/
|
|
56
|
+
function getType(variable) {
|
|
57
|
+
let temp = Object.prototype.toString.call(variable);
|
|
58
|
+
return temp.substring(8, temp.length - 1);
|
|
59
|
+
}
|
|
60
|
+
exports.Git = {
|
|
61
|
+
/**
|
|
62
|
+
* 获取当前 Git 分支
|
|
63
|
+
* @param cwd 运行命令的目录
|
|
64
|
+
*/
|
|
65
|
+
async getCurrentBranch(cwd = process.cwd()) {
|
|
66
|
+
const { data } = await asyncExecute('git rev-parse --abbrev-ref HEAD', cwd);
|
|
67
|
+
return {
|
|
68
|
+
status: true,
|
|
69
|
+
data,
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
/**
|
|
73
|
+
* 获取当前的 Git 标签
|
|
74
|
+
* @param cwd 运行命令的目录
|
|
75
|
+
*/
|
|
76
|
+
async getCurrentTag(cwd = process.cwd()) {
|
|
77
|
+
const { data, status } = await asyncExecute('git describe --tags', cwd);
|
|
78
|
+
return {
|
|
79
|
+
status,
|
|
80
|
+
data,
|
|
81
|
+
};
|
|
82
|
+
},
|
|
83
|
+
/**
|
|
84
|
+
* 获取最近一次的提交记录
|
|
85
|
+
* @param cwd 运行命令的目录
|
|
86
|
+
*/
|
|
87
|
+
async getLatestCommit(cwd = process.cwd()) {
|
|
88
|
+
const cmd = `git log -1 --pretty=format:'{
|
|
89
|
+
"hash": "%H",
|
|
90
|
+
"author": "%an",
|
|
91
|
+
"email": "%ae",
|
|
92
|
+
"date": "%ad",
|
|
93
|
+
"message": "%s"
|
|
94
|
+
}'`;
|
|
95
|
+
const { data, status } = await asyncExecute(cmd, cwd);
|
|
96
|
+
return {
|
|
97
|
+
status,
|
|
98
|
+
data: JSON.parse(data),
|
|
99
|
+
};
|
|
100
|
+
},
|
|
101
|
+
/**
|
|
102
|
+
* 为当前项目通过 CLI 初始化 Git 用户信息
|
|
103
|
+
* @param name Git 用户名
|
|
104
|
+
* @param email Git 用户邮箱
|
|
105
|
+
* @returns 本地 Git 用户账户信息对象
|
|
106
|
+
*/
|
|
107
|
+
async initLocalUser(name, email) {
|
|
108
|
+
let setName = `git config --local user.name "${name}"`;
|
|
109
|
+
let setEmail = `git config --local user.email "${email}"`;
|
|
110
|
+
await asyncExecute(setName);
|
|
111
|
+
await asyncExecute(setEmail);
|
|
112
|
+
const { data } = await asyncExecute('git config --local --list');
|
|
113
|
+
let rows = data.split('\n');
|
|
114
|
+
let local = {};
|
|
115
|
+
rows.forEach(row => {
|
|
116
|
+
let temp = row.split('=');
|
|
117
|
+
if (temp.length >= 2) {
|
|
118
|
+
local[temp[0]] = temp[1];
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
return local;
|
|
122
|
+
},
|
|
123
|
+
/**
|
|
124
|
+
* 获取所有的 Git 分支以及当前分支
|
|
125
|
+
* @param cwd 运行命令的目录
|
|
126
|
+
* @returns 所有分支及当前分支的对象
|
|
127
|
+
*/
|
|
128
|
+
async getBranchs(cwd = process.cwd()) {
|
|
129
|
+
const cmd = 'git branch';
|
|
130
|
+
let { data } = await asyncExecute(cmd, cwd);
|
|
131
|
+
let branchs = data.split('\n');
|
|
132
|
+
let current = branchs.find(branch => branch.indexOf('*') > -1) || '';
|
|
133
|
+
return {
|
|
134
|
+
current,
|
|
135
|
+
branchs,
|
|
136
|
+
};
|
|
137
|
+
},
|
|
138
|
+
/**
|
|
139
|
+
* 切换 Git 分支
|
|
140
|
+
* @param cwd 运行命令的目录
|
|
141
|
+
* @param branch 分支名称
|
|
142
|
+
*/
|
|
143
|
+
async checkout(cwd = process.cwd(), branch) {
|
|
144
|
+
const cmd = `git checkout ${branch}`;
|
|
145
|
+
const expect1 = `Your branch is up to date with 'origin/${branch}'.`;
|
|
146
|
+
const expect2 = `Your branch is ahead of 'origin/${branch}'`;
|
|
147
|
+
const expect3 = `Switched to a new branch '${branch}'`;
|
|
148
|
+
const { data } = await asyncExecute(cmd, cwd);
|
|
149
|
+
let realStatus = false;
|
|
150
|
+
if (data.indexOf(expect1) >= 0 || data.indexOf(expect2) >= 0 || data.indexOf(expect3) >= 0) {
|
|
151
|
+
realStatus = true;
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
status: realStatus,
|
|
155
|
+
data,
|
|
156
|
+
};
|
|
157
|
+
},
|
|
158
|
+
/**
|
|
159
|
+
* 获取当前分支的状态
|
|
160
|
+
* @param cwd 运行命令的目录
|
|
161
|
+
* @returns 当前分支状态的字符串内容
|
|
162
|
+
*/
|
|
163
|
+
async status(cwd = process.cwd()) {
|
|
164
|
+
let cmd = 'git status';
|
|
165
|
+
const { data } = await asyncExecute(cmd, cwd);
|
|
166
|
+
let status = true;
|
|
167
|
+
if (data.indexOf('use "git add" and/or "git commit -a"') > -1) {
|
|
168
|
+
status = false;
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
status,
|
|
172
|
+
data,
|
|
173
|
+
};
|
|
174
|
+
},
|
|
175
|
+
/**
|
|
176
|
+
* 在当前分支提交所有更改
|
|
177
|
+
* @param cwd 运行命令的目录
|
|
178
|
+
* @param msg 提交说明信息
|
|
179
|
+
* @returns 提交分支状态的布尔值
|
|
180
|
+
*/
|
|
181
|
+
async commit(cwd = process.cwd(), msg) {
|
|
182
|
+
const comitCmd = `git commit -m "${msg}"`;
|
|
183
|
+
const expect1 = 'use "git push"';
|
|
184
|
+
const expect2 = 'nothing to commit';
|
|
185
|
+
const expect3 = 'changed';
|
|
186
|
+
const expect4 = 'insertions';
|
|
187
|
+
const expect5 = 'deletions';
|
|
188
|
+
await asyncExecute('git add .', cwd);
|
|
189
|
+
const { data } = await asyncExecute(comitCmd, cwd);
|
|
190
|
+
let realStatus = false;
|
|
191
|
+
if (data.indexOf(expect1) >= 0 ||
|
|
192
|
+
data.indexOf(expect2) >= 0 ||
|
|
193
|
+
data.indexOf(expect3) >= 0 ||
|
|
194
|
+
data.indexOf(expect4) >= 0 ||
|
|
195
|
+
data.indexOf(expect5) >= 0) {
|
|
196
|
+
realStatus = true;
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
status: realStatus,
|
|
200
|
+
data,
|
|
201
|
+
};
|
|
202
|
+
},
|
|
203
|
+
/**
|
|
204
|
+
* 拉取分支代码
|
|
205
|
+
* @param cwd 运行命令的目录
|
|
206
|
+
*/
|
|
207
|
+
async pull(cwd = process.cwd()) {
|
|
208
|
+
const cmd = 'git pull';
|
|
209
|
+
const expect1 = 'Already up to date.';
|
|
210
|
+
let current = await exports.Git.status(cwd);
|
|
211
|
+
if (!current.status) {
|
|
212
|
+
return {
|
|
213
|
+
status: current.status,
|
|
214
|
+
data: current.data,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
const { data } = await asyncExecute(cmd, cwd);
|
|
218
|
+
let realStatus = data.indexOf(expect1) >= 0 ? true : false;
|
|
219
|
+
return {
|
|
220
|
+
status: realStatus,
|
|
221
|
+
data,
|
|
222
|
+
};
|
|
223
|
+
},
|
|
224
|
+
/**
|
|
225
|
+
* 推送分支代码
|
|
226
|
+
* @param cwd 运行命令的目录
|
|
227
|
+
* @param isFource 是否强制推送
|
|
228
|
+
*/
|
|
229
|
+
async push(cwd = process.cwd(), isFource = false) {
|
|
230
|
+
let cmd = 'git push';
|
|
231
|
+
if (isFource)
|
|
232
|
+
cmd = 'git push -f';
|
|
233
|
+
let current = await exports.Git.status(cwd);
|
|
234
|
+
if (!current.status) {
|
|
235
|
+
return {
|
|
236
|
+
status: current.status,
|
|
237
|
+
data: current.data,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
const { status, data } = await asyncExecute(cmd, cwd);
|
|
241
|
+
return {
|
|
242
|
+
status,
|
|
243
|
+
data,
|
|
244
|
+
};
|
|
245
|
+
},
|
|
246
|
+
/**
|
|
247
|
+
* 合并分支
|
|
248
|
+
* @param cwd 运行命令的目录
|
|
249
|
+
* @param branch 要合并的分支名
|
|
250
|
+
*/
|
|
251
|
+
async merge(cwd = process.cwd(), branch) {
|
|
252
|
+
const cmd = `git merge ${branch}`;
|
|
253
|
+
const expect1 = `Merge made by the 'recursive' strategy`;
|
|
254
|
+
const expect2 = `Already up to date`;
|
|
255
|
+
const expect3 = `not something we can merge`;
|
|
256
|
+
let current = await exports.Git.status(cwd);
|
|
257
|
+
if (!current.status) {
|
|
258
|
+
return {
|
|
259
|
+
status: current.status,
|
|
260
|
+
data: current.data,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
const { data } = await asyncExecute(cmd, cwd);
|
|
264
|
+
let realStatus = false;
|
|
265
|
+
if (data.indexOf(expect1) >= 0 || data.indexOf(expect2) >= 0 || data.indexOf(expect3) >= 0) {
|
|
266
|
+
realStatus = true;
|
|
267
|
+
}
|
|
268
|
+
return {
|
|
269
|
+
status: realStatus,
|
|
270
|
+
data,
|
|
271
|
+
};
|
|
272
|
+
},
|
|
273
|
+
/**
|
|
274
|
+
* 更新子模块
|
|
275
|
+
* @param cwd 运行命令的目录
|
|
276
|
+
*/
|
|
277
|
+
async updateSubmodule(cwd = process.cwd()) {
|
|
278
|
+
const cmd = 'git submodule update --remote';
|
|
279
|
+
const { data, status } = await asyncExecute(cmd, cwd);
|
|
280
|
+
return {
|
|
281
|
+
status: status,
|
|
282
|
+
data: data,
|
|
283
|
+
};
|
|
284
|
+
},
|
|
285
|
+
/**
|
|
286
|
+
* 获取远程分支
|
|
287
|
+
* @param cwd 运行命令的目录
|
|
288
|
+
* @param branch 分支名称
|
|
289
|
+
*/
|
|
290
|
+
async fetchOrigin(cwd = process.cwd(), branch) {
|
|
291
|
+
const cmd = 'git fetch origin' + ' ' + branch;
|
|
292
|
+
const { status, data } = await asyncExecute(cmd, cwd);
|
|
293
|
+
return {
|
|
294
|
+
status,
|
|
295
|
+
data,
|
|
296
|
+
};
|
|
297
|
+
},
|
|
298
|
+
/**
|
|
299
|
+
* 变基操作
|
|
300
|
+
* @param cwd 运行命令的目录
|
|
301
|
+
* @param branch 分支名称
|
|
302
|
+
*/
|
|
303
|
+
async rebaese(cwd = process.cwd(), branch) {
|
|
304
|
+
const cmd = 'git rebase origin/' + branch;
|
|
305
|
+
const { status, data } = await asyncExecute(cmd, cwd);
|
|
306
|
+
return {
|
|
307
|
+
status,
|
|
308
|
+
data,
|
|
309
|
+
};
|
|
310
|
+
},
|
|
311
|
+
/**
|
|
312
|
+
* 删除分支
|
|
313
|
+
* @param cwd 运行命令的目录
|
|
314
|
+
* @param branch 分支名称
|
|
315
|
+
*/
|
|
316
|
+
async deleteBranch(cwd = process.cwd(), branch) {
|
|
317
|
+
const cmd = `git branch -D ${branch}`;
|
|
318
|
+
const { data } = await asyncExecute(cmd, cwd);
|
|
319
|
+
return {
|
|
320
|
+
status: true,
|
|
321
|
+
data: data,
|
|
322
|
+
};
|
|
323
|
+
},
|
|
324
|
+
};
|
|
325
|
+
exports.default = {
|
|
326
|
+
Git: exports.Git,
|
|
327
|
+
asyncExecute,
|
|
328
|
+
};
|
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
import {spawn} from 'child_process';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 命令执行结果接口
|
|
5
|
+
*/
|
|
6
|
+
export interface ExecResult {
|
|
7
|
+
status: boolean;
|
|
8
|
+
data: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 最新提交记录接口
|
|
13
|
+
*/
|
|
14
|
+
export interface CommitInfo {
|
|
15
|
+
hash: string;
|
|
16
|
+
author: string;
|
|
17
|
+
email: string;
|
|
18
|
+
date: string;
|
|
19
|
+
message: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 分支信息接口
|
|
24
|
+
*/
|
|
25
|
+
export interface BranchsResult {
|
|
26
|
+
current: string;
|
|
27
|
+
branchs: string[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 异步执行命令
|
|
32
|
+
* @param cmd 命令
|
|
33
|
+
* @param dir 运行命令的目录
|
|
34
|
+
* @returns Promise 对象,包含执行状态与输出结果
|
|
35
|
+
*/
|
|
36
|
+
export function asyncExecute(cmd: string, dir: string = process.cwd()): Promise<ExecResult> {
|
|
37
|
+
const volidateCmdFailed = (status: boolean, reason: string): ExecResult | undefined => {
|
|
38
|
+
if (!status) {
|
|
39
|
+
return {
|
|
40
|
+
status: false,
|
|
41
|
+
data: reason,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
return new Promise(resolve => {
|
|
47
|
+
const cp = spawn(cmd, {
|
|
48
|
+
cwd: dir,
|
|
49
|
+
stdio: 'pipe',
|
|
50
|
+
shell: true,
|
|
51
|
+
});
|
|
52
|
+
let dataOk = '';
|
|
53
|
+
let dataError = '';
|
|
54
|
+
|
|
55
|
+
cp.stdout?.on('data', (data: Buffer) => {
|
|
56
|
+
dataOk += data.toString().trim();
|
|
57
|
+
});
|
|
58
|
+
cp.stderr?.on('data', (data: Buffer) => {
|
|
59
|
+
dataError += data.toString().trim();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
cp.on('close', () => {
|
|
63
|
+
let status = true;
|
|
64
|
+
if (
|
|
65
|
+
(dataOk.length === 0 && dataError.indexOf('error:') > -1) ||
|
|
66
|
+
dataError.indexOf('fatal:') > -1
|
|
67
|
+
) {
|
|
68
|
+
status = false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const data = dataOk.length !== 0 ? dataOk : dataError;
|
|
72
|
+
volidateCmdFailed(status, data);
|
|
73
|
+
|
|
74
|
+
resolve({
|
|
75
|
+
status,
|
|
76
|
+
data,
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 获取数据的精确类型
|
|
84
|
+
* @param variable 任意变量
|
|
85
|
+
* @returns 类型字符串
|
|
86
|
+
*/
|
|
87
|
+
export function getType(variable: unknown): string {
|
|
88
|
+
let temp = Object.prototype.toString.call(variable);
|
|
89
|
+
return temp.substring(8, temp.length - 1);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export const Git = {
|
|
93
|
+
/**
|
|
94
|
+
* 获取当前 Git 分支
|
|
95
|
+
* @param cwd 运行命令的目录
|
|
96
|
+
*/
|
|
97
|
+
async getCurrentBranch(cwd: string = process.cwd()): Promise<ExecResult> {
|
|
98
|
+
const {data} = await asyncExecute('git rev-parse --abbrev-ref HEAD', cwd);
|
|
99
|
+
return {
|
|
100
|
+
status: true,
|
|
101
|
+
data,
|
|
102
|
+
};
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* 获取当前的 Git 标签
|
|
107
|
+
* @param cwd 运行命令的目录
|
|
108
|
+
*/
|
|
109
|
+
async getCurrentTag(cwd: string = process.cwd()): Promise<ExecResult> {
|
|
110
|
+
const {data, status} = await asyncExecute('git describe --tags', cwd);
|
|
111
|
+
return {
|
|
112
|
+
status,
|
|
113
|
+
data,
|
|
114
|
+
};
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* 获取最近一次的提交记录
|
|
119
|
+
* @param cwd 运行命令的目录
|
|
120
|
+
*/
|
|
121
|
+
async getLatestCommit(cwd: string = process.cwd()): Promise<{status: boolean; data: CommitInfo}> {
|
|
122
|
+
const cmd = `git log -1 --pretty=format:'{
|
|
123
|
+
"hash": "%H",
|
|
124
|
+
"author": "%an",
|
|
125
|
+
"email": "%ae",
|
|
126
|
+
"date": "%ad",
|
|
127
|
+
"message": "%s"
|
|
128
|
+
}'`;
|
|
129
|
+
const {data, status} = await asyncExecute(cmd, cwd);
|
|
130
|
+
return {
|
|
131
|
+
status,
|
|
132
|
+
data: JSON.parse(data),
|
|
133
|
+
};
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* 为当前项目通过 CLI 初始化 Git 用户信息
|
|
138
|
+
* @param name Git 用户名
|
|
139
|
+
* @param email Git 用户邮箱
|
|
140
|
+
* @returns 本地 Git 用户账户信息对象
|
|
141
|
+
*/
|
|
142
|
+
async initLocalUser(name: string, email: string): Promise<Record<string, string>> {
|
|
143
|
+
let setName = `git config --local user.name "${name}"`;
|
|
144
|
+
let setEmail = `git config --local user.email "${email}"`;
|
|
145
|
+
await asyncExecute(setName);
|
|
146
|
+
await asyncExecute(setEmail);
|
|
147
|
+
|
|
148
|
+
const {data} = await asyncExecute('git config --local --list');
|
|
149
|
+
let rows = data.split('\n');
|
|
150
|
+
let local: Record<string, string> = {};
|
|
151
|
+
rows.forEach(row => {
|
|
152
|
+
let temp = row.split('=');
|
|
153
|
+
if (temp.length >= 2) {
|
|
154
|
+
local[temp[0]] = temp[1];
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
return local;
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* 获取所有的 Git 分支以及当前分支
|
|
162
|
+
* @param cwd 运行命令的目录
|
|
163
|
+
* @returns 所有分支及当前分支的对象
|
|
164
|
+
*/
|
|
165
|
+
async getBranchs(cwd: string = process.cwd()): Promise<BranchsResult> {
|
|
166
|
+
const cmd = 'git branch';
|
|
167
|
+
let {data} = await asyncExecute(cmd, cwd);
|
|
168
|
+
let branchs = data.split('\n');
|
|
169
|
+
let current = branchs.find(branch => branch.indexOf('*') > -1) || '';
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
current,
|
|
173
|
+
branchs,
|
|
174
|
+
};
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* 切换 Git 分支
|
|
179
|
+
* @param cwd 运行命令的目录
|
|
180
|
+
* @param branch 分支名称
|
|
181
|
+
*/
|
|
182
|
+
async checkout(cwd: string = process.cwd(), branch: string): Promise<ExecResult> {
|
|
183
|
+
const cmd = `git checkout ${branch}`;
|
|
184
|
+
const expect1 = `Your branch is up to date with 'origin/${branch}'.`;
|
|
185
|
+
const expect2 = `Your branch is ahead of 'origin/${branch}'`;
|
|
186
|
+
const expect3 = `Switched to a new branch '${branch}'`;
|
|
187
|
+
const {data} = await asyncExecute(cmd, cwd);
|
|
188
|
+
|
|
189
|
+
let realStatus = false;
|
|
190
|
+
if (data.indexOf(expect1) >= 0 || data.indexOf(expect2) >= 0 || data.indexOf(expect3) >= 0) {
|
|
191
|
+
realStatus = true;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return {
|
|
195
|
+
status: realStatus,
|
|
196
|
+
data,
|
|
197
|
+
};
|
|
198
|
+
},
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* 获取当前分支的状态
|
|
202
|
+
* @param cwd 运行命令的目录
|
|
203
|
+
* @returns 当前分支状态的字符串内容
|
|
204
|
+
*/
|
|
205
|
+
async status(cwd: string = process.cwd()): Promise<ExecResult> {
|
|
206
|
+
let cmd = 'git status';
|
|
207
|
+
const {data} = await asyncExecute(cmd, cwd);
|
|
208
|
+
let status = true;
|
|
209
|
+
|
|
210
|
+
if (data.indexOf('use "git add" and/or "git commit -a"') > -1) {
|
|
211
|
+
status = false;
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
status,
|
|
215
|
+
data,
|
|
216
|
+
};
|
|
217
|
+
},
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* 在当前分支提交所有更改
|
|
221
|
+
* @param cwd 运行命令的目录
|
|
222
|
+
* @param msg 提交说明信息
|
|
223
|
+
* @returns 提交分支状态的布尔值
|
|
224
|
+
*/
|
|
225
|
+
async commit(cwd: string = process.cwd(), msg: string): Promise<ExecResult> {
|
|
226
|
+
const comitCmd = `git commit -m "${msg}"`;
|
|
227
|
+
const expect1 = 'use "git push"';
|
|
228
|
+
const expect2 = 'nothing to commit';
|
|
229
|
+
const expect3 = 'changed';
|
|
230
|
+
const expect4 = 'insertions';
|
|
231
|
+
const expect5 = 'deletions';
|
|
232
|
+
|
|
233
|
+
await asyncExecute('git add .', cwd);
|
|
234
|
+
const {data} = await asyncExecute(comitCmd, cwd);
|
|
235
|
+
|
|
236
|
+
let realStatus = false;
|
|
237
|
+
if (
|
|
238
|
+
data.indexOf(expect1) >= 0 ||
|
|
239
|
+
data.indexOf(expect2) >= 0 ||
|
|
240
|
+
data.indexOf(expect3) >= 0 ||
|
|
241
|
+
data.indexOf(expect4) >= 0 ||
|
|
242
|
+
data.indexOf(expect5) >= 0
|
|
243
|
+
) {
|
|
244
|
+
realStatus = true;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return {
|
|
248
|
+
status: realStatus,
|
|
249
|
+
data,
|
|
250
|
+
};
|
|
251
|
+
},
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* 拉取分支代码
|
|
255
|
+
* @param cwd 运行命令的目录
|
|
256
|
+
*/
|
|
257
|
+
async pull(cwd: string = process.cwd()): Promise<ExecResult> {
|
|
258
|
+
const cmd = 'git pull';
|
|
259
|
+
const expect1 = 'Already up to date.';
|
|
260
|
+
|
|
261
|
+
let current = await Git.status(cwd);
|
|
262
|
+
if (!current.status) {
|
|
263
|
+
return {
|
|
264
|
+
status: current.status,
|
|
265
|
+
data: current.data,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const {data} = await asyncExecute(cmd, cwd);
|
|
270
|
+
let realStatus = data.indexOf(expect1) >= 0 ? true : false;
|
|
271
|
+
|
|
272
|
+
return {
|
|
273
|
+
status: realStatus,
|
|
274
|
+
data,
|
|
275
|
+
};
|
|
276
|
+
},
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* 推送分支代码
|
|
280
|
+
* @param cwd 运行命令的目录
|
|
281
|
+
* @param isFource 是否强制推送
|
|
282
|
+
*/
|
|
283
|
+
async push(cwd: string = process.cwd(), isFource: boolean = false): Promise<ExecResult> {
|
|
284
|
+
let cmd = 'git push';
|
|
285
|
+
|
|
286
|
+
if (isFource) cmd = 'git push -f';
|
|
287
|
+
|
|
288
|
+
let current = await Git.status(cwd);
|
|
289
|
+
if (!current.status) {
|
|
290
|
+
return {
|
|
291
|
+
status: current.status,
|
|
292
|
+
data: current.data,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const {status, data} = await asyncExecute(cmd, cwd);
|
|
297
|
+
|
|
298
|
+
return {
|
|
299
|
+
status,
|
|
300
|
+
data,
|
|
301
|
+
};
|
|
302
|
+
},
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* 合并分支
|
|
306
|
+
* @param cwd 运行命令的目录
|
|
307
|
+
* @param branch 要合并的分支名
|
|
308
|
+
*/
|
|
309
|
+
async merge(cwd: string = process.cwd(), branch: string): Promise<ExecResult> {
|
|
310
|
+
const cmd = `git merge ${branch}`;
|
|
311
|
+
const expect1 = `Merge made by the 'recursive' strategy`;
|
|
312
|
+
const expect2 = `Already up to date`;
|
|
313
|
+
const expect3 = `not something we can merge`;
|
|
314
|
+
|
|
315
|
+
let current = await Git.status(cwd);
|
|
316
|
+
if (!current.status) {
|
|
317
|
+
return {
|
|
318
|
+
status: current.status,
|
|
319
|
+
data: current.data,
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
const {data} = await asyncExecute(cmd, cwd);
|
|
324
|
+
|
|
325
|
+
let realStatus = false;
|
|
326
|
+
if (data.indexOf(expect1) >= 0 || data.indexOf(expect2) >= 0 || data.indexOf(expect3) >= 0) {
|
|
327
|
+
realStatus = true;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return {
|
|
331
|
+
status: realStatus,
|
|
332
|
+
data,
|
|
333
|
+
};
|
|
334
|
+
},
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* 更新子模块
|
|
338
|
+
* @param cwd 运行命令的目录
|
|
339
|
+
*/
|
|
340
|
+
async updateSubmodule(cwd: string = process.cwd()): Promise<ExecResult> {
|
|
341
|
+
const cmd = 'git submodule update --remote';
|
|
342
|
+
const {data, status} = await asyncExecute(cmd, cwd);
|
|
343
|
+
|
|
344
|
+
return {
|
|
345
|
+
status: status,
|
|
346
|
+
data: data,
|
|
347
|
+
};
|
|
348
|
+
},
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* 获取远程分支
|
|
352
|
+
* @param cwd 运行命令的目录
|
|
353
|
+
* @param branch 分支名称
|
|
354
|
+
*/
|
|
355
|
+
async fetchOrigin(cwd: string = process.cwd(), branch: string): Promise<ExecResult> {
|
|
356
|
+
const cmd = 'git fetch origin' + ' ' + branch;
|
|
357
|
+
const {status, data} = await asyncExecute(cmd, cwd);
|
|
358
|
+
return {
|
|
359
|
+
status,
|
|
360
|
+
data,
|
|
361
|
+
};
|
|
362
|
+
},
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* 变基操作
|
|
366
|
+
* @param cwd 运行命令的目录
|
|
367
|
+
* @param branch 分支名称
|
|
368
|
+
*/
|
|
369
|
+
async rebaese(cwd: string = process.cwd(), branch: string): Promise<ExecResult> {
|
|
370
|
+
const cmd = 'git rebase origin/' + branch;
|
|
371
|
+
const {status, data} = await asyncExecute(cmd, cwd);
|
|
372
|
+
|
|
373
|
+
return {
|
|
374
|
+
status,
|
|
375
|
+
data,
|
|
376
|
+
};
|
|
377
|
+
},
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* 删除分支
|
|
381
|
+
* @param cwd 运行命令的目录
|
|
382
|
+
* @param branch 分支名称
|
|
383
|
+
*/
|
|
384
|
+
async deleteBranch(cwd: string = process.cwd(), branch: string): Promise<ExecResult> {
|
|
385
|
+
const cmd = `git branch -D ${branch}`;
|
|
386
|
+
const {data} = await asyncExecute(cmd, cwd);
|
|
387
|
+
return {
|
|
388
|
+
status: true,
|
|
389
|
+
data: data,
|
|
390
|
+
};
|
|
391
|
+
},
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
export default {
|
|
395
|
+
Git,
|
|
396
|
+
asyncExecute,
|
|
397
|
+
};
|