fix(desktop): retain unsupported filename coverage

Fixes #6665
This commit is contained in:
morluto
2026-10-23 21:07:20 +08:00
parent 47900f99c5
commit 992e930b86
4 changed files with 38 additions and 0 deletions
+2
View File
@@ -155,6 +155,8 @@ export interface ArtifactTraversalOmission {
export interface ArtifactReaderTraversal {
readonly status: ArtifactInventoryCoverage["status"];
readonly limitations: readonly string[];
/** Number of directory entries examined, including names omitted before decoding. */
readonly examinedEntries?: number;
}
/** Per-iterator observation sink; adapters report intentional omissions without shared state. */
@@ -271,6 +271,12 @@ const scanDirectory = async (
kind: omission.kind,
});
},
onCoverage: (coverage) => {
if (coverage.examinedEntries !== undefined)
entries = coverage.examinedEntries;
if (coverage.status !== "complete") partial = true;
limitations.push(...coverage.limitations);
},
})) {
entries++;
abortIfNeeded(signal);
+1
View File
@@ -132,6 +132,7 @@ export class DirectoryArtifactReader implements ArtifactReader {
if (unrepresentableNameCount > 0)
options?.onCoverage?.({
status: "unknown",
examinedEntries: examined,
limitations: [
`Directory contains ${String(unrepresentableNameCount)} entry name(s) that are not valid UTF-8; no filesystem operations were performed for them. First raw basename bytes: ${firstUnrepresentableNameHex ?? "unknown"}.`,
],
@@ -53,6 +53,35 @@ const put = async (root: string, path: string, bytes: Buffer | string) => {
await writeFile(destination, bytes);
};
it.skipIf(process.platform !== "linux")(
"keeps desktop sibling files with partial coverage for invalid UTF-8 names",
async () => {
const root = await createTestTempDirectory("rea-desktop-filename-bytes-");
const rawName = Buffer.from([
0x62, 0x61, 0x64, 0xff, 0x2e, 0x74, 0x78, 0x74,
]);
const rawPath = Buffer.concat([Buffer.from(`${root}/`), rawName]);
await Promise.all([
writeFile(rawPath, "RAW_FILE"),
writeFile(join(root, "bad\ufffd.txt"), "UNICODE_FILE"),
writeFile(join(root, "good.txt"), "GOOD_FILE"),
]);
const { report } = await inspect(root);
expect(report.coverage).toMatchObject({
status: "partial",
entries_examined: 3,
});
expect(
report.files.filter(({ path }) => path === "bad\ufffd.txt"),
).toHaveLength(1);
expect(report.files.map(({ path }) => path)).toContain("good.txt");
expect(report.limitations.join(" ")).toContain(
`First raw basename bytes: ${rawName.toString("hex")}`,
);
},
);
it("joins real PE/CLI reference facts and independent engine markers without picking a winner", async () => {
const root = await createTestTempDirectory("rea-desktop-mixed-");
await put(