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.
- package/README.md +148 -148
- package/package.json +1 -1
- package/src/ui/public/assets/index-DhhwG1j0.css +1 -0
- package/src/ui/public/assets/index-DkDsLMia.js +59 -0
- package/src/ui/public/assets/vendor-D9qDBEE1.css +1 -0
- package/src/ui/public/assets/vendor-DBEYYHfT.js +68 -0
- package/src/ui/public/index.html +4 -4
- package/src/ui/server/index.js +214 -42
- package/src/ui/public/assets/index-6Nf0Jabf.css +0 -1
- package/src/ui/public/assets/index-B8Tdx6e-.js +0 -59
- package/src/ui/public/assets/vendor-C0dfGhZ-.js +0 -75
- package/src/ui/public/assets/vendor-HJmoQ7iQ.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 - Git同步工具</title>
|
|
9
|
-
<script type="module" crossorigin src="/assets/index-
|
|
10
|
-
<link rel="modulepreload" crossorigin href="/assets/vendor-
|
|
11
|
-
<link rel="stylesheet" crossorigin href="/assets/vendor-
|
|
12
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
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>
|
package/src/ui/server/index.js
CHANGED
|
@@ -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
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
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:
|
|
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(
|
|
2101
|
+
const { stdout } = await execGitCommand(diffCommand);
|
|
1990
2102
|
|
|
1991
|
-
//
|
|
1992
|
-
const
|
|
1993
|
-
if (
|
|
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
|
-
|
|
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
|
-
|
|
2017
|
-
|
|
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:
|
|
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(
|
|
2139
|
+
const { stdout } = await execGitCommand(diffCommand);
|
|
2026
2140
|
|
|
2027
|
-
//
|
|
2028
|
-
const
|
|
2029
|
-
if (
|
|
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
|
-
|
|
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
|
-
|
|
2251
|
-
|
|
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
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
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.
|
|
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
|
|
2881
|
-
const
|
|
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
|
-
|
|
2885
|
-
|
|
3050
|
+
|
|
3051
|
+
// 检查实际diff大小
|
|
3052
|
+
const sizeCheck = checkDiffSize(stdout, 500);
|
|
3053
|
+
if (sizeCheck) {
|
|
3054
|
+
return res.json({ success: true, ...sizeCheck });
|
|
2886
3055
|
}
|
|
2887
3056
|
|
|
2888
|
-
|
|
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({
|