diff --git a/lib/ios-fs-helpers.js b/lib/ios-fs-helpers.js index 7503490b7..248df25d2 100644 --- a/lib/ios-fs-helpers.js +++ b/lib/ios-fs-helpers.js @@ -198,15 +198,25 @@ async function pushFolder(afcService, srcRootPath, dstRootPath, opts = {}) { const {timeoutMs = IO_TIMEOUT_MS, enableParallelPush = false} = opts; const timer = new timing.Timer().start(); - const itemsToPush = await fs.glob('**', { - cwd: srcRootPath, - mark: true, - }); + const allItems = /** @type {import('path-scurry').Path[]} */ (/** @type {unknown} */ ( + await fs.glob('**', { + cwd: srcRootPath, + withFileTypes: true, + })) + ); log.debug(`Successfully scanned the tree structure of '${srcRootPath}'`); - const [foldersToPush, filesToPush] = itemsToPush.reduce((acc, x) => { - acc[_.endsWith(x, path.sep) ? 0 : 1].push(x); - return acc; - }, /** @type {[string[], string[]]} */ ([[], []])); + // top-level folders go first + /** @type {string[]} */ + const foldersToPush = allItems + .filter((x) => x.isDirectory()) + .map((x) => x.relative()) + .sort((a, b) => a.split(path.sep).length - b.split(path.sep).length); + // larger files go first + /** @type {string[]} */ + const filesToPush = allItems + .filter((x) => !x.isDirectory()) + .sort((a, b) => (b.size ?? 0) - (a.size ?? 0)) + .map((x) => x.relative()); log.debug( `Got ${util.pluralize('folder', foldersToPush.length, true)} and ` + `${util.pluralize('file', filesToPush.length, true)} to push`, @@ -216,11 +226,7 @@ async function pushFolder(afcService, srcRootPath, dstRootPath, opts = {}) { await afcService.deleteDirectory(dstRootPath); } catch (ign) {} await afcService.createDirectory(dstRootPath); - // top-level folders must go first - const foldersToPushByHierarchy = foldersToPush.sort( - (a, b) => a.split(path.sep).length - b.split(path.sep).length, - ); - for (const relativeFolderPath of foldersToPushByHierarchy) { + for (const relativeFolderPath of foldersToPush) { // createDirectory does not accept folder names ending with a path separator const absoluteFolderPath = _.trimEnd(path.join(dstRootPath, relativeFolderPath), path.sep); if (absoluteFolderPath) { @@ -265,7 +271,7 @@ async function pushFolder(afcService, srcRootPath, dstRootPath, opts = {}) { if (enableParallelPush) { log.debug(`Proceeding to parallel files push (max ${MAX_IO_CHUNK_SIZE} writers)`); const pushPromises = []; - for (const relativeFilePath of _.shuffle(filesToPush)) { + for (const relativeFilePath of filesToPush) { pushPromises.push(B.resolve(pushFile(relativeFilePath))); // keep the push queue filled if (pushPromises.length >= MAX_IO_CHUNK_SIZE) {