mirror of
https://github.com/morluto/rea.git
synced 2026-11-14 02:32:54 +00:00
* feat(artifacts): read Godot PCK packs Add a Godot Engine PCK artifact reader for standalone packs and packs embedded behind an executable trailer (formats 2 and 3). Members are uncompressed byte ranges verified against their declared MD5 on read. Encrypted directories, sparse bundles, patch removal entries, unknown flags and format 1 fail closed as unavailable; encrypted members are reported without being read. inspect-artifact and extract-artifact recognize standalone packs by their GDPC magic. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(artifacts): bound Godot PCK metadata and own member streams Cap member paths at 4096 bytes and the retained directory at 64 MiB before allocation. Read members with positional chunk reads through pipeline so cancellation is typed, abandoned consumers release their source, and the shared descriptor stays reader-owned. Retain the root descriptor for godot-pck inventory, as for ZIP and universal Mach-O. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(artifacts): complete Godot PCK facts, integrity and selected views * fix(artifacts): preserve atomic-root inventory Evidence * fix(artifacts): bound aggregate PCK member expansion --------- Co-authored-by: Samucahub <151155051+Samucahub@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
102 lines
3.5 KiB
TypeScript
102 lines
3.5 KiB
TypeScript
import { AsarArtifactReader } from "../AsarArtifactReader.js";
|
|
import type {
|
|
ArtifactReader,
|
|
ArtifactReaderTraversal,
|
|
} from "../ArtifactReader.js";
|
|
import { DirectoryArtifactReader } from "../DirectoryArtifactReader.js";
|
|
import { GodotPckArtifactReader } from "../GodotPckArtifactReader.js";
|
|
import { MachOSliceArtifactReader } from "../MachOSliceArtifactReader.js";
|
|
import { NativeDmgArtifactReader } from "../NativeDmgArtifactReader.js";
|
|
import { ZipArtifactReader } from "../ZipArtifactReader.js";
|
|
import type {
|
|
ArtifactInventoryCoverage,
|
|
ArtifactOccurrence,
|
|
} from "../../domain/artifactGraph.js";
|
|
import {
|
|
isZipPackageFormat,
|
|
ZIP_NON_ENTRY_LIMITATION,
|
|
} from "../../domain/zipPackageFormat.js";
|
|
import type { StableRegularFileDescriptor } from "../../filesystem/RegularFile.js";
|
|
|
|
export const createReader = (
|
|
path: string,
|
|
format: ArtifactOccurrence["artifact_format"],
|
|
environment: Readonly<NodeJS.ProcessEnv>,
|
|
rootSource?: StableRegularFileDescriptor,
|
|
): ArtifactReader | undefined => {
|
|
if (isZipPackageFormat(format))
|
|
return new ZipArtifactReader(path, format, undefined, rootSource);
|
|
switch (format) {
|
|
case "directory":
|
|
return new DirectoryArtifactReader(path);
|
|
case "asar":
|
|
return new AsarArtifactReader(path);
|
|
case "godot-pck":
|
|
return new GodotPckArtifactReader(path, rootSource);
|
|
case "mach-o-universal":
|
|
return process.platform === "darwin"
|
|
? new MachOSliceArtifactReader(path, environment, undefined, rootSource)
|
|
: undefined;
|
|
case "dmg":
|
|
if (process.platform !== "darwin") return undefined;
|
|
return new NativeDmgArtifactReader(path, environment);
|
|
default:
|
|
return undefined;
|
|
}
|
|
};
|
|
|
|
/** Decide traversal scope and availability once, independently of diagnostic wording. */
|
|
export const inventoryCoverage = (
|
|
format: ArtifactOccurrence["artifact_format"],
|
|
reader: ArtifactReader | undefined,
|
|
traversal: ArtifactReaderTraversal,
|
|
): {
|
|
readonly coverage: ArtifactInventoryCoverage;
|
|
readonly limitations: string[];
|
|
} => {
|
|
if (reader !== undefined)
|
|
return {
|
|
coverage: { scope: "container-entries", status: traversal.status },
|
|
limitations: [
|
|
...(isZipPackageFormat(reader.format)
|
|
? [ZIP_NON_ENTRY_LIMITATION]
|
|
: []),
|
|
...(reader.format === "godot-pck"
|
|
? [
|
|
"PCK inventory establishes packaged bytes and metadata; scenes, binary resources, GDScript bytecode and runtime signal behavior were not decoded.",
|
|
]
|
|
: []),
|
|
...traversal.limitations,
|
|
],
|
|
};
|
|
// dmg and pkg reach here only after classifyRootFormat matched their bytes.
|
|
if (format === "dmg" || format === "pkg")
|
|
return {
|
|
coverage: { scope: "container-entries", status: "unknown" },
|
|
limitations: [
|
|
`${format.toUpperCase()} root hash is observed; child inventory requires a native macOS adapter.`,
|
|
],
|
|
};
|
|
if (format === "mach-o-universal")
|
|
return {
|
|
coverage: { scope: "container-entries", status: "unknown" },
|
|
limitations: [
|
|
"Universal Mach-O slices require the native macOS lipo adapter.",
|
|
],
|
|
};
|
|
if (
|
|
isZipPackageFormat(format) ||
|
|
format === "directory" ||
|
|
format === "asar" ||
|
|
format === "godot-pck"
|
|
)
|
|
return {
|
|
coverage: { scope: "container-entries", status: "unknown" },
|
|
limitations: [`${format} child inventory reader is unavailable.`],
|
|
};
|
|
return {
|
|
coverage: { scope: "root", status: "complete" },
|
|
limitations: ["Artifact has no child container entries."],
|
|
};
|
|
};
|