refactor: Simplify the logic of unzipApp helper
MODIFY
lib/basedriver/helpers.js
lib/basedriver/helpers.js
@@ -89,7 +89,9 @@ function verifyAppExtension (app, supportedAppExtensions) {
if (supportedAppExtensions.includes(path.extname(app))) {
return app;
}
- throw new Error(`New app path '${app}' did not have extension(s) '${supportedAppExtensions}'`);
+ throw new Error(`New app path '${app}' did not have ` +
+ `${util.pluralize('extension', supportedAppExtensions.length, false)}: ` +
+ supportedAppExtensions);
}
async function configureApp (app, supportedAppExtensions) {
@@ -139,9 +141,10 @@ async function configureApp (app, supportedAppExtensions) {
shouldUnzipApp = true;
}
if (headers['content-type']) {
- logger.debug(`Content-Type: ${headers['content-type']}`);
+ const ct = headers['content-type'];
+ logger.debug(`Content-Type: ${ct}`);
// the filetype may not be obvious for certain urls, so check the mime type too
- if (ZIP_MIME_TYPES.some(mimeType => new RegExp(`\\b${_.escapeRegExp(mimeType)}\\b`).test(headers['content-type']))) {
+ if (ZIP_MIME_TYPES.some((mimeType) => new RegExp(`\\b${_.escapeRegExp(mimeType)}\\b`).test(ct))) {
if (!fileName) {
fileName = `${DEFAULT_BASENAME}.zip`;
}
@@ -272,6 +275,19 @@ async function downloadApp (app, targetPath) {
return targetPath;
}
+/**
+ * Extracts the bundle from an archive into the given folder
+ *
+ * @param {string} zipPath Full path to the archive containing the bundle
+ * @param {string} dstRoot Full path to the folder where the extracted bundle
+ * should be placed
+ * @param {Array<string>|string} supportedAppExtensions The list of extensions
+ * the target application bundle supports, for example ['.apk', '.apks'] for
+ * Android packages
+ * @returns {string} Full path to the bundle in the destination folder
+ * @throws {Error} If the given archive is invalid or no application bundles
+ * have been found inside
+ */
async function unzipApp (zipPath, dstRoot, supportedAppExtensions) {
await zip.assertValidZip(zipPath);
@@ -283,42 +299,24 @@ async function unzipApp (zipPath, dstRoot, supportedAppExtensions) {
try {
logger.debug(`Unzipping '${zipPath}'`);
await zip.extractAllTo(zipPath, tmpRoot);
- const allExtractedItems = [];
- await fs.walkDir(tmpRoot, true, (itemPath) => void allExtractedItems.push(itemPath));
- logger.debug(`Extracted ${allExtractedItems.length} item(s) from '${zipPath}'`);
- const isSupportedAppItem = (relativePath) => supportedAppExtensions.includes(path.extname(relativePath))
- || _.some(supportedAppExtensions, (x) => relativePath.includes(`${x}${path.sep}`));
- const itemsToKeep = allExtractedItems
- .map((itemPath) => path.relative(tmpRoot, itemPath))
- .filter((relativePath) => isSupportedAppItem(relativePath))
- .map((relativePath) => path.resolve(tmpRoot, relativePath));
- const itemsToRemove = _.difference(allExtractedItems, itemsToKeep)
- // Avoid parent folders to be recursively removed
- .filter((itemToRemovePath) => !_.some(itemsToKeep, (itemToKeepPath) => itemToKeepPath.startsWith(itemToRemovePath)));
- await B.all(itemsToRemove, async (itemPath) => {
- if (await fs.exists(itemPath)) {
- await fs.rimraf(itemPath);
- }
- });
- let allBundleItems = [];
- await fs.walkDir(tmpRoot, true, (itemPath) => void allBundleItems.push(itemPath));
- allBundleItems = allBundleItems
- .map((itemPath) => path.relative(tmpRoot, itemPath))
- .filter((relativePath) => isSupportedAppItem(relativePath))
+ const allExtractedItems = await fs.glob('**', {cwd: tmpRoot});
+ logger.debug(`Extracted ${util.pluralize('item', allExtractedItems.length, true)} from '${zipPath}'`);
+ const allBundleItems = allExtractedItems
+ .filter((relativePath) => supportedAppExtensions.includes(path.extname(relativePath)))
// Get the top level match
.sort((a, b) => a.split(path.sep).length - b.split(path.sep).length);
if (_.isEmpty(allBundleItems)) {
- throw new Error(`App zip unzipped OK, but we could not find ${supportedAppExtensions} bundle(s) ` +
- `in it. Make sure your archive contains ${supportedAppExtensions} package(s) ` +
- `and nothing else`);
+ throw new Error(`App zip unzipped OK, but we could not find '${supportedAppExtensions}' ` +
+ util.pluralize('bundle', supportedAppExtensions.length, false) +
+ ` in it. Make sure your archive contains at least one package having ` +
+ `'${supportedAppExtensions}' ${util.pluralize('extension', supportedAppExtensions.length, false)}`);
}
const matchedBundle = _.first(allBundleItems);
- logger.debug(`Matched ${allBundleItems.length} item(s) in the extracted archive. ` +
+ logger.debug(`Matched ${util.pluralize('item', allBundleItems.length, true)} in the extracted archive. ` +
`Assuming '${matchedBundle}' is the correct bundle`);
- await fs.mv(path.resolve(tmpRoot, matchedBundle), path.resolve(dstRoot, matchedBundle), {
- mkdirp: true
- });
- return path.resolve(dstRoot, matchedBundle);
+ const dstPath = path.resolve(dstRoot, matchedBundle);
+ await fs.mv(path.resolve(tmpRoot, matchedBundle), dstPath, {mkdirp: true});
+ return dstPath;
} finally {
await fs.rimraf(tmpRoot);
}

refactor: Simplify the logic of unzipApp helper (#392)