zen-gitsync 2.12.2 → 2.12.4
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 +190 -21
- package/index.js +25 -11
- package/package.json +18 -5
- package/scripts/convert-colors-to-vars.cjs +286 -272
- package/scripts/convert-fontsize-to-vars.cjs +221 -207
- package/scripts/convert-spacing-to-vars.cjs +256 -242
- package/scripts/convert-to-standard-vars.cjs +282 -268
- package/scripts/release.js +599 -585
- package/src/config.js +350 -336
- package/src/gitCommit.js +455 -440
- package/src/ui/public/assets/{EditorView-bnJmBq-i.js → EditorView-BZaOzahT.js} +2 -2
- package/src/ui/public/assets/EditorView-CbqSI9nw.css +1 -0
- package/src/ui/public/assets/{SourceMapView-Rz5SD0A0.js → SourceMapView-D_8mnVt2.js} +3 -3
- package/src/ui/public/assets/SourceMapView-DyMK80hS.css +1 -0
- package/src/ui/public/assets/{index-Bo3tntQh.js → index-BgFwmXzV.js} +11 -11
- package/src/ui/public/assets/{index-bOs5P8fz.css → index-Dsi6tg7k.css} +1 -1
- package/src/ui/public/index.html +2 -2
- package/src/ui/server/index.js +410 -396
- package/src/ui/server/middleware/requestLogger.js +51 -37
- package/src/ui/server/routes/branchStatus.js +101 -87
- package/src/ui/server/routes/code.js +110 -96
- package/src/ui/server/routes/codeAnalysis.js +995 -981
- package/src/ui/server/routes/config.js +1190 -1158
- package/src/ui/server/routes/exec.js +272 -258
- package/src/ui/server/routes/fileOpen.js +279 -265
- package/src/ui/server/routes/fs.js +701 -687
- package/src/ui/server/routes/git/diff.js +352 -338
- package/src/ui/server/routes/git/diffUtils.js +128 -114
- package/src/ui/server/routes/git/stash.js +552 -538
- package/src/ui/server/routes/git/tags.js +172 -158
- package/src/ui/server/routes/git.js +190 -176
- package/src/ui/server/routes/gitOps.js +1179 -1165
- package/src/ui/server/routes/instances.js +14 -0
- package/src/ui/server/routes/npm.js +1023 -1009
- package/src/ui/server/routes/process.js +82 -68
- package/src/ui/server/routes/status.js +67 -53
- package/src/ui/server/routes/terminal.js +319 -305
- package/src/ui/server/socket/registerUiSocketHandlers.js +226 -212
- package/src/ui/server/utils/createSavePortToFile.js +46 -32
- package/src/ui/server/utils/instanceRegistry.js +14 -0
- package/src/ui/server/utils/pathGuard.js +14 -0
- package/src/ui/server/utils/pathGuard.test.js +14 -0
- package/src/ui/server/utils/randomStartPort.js +14 -0
- package/src/ui/server/utils/startServerOnAvailablePort.js +101 -87
- package/src/utils/index.js +14 -0
- package/src/ui/public/assets/EditorView-CHBjgiZc.css +0 -1
- package/src/ui/public/assets/SourceMapView-DhQX0K7t.css +0 -1
package/src/gitCommit.js
CHANGED
|
@@ -1,440 +1,455 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
//
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
//
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
//
|
|
398
|
-
//
|
|
399
|
-
//
|
|
400
|
-
//
|
|
401
|
-
// //
|
|
402
|
-
// //
|
|
403
|
-
// //
|
|
404
|
-
// //
|
|
405
|
-
// //
|
|
406
|
-
// //
|
|
407
|
-
//
|
|
408
|
-
//
|
|
409
|
-
// //
|
|
410
|
-
// //
|
|
411
|
-
// //
|
|
412
|
-
// // timer
|
|
413
|
-
// //
|
|
414
|
-
// //
|
|
415
|
-
// //
|
|
416
|
-
//
|
|
417
|
-
//
|
|
418
|
-
//
|
|
419
|
-
//
|
|
420
|
-
//
|
|
421
|
-
//
|
|
422
|
-
//
|
|
423
|
-
//
|
|
424
|
-
//
|
|
425
|
-
//
|
|
426
|
-
//
|
|
427
|
-
//
|
|
428
|
-
//
|
|
429
|
-
// };
|
|
430
|
-
//
|
|
431
|
-
//
|
|
432
|
-
//
|
|
433
|
-
//
|
|
434
|
-
//
|
|
435
|
-
//
|
|
436
|
-
//
|
|
437
|
-
//
|
|
438
|
-
//
|
|
439
|
-
|
|
440
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Copyright 2026 xz333221
|
|
3
|
+
//
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// you may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
//
|
|
8
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
//
|
|
10
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
// See the License for the specific language governing permissions and
|
|
14
|
+
// limitations under the License.
|
|
15
|
+
//
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
coloredLog, errorLog, execGitCommand, showHelp,
|
|
19
|
+
getCwd, judgePlatform, judgeLog, judgeHelp, exec_exit, judgeUnmerged, formatDuration,
|
|
20
|
+
exec_push, execPull, judgeRemote, execDiff, execAddAndCommit, delay, addScriptToPackageJson, addResetScriptToPackageJson
|
|
21
|
+
} from './utils/index.js';
|
|
22
|
+
import readline from 'readline'
|
|
23
|
+
import ora from 'ora';
|
|
24
|
+
import chalk from 'chalk';
|
|
25
|
+
import boxen from 'boxen';
|
|
26
|
+
import config from './config.js';
|
|
27
|
+
import { format as dateFormat } from 'date-fns/format';
|
|
28
|
+
import logUpdate from 'log-update';
|
|
29
|
+
import startUIServer from './ui/server/index.js';
|
|
30
|
+
import { exec } from 'child_process';
|
|
31
|
+
|
|
32
|
+
let countdownInterval = null;
|
|
33
|
+
|
|
34
|
+
function startCountdown(interval) {
|
|
35
|
+
let remaining = interval;
|
|
36
|
+
|
|
37
|
+
// 清除旧的倒计时
|
|
38
|
+
if (countdownInterval) {
|
|
39
|
+
clearInterval(countdownInterval);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const render = () => {
|
|
43
|
+
const nextTime = Date.now() + remaining;
|
|
44
|
+
const formattedTime = dateFormat(nextTime, 'yyyy-MM-dd HH:mm:ss');
|
|
45
|
+
const duration = formatDuration(remaining);
|
|
46
|
+
|
|
47
|
+
const message = [
|
|
48
|
+
`🕒 ${chalk.green.bold('倒计时')}`,
|
|
49
|
+
`工作目录: ${chalk.green(getCwd())}`,
|
|
50
|
+
`下次提交: ${chalk.blue(formattedTime)}`,
|
|
51
|
+
`剩余时间: ${chalk.yellow(duration)}`,
|
|
52
|
+
chalk.dim('按 Ctrl+C 终止进程')
|
|
53
|
+
].join('\n');
|
|
54
|
+
|
|
55
|
+
const box = boxen(message, {
|
|
56
|
+
padding: 1,
|
|
57
|
+
margin: 1,
|
|
58
|
+
borderColor: 'cyan',
|
|
59
|
+
borderStyle: 'round'
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
setTimeout(() => {
|
|
63
|
+
logUpdate(box);
|
|
64
|
+
}, 200);
|
|
65
|
+
// logUpdate(box);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// 立即渲染一次
|
|
69
|
+
render();
|
|
70
|
+
|
|
71
|
+
// 每秒更新
|
|
72
|
+
countdownInterval = setInterval(() => {
|
|
73
|
+
remaining -= 1000;
|
|
74
|
+
|
|
75
|
+
if (remaining <= 0) {
|
|
76
|
+
clearInterval(countdownInterval);
|
|
77
|
+
logUpdate.clear();
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
render();
|
|
82
|
+
}, 1000);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const {loadConfig, saveConfig, handleConfigCommands} = config;
|
|
86
|
+
const {defaultCommitMessage} = config
|
|
87
|
+
|
|
88
|
+
let timer = null
|
|
89
|
+
|
|
90
|
+
async function createGitCommit(options) {
|
|
91
|
+
// console.log(`自动提交流程开始=====================>`)
|
|
92
|
+
try {
|
|
93
|
+
let statusOutput = null
|
|
94
|
+
let exit = options ? !!options.exit : true
|
|
95
|
+
const config = await loadConfig()
|
|
96
|
+
let commitMessage = config.defaultCommitMessage
|
|
97
|
+
let {stdout} = await execGitCommand('git status')
|
|
98
|
+
statusOutput = stdout
|
|
99
|
+
judgeUnmerged(statusOutput)
|
|
100
|
+
// 先检查本地是否有未提交的更改
|
|
101
|
+
const hasLocalChanges = !statusOutput.includes('nothing to commit, working tree clean');
|
|
102
|
+
if (hasLocalChanges) {
|
|
103
|
+
// 检查是否有 --no-diff 参数
|
|
104
|
+
await execDiff()
|
|
105
|
+
// 获取实际使用的提交信息(可能是用户交互输入的)
|
|
106
|
+
commitMessage = await execAddAndCommit({statusOutput, commitMessage, exit})
|
|
107
|
+
statusOutput.includes('use "git pull') && await execPull()
|
|
108
|
+
|
|
109
|
+
// 检查是否有远程更新
|
|
110
|
+
await judgeRemote() // 等待 judgeRemote 完成
|
|
111
|
+
|
|
112
|
+
await exec_push({exit, commitMessage})
|
|
113
|
+
} else {
|
|
114
|
+
if (statusOutput.includes('use "git push')) {
|
|
115
|
+
// 获取最近一次提交的实际信息
|
|
116
|
+
const lastCommitResult = await execGitCommand('git log -1 --pretty=%B', {log: false});
|
|
117
|
+
const actualCommitMessage = lastCommitResult.stdout.trim();
|
|
118
|
+
await exec_push({exit, commitMessage: actualCommitMessage || commitMessage})
|
|
119
|
+
} else if (statusOutput.includes('use "git pull')) {
|
|
120
|
+
await execPull()
|
|
121
|
+
} else {
|
|
122
|
+
await judgeRemote() // 等待 judgeRemote 完成
|
|
123
|
+
exec_exit(exit);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
} catch (e) {
|
|
127
|
+
console.error(chalk.red.bold('提交流程错误:'));
|
|
128
|
+
console.error(chalk.dim(e.stack)); // 打印完整错误堆栈
|
|
129
|
+
throw e; // 继续向上抛出错误
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// 处理文件锁定相关命令
|
|
133
|
+
async function handleFileLockCommands() {
|
|
134
|
+
// 锁定文件命令
|
|
135
|
+
const lockFileArg = process.argv.find(arg => arg.startsWith('--lock-file='));
|
|
136
|
+
if (lockFileArg) {
|
|
137
|
+
const filePath = lockFileArg.split('=')[1];
|
|
138
|
+
if (filePath) {
|
|
139
|
+
await config.lockFile(filePath);
|
|
140
|
+
} else {
|
|
141
|
+
console.log(chalk.red('❌ 请指定要锁定的文件路径'));
|
|
142
|
+
}
|
|
143
|
+
process.exit();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// 解锁文件命令
|
|
147
|
+
const unlockFileArg = process.argv.find(arg => arg.startsWith('--unlock-file='));
|
|
148
|
+
if (unlockFileArg) {
|
|
149
|
+
const filePath = unlockFileArg.split('=')[1];
|
|
150
|
+
if (filePath) {
|
|
151
|
+
await config.unlockFile(filePath);
|
|
152
|
+
} else {
|
|
153
|
+
console.log(chalk.red('❌ 请指定要解锁的文件路径'));
|
|
154
|
+
}
|
|
155
|
+
process.exit();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// 列出锁定文件命令
|
|
159
|
+
if (process.argv.includes('--list-locked')) {
|
|
160
|
+
await config.listLockedFiles();
|
|
161
|
+
process.exit();
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// 检查文件是否锁定命令
|
|
165
|
+
const checkLockArg = process.argv.find(arg => arg.startsWith('--check-lock='));
|
|
166
|
+
if (checkLockArg) {
|
|
167
|
+
const filePath = checkLockArg.split('=')[1];
|
|
168
|
+
if (filePath) {
|
|
169
|
+
const isLocked = await config.isFileLocked(filePath);
|
|
170
|
+
if (isLocked) {
|
|
171
|
+
console.log(chalk.yellow(`🔒 文件已锁定: ${filePath}`));
|
|
172
|
+
} else {
|
|
173
|
+
console.log(chalk.green(`🔓 文件未锁定: ${filePath}`));
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
console.log(chalk.red('❌ 请指定要检查的文件路径'));
|
|
177
|
+
}
|
|
178
|
+
process.exit();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async function main() {
|
|
183
|
+
judgePlatform()
|
|
184
|
+
|
|
185
|
+
// 检查是否是UI命令
|
|
186
|
+
if (process.argv.includes('ui')) {
|
|
187
|
+
await startUIServer(false, false); // 传入noOpen=false, savePort=false
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// 检查是否是添加脚本命令
|
|
192
|
+
if (process.argv.includes('addScript')) {
|
|
193
|
+
await addScriptToPackageJson();
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// 检查是否是添加重置脚本命令
|
|
198
|
+
if (process.argv.includes('addResetScript')) {
|
|
199
|
+
await addResetScriptToPackageJson();
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// 检查是否有 log 参数
|
|
204
|
+
judgeLog()
|
|
205
|
+
|
|
206
|
+
// 检查帮助参数
|
|
207
|
+
judgeHelp()
|
|
208
|
+
|
|
209
|
+
await handleConfigCommands();
|
|
210
|
+
|
|
211
|
+
// ========== 文件锁定功能 ==========
|
|
212
|
+
await handleFileLockCommands();
|
|
213
|
+
|
|
214
|
+
// ========== 新增:自定义cmd定时/定点执行功能 ==========
|
|
215
|
+
const cmdArg = process.argv.find(arg => arg.startsWith('--cmd='));
|
|
216
|
+
if (cmdArg) {
|
|
217
|
+
// 使用正则表达式提取参数值,确保等号不会截断命令内容
|
|
218
|
+
const cmdMatch = cmdArg.match(/^--cmd=(['"]?)(.*)\1$/);
|
|
219
|
+
let cmd = cmdMatch ? cmdMatch[2] : '';
|
|
220
|
+
cmd = cmd.replace(/%%/g, '%'); // 关键修复
|
|
221
|
+
|
|
222
|
+
const atArg = process.argv.find(arg => arg.startsWith('--at='));
|
|
223
|
+
const intervalArg = process.argv.find(arg => arg.startsWith('--cmd-interval='));
|
|
224
|
+
|
|
225
|
+
if (atArg) {
|
|
226
|
+
const atMatch = atArg.match(/^--at=(['"]?)(.*)\1$/);
|
|
227
|
+
const atTime = atMatch ? atMatch[2] : '';
|
|
228
|
+
const repeatDaily = process.argv.includes('--daily') || process.argv.includes('--repeat=daily') || process.argv.includes('--at-repeat=daily');
|
|
229
|
+
|
|
230
|
+
const runOnce = () => {
|
|
231
|
+
console.log(`\n[自定义命令执行] ${new Date().toLocaleString()}\n> ${cmd}`);
|
|
232
|
+
exec(cmd, (err, stdout, stderr) => {
|
|
233
|
+
if (err) {
|
|
234
|
+
console.error(`[自定义命令错误]`, err.message);
|
|
235
|
+
}
|
|
236
|
+
if (stdout) console.log(`[自定义命令输出]\n${stdout}`);
|
|
237
|
+
if (stderr) console.error(`[自定义命令错误输出]\n${stderr}`);
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
const getNextTarget = (now) => {
|
|
242
|
+
if (/^\d{2}:\d{2}$/.test(atTime)) {
|
|
243
|
+
const [h, m] = atTime.split(':').map((v) => parseInt(v, 10));
|
|
244
|
+
if (!Number.isFinite(h) || !Number.isFinite(m)) return null;
|
|
245
|
+
const base = new Date(now.getFullYear(), now.getMonth(), now.getDate(), h, m, 0, 0);
|
|
246
|
+
if (base.getTime() > now.getTime()) return base;
|
|
247
|
+
return new Date(base.getTime() + 24 * 60 * 60 * 1000);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const parsed = new Date(atTime);
|
|
251
|
+
if (!Number.isFinite(parsed.getTime())) return null;
|
|
252
|
+
|
|
253
|
+
if (!repeatDaily) return parsed;
|
|
254
|
+
|
|
255
|
+
const base = new Date(now.getFullYear(), now.getMonth(), now.getDate(), parsed.getHours(), parsed.getMinutes(), parsed.getSeconds(), 0);
|
|
256
|
+
if (base.getTime() > now.getTime()) return base;
|
|
257
|
+
return new Date(base.getTime() + 24 * 60 * 60 * 1000);
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
let atTimer = null;
|
|
261
|
+
const scheduleNext = () => {
|
|
262
|
+
const now = new Date();
|
|
263
|
+
const target = getNextTarget(now);
|
|
264
|
+
if (!target) {
|
|
265
|
+
console.error('无效的时间参数');
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
let delay = target.getTime() - now.getTime();
|
|
270
|
+
if (!Number.isFinite(delay)) {
|
|
271
|
+
console.error('无效的时间参数');
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (!repeatDaily && delay <= 0) {
|
|
276
|
+
console.log('指定时间已过,不执行自定义命令');
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (delay < 0) delay = 0;
|
|
281
|
+
console.log(`将在 ${target.toLocaleString()} 执行: ${cmd}${repeatDaily ? '(每日循环)' : ''}`);
|
|
282
|
+
atTimer = setTimeout(() => {
|
|
283
|
+
runOnce();
|
|
284
|
+
if (repeatDaily) scheduleNext();
|
|
285
|
+
}, delay);
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
scheduleNext();
|
|
289
|
+
|
|
290
|
+
process.on('SIGINT', () => {
|
|
291
|
+
if (atTimer) clearTimeout(atTimer);
|
|
292
|
+
process.exit();
|
|
293
|
+
});
|
|
294
|
+
} else if (intervalArg) {
|
|
295
|
+
// 定时循环执行
|
|
296
|
+
const intervalMatch = intervalArg.match(/^--cmd-interval=(['"]?)(.*)\1$/);
|
|
297
|
+
const interval = intervalMatch ? parseInt(intervalMatch[2], 10) * 1000 : 0;
|
|
298
|
+
if (interval > 0) {
|
|
299
|
+
console.log(`每隔 ${interval/1000} 秒执行: ${cmd}`);
|
|
300
|
+
setInterval(() => {
|
|
301
|
+
console.log(`\n[自定义命令执行] ${new Date().toLocaleString()}\n> ${cmd}`);
|
|
302
|
+
exec(cmd, (err, stdout, stderr) => {
|
|
303
|
+
if (err) {
|
|
304
|
+
console.error(`[自定义命令错误]`, err.message);
|
|
305
|
+
}
|
|
306
|
+
if (stdout) console.log(`[自定义命令输出]\n${stdout}`);
|
|
307
|
+
if (stderr) console.error(`[自定义命令错误输出]\n${stderr}`);
|
|
308
|
+
});
|
|
309
|
+
}, interval);
|
|
310
|
+
} else {
|
|
311
|
+
console.error('无效的时间间隔参数');
|
|
312
|
+
}
|
|
313
|
+
} else {
|
|
314
|
+
// 立即执行一次
|
|
315
|
+
console.log(`[自定义命令立即执行] > ${cmd}`);
|
|
316
|
+
exec(cmd, (err, stdout, stderr) => {
|
|
317
|
+
if (err) {
|
|
318
|
+
console.error(`[自定义命令错误]`, err.message);
|
|
319
|
+
}
|
|
320
|
+
if (stdout) console.log(`[自定义命令输出]\n${stdout}`);
|
|
321
|
+
if (stderr) console.error(`[自定义命令错误输出]\n${stderr}`);
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
// ========== 新增功能结束 ==========
|
|
326
|
+
|
|
327
|
+
// 判断是否需要执行git自动提交
|
|
328
|
+
const hasGitTask = process.argv.some(arg =>
|
|
329
|
+
arg.startsWith('--interval') ||
|
|
330
|
+
arg === '-y' ||
|
|
331
|
+
arg.startsWith('-m')
|
|
332
|
+
);
|
|
333
|
+
if (hasGitTask || !cmdArg) {
|
|
334
|
+
judgeInterval();
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const showStartInfo = (interval) => {
|
|
339
|
+
const cwd = getCwd();
|
|
340
|
+
const intervalSeconds = interval / 1000;
|
|
341
|
+
const startTime = new Date().toLocaleString();
|
|
342
|
+
|
|
343
|
+
const head = `⏰ 定时提交任务已启动`;
|
|
344
|
+
|
|
345
|
+
const message = chalk.green.bold([
|
|
346
|
+
`开始时间: ${chalk.yellow(startTime)}`,
|
|
347
|
+
`工作目录: ${chalk.cyan(cwd)}`,
|
|
348
|
+
`提交间隔: ${chalk.magenta(formatDuration(interval))}`,
|
|
349
|
+
].join("\n"));
|
|
350
|
+
|
|
351
|
+
coloredLog(head, message)
|
|
352
|
+
// console.log('\n'.repeat(6));
|
|
353
|
+
}
|
|
354
|
+
const commitAndSchedule = async (interval) => {
|
|
355
|
+
try {
|
|
356
|
+
await createGitCommit({exit: false});
|
|
357
|
+
// await delay(2000)
|
|
358
|
+
startCountdown(interval); // 启动倒计时
|
|
359
|
+
|
|
360
|
+
// 设置定时提交
|
|
361
|
+
timer = setTimeout(async () => {
|
|
362
|
+
await commitAndSchedule(interval);
|
|
363
|
+
}, interval + 100);
|
|
364
|
+
} catch (error) {
|
|
365
|
+
console.error('提交出错:', error.message);
|
|
366
|
+
clearTimeout(timer);
|
|
367
|
+
clearInterval(countdownInterval);
|
|
368
|
+
process.exit(1);
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
const judgeInterval = async () => {
|
|
372
|
+
const intervalArg = process.argv.find(arg => arg.startsWith('--interval'));
|
|
373
|
+
if (intervalArg) {
|
|
374
|
+
let interval = parseInt(intervalArg.split('=')[1] || '3600', 10) * 1000;
|
|
375
|
+
|
|
376
|
+
showStartInfo(interval);
|
|
377
|
+
|
|
378
|
+
try {
|
|
379
|
+
await commitAndSchedule(interval);
|
|
380
|
+
} catch (error) {
|
|
381
|
+
console.error(chalk.red.bold('定时提交致命错误:'), error.message);
|
|
382
|
+
process.exit(1);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// 处理退出清理
|
|
386
|
+
process.on('SIGINT', () => {
|
|
387
|
+
logUpdate.clear();
|
|
388
|
+
clearTimeout(timer);
|
|
389
|
+
clearInterval(countdownInterval);
|
|
390
|
+
console.log(chalk.yellow('\n🛑 定时任务已终止'));
|
|
391
|
+
process.exit();
|
|
392
|
+
});
|
|
393
|
+
} else {
|
|
394
|
+
createGitCommit({exit: false});
|
|
395
|
+
}
|
|
396
|
+
};
|
|
397
|
+
// const judgeInterval = async () => {
|
|
398
|
+
// // 判断是否有 --interval 参数
|
|
399
|
+
// const intervalArg = process.argv.find(arg => arg.startsWith('--interval'));
|
|
400
|
+
// if (intervalArg) {
|
|
401
|
+
// // // console.log(`intervalArg ==> `, intervalArg)
|
|
402
|
+
// // let interval = intervalArg.split('=')[1] || 60 * 60; // 默认间隔为1小时
|
|
403
|
+
// // // console.log(`interval ==> `, interval)
|
|
404
|
+
// // interval = parseInt(interval, 10) * 1000; // 将间隔时间转换为毫秒
|
|
405
|
+
// // // console.log(`interval ==> `, interval)
|
|
406
|
+
// // if (isNaN(interval)) {
|
|
407
|
+
// // console.log('无效的间隔时间,请使用 --interval=秒数');
|
|
408
|
+
// // process.exit(1);
|
|
409
|
+
// // }
|
|
410
|
+
// // if (timer) {
|
|
411
|
+
// // console.log(`清空定时器`)
|
|
412
|
+
// // clearInterval(timer);
|
|
413
|
+
// // timer = null;
|
|
414
|
+
// // }
|
|
415
|
+
// // showStartInfo(interval);
|
|
416
|
+
// // await createGitCommit({exit: false})
|
|
417
|
+
// //
|
|
418
|
+
// // timer = setInterval(() => {
|
|
419
|
+
// // // console.log(`定时执行`)
|
|
420
|
+
// // createGitCommit({exit: false})
|
|
421
|
+
// // }, interval)
|
|
422
|
+
//
|
|
423
|
+
// let interval = parseInt(intervalArg.split('=')[1] || '3600', 10) * 1000;
|
|
424
|
+
// // const showUpdates = () => {
|
|
425
|
+
// // showNextCommitTime(interval);
|
|
426
|
+
// // // 每小时更新一次时间显示
|
|
427
|
+
// // timer = setTimeout(() => {
|
|
428
|
+
// // showUpdates();
|
|
429
|
+
// // }, 20000); // 每小时更新一次
|
|
430
|
+
// // };
|
|
431
|
+
//
|
|
432
|
+
// const commitAndSchedule = async (interval) => {
|
|
433
|
+
// try {
|
|
434
|
+
// await createGitCommit({exit: false});
|
|
435
|
+
// startCountdown(interval); // 启动倒计时
|
|
436
|
+
//
|
|
437
|
+
// // 设置定时提交
|
|
438
|
+
// timer = setTimeout(async () => {
|
|
439
|
+
// await commitAndSchedule(interval);
|
|
440
|
+
// }, interval);
|
|
441
|
+
// } catch (error) {
|
|
442
|
+
// console.error('提交出错:', error.message);
|
|
443
|
+
// }
|
|
444
|
+
// };
|
|
445
|
+
//
|
|
446
|
+
// await commitAndSchedule();
|
|
447
|
+
//
|
|
448
|
+
// // 设置定时提交
|
|
449
|
+
// timer = setInterval(commitAndSchedule, interval);
|
|
450
|
+
// } else {
|
|
451
|
+
// createGitCommit({exit: false})
|
|
452
|
+
// }
|
|
453
|
+
// };
|
|
454
|
+
|
|
455
|
+
main()
|