diff --git a/src/domain/apple/appleApplication.test.ts b/src/domain/apple/appleApplication.test.ts index 9caf21fcbb..3f8906e2b8 100644 --- a/src/domain/apple/appleApplication.test.ts +++ b/src/domain/apple/appleApplication.test.ts @@ -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( diff --git a/src/domain/apple/appleApplication.ts b/src/domain/apple/appleApplication.ts index d46ddf26b0..dfb34e3c54 100644 --- a/src/domain/apple/appleApplication.ts +++ b/src/domain/apple/appleApplication.ts @@ -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)), );