File size: 1,978 Bytes
24a2ddf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
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
/**
 * 递归对比两个目录,列出差异文件(排除 node_modules/.git/dist 等)。
 * 用法: node compare-dirs.js <dirA> <dirB>
 */
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');

const EXCLUDE_DIRS = new Set(['node_modules', '.git', 'temp', 'test-results', 'make', 'dist', 'tools', 'tests', 'stress', 'hf-trend', '.sisyphus', '.opencode', 'output', 'test-outputs']);
const EXCLUDE_FILES = new Set(['PERFORMANCE_ANALYSIS.md', 'PERFORMANCE_STRESS_TEST_2026-08-03.md', 'HF_TOKEN.md']);

const [A, B] = process.argv.slice(2);
if (!A || !B) { console.error('need two dirs'); process.exit(1); }

const md5 = (p) => crypto.createHash('md5').update(fs.readFileSync(p)).digest('hex');

function walk(d, base) {
  const out = new Map();
  if (!fs.existsSync(d)) return out;
  for (const f of fs.readdirSync(d)) {
    const fp = path.join(d, f);
    if (fs.statSync(fp).isDirectory()) {
      if (EXCLUDE_DIRS.has(f)) continue;
      for (const [rel, h] of walk(fp, base)) out.set(rel, h);
    } else {
      if (EXCLUDE_FILES.has(f)) continue;
      const rel = path.relative(base, fp).replace(/\\/g, '/');
      out.set(rel, md5(fp));
    }
  }
  return out;
}

const mapA = walk(A, A);
const mapB = walk(B, B);

const all = new Set([...mapA.keys(), ...mapB.keys()]);
const changed = [];
const onlyA = [];
const onlyB = [];
for (const rel of all) {
  const ha = mapA.get(rel);
  const hb = mapB.get(rel);
  if (ha && hb) { if (ha !== hb) changed.push(rel); }
  else if (ha && !hb) onlyA.push(rel);
  else onlyB.push(rel);
}

changed.sort(); onlyA.sort(); onlyB.sort();
console.log(`=== A=${A}`);
console.log(`=== B=${B}`);
console.log(`\n[不同内容] ${changed.length} 个:`);
for (const f of changed) console.log(`  M  ${f}`);
console.log(`\n[仅 A 有] ${onlyA.length} 个:`);
for (const f of onlyA) console.log(`  A  ${f}`);
console.log(`\n[仅 B 有] ${onlyB.length} 个:`);
for (const f of onlyB) console.log(`  B  ${f}`);