Skip to content

Commit

Permalink
chore: replace superspawn & child_process with execa (#862)
Browse files Browse the repository at this point in the history
* chore: added execa dependency

Co-authored-by: Raphael von der Grün <raphinesse@gmail.com>

* chore: execa - drop superspawn in android_sdk

Co-authored-by: Raphael von der Grün <raphinesse@gmail.com>

* chore: execa - drop superspawn in build

* chore: execa - drop superspawn in check_reqs

Plus: Remove useless trimming of execa output

Co-authored-by: Raphael von der Grün <raphinesse@gmail.com>

* chore: execa - drop superspawn in emulator

Co-authored-by: Raphael von der Grün <raphinesse@gmail.com>

* chore: execa - drop superspawn in device

Co-authored-by: Raphael von der Grün <raphinesse@gmail.com>

* chore: execa - drop superspawn in run_java_unit_tests

* chore: execa - drop superspawn in ProjectBuilder

Co-authored-by: Raphael von der Grün <raphinesse@gmail.com>

* chore: execa - drop superspawn in adb

* chore: execa - drop superspawn in plugin.spec

* chore: execa - replace child_process in log

* chore: execa - replace child_process in check_reqs

* chore: execa - replace child_process in emulator

Co-authored-by: エリス <erisu@users.noreply.github.com>
  • Loading branch information
raphinesse and erisu authored Jan 6, 2020
1 parent e3cc75c commit fd57909
Show file tree
Hide file tree
Showing 16 changed files with 138 additions and 157 deletions.
16 changes: 8 additions & 8 deletions bin/templates/cordova/lib/Adb.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@

var Q = require('q');
var os = require('os');
var execa = require('execa');
var events = require('cordova-common').events;
var spawn = require('cordova-common').superspawn.spawn;
var CordovaError = require('cordova-common').CordovaError;

var Adb = {};
Expand All @@ -44,7 +44,7 @@ function isEmulator (line) {
* devices/emulators
*/
Adb.devices = function (opts) {
return spawn('adb', ['devices'], { cwd: os.tmpdir() }).then(function (output) {
return execa('adb', ['devices'], { cwd: os.tmpdir() }).then(({ stdout: output }) => {
return output.split('\n').filter(function (line) {
// Filter out either real devices or emulators, depending on options
return (line && opts && opts.emulators) ? isEmulator(line) : isDevice(line);
Expand All @@ -58,7 +58,7 @@ Adb.install = function (target, packagePath, opts) {
events.emit('verbose', 'Installing apk ' + packagePath + ' on target ' + target + '...');
var args = ['-s', target, 'install'];
if (opts && opts.replace) args.push('-r');
return spawn('adb', args.concat(packagePath), { cwd: os.tmpdir() }).then(function (output) {
return execa('adb', args.concat(packagePath), { cwd: os.tmpdir() }).then(({ stdout: output }) => {
// 'adb install' seems to always returns no error, even if installation fails
// so we catching output to detect installation failure
if (output.match(/Failure/)) {
Expand All @@ -77,24 +77,24 @@ Adb.install = function (target, packagePath, opts) {

Adb.uninstall = function (target, packageId) {
events.emit('verbose', 'Uninstalling package ' + packageId + ' from target ' + target + '...');
return spawn('adb', ['-s', target, 'uninstall', packageId], { cwd: os.tmpdir() });
return execa('adb', ['-s', target, 'uninstall', packageId], { cwd: os.tmpdir() }).then(({ stdout }) => stdout);
};

Adb.shell = function (target, shellCommand) {
events.emit('verbose', 'Running adb shell command "' + shellCommand + '" on target ' + target + '...');
var args = ['-s', target, 'shell'];
shellCommand = shellCommand.split(/\s+/);
return spawn('adb', args.concat(shellCommand), { cwd: os.tmpdir() }).catch(function (output) {
return execa('adb', args.concat(shellCommand), { cwd: os.tmpdir() }).catch((error) => {
return Q.reject(new CordovaError('Failed to execute shell command "' +
shellCommand + '"" on device: ' + output));
shellCommand + '"" on device: ' + error));
});
};

Adb.start = function (target, activityName) {
events.emit('verbose', 'Starting application "' + activityName + '" on target ' + target + '...');
return Adb.shell(target, 'am start -W -a android.intent.action.MAIN -n' + activityName).catch(function (output) {
return Adb.shell(target, 'am start -W -a android.intent.action.MAIN -n' + activityName).catch((error) => {
return Q.reject(new CordovaError('Failed to start application "' +
activityName + '"" on device: ' + output));
activityName + '"" on device: ' + error));
});
};

Expand Down
6 changes: 3 additions & 3 deletions bin/templates/cordova/lib/android_sdk.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
under the License.
*/

var superspawn = require('cordova-common').superspawn;
const execa = require('execa');

var suffix_number_regex = /(\d+)$/;
// Used for sorting Android targets, example strings to sort:
Expand Down Expand Up @@ -77,11 +77,11 @@ function parse_targets (output) {
}

module.exports.list_targets_with_android = function () {
return superspawn.spawn('android', ['list', 'target']).then(parse_targets);
return execa('android', ['list', 'target']).then(result => parse_targets(result.stdout));
};

module.exports.list_targets_with_avdmanager = function () {
return superspawn.spawn('avdmanager', ['list', 'target']).then(parse_targets);
return execa('avdmanager', ['list', 'target']).then(result => parse_targets(result.stdout));
};

module.exports.list_targets = function () {
Expand Down
6 changes: 3 additions & 3 deletions bin/templates/cordova/lib/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ var Adb = require('./Adb');

var builders = require('./builders/builders');
var events = require('cordova-common').events;
var spawn = require('cordova-common').superspawn.spawn;
const execa = require('execa');
var CordovaError = require('cordova-common').CordovaError;
var PackageType = require('./PackageType');

Expand Down Expand Up @@ -212,11 +212,11 @@ module.exports.detectArchitecture = function (target) {
// Could probably find a x-platform version of killall, but I'm not actually
// sure that this scenario even happens on non-OSX machines.
events.emit('verbose', 'adb timed out while detecting device/emulator architecture. Killing adb and trying again.');
return spawn('killall', ['adb']).then(function () {
return execa('killall', ['adb']).then(function () {
return helper().then(null, function () {
// The double kill is sadly often necessary, at least on mac.
events.emit('warn', 'adb timed out a second time while detecting device/emulator architecture. Killing adb and trying again.');
return spawn('killall', ['adb']).then(function () {
return execa('killall', ['adb']).then(function () {
return helper().then(null, function () {
return Q.reject(new CordovaError('adb timed out a third time while detecting device/emulator architecture. Try unplugging & replugging the device.'));
});
Expand Down
15 changes: 6 additions & 9 deletions bin/templates/cordova/lib/builders/ProjectBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@
under the License.
*/

var Q = require('q');
var fs = require('fs');
var path = require('path');
var shell = require('shelljs');
var spawn = require('cordova-common').superspawn.spawn;
const execa = require('execa');
var events = require('cordova-common').events;
var CordovaError = require('cordova-common').CordovaError;
var check_reqs = require('../check_reqs');
Expand Down Expand Up @@ -80,7 +79,7 @@ class ProjectBuilder {
if (fs.existsSync(gradlePath)) {
// Literally do nothing, for some reason this works, while !fs.existsSync didn't on Windows
} else {
return spawn(gradle_cmd, ['-p', this.root, 'wrapper', '-b', wrapperGradle], { stdio: 'inherit' });
return execa(gradle_cmd, ['-p', this.root, 'wrapper', '-b', wrapperGradle], { stdio: 'inherit' });
}
}

Expand Down Expand Up @@ -250,26 +249,24 @@ class ProjectBuilder {
var wrapper = path.join(this.root, 'gradlew');
var args = this.getArgs(opts.buildType === 'debug' ? 'debug' : 'release', opts);

return spawn(wrapper, args, { stdio: 'inherit' })
return execa(wrapper, args, { stdio: 'inherit' })
.catch(function (error) {
if (error.toString().indexOf('failed to find target with hash string') >= 0) {
return check_reqs.check_android_target(error).then(function () {
// If due to some odd reason - check_android_target succeeds
// we should still fail here.
return Q.reject(error);
throw error;
});
}
return Q.reject(error);
throw error;
});
}

clean (opts) {
var builder = this;
var wrapper = path.join(this.root, 'gradlew');
var args = builder.getArgs('clean', opts);
return Q().then(function () {
return spawn(wrapper, args, { stdio: 'inherit' });
})
return execa(wrapper, args, { stdio: 'inherit' })
.then(function () {
shell.rm('-rf', path.join(builder.root, 'out'));

Expand Down
17 changes: 7 additions & 10 deletions bin/templates/cordova/lib/check_reqs.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,15 @@
under the License.
*/

const execa = require('execa');
var shelljs = require('shelljs');
var child_process = require('child_process');
var Q = require('q');
var path = require('path');
var fs = require('fs');
var os = require('os');
var REPO_ROOT = path.join(__dirname, '..', '..', '..', '..');
var PROJECT_ROOT = path.join(__dirname, '..', '..');
var CordovaError = require('cordova-common').CordovaError;
var superspawn = require('cordova-common').superspawn;
var android_sdk = require('./android_sdk');

function forgivingWhichSync (cmd) {
Expand Down Expand Up @@ -71,7 +70,7 @@ module.exports.get_target = function () {

// Returns a promise. Called only by build and clean commands.
module.exports.check_ant = function () {
return superspawn.spawn('ant', ['-version']).then(function (output) {
return execa('ant', ['-version']).then(({ stdout: output }) => {
// Parse Ant version from command output
return /version ((?:\d+\.)+(?:\d+))/i.exec(output)[1];
}).catch(function (err) {
Expand All @@ -89,7 +88,7 @@ module.exports.get_gradle_wrapper = function () {
// OK, This hack only works on Windows, not on Mac OS or Linux. We will be deleting this eventually!
if (module.exports.isWindows()) {

var result = child_process.spawnSync(path.join(__dirname, 'getASPath.bat'));
var result = execa.sync(path.join(__dirname, 'getASPath.bat'));
// console.log('result.stdout =' + result.stdout.toString());
// console.log('result.stderr =' + result.stderr.toString());

Expand Down Expand Up @@ -157,8 +156,8 @@ module.exports.check_java = function () {
var find_java = '/usr/libexec/java_home';
var default_java_error_msg = 'Failed to find \'JAVA_HOME\' environment variable. Try setting it manually.';
if (fs.existsSync(find_java)) {
return superspawn.spawn(find_java).then(function (stdout) {
process.env['JAVA_HOME'] = stdout.trim();
return execa(find_java).then(({ stdout }) => {
process.env['JAVA_HOME'] = stdout;
}).catch(function (err) {
if (err) {
throw new CordovaError(default_java_error_msg);
Expand Down Expand Up @@ -194,11 +193,9 @@ module.exports.check_java = function () {
}
}
}).then(function () {
return Q.denodeify(child_process.exec)('javac -version')
.then(outputs => {
// outputs contains two entries: stdout and stderr
return execa('javac', ['-version'], { all: true })
.then(({ all: output }) => {
// Java <= 8 writes version info to stderr, Java >= 9 to stdout
const output = outputs.join('').trim();
const match = /javac\s+([\d.]+)/i.exec(output);
return match && match[1];
}, () => {
Expand Down
4 changes: 2 additions & 2 deletions bin/templates/cordova/lib/device.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@
under the License.
*/

const execa = require('execa');
var build = require('./build');
var path = require('path');
var Adb = require('./Adb');
var AndroidManifest = require('./AndroidManifest');
var spawn = require('cordova-common').superspawn.spawn;
var CordovaError = require('cordova-common').CordovaError;
var events = require('cordova-common').events;

Expand All @@ -37,7 +37,7 @@ module.exports.list = function (lookHarder) {
// adb kill-server doesn't seem to do the trick.
// Could probably find a x-platform version of killall, but I'm not actually
// sure that this scenario even happens on non-OSX machines.
return spawn('killall', ['adb']).then(function () {
return execa('killall', ['adb']).then(function () {
events.emit('verbose', 'Restarting adb to see if more devices are detected.');
return Adb.devices();
}, function () {
Expand Down
51 changes: 23 additions & 28 deletions bin/templates/cordova/lib/emulator.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,21 @@
under the License.
*/

const execa = require('execa');
var android_versions = require('android-versions');
var retry = require('./retry');
var build = require('./build');
var path = require('path');
var Adb = require('./Adb');
var AndroidManifest = require('./AndroidManifest');
var events = require('cordova-common').events;
var superspawn = require('cordova-common').superspawn;
var CordovaError = require('cordova-common').CordovaError;
var shelljs = require('shelljs');
var android_sdk = require('./android_sdk');
var check_reqs = require('./check_reqs');

var os = require('os');
var fs = require('fs');
var child_process = require('child_process');

// constants
var ONE_SECOND = 1000; // in milliseconds
Expand All @@ -53,7 +52,7 @@ function forgivingWhichSync (cmd) {
}

module.exports.list_images_using_avdmanager = function () {
return superspawn.spawn('avdmanager', ['list', 'avd']).then(function (output) {
return execa('avdmanager', ['list', 'avd']).then(({ stdout: output }) => {
var response = output.split('\n');
var emulator_list = [];
for (var i = 1; i < response.length; i++) {
Expand Down Expand Up @@ -113,7 +112,7 @@ module.exports.list_images_using_avdmanager = function () {
};

module.exports.list_images_using_android = function () {
return superspawn.spawn('android', ['list', 'avd']).then(function (output) {
return execa('android', ['list', 'avd']).then(({ stdout: output }) => {
var response = output.split('\n');
var emulator_list = [];
for (var i = 1; i < response.length; i++) {
Expand Down Expand Up @@ -229,7 +228,7 @@ module.exports.list_started = function () {
// Returns a promise.
// TODO: we should remove this, there's a more robust method under android_sdk.js
module.exports.list_targets = function () {
return superspawn.spawn('android', ['list', 'targets'], { cwd: os.tmpdir() }).then(function (output) {
return execa('android', ['list', 'targets'], { cwd: os.tmpdir() }).then(({ stdout: output }) => {
var target_out = output.split('\n');
var targets = [];
for (var i = target_out.length; i >= 0; i--) {
Expand Down Expand Up @@ -294,8 +293,7 @@ module.exports.start = function (emulator_ID, boot_timeout) {
var emulator_dir = path.dirname(shelljs.which('emulator'));
var args = ['-avd', emulatorId, '-port', port];
// Don't wait for it to finish, since the emulator will probably keep running for a long time.
child_process
.spawn('emulator', args, { stdio: 'inherit', detached: true, cwd: emulator_dir })
execa('emulator', args, { stdio: 'inherit', detached: true, cwd: emulator_dir })
.unref();

// wait for emulator to start
Expand Down Expand Up @@ -387,22 +385,22 @@ module.exports.wait_for_boot = function (emulator_id, time_remaining) {
module.exports.create_image = function (name, target) {
console.log('Creating new avd named ' + name);
if (target) {
return superspawn.spawn('android', ['create', 'avd', '--name', name, '--target', target]).then(null, function (error) {
return execa('android', ['create', 'avd', '--name', name, '--target', target]).then(null, function (error) {
console.error('ERROR : Failed to create emulator image : ');
console.error(' Do you have the latest android targets including ' + target + '?');
console.error(error);
console.error(error.message);
});
} else {
console.log('WARNING : Project target not found, creating avd with a different target but the project may fail to install.');
// TODO: there's a more robust method for finding targets in android_sdk.js
return superspawn.spawn('android', ['create', 'avd', '--name', name, '--target', this.list_targets()[0]]).then(function () {
return execa('android', ['create', 'avd', '--name', name, '--target', this.list_targets()[0]]).then(function () {
// TODO: This seems like another error case, even though it always happens.
console.error('ERROR : Unable to create an avd emulator, no targets found.');
console.error('Ensure you have targets available by running the "android" command');
return Promise.reject(new CordovaError());
}, function (error) {
console.error('ERROR : Failed to create emulator image : ');
console.error(error);
console.error(error.message);
});
}
};
Expand Down Expand Up @@ -474,24 +472,21 @@ module.exports.install = function (givenTarget, buildResults) {
function adbInstallWithOptions (target, apk, opts) {
events.emit('verbose', 'Installing apk ' + apk + ' on ' + target + '...');

var command = 'adb -s ' + target + ' install -r "' + apk + '"';
return new Promise(function (resolve, reject) {
child_process.exec(command, opts, function (err, stdout, stderr) {
if (err) reject(new CordovaError('Error executing "' + command + '": ' + stderr));
// adb does not return an error code even if installation fails. Instead it puts a specific
// message to stdout, so we have to use RegExp matching to detect installation failure.
else if (/Failure/.test(stdout)) {
if (stdout.match(/INSTALL_PARSE_FAILED_NO_CERTIFICATES/)) {
stdout += 'Sign the build using \'-- --keystore\' or \'--buildConfig\'' +
' or sign and deploy the unsigned apk manually using Android tools.';
} else if (stdout.match(/INSTALL_FAILED_VERSION_DOWNGRADE/)) {
stdout += 'You\'re trying to install apk with a lower versionCode that is already installed.' +
'\nEither uninstall an app or increment the versionCode.';
}
const args = ['-s', target, 'install', '-r', apk];
return execa('adb', args, opts).then(({ stdout }) => {
// adb does not return an error code even if installation fails. Instead it puts a specific
// message to stdout, so we have to use RegExp matching to detect installation failure.
if (/Failure/.test(stdout)) {
if (stdout.match(/INSTALL_PARSE_FAILED_NO_CERTIFICATES/)) {
stdout += 'Sign the build using \'-- --keystore\' or \'--buildConfig\'' +
' or sign and deploy the unsigned apk manually using Android tools.';
} else if (stdout.match(/INSTALL_FAILED_VERSION_DOWNGRADE/)) {
stdout += 'You\'re trying to install apk with a lower versionCode that is already installed.' +
'\nEither uninstall an app or increment the versionCode.';
}

reject(new CordovaError('Failed to install apk to emulator: ' + stdout));
} else resolve(stdout);
});
throw new CordovaError('Failed to install apk to emulator: ' + stdout);
}
});
}

Expand Down
Loading

0 comments on commit fd57909

Please # to comment.