@@ -3,6 +3,9 @@ import * as os from 'os';
3
3
import * as path from 'path' ;
4
4
import * as plist from 'plist' ;
5
5
import compareVersion from 'compare-version' ;
6
+ import pLimit from 'p-limit' ;
7
+
8
+ const limit = pLimit ( 20 ) ;
6
9
7
10
import {
8
11
debugLog ,
@@ -199,103 +202,128 @@ async function signApplication (opts: ValidatedSignOptions, identity: Identity)
199
202
return bDepth - aDepth ;
200
203
} ) ;
201
204
202
- for ( const filePath of [ ...children , opts . app ] ) {
203
- if ( shouldIgnoreFilePath ( filePath ) ) {
204
- debugLog ( 'Skipped... ' + filePath ) ;
205
- continue ;
206
- }
205
+ let filesByLength : any [ ] = [ ] ;
206
+ for ( let s of [ ...children , opts . app ] ) {
207
+ let len = s . split ( path . sep ) . length ;
207
208
208
- const perFileOptions = await mergeOptionsForFile (
209
- opts . optionsForFile ? opts . optionsForFile ( filePath ) : null ,
210
- defaultOptionsForFile ( filePath , opts . platform )
211
- ) ;
209
+ if ( filesByLength [ len ] === undefined )
210
+ filesByLength [ len ] = [ ] ;
212
211
213
- // preAutoEntitlements should only be applied to the top level app bundle.
214
- // Applying it other files will cause the app to crash and be rejected by Apple.
215
- if ( ! filePath . includes ( '.app/' ) ) {
216
- if ( opts . preAutoEntitlements === false ) {
217
- debugWarn ( 'Pre-sign operation disabled for entitlements automation.' ) ;
218
- } else {
219
- debugLog (
220
- 'Pre-sign operation enabled for entitlements automation with versions >= `1.1.1`:' ,
221
- '\n' ,
222
- '* Disable by setting `pre-auto-entitlements` to `false`.'
223
- ) ;
224
- if ( ! opts . version || compareVersion ( opts . version , '1.1.1' ) >= 0 ) {
225
- // Enable Mac App Store sandboxing without using temporary-exception, introduced in Electron v1.1.1. Relates to electron#5601
226
- const newEntitlements = await preAutoEntitlements ( opts , perFileOptions , {
227
- identity,
228
- provisioningProfile : opts . provisioningProfile
229
- ? await getProvisioningProfile ( opts . provisioningProfile , opts . keychain )
230
- : undefined
212
+ filesByLength [ len ] . push ( s ) ;
213
+ }
214
+ filesByLength . reverse ( ) ;
215
+
216
+ const signingPromises = filesByLength . map ( ( files ) => {
217
+ return {
218
+ files : files ,
219
+ run : async ( ) => await Promise . all (
220
+ files . map ( ( filePath : string ) => {
221
+ return limit ( async ( ) => {
222
+ if ( shouldIgnoreFilePath ( filePath ) ) {
223
+ debugLog ( 'Skipped... ' + filePath ) ;
224
+ return ;
225
+ }
226
+
227
+ const perFileOptions = await mergeOptionsForFile (
228
+ opts . optionsForFile ? opts . optionsForFile ( filePath ) : null ,
229
+ defaultOptionsForFile ( filePath , opts . platform )
230
+ ) ;
231
+
232
+ // preAutoEntitlements should only be applied to the top level app bundle.
233
+ // Applying it other files will cause the app to crash and be rejected by Apple.
234
+ if ( ! filePath . includes ( '.app/' ) ) {
235
+ if ( opts . preAutoEntitlements === false ) {
236
+ debugWarn ( 'Pre-sign operation disabled for entitlements automation.' ) ;
237
+ } else {
238
+ debugLog (
239
+ 'Pre-sign operation enabled for entitlements automation with versions >= `1.1.1`:' ,
240
+ '\n' ,
241
+ '* Disable by setting `pre-auto-entitlements` to `false`.'
242
+ ) ;
243
+ if ( ! opts . version || compareVersion ( opts . version , '1.1.1' ) >= 0 ) {
244
+ // Enable Mac App Store sandboxing without using temporary-exception, introduced in Electron v1.1.1. Relates to electron#5601
245
+ const newEntitlements = await preAutoEntitlements ( opts , perFileOptions , {
246
+ identity,
247
+ provisioningProfile : opts . provisioningProfile
248
+ ? await getProvisioningProfile ( opts . provisioningProfile , opts . keychain )
249
+ : undefined
250
+ } ) ;
251
+
252
+ // preAutoEntitlements may provide us new entitlements, if so we update our options
253
+ // and ensure that entitlements-loginhelper has a correct default value
254
+ if ( newEntitlements ) {
255
+ perFileOptions . entitlements = newEntitlements ;
256
+ }
257
+ }
258
+ }
259
+ }
260
+
261
+ debugLog ( 'Signing in parallel... ' + filePath ) ;
262
+
263
+ const perFileArgs = [ ...args ] ;
264
+
265
+ if ( perFileOptions . requirements ) {
266
+ if ( perFileOptions . requirements . charAt ( 0 ) === '=' ) {
267
+ perFileArgs . push ( `-r${ perFileOptions . requirements } ` ) ;
268
+ } else {
269
+ perFileArgs . push ( '--requirements' , perFileOptions . requirements ) ;
270
+ }
271
+ }
272
+ if ( perFileOptions . timestamp ) {
273
+ perFileArgs . push ( '--timestamp=' + perFileOptions . timestamp ) ;
274
+ } else {
275
+ perFileArgs . push ( '--timestamp' ) ;
276
+ }
277
+
278
+ let optionsArguments : string [ ] = [ ] ;
279
+
280
+ if ( perFileOptions . signatureFlags ) {
281
+ if ( Array . isArray ( perFileOptions . signatureFlags ) ) {
282
+ optionsArguments . push ( ...perFileOptions . signatureFlags ) ;
283
+ } else {
284
+ const flags = perFileOptions . signatureFlags . split ( ',' ) . map ( function ( flag ) {
285
+ return flag . trim ( ) ;
286
+ } ) ;
287
+ optionsArguments . push ( ...flags ) ;
288
+ }
289
+ }
290
+
291
+ if ( perFileOptions . hardenedRuntime || optionsArguments . includes ( 'runtime' ) ) {
292
+ // Hardened runtime since darwin 17.7.0 --> macOS 10.13.6
293
+ if ( compareVersion ( osRelease , '17.7.0' ) >= 0 ) {
294
+ optionsArguments . push ( 'runtime' ) ;
295
+ } else {
296
+ // Remove runtime if passed in with --signature-flags
297
+ debugLog (
298
+ 'Not enabling hardened runtime, current macOS version too low, requires 10.13.6 and higher'
299
+ ) ;
300
+ optionsArguments = optionsArguments . filter ( ( arg ) => {
301
+ return arg !== 'runtime' ;
302
+ } ) ;
303
+ }
304
+ }
305
+
306
+ if ( optionsArguments . length ) {
307
+ perFileArgs . push ( '--options' , [ ...new Set ( optionsArguments ) ] . join ( ',' ) ) ;
308
+ }
309
+
310
+ if ( perFileOptions . additionalArguments ) {
311
+ perFileArgs . push ( ...perFileOptions . additionalArguments ) ;
312
+ }
313
+
314
+ await execFileAsync (
315
+ 'codesign' ,
316
+ perFileArgs . concat ( '--entitlements' , perFileOptions . entitlements , filePath )
317
+ ) ;
231
318
} ) ;
232
-
233
- // preAutoEntitlements may provide us new entitlements, if so we update our options
234
- // and ensure that entitlements-loginhelper has a correct default value
235
- if ( newEntitlements ) {
236
- perFileOptions . entitlements = newEntitlements ;
237
- }
238
- }
239
- }
240
- }
241
-
242
- debugLog ( 'Signing... ' + filePath ) ;
243
-
244
- const perFileArgs = [ ...args ] ;
245
-
246
- if ( perFileOptions . requirements ) {
247
- if ( perFileOptions . requirements . charAt ( 0 ) === '=' ) {
248
- perFileArgs . push ( `-r${ perFileOptions . requirements } ` ) ;
249
- } else {
250
- perFileArgs . push ( '--requirements' , perFileOptions . requirements ) ;
251
- }
252
- }
253
- if ( perFileOptions . timestamp ) {
254
- perFileArgs . push ( '--timestamp=' + perFileOptions . timestamp ) ;
255
- } else {
256
- perFileArgs . push ( '--timestamp' ) ;
257
- }
258
-
259
- let optionsArguments : string [ ] = [ ] ;
260
-
261
- if ( perFileOptions . signatureFlags ) {
262
- if ( Array . isArray ( perFileOptions . signatureFlags ) ) {
263
- optionsArguments . push ( ...perFileOptions . signatureFlags ) ;
264
- } else {
265
- const flags = perFileOptions . signatureFlags . split ( ',' ) . map ( function ( flag ) {
266
- return flag . trim ( ) ;
267
- } ) ;
268
- optionsArguments . push ( ...flags ) ;
269
- }
270
- }
271
-
272
- if ( perFileOptions . hardenedRuntime || optionsArguments . includes ( 'runtime' ) ) {
273
- // Hardened runtime since darwin 17.7.0 --> macOS 10.13.6
274
- if ( compareVersion ( osRelease , '17.7.0' ) >= 0 ) {
275
- optionsArguments . push ( 'runtime' ) ;
276
- } else {
277
- // Remove runtime if passed in with --signature-flags
278
- debugLog (
279
- 'Not enabling hardened runtime, current macOS version too low, requires 10.13.6 and higher'
280
- ) ;
281
- optionsArguments = optionsArguments . filter ( ( arg ) => {
282
- return arg !== 'runtime' ;
283
- } ) ;
284
- }
285
- }
286
-
287
- if ( optionsArguments . length ) {
288
- perFileArgs . push ( '--options' , [ ...new Set ( optionsArguments ) ] . join ( ',' ) ) ;
289
- }
290
-
291
- if ( perFileOptions . additionalArguments ) {
292
- perFileArgs . push ( ...perFileOptions . additionalArguments ) ;
319
+ } )
320
+ )
293
321
}
322
+ } ) ;
294
323
295
- await execFileAsync (
296
- 'codesign' ,
297
- perFileArgs . concat ( '--entitlements' , perFileOptions . entitlements , filePath )
298
- ) ;
324
+ for ( const idx in signingPromises ) {
325
+ let { run } = signingPromises [ idx ] ;
326
+ await run ( ) ;
299
327
}
300
328
301
329
// Verify code sign
0 commit comments