mirror of
https://github.com/morluto/rea.git
synced 2026-11-04 22:06:10 +00:00
refactor(artifacts): retain PyInstaller carrier dialect
This commit is contained in:
1 parent
5b8e415483
commit
ee654e98a6
4 files changed
+121
-3
No files matched your search
@@ -323,7 +323,9 @@ export class PyInstallerArtifactReader implements ArtifactReader {
|
||||
await this.#openHandle(signal);
|
||||
const { handle, initial } = await this.#source.readSelectedPath();
|
||||
const size = initial.size;
|
||||
const pathDialect = await carrierPathDialect(handle, size, signal);
|
||||
const pathDialect =
|
||||
this.#admission?.carrierPathDialect ??
|
||||
(await carrierPathDialect(handle, size, signal));
|
||||
const cookie =
|
||||
this.#admission?.cookie ?? (await this.#cookie(handle, size, signal));
|
||||
this.#budget = artifactExpansionBudgetBytes(cookie.packageLength);
|
||||
|
||||
@@ -302,8 +302,15 @@ const classifyRootFormat = async (
|
||||
}
|
||||
const packaged = await embeddedProbes.pyInstaller();
|
||||
abortIfNeeded(signal);
|
||||
// A valid cookie also proves enough bytes for a thin Mach-O identity;
|
||||
// PE and universal Mach-O classification already require stronger proof.
|
||||
if (packaged !== undefined)
|
||||
return { kind: "pyinstaller", source, cookie: packaged };
|
||||
return {
|
||||
kind: "pyinstaller",
|
||||
source,
|
||||
cookie: packaged,
|
||||
carrierPathDialect: format === "pe" ? "windows" : "posix",
|
||||
};
|
||||
}
|
||||
return format;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { appendFile, writeFile } from "node:fs/promises";
|
||||
import { appendFile, lstat, writeFile } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import { expect, it, vi } from "vitest";
|
||||
import { createTestTempDirectory } from "../../../tests/fixtures/temporaryDirectory.js";
|
||||
@@ -6,6 +6,7 @@ import { withOwnedRegularFile } from "../../filesystem/OwnedRegularFile.js";
|
||||
import { ArtifactEmbeddedFormatProbes } from "../ArtifactEmbeddedFormatProbes.js";
|
||||
import { ArtifactResourceScope } from "../ArtifactResourceScope.js";
|
||||
import { inventoryArtifact } from "../inventory/ArtifactInventory.js";
|
||||
import { classifyAndHashRootForInventory } from "../inventory/classify.js";
|
||||
import { PyInstallerArtifactReader } from "../PyInstallerArtifactReader.js";
|
||||
import { cArchiveExecutable } from "./CArchive.fixture.js";
|
||||
import * as layout from "./CArchiveLayout.js";
|
||||
@@ -25,6 +26,110 @@ const fixture = () =>
|
||||
],
|
||||
});
|
||||
|
||||
it.each([
|
||||
{
|
||||
carrier: "elf",
|
||||
offset: undefined,
|
||||
dialect: "posix",
|
||||
path: String.raw`pkg\data.bin`,
|
||||
},
|
||||
{ carrier: "pe", offset: 64, dialect: "windows", path: "pkg/data.bin" },
|
||||
{ carrier: "pe", offset: 8190, dialect: "windows", path: "pkg/data.bin" },
|
||||
] as const)(
|
||||
"retains $carrier carrier dialect at offset $offset through member projection",
|
||||
async ({ carrier, offset, dialect, path: memberPath }) => {
|
||||
const root = await createTestTempDirectory(
|
||||
"rea-pyinstaller-carrier-admission-",
|
||||
);
|
||||
const path = join(root, "app");
|
||||
const sourceName = String.raw`pkg\data.bin`;
|
||||
await writeFile(
|
||||
path,
|
||||
cArchiveExecutable({
|
||||
carrier,
|
||||
...(offset === undefined ? {} : { peHeaderOffset: offset }),
|
||||
layout: "2.1",
|
||||
pythonVersion: 314,
|
||||
members: [
|
||||
{
|
||||
name: sourceName,
|
||||
typeCode: "x",
|
||||
payload: Buffer.from("fixture"),
|
||||
compress: false,
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
const resourceScope = new ArtifactResourceScope();
|
||||
try {
|
||||
const classified = await classifyAndHashRootForInventory(
|
||||
path,
|
||||
false,
|
||||
await lstat(path),
|
||||
{ resourceScope },
|
||||
);
|
||||
const admission = classified.readerAdmission;
|
||||
if (
|
||||
admission === undefined ||
|
||||
!("kind" in admission) ||
|
||||
admission.kind !== "pyinstaller"
|
||||
)
|
||||
throw new Error("Fixture did not produce a PyInstaller admission");
|
||||
expect(admission.carrierPathDialect).toBe(dialect);
|
||||
const reader = new PyInstallerArtifactReader(path, admission);
|
||||
try {
|
||||
if (classified.digest === null)
|
||||
throw new Error("Missing carrier digest");
|
||||
await reader.prepareContainer(classified.digest.sha256);
|
||||
const entries = [];
|
||||
for await (const entry of reader.entries()) entries.push(entry);
|
||||
expect(entries).toEqual([
|
||||
expect.objectContaining({
|
||||
path: memberPath,
|
||||
formatMetadata: expect.objectContaining({
|
||||
source_name: sourceName,
|
||||
}),
|
||||
}),
|
||||
]);
|
||||
} finally {
|
||||
await reader.close();
|
||||
}
|
||||
} finally {
|
||||
await resourceScope.close();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
it("preserves backslashes when a standalone archive has no recognized carrier", async () => {
|
||||
const root = await createTestTempDirectory(
|
||||
"rea-pyinstaller-unknown-carrier-",
|
||||
);
|
||||
const path = join(root, "app");
|
||||
const sourceName = String.raw`pkg\data.bin`;
|
||||
const bytes = cArchiveExecutable({
|
||||
layout: "2.1",
|
||||
pythonVersion: 314,
|
||||
members: [
|
||||
{
|
||||
name: sourceName,
|
||||
typeCode: "x",
|
||||
payload: Buffer.from("fixture"),
|
||||
compress: false,
|
||||
},
|
||||
],
|
||||
});
|
||||
bytes.fill(0, 0, 64);
|
||||
await writeFile(path, bytes);
|
||||
const reader = new PyInstallerArtifactReader(path);
|
||||
try {
|
||||
const entries = [];
|
||||
for await (const entry of reader.entries()) entries.push(entry);
|
||||
expect(entries.map((entry) => entry.path)).toEqual([sourceName]);
|
||||
} finally {
|
||||
await reader.close();
|
||||
}
|
||||
});
|
||||
|
||||
it("inventories members using the cookie discovered by root classification", async () => {
|
||||
const root = await createTestTempDirectory(
|
||||
"rea-pyinstaller-cookie-inventory-",
|
||||
@@ -66,6 +171,7 @@ it("rejects changed source before consuming an admitted cookie and leaves the bo
|
||||
kind: "pyinstaller",
|
||||
source,
|
||||
cookie,
|
||||
carrierPathDialect: "posix",
|
||||
});
|
||||
await appendFile(path, "changed");
|
||||
try {
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import type { StableRegularFileDescriptor } from "../../filesystem/RegularFile.js";
|
||||
import type { PyInstallerCookie } from "./CArchiveLayout.js";
|
||||
import type { CarrierPathDialect } from "./CArchiveMembers.js";
|
||||
|
||||
/** Validated cookie facts borrowed with the descriptor that produced them. */
|
||||
export interface PyInstallerAdmission {
|
||||
readonly kind: "pyinstaller";
|
||||
readonly source: StableRegularFileDescriptor;
|
||||
readonly cookie: PyInstallerCookie;
|
||||
/** Carrier interpretation retained by the classifier that admitted this source. */
|
||||
readonly carrierPathDialect?: CarrierPathDialect;
|
||||
}
|
||||
Reference in new issue
Block a user