@@ -2,6 +2,7 @@ import { lstat, readFile, realpath } from "node:fs/promises";
22import { dirname , resolve } from "node:path" ;
33import { parse as parsePbxProject } from "@bacons/xcode/json" ;
44import { decodePublishableKey } from "../../../lib/fapi.ts" ;
5+ import { readBoundedRegularFile } from "./bounded-file.ts" ;
56import { inspectTargetBuildConfigurations } from "./build-settings.ts" ;
67import {
78 discoverLocalIOSProjects ,
@@ -249,20 +250,46 @@ async function inspectEntitlementsFile(
249250 } ;
250251 }
251252
252- try {
253- const info = await lstat ( absolutePath ) ;
254- if ( ! info . isFile ( ) || info . isSymbolicLink ( ) || info . size > MAX_ENTITLEMENTS_BYTES ) {
255- return {
256- blocker : blocker (
257- "unsupported-entitlements" ,
258- `${ relativeIOSPath (
259- root ,
260- absolutePath ,
261- ) } must be a regular, non-symlink XML plist no larger than 1 MB.`,
262- ) ,
263- } ;
253+ const file = await readBoundedRegularFile ( absolutePath , MAX_ENTITLEMENTS_BYTES ) ;
254+ if ( file . status === "not-regular" || file . status === "too-large" ) {
255+ return {
256+ blocker : blocker (
257+ "unsupported-entitlements" ,
258+ `${ relativeIOSPath (
259+ root ,
260+ absolutePath ,
261+ ) } must be a regular, non-symlink XML plist no larger than 1 MB.`,
262+ ) ,
263+ } ;
264+ }
265+ if ( file . status !== "ok" ) {
266+ try {
267+ const info = await lstat ( absolutePath ) ;
268+ if ( ! info . isFile ( ) || info . isSymbolicLink ( ) || info . size > MAX_ENTITLEMENTS_BYTES ) {
269+ return {
270+ blocker : blocker (
271+ "unsupported-entitlements" ,
272+ `${ relativeIOSPath (
273+ root ,
274+ absolutePath ,
275+ ) } must be a regular, non-symlink XML plist no larger than 1 MB.`,
276+ ) ,
277+ } ;
278+ }
279+ } catch {
280+ // Preserve the unreadable classification below when the current path
281+ // cannot explain the bounded reader's failure.
264282 }
265- const bytes = new Uint8Array ( await readFile ( absolutePath ) ) ;
283+ return {
284+ blocker : blocker (
285+ "unreadable-entitlements" ,
286+ `${ relativeIOSPath ( root , absolutePath ) } could not be read as a UTF-8 XML plist dictionary.` ,
287+ ) ,
288+ } ;
289+ }
290+
291+ try {
292+ const bytes = file . bytes ;
266293 if ( new TextDecoder ( ) . decode ( bytes . slice ( 0 , 8 ) ) . startsWith ( "bplist" ) ) {
267294 return {
268295 blocker : blocker (
@@ -330,7 +357,7 @@ async function inspectEntitlementsFile(
330357 relativePath : relativeIOSPath ( root , absolutePath ) ,
331358 bytes,
332359 hash : hashIOSFileBytes ( bytes ) ,
333- mode : info . mode & 0o7777 ,
360+ mode : file . mode ,
334361 source,
335362 bom,
336363 domains,
@@ -866,17 +893,9 @@ export async function prepareIOSAssociatedDomainMutation(
866893 }
867894 continue ;
868895 }
869- try {
870- if ( ! plannedFile . expectedHash ) return { status : "blocked" , plan } ;
871- const info = await lstat ( absolutePath ) ;
872- if (
873- ! info . isFile ( ) ||
874- info . isSymbolicLink ( ) ||
875- hashIOSFileBytes ( await readFile ( absolutePath ) ) !== plannedFile . expectedHash
876- ) {
877- return { status : "stale" , plan } ;
878- }
879- } catch {
896+ if ( ! plannedFile . expectedHash ) return { status : "blocked" , plan } ;
897+ const current = await readBoundedRegularFile ( absolutePath , MAX_ENTITLEMENTS_BYTES ) ;
898+ if ( current . status !== "ok" || hashIOSFileBytes ( current . bytes ) !== plannedFile . expectedHash ) {
880899 return { status : "stale" , plan } ;
881900 }
882901 }
0 commit comments