fix: prevent double-counting orphaned pages in conflicting scenarios

This commit is contained in:
meels
2026-07-28 13:17:51 +02:00
parent 80ef971d1a
commit 7958d225d5
2 changed files with 19 additions and 3 deletions

View File

@@ -49,10 +49,15 @@ function derivePipeline({ rawFiles, sourcePages }) {
else unprocessed.push(file); else unprocessed.push(file);
} }
// One pass over sourcePages, so a page appears in `orphaned` at most once no
// matter how many of the three reasons apply to it. Concatenating a separate
// duplicates array here would double-count a losing claimant whose shared raw
// path is also missing from disk.
const rawPaths = new Set(rawFiles.map((f) => f.path)); const rawPaths = new Set(rawFiles.map((f) => f.path));
const orphaned = sourcePages const duplicateSet = new Set(duplicates);
.filter((p) => !p.rawPath || !rawPaths.has(p.rawPath)) const orphaned = sourcePages.filter(
.concat(duplicates); (p) => duplicateSet.has(p) || !p.rawPath || !rawPaths.has(p.rawPath)
);
unprocessed.sort((a, b) => a.name.localeCompare(b.name)); unprocessed.sort((a, b) => a.name.localeCompare(b.name));
processed.sort((a, b) => b.page.name.localeCompare(a.page.name)); processed.sort((a, b) => b.page.name.localeCompare(a.page.name));

View File

@@ -82,6 +82,17 @@ test("derivePipeline routes a duplicate raw-path claim to orphaned", () => {
assert.deepEqual(out.orphaned.map((p) => p.name), ["second.md"]); assert.deepEqual(out.orphaned.map((p) => p.name), ["second.md"]);
}); });
test("derivePipeline lists a page once when it is both a duplicate claim and missing its raw file", () => {
const out = derivePipeline({
rawFiles: [{ path: "raw/sources/other.md", name: "other.md", size: 10 }],
sourcePages: [
{ path: "wiki/sources/first.md", name: "first.md", rawPath: "raw/sources/gone.md" },
{ path: "wiki/sources/second.md", name: "second.md", rawPath: "raw/sources/gone.md" },
],
});
assert.deepEqual(out.orphaned.map((p) => p.name), ["first.md", "second.md"]);
});
test("derivePipeline sorts unprocessed by name and processed newest first", () => { test("derivePipeline sorts unprocessed by name and processed newest first", () => {
const out = derivePipeline({ const out = derivePipeline({
rawFiles: [ rawFiles: [