diff --git a/src/util.ts b/src/util.ts index 00dc1c8..7fd1217 100644 --- a/src/util.ts +++ b/src/util.ts @@ -84,16 +84,6 @@ export async function detectElectronPlatform (opts: BaseSignOptions): Promise { debugLog('Walking... ' + dirPath); - async function _walkAsync (dirPath: string): Promise> { + async function _walkAsync (dirPath: string): Promise { const children = await fs.readdir(dirPath); - return await Promise.all( + + const binaryFiles: string[] = []; + const filesToCheck: string[] = []; + const filesToRemove: string[] = []; + const foldersToCheck: string[] = []; + + await Promise.all( children.map(async (child) => { const filePath = path.resolve(dirPath, child); @@ -146,26 +142,46 @@ export async function walkAsync (dirPath: string): Promise { if (stat.isFile()) { switch (path.extname(filePath)) { case '.cstemp': // Temporary file generated from past codesign - debugLog('Removing... ' + filePath); - await fs.remove(filePath); - return null; + filesToRemove.push(filePath); + break; default: - return await getFilePathIfBinary(filePath); + filesToCheck.push(filePath); } } else if (stat.isDirectory() && !stat.isSymbolicLink()) { - const walkResult = await _walkAsync(filePath); + foldersToCheck.push(filePath); + switch (path.extname(filePath)) { case '.app': // Application case '.framework': // Framework - walkResult.push(filePath); + binaryFiles.push(filePath); } - return walkResult; } - return null; }) ); + + // Remove all old tmp files -> should be not much per folder recursion + await Promise.all(filesToRemove.map(async (filePath) => { + debugLog(`Removing... ${filePath}`); + await fs.remove(filePath); + })); + + // Only binaries need to be signed + // isBinaryFile method opens file, calls stat and alloc 1KB memory and reads in file + // build chunks of 10 files to avoid reaching memory or open file handle limits + const chunkSize = 10; + for (let index = 0; index < filesToCheck.length; index += chunkSize) { + await Promise.all(filesToCheck.slice(index, index + chunkSize).map( + async (filePath) => await isBinaryFile(filePath) && binaryFiles.push(filePath)) + ); + } + + // Do avoid fast and easy memory or open file handle bail outs trigger recursion not in parallel + for (const folderPath of foldersToCheck) { + binaryFiles.push(...(await _walkAsync(folderPath))); + } + + return binaryFiles; } - const allPaths = await _walkAsync(dirPath); - return compactFlattenedList(allPaths); + return await _walkAsync(dirPath); }