diff --git a/src/server/merge.js b/src/server/merge.js index dece0eb..99ec971 100644 --- a/src/server/merge.js +++ b/src/server/merge.js @@ -336,12 +336,15 @@ export class Merger { batch.id, ).map((r) => r.name); const identicalCount = results.filter((r) => !r.peerConfirmed).length; - const title = - results.length === 1 - ? `Decompile ${results[0].id}${results[0].name ? ` (${results[0].name})` : ''}` - : `Decompile ${results.length} functions in ${[...new Set(Object.keys(files))].slice(0, 2).join(', ')}${Object.keys(files).length > 2 ? ', ...' : ''}`; const head = this.repo.head(); const change = (id) => this.codeChange(id, merged.files, head); + // Code that was already on main and is only confirmed now (often ported before the migration) + // is not a decompilation; the diff then shows only what else the batch changed. + const verb = results.every((r) => change(r.id) === ' (already on main)') ? 'Confirm' : 'Decompile'; + const title = + results.length === 1 + ? `${verb} ${results[0].id}${results[0].name ? ` (${results[0].name})` : ''}` + : `${verb} ${results.length} functions in ${[...new Set(Object.keys(files))].slice(0, 2).join(', ')}${Object.keys(files).length > 2 ? ', ...' : ''}`; const lines = results.map((r) => `- ${r.id}${r.name ? ` ${r.name}` : ''}: ${r.peerConfirmed ? 'logic confirmed by peer review' : 'byte-identical'}${change(r.id)}`); const message = `${title}\n\nBatch #${batch.id} by ${author}: ${identicalCount} byte-identical, ${results.length - identicalCount} confirmed by peer review.\n\n${lines.join('\n')}\n` + diff --git a/src/server/split.js b/src/server/split.js index 20285ce..2a13f01 100644 --- a/src/server/split.js +++ b/src/server/split.js @@ -94,7 +94,11 @@ export function withoutFunctions(files, ids, baseText, { keepCode = false } = {} continue; } if (keepCode) { - const drop = mine.flatMap((r) => r.ids.filter((id) => pending.has(id)).map((id) => r.lines.get(id))).sort((a, b) => b - a); + // Annotations already on main stay (the function keeps being measured there); only the ones + // the submission added are taken out. + const base = baseText(file); + const onMain = new Set(base === null ? [] : [...(functionRegions(base) ?? new Map()).keys()]); + const drop = mine.flatMap((r) => r.ids.filter((id) => pending.has(id) && !onMain.has(id)).map((id) => r.lines.get(id))).sort((a, b) => b - a); const lines = text.split('\n'); for (const i of drop) lines.splice(i, 1); out[file] = lines.join('\n'); diff --git a/test/split.test.js b/test/split.test.js index 4c87a2a..c610586 100644 --- a/test/split.test.js +++ b/test/split.test.js @@ -54,3 +54,9 @@ test('keepCode keeps the pending code and drops only its annotations', () => { const out = withoutFunctions({ 'a.cpp': text }, ['fn_00001'], () => 'int helper() {\n return 1;\n}\n', { keepCode: true }); assert.equal(out['a.cpp'], 'int helper(int x) {\n return x;\n}\n\n// FUNCTION: fn_00002\nint user() {\n return helper(2);\n}\n'); }); + +test('keepCode leaves annotations that are already on main', () => { + const text = '// FUNCTION: fn_00001\nint helper(int x) {\n return x;\n}\n\n// FUNCTION: fn_00002\nint user() {\n return helper(2);\n}\n'; + const base = '// FUNCTION: fn_00001\nint helper() {\n return 1;\n}\n'; + assert.equal(withoutFunctions({ 'a.cpp': text }, ['fn_00001'], () => base, { keepCode: true })['a.cpp'], text); +});