zen-gitsync 2.6.2 → 2.6.3

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-B8Tdx6e-.js"></script>
10
- <link rel="modulepreload" crossorigin href="/assets/vendor-C0dfGhZ-.js">
11
- <link rel="stylesheet" crossorigin href="/assets/vendor-HJmoQ7iQ.css">
12
- <link rel="stylesheet" crossorigin href="/assets/index-6Nf0Jabf.css">
9
+ <script type="module" crossorigin src="/assets/index-DkDsLMia.js"></script>
10
+ <link rel="modulepreload" crossorigin href="/assets/vendor-DBEYYHfT.js">
11
+ <link rel="stylesheet" crossorigin href="/assets/vendor-D9qDBEE1.css">
12
+ <link rel="stylesheet" crossorigin href="/assets/index-DhhwG1j0.css">
13
13
  </head>
14
14
  <body>
15
15
  <div id="app"></div>
@@ -1967,6 +1967,115 @@ async function startUIServer(noOpen = false, savePort = false) {
1967
1967
  });
1968
1968
  }
1969
1969
 
1970
+ // ========== Diff 大文件检测和过滤工具函数 ==========
1971
+
1972
+ /**
1973
+ * 检查文件是否应该跳过diff显示(参考GitLab策略)
1974
+ * @param {string} filePath - 文件路径
1975
+ * @param {string} diffCommand - 要执行的git diff命令
1976
+ * @returns {Promise<{shouldSkip: boolean, reason?: string, stats?: object}>}
1977
+ */
1978
+ async function checkShouldSkipDiff(filePath, diffCommand) {
1979
+ // 1. 检查文件扩展名 - 编译/压缩/二进制文件
1980
+ const skipExtensions = /\.(min\.js|umd\.cjs|bundle\.js|dist\.js|prod\.js|map|wasm|exe|dll|so|dylib|bin|zip|tar|gz|rar|7z|jar|war|ear|pdf|doc|docx|xls|xlsx|ppt|pptx|jpg|jpeg|png|gif|bmp|ico|mp3|mp4|avi|mov|wmv|flv|webm|mkv|ttf|woff|woff2|eot|otf)$/i;
1981
+ if (skipExtensions.test(filePath)) {
1982
+ return {
1983
+ shouldSkip: true,
1984
+ reason: '⚠️ 检测到编译/打包/二进制文件,diff已跳过显示。\n\n提示:这类文件通常是自动生成的或二进制文件,不适合查看diff。\n如需查看,请使用命令行。'
1985
+ };
1986
+ }
1987
+
1988
+ // 2. 使用 --numstat 快速检查变更量(不获取实际内容,速度快)
1989
+ try {
1990
+ const numstatCommand = diffCommand.replace(/git (diff|show)/, 'git $1 --numstat');
1991
+ const { stdout: numstat } = await execGitCommand(numstatCommand, { log: false });
1992
+
1993
+ if (numstat.trim()) {
1994
+ const lines = numstat.trim().split('\n');
1995
+ for (const line of lines) {
1996
+ const parts = line.split('\t');
1997
+ if (parts.length >= 3) {
1998
+ const added = parts[0];
1999
+ const deleted = parts[1];
2000
+
2001
+ // 检查是否是二进制文件(显示为 - -)
2002
+ if (added === '-' && deleted === '-') {
2003
+ return {
2004
+ shouldSkip: true,
2005
+ reason: '⚠️ 检测到二进制文件,diff已跳过显示。\n\n提示:二进制文件无法以文本形式显示diff。'
2006
+ };
2007
+ }
2008
+
2009
+ // 检查变更行数是否过多(超过3000行)
2010
+ const totalChanges = parseInt(added) + parseInt(deleted);
2011
+ if (!isNaN(totalChanges) && totalChanges > 3000) {
2012
+ return {
2013
+ shouldSkip: true,
2014
+ reason: `⚠️ 变更内容过大 (${totalChanges.toLocaleString()} 行变更),diff已跳过显示以避免浏览器卡顿。\n\n提示:建议使用命令行或专业diff工具查看大文件变更。\n增加:${parseInt(added).toLocaleString()} 行\n删除:${parseInt(deleted).toLocaleString()} 行`,
2015
+ stats: { added: parseInt(added), deleted: parseInt(deleted), total: totalChanges }
2016
+ };
2017
+ }
2018
+ }
2019
+ }
2020
+ }
2021
+ } catch (error) {
2022
+ // numstat失败不影响后续流程
2023
+ console.log('numstat检查失败,继续执行:', error.message);
2024
+ }
2025
+
2026
+ // 3. 通过了初步检查
2027
+ return { shouldSkip: false };
2028
+ }
2029
+
2030
+ /**
2031
+ * 检查diff内容大小,如果过大则跳过
2032
+ * @param {string} diffContent - diff内容
2033
+ * @param {number} maxSizeKB - 最大大小(KB),默认500KB
2034
+ * @returns {object|null} - 如果需要跳过返回提示对象,否则返回null
2035
+ */
2036
+ function checkDiffSize(diffContent, maxSizeKB = 500) {
2037
+ const diffSizeKB = Buffer.byteLength(diffContent, 'utf8') / 1024;
2038
+ if (diffSizeKB > maxSizeKB) {
2039
+ return {
2040
+ diff: `⚠️ Diff内容过大 (${diffSizeKB.toFixed(1)} KB),已跳过显示以避免浏览器卡顿。\n\n提示:建议使用命令行查看大文件diff。`,
2041
+ isLargeFile: true,
2042
+ size: diffSizeKB
2043
+ };
2044
+ }
2045
+ return null;
2046
+ }
2047
+
2048
+ /**
2049
+ * 从 diff 内容中统计增加和删除行数
2050
+ * @param {string} diffContent - diff内容
2051
+ * @returns {object} - {added, deleted}
2052
+ */
2053
+ function getDiffStats(diffContent) {
2054
+ if (!diffContent) return { added: 0, deleted: 0 };
2055
+
2056
+ const lines = diffContent.split('\n');
2057
+ let added = 0;
2058
+ let deleted = 0;
2059
+
2060
+ for (const line of lines) {
2061
+ // 跳过diff头部信息
2062
+ if (line.startsWith('diff ') || line.startsWith('index ') ||
2063
+ line.startsWith('--- ') || line.startsWith('+++ ') ||
2064
+ line.startsWith('@@ ')) {
2065
+ continue;
2066
+ }
2067
+
2068
+ // 统计增加和删除的行
2069
+ if (line.startsWith('+')) {
2070
+ added++;
2071
+ } else if (line.startsWith('-')) {
2072
+ deleted++;
2073
+ }
2074
+ }
2075
+
2076
+ return { added, deleted };
2077
+ }
2078
+
1970
2079
  // 获取文件差异
1971
2080
  app.get('/api/diff', async (req, res) => {
1972
2081
  try {
@@ -1976,29 +2085,31 @@ async function startUIServer(noOpen = false, savePort = false) {
1976
2085
  return res.status(400).json({ error: '缺少文件路径参数' });
1977
2086
  }
1978
2087
 
1979
- // 检查是否是编译/压缩文件(通常很大且不需要查看diff
1980
- const isCompiledFile = /\.(min\.js|umd\.cjs|bundle\.js|dist\.js|prod\.js)$/i.test(filePath);
1981
- if (isCompiledFile) {
2088
+ const diffCommand = `git diff -- "${filePath}"`;
2089
+
2090
+ // 使用优化的检查函数
2091
+ const skipCheck = await checkShouldSkipDiff(filePath, diffCommand);
2092
+ if (skipCheck.shouldSkip) {
1982
2093
  return res.json({
1983
- diff: '⚠️ 检测到编译/打包文件,diff内容过大已跳过显示。\n\n提示:这类文件通常是自动生成的,不建议查看diff。\n如需查看,请使用命令行:git diff -- "' + filePath + '"',
1984
- isLargeFile: true
2094
+ diff: skipCheck.reason,
2095
+ isLargeFile: true,
2096
+ stats: skipCheck.stats
1985
2097
  });
1986
2098
  }
1987
2099
 
1988
2100
  // 执行git diff命令获取文件差异
1989
- const { stdout } = await execGitCommand(`git diff -- "${filePath}"`);
2101
+ const { stdout } = await execGitCommand(diffCommand);
1990
2102
 
1991
- // 检查diff大小,如果超过500KB,只返回提示
1992
- const diffSizeKB = Buffer.byteLength(stdout, 'utf8') / 1024;
1993
- if (diffSizeKB > 500) {
1994
- return res.json({
1995
- diff: `⚠️ Diff内容过大 (${diffSizeKB.toFixed(1)}KB),已跳过显示以避免浏览器卡顿。\n\n提示:请使用命令行查看:git diff -- "${filePath}"`,
1996
- isLargeFile: true,
1997
- size: diffSizeKB
1998
- });
2103
+ // 检查实际diff大小
2104
+ const sizeCheck = checkDiffSize(stdout, 500);
2105
+ if (sizeCheck) {
2106
+ return res.json(sizeCheck);
1999
2107
  }
2000
2108
 
2001
- res.json({ diff: stdout });
2109
+ // 统计增加和删除行数
2110
+ const stats = getDiffStats(stdout);
2111
+
2112
+ res.json({ diff: stdout, stats });
2002
2113
  } catch (error) {
2003
2114
  res.status(500).json({ error: error.message });
2004
2115
  }
@@ -2012,29 +2123,31 @@ async function startUIServer(noOpen = false, savePort = false) {
2012
2123
  return res.status(400).json({ error: '缺少文件路径参数' });
2013
2124
  }
2014
2125
 
2015
- // 检查是否是编译/压缩文件
2016
- const isCompiledFile = /\.(min\.js|umd\.cjs|bundle\.js|dist\.js|prod\.js)$/i.test(filePath);
2017
- if (isCompiledFile) {
2126
+ const diffCommand = `git diff --cached -- "${filePath}"`;
2127
+
2128
+ // 使用优化的检查函数
2129
+ const skipCheck = await checkShouldSkipDiff(filePath, diffCommand);
2130
+ if (skipCheck.shouldSkip) {
2018
2131
  return res.json({
2019
- diff: '⚠️ 检测到编译/打包文件,diff内容过大已跳过显示。\n\n提示:这类文件通常是自动生成的,不建议查看diff。\n如需查看,请使用命令行:git diff --cached -- "' + filePath + '"',
2020
- isLargeFile: true
2132
+ diff: skipCheck.reason,
2133
+ isLargeFile: true,
2134
+ stats: skipCheck.stats
2021
2135
  });
2022
2136
  }
2023
2137
 
2024
2138
  // 执行git diff --cached命令获取已暂存文件差异
2025
- const { stdout } = await execGitCommand(`git diff --cached -- "${filePath}"`);
2139
+ const { stdout } = await execGitCommand(diffCommand);
2026
2140
 
2027
- // 检查diff大小
2028
- const diffSizeKB = Buffer.byteLength(stdout, 'utf8') / 1024;
2029
- if (diffSizeKB > 500) {
2030
- return res.json({
2031
- diff: `⚠️ Diff内容过大 (${diffSizeKB.toFixed(1)}KB),已跳过显示以避免浏览器卡顿。\n\n提示:请使用命令行查看:git diff --cached -- "${filePath}"`,
2032
- isLargeFile: true,
2033
- size: diffSizeKB
2034
- });
2141
+ // 检查实际diff大小
2142
+ const sizeCheck = checkDiffSize(stdout, 500);
2143
+ if (sizeCheck) {
2144
+ return res.json(sizeCheck);
2035
2145
  }
2036
2146
 
2037
- res.json({ diff: stdout });
2147
+ // 统计增加和删除行数
2148
+ const stats = getDiffStats(stdout);
2149
+
2150
+ res.json({ diff: stdout, stats });
2038
2151
  } catch (error) {
2039
2152
  res.status(500).json({ error: error.message });
2040
2153
  }
@@ -2247,18 +2360,40 @@ async function startUIServer(noOpen = false, savePort = false) {
2247
2360
 
2248
2361
  console.log(`获取提交文件差异: hash=${hash}, file=${filePath}`);
2249
2362
 
2250
- // 执行命令获取文件差异,-p显示补丁,限定文件路径
2251
- const { stdout } = await execGitCommand(`git show ${hash} -- "${filePath}"`);
2363
+ const diffCommand = `git show ${hash} -- "${filePath}"`;
2364
+
2365
+ // 使用优化的检查函数
2366
+ const skipCheck = await checkShouldSkipDiff(filePath, diffCommand);
2367
+ if (skipCheck.shouldSkip) {
2368
+ return res.json({
2369
+ success: true,
2370
+ diff: skipCheck.reason,
2371
+ isLargeFile: true,
2372
+ stats: skipCheck.stats
2373
+ });
2374
+ }
2375
+
2376
+ // 执行命令获取文件差异
2377
+ const { stdout } = await execGitCommand(diffCommand);
2252
2378
 
2253
2379
  console.log(`获取到差异内容,长度: ${stdout.length}`);
2254
- // 如果差异内容太长,只打印前100个字符
2255
- if (stdout.length > 100) {
2256
- console.log(`差异内容预览: ${stdout.substring(0, 100)}...`);
2380
+
2381
+ // 检查实际diff大小
2382
+ const sizeCheck = checkDiffSize(stdout, 500);
2383
+ if (sizeCheck) {
2384
+ return res.json({
2385
+ success: true,
2386
+ ...sizeCheck
2387
+ });
2257
2388
  }
2258
2389
 
2390
+ // 统计增加和删除行数
2391
+ const stats = getDiffStats(stdout);
2392
+
2259
2393
  res.json({
2260
2394
  success: true,
2261
- diff: stdout
2395
+ diff: stdout,
2396
+ stats
2262
2397
  });
2263
2398
  } catch (error) {
2264
2399
  console.error('获取提交文件差异失败:', error);
@@ -2862,8 +2997,26 @@ async function startUIServer(noOpen = false, savePort = false) {
2862
2997
  if (isFromThirdParent) {
2863
2998
  // 未跟踪文件:读取第三父中的内容,构造新增文件的统一diff
2864
2999
  const { stdout: blob } = await execGitCommand(`git show ${parent3}:"${file}"`, { log: false });
3000
+
3001
+ // 检查文件大小
3002
+ const sizeCheck = checkDiffSize(blob, 500);
3003
+ if (sizeCheck) {
3004
+ return res.json({ success: true, ...sizeCheck });
3005
+ }
3006
+
2865
3007
  const lines = blob.endsWith('\n') ? blob.slice(0, -1).split('\n') : blob.split('\n');
2866
- const lineCount = lines.filter(() => true).length; // 保持计数正确
3008
+ const lineCount = lines.length;
3009
+
3010
+ // 检查行数
3011
+ if (lineCount > 10000) {
3012
+ return res.json({
3013
+ success: true,
3014
+ diff: `⚠️ 变更内容过大 (${lineCount.toLocaleString()} 行),diff已跳过显示以避免浏览器卡顿。\n\n提示:建议使用命令行查看大文件变更。`,
3015
+ isLargeFile: true,
3016
+ stats: { added: lineCount, deleted: 0, total: lineCount }
3017
+ });
3018
+ }
3019
+
2867
3020
  const plusLines = lines.map(l => `+${l}`).join('\n');
2868
3021
  const diffText = [
2869
3022
  `diff --git a/${file} b/${file}`,
@@ -2877,15 +3030,34 @@ async function startUIServer(noOpen = false, savePort = false) {
2877
3030
  return res.json({ success: true, diff: diffText });
2878
3031
  }
2879
3032
 
2880
- // 否则,使用原有方式获取与父1的变更(直接针对 stash 提交显示该文件的变化)
2881
- const { stdout } = await execGitCommand(`git show ${stashCommit} -- "${file}"`);
3033
+ // 否则,使用原有方式获取与父1的变更
3034
+ const diffCommand = `git show ${stashCommit} -- "${file}"`;
3035
+
3036
+ // 使用优化的检查函数
3037
+ const skipCheck = await checkShouldSkipDiff(file, diffCommand);
3038
+ if (skipCheck.shouldSkip) {
3039
+ return res.json({
3040
+ success: true,
3041
+ diff: skipCheck.reason,
3042
+ isLargeFile: true,
3043
+ stats: skipCheck.stats
3044
+ });
3045
+ }
3046
+
3047
+ const { stdout } = await execGitCommand(diffCommand);
2882
3048
 
2883
3049
  console.log(`获取到差异内容,长度: ${stdout.length}`);
2884
- if (stdout.length > 100) {
2885
- console.log(`差异内容预览: ${stdout.substring(0, 100)}...`);
3050
+
3051
+ // 检查实际diff大小
3052
+ const sizeCheck = checkDiffSize(stdout, 500);
3053
+ if (sizeCheck) {
3054
+ return res.json({ success: true, ...sizeCheck });
2886
3055
  }
2887
3056
 
2888
- res.json({ success: true, diff: stdout });
3057
+ // 统计增加和删除行数
3058
+ const stats = getDiffStats(stdout);
3059
+
3060
+ res.json({ success: true, diff: stdout, stats });
2889
3061
  } catch (error) {
2890
3062
  console.error('获取stash文件差异失败:', error);
2891
3063
  res.status(500).json({