From c50f2a4a44e39363fd096a300c616a6514e0401c Mon Sep 17 00:00:00 2001 From: Definitely-Not-Vlad Date: Mon, 8 Mar 2021 12:32:58 +0100 Subject: [PATCH 1/3] Add proper exit to ext download retry loop --- src/commands/clone.js | 94 ++++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 36 deletions(-) diff --git a/src/commands/clone.js b/src/commands/clone.js index e1bda19..c4e045c 100644 --- a/src/commands/clone.js +++ b/src/commands/clone.js @@ -13,8 +13,11 @@ import { getApp } from '../clients/legacy-service'; import { pathExists, copy } from 'fs-extra'; import selectApp from '../services/app-selector'; import { - downloadApp, fixPlatform, configurePlatform, createPlatformConfig, - setPlatformConfig + downloadApp, + fixPlatform, + configurePlatform, + createPlatformConfig, + setPlatformConfig, } from '../services/platform'; import { ensureUserIsLoggedIn } from './login'; import { createProgressHandler } from '../services/progress-bar'; @@ -29,29 +32,36 @@ export async function pullExtensions(appId, destinationDir) { const installations = await appManager.getInstallations(appId); const n = installations.length; let i = 0; - for(const inst of installations) { + for (const inst of installations) { i++; - await spinify(pullExtension(destinationDir, inst), `Downloading extension ${i}/${n}: ${inst.canonicalName}...`); + await spinify( + pullExtension(destinationDir, inst), + `Downloading extension ${i}/${n}: ${inst.canonicalName}...` + ); } } async function pullExtension(destinationDir, { extension, canonicalName }) { let pullError = {}; - let pullSuccessful = false; - for (let i = 0; !pullSuccessful || i < 4; i++) { + for (let i = 0; i < 5; i++) { try { const url = await getExtensionUrl(extension); const tgzDir = (await tmp.dir()).path; await downloadFile(url, { directory: tgzDir, filename: 'extension.tgz' }); - await shoutemUnpack(path.join(tgzDir, 'extension.tgz'), path.join(destinationDir, canonicalName)); - pullSuccessful = true; + await shoutemUnpack( + path.join(tgzDir, 'extension.tgz'), + path.join(destinationDir, canonicalName) + ); + + return; } catch (error) { - pullError = error; - console.log(`Failed to download extension ${canonicalName}, try ${i + 1}/5`); + if (error.code !== 'ENOTEMPTY') { + pullError = error; + } } } - if (!pullSuccessful) { + if (!_.isEmpty(pullError)) { pullError.message = `Could not fetch extension ${canonicalName}.`; throw pullError; } @@ -59,18 +69,21 @@ async function pullExtension(destinationDir, { extension, canonicalName }) { async function getExtensionUrl(extId) { const resp = await getExtension(extId); - const { location: { extension } } = resp; + const { + location: { extension }, + } = resp; - return `${removeTrailingSlash(extension.package)}/extension.tgz`; + return `${removeTrailingSlash(extension.package)}/extension.tgz`; } function removeTrailingSlash(str) { - return str.replace(/\/$/, ""); + return str.replace(/\/$/, ''); } function ensurePlatformCompatibility(platform) { - const msg = `Your app is using Shoutem Platform ${platform.version}`+ - `, but cloning is supported only on Shoutem Platform 1.1.2 or later.\n`+ + const msg = + `Your app is using Shoutem Platform ${platform.version}` + + `, but cloning is supported only on Shoutem Platform 1.1.2 or later.\n` + `Please, update the Platform through Settings -> Shoutem Platform -> Install page on the Builder or install older (and unsupported) version of ` + `the Shoutem CLI by running 'npm install -g @shoutem/cli@0.0.152'`; @@ -84,16 +97,20 @@ async function queryPathExistsAction(destinationDir, oldDirectoryName) { type: 'list', name: 'action', message: `Directory ${oldDirectoryName} already exists.`, - choices: [{ - name: 'Overwrite', - value: 'overwrite' - }, { - name: 'Abort', - value: 'abort', - }, { - name: 'Different app directory name', - value: 'rename' - }] + choices: [ + { + name: 'Overwrite', + value: 'overwrite', + }, + { + name: 'Abort', + value: 'abort', + }, + { + name: 'Different app directory name', + value: 'rename', + }, + ], }); if (action === 'overwrite') { @@ -111,26 +128,26 @@ async function queryPathExistsAction(destinationDir, oldDirectoryName) { return 'No spaces are allowed.'; } if (await pathExists(path.join(destinationDir, dirName))) { - return `Directory ${dirName} already exists.` + return `Directory ${dirName} already exists.`; } return true; - } + }, }); return { type: 'rename', newDirectoryName, - newAppDir: path.join(destinationDir, newDirectoryName) + newAppDir: path.join(destinationDir, newDirectoryName), }; } export async function clone(opts, destinationDir) { - if (!await commandExists('git')) { + if (!(await commandExists('git'))) { throw new Error('Missing `git` command'); } await ensureUserIsLoggedIn(); - opts.appId = opts.appId || await selectApp(); + opts.appId = opts.appId || (await selectApp()); const { name } = await getApp(opts.appId); @@ -174,9 +191,11 @@ export async function clone(opts, destinationDir) { versionCheck: mobileAppVersion => { if (!semver.gte(mobileAppVersion, '0.58.9')) { - throw new Error('This version of CLI only supports platforms containing mobile app 0.58.9 or higher.'); + throw new Error( + 'This version of CLI only supports platforms containing mobile app 0.58.9 or higher.' + ); } - } + }, }); } @@ -185,7 +204,7 @@ export async function clone(opts, destinationDir) { await fixPlatform(appDir, opts.appId); const config = await createPlatformConfig(appDir, { - appId: opts.appId + appId: opts.appId, }); await setPlatformConfig(appDir, config); @@ -205,7 +224,10 @@ export async function clone(opts, destinationDir) { console.log(' Have an Android simulator running or a device connected'); console.log(' react-native run-android'); - if (!/^win/.test(process.platform) && !await commandExists('watchman')) { - console.log('HINT: You should probably install Facebook\'s `watchman` before running react-native commands'.bold.yellow); + if (!/^win/.test(process.platform) && !(await commandExists('watchman'))) { + console.log( + "HINT: You should probably install Facebook's `watchman` before running react-native commands" + .bold.yellow + ); } } From 0133e6f30c7153b04acd2b755e2541f64a2442c1 Mon Sep 17 00:00:00 2001 From: Definitely-Not-Vlad Date: Mon, 8 Mar 2021 12:34:48 +0100 Subject: [PATCH 2/3] Fix number of loops --- package-lock.json | 2 +- src/commands/clone.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 47a49d2..66f4166 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@shoutem/cli", - "version": "0.13.11", + "version": "0.13.13", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/src/commands/clone.js b/src/commands/clone.js index c4e045c..ed596a0 100644 --- a/src/commands/clone.js +++ b/src/commands/clone.js @@ -43,7 +43,7 @@ export async function pullExtensions(appId, destinationDir) { async function pullExtension(destinationDir, { extension, canonicalName }) { let pullError = {}; - for (let i = 0; i < 5; i++) { + for (let i = 0; i < 4; i++) { try { const url = await getExtensionUrl(extension); const tgzDir = (await tmp.dir()).path; From 39e61945381e493e87f4006682081b89431a521a Mon Sep 17 00:00:00 2001 From: Definitely-Not-Vlad Date: Mon, 8 Mar 2021 13:45:51 +0100 Subject: [PATCH 3/3] Reset error to null on successful pull --- src/commands/clone.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/commands/clone.js b/src/commands/clone.js index ed596a0..1e4dd7e 100644 --- a/src/commands/clone.js +++ b/src/commands/clone.js @@ -42,7 +42,7 @@ export async function pullExtensions(appId, destinationDir) { } async function pullExtension(destinationDir, { extension, canonicalName }) { - let pullError = {}; + let pullError = null; for (let i = 0; i < 4; i++) { try { const url = await getExtensionUrl(extension); @@ -53,6 +53,7 @@ async function pullExtension(destinationDir, { extension, canonicalName }) { path.join(destinationDir, canonicalName) ); + pullError = null; return; } catch (error) { if (error.code !== 'ENOTEMPTY') {