zen-gitsync 2.10.22 → 2.10.25
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/package.json +7 -1
- package/src/config.js +27 -5
- package/src/ui/public/assets/index-B_4pBzHH.js +108 -0
- package/src/ui/public/assets/index-aLDYiWyf.css +1 -0
- package/src/ui/public/assets/{vendor-BpNfZzQX.js → vendor-fjnRPl5Q.js} +156 -156
- package/src/ui/public/index.html +3 -3
- package/src/ui/server/index.js +2 -1
- package/src/ui/server/routes/config.js +25 -1
- package/src/ui/server/routes/gitOps.js +37 -5
- package/src/utils/index.js +39 -2
- package/src/ui/public/assets/index-CMtBiEyQ.js +0 -108
- package/src/ui/public/assets/index-yIgMDwRm.css +0 -1
package/src/ui/public/index.html
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
7
7
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
8
8
|
<title>Zen GitSync</title>
|
|
9
|
-
<script type="module" crossorigin src="/assets/index-
|
|
10
|
-
<link rel="modulepreload" crossorigin href="/assets/vendor-
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-B_4pBzHH.js"></script>
|
|
10
|
+
<link rel="modulepreload" crossorigin href="/assets/vendor-fjnRPl5Q.js">
|
|
11
11
|
<link rel="stylesheet" crossorigin href="/assets/vendor-DpSHka1A.css">
|
|
12
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
12
|
+
<link rel="stylesheet" crossorigin href="/assets/index-aLDYiWyf.css">
|
|
13
13
|
</head>
|
|
14
14
|
<body>
|
|
15
15
|
<div id="app"></div>
|
package/src/ui/server/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import express from 'express';
|
|
|
2
2
|
import { createServer } from 'http';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
4
|
import path from 'path';
|
|
5
|
-
import { execGitCommand, getCommandHistory, addCommandToHistory, clearCommandHistory, registerSocketIO, execGitAddWithLockFilter } from '../../utils/index.js';
|
|
5
|
+
import { execGitCommand, getCommandHistory, addCommandToHistory, clearCommandHistory, registerSocketIO, execGitAddWithLockFilter, checkAndClearGitLock } from '../../utils/index.js';
|
|
6
6
|
import open from 'open';
|
|
7
7
|
import config from '../../config.js';
|
|
8
8
|
import chalk from 'chalk';
|
|
@@ -230,6 +230,7 @@ async function startUIServer(noOpen = false, savePort = false) {
|
|
|
230
230
|
execGitAddWithLockFilter,
|
|
231
231
|
addCommandToHistory,
|
|
232
232
|
clearCommandHistory,
|
|
233
|
+
checkAndClearGitLock,
|
|
233
234
|
getIsGitRepo: () => isGitRepo,
|
|
234
235
|
setRecentPushStatus: (v) => { recentPushStatus = v; }
|
|
235
236
|
});
|
|
@@ -644,7 +644,7 @@ export function registerConfigRoutes({
|
|
|
644
644
|
}
|
|
645
645
|
})
|
|
646
646
|
|
|
647
|
-
//
|
|
647
|
+
// 保存"一键推送成功后启动项"
|
|
648
648
|
app.post('/api/config/save-after-quick-push-action', express.json(), async (req, res) => {
|
|
649
649
|
try {
|
|
650
650
|
const { afterQuickPushAction } = req.body
|
|
@@ -670,4 +670,28 @@ export function registerConfigRoutes({
|
|
|
670
670
|
res.status(500).json({ success: false, error: error.message })
|
|
671
671
|
}
|
|
672
672
|
})
|
|
673
|
+
|
|
674
|
+
// 保存通用设置(主题和语言)
|
|
675
|
+
app.post('/api/config/save-general-settings', express.json(), async (req, res) => {
|
|
676
|
+
try {
|
|
677
|
+
const { theme, locale } = req.body
|
|
678
|
+
|
|
679
|
+
// 读取原始配置以保留项目设置
|
|
680
|
+
const rawConfig = await configManager.readRawConfigFile()
|
|
681
|
+
|
|
682
|
+
// 更新全局设置
|
|
683
|
+
if (theme && ['light', 'dark', 'auto'].includes(theme)) {
|
|
684
|
+
rawConfig.theme = theme
|
|
685
|
+
}
|
|
686
|
+
if (locale && ['zh-CN', 'en-US'].includes(locale)) {
|
|
687
|
+
rawConfig.locale = locale
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
// 直接写入原始配置,避免覆盖项目设置
|
|
691
|
+
await configManager.writeRawConfigFile(rawConfig)
|
|
692
|
+
res.json({ success: true })
|
|
693
|
+
} catch (error) {
|
|
694
|
+
res.status(500).json({ success: false, error: error.message })
|
|
695
|
+
}
|
|
696
|
+
})
|
|
673
697
|
}
|
|
@@ -16,6 +16,7 @@ export function registerGitOpsRoutes({
|
|
|
16
16
|
execGitAddWithLockFilter,
|
|
17
17
|
addCommandToHistory,
|
|
18
18
|
clearCommandHistory,
|
|
19
|
+
checkAndClearGitLock,
|
|
19
20
|
getIsGitRepo,
|
|
20
21
|
setRecentPushStatus
|
|
21
22
|
}) {
|
|
@@ -344,11 +345,17 @@ export function registerGitOpsRoutes({
|
|
|
344
345
|
res.json({ success: true, message: stdout });
|
|
345
346
|
} catch (error) {
|
|
346
347
|
// 改进错误处理,检查是否需要合并
|
|
347
|
-
|
|
348
|
-
const
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
348
|
+
// 合并冲突信息可能在 message 或 stderr 中
|
|
349
|
+
const errorMsg = (error.message || '').toLowerCase();
|
|
350
|
+
const stderrMsg = (error.stderr || '').toLowerCase();
|
|
351
|
+
const stdoutMsg = (error.stdout || '').toLowerCase();
|
|
352
|
+
const fullOutput = errorMsg + ' ' + stderrMsg + ' ' + stdoutMsg;
|
|
353
|
+
|
|
354
|
+
const needsMerge = fullOutput.includes('merge') ||
|
|
355
|
+
fullOutput.includes('需要合并') ||
|
|
356
|
+
fullOutput.includes('conflict') ||
|
|
357
|
+
fullOutput.includes('冲突') ||
|
|
358
|
+
fullOutput.includes('automatic merge failed');
|
|
352
359
|
|
|
353
360
|
// 返回更详细的错误信息和标记
|
|
354
361
|
res.status(500).json({
|
|
@@ -637,6 +644,9 @@ export function registerGitOpsRoutes({
|
|
|
637
644
|
});
|
|
638
645
|
}
|
|
639
646
|
|
|
647
|
+
// 尝试清理 Git 锁文件
|
|
648
|
+
await checkAndClearGitLock();
|
|
649
|
+
|
|
640
650
|
// 执行 git reset --hard origin/branch 命令
|
|
641
651
|
await execGitCommand(`git reset --hard origin/${branch}`);
|
|
642
652
|
res.json({ success: true });
|
|
@@ -649,6 +659,28 @@ export function registerGitOpsRoutes({
|
|
|
649
659
|
}
|
|
650
660
|
});
|
|
651
661
|
|
|
662
|
+
// 清除本地所有更改,包括未跟踪文件 (git reset --hard && git clean -fd)
|
|
663
|
+
app.post('/api/discard-all-changes', async (req, res) => {
|
|
664
|
+
try {
|
|
665
|
+
// 尝试清理 Git 锁文件
|
|
666
|
+
await checkAndClearGitLock();
|
|
667
|
+
|
|
668
|
+
// 1. 执行 git reset --hard 丢弃已跟踪文件的更改
|
|
669
|
+
await execGitCommand('git reset --hard');
|
|
670
|
+
|
|
671
|
+
// 2. 执行 git clean -fd 移除未跟踪的文件和目录
|
|
672
|
+
await execGitCommand('git clean -fd');
|
|
673
|
+
|
|
674
|
+
res.json({ success: true });
|
|
675
|
+
} catch (error) {
|
|
676
|
+
console.error('清除所有更改失败:', error);
|
|
677
|
+
res.status(500).json({
|
|
678
|
+
success: false,
|
|
679
|
+
error: `清除所有更改失败: ${error.message}`
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
});
|
|
683
|
+
|
|
652
684
|
// 获取提交的文件列表
|
|
653
685
|
app.get('/api/commit-files', async (req, res) => {
|
|
654
686
|
try {
|
package/src/utils/index.js
CHANGED
|
@@ -350,6 +350,9 @@ function execGitCommand(command, options = {}) {
|
|
|
350
350
|
const currentTime = new Date().toLocaleString('zh-CN', { hour12: false });
|
|
351
351
|
console.log(chalk.dim(`📁 目录: ${cwd} | ⏰ 时间: ${currentTime}`));
|
|
352
352
|
}
|
|
353
|
+
// 将 stdout 和 stderr 附加到 error 对象,以便上层可以获取完整输出
|
|
354
|
+
error.stdout = stdout
|
|
355
|
+
error.stderr = stderr
|
|
353
356
|
reject(error)
|
|
354
357
|
return
|
|
355
358
|
}
|
|
@@ -362,6 +365,39 @@ function execGitCommand(command, options = {}) {
|
|
|
362
365
|
})
|
|
363
366
|
}
|
|
364
367
|
|
|
368
|
+
/**
|
|
369
|
+
* 检查并尝试清理 Git 锁文件
|
|
370
|
+
* @returns {Promise<boolean>} 是否清理成功
|
|
371
|
+
*/
|
|
372
|
+
async function checkAndClearGitLock() {
|
|
373
|
+
try {
|
|
374
|
+
const cwd = getCwd();
|
|
375
|
+
let gitRoot;
|
|
376
|
+
try {
|
|
377
|
+
// 使用 execSync 快速获取 Git 根目录
|
|
378
|
+
const rootOutput = execSync('git rev-parse --show-toplevel', { cwd, encoding: 'utf-8' });
|
|
379
|
+
gitRoot = rootOutput.trim();
|
|
380
|
+
} catch (e) {
|
|
381
|
+
gitRoot = cwd;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const lockFilePath = path.join(gitRoot, '.git', 'index.lock');
|
|
385
|
+
try {
|
|
386
|
+
await fs.access(lockFilePath);
|
|
387
|
+
// 如果文件存在,尝试删除它
|
|
388
|
+
await fs.unlink(lockFilePath);
|
|
389
|
+
console.log(chalk.green(`✅ 已清理 Git 锁文件: ${lockFilePath}`));
|
|
390
|
+
return true;
|
|
391
|
+
} catch (e) {
|
|
392
|
+
// 文件不存在,不需要清理
|
|
393
|
+
return false;
|
|
394
|
+
}
|
|
395
|
+
} catch (error) {
|
|
396
|
+
console.error(chalk.red('清理 Git 锁文件失败:'), error.message);
|
|
397
|
+
return false;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
365
401
|
// Function to get command history
|
|
366
402
|
function getCommandHistory() {
|
|
367
403
|
return [...commandHistory];
|
|
@@ -462,12 +498,12 @@ File Locking:
|
|
|
462
498
|
--cmd="your-cmd" Execute custom cmd command (immediately, at a time, or periodically)
|
|
463
499
|
--cmd-interval=<seconds> Execute custom cmd every N seconds
|
|
464
500
|
--at="HH:MM" Execute custom cmd at a specific time (today) or --at="YYYY-MM-DD HH:MM:SS"
|
|
465
|
-
--daily Repeat with --at every day at the same time
|
|
501
|
+
--daily Repeat with --at every day at the same time
|
|
466
502
|
|
|
467
503
|
Example:
|
|
468
504
|
g --cmd="echo hello" --cmd-interval=5 # 每5秒执行一次echo hello
|
|
469
505
|
g --cmd="echo at-time" --at=23:59 # 在23:59执行一次echo at-time
|
|
470
|
-
g --cmd="echo daily" --at=23:59 --daily # 每天23:59执行一次echo daily
|
|
506
|
+
g --cmd="echo daily" --at=23:59 --daily # 每天23:59执行一次echo daily
|
|
471
507
|
g --cmd="echo now" # 立即执行一次echo now
|
|
472
508
|
g --cmd="echo hi" --cmd-interval=10 --interval=60 # cmd和git自动提交并行
|
|
473
509
|
g -m "Initial commit" Commit with a custom message
|
|
@@ -998,6 +1034,7 @@ export {
|
|
|
998
1034
|
coloredLog, errorLog, execSyncGitCommand,
|
|
999
1035
|
execGitCommand, getCommandHistory, addCommandToHistory, // Add command history exports
|
|
1000
1036
|
clearCommandHistory,
|
|
1037
|
+
checkAndClearGitLock,
|
|
1001
1038
|
registerSocketIO, // 导出注册Socket.io的函数
|
|
1002
1039
|
getCwd, judgePlatform, showHelp, judgeLog, printGitLog,
|
|
1003
1040
|
judgeHelp, exec_exit, judgeUnmerged, delay, formatDuration,
|