zen-gitsync 2.6.7 → 2.7.1

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.
@@ -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 - Git同步工具</title>
9
- <script type="module" crossorigin src="/assets/index-B2e9R1rl.js"></script>
10
- <link rel="modulepreload" crossorigin href="/assets/vendor-CHpDISRi.js">
9
+ <script type="module" crossorigin src="/assets/index-B3tYubJy.js"></script>
10
+ <link rel="modulepreload" crossorigin href="/assets/vendor-CSWa5gWa.js">
11
11
  <link rel="stylesheet" crossorigin href="/assets/vendor-HJmoQ7iQ.css">
12
- <link rel="stylesheet" crossorigin href="/assets/index-M7x7bOZu.css">
12
+ <link rel="stylesheet" crossorigin href="/assets/index-D43E11BH.css">
13
13
  </head>
14
14
  <body>
15
15
  <div id="app"></div>
@@ -172,9 +172,9 @@ async function startUIServer(noOpen = false, savePort = false) {
172
172
  res.setHeader('X-Accel-Buffering', 'no'); // 禁用nginx缓冲
173
173
 
174
174
  // 使用 spawn 执行命令,支持实时输出
175
- console.log(`[流式输出] 准备执行命令: ${command}`);
176
- console.log(`[流式输出] 当前平台: ${process.platform}`);
177
- console.log(`[流式输出] 工作目录: ${execDirectory}`);
175
+ // console.log(`[流式输出] 准备执行命令: ${command}`);
176
+ // console.log(`[流式输出] 当前平台: ${process.platform}`);
177
+ // console.log(`[流式输出] 工作目录: ${execDirectory}`);
178
178
 
179
179
  // 使用 shell: true 来支持 Windows 内置命令(如 dir、cd 等)
180
180
  const childProcess = spawn(command.trim(), [], {
@@ -186,22 +186,22 @@ async function startUIServer(noOpen = false, savePort = false) {
186
186
  }
187
187
  });
188
188
 
189
- console.log(`[流式输出] childProcess.stdout 是否存在:`, !!childProcess.stdout);
190
- console.log(`[流式输出] childProcess.stderr 是否存在:`, !!childProcess.stderr);
189
+ // console.log(`[流式输出] childProcess.stdout 是否存在:`, !!childProcess.stdout);
190
+ // console.log(`[流式输出] childProcess.stderr 是否存在:`, !!childProcess.stderr);
191
191
 
192
192
  let outputReceived = false;
193
193
 
194
194
  // 发送数据到客户端的辅助函数
195
195
  const sendData = (type, data) => {
196
196
  const message = `data: ${JSON.stringify({ type, data })}\n\n`;
197
- console.log(`[流式输出] 发送数据 - 类型: ${type}, 长度: ${data?.length || 0}`);
197
+ // console.log(`[流式输出] 发送数据 - 类型: ${type}, 长度: ${data?.length || 0}`);
198
198
  res.write(message);
199
199
  };
200
200
 
201
201
  // 在 Windows 上,CMD 默认使用 GBK 编码
202
202
  // 不设置 encoding,直接处理 Buffer,然后用 iconv-lite 转换
203
203
  const isWindows = process.platform === 'win32';
204
- console.log(`[流式输出] 平台: ${process.platform}, 使用编码转换: ${isWindows}`);
204
+ // console.log(`[流式输出] 平台: ${process.platform}, 使用编码转换: ${isWindows}`);
205
205
 
206
206
  // 监听标准输出
207
207
  childProcess.stdout?.on('data', (data) => {
@@ -210,11 +210,11 @@ async function startUIServer(noOpen = false, savePort = false) {
210
210
  if (isWindows) {
211
211
  // Windows 系统,从 GBK 转换为 UTF-8
212
212
  output = iconv.decode(data, 'gbk');
213
- console.log(`[流式输出] 收到stdout(GBK转UTF8):`, output.substring(0, 100));
213
+ // console.log(`[流式输出] 收到stdout(GBK转UTF8):`, output.substring(0, 100));
214
214
  } else {
215
215
  // Unix 系统,直接使用 UTF-8
216
216
  output = data.toString('utf8');
217
- console.log(`[流式输出] 收到stdout(UTF8):`, output.substring(0, 100));
217
+ // console.log(`[流式输出] 收到stdout(UTF8):`, output.substring(0, 100));
218
218
  }
219
219
  outputReceived = true;
220
220
  sendData('stdout', output);
@@ -227,11 +227,11 @@ async function startUIServer(noOpen = false, savePort = false) {
227
227
  if (isWindows) {
228
228
  // Windows 系统,从 GBK 转换为 UTF-8
229
229
  output = iconv.decode(data, 'gbk');
230
- console.log(`[流式输出] 收到stderr(GBK转UTF8):`, output.substring(0, 100));
230
+ // console.log(`[流式输出] 收到stderr(GBK转UTF8):`, output.substring(0, 100));
231
231
  } else {
232
232
  // Unix 系统,直接使用 UTF-8
233
233
  output = data.toString('utf8');
234
- console.log(`[流式输出] 收到stderr(UTF8):`, output.substring(0, 100));
234
+ // console.log(`[流式输出] 收到stderr(UTF8):`, output.substring(0, 100));
235
235
  }
236
236
  outputReceived = true;
237
237
  // 不再自动标记为错误,只显示 stderr 输出
@@ -241,12 +241,12 @@ async function startUIServer(noOpen = false, savePort = false) {
241
241
 
242
242
  // 监听进程退出(exit 在流关闭前触发)
243
243
  childProcess.on('exit', (code, signal) => {
244
- console.log(`[流式输出] 进程 exit 事件 - 代码: ${code}, 信号: ${signal}`);
244
+ // console.log(`[流式输出] 进程 exit 事件 - 代码: ${code}, 信号: ${signal}`);
245
245
  });
246
246
 
247
247
  // 监听进程关闭(close 在流关闭后触发)
248
248
  childProcess.on('close', (code, signal) => {
249
- console.log(`[流式输出] 进程 close 事件 - 代码: ${code}, 信号: ${signal}, 有输出: ${outputReceived}`);
249
+ // console.log(`[流式输出] 进程 close 事件 - 代码: ${code}, 信号: ${signal}, 有输出: ${outputReceived}`);
250
250
  // 只根据退出码判断成功与否,退出码为 0 表示成功
251
251
  sendData('exit', { code, success: code === 0 });
252
252
  res.end();
@@ -254,14 +254,14 @@ async function startUIServer(noOpen = false, savePort = false) {
254
254
 
255
255
  // 监听错误
256
256
  childProcess.on('error', (error) => {
257
- console.error(`[流式输出] 进程错误:`, error);
257
+ // console.error(`[流式输出] 进程错误:`, error);
258
258
  sendData('error', error.message);
259
259
  res.end();
260
260
  });
261
261
 
262
262
  // 添加spawn事件监听
263
263
  childProcess.on('spawn', () => {
264
- console.log(`[流式输出] 进程已启动 - PID: ${childProcess.pid}`);
264
+ // console.log(`[流式输出] 进程已启动 - PID: ${childProcess.pid}`);
265
265
  });
266
266
 
267
267
  // 注意:不监听req.on('close'),参考git push的实现
@@ -361,7 +361,7 @@ async function startUIServer(noOpen = false, savePort = false) {
361
361
  }
362
362
 
363
363
  // 缓存失效或强制刷新,重新获取
364
- console.log('重新获取当前分支名...');
364
+ // console.log('重新获取当前分支名...');
365
365
  const { stdout } = await execGitCommand('git symbolic-ref --short HEAD');
366
366
  const branchName = stdout.trim();
367
367
 
@@ -491,7 +491,7 @@ async function startUIServer(noOpen = false, savePort = false) {
491
491
  }
492
492
 
493
493
  // 缓存失效或强制刷新,重新获取分支信息
494
- console.log('重新获取分支信息...');
494
+ // console.log('重新获取分支信息...');
495
495
 
496
496
  // 分支名缓存和分支状态缓存独立工作
497
497
  // 只有在分支状态强制刷新且分支名缓存也失效时,才强制刷新分支名
@@ -571,10 +571,6 @@ async function startUIServer(noOpen = false, savePort = false) {
571
571
  ...remoteBranchList
572
572
  ];
573
573
 
574
- console.log('本地分支:', localBranchList);
575
- console.log('远程分支:', remoteBranchList);
576
- console.log('所有分支:', allBranches);
577
-
578
574
  res.json({ branches: allBranches });
579
575
  } catch (error) {
580
576
  console.error('获取分支列表失败:', error);
@@ -1287,12 +1283,12 @@ async function startUIServer(noOpen = false, savePort = false) {
1287
1283
  // 获取配置
1288
1284
  app.get('/api/config/getConfig', async (req, res) => {
1289
1285
  try {
1290
- console.log('获取配置中。。。')
1286
+ // console.log('获取配置中。。。')
1291
1287
  const config = await configManager.loadConfig()
1292
- console.log('获取配置成功')
1288
+ // console.log('获取配置成功')
1293
1289
  res.json(config)
1294
1290
  } catch (error) {
1295
- console.log('获取配置失败')
1291
+ // console.log('获取配置失败')
1296
1292
  res.status(500).json({ error: error.message })
1297
1293
  }
1298
1294
  })
@@ -2300,7 +2296,7 @@ async function startUIServer(noOpen = false, savePort = false) {
2300
2296
  formatString = '%H%x1E%an%x1E%ae%x1E%ad%x1E%B%x1E%D%x1E%P';
2301
2297
  }
2302
2298
 
2303
- console.log(`执行Git命令: git log --all --pretty=format:"${formatString}" --date=format-local:"%Y-%m-%d %H:%M" ${options}`);
2299
+ // console.log(`执行Git命令: git log --all --pretty=format:"${formatString}" --date=format-local:"%Y-%m-%d %H:%M" ${options}`);
2304
2300
 
2305
2301
  // 使用 git log 命令获取提交历史
2306
2302
  let { stdout: logOutput } = await execGitCommand(
@@ -2426,7 +2422,7 @@ async function startUIServer(noOpen = false, savePort = false) {
2426
2422
  // 如果返回的数据量小于limit,说明已经到底了
2427
2423
  const hasMore = data.length === limit;
2428
2424
 
2429
- console.log(`分页查询 - 页码: ${page}, 每页数量: ${limit}, 返回数量: ${data.length}, 是否有更多: ${hasMore} (优化版本,不计算总数)`);
2425
+ // console.log(`分页查询 - 页码: ${page}, 每页数量: ${limit}, 返回数量: ${data.length}, 是否有更多: ${hasMore} (优化版本,不计算总数)`);
2430
2426
 
2431
2427
  // 返回提交历史数据,包括是否有更多数据的标志
2432
2428
  res.json({
@@ -3551,6 +3547,153 @@ async function startUIServer(noOpen = false, savePort = false) {
3551
3547
  }
3552
3548
  });
3553
3549
 
3550
+ // ============ Git Tag 相关接口 ============
3551
+
3552
+ // 创建标签
3553
+ app.post('/api/create-tag', async (req, res) => {
3554
+ try {
3555
+ const { tagName, message, type, commit } = req.body;
3556
+
3557
+ if (!tagName) {
3558
+ return res.status(400).json({ success: false, error: '缺少标签名称' });
3559
+ }
3560
+
3561
+ let command = 'git tag';
3562
+
3563
+ if (type === 'annotated') {
3564
+ // 附注标签
3565
+ if (!message) {
3566
+ return res.status(400).json({ success: false, error: '附注标签需要提供说明信息' });
3567
+ }
3568
+ command += ` -a "${tagName}" -m "${message}"`;
3569
+ } else {
3570
+ // 轻量标签
3571
+ command += ` "${tagName}"`;
3572
+ }
3573
+
3574
+ // 如果指定了commit,添加到命令中
3575
+ if (commit && commit.trim()) {
3576
+ command += ` ${commit.trim()}`;
3577
+ }
3578
+
3579
+ const { stdout } = await execGitCommand(command);
3580
+
3581
+ res.json({
3582
+ success: true,
3583
+ message: '标签创建成功',
3584
+ output: stdout
3585
+ });
3586
+ } catch (error) {
3587
+ console.error('创建标签失败:', error);
3588
+ res.status(500).json({ success: false, error: error.message });
3589
+ }
3590
+ });
3591
+
3592
+ // 获取标签列表
3593
+ app.get('/api/list-tags', async (req, res) => {
3594
+ try {
3595
+ // 使用 git tag -n --format 获取详细信息
3596
+ const { stdout } = await execGitCommand(
3597
+ 'git tag -n --format="%(refname:short)|%(objectname:short)|%(creatordate:iso8601)|%(subject)"'
3598
+ );
3599
+
3600
+ if (!stdout.trim()) {
3601
+ return res.json({ success: true, tags: [] });
3602
+ }
3603
+
3604
+ const tags = stdout.trim().split('\n').map(line => {
3605
+ const [name, commit, date, message] = line.split('|');
3606
+ return {
3607
+ name: name || '',
3608
+ commit: commit || '',
3609
+ date: date || '',
3610
+ message: message || '',
3611
+ type: 'lightweight' // 默认为轻量标签
3612
+ };
3613
+ });
3614
+
3615
+ // 检测哪些是附注标签
3616
+ for (const tag of tags) {
3617
+ try {
3618
+ const { stdout: typeCheck } = await execGitCommand(
3619
+ `git cat-file -t ${tag.name}`,
3620
+ { log: false }
3621
+ );
3622
+ if (typeCheck.trim() === 'tag') {
3623
+ tag.type = 'annotated';
3624
+ }
3625
+ } catch (error) {
3626
+ // 忽略错误,保持默认值
3627
+ }
3628
+ }
3629
+
3630
+ res.json({ success: true, tags });
3631
+ } catch (error) {
3632
+ console.error('获取标签列表失败:', error);
3633
+ res.status(500).json({ success: false, error: error.message });
3634
+ }
3635
+ });
3636
+
3637
+ // 推送标签到远程
3638
+ app.post('/api/push-tag', async (req, res) => {
3639
+ try {
3640
+ const { tagName } = req.body;
3641
+
3642
+ if (!tagName) {
3643
+ return res.status(400).json({ success: false, error: '缺少标签名称' });
3644
+ }
3645
+
3646
+ const { stdout } = await execGitCommand(`git push origin ${tagName}`);
3647
+
3648
+ res.json({
3649
+ success: true,
3650
+ message: '标签推送成功',
3651
+ output: stdout
3652
+ });
3653
+ } catch (error) {
3654
+ console.error('推送标签失败:', error);
3655
+ res.status(500).json({ success: false, error: error.message });
3656
+ }
3657
+ });
3658
+
3659
+ // 推送所有标签到远程
3660
+ app.post('/api/push-all-tags', async (req, res) => {
3661
+ try {
3662
+ const { stdout } = await execGitCommand('git push origin --tags');
3663
+
3664
+ res.json({
3665
+ success: true,
3666
+ message: '所有标签推送成功',
3667
+ output: stdout
3668
+ });
3669
+ } catch (error) {
3670
+ console.error('推送所有标签失败:', error);
3671
+ res.status(500).json({ success: false, error: error.message });
3672
+ }
3673
+ });
3674
+
3675
+ // 删除标签
3676
+ app.post('/api/delete-tag', async (req, res) => {
3677
+ try {
3678
+ const { tagName } = req.body;
3679
+
3680
+ if (!tagName) {
3681
+ return res.status(400).json({ success: false, error: '缺少标签名称' });
3682
+ }
3683
+
3684
+ const { stdout } = await execGitCommand(`git tag -d ${tagName}`);
3685
+
3686
+ res.json({
3687
+ success: true,
3688
+ message: '标签删除成功',
3689
+ output: stdout
3690
+ });
3691
+ } catch (error) {
3692
+ console.error('删除标签失败:', error);
3693
+ res.status(500).json({ success: false, error: error.message });
3694
+ }
3695
+ });
3696
+
3554
3697
  // 锁定文件
3555
3698
  app.post('/api/lock-file', async (req, res) => {
3556
3699
  try {
@@ -3629,7 +3772,7 @@ async function startUIServer(noOpen = false, savePort = false) {
3629
3772
  const packageJsons = [];
3630
3773
  const startTime = Date.now();
3631
3774
 
3632
- console.log(`[NPM扫描-后端] 开始扫描项目: ${projectRoot}`);
3775
+ // console.log(`[NPM扫描-后端] 开始扫描项目: ${projectRoot}`);
3633
3776
 
3634
3777
  // 需要忽略的目录列表(更全面)
3635
3778
  const IGNORED_DIRS = new Set([
@@ -3697,7 +3840,8 @@ async function startUIServer(noOpen = false, savePort = false) {
3697
3840
  relativePath: relativePath || '.',
3698
3841
  name: packageData.name || path.basename(dir),
3699
3842
  scripts: packageData.scripts,
3700
- version: packageData.version || '0.0.0'
3843
+ version: packageData.version || '0.0.0',
3844
+ repository: packageData.repository
3701
3845
  });
3702
3846
  return true;
3703
3847
  }
@@ -3784,10 +3928,10 @@ async function startUIServer(noOpen = false, savePort = false) {
3784
3928
  }
3785
3929
 
3786
3930
  // 执行递归扫描
3787
- console.log(`[NPM扫描-后端] 开始递归扫描(最大深度${MAX_DEPTH}层)`);
3931
+ // console.log(`[NPM扫描-后端] 开始递归扫描(最大深度${MAX_DEPTH}层)`);
3788
3932
  const scanStart = Date.now();
3789
3933
  await scanDirectory(projectRoot, 0);
3790
- console.log(`[NPM扫描-后端] 递归扫描完成,耗时${Date.now() - scanStart}ms`);
3934
+ // console.log(`[NPM扫描-后端] 递归扫描完成,耗时${Date.now() - scanStart}ms`);
3791
3935
 
3792
3936
  // 扫描完成,清除abort controller
3793
3937
  if (currentScanAbortController === scanController) {
@@ -3812,8 +3956,8 @@ async function startUIServer(noOpen = false, savePort = false) {
3812
3956
  .filter(Boolean)
3813
3957
  .join(', ');
3814
3958
 
3815
- console.log(`npm脚本扫描完成,耗时${scanTime}ms,扫描了${scannedCount}个目录,读取了${fileReadCount}个package.json文件,跳过${skippedCount}个目录,找到${packageJsons.length}个有效的package.json`);
3816
- console.log(`[NPM扫描-后端] 深度分布: ${depthInfo}`);
3959
+ // console.log(`npm脚本扫描完成,耗时${scanTime}ms,扫描了${scannedCount}个目录,读取了${fileReadCount}个package.json文件,跳过${skippedCount}个目录,找到${packageJsons.length}个有效的package.json`);
3960
+ // console.log(`[NPM扫描-后端] 深度分布: ${depthInfo}`);
3817
3961
 
3818
3962
  res.json({
3819
3963
  success: true,
@@ -4383,9 +4527,6 @@ async function startUIServer(noOpen = false, savePort = false) {
4383
4527
 
4384
4528
  if (isGitRepo) {
4385
4529
  console.log(chalk.green(` 当前目录是Git仓库`));
4386
- console.log(chalk.yellow(` 文件监控已禁用(默认),需要时请在前端开启自动更新开关`));
4387
- // 不再自动启动文件监控,只在用户开启自动更新开关时启动
4388
- // initFileSystemWatcher().catch(err => console.error('[文件监控] 初始化失败:', err));
4389
4530
  } else {
4390
4531
  console.log(chalk.yellow(` 当前目录不是Git仓库,文件监控未启动`));
4391
4532
  }
@@ -158,11 +158,33 @@ const tableLog = (commandLine, content, type) => {
158
158
  default:
159
159
  break;
160
160
  }
161
+
162
+ // 限制输出内容
163
+ const MAX_LINES = 10; // 最大行数
164
+ const MAX_LINE_LENGTH = 200; // 每行最大字符数
165
+ let isTruncated = false;
166
+
167
+ if (content.length > MAX_LINES) {
168
+ content = content.slice(0, MAX_LINES);
169
+ isTruncated = true;
170
+ }
171
+
161
172
  content = content.map(item => {
162
173
  let fontColor = calcColor(commandLine, item)
163
174
  let row = item.replaceAll('\t', ' ')
175
+
176
+ // 截断过长的行
177
+ if (row.length > MAX_LINE_LENGTH) {
178
+ row = row.substring(0, MAX_LINE_LENGTH) + '...';
179
+ }
180
+
164
181
  return chalk[fontColor](row)
165
182
  })
183
+
184
+ // 如果内容被截断,添加提示
185
+ if (isTruncated) {
186
+ content.push(chalk.dim('... (输出内容过多,已省略)'));
187
+ }
166
188
 
167
189
  printTableWithHeaderUnderline(head, content, style)
168
190
  }