fix(apple): exclude AppleDouble sidecars from IPA components (#2838)

* fix(apple): exclude AppleDouble sidecars from IPA components

IPA projection returned every inventoried component before the AppleDouble
sidecar filter applied to directory, ZIP and DMG roots, so ._* and
__MACOSX/ metadata appeared as native libraries and frameworks while the
result reported that sidecars are excluded. Apply the sidecar exclusion
first for every root format; IPA still keeps non-sidecar components
outside Payload/.

Fixes #2546

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(apple): exercise the __MACOSX exclusion with a non-dotfile name

The IPA fixture's __MACOSX entry also started with "._", so the AppleDouble
filename rule excluded it and a broken __MACOSX check would go unnoticed.
Use a library name that only the __MACOSX rule excludes; the native
library assertion now fails if that rule regresses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
yasshmittalandClaude Opus 5.5 authored and GitHub committed 2026-10-13 22:55:21 +08:00
1 parent 94072364c7
commit e13da084e7
2 files changed
+32 -3

No files matched your search

+28
View File
@@ -417,6 +417,34 @@ describe("Apple bundle layouts and containers", () => {
});
});
describe("Apple IPA components", () => {
it("excludes AppleDouble sidecars from IPA components", () => {
const result = project(
inventoryEvidence("ipa", "Fixture.ipa", [
{ path: "Payload/Fixture.app/Info.plist" },
macho("Payload/Fixture.app/Fixture"),
{ path: "Payload/Fixture.app/Contents/Resources/._libfoo.dylib" },
{ path: "Payload/Fixture.app/Frameworks/Foo.framework/._Foo" },
{ path: "__MACOSX/Payload/Fixture.app/libghost.dylib" },
macho("Payload/Fixture.app/Contents/Resources/libreal.dylib"),
macho("SwiftSupport/iphoneos/libswiftCore.dylib"),
]),
);
expect(result.components.native_libraries.map(({ path }) => path)).toEqual([
"Payload/Fixture.app/Contents/Resources/libreal.dylib",
"SwiftSupport/iphoneos/libswiftCore.dylib",
]);
expect(result.components.frameworks).toEqual([]);
expect(result.components.executables.map(({ path }) => path)).toEqual([
"Payload/Fixture.app/Contents/Resources/libreal.dylib",
"Payload/Fixture.app/Fixture",
]);
expect(result.limitations).toContainEqual(
expect.stringContaining("AppleDouble sidecar entries"),
);
});
});
describe("macOS application scope", () => {
it("attributes only components inside the application roots", () => {
const result = project(
+4 -3
View File
@@ -218,8 +218,9 @@ export const appleProjectionId = (projection: unknown): string =>
`aap_${digest(projection)}`;
/**
* IPA projection keeps every archive component, as before. Directory, ZIP,
* and DMG inventories can hold installers and other siblings, so only
* AppleDouble sidecars describe neighbouring files and are never components.
* IPA projection keeps every other archive component, as before. Directory,
* ZIP, and DMG inventories can hold installers and other siblings, so only
* components inside an application root are attributed to it.
*/
const attributeComponents = (
@@ -227,8 +228,8 @@ const attributeComponents = (
roots: readonly string[],
rootFormat: RootFormat,
): { readonly all: Component[]; readonly unattributed: number } => {
if (rootFormat === "ipa") return { all: [...inventoried], unattributed: 0 };
const visible = inventoried.filter(({ path }) => !isSidecar(path));
if (rootFormat === "ipa") return { all: visible, unattributed: 0 };
const all = visible.filter(({ path }) =>
roots.some((root) => isWithin(path, root)),
);