Files
stockfill/scripts/merge-lcov.cjs
T
beatzaplenty 6192bd20eb modified: .gitignore
modified:   .vscode/launch.json
	new file:   e2e/playwright-collect-coverage.spec.ts
	modified:   package-lock.json
	modified:   package.json
	modified:   playwright.config.ts
	new file:   scripts/merge-lcov.cjs
	new file:   scripts/normalize-lcov.cjs
	new file:   scripts/playwright-collect-coverage.cjs
	new file:   scripts/remap-and-report.cjs
	modified:   vite.config.ts
	new file:   vitest.config.ts
2025-12-02 16:14:12 +10:00

65 lines
1.8 KiB
JavaScript
Executable File

#!/usr/bin/env node
'use strict';
const fs = require('fs');
const files = process.argv.slice(2);
if (files.length < 2) {
console.error('Usage: node merge-lcov.cjs <file1.lcov> <file2.lcov> [<file3.lcov> ...]');
process.exit(2);
}
function ensureEntry(map, sf) {
if (!map.has(sf)) map.set(sf, { other: new Set(), da: new Map() });
return map.get(sf);
}
const combined = new Map();
for (const f of files) {
let content;
try {
content = fs.readFileSync(f, 'utf8');
} catch (err) {
console.error('Could not read', f, err.message);
process.exit(3);
}
const lines = content.split(/\r?\n/);
let currentSF = null;
for (let raw of lines) {
const line = raw.trim();
if (!line) continue;
if (line.startsWith('SF:')) {
currentSF = line.slice(3);
ensureEntry(combined, currentSF);
} else if (!currentSF) {
// ignore lines before first SF
} else if (line.startsWith('DA:')) {
const parts = line.slice(3).split(',');
const lnNum = parseInt(parts[0], 10);
const hitsNum = parseInt(parts[1] || '0', 10);
const entry = ensureEntry(combined, currentSF);
entry.da.set(lnNum, (entry.da.get(lnNum) || 0) + hitsNum);
} else if (line.startsWith('end_of_record')) {
// ignore
} else {
const entry = ensureEntry(combined, currentSF);
entry.other.add(line);
}
}
}
let out = '';
for (const [sf, data] of combined.entries()) {
out += `SF:${sf}\n`;
const other = Array.from(data.other).sort();
for (const l of other) out += l + '\n';
const daEntries = Array.from(data.da.entries()).sort((a, b) => a[0] - b[0]);
for (const [ln, hits] of daEntries) out += `DA:${ln},${hits}\n`;
const lf = daEntries.length;
const lh = daEntries.reduce((acc, [, hits]) => acc + (hits > 0 ? 1 : 0), 0);
out += `LF:${lf}\nLH:${lh}\nend_of_record\n`;
}
process.stdout.write(out);