mirror of
https://github.com/apache/cordova-android.git
synced 2025-02-26 03:53:09 +08:00
Merge branch 'master' into StudioProjectCompat
This will have to be linted
This commit is contained in:
commit
e456175a81
10
.eslintrc.yml
Normal file
10
.eslintrc.yml
Normal file
@ -0,0 +1,10 @@
|
||||
root: true
|
||||
extends: semistandard
|
||||
rules:
|
||||
indent:
|
||||
- error
|
||||
- 4
|
||||
camelcase: off
|
||||
padded-blocks: off
|
||||
operator-linebreak: off
|
||||
no-throw-literal: off
|
@ -15,7 +15,7 @@ android:
|
||||
- tools
|
||||
- tools
|
||||
script:
|
||||
- npm run jshint
|
||||
- npm run eslint
|
||||
- npm run cover
|
||||
- npm run test-build
|
||||
after_script:
|
||||
|
@ -19,12 +19,12 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var shell = require('shelljs'),
|
||||
Q = require('q'),
|
||||
path = require('path'),
|
||||
fs = require('fs'),
|
||||
check_reqs = require('./../templates/cordova/lib/check_reqs'),
|
||||
ROOT = path.join(__dirname, '..', '..');
|
||||
var shell = require('shelljs');
|
||||
var Q = require('q');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var check_reqs = require('./../templates/cordova/lib/check_reqs');
|
||||
var ROOT = path.join(__dirname, '..', '..');
|
||||
|
||||
var MIN_SDK_VERSION = 19;
|
||||
|
||||
@ -32,14 +32,14 @@ var CordovaError = require('cordova-common').CordovaError;
|
||||
var AndroidStudio = require('../templates/cordova/lib/AndroidStudio');
|
||||
var AndroidManifest = require('../templates/cordova/lib/AndroidManifest');
|
||||
|
||||
function setShellFatal(value, func) {
|
||||
function setShellFatal (value, func) {
|
||||
var oldVal = shell.config.fatal;
|
||||
shell.config.fatal = value;
|
||||
func();
|
||||
shell.config.fatal = oldVal;
|
||||
}
|
||||
|
||||
function getFrameworkDir(projectPath, shared) {
|
||||
function getFrameworkDir (projectPath, shared) {
|
||||
return shared ? path.join(ROOT, 'framework') : path.join(projectPath, 'CordovaLib');
|
||||
}
|
||||
|
||||
@ -62,9 +62,9 @@ function copyJsAndLibrary(projectPath, shared, projectName, isLegacy) {
|
||||
// We need these files to build cordova.js if using browserify method.
|
||||
shell.cp('-rf', path.join(ROOT, 'cordova-js-src'), path.join(projectPath, 'platform_www'));
|
||||
|
||||
// Don't fail if there are no old jars, because there hasn't been cordova JARs for years!
|
||||
setShellFatal(false, function() {
|
||||
shell.ls(path.join(app_path, 'libs', 'cordova-*.jar')).forEach(function(oldJar) {
|
||||
// Don't fail if there are no old jars.
|
||||
setShellFatal(false, function () {
|
||||
shell.ls(path.join(projectPath, 'libs', 'cordova-*.jar')).forEach(function (oldJar) {
|
||||
console.log('Deleting ' + oldJar);
|
||||
shell.rm('-f', oldJar);
|
||||
});
|
||||
@ -96,7 +96,7 @@ function copyJsAndLibrary(projectPath, shared, projectName, isLegacy) {
|
||||
}
|
||||
}
|
||||
|
||||
function extractSubProjectPaths(data) {
|
||||
function extractSubProjectPaths (data) {
|
||||
var ret = {};
|
||||
var r = /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg;
|
||||
var m;
|
||||
@ -106,7 +106,7 @@ function extractSubProjectPaths(data) {
|
||||
return Object.keys(ret);
|
||||
}
|
||||
|
||||
function writeProjectProperties(projectPath, target_api) {
|
||||
function writeProjectProperties (projectPath, target_api) {
|
||||
var dstPath = path.join(projectPath, 'project.properties');
|
||||
var templatePath = path.join(ROOT, 'bin', 'templates', 'project', 'project.properties');
|
||||
var srcPath = fs.existsSync(dstPath) ? dstPath : templatePath;
|
||||
@ -114,11 +114,10 @@ function writeProjectProperties(projectPath, target_api) {
|
||||
var data = fs.readFileSync(srcPath, 'utf8');
|
||||
data = data.replace(/^target=.*/m, 'target=' + target_api);
|
||||
var subProjects = extractSubProjectPaths(data);
|
||||
subProjects = subProjects.filter(function(p) {
|
||||
subProjects = subProjects.filter(function (p) {
|
||||
return !(/^CordovaLib$/m.exec(p) ||
|
||||
/[\\\/]cordova-android[\\\/]framework$/m.exec(p) ||
|
||||
/^(\.\.[\\\/])+framework$/m.exec(p)
|
||||
);
|
||||
/[\\/]cordova-android[\\/]framework$/m.exec(p) ||
|
||||
/^(\.\.[\\/])+framework$/m.exec(p));
|
||||
});
|
||||
subProjects.unshift('CordovaLib');
|
||||
data = data.replace(/^\s*android\.library\.reference\.\d+=.*\n/mg, '');
|
||||
@ -126,7 +125,7 @@ function writeProjectProperties(projectPath, target_api) {
|
||||
data += '\n';
|
||||
}
|
||||
for (var i = 0; i < subProjects.length; ++i) {
|
||||
data += 'android.library.reference.' + (i+1) + '=' + subProjects[i] + '\n';
|
||||
data += 'android.library.reference.' + (i + 1) + '=' + subProjects[i] + '\n';
|
||||
}
|
||||
fs.writeFileSync(dstPath, data);
|
||||
}
|
||||
@ -151,7 +150,7 @@ function copyBuildRules(projectPath, isLegacy) {
|
||||
}
|
||||
}
|
||||
|
||||
function copyScripts(projectPath) {
|
||||
function copyScripts (projectPath) {
|
||||
var bin = path.join(ROOT, 'bin');
|
||||
var srcScriptsDir = path.join(bin, 'templates', 'cordova');
|
||||
var destScriptsDir = path.join(projectPath, 'cordova');
|
||||
@ -178,17 +177,17 @@ function copyScripts(projectPath) {
|
||||
* Returns a promise, fulfilled if the package name is acceptable; rejected
|
||||
* otherwise.
|
||||
*/
|
||||
function validatePackageName(package_name) {
|
||||
//Make the package conform to Java package types
|
||||
//http://developer.android.com/guide/topics/manifest/manifest-element.html#package
|
||||
//Enforce underscore limitation
|
||||
function validatePackageName (package_name) {
|
||||
// Make the package conform to Java package types
|
||||
// http://developer.android.com/guide/topics/manifest/manifest-element.html#package
|
||||
// Enforce underscore limitation
|
||||
var msg = 'Error validating package name. ';
|
||||
if (!/^[a-zA-Z][a-zA-Z0-9_]+(\.[a-zA-Z][a-zA-Z0-9_]*)+$/.test(package_name)) {
|
||||
return Q.reject(new CordovaError(msg + 'Package name must look like: com.company.Name'));
|
||||
}
|
||||
|
||||
//Class is a reserved word
|
||||
if(/\b[Cc]lass\b/.test(package_name)) {
|
||||
// Class is a reserved word
|
||||
if (/\b[Cc]lass\b/.test(package_name)) {
|
||||
return Q.reject(new CordovaError(msg + '"class" is a reserved word'));
|
||||
}
|
||||
|
||||
@ -200,19 +199,19 @@ function validatePackageName(package_name) {
|
||||
* Returns a promise, fulfilled if the project name is acceptable; rejected
|
||||
* otherwise.
|
||||
*/
|
||||
function validateProjectName(project_name) {
|
||||
function validateProjectName (project_name) {
|
||||
var msg = 'Error validating project name. ';
|
||||
//Make sure there's something there
|
||||
// Make sure there's something there
|
||||
if (project_name === '') {
|
||||
return Q.reject(new CordovaError(msg + 'Project name cannot be empty'));
|
||||
}
|
||||
|
||||
//Enforce stupid name error
|
||||
// Enforce stupid name error
|
||||
if (project_name === 'CordovaActivity') {
|
||||
return Q.reject(new CordovaError(msg + 'Project name cannot be CordovaActivity'));
|
||||
}
|
||||
|
||||
//Classes in Java don't begin with numbers
|
||||
// Classes in Java don't begin with numbers
|
||||
if (/^[0-9]/.test(project_name)) {
|
||||
return Q.reject(new CordovaError(msg + 'Project name must not begin with a number'));
|
||||
}
|
||||
@ -238,29 +237,29 @@ function validateProjectName(project_name) {
|
||||
*
|
||||
* @return {Promise<String>} Directory where application has been created
|
||||
*/
|
||||
exports.create = function(project_path, config, options, events) {
|
||||
exports.create = function (project_path, config, options, events) {
|
||||
|
||||
options = options || {};
|
||||
|
||||
// Set default values for path, package and name
|
||||
project_path = path.relative(process.cwd(), (project_path || 'CordovaExample'));
|
||||
// Check if project already exists
|
||||
if(fs.existsSync(project_path)) {
|
||||
if (fs.existsSync(project_path)) {
|
||||
return Q.reject(new CordovaError('Project already exists! Delete and recreate'));
|
||||
}
|
||||
|
||||
var package_name = config.packageName() || 'my.cordova.project';
|
||||
var project_name = config.name() ?
|
||||
config.name().replace(/[^\w.]/g,'_') : 'CordovaExample';
|
||||
config.name().replace(/[^\w.]/g, '_') : 'CordovaExample';
|
||||
|
||||
var safe_activity_name = config.android_activityName() || options.activityName || 'MainActivity';
|
||||
var target_api = check_reqs.get_target();
|
||||
var target_api = check_reqs.get_target();
|
||||
|
||||
//Make the package conform to Java package types
|
||||
// Make the package conform to Java package types
|
||||
return validatePackageName(package_name)
|
||||
.then(function() {
|
||||
validateProjectName(project_name);
|
||||
}).then(function() {
|
||||
.then(function () {
|
||||
validateProjectName(project_name);
|
||||
}).then(function () {
|
||||
// Log the given values for the project
|
||||
events.emit('log', 'Creating Cordova project for the Android platform:');
|
||||
events.emit('log', '\tPath: ' + project_path);
|
||||
@ -324,9 +323,9 @@ exports.create = function(project_path, config, options, events) {
|
||||
}).thenResolve(project_path);
|
||||
};
|
||||
|
||||
function generateDoneMessage(type, link) {
|
||||
function generateDoneMessage (type, link) {
|
||||
var pkg = require('../../package');
|
||||
var msg = 'Android project ' + (type == 'update' ? 'updated ' : 'created ') + 'with ' + pkg.name + '@' + pkg.version;
|
||||
var msg = 'Android project ' + (type === 'update' ? 'updated ' : 'created ') + 'with ' + pkg.name + '@' + pkg.version;
|
||||
if (link) {
|
||||
msg += ' and has a linked CordovaLib';
|
||||
}
|
||||
@ -334,11 +333,11 @@ function generateDoneMessage(type, link) {
|
||||
}
|
||||
|
||||
// Returns a promise.
|
||||
exports.update = function(projectPath, options, events) {
|
||||
exports.update = function (projectPath, options, events) {
|
||||
options = options || {};
|
||||
|
||||
return Q()
|
||||
.then(function() {
|
||||
.then(function () {
|
||||
|
||||
var isAndroidStudio = AndroidStudio.isAndroidStudioProject(projectPath);
|
||||
var isLegacy = !isAndroidStudio;
|
||||
@ -353,15 +352,15 @@ exports.update = function(projectPath, options, events) {
|
||||
builder = 'gradle';
|
||||
}
|
||||
|
||||
if (Number(manifest.getMinSdkVersion()) < MIN_SDK_VERSION) {
|
||||
events.emit('verbose', 'Updating minSdkVersion to ' + MIN_SDK_VERSION + ' in AndroidManifest.xml');
|
||||
manifest.setMinSdkVersion(MIN_SDK_VERSION);
|
||||
}
|
||||
if (Number(manifest.getMinSdkVersion()) < MIN_SDK_VERSION) {
|
||||
events.emit('verbose', 'Updating minSdkVersion to ' + MIN_SDK_VERSION + ' in AndroidManifest.xml');
|
||||
manifest.setMinSdkVersion(MIN_SDK_VERSION);
|
||||
}
|
||||
|
||||
manifest.setDebuggable(false).write();
|
||||
manifest.setDebuggable(false).write();
|
||||
|
||||
var projectName = manifest.getActivity().getName();
|
||||
var target_api = check_reqs.get_target();
|
||||
var projectName = manifest.getActivity().getName();
|
||||
var target_api = check_reqs.get_target();
|
||||
|
||||
copyJsAndLibrary(projectPath, options.link, projectName, isLegacy);
|
||||
copyScripts(projectPath);
|
||||
@ -372,7 +371,6 @@ exports.update = function(projectPath, options, events) {
|
||||
}).thenResolve(projectPath);
|
||||
};
|
||||
|
||||
|
||||
// For testing
|
||||
exports.validatePackageName = validatePackageName;
|
||||
exports.validateProjectName = validateProjectName;
|
||||
|
137
bin/templates/cordova/Api.js
vendored
137
bin/templates/cordova/Api.js
vendored
@ -29,8 +29,7 @@ var selfEvents = require('cordova-common').events;
|
||||
|
||||
var PLATFORM = 'android';
|
||||
|
||||
|
||||
function setupEvents(externalEventEmitter) {
|
||||
function setupEvents (externalEventEmitter) {
|
||||
if (externalEventEmitter) {
|
||||
// This will make the platform internal events visible outside
|
||||
selfEvents.forwardEventsTo(externalEventEmitter);
|
||||
@ -43,7 +42,6 @@ function setupEvents(externalEventEmitter) {
|
||||
return selfEvents;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class, that acts as abstraction over particular platform. Encapsulates the
|
||||
* platform's properties and methods.
|
||||
@ -55,7 +53,7 @@ function setupEvents(externalEventEmitter) {
|
||||
*
|
||||
* * platform: String that defines a platform name.
|
||||
*/
|
||||
function Api(platform, platformRootDir, events) {
|
||||
function Api (platform, platformRootDir, events) {
|
||||
this.platform = PLATFORM;
|
||||
this.root = path.resolve(__dirname, '..');
|
||||
this.builder = 'gradle';
|
||||
@ -82,16 +80,16 @@ function Api(platform, platformRootDir, events) {
|
||||
|
||||
// XXX Override some locations for Android Studio projects
|
||||
if(AndroidStudio.isAndroidStudioProject(self.root) === true) {
|
||||
selfEvents.emit('log', 'Android Studio project detected');
|
||||
this.builder='studio';
|
||||
this.android_studio = true;
|
||||
this.locations.configXml = path.join(self.root, 'app/src/main/res/xml/config.xml');
|
||||
this.locations.strings = path.join(self.root, 'app/src/main/res/values/strings.xml');
|
||||
this.locations.manifest = path.join(self.root, 'app/src/main/AndroidManifest.xml');
|
||||
//We could have Java Source, we could have other languages
|
||||
this.locations.javaSrc = path.join(self.root, 'app/src/main/java/');
|
||||
this.locations.www = path.join(self.root, 'app/src/main/assets/www');
|
||||
this.locations.res = path.join(self.root, 'app/src/main/res');
|
||||
selfEvents.emit('log', 'Android Studio project detected');
|
||||
this.builder='studio';
|
||||
this.android_studio = true;
|
||||
this.locations.configXml = path.join(self.root, 'app/src/main/res/xml/config.xml');
|
||||
this.locations.strings = path.join(self.root, 'app/src/main/res/values/strings.xml');
|
||||
this.locations.manifest = path.join(self.root, 'app/src/main/AndroidManifest.xml');
|
||||
//We could have Java Source, we could have other languages
|
||||
this.locations.javaSrc = path.join(self.root, 'app/src/main/java/');
|
||||
this.locations.www = path.join(self.root, 'app/src/main/assets/www');
|
||||
this.locations.res = path.join(self.root, 'app/src/main/res');
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,16 +115,13 @@ Api.createPlatform = function (destination, config, options, events) {
|
||||
events = setupEvents(events);
|
||||
var result;
|
||||
try {
|
||||
result = require('../../lib/create')
|
||||
.create(destination, config, options, events)
|
||||
.then(function (destination) {
|
||||
result = require('../../lib/create').create(destination, config, options, events).then(function (destination) {
|
||||
var PlatformApi = require(path.resolve(destination, 'cordova/Api'));
|
||||
return new PlatformApi(PLATFORM, destination, events);
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
events.emit('error','createPlatform is not callable from the android project API.');
|
||||
throw(e);
|
||||
} catch (e) {
|
||||
events.emit('error', 'createPlatform is not callable from the android project API.');
|
||||
throw (e);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
@ -151,16 +146,13 @@ Api.updatePlatform = function (destination, options, events) {
|
||||
events = setupEvents(events);
|
||||
var result;
|
||||
try {
|
||||
result = require('../../lib/create')
|
||||
.update(destination, options, events)
|
||||
.then(function (destination) {
|
||||
result = require('../../lib/create').update(destination, options, events).then(function (destination) {
|
||||
var PlatformApi = require(path.resolve(destination, 'cordova/Api'));
|
||||
return new PlatformApi('android', destination, events);
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
events.emit('error','updatePlatform is not callable from the android project API, you will need to do this manually.');
|
||||
throw(e);
|
||||
} catch (e) {
|
||||
events.emit('error', 'updatePlatform is not callable from the android project API, you will need to do this manually.');
|
||||
throw (e);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
@ -231,41 +223,35 @@ Api.prototype.addPlugin = function (plugin, installOptions) {
|
||||
installOptions.variables.PACKAGE_NAME = project.getPackageName();
|
||||
}
|
||||
|
||||
if(this.android_studio === true) {
|
||||
installOptions.android_studio = true;
|
||||
if (this.android_studio === true) {
|
||||
installOptions.android_studio = true;
|
||||
}
|
||||
|
||||
return Q()
|
||||
.then(function () {
|
||||
//CB-11964: Do a clean when installing the plugin code to get around
|
||||
//the Gradle bug introduced by the Android Gradle Plugin Version 2.2
|
||||
//TODO: Delete when the next version of Android Gradle plugin comes out
|
||||
return Q().then(function () {
|
||||
// CB-11964: Do a clean when installing the plugin code to get around
|
||||
// the Gradle bug introduced by the Android Gradle Plugin Version 2.2
|
||||
// TODO: Delete when the next version of Android Gradle plugin comes out
|
||||
// Since clean doesn't just clean the build, it also wipes out www, we need
|
||||
// to pass additional options.
|
||||
|
||||
// Since clean doesn't just clean the build, it also wipes out www, we need
|
||||
// to pass additional options.
|
||||
// Do some basic argument parsing
|
||||
var opts = {};
|
||||
|
||||
// Do some basic argument parsing
|
||||
var opts = {};
|
||||
// Skip cleaning prepared files when not invoking via cordova CLI.
|
||||
opts.noPrepare = true;
|
||||
|
||||
// Skip cleaning prepared files when not invoking via cordova CLI.
|
||||
opts.noPrepare = true;
|
||||
|
||||
if(!AndroidStudio.isAndroidStudioProject(self.root) && !project.isClean()) {
|
||||
return self.clean(opts);
|
||||
}
|
||||
})
|
||||
.then(function () {
|
||||
return PluginManager.get(self.platform, self.locations, project)
|
||||
.addPlugin(plugin, installOptions);
|
||||
})
|
||||
.then(function () {
|
||||
if (plugin.getFrameworks(this.platform).length === 0) return;
|
||||
|
||||
selfEvents.emit('verbose', 'Updating build files since android plugin contained <framework>');
|
||||
//This should pick the correct builder, not just get gradle
|
||||
require('./lib/builders/builders').getBuilder(this.builder).prepBuildFiles();
|
||||
}.bind(this))
|
||||
// CB-11022 Return truthy value to prevent running prepare after
|
||||
if (!AndroidStudio.isAndroidStudioProject(self.root) && !project.isClean()) {
|
||||
return self.clean(opts);
|
||||
}
|
||||
}).then(function () {
|
||||
return PluginManager.get(self.platform, self.locations, project).addPlugin(plugin, installOptions);
|
||||
}).then(function () {
|
||||
if (plugin.getFrameworks(this.platform).length === 0) return;
|
||||
selfEvents.emit('verbose', 'Updating build files since android plugin contained <framework>');
|
||||
//This should pick the correct builder, not just get gradle
|
||||
require('./lib/builders/builders').getBuilder(this.builder).prepBuildFiles();
|
||||
}.bind(this))
|
||||
// CB-11022 Return truthy value to prevent running prepare after
|
||||
.thenResolve(true);
|
||||
};
|
||||
|
||||
@ -285,9 +271,9 @@ Api.prototype.addPlugin = function (plugin, installOptions) {
|
||||
Api.prototype.removePlugin = function (plugin, uninstallOptions) {
|
||||
var project = AndroidProject.getProjectFile(this.root);
|
||||
|
||||
if(uninstallOptions && uninstallOptions.usePlatformWww === true && this.android_studio === true) {
|
||||
uninstallOptions.usePlatformWww = false;
|
||||
uninstallOptions.android_studio = true;
|
||||
if (uninstallOptions && uninstallOptions.usePlatformWww === true && this.android_studio === true) {
|
||||
uninstallOptions.usePlatformWww = false;
|
||||
uninstallOptions.android_studio = true;
|
||||
}
|
||||
|
||||
return PluginManager.get(this.platform, this.locations, project)
|
||||
@ -351,11 +337,9 @@ Api.prototype.build = function (buildOptions) {
|
||||
var self = this;
|
||||
if(this.android_studio)
|
||||
buildOptions.studio = true;
|
||||
return require('./lib/check_reqs').run()
|
||||
.then(function () {
|
||||
return require('./lib/check_reqs').run() .then(function () {
|
||||
return require('./lib/build').run.call(self, buildOptions);
|
||||
})
|
||||
.then(function (buildResults) {
|
||||
}).then(function (buildResults) {
|
||||
// Cast build result to array of build artifacts
|
||||
return buildResults.apkPaths.map(function (apkPath) {
|
||||
return {
|
||||
@ -380,10 +364,9 @@ Api.prototype.build = function (buildOptions) {
|
||||
* @return {Promise} A promise either fulfilled if package was built and ran
|
||||
* successfully, or rejected with CordovaError.
|
||||
*/
|
||||
Api.prototype.run = function(runOptions) {
|
||||
Api.prototype.run = function (runOptions) {
|
||||
var self = this;
|
||||
return require('./lib/check_reqs').run()
|
||||
.then(function () {
|
||||
return require('./lib/check_reqs').run().then(function () {
|
||||
return require('./lib/run').run.call(self, runOptions);
|
||||
});
|
||||
};
|
||||
@ -395,19 +378,15 @@ Api.prototype.run = function(runOptions) {
|
||||
* @return {Promise} Return a promise either fulfilled, or rejected with
|
||||
* CordovaError.
|
||||
*/
|
||||
Api.prototype.clean = function(cleanOptions) {
|
||||
Api.prototype.clean = function (cleanOptions) {
|
||||
var self = this;
|
||||
return require('./lib/check_reqs').run()
|
||||
.then(function () {
|
||||
return require('./lib/build').runClean.call(self, cleanOptions);
|
||||
})
|
||||
.then(function () {
|
||||
return require('./lib/prepare').clean.call(self, cleanOptions);
|
||||
});
|
||||
return require('./lib/check_reqs').run().then(function () {
|
||||
return require('./lib/build').runClean.call(self, cleanOptions);
|
||||
}).then(function () {
|
||||
return require('./lib/prepare').clean.call(self, cleanOptions);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Performs a requirements check for current platform. Each platform defines its
|
||||
* own set of requirements, which should be resolved before platform can be
|
||||
@ -416,7 +395,7 @@ Api.prototype.clean = function(cleanOptions) {
|
||||
* @return {Promise<Requirement[]>} Promise, resolved with set of Requirement
|
||||
* objects for current platform.
|
||||
*/
|
||||
Api.prototype.requirements = function() {
|
||||
Api.prototype.requirements = function () {
|
||||
return require('./lib/check_reqs').check_all();
|
||||
};
|
||||
|
||||
|
16
bin/templates/cordova/lib/Adb.js
vendored
16
bin/templates/cordova/lib/Adb.js
vendored
@ -25,11 +25,11 @@ var CordovaError = require('cordova-common').CordovaError;
|
||||
|
||||
var Adb = {};
|
||||
|
||||
function isDevice(line) {
|
||||
function isDevice (line) {
|
||||
return line.match(/\w+\tdevice/) && !line.match(/emulator/);
|
||||
}
|
||||
|
||||
function isEmulator(line) {
|
||||
function isEmulator (line) {
|
||||
return line.match(/device/) && line.match(/emulator/);
|
||||
}
|
||||
|
||||
@ -44,8 +44,7 @@ function isEmulator(line) {
|
||||
* devices/emulators
|
||||
*/
|
||||
Adb.devices = function (opts) {
|
||||
return spawn('adb', ['devices'], {cwd: os.tmpdir()})
|
||||
.then(function(output) {
|
||||
return spawn('adb', ['devices'], {cwd: os.tmpdir()}).then(function (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);
|
||||
@ -59,8 +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 spawn('adb', args.concat(packagePath), {cwd: os.tmpdir()}).then(function (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/)) {
|
||||
@ -86,8 +84,7 @@ 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 spawn('adb', args.concat(shellCommand), {cwd: os.tmpdir()}).catch(function (output) {
|
||||
return Q.reject(new CordovaError('Failed to execute shell command "' +
|
||||
shellCommand + '"" on device: ' + output));
|
||||
});
|
||||
@ -95,8 +92,7 @@ Adb.shell = function (target, shellCommand) {
|
||||
|
||||
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(function (output) {
|
||||
return Q.reject(new CordovaError('Failed to start application "' +
|
||||
activityName + '"" on device: ' + output));
|
||||
});
|
||||
|
39
bin/templates/cordova/lib/AndroidManifest.js
vendored
39
bin/templates/cordova/lib/AndroidManifest.js
vendored
@ -19,12 +19,12 @@
|
||||
|
||||
var fs = require('fs');
|
||||
var et = require('elementtree');
|
||||
var xml= require('cordova-common').xmlHelpers;
|
||||
var xml = require('cordova-common').xmlHelpers;
|
||||
|
||||
var DEFAULT_ORIENTATION = 'default';
|
||||
|
||||
/** Wraps an AndroidManifest file */
|
||||
function AndroidManifest(path) {
|
||||
function AndroidManifest (path) {
|
||||
this.path = path;
|
||||
this.doc = xml.parseElementtreeSync(path);
|
||||
if (this.doc.getroot().tag !== 'manifest') {
|
||||
@ -32,38 +32,38 @@ function AndroidManifest(path) {
|
||||
}
|
||||
}
|
||||
|
||||
AndroidManifest.prototype.getVersionName = function() {
|
||||
AndroidManifest.prototype.getVersionName = function () {
|
||||
return this.doc.getroot().attrib['android:versionName'];
|
||||
};
|
||||
|
||||
AndroidManifest.prototype.setVersionName = function(versionName) {
|
||||
AndroidManifest.prototype.setVersionName = function (versionName) {
|
||||
this.doc.getroot().attrib['android:versionName'] = versionName;
|
||||
return this;
|
||||
};
|
||||
|
||||
AndroidManifest.prototype.getVersionCode = function() {
|
||||
AndroidManifest.prototype.getVersionCode = function () {
|
||||
return this.doc.getroot().attrib['android:versionCode'];
|
||||
};
|
||||
|
||||
AndroidManifest.prototype.setVersionCode = function(versionCode) {
|
||||
AndroidManifest.prototype.setVersionCode = function (versionCode) {
|
||||
this.doc.getroot().attrib['android:versionCode'] = versionCode;
|
||||
return this;
|
||||
};
|
||||
|
||||
AndroidManifest.prototype.getPackageId = function() {
|
||||
/*jshint -W069 */
|
||||
AndroidManifest.prototype.getPackageId = function () {
|
||||
/* jshint -W069 */
|
||||
return this.doc.getroot().attrib['package'];
|
||||
/*jshint +W069 */
|
||||
/* jshint +W069 */
|
||||
};
|
||||
|
||||
AndroidManifest.prototype.setPackageId = function(pkgId) {
|
||||
/*jshint -W069 */
|
||||
AndroidManifest.prototype.setPackageId = function (pkgId) {
|
||||
/* jshint -W069 */
|
||||
this.doc.getroot().attrib['package'] = pkgId;
|
||||
/*jshint +W069 */
|
||||
/* jshint +W069 */
|
||||
return this;
|
||||
};
|
||||
|
||||
AndroidManifest.prototype.getActivity = function() {
|
||||
AndroidManifest.prototype.getActivity = function () {
|
||||
var activity = this.doc.getroot().find('./application/activity');
|
||||
return {
|
||||
getName: function () {
|
||||
@ -102,17 +102,16 @@ AndroidManifest.prototype.getActivity = function() {
|
||||
};
|
||||
};
|
||||
|
||||
['minSdkVersion', 'maxSdkVersion', 'targetSdkVersion']
|
||||
.forEach(function(sdkPrefName) {
|
||||
['minSdkVersion', 'maxSdkVersion', 'targetSdkVersion'].forEach(function (sdkPrefName) {
|
||||
// Copy variable reference to avoid closure issues
|
||||
var prefName = sdkPrefName;
|
||||
|
||||
AndroidManifest.prototype['get' + capitalize(prefName)] = function() {
|
||||
AndroidManifest.prototype['get' + capitalize(prefName)] = function () {
|
||||
var usesSdk = this.doc.getroot().find('./uses-sdk');
|
||||
return usesSdk && usesSdk.attrib['android:' + prefName];
|
||||
};
|
||||
|
||||
AndroidManifest.prototype['set' + capitalize(prefName)] = function(prefValue) {
|
||||
AndroidManifest.prototype['set' + capitalize(prefName)] = function (prefValue) {
|
||||
var usesSdk = this.doc.getroot().find('./uses-sdk');
|
||||
|
||||
if (!usesSdk && prefValue) { // if there is no required uses-sdk element, we should create it first
|
||||
@ -128,11 +127,11 @@ AndroidManifest.prototype.getActivity = function() {
|
||||
};
|
||||
});
|
||||
|
||||
AndroidManifest.prototype.getDebuggable = function() {
|
||||
AndroidManifest.prototype.getDebuggable = function () {
|
||||
return this.doc.getroot().find('./application').attrib['android:debuggable'] === 'true';
|
||||
};
|
||||
|
||||
AndroidManifest.prototype.setDebuggable = function(value) {
|
||||
AndroidManifest.prototype.setDebuggable = function (value) {
|
||||
var application = this.doc.getroot().find('./application');
|
||||
if (value) {
|
||||
application.attrib['android:debuggable'] = 'true';
|
||||
@ -150,7 +149,7 @@ AndroidManifest.prototype.setDebuggable = function(value) {
|
||||
* @param {String} [destPath] File to write manifest to. If omitted,
|
||||
* manifest will be written to file it has been read from.
|
||||
*/
|
||||
AndroidManifest.prototype.write = function(destPath) {
|
||||
AndroidManifest.prototype.write = function (destPath) {
|
||||
fs.writeFileSync(destPath || this.path, this.doc.write({indent: 4}), 'utf-8');
|
||||
};
|
||||
|
||||
|
41
bin/templates/cordova/lib/AndroidProject.js
vendored
41
bin/templates/cordova/lib/AndroidProject.js
vendored
@ -26,16 +26,15 @@ var pluginHandlers = require('./pluginHandlers');
|
||||
|
||||
var projectFileCache = {};
|
||||
|
||||
function addToPropertyList(projectProperties, key, value) {
|
||||
function addToPropertyList (projectProperties, key, value) {
|
||||
var i = 1;
|
||||
while (projectProperties.get(key + '.' + i))
|
||||
i++;
|
||||
while (projectProperties.get(key + '.' + i)) { i++; }
|
||||
|
||||
projectProperties.set(key + '.' + i, value);
|
||||
projectProperties.dirty = true;
|
||||
}
|
||||
|
||||
function removeFromPropertyList(projectProperties, key, value) {
|
||||
function removeFromPropertyList (projectProperties, key, value) {
|
||||
var i = 1;
|
||||
var currentValue;
|
||||
while ((currentValue = projectProperties.get(key + '.' + i))) {
|
||||
@ -54,18 +53,18 @@ function removeFromPropertyList(projectProperties, key, value) {
|
||||
|
||||
function getRelativeLibraryPath (parentDir, subDir) {
|
||||
var libraryPath = path.relative(parentDir, subDir);
|
||||
return (path.sep == '\\') ? libraryPath.replace(/\\/g, '/') : libraryPath;
|
||||
return (path.sep === '\\') ? libraryPath.replace(/\\/g, '/') : libraryPath;
|
||||
}
|
||||
|
||||
function AndroidProject(projectDir) {
|
||||
function AndroidProject (projectDir) {
|
||||
this._propertiesEditors = {};
|
||||
this._subProjectDirs = {};
|
||||
this._dirty = false;
|
||||
this.projectDir = projectDir;
|
||||
this.platformWww = path.join(this.projectDir, 'platform_www');
|
||||
this.www = path.join(this.projectDir, 'assets/www');
|
||||
if(AndroidStudio.isAndroidStudioProject(projectDir) === true) {
|
||||
this.www = path.join(this.projectDir, 'app/src/main/assets/www');
|
||||
if (AndroidStudio.isAndroidStudioProject(projectDir) === true) {
|
||||
this.www = path.join(this.projectDir, 'app/src/main/assets/www');
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,15 +91,15 @@ AndroidProject.purgeCache = function (projectDir) {
|
||||
*
|
||||
* @return {String} The name of the package
|
||||
*/
|
||||
AndroidProject.prototype.getPackageName = function() {
|
||||
AndroidProject.prototype.getPackageName = function () {
|
||||
var manifestPath = path.join(this.projectDir, 'AndroidManifest.xml');
|
||||
if(AndroidStudio.isAndroidStudioProject(this.projectDir) === true) {
|
||||
manifestPath = path.join(this.projectDir, 'app/src/main/AndroidManifest.xml');
|
||||
if (AndroidStudio.isAndroidStudioProject(this.projectDir) === true) {
|
||||
manifestPath = path.join(this.projectDir, 'app/src/main/AndroidManifest.xml');
|
||||
}
|
||||
return new AndroidManifest(manifestPath).getPackageId();
|
||||
};
|
||||
|
||||
AndroidProject.prototype.getCustomSubprojectRelativeDir = function(plugin_id, src) {
|
||||
AndroidProject.prototype.getCustomSubprojectRelativeDir = function (plugin_id, src) {
|
||||
// All custom subprojects are prefixed with the last portion of the package id.
|
||||
// This is to avoid collisions when opening multiple projects in Eclipse that have subprojects with the same name.
|
||||
var packageName = this.getPackageName();
|
||||
@ -110,7 +109,7 @@ AndroidProject.prototype.getCustomSubprojectRelativeDir = function(plugin_id, sr
|
||||
return subRelativeDir;
|
||||
};
|
||||
|
||||
AndroidProject.prototype.addSubProject = function(parentDir, subDir) {
|
||||
AndroidProject.prototype.addSubProject = function (parentDir, subDir) {
|
||||
var parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||
var subProjectFile = path.resolve(subDir, 'project.properties');
|
||||
var parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||
@ -126,7 +125,7 @@ AndroidProject.prototype.addSubProject = function(parentDir, subDir) {
|
||||
this._dirty = true;
|
||||
};
|
||||
|
||||
AndroidProject.prototype.removeSubProject = function(parentDir, subDir) {
|
||||
AndroidProject.prototype.removeSubProject = function (parentDir, subDir) {
|
||||
var parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||
var parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||
removeFromPropertyList(parentProperties, 'android.library.reference', getRelativeLibraryPath(parentDir, subDir));
|
||||
@ -134,35 +133,35 @@ AndroidProject.prototype.removeSubProject = function(parentDir, subDir) {
|
||||
this._dirty = true;
|
||||
};
|
||||
|
||||
AndroidProject.prototype.addGradleReference = function(parentDir, subDir) {
|
||||
AndroidProject.prototype.addGradleReference = function (parentDir, subDir) {
|
||||
var parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||
var parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||
addToPropertyList(parentProperties, 'cordova.gradle.include', getRelativeLibraryPath(parentDir, subDir));
|
||||
this._dirty = true;
|
||||
};
|
||||
|
||||
AndroidProject.prototype.removeGradleReference = function(parentDir, subDir) {
|
||||
AndroidProject.prototype.removeGradleReference = function (parentDir, subDir) {
|
||||
var parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||
var parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||
removeFromPropertyList(parentProperties, 'cordova.gradle.include', getRelativeLibraryPath(parentDir, subDir));
|
||||
this._dirty = true;
|
||||
};
|
||||
|
||||
AndroidProject.prototype.addSystemLibrary = function(parentDir, value) {
|
||||
AndroidProject.prototype.addSystemLibrary = function (parentDir, value) {
|
||||
var parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||
var parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||
addToPropertyList(parentProperties, 'cordova.system.library', value);
|
||||
this._dirty = true;
|
||||
};
|
||||
|
||||
AndroidProject.prototype.removeSystemLibrary = function(parentDir, value) {
|
||||
AndroidProject.prototype.removeSystemLibrary = function (parentDir, value) {
|
||||
var parentProjectFile = path.resolve(parentDir, 'project.properties');
|
||||
var parentProperties = this._getPropertiesFile(parentProjectFile);
|
||||
removeFromPropertyList(parentProperties, 'cordova.system.library', value);
|
||||
this._dirty = true;
|
||||
};
|
||||
|
||||
AndroidProject.prototype.write = function() {
|
||||
AndroidProject.prototype.write = function () {
|
||||
if (!this._dirty) {
|
||||
return;
|
||||
}
|
||||
@ -201,9 +200,9 @@ AndroidProject.prototype.getUninstaller = function (type) {
|
||||
* This checks if an Android project is clean or has old build artifacts
|
||||
*/
|
||||
|
||||
AndroidProject.prototype.isClean = function() {
|
||||
AndroidProject.prototype.isClean = function () {
|
||||
var build_path = path.join(this.projectDir, 'build');
|
||||
//If the build directory doesn't exist, it's clean
|
||||
// If the build directory doesn't exist, it's clean
|
||||
return !(fs.existsSync(build_path));
|
||||
};
|
||||
|
||||
|
14
bin/templates/cordova/lib/AndroidStudio.js
vendored
14
bin/templates/cordova/lib/AndroidStudio.js
vendored
@ -4,7 +4,7 @@
|
||||
* @param {String} root Root folder of the project
|
||||
*/
|
||||
|
||||
/*jshint esnext: false */
|
||||
/* jshint esnext: false */
|
||||
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
@ -18,21 +18,21 @@ module.exports.isAndroidStudioProject = function isAndroidStudioProject(root) {
|
||||
var isEclipse = false;
|
||||
var isAS = true;
|
||||
|
||||
if(!fs.existsSync(root)) {
|
||||
if (!fs.existsSync(root)) {
|
||||
throw new CordovaError('AndroidStudio.js:inAndroidStudioProject root does not exist: ' + root);
|
||||
}
|
||||
|
||||
// if any of the following exists, then we are not an ASProj
|
||||
eclipseFiles.forEach(function(file) {
|
||||
if(fs.existsSync(path.join(root, file))) {
|
||||
eclipseFiles.forEach(function (file) {
|
||||
if (fs.existsSync(path.join(root, file))) {
|
||||
isEclipse = true;
|
||||
}
|
||||
});
|
||||
|
||||
// if it is NOT an eclipse project, check that all required files exist
|
||||
if(!isEclipse) {
|
||||
androidStudioFiles.forEach(function(file){
|
||||
if(!fs.existsSync(path.join(root, file))) {
|
||||
if (!isEclipse) {
|
||||
androidStudioFiles.forEach(function (file) {
|
||||
if (!fs.existsSync(path.join(root, file))) {
|
||||
console.log('missing file :: ' + file);
|
||||
isAS = false;
|
||||
}
|
||||
|
37
bin/templates/cordova/lib/android_sdk.js
vendored
37
bin/templates/cordova/lib/android_sdk.js
vendored
@ -17,8 +17,8 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var Q = require('q'),
|
||||
superspawn = require('cordova-common').superspawn;
|
||||
var Q = require('q');
|
||||
var superspawn = require('cordova-common').superspawn;
|
||||
|
||||
var suffix_number_regex = /(\d+)$/;
|
||||
// Used for sorting Android targets, example strings to sort:
|
||||
@ -29,7 +29,7 @@ var suffix_number_regex = /(\d+)$/;
|
||||
// The idea is to sort based on largest "suffix" number - meaning the bigger
|
||||
// the number at the end, the more recent the target, the closer to the
|
||||
// start of the array.
|
||||
function sort_by_largest_numerical_suffix(a, b) {
|
||||
function sort_by_largest_numerical_suffix (a, b) {
|
||||
var suffix_a = a.match(suffix_number_regex);
|
||||
var suffix_b = b.match(suffix_number_regex);
|
||||
if (suffix_a && suffix_b) {
|
||||
@ -43,9 +43,8 @@ function sort_by_largest_numerical_suffix(a, b) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.print_newest_available_sdk_target = function() {
|
||||
return module.exports.list_targets()
|
||||
.then(function(targets) {
|
||||
module.exports.print_newest_available_sdk_target = function () {
|
||||
return module.exports.list_targets().then(function (targets) {
|
||||
targets.sort(sort_by_largest_numerical_suffix);
|
||||
console.log(targets[0]);
|
||||
});
|
||||
@ -66,38 +65,34 @@ module.exports.version_string_to_api_level = {
|
||||
'7.1.1': 25
|
||||
};
|
||||
|
||||
function parse_targets(output) {
|
||||
function parse_targets (output) {
|
||||
var target_out = output.split('\n');
|
||||
var targets = [];
|
||||
for (var i = target_out.length - 1; i >= 0; i--) {
|
||||
if(target_out[i].match(/id:/)) { // if "id:" is in the line...
|
||||
targets.push(target_out[i].match(/"(.+)"/)[1]); //.. match whatever is in quotes.
|
||||
if (target_out[i].match(/id:/)) { // if "id:" is in the line...
|
||||
targets.push(target_out[i].match(/"(.+)"/)[1]); // .. match whatever is in quotes.
|
||||
}
|
||||
}
|
||||
return targets;
|
||||
}
|
||||
|
||||
module.exports.list_targets_with_android = function() {
|
||||
return superspawn.spawn('android', ['list', 'target'])
|
||||
.then(parse_targets);
|
||||
module.exports.list_targets_with_android = function () {
|
||||
return superspawn.spawn('android', ['list', 'target']).then(parse_targets);
|
||||
};
|
||||
|
||||
module.exports.list_targets_with_avdmanager = function() {
|
||||
return superspawn.spawn('avdmanager', ['list', 'target'])
|
||||
.then(parse_targets);
|
||||
module.exports.list_targets_with_avdmanager = function () {
|
||||
return superspawn.spawn('avdmanager', ['list', 'target']).then(parse_targets);
|
||||
};
|
||||
|
||||
module.exports.list_targets = function() {
|
||||
return module.exports.list_targets_with_avdmanager()
|
||||
.catch(function(err) {
|
||||
module.exports.list_targets = function () {
|
||||
return module.exports.list_targets_with_avdmanager().catch(function (err) {
|
||||
// If there's an error, like avdmanager could not be found, we can try
|
||||
// as a last resort, to run `android`, in case this is a super old
|
||||
// SDK installation.
|
||||
if (err && (err.code == 'ENOENT' || (err.stderr && err.stderr.match(/not recognized/)))) {
|
||||
if (err && (err.code === 'ENOENT' || (err.stderr && err.stderr.match(/not recognized/)))) {
|
||||
return module.exports.list_targets_with_android();
|
||||
} else throw err;
|
||||
})
|
||||
.then(function(targets) {
|
||||
}).then(function (targets) {
|
||||
if (targets.length === 0) {
|
||||
return Q.reject(new Error('No android targets (SDKs) installed!'));
|
||||
}
|
||||
|
88
bin/templates/cordova/lib/build.js
vendored
88
bin/templates/cordova/lib/build.js
vendored
@ -19,10 +19,10 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var Q = require('q'),
|
||||
path = require('path'),
|
||||
fs = require('fs'),
|
||||
nopt = require('nopt');
|
||||
var Q = require('q');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var nopt = require('nopt');
|
||||
|
||||
var Adb = require('./Adb');
|
||||
|
||||
@ -31,7 +31,7 @@ var events = require('cordova-common').events;
|
||||
var spawn = require('cordova-common').superspawn.spawn;
|
||||
var CordovaError = require('cordova-common').CordovaError;
|
||||
|
||||
function parseOpts(options, resolvedTarget, projectRoot) {
|
||||
function parseOpts (options, resolvedTarget, projectRoot) {
|
||||
options = options || {};
|
||||
options.argv = nopt({
|
||||
gradle: Boolean,
|
||||
@ -64,11 +64,9 @@ function parseOpts(options, resolvedTarget, projectRoot) {
|
||||
|
||||
if (options.nobuild) ret.buildMethod = 'none';
|
||||
|
||||
if (options.argv.versionCode)
|
||||
ret.extraArgs.push('-PcdvVersionCode=' + options.argv.versionCode);
|
||||
if (options.argv.versionCode) { ret.extraArgs.push('-PcdvVersionCode=' + options.argv.versionCode); }
|
||||
|
||||
if (options.argv.minSdkVersion)
|
||||
ret.extraArgs.push('-PcdvMinSdkVersion=' + options.argv.minSdkVersion);
|
||||
if (options.argv.minSdkVersion) { ret.extraArgs.push('-PcdvMinSdkVersion=' + options.argv.minSdkVersion); }
|
||||
|
||||
if (options.argv.gradleArg) {
|
||||
ret.extraArgs = ret.extraArgs.concat(options.argv.gradleArg);
|
||||
@ -76,12 +74,10 @@ function parseOpts(options, resolvedTarget, projectRoot) {
|
||||
|
||||
var packageArgs = {};
|
||||
|
||||
if (options.argv.keystore)
|
||||
packageArgs.keystore = path.relative(projectRoot, path.resolve(options.argv.keystore));
|
||||
if (options.argv.keystore) { packageArgs.keystore = path.relative(projectRoot, path.resolve(options.argv.keystore)); }
|
||||
|
||||
['alias','storePassword','password','keystoreType'].forEach(function (flagName) {
|
||||
if (options.argv[flagName])
|
||||
packageArgs[flagName] = options.argv[flagName];
|
||||
['alias', 'storePassword', 'password', 'keystoreType'].forEach(function (flagName) {
|
||||
if (options.argv[flagName]) { packageArgs[flagName] = options.argv[flagName]; }
|
||||
});
|
||||
|
||||
var buildConfig = options.buildConfig;
|
||||
@ -92,20 +88,20 @@ function parseOpts(options, resolvedTarget, projectRoot) {
|
||||
if (!fs.existsSync(buildConfig)) {
|
||||
throw new Error('Specified build config file does not exist: ' + buildConfig);
|
||||
}
|
||||
events.emit('log', 'Reading build config file: '+ path.resolve(buildConfig));
|
||||
events.emit('log', 'Reading build config file: ' + path.resolve(buildConfig));
|
||||
var buildjson = fs.readFileSync(buildConfig, 'utf8');
|
||||
var config = JSON.parse(buildjson.replace(/^\ufeff/, '')); // Remove BOM
|
||||
if (config.android && config.android[ret.buildType]) {
|
||||
var androidInfo = config.android[ret.buildType];
|
||||
if(androidInfo.keystore && !packageArgs.keystore) {
|
||||
if(androidInfo.keystore.substr(0,1) === '~') {
|
||||
if (androidInfo.keystore && !packageArgs.keystore) {
|
||||
if (androidInfo.keystore.substr(0, 1) === '~') {
|
||||
androidInfo.keystore = process.env.HOME + androidInfo.keystore.substr(1);
|
||||
}
|
||||
packageArgs.keystore = path.resolve(path.dirname(buildConfig), androidInfo.keystore);
|
||||
events.emit('log', 'Reading the keystore from: ' + packageArgs.keystore);
|
||||
}
|
||||
|
||||
['alias', 'storePassword', 'password','keystoreType'].forEach(function (key){
|
||||
['alias', 'storePassword', 'password', 'keystoreType'].forEach(function (key) {
|
||||
packageArgs[key] = packageArgs[key] || androidInfo[key];
|
||||
});
|
||||
}
|
||||
@ -116,8 +112,8 @@ function parseOpts(options, resolvedTarget, projectRoot) {
|
||||
packageArgs.password, packageArgs.keystoreType);
|
||||
}
|
||||
|
||||
if(!ret.packageInfo) {
|
||||
if(Object.keys(packageArgs).length > 0) {
|
||||
if (!ret.packageInfo) {
|
||||
if (Object.keys(packageArgs).length > 0) {
|
||||
events.emit('warn', '\'keystore\' and \'alias\' need to be specified to generate a signed archive.');
|
||||
}
|
||||
}
|
||||
@ -129,11 +125,10 @@ function parseOpts(options, resolvedTarget, projectRoot) {
|
||||
* Builds the project with the specifed options
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.runClean = function(options) {
|
||||
module.exports.runClean = function (options) {
|
||||
var opts = parseOpts(options, null, this.root);
|
||||
var builder = builders.getBuilder(opts.buildMethod);
|
||||
return builder.prepEnv(opts)
|
||||
.then(function() {
|
||||
return builder.prepEnv(opts).then(function () {
|
||||
return builder.clean(opts);
|
||||
});
|
||||
};
|
||||
@ -150,18 +145,16 @@ module.exports.runClean = function(options) {
|
||||
* @return {Promise<Object>} Promise, resolved with built packages
|
||||
* information.
|
||||
*/
|
||||
module.exports.run = function(options, optResolvedTarget) {
|
||||
module.exports.run = function (options, optResolvedTarget) {
|
||||
var opts = parseOpts(options, optResolvedTarget, this.root);
|
||||
console.log(opts.buildMethod);
|
||||
var builder = builders.getBuilder(opts.buildMethod);
|
||||
return builder.prepEnv(opts)
|
||||
.then(function() {
|
||||
return builder.prepEnv(opts).then(function () {
|
||||
if (opts.prepEnv) {
|
||||
events.emit('verbose', 'Build file successfully prepared.');
|
||||
return;
|
||||
}
|
||||
return builder.build(opts)
|
||||
.then(function() {
|
||||
return builder.build(opts).then(function () {
|
||||
var apkPaths = builder.findOutputApks(opts.buildType, opts.arch);
|
||||
events.emit('log', 'Built the following apk(s): \n\t' + apkPaths.join('\n\t'));
|
||||
return {
|
||||
@ -177,38 +170,31 @@ module.exports.run = function(options, optResolvedTarget) {
|
||||
* Detects the architecture of a device/emulator
|
||||
* Returns "arm" or "x86".
|
||||
*/
|
||||
module.exports.detectArchitecture = function(target) {
|
||||
function helper() {
|
||||
return Adb.shell(target, 'cat /proc/cpuinfo')
|
||||
.then(function(output) {
|
||||
module.exports.detectArchitecture = function (target) {
|
||||
function helper () {
|
||||
return Adb.shell(target, 'cat /proc/cpuinfo').then(function (output) {
|
||||
return /intel/i.exec(output) ? 'x86' : 'arm';
|
||||
});
|
||||
}
|
||||
// It sometimes happens (at least on OS X), that this command will hang forever.
|
||||
// To fix it, either unplug & replug device, or restart adb server.
|
||||
return helper()
|
||||
.timeout(1000, new CordovaError('Device communication timed out. Try unplugging & replugging the device.'))
|
||||
.then(null, function(err) {
|
||||
return helper().timeout(1000, new CordovaError('Device communication timed out. Try unplugging & replugging the device.')).then(null, function (err) {
|
||||
if (/timed out/.exec('' + err)) {
|
||||
// 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.
|
||||
events.emit('verbose', 'adb timed out while detecting device/emulator architecture. Killing adb and trying again.');
|
||||
return spawn('killall', ['adb'])
|
||||
.then(function() {
|
||||
return helper()
|
||||
.then(null, function() {
|
||||
return spawn('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 helper()
|
||||
.then(null, function() {
|
||||
return spawn('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.'));
|
||||
});
|
||||
});
|
||||
});
|
||||
}, function() {
|
||||
}, function () {
|
||||
// For non-killall OS's.
|
||||
return Q.reject(err);
|
||||
});
|
||||
@ -217,10 +203,10 @@ module.exports.detectArchitecture = function(target) {
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.findBestApkForArchitecture = function(buildResults, arch) {
|
||||
var paths = buildResults.apkPaths.filter(function(p) {
|
||||
module.exports.findBestApkForArchitecture = function (buildResults, arch) {
|
||||
var paths = buildResults.apkPaths.filter(function (p) {
|
||||
var apkName = path.basename(p);
|
||||
if (buildResults.buildType == 'debug') {
|
||||
if (buildResults.buildType === 'debug') {
|
||||
return /-debug/.exec(apkName);
|
||||
}
|
||||
return !/-debug/.exec(apkName);
|
||||
@ -240,7 +226,7 @@ module.exports.findBestApkForArchitecture = function(buildResults, arch) {
|
||||
throw new Error('Could not find apk architecture: ' + arch + ' build-type: ' + buildResults.buildType);
|
||||
};
|
||||
|
||||
function PackageInfo(keystore, alias, storePassword, password, keystoreType) {
|
||||
function PackageInfo (keystore, alias, storePassword, password, keystoreType) {
|
||||
this.keystore = {
|
||||
'name': 'key.store',
|
||||
'value': keystore
|
||||
@ -270,10 +256,10 @@ function PackageInfo(keystore, alias, storePassword, password, keystoreType) {
|
||||
}
|
||||
|
||||
PackageInfo.prototype = {
|
||||
toProperties: function() {
|
||||
toProperties: function () {
|
||||
var self = this;
|
||||
var result = '';
|
||||
Object.keys(self).forEach(function(key) {
|
||||
Object.keys(self).forEach(function (key) {
|
||||
result += self[key].name;
|
||||
result += '=';
|
||||
result += self[key].value.replace(/\\/g, '\\\\');
|
||||
@ -283,7 +269,7 @@ PackageInfo.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.help = function() {
|
||||
module.exports.help = function () {
|
||||
console.log('Usage: ' + path.relative(process.cwd(), path.join('../build')) + ' [flags] [Signed APK flags]');
|
||||
console.log('Flags:');
|
||||
console.log(' \'--debug\': will build project in debug mode (default)');
|
||||
|
@ -16,6 +16,8 @@
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
/* eslint no-self-assign: 0 */
|
||||
/* eslint no-unused-vars: 0 */
|
||||
|
||||
var Q = require('q');
|
||||
var fs = require('fs');
|
||||
@ -35,29 +37,27 @@ GenericBuilder.prototype.prepEnv = function() {
|
||||
return Q();
|
||||
};
|
||||
|
||||
GenericBuilder.prototype.build = function() {
|
||||
GenericBuilder.prototype.build = function () {
|
||||
events.emit('log', 'Skipping build...');
|
||||
return Q(null);
|
||||
};
|
||||
|
||||
GenericBuilder.prototype.clean = function() {
|
||||
GenericBuilder.prototype.clean = function () {
|
||||
return Q();
|
||||
};
|
||||
|
||||
GenericBuilder.prototype.findOutputApks = function(build_type, arch) {
|
||||
GenericBuilder.prototype.findOutputApks = function (build_type, arch) {
|
||||
var self = this;
|
||||
return Object.keys(this.binDirs)
|
||||
.reduce(function (result, builderName) {
|
||||
return Object.keys(this.binDirs) .reduce(function (result, builderName) {
|
||||
console.log('builderName:'+ builderName);
|
||||
var binDir = self.binDirs[builderName];
|
||||
return result.concat(findOutputApksHelper(binDir, build_type, builderName === 'ant' ? null : arch));
|
||||
}, [])
|
||||
.sort(apkSorter);
|
||||
}, []).sort(apkSorter);
|
||||
};
|
||||
|
||||
module.exports = GenericBuilder;
|
||||
|
||||
function apkSorter(fileA, fileB) {
|
||||
function apkSorter (fileA, fileB) {
|
||||
// De-prioritize unsigned builds
|
||||
var unsignedRE = /-unsigned/;
|
||||
if (unsignedRE.exec(fileA)) {
|
||||
@ -70,12 +70,11 @@ function apkSorter(fileA, fileB) {
|
||||
return timeDiff === 0 ? fileA.length - fileB.length : timeDiff;
|
||||
}
|
||||
|
||||
function findOutputApksHelper(dir, build_type, arch) {
|
||||
function findOutputApksHelper (dir, build_type, arch) {
|
||||
var shellSilent = shell.config.silent;
|
||||
shell.config.silent = true;
|
||||
|
||||
var ret = shell.ls(path.join(dir, '*.apk'))
|
||||
.filter(function(candidate) {
|
||||
var ret = shell.ls(path.join(dir, '*.apk')).filter(function (candidate) {
|
||||
var apkName = path.basename(candidate);
|
||||
// Need to choose between release and debug .apk.
|
||||
if (build_type === 'debug') {
|
||||
@ -85,8 +84,7 @@ function findOutputApksHelper(dir, build_type, arch) {
|
||||
return /-release/.exec(apkName) && !/-unaligned/.exec(apkName);
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.sort(apkSorter);
|
||||
}).sort(apkSorter);
|
||||
|
||||
shellSilent = shellSilent;
|
||||
|
||||
@ -96,15 +94,15 @@ function findOutputApksHelper(dir, build_type, arch) {
|
||||
// Assume arch-specific build if newest apk has -x86 or -arm.
|
||||
var archSpecific = !!/-x86|-arm/.exec(path.basename(ret[0]));
|
||||
// And show only arch-specific ones (or non-arch-specific)
|
||||
ret = ret.filter(function(p) {
|
||||
/*jshint -W018 */
|
||||
return !!/-x86|-arm/.exec(path.basename(p)) == archSpecific;
|
||||
/*jshint +W018 */
|
||||
ret = ret.filter(function (p) {
|
||||
/* jshint -W018 */
|
||||
return !!/-x86|-arm/.exec(path.basename(p)) === archSpecific;
|
||||
/* jshint +W018 */
|
||||
});
|
||||
|
||||
if (archSpecific && ret.length > 1 && arch) {
|
||||
ret = ret.filter(function(p) {
|
||||
return path.basename(p).indexOf('-' + arch) != -1;
|
||||
ret = ret.filter(function (p) {
|
||||
return path.basename(p).indexOf('-' + arch) !== -1;
|
||||
});
|
||||
}
|
||||
|
||||
|
108
bin/templates/cordova/lib/builders/GradleBuilder.js
vendored
108
bin/templates/cordova/lib/builders/GradleBuilder.js
vendored
@ -42,10 +42,10 @@ function GradleBuilder (projectRoot) {
|
||||
|
||||
util.inherits(GradleBuilder, GenericBuilder);
|
||||
|
||||
GradleBuilder.prototype.getArgs = function(cmd, opts) {
|
||||
if (cmd == 'release') {
|
||||
GradleBuilder.prototype.getArgs = function (cmd, opts) {
|
||||
if (cmd === 'release') {
|
||||
cmd = 'cdvBuildRelease';
|
||||
} else if (cmd == 'debug') {
|
||||
} else if (cmd === 'debug') {
|
||||
cmd = 'cdvBuildDebug';
|
||||
}
|
||||
var args = [cmd, '-b', path.join(this.root, 'build.gradle')];
|
||||
@ -69,13 +69,13 @@ GradleBuilder.prototype.getArgs = function(cmd, opts) {
|
||||
* This returns a promise
|
||||
*/
|
||||
|
||||
GradleBuilder.prototype.runGradleWrapper = function(gradle_cmd) {
|
||||
GradleBuilder.prototype.runGradleWrapper = function (gradle_cmd) {
|
||||
var gradlePath = path.join(this.root, 'gradlew');
|
||||
var wrapperGradle = path.join(this.root, 'wrapper.gradle');
|
||||
if(fs.existsSync(gradlePath)) {
|
||||
//Literally do nothing, for some reason this works, while !fs.existsSync didn't on Windows
|
||||
if (fs.existsSync(gradlePath)) {
|
||||
// Literally do nothing, for some reason this works, while !fs.existsSync didn't on Windows
|
||||
} else {
|
||||
return superspawn.spawn(gradle_cmd, ['-p', this.root, 'wrapper', '-b', wrapperGradle], {stdio: 'inherit'});
|
||||
return superspawn.spawn(gradle_cmd, ['-p', this.root, 'wrapper', '-b', wrapperGradle], {stdio: 'inherit'});
|
||||
}
|
||||
};
|
||||
|
||||
@ -116,7 +116,7 @@ GradleBuilder.prototype.extractRealProjectNameFromManifest = function () {
|
||||
|
||||
|
||||
// Makes the project buildable, minus the gradle wrapper.
|
||||
GradleBuilder.prototype.prepBuildFiles = function() {
|
||||
GradleBuilder.prototype.prepBuildFiles = function () {
|
||||
// Update the version of build.gradle in each dependent library.
|
||||
var pluginBuildGradle = path.join(this.root, 'cordova', 'lib', 'plugin-build.gradle');
|
||||
var propertiesObj = this.readProjectProperties();
|
||||
@ -125,33 +125,32 @@ GradleBuilder.prototype.prepBuildFiles = function() {
|
||||
// Check and copy the gradle file into the subproject.
|
||||
// Called by the loop below this function def.
|
||||
var checkAndCopy = function(subProject, root) {
|
||||
var subProjectGradle = path.join(root, subProject, 'build.gradle');
|
||||
// This is the future-proof way of checking if a file exists
|
||||
// This must be synchronous to satisfy a Travis test
|
||||
try {
|
||||
fs.accessSync(subProjectGradle, fs.F_OK);
|
||||
} catch (e) {
|
||||
shell.cp('-f', pluginBuildGradle, subProjectGradle);
|
||||
}
|
||||
var subProjectGradle = path.join(root, subProject, 'build.gradle');
|
||||
// This is the future-proof way of checking if a file exists
|
||||
// This must be synchronous to satisfy a Travis test
|
||||
try {
|
||||
fs.accessSync(subProjectGradle, fs.F_OK);
|
||||
} catch (e) {
|
||||
shell.cp('-f', pluginBuildGradle, subProjectGradle);
|
||||
}
|
||||
};
|
||||
|
||||
// Some dependencies on Android don't use gradle, or don't have default
|
||||
// gradle files. This copies a dummy gradle file into them
|
||||
for (var i = 0; i < subProjects.length; ++i) {
|
||||
if (subProjects[i] !== 'CordovaLib' && subProjects[i] !== 'app') {
|
||||
checkAndCopy(subProjects[i], this.root);
|
||||
checkAndCopy(subProjects[i], this.root);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var name = this.extractRealProjectNameFromManifest();
|
||||
//Remove the proj.id/name- prefix from projects: https://issues.apache.org/jira/browse/CB-9149
|
||||
var settingsGradlePaths = subProjects.map(function(p){
|
||||
var realDir=p.replace(/[/\\]/g, ':');
|
||||
var libName=realDir.replace(name+'-','');
|
||||
var str='include ":'+libName+'"\n';
|
||||
if(realDir.indexOf(name+'-')!==-1)
|
||||
str+='project(":'+libName+'").projectDir = new File("'+p+'")\n';
|
||||
// Remove the proj.id/name- prefix from projects: https://issues.apache.org/jira/browse/CB-9149
|
||||
var settingsGradlePaths = subProjects.map(function (p) {
|
||||
var realDir = p.replace(/[/\\]/g, ':');
|
||||
var libName = realDir.replace(name + '-', '');
|
||||
var str = 'include ":' + libName + '"\n';
|
||||
if (realDir.indexOf(name + '-') !== -1) { str += 'project(":' + libName + '").projectDir = new File("' + p + '")\n'; }
|
||||
return str;
|
||||
});
|
||||
|
||||
@ -169,19 +168,18 @@ GradleBuilder.prototype.prepBuildFiles = function() {
|
||||
// dependency. Because we need to make sure that Cordova is compiled only once for
|
||||
// dexing, we make sure to exclude CordovaLib from these modules
|
||||
var insertExclude = function(p) {
|
||||
var gradlePath = path.join(root, p, 'build.gradle');
|
||||
var projectGradleFile = fs.readFileSync(gradlePath, 'utf-8');
|
||||
if(projectGradleFile.indexOf('CordovaLib') != -1) {
|
||||
var gradlePath = path.join(root, p, 'build.gradle');
|
||||
var projectGradleFile = fs.readFileSync(gradlePath, 'utf-8');
|
||||
if(projectGradleFile.indexOf('CordovaLib') != -1) {
|
||||
depsList += '{\n exclude module:("CordovaLib")\n }\n';
|
||||
}
|
||||
else {
|
||||
depsList +='\n';
|
||||
}
|
||||
} else {
|
||||
depsList += '\n';
|
||||
}
|
||||
};
|
||||
|
||||
subProjects.forEach(function(p) {
|
||||
subProjects.forEach(function (p) {
|
||||
console.log('Subproject Path: ' + p);
|
||||
var libName=p.replace(/[/\\]/g, ':').replace(name+'-','');
|
||||
var libName = p.replace(/[/\\]/g, ':').replace(name + '-', '');
|
||||
depsList += ' debugCompile(project(path: "' + libName + '", configuration: "debug"))';
|
||||
insertExclude(p);
|
||||
depsList += ' releaseCompile(project(path: "' + libName + '", configuration: "release"))';
|
||||
@ -194,8 +192,7 @@ GradleBuilder.prototype.prepBuildFiles = function() {
|
||||
[/^\/?extras\/android\/support\/(.*)$/, 'com.android.support:support-$1:+'],
|
||||
[/^\/?google\/google_play_services\/libproject\/google-play-services_lib\/?$/, 'com.google.android.gms:play-services:+']
|
||||
];
|
||||
|
||||
propertiesObj.systemLibs.forEach(function(p) {
|
||||
propertiesObj.systemLibs.forEach(function (p) {
|
||||
var mavenRef;
|
||||
// It's already in gradle form if it has two ':'s
|
||||
if (/:.*:/.exec(p)) {
|
||||
@ -219,21 +216,20 @@ GradleBuilder.prototype.prepBuildFiles = function() {
|
||||
//Try not to mess with this if possible
|
||||
buildGradle = buildGradle.replace(/(SUB-PROJECT DEPENDENCIES START)[\s\S]*(\/\/ SUB-PROJECT DEPENDENCIES END)/, '$1\n' + depsList + ' $2');
|
||||
var includeList = '';
|
||||
propertiesObj.gradleIncludes.forEach(function(includePath) {
|
||||
propertiesObj.gradleIncludes.forEach(function (includePath) {
|
||||
includeList += 'apply from: "' + includePath + '"\n';
|
||||
});
|
||||
buildGradle = buildGradle.replace(/(PLUGIN GRADLE EXTENSIONS START)[\s\S]*(\/\/ PLUGIN GRADLE EXTENSIONS END)/, '$1\n' + includeList + '$2');
|
||||
fs.writeFileSync(path.join(this.root, 'build.gradle'), buildGradle);
|
||||
};
|
||||
|
||||
GradleBuilder.prototype.prepEnv = function(opts) {
|
||||
GradleBuilder.prototype.prepEnv = function (opts) {
|
||||
var self = this;
|
||||
return check_reqs.check_gradle()
|
||||
.then(function(gradlePath) {
|
||||
return check_reqs.check_gradle().then(function (gradlePath) {
|
||||
return self.runGradleWrapper(gradlePath);
|
||||
}).then(function() {
|
||||
return self.prepBuildFiles();
|
||||
}).then(function() {
|
||||
}).then(function () {
|
||||
return self.prepBuildFiles();
|
||||
}).then(function () {
|
||||
// We now copy the gradle out of the framework
|
||||
// This is a dirty patch to get the build working
|
||||
/*
|
||||
@ -253,12 +249,12 @@ GradleBuilder.prototype.prepEnv = function(opts) {
|
||||
// If it's not set, do nothing, assuming that we're using a future version of gradle that we don't want to mess with.
|
||||
// For some reason, using ^ and $ don't work. This does the job, though.
|
||||
var distributionUrlRegex = /distributionUrl.*zip/;
|
||||
/*jshint -W069 */
|
||||
/* jshint -W069 */
|
||||
var distributionUrl = process.env['CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL'] || 'https\\://services.gradle.org/distributions/gradle-3.3-all.zip';
|
||||
/*jshint +W069 */
|
||||
/* jshint +W069 */
|
||||
var gradleWrapperPropertiesPath = path.join(self.root, 'gradle', 'wrapper', 'gradle-wrapper.properties');
|
||||
shell.chmod('u+w', gradleWrapperPropertiesPath);
|
||||
shell.sed('-i', distributionUrlRegex, 'distributionUrl='+distributionUrl, gradleWrapperPropertiesPath);
|
||||
shell.sed('-i', distributionUrlRegex, 'distributionUrl=' + distributionUrl, gradleWrapperPropertiesPath);
|
||||
|
||||
var propertiesFile = opts.buildType + SIGNING_PROPERTIES;
|
||||
var propertiesFilePath = path.join(self.root, propertiesFile);
|
||||
@ -274,12 +270,11 @@ GradleBuilder.prototype.prepEnv = function(opts) {
|
||||
* Builds the project with gradle.
|
||||
* Returns a promise.
|
||||
*/
|
||||
GradleBuilder.prototype.build = function(opts) {
|
||||
GradleBuilder.prototype.build = function (opts) {
|
||||
var wrapper = path.join(this.root, 'gradlew');
|
||||
var args = this.getArgs(opts.buildType == 'debug' ? 'debug' : 'release', opts);
|
||||
var args = this.getArgs(opts.buildType === 'debug' ? 'debug' : 'release', opts);
|
||||
|
||||
return superspawn.spawn(wrapper, args, {stdio: 'pipe'})
|
||||
.progress(function (stdio){
|
||||
return superspawn.spawn(wrapper, args, {stdio: 'pipe'}).progress(function (stdio) {
|
||||
if (stdio.stderr) {
|
||||
/*
|
||||
* Workaround for the issue with Java printing some unwanted information to
|
||||
@ -298,7 +293,7 @@ GradleBuilder.prototype.build = function(opts) {
|
||||
}
|
||||
}).catch(function (error) {
|
||||
if (error.toString().indexOf('failed to find target with hash string') >= 0) {
|
||||
return check_reqs.check_android_target(error).then(function() {
|
||||
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);
|
||||
@ -308,19 +303,18 @@ GradleBuilder.prototype.build = function(opts) {
|
||||
});
|
||||
};
|
||||
|
||||
GradleBuilder.prototype.clean = function(opts) {
|
||||
GradleBuilder.prototype.clean = function (opts) {
|
||||
var builder = this;
|
||||
var wrapper = path.join(this.root, 'gradlew');
|
||||
var args = builder.getArgs('clean', opts);
|
||||
return Q().then(function() {
|
||||
return Q().then(function () {
|
||||
return superspawn.spawn(wrapper, args, {stdio: 'inherit'});
|
||||
})
|
||||
.then(function () {
|
||||
}).then(function () {
|
||||
shell.rm('-rf', path.join(builder.root, 'out'));
|
||||
|
||||
['debug', 'release'].forEach(function(config) {
|
||||
['debug', 'release'].forEach(function (config) {
|
||||
var propertiesFilePath = path.join(builder.root, config + SIGNING_PROPERTIES);
|
||||
if(isAutoGenerated(propertiesFilePath)){
|
||||
if (isAutoGenerated(propertiesFilePath)) {
|
||||
shell.rm('-f', propertiesFilePath);
|
||||
}
|
||||
});
|
||||
@ -329,6 +323,6 @@ GradleBuilder.prototype.clean = function(opts) {
|
||||
|
||||
module.exports = GradleBuilder;
|
||||
|
||||
function isAutoGenerated(file) {
|
||||
function isAutoGenerated (file) {
|
||||
return fs.existsSync(file) && fs.readFileSync(file, 'utf8').indexOf(MARKER) > 0;
|
||||
}
|
||||
|
@ -35,8 +35,7 @@ var knownBuilders = {
|
||||
* @return {Builder} A builder instance for specified build type.
|
||||
*/
|
||||
module.exports.getBuilder = function (builderType, projectRoot) {
|
||||
if (!knownBuilders[builderType])
|
||||
throw new CordovaError('Builder ' + builderType + ' is not supported.');
|
||||
if (!knownBuilders[builderType]) { throw new CordovaError('Builder ' + builderType + ' is not supported.'); }
|
||||
|
||||
try {
|
||||
var Builder = require('./' + knownBuilders[builderType]);
|
||||
|
160
bin/templates/cordova/lib/check_reqs.js
vendored
160
bin/templates/cordova/lib/check_reqs.js
vendored
@ -21,19 +21,19 @@
|
||||
|
||||
/* jshint sub:true */
|
||||
|
||||
var shelljs = require('shelljs'),
|
||||
child_process = require('child_process'),
|
||||
Q = require('q'),
|
||||
path = require('path'),
|
||||
fs = require('fs'),
|
||||
os = require('os'),
|
||||
REPO_ROOT = path.join(__dirname, '..', '..', '..', '..'),
|
||||
PROJECT_ROOT = path.join(__dirname, '..', '..');
|
||||
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) {
|
||||
function forgivingWhichSync (cmd) {
|
||||
try {
|
||||
return fs.realpathSync(shelljs.which(cmd));
|
||||
} catch (e) {
|
||||
@ -41,9 +41,9 @@ function forgivingWhichSync(cmd) {
|
||||
}
|
||||
}
|
||||
|
||||
function tryCommand(cmd, errMsg, catchStderr) {
|
||||
function tryCommand (cmd, errMsg, catchStderr) {
|
||||
var d = Q.defer();
|
||||
child_process.exec(cmd, function(err, stdout, stderr) {
|
||||
child_process.exec(cmd, function (err, stdout, stderr) {
|
||||
if (err) d.reject(new CordovaError(errMsg));
|
||||
// Sometimes it is necessary to return an stderr instead of stdout in case of success, since
|
||||
// some commands prints theirs output to stderr instead of stdout. 'javac' is the example
|
||||
@ -52,18 +52,18 @@ function tryCommand(cmd, errMsg, catchStderr) {
|
||||
return d.promise;
|
||||
}
|
||||
|
||||
module.exports.isWindows = function() {
|
||||
return (os.platform() == 'win32');
|
||||
module.exports.isWindows = function () {
|
||||
return (os.platform() === 'win32');
|
||||
};
|
||||
|
||||
module.exports.isDarwin = function() {
|
||||
return (os.platform() == 'darwin');
|
||||
module.exports.isDarwin = function () {
|
||||
return (os.platform() === 'darwin');
|
||||
};
|
||||
|
||||
// Get valid target from framework/project.properties if run from this repo
|
||||
// Otherwise get target from project.properties file within a generated cordova-android project
|
||||
module.exports.get_target = function() {
|
||||
function extractFromFile(filePath) {
|
||||
module.exports.get_target = function () {
|
||||
function extractFromFile (filePath) {
|
||||
var target = shelljs.grep(/\btarget=/, filePath);
|
||||
if (!target) {
|
||||
throw new Error('Could not find android target within: ' + filePath);
|
||||
@ -83,17 +83,18 @@ 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) {
|
||||
module.exports.check_ant = function () {
|
||||
return superspawn.spawn('ant', ['-version']).then(function (output) {
|
||||
// Parse Ant version from command output
|
||||
return /version ((?:\d+\.)+(?:\d+))/i.exec(output)[1];
|
||||
}).catch(function(err) {
|
||||
throw new CordovaError('Failed to run `ant -version`. Make sure you have `ant` on your $PATH.');
|
||||
}).catch(function (err) {
|
||||
if (err) {
|
||||
throw new CordovaError('Failed to run `ant -version`. Make sure you have `ant` on your $PATH.');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.get_gradle_wrapper = function() {
|
||||
module.exports.get_gradle_wrapper = function () {
|
||||
var androidStudioPath;
|
||||
var i = 0;
|
||||
var foundStudio = false;
|
||||
@ -102,58 +103,70 @@ module.exports.get_gradle_wrapper = function() {
|
||||
program_dir = fs.readdirSync('/Applications');
|
||||
while (i < program_dir.length && !foundStudio) {
|
||||
if (program_dir[i].startsWith('Android Studio')) {
|
||||
//TODO: Check for a specific Android Studio version, make sure it's not Canary
|
||||
// TODO: Check for a specific Android Studio version, make sure it's not Canary
|
||||
androidStudioPath = path.join('/Applications', program_dir[i], 'Contents', 'gradle');
|
||||
foundStudio = true;
|
||||
} else { ++i; }
|
||||
}
|
||||
} else if (module.exports.isWindows()) {
|
||||
var androidPath = path.join(process.env['ProgramFiles'], 'Android') + '/';
|
||||
if (fs.existsSync(androidPath)) {
|
||||
program_dir = fs.readdirSync(androidPath);
|
||||
while (i < program_dir.length && !foundStudio) {
|
||||
if (program_dir[i].startsWith('Android Studio')) {
|
||||
foundStudio = true;
|
||||
androidStudioPath = path.join(process.env['ProgramFiles'], 'Android', program_dir[i], 'gradle');
|
||||
} else { ++i; }
|
||||
|
||||
var result = child_process.spawnSync(path.join(__dirname, 'getASPath.bat'));
|
||||
// console.log('result.stdout =' + result.stdout.toString());
|
||||
// console.log('result.stderr =' + result.stderr.toString());
|
||||
|
||||
if (result.stderr.toString().length > 0) {
|
||||
var androidPath = path.join(process.env['ProgramFiles'], 'Android') + '/';
|
||||
if (fs.existsSync(androidPath)) {
|
||||
program_dir = fs.readdirSync(androidPath);
|
||||
while (i < program_dir.length && !foundStudio) {
|
||||
if (program_dir[i].startsWith('Android Studio')) {
|
||||
foundStudio = true;
|
||||
androidStudioPath = path.join(process.env['ProgramFiles'], 'Android', program_dir[i], 'gradle');
|
||||
} else { ++i; }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// console.log('got android studio path from registry');
|
||||
// remove the (os independent) new line char at the end of stdout
|
||||
// add gradle to match the above.
|
||||
androidStudioPath = path.join(result.stdout.toString().split('\r\n')[0], 'gradle');
|
||||
}
|
||||
}
|
||||
|
||||
if (androidStudioPath !== null && fs.existsSync(androidStudioPath)) {
|
||||
var dirs = fs.readdirSync(androidStudioPath);
|
||||
if(dirs[0].split('-')[0] == 'gradle') {
|
||||
if (dirs[0].split('-')[0] === 'gradle') {
|
||||
return path.join(androidStudioPath, dirs[0], 'bin', 'gradle');
|
||||
}
|
||||
} else {
|
||||
//OK, let's try to check for Gradle!
|
||||
// OK, let's try to check for Gradle!
|
||||
return forgivingWhichSync('gradle');
|
||||
}
|
||||
};
|
||||
|
||||
// Returns a promise. Called only by build and clean commands.
|
||||
module.exports.check_gradle = function() {
|
||||
module.exports.check_gradle = function () {
|
||||
var sdkDir = process.env['ANDROID_HOME'];
|
||||
var d = Q.defer();
|
||||
if (!sdkDir)
|
||||
if (!sdkDir) {
|
||||
return Q.reject(new CordovaError('Could not find gradle wrapper within Android SDK. Could not find Android SDK directory.\n' +
|
||||
'Might need to install Android SDK or set up \'ANDROID_HOME\' env variable.'));
|
||||
}
|
||||
|
||||
var gradlePath = module.exports.get_gradle_wrapper();
|
||||
if (gradlePath.length !== 0)
|
||||
d.resolve(gradlePath);
|
||||
else
|
||||
if (gradlePath.length !== 0) { d.resolve(gradlePath); } else {
|
||||
d.reject(new CordovaError('Could not find an installed version of Gradle either in Android Studio,\n' +
|
||||
'or on your system to install the gradle wrapper. Please include gradle \n' +
|
||||
'in your path, or install Android Studio'));
|
||||
}
|
||||
return d.promise;
|
||||
};
|
||||
|
||||
// Returns a promise.
|
||||
module.exports.check_java = function() {
|
||||
module.exports.check_java = function () {
|
||||
var javacPath = forgivingWhichSync('javac');
|
||||
var hasJavaHome = !!process.env['JAVA_HOME'];
|
||||
return Q().then(function() {
|
||||
return Q().then(function () {
|
||||
if (hasJavaHome) {
|
||||
// Windows java installer doesn't add javac to PATH, nor set JAVA_HOME (ugh).
|
||||
if (!javacPath) {
|
||||
@ -165,11 +178,12 @@ 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 setting it manually.';
|
||||
if (fs.existsSync(find_java)) {
|
||||
return superspawn.spawn(find_java)
|
||||
.then(function(stdout) {
|
||||
return superspawn.spawn(find_java).then(function (stdout) {
|
||||
process.env['JAVA_HOME'] = stdout.trim();
|
||||
}).catch(function(err) {
|
||||
throw new CordovaError(default_java_error_msg);
|
||||
}).catch(function (err) {
|
||||
if (err) {
|
||||
throw new CordovaError(default_java_error_msg);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// See if we can derive it from javac's location.
|
||||
@ -200,7 +214,7 @@ module.exports.check_java = function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}).then(function() {
|
||||
}).then(function () {
|
||||
var msg =
|
||||
'Failed to run "javac -version", make sure that you have a JDK installed.\n' +
|
||||
'You can get it from: http://www.oracle.com/technetwork/java/javase/downloads.\n';
|
||||
@ -209,9 +223,8 @@ module.exports.check_java = function() {
|
||||
}
|
||||
// We use tryCommand with catchStderr = true, because
|
||||
// javac writes version info to stderr instead of stdout
|
||||
return tryCommand('javac -version', msg, true)
|
||||
.then(function (output) {
|
||||
//Let's check for at least Java 8, and keep it future proof so we can support Java 10
|
||||
return tryCommand('javac -version', msg, true).then(function (output) {
|
||||
// Let's check for at least Java 8, and keep it future proof so we can support Java 10
|
||||
var match = /javac ((?:1\.)(?:[8-9]\.)(?:\d+))|((?:1\.)(?:[1-9]\d+\.)(?:\d+))/i.exec(output);
|
||||
return match && match[1];
|
||||
});
|
||||
@ -219,13 +232,13 @@ module.exports.check_java = function() {
|
||||
};
|
||||
|
||||
// Returns a promise.
|
||||
module.exports.check_android = function() {
|
||||
return Q().then(function() {
|
||||
module.exports.check_android = function () {
|
||||
return Q().then(function () {
|
||||
var androidCmdPath = forgivingWhichSync('android');
|
||||
var adbInPath = forgivingWhichSync('adb');
|
||||
var avdmanagerInPath = forgivingWhichSync('avdmanager');
|
||||
var hasAndroidHome = !!process.env['ANDROID_HOME'] && fs.existsSync(process.env['ANDROID_HOME']);
|
||||
function maybeSetAndroidHome(value) {
|
||||
function maybeSetAndroidHome (value) {
|
||||
if (!hasAndroidHome && fs.existsSync(value)) {
|
||||
hasAndroidHome = true;
|
||||
process.env['ANDROID_HOME'] = value;
|
||||
@ -265,7 +278,7 @@ module.exports.check_android = function() {
|
||||
if (androidCmdPath) {
|
||||
parentDir = path.dirname(androidCmdPath);
|
||||
grandParentDir = path.dirname(parentDir);
|
||||
if (path.basename(parentDir) == 'tools' || fs.existsSync(path.join(grandParentDir, 'tools', 'android'))) {
|
||||
if (path.basename(parentDir) === 'tools' || fs.existsSync(path.join(grandParentDir, 'tools', 'android'))) {
|
||||
maybeSetAndroidHome(grandParentDir);
|
||||
} else {
|
||||
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' +
|
||||
@ -276,7 +289,7 @@ module.exports.check_android = function() {
|
||||
if (adbInPath) {
|
||||
parentDir = path.dirname(adbInPath);
|
||||
grandParentDir = path.dirname(parentDir);
|
||||
if (path.basename(parentDir) == 'platform-tools') {
|
||||
if (path.basename(parentDir) === 'platform-tools') {
|
||||
maybeSetAndroidHome(grandParentDir);
|
||||
} else {
|
||||
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' +
|
||||
@ -287,7 +300,7 @@ module.exports.check_android = function() {
|
||||
if (avdmanagerInPath) {
|
||||
parentDir = path.dirname(avdmanagerInPath);
|
||||
grandParentDir = path.dirname(parentDir);
|
||||
if (path.basename(parentDir) == 'bin' && path.basename(grandParentDir) == 'tools') {
|
||||
if (path.basename(parentDir) === 'bin' && path.basename(grandParentDir) === 'tools') {
|
||||
maybeSetAndroidHome(path.dirname(grandParentDir));
|
||||
} else {
|
||||
throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' +
|
||||
@ -330,20 +343,19 @@ module.exports.getAbsoluteAndroidCmd = function () {
|
||||
return cmd.replace(/(\s)/g, '\\$1');
|
||||
};
|
||||
|
||||
module.exports.check_android_target = function(originalError) {
|
||||
module.exports.check_android_target = function (originalError) {
|
||||
// valid_target can look like:
|
||||
// android-19
|
||||
// android-L
|
||||
// Google Inc.:Google APIs:20
|
||||
// Google Inc.:Glass Development Kit Preview:20
|
||||
var desired_api_level = module.exports.get_target();
|
||||
return android_sdk.list_targets()
|
||||
.then(function(targets) {
|
||||
return android_sdk.list_targets().then(function (targets) {
|
||||
if (targets.indexOf(desired_api_level) >= 0) {
|
||||
return targets;
|
||||
}
|
||||
var androidCmd = module.exports.getAbsoluteAndroidCmd();
|
||||
var msg = 'Please install Android target / API level: "' + desired_api_level + '".\n\n' +
|
||||
var msg = 'Please install Android target / API level: "' + desired_api_level + '".\n\n' +
|
||||
'Hint: Open the SDK manager by running: ' + androidCmd + '\n' +
|
||||
'You will require:\n' +
|
||||
'1. "SDK Platform" for API level ' + desired_api_level + '\n' +
|
||||
@ -357,23 +369,21 @@ module.exports.check_android_target = function(originalError) {
|
||||
};
|
||||
|
||||
// Returns a promise.
|
||||
module.exports.run = function() {
|
||||
return Q.all([this.check_java(), this.check_android()])
|
||||
.then(function(values) {
|
||||
console.log('ANDROID_HOME=' + process.env['ANDROID_HOME']);
|
||||
console.log('JAVA_HOME=' + process.env['JAVA_HOME']);
|
||||
module.exports.run = function () {
|
||||
return Q.all([this.check_java(), this.check_android()]).then(function (values) {
|
||||
console.log('ANDROID_HOME=' + process.env['ANDROID_HOME']);
|
||||
console.log('JAVA_HOME=' + process.env['JAVA_HOME']);
|
||||
|
||||
if (!values[0]) {
|
||||
if (!values[0]) {
|
||||
throw new CordovaError('Requirements check failed for JDK 1.8 or greater');
|
||||
}
|
||||
}
|
||||
|
||||
if (!values[1]) {
|
||||
if (!values[1]) {
|
||||
throw new CordovaError('Requirements check failed for Android SDK');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Object thar represents one of requirements for current platform.
|
||||
* @param {String} id The unique identifier for this requirements.
|
||||
@ -387,7 +397,7 @@ var Requirement = function (id, name, version, installed) {
|
||||
this.name = name;
|
||||
this.installed = installed || false;
|
||||
this.metadata = {
|
||||
version: version,
|
||||
version: version
|
||||
};
|
||||
};
|
||||
|
||||
@ -397,7 +407,7 @@ var Requirement = function (id, name, version, installed) {
|
||||
*
|
||||
* @return Promise<Requirement[]> Array of requirements. Due to implementation, promise is always fulfilled.
|
||||
*/
|
||||
module.exports.check_all = function() {
|
||||
module.exports.check_all = function () {
|
||||
|
||||
var requirements = [
|
||||
new Requirement('java', 'Java JDK'),
|
||||
@ -417,15 +427,13 @@ module.exports.check_all = function() {
|
||||
return checkFns.reduce(function (promise, checkFn, idx) {
|
||||
// Update each requirement with results
|
||||
var requirement = requirements[idx];
|
||||
return promise.then(checkFn)
|
||||
.then(function (version) {
|
||||
return promise.then(checkFn).then(function (version) {
|
||||
requirement.installed = true;
|
||||
requirement.metadata.version = version;
|
||||
}, function (err) {
|
||||
requirement.metadata.reason = err instanceof Error ? err.message : err;
|
||||
});
|
||||
}, Q())
|
||||
.then(function () {
|
||||
}, Q()).then(function () {
|
||||
// When chain is completed, return requirements array to upstream API
|
||||
return requirements;
|
||||
});
|
||||
|
48
bin/templates/cordova/lib/device.js
vendored
48
bin/templates/cordova/lib/device.js
vendored
@ -19,8 +19,8 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var Q = require('q'),
|
||||
build = require('./build');
|
||||
var Q = require('q');
|
||||
var build = require('./build');
|
||||
var path = require('path');
|
||||
var Adb = require('./Adb');
|
||||
var AndroidManifest = require('./AndroidManifest');
|
||||
@ -32,18 +32,16 @@ var events = require('cordova-common').events;
|
||||
* Returns a promise for the list of the device ID's found
|
||||
* @param lookHarder When true, try restarting adb if no devices are found.
|
||||
*/
|
||||
module.exports.list = function(lookHarder) {
|
||||
return Adb.devices()
|
||||
.then(function(list) {
|
||||
module.exports.list = function (lookHarder) {
|
||||
return Adb.devices().then(function (list) {
|
||||
if (list.length === 0 && 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 spawn('killall', ['adb']).then(function () {
|
||||
events.emit('verbose', 'Restarting adb to see if more devices are detected.');
|
||||
return Adb.devices();
|
||||
}, function() {
|
||||
}, function () {
|
||||
// For non-killall OS's.
|
||||
return list;
|
||||
});
|
||||
@ -52,9 +50,8 @@ module.exports.list = function(lookHarder) {
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.resolveTarget = function(target) {
|
||||
return this.list(true)
|
||||
.then(function(device_list) {
|
||||
module.exports.resolveTarget = function (target) {
|
||||
return this.list(true).then(function (device_list) {
|
||||
if (!device_list || !device_list.length) {
|
||||
return Q.reject(new CordovaError('Failed to deploy to device, no devices found.'));
|
||||
}
|
||||
@ -65,8 +62,7 @@ module.exports.resolveTarget = function(target) {
|
||||
return Q.reject('ERROR: Unable to find target \'' + target + '\'.');
|
||||
}
|
||||
|
||||
return build.detectArchitecture(target)
|
||||
.then(function(arch) {
|
||||
return build.detectArchitecture(target).then(function (arch) {
|
||||
return { target: target, arch: arch, isEmulator: false };
|
||||
});
|
||||
});
|
||||
@ -77,13 +73,13 @@ module.exports.resolveTarget = function(target) {
|
||||
* and launches it.
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.install = function(target, buildResults) {
|
||||
return Q().then(function() {
|
||||
if (target && typeof target == 'object') {
|
||||
module.exports.install = function (target, buildResults) {
|
||||
return Q().then(function () {
|
||||
if (target && typeof target === 'object') {
|
||||
return target;
|
||||
}
|
||||
return module.exports.resolveTarget(target);
|
||||
}).then(function(resolvedTarget) {
|
||||
}).then(function (resolvedTarget) {
|
||||
var apk_path = build.findBestApkForArchitecture(buildResults, resolvedTarget.arch);
|
||||
var manifest = new AndroidManifest(path.join(__dirname, '../../app/src/main/AndroidManifest.xml'));
|
||||
var pkgName = manifest.getPackageId();
|
||||
@ -91,29 +87,25 @@ module.exports.install = function(target, buildResults) {
|
||||
events.emit('log', 'Using apk: ' + apk_path);
|
||||
events.emit('log', 'Package name: ' + pkgName);
|
||||
|
||||
return Adb.install(resolvedTarget.target, apk_path, {replace: true})
|
||||
.catch(function (error) {
|
||||
return Adb.install(resolvedTarget.target, apk_path, {replace: true}).catch(function (error) {
|
||||
// CB-9557 CB-10157 only uninstall and reinstall app if the one that
|
||||
// is already installed on device was signed w/different certificate
|
||||
if (!/INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES/.test(error.toString()))
|
||||
throw error;
|
||||
if (!/INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES/.test(error.toString())) { throw error; }
|
||||
|
||||
events.emit('warn', 'Uninstalling app from device and reinstalling it again because the ' +
|
||||
'installed app already signed with different key');
|
||||
|
||||
// This promise is always resolved, even if 'adb uninstall' fails to uninstall app
|
||||
// or the app doesn't installed at all, so no error catching needed.
|
||||
return Adb.uninstall(resolvedTarget.target, pkgName)
|
||||
.then(function() {
|
||||
return Adb.uninstall(resolvedTarget.target, pkgName).then(function () {
|
||||
return Adb.install(resolvedTarget.target, apk_path, {replace: true});
|
||||
});
|
||||
})
|
||||
.then(function() {
|
||||
//unlock screen
|
||||
}).then(function () {
|
||||
// unlock screen
|
||||
return Adb.shell(resolvedTarget.target, 'input keyevent 82');
|
||||
}).then(function() {
|
||||
}).then(function () {
|
||||
return Adb.start(resolvedTarget.target, launchName);
|
||||
}).then(function() {
|
||||
}).then(function () {
|
||||
events.emit('log', 'LAUNCH SUCCESS');
|
||||
});
|
||||
});
|
||||
|
159
bin/templates/cordova/lib/emulator.js
vendored
159
bin/templates/cordova/lib/emulator.js
vendored
@ -21,8 +21,8 @@
|
||||
|
||||
/* jshint sub:true */
|
||||
|
||||
var retry = require('./retry');
|
||||
var build = require('./build');
|
||||
var retry = require('./retry');
|
||||
var build = require('./build');
|
||||
var path = require('path');
|
||||
var Adb = require('./Adb');
|
||||
var AndroidManifest = require('./AndroidManifest');
|
||||
@ -33,20 +33,20 @@ var shelljs = require('shelljs');
|
||||
var android_sdk = require('./android_sdk');
|
||||
var check_reqs = require('./check_reqs');
|
||||
|
||||
var Q = require('q');
|
||||
var os = require('os');
|
||||
var fs = require('fs');
|
||||
var Q = require('q');
|
||||
var os = require('os');
|
||||
var fs = require('fs');
|
||||
var child_process = require('child_process');
|
||||
|
||||
// constants
|
||||
var ONE_SECOND = 1000; // in milliseconds
|
||||
var ONE_MINUTE = 60 * ONE_SECOND; // in milliseconds
|
||||
var ONE_SECOND = 1000; // in milliseconds
|
||||
var ONE_MINUTE = 60 * ONE_SECOND; // in milliseconds
|
||||
var INSTALL_COMMAND_TIMEOUT = 5 * ONE_MINUTE; // in milliseconds
|
||||
var NUM_INSTALL_RETRIES = 3;
|
||||
var CHECK_BOOTED_INTERVAL = 3 * ONE_SECOND; // in milliseconds
|
||||
var EXEC_KILL_SIGNAL = 'SIGKILL';
|
||||
var NUM_INSTALL_RETRIES = 3;
|
||||
var CHECK_BOOTED_INTERVAL = 3 * ONE_SECOND; // in milliseconds
|
||||
var EXEC_KILL_SIGNAL = 'SIGKILL';
|
||||
|
||||
function forgivingWhichSync(cmd) {
|
||||
function forgivingWhichSync (cmd) {
|
||||
try {
|
||||
return fs.realpathSync(shelljs.which(cmd));
|
||||
} catch (e) {
|
||||
@ -55,8 +55,7 @@ function forgivingWhichSync(cmd) {
|
||||
}
|
||||
|
||||
module.exports.list_images_using_avdmanager = function () {
|
||||
return superspawn.spawn('avdmanager', ['list', 'avd'])
|
||||
.then(function(output) {
|
||||
return superspawn.spawn('avdmanager', ['list', 'avd']).then(function (output) {
|
||||
var response = output.split('\n');
|
||||
var emulator_list = [];
|
||||
for (var i = 1; i < response.length; i++) {
|
||||
@ -108,16 +107,15 @@ module.exports.list_images_using_avdmanager = function () {
|
||||
/* To just return a list of names use this
|
||||
if (response[i].match(/Name:\s/)) {
|
||||
emulator_list.push(response[i].split('Name: ')[1].replace('\r', '');
|
||||
}*/
|
||||
} */
|
||||
|
||||
}
|
||||
return emulator_list;
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.list_images_using_android = function() {
|
||||
return superspawn.spawn('android', ['list', 'avd'])
|
||||
.then(function(output) {
|
||||
module.exports.list_images_using_android = function () {
|
||||
return superspawn.spawn('android', ['list', 'avd']).then(function (output) {
|
||||
var response = output.split('\n');
|
||||
var emulator_list = [];
|
||||
for (var i = 1; i < response.length; i++) {
|
||||
@ -152,7 +150,7 @@ module.exports.list_images_using_android = function() {
|
||||
/* To just return a list of names use this
|
||||
if (response[i].match(/Name:\s/)) {
|
||||
emulator_list.push(response[i].split('Name: ')[1].replace('\r', '');
|
||||
}*/
|
||||
} */
|
||||
|
||||
}
|
||||
return emulator_list;
|
||||
@ -170,13 +168,13 @@ module.exports.list_images_using_android = function() {
|
||||
skin : <skin>
|
||||
}
|
||||
*/
|
||||
module.exports.list_images = function() {
|
||||
module.exports.list_images = function () {
|
||||
if (forgivingWhichSync('avdmanager')) {
|
||||
return module.exports.list_images_using_avdmanager();
|
||||
} else if (forgivingWhichSync('android')) {
|
||||
return module.exports.list_images_using_android();
|
||||
} else {
|
||||
return Q().then(function() {
|
||||
return Q().then(function () {
|
||||
throw new CordovaError('Could not find either `android` or `avdmanager` on your $PATH! Are you sure the Android SDK is installed and available?');
|
||||
});
|
||||
}
|
||||
@ -187,9 +185,8 @@ module.exports.list_images = function() {
|
||||
* or undefined if no avds exist.
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.best_image = function() {
|
||||
return this.list_images()
|
||||
.then(function(images) {
|
||||
module.exports.best_image = function () {
|
||||
return this.list_images().then(function (images) {
|
||||
// Just return undefined if there is no images
|
||||
if (images.length === 0) return;
|
||||
|
||||
@ -198,9 +195,9 @@ module.exports.best_image = function() {
|
||||
var project_target = check_reqs.get_target().replace('android-', '');
|
||||
for (var i in images) {
|
||||
var target = images[i].target;
|
||||
if(target) {
|
||||
if (target) {
|
||||
var num = target.split('(API level ')[1].replace(')', '');
|
||||
if (num == project_target) {
|
||||
if (num === project_target) {
|
||||
return images[i];
|
||||
} else if (project_target - num < closest && project_target > num) {
|
||||
closest = project_target - num;
|
||||
@ -213,19 +210,18 @@ module.exports.best_image = function() {
|
||||
};
|
||||
|
||||
// Returns a promise.
|
||||
module.exports.list_started = function() {
|
||||
module.exports.list_started = function () {
|
||||
return Adb.devices({emulators: true});
|
||||
};
|
||||
|
||||
// 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) {
|
||||
module.exports.list_targets = function () {
|
||||
return superspawn.spawn('android', ['list', 'targets'], {cwd: os.tmpdir()}).then(function (output) {
|
||||
var target_out = output.split('\n');
|
||||
var targets = [];
|
||||
for (var i = target_out.length; i >= 0; i--) {
|
||||
if(target_out[i].match(/id:/)) {
|
||||
if (target_out[i].match(/id:/)) {
|
||||
targets.push(targets[i].split(' ')[1]);
|
||||
}
|
||||
}
|
||||
@ -240,9 +236,8 @@ module.exports.list_targets = function() {
|
||||
module.exports.get_available_port = function () {
|
||||
var self = this;
|
||||
|
||||
return self.list_started()
|
||||
.then(function (emulators) {
|
||||
for (var p = 5584; p >= 5554; p-=2) {
|
||||
return self.list_started().then(function (emulators) {
|
||||
for (var p = 5584; p >= 5554; p -= 2) {
|
||||
if (emulators.indexOf('emulator-' + p) === -1) {
|
||||
events.emit('verbose', 'Found available port: ' + p);
|
||||
return p;
|
||||
@ -262,14 +257,13 @@ module.exports.get_available_port = function () {
|
||||
*
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.start = function(emulator_ID, boot_timeout) {
|
||||
module.exports.start = function (emulator_ID, boot_timeout) {
|
||||
var self = this;
|
||||
|
||||
return Q().then(function() {
|
||||
return Q().then(function () {
|
||||
if (emulator_ID) return Q(emulator_ID);
|
||||
|
||||
return self.best_image()
|
||||
.then(function(best) {
|
||||
return self.best_image().then(function (best) {
|
||||
if (best && best.name) {
|
||||
events.emit('warn', 'No emulator specified, defaulting to ' + best.name);
|
||||
return best.name;
|
||||
@ -281,9 +275,8 @@ module.exports.start = function(emulator_ID, boot_timeout) {
|
||||
'2. Create an AVD by running: ' + androidCmd + ' avd\n' +
|
||||
'HINT: For a faster emulator, use an Intel System Image and install the HAXM device driver\n'));
|
||||
});
|
||||
}).then(function(emulatorId) {
|
||||
return self.get_available_port()
|
||||
.then(function (port) {
|
||||
}).then(function (emulatorId) {
|
||||
return self.get_available_port().then(function (port) {
|
||||
// Figure out the directory the emulator binary runs in, and set the cwd to that directory.
|
||||
// Workaround for https://code.google.com/p/android/issues/detail?id=235461
|
||||
var emulator_dir = path.dirname(shelljs.which('emulator'));
|
||||
@ -297,20 +290,17 @@ module.exports.start = function(emulator_ID, boot_timeout) {
|
||||
events.emit('log', 'Waiting for emulator to start...');
|
||||
return self.wait_for_emulator(port);
|
||||
});
|
||||
}).then(function(emulatorId) {
|
||||
if (!emulatorId)
|
||||
return Q.reject(new CordovaError('Failed to start emulator'));
|
||||
}).then(function (emulatorId) {
|
||||
if (!emulatorId) { return Q.reject(new CordovaError('Failed to start emulator')); }
|
||||
|
||||
//wait for emulator to boot up
|
||||
// wait for emulator to boot up
|
||||
process.stdout.write('Waiting for emulator to boot (this may take a while)...');
|
||||
return self.wait_for_boot(emulatorId, boot_timeout)
|
||||
.then(function(success) {
|
||||
return self.wait_for_boot(emulatorId, boot_timeout).then(function (success) {
|
||||
if (success) {
|
||||
events.emit('log','BOOT COMPLETE');
|
||||
//unlock screen
|
||||
return Adb.shell(emulatorId, 'input keyevent 82')
|
||||
.then(function() {
|
||||
//return the new emulator id for the started emulators
|
||||
events.emit('log', 'BOOT COMPLETE');
|
||||
// unlock screen
|
||||
return Adb.shell(emulatorId, 'input keyevent 82').then(function () {
|
||||
// return the new emulator id for the started emulators
|
||||
return emulatorId;
|
||||
});
|
||||
} else {
|
||||
@ -325,20 +315,19 @@ module.exports.start = function(emulator_ID, boot_timeout) {
|
||||
* Waits for an emulator to boot on a given port.
|
||||
* Returns this emulator's ID in a promise.
|
||||
*/
|
||||
module.exports.wait_for_emulator = function(port) {
|
||||
module.exports.wait_for_emulator = function (port) {
|
||||
var self = this;
|
||||
return Q().then(function() {
|
||||
return Q().then(function () {
|
||||
var emulator_id = 'emulator-' + port;
|
||||
return Adb.shell(emulator_id, 'getprop dev.bootcomplete')
|
||||
.then(function (output) {
|
||||
return Adb.shell(emulator_id, 'getprop dev.bootcomplete').then(function (output) {
|
||||
if (output.indexOf('1') >= 0) {
|
||||
return emulator_id;
|
||||
}
|
||||
return self.wait_for_emulator(port);
|
||||
}, function (error) {
|
||||
if (error && error.message &&
|
||||
(error.message.indexOf('not found') > -1) ||
|
||||
error.message.indexOf('device offline') > -1) {
|
||||
if ((error && error.message &&
|
||||
(error.message.indexOf('not found') > -1)) ||
|
||||
(error.message.indexOf('device offline') > -1)) {
|
||||
// emulator not yet started, continue waiting
|
||||
return self.wait_for_emulator(port);
|
||||
} else {
|
||||
@ -346,7 +335,7 @@ module.exports.wait_for_emulator = function(port) {
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
@ -354,10 +343,9 @@ module.exports.wait_for_emulator = function(port) {
|
||||
* promise that resolves to a boolean indicating success. Not specifying a
|
||||
* time_remaining or passing a negative value will cause it to wait forever
|
||||
*/
|
||||
module.exports.wait_for_boot = function(emulator_id, time_remaining) {
|
||||
module.exports.wait_for_boot = function (emulator_id, time_remaining) {
|
||||
var self = this;
|
||||
return Adb.shell(emulator_id, 'ps')
|
||||
.then(function(output) {
|
||||
return Adb.shell(emulator_id, 'ps').then(function (output) {
|
||||
if (output.match(/android\.process\.acore/)) {
|
||||
return true;
|
||||
} else if (time_remaining === 0) {
|
||||
@ -366,7 +354,7 @@ module.exports.wait_for_boot = function(emulator_id, time_remaining) {
|
||||
process.stdout.write('.');
|
||||
|
||||
// Check at regular intervals
|
||||
return Q.delay(time_remaining < CHECK_BOOTED_INTERVAL ? time_remaining : CHECK_BOOTED_INTERVAL).then(function() {
|
||||
return Q.delay(time_remaining < CHECK_BOOTED_INTERVAL ? time_remaining : CHECK_BOOTED_INTERVAL).then(function () {
|
||||
var updated_time = time_remaining >= 0 ? Math.max(time_remaining - CHECK_BOOTED_INTERVAL, 0) : time_remaining;
|
||||
return self.wait_for_boot(emulator_id, updated_time);
|
||||
});
|
||||
@ -379,11 +367,10 @@ module.exports.wait_for_boot = function(emulator_id, time_remaining) {
|
||||
* TODO : Enter the stdin input required to complete the creation of an avd.
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.create_image = function(name, target) {
|
||||
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 superspawn.spawn('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);
|
||||
@ -391,22 +378,20 @@ module.exports.create_image = function(name, target) {
|
||||
} 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 superspawn.spawn('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 Q.reject();
|
||||
}, function(error) {
|
||||
}, function (error) {
|
||||
console.error('ERROR : Failed to create emulator image : ');
|
||||
console.error(error);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.resolveTarget = function(target) {
|
||||
return this.list_started()
|
||||
.then(function(emulator_list) {
|
||||
module.exports.resolveTarget = function (target) {
|
||||
return this.list_started().then(function (emulator_list) {
|
||||
if (emulator_list.length < 1) {
|
||||
return Q.reject('No running Android emulators found, please start an emulator before deploying your project.');
|
||||
}
|
||||
@ -417,9 +402,8 @@ module.exports.resolveTarget = function(target) {
|
||||
return Q.reject('Unable to find target \'' + target + '\'. Failed to deploy to emulator.');
|
||||
}
|
||||
|
||||
return build.detectArchitecture(target)
|
||||
.then(function(arch) {
|
||||
return {target:target, arch:arch, isEmulator:true};
|
||||
return build.detectArchitecture(target).then(function (arch) {
|
||||
return {target: target, arch: arch, isEmulator: true};
|
||||
});
|
||||
});
|
||||
};
|
||||
@ -430,7 +414,7 @@ module.exports.resolveTarget = function(target) {
|
||||
* If no started emulators are found, error out.
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.install = function(givenTarget, buildResults) {
|
||||
module.exports.install = function (givenTarget, buildResults) {
|
||||
|
||||
var target;
|
||||
var manifest = new AndroidManifest(path.join(__dirname, '../../AndroidManifest.xml'));
|
||||
@ -438,7 +422,7 @@ module.exports.install = function(givenTarget, buildResults) {
|
||||
|
||||
// resolve the target emulator
|
||||
return Q().then(function () {
|
||||
if (givenTarget && typeof givenTarget == 'object') {
|
||||
if (givenTarget && typeof givenTarget === 'object') {
|
||||
return givenTarget;
|
||||
} else {
|
||||
return module.exports.resolveTarget(givenTarget);
|
||||
@ -452,13 +436,12 @@ module.exports.install = function(givenTarget, buildResults) {
|
||||
}).then(function () {
|
||||
// This promise is always resolved, even if 'adb uninstall' fails to uninstall app
|
||||
// or the app doesn't installed at all, so no error catching needed.
|
||||
return Q.when()
|
||||
.then(function() {
|
||||
return Q.when().then(function () {
|
||||
|
||||
var apk_path = build.findBestApkForArchitecture(buildResults, target.arch);
|
||||
var execOptions = {
|
||||
cwd: os.tmpdir(),
|
||||
timeout: INSTALL_COMMAND_TIMEOUT, // in milliseconds
|
||||
timeout: INSTALL_COMMAND_TIMEOUT, // in milliseconds
|
||||
killSignal: EXEC_KILL_SIGNAL
|
||||
};
|
||||
|
||||
@ -469,12 +452,12 @@ module.exports.install = function(givenTarget, buildResults) {
|
||||
// A special function to call adb install in specific environment w/ specific options.
|
||||
// Introduced as a part of fix for http://issues.apache.org/jira/browse/CB-9119
|
||||
// to workaround sporadic emulator hangs
|
||||
function adbInstallWithOptions(target, apk, opts) {
|
||||
function adbInstallWithOptions (target, apk, opts) {
|
||||
events.emit('verbose', 'Installing apk ' + apk + ' on ' + target + '...');
|
||||
|
||||
var command = 'adb -s ' + target + ' install -r "' + apk + '"';
|
||||
return Q.promise(function (resolve, reject) {
|
||||
child_process.exec(command, opts, function(err, stdout, stderr) {
|
||||
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.
|
||||
@ -494,27 +477,23 @@ module.exports.install = function(givenTarget, buildResults) {
|
||||
}
|
||||
|
||||
function installPromise () {
|
||||
return adbInstallWithOptions(target.target, apk_path, execOptions)
|
||||
.catch(function (error) {
|
||||
return adbInstallWithOptions(target.target, apk_path, execOptions).catch(function (error) {
|
||||
// CB-9557 CB-10157 only uninstall and reinstall app if the one that
|
||||
// is already installed on device was signed w/different certificate
|
||||
if (!/INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES/.test(error.toString()))
|
||||
throw error;
|
||||
if (!/INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES/.test(error.toString())) { throw error; }
|
||||
|
||||
events.emit('warn', 'Uninstalling app from device and reinstalling it because the ' +
|
||||
'currently installed app was signed with different key');
|
||||
|
||||
// This promise is always resolved, even if 'adb uninstall' fails to uninstall app
|
||||
// or the app doesn't installed at all, so no error catching needed.
|
||||
return Adb.uninstall(target.target, pkgName)
|
||||
.then(function() {
|
||||
return Adb.uninstall(target.target, pkgName).then(function () {
|
||||
return adbInstallWithOptions(target.target, apk_path, execOptions);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return retry.retryPromise(NUM_INSTALL_RETRIES, installPromise)
|
||||
.then(function (output) {
|
||||
return retry.retryPromise(NUM_INSTALL_RETRIES, installPromise).then(function (output) {
|
||||
events.emit('log', 'INSTALL SUCCESS');
|
||||
});
|
||||
});
|
||||
|
3
bin/templates/cordova/lib/getASPath.bat
Normal file
3
bin/templates/cordova/lib/getASPath.bat
Normal file
@ -0,0 +1,3 @@
|
||||
@ECHO OFF
|
||||
for /f "tokens=2*" %%a in ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Android Studio" /v Path') do set "ASPath=%%~b"
|
||||
ECHO %ASPath%
|
20
bin/templates/cordova/lib/log.js
vendored
20
bin/templates/cordova/lib/log.js
vendored
@ -19,28 +19,28 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var path = require('path'),
|
||||
os = require('os'),
|
||||
Q = require('q'),
|
||||
child_process = require('child_process'),
|
||||
ROOT = path.join(__dirname, '..', '..');
|
||||
var path = require('path');
|
||||
var os = require('os');
|
||||
var Q = require('q');
|
||||
var child_process = require('child_process');
|
||||
var ROOT = path.join(__dirname, '..', '..');
|
||||
|
||||
/*
|
||||
* Starts running logcat in the shell.
|
||||
* Returns a promise.
|
||||
*/
|
||||
module.exports.run = function() {
|
||||
module.exports.run = function () {
|
||||
var d = Q.defer();
|
||||
var adb = child_process.spawn('adb', ['logcat'], {cwd: os.tmpdir()});
|
||||
|
||||
adb.stdout.on('data', function(data) {
|
||||
adb.stdout.on('data', function (data) {
|
||||
var lines = data ? data.toString().split('\n') : [];
|
||||
var out = lines.filter(function(x) { return x.indexOf('nativeGetEnabledTags') < 0; });
|
||||
var out = lines.filter(function (x) { return x.indexOf('nativeGetEnabledTags') < 0; });
|
||||
console.log(out.join('\n'));
|
||||
});
|
||||
|
||||
adb.stderr.on('data', console.error);
|
||||
adb.on('close', function(code) {
|
||||
adb.on('close', function (code) {
|
||||
if (code > 0) {
|
||||
d.reject('Failed to run logcat command.');
|
||||
} else d.resolve();
|
||||
@ -49,7 +49,7 @@ module.exports.run = function() {
|
||||
return d.promise;
|
||||
};
|
||||
|
||||
module.exports.help = function() {
|
||||
module.exports.help = function () {
|
||||
console.log('Usage: ' + path.relative(process.cwd(), path.join(ROOT, 'cordova', 'log')));
|
||||
console.log('Gives the logcat output on the command line.');
|
||||
process.exit(0);
|
||||
|
82
bin/templates/cordova/lib/pluginHandlers.js
vendored
82
bin/templates/cordova/lib/pluginHandlers.js
vendored
@ -26,15 +26,15 @@ var events = require('cordova-common').events;
|
||||
var CordovaError = require('cordova-common').CordovaError;
|
||||
|
||||
var handlers = {
|
||||
'source-file':{
|
||||
install:function(obj, plugin, project, options) {
|
||||
'source-file': {
|
||||
install: function (obj, plugin, project, options) {
|
||||
if (!obj.src) throw new CordovaError(generateAttributeError('src', 'source-file', plugin.id));
|
||||
if (!obj.targetDir) throw new CordovaError(generateAttributeError('target-dir', 'source-file', plugin.id));
|
||||
|
||||
var dest = path.join(obj.targetDir, path.basename(obj.src));
|
||||
|
||||
if(options && options.android_studio === true) {
|
||||
dest = path.join('app/src/main/java', obj.targetDir.substring(4), path.basename(obj.src));
|
||||
if (options && options.android_studio === true) {
|
||||
dest = path.join('app/src/main/java', obj.targetDir.substring(4), path.basename(obj.src));
|
||||
}
|
||||
|
||||
if (options && options.force) {
|
||||
@ -43,42 +43,42 @@ var handlers = {
|
||||
copyNewFile(plugin.dir, obj.src, project.projectDir, dest, !!(options && options.link));
|
||||
}
|
||||
},
|
||||
uninstall:function(obj, plugin, project, options) {
|
||||
uninstall: function (obj, plugin, project, options) {
|
||||
var dest = path.join(obj.targetDir, path.basename(obj.src));
|
||||
|
||||
if(options && options.android_studio === true) {
|
||||
dest = path.join('app/src/main/java', obj.targetDir.substring(4), path.basename(obj.src));
|
||||
|
||||
if (options && options.android_studio === true) {
|
||||
dest = path.join('app/src/main/java', obj.targetDir.substring(4), path.basename(obj.src));
|
||||
}
|
||||
|
||||
deleteJava(project.projectDir, dest);
|
||||
}
|
||||
},
|
||||
'lib-file':{
|
||||
install:function(obj, plugin, project, options) {
|
||||
'lib-file': {
|
||||
install: function (obj, plugin, project, options) {
|
||||
var dest = path.join('libs', path.basename(obj.src));
|
||||
if(options && options.android_studio === true) {
|
||||
dest = path.join('app/libs', path.basename(obj.src));
|
||||
if (options && options.android_studio === true) {
|
||||
dest = path.join('app/libs', path.basename(obj.src));
|
||||
}
|
||||
copyFile(plugin.dir, obj.src, project.projectDir, dest, !!(options && options.link));
|
||||
},
|
||||
uninstall:function(obj, plugin, project, options) {
|
||||
uninstall: function (obj, plugin, project, options) {
|
||||
var dest = path.join('libs', path.basename(obj.src));
|
||||
if(options && options.android_studio === true) {
|
||||
dest = path.join('app/libs', path.basename(obj.src));
|
||||
if (options && options.android_studio === true) {
|
||||
dest = path.join('app/libs', path.basename(obj.src));
|
||||
}
|
||||
removeFile(project.projectDir, dest);
|
||||
}
|
||||
},
|
||||
'resource-file':{
|
||||
install:function(obj, plugin, project, options) {
|
||||
'resource-file': {
|
||||
install: function (obj, plugin, project, options) {
|
||||
copyFile(plugin.dir, obj.src, project.projectDir, path.normalize(obj.target), !!(options && options.link));
|
||||
},
|
||||
uninstall:function(obj, plugin, project, options) {
|
||||
uninstall: function (obj, plugin, project, options) {
|
||||
removeFile(project.projectDir, path.normalize(obj.target));
|
||||
}
|
||||
},
|
||||
'framework': {
|
||||
install:function(obj, plugin, project, options) {
|
||||
install: function (obj, plugin, project, options) {
|
||||
var src = obj.src;
|
||||
if (!src) throw new CordovaError(generateAttributeError('src', 'framework', plugin.id));
|
||||
|
||||
@ -95,15 +95,15 @@ var handlers = {
|
||||
subDir = src;
|
||||
}
|
||||
|
||||
if (obj.type == 'gradleReference') {
|
||||
if (obj.type === 'gradleReference') {
|
||||
project.addGradleReference(parentDir, subDir);
|
||||
} else if (obj.type == 'sys') {
|
||||
} else if (obj.type === 'sys') {
|
||||
project.addSystemLibrary(parentDir, subDir);
|
||||
} else {
|
||||
project.addSubProject(parentDir, subDir);
|
||||
}
|
||||
},
|
||||
uninstall:function(obj, plugin, project, options) {
|
||||
uninstall: function (obj, plugin, project, options) {
|
||||
var src = obj.src;
|
||||
if (!src) throw new CordovaError(generateAttributeError('src', 'framework', plugin.id));
|
||||
|
||||
@ -125,17 +125,17 @@ var handlers = {
|
||||
subDir = src;
|
||||
}
|
||||
|
||||
if (obj.type == 'gradleReference') {
|
||||
if (obj.type === 'gradleReference') {
|
||||
project.removeGradleReference(parentDir, subDir);
|
||||
} else if (obj.type == 'sys') {
|
||||
} else if (obj.type === 'sys') {
|
||||
project.removeSystemLibrary(parentDir, subDir);
|
||||
} else {
|
||||
project.removeSubProject(parentDir, subDir);
|
||||
}
|
||||
}
|
||||
},
|
||||
asset:{
|
||||
install:function(obj, plugin, project, options) {
|
||||
asset: {
|
||||
install: function (obj, plugin, project, options) {
|
||||
if (!obj.src) {
|
||||
throw new CordovaError(generateAttributeError('src', 'asset', plugin.id));
|
||||
}
|
||||
@ -149,7 +149,7 @@ var handlers = {
|
||||
copyFile(plugin.dir, obj.src, project.platformWww, obj.target);
|
||||
}
|
||||
},
|
||||
uninstall:function(obj, plugin, project, options) {
|
||||
uninstall: function (obj, plugin, project, options) {
|
||||
var target = obj.target || obj.src;
|
||||
|
||||
if (!target) throw new CordovaError(generateAttributeError('target', 'asset', plugin.id));
|
||||
@ -167,7 +167,7 @@ var handlers = {
|
||||
install: function (obj, plugin, project, options) {
|
||||
// Copy the plugin's files into the www directory.
|
||||
var moduleSource = path.resolve(plugin.dir, obj.src);
|
||||
var moduleName = plugin.id + '.' + (obj.name || path.basename(obj.src, path.extname (obj.src)));
|
||||
var moduleName = plugin.id + '.' + (obj.name || path.basename(obj.src, path.extname(obj.src)));
|
||||
|
||||
// Read in the file, prepend the cordova.define, and write it back out.
|
||||
var scriptContent = fs.readFileSync(moduleSource, 'utf-8').replace(/^\ufeff/, ''); // Window BOM
|
||||
@ -206,7 +206,7 @@ module.exports.getInstaller = function (type) {
|
||||
events.emit('verbose', '<' + type + '> is not supported for android plugins');
|
||||
};
|
||||
|
||||
module.exports.getUninstaller = function(type) {
|
||||
module.exports.getUninstaller = function (type) {
|
||||
if (handlers[type] && handlers[type].uninstall) {
|
||||
return handlers[type].uninstall;
|
||||
}
|
||||
@ -221,21 +221,19 @@ function copyFile (plugin_dir, src, project_dir, dest, link) {
|
||||
// check that src path is inside plugin directory
|
||||
var real_path = fs.realpathSync(src);
|
||||
var real_plugin_path = fs.realpathSync(plugin_dir);
|
||||
if (real_path.indexOf(real_plugin_path) !== 0)
|
||||
throw new CordovaError('File "' + src + '" is located outside the plugin directory "' + plugin_dir + '"');
|
||||
if (real_path.indexOf(real_plugin_path) !== 0) { throw new CordovaError('File "' + src + '" is located outside the plugin directory "' + plugin_dir + '"'); }
|
||||
|
||||
dest = path.resolve(project_dir, dest);
|
||||
|
||||
// check that dest path is located in project directory
|
||||
if (dest.indexOf(project_dir) !== 0)
|
||||
throw new CordovaError('Destination "' + dest + '" for source file "' + src + '" is located outside the project');
|
||||
if (dest.indexOf(project_dir) !== 0) { throw new CordovaError('Destination "' + dest + '" for source file "' + src + '" is located outside the project'); }
|
||||
|
||||
shell.mkdir('-p', path.dirname(dest));
|
||||
if (link) {
|
||||
symlinkFileOrDirTree(src, dest);
|
||||
} else if (fs.statSync(src).isDirectory()) {
|
||||
// XXX shelljs decides to create a directory when -R|-r is used which sucks. http://goo.gl/nbsjq
|
||||
shell.cp('-Rf', src+'/*', dest);
|
||||
shell.cp('-Rf', src + '/*', dest);
|
||||
} else {
|
||||
shell.cp('-f', src, dest);
|
||||
}
|
||||
@ -244,24 +242,22 @@ function copyFile (plugin_dir, src, project_dir, dest, link) {
|
||||
// Same as copy file but throws error if target exists
|
||||
function copyNewFile (plugin_dir, src, project_dir, dest, link) {
|
||||
var target_path = path.resolve(project_dir, dest);
|
||||
if (fs.existsSync(target_path))
|
||||
throw new CordovaError('"' + target_path + '" already exists!');
|
||||
if (fs.existsSync(target_path)) { throw new CordovaError('"' + target_path + '" already exists!'); }
|
||||
|
||||
copyFile(plugin_dir, src, project_dir, dest, !!link);
|
||||
}
|
||||
|
||||
function symlinkFileOrDirTree(src, dest) {
|
||||
function symlinkFileOrDirTree (src, dest) {
|
||||
if (fs.existsSync(dest)) {
|
||||
shell.rm('-Rf', dest);
|
||||
}
|
||||
|
||||
if (fs.statSync(src).isDirectory()) {
|
||||
shell.mkdir('-p', dest);
|
||||
fs.readdirSync(src).forEach(function(entry) {
|
||||
fs.readdirSync(src).forEach(function (entry) {
|
||||
symlinkFileOrDirTree(path.join(src, entry), path.join(dest, entry));
|
||||
});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
fs.symlinkSync(path.relative(fs.realpathSync(path.dirname(dest)), src), dest);
|
||||
}
|
||||
}
|
||||
@ -292,8 +288,8 @@ function removeFileAndParents (baseDir, destFile, stopper) {
|
||||
// check if directory is empty
|
||||
var curDir = path.dirname(file);
|
||||
|
||||
while(curDir !== path.resolve(baseDir, stopper)) {
|
||||
if(fs.existsSync(curDir) && fs.readdirSync(curDir).length === 0) {
|
||||
while (curDir !== path.resolve(baseDir, stopper)) {
|
||||
if (fs.existsSync(curDir) && fs.readdirSync(curDir).length === 0) {
|
||||
fs.rmdirSync(curDir);
|
||||
curDir = path.resolve(curDir, '..');
|
||||
} else {
|
||||
@ -303,6 +299,6 @@ function removeFileAndParents (baseDir, destFile, stopper) {
|
||||
}
|
||||
}
|
||||
|
||||
function generateAttributeError(attribute, element, id) {
|
||||
function generateAttributeError (attribute, element, id) {
|
||||
return 'Required attribute "' + attribute + '" not specified in <' + element + '> element from plugin: ' + id;
|
||||
}
|
||||
|
68
bin/templates/cordova/lib/prepare.js
vendored
68
bin/templates/cordova/lib/prepare.js
vendored
@ -16,6 +16,7 @@
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
/* eslint no-useless-escape: 0 */
|
||||
|
||||
var Q = require('q');
|
||||
var fs = require('fs');
|
||||
@ -40,17 +41,14 @@ module.exports.prepare = function (cordovaProject, options) {
|
||||
this._config = updateConfigFilesFrom(cordovaProject.projectConfig, munger, this.locations);
|
||||
|
||||
// Update own www dir with project's www assets and plugins' assets and js-files
|
||||
return Q.when(updateWww(cordovaProject, this.locations))
|
||||
.then(function () {
|
||||
return Q.when(updateWww(cordovaProject, this.locations)).then(function () {
|
||||
// update project according to config.xml changes.
|
||||
return updateProjectAccordingTo(self._config, self.locations);
|
||||
})
|
||||
.then(function () {
|
||||
}).then(function () {
|
||||
updateIcons(cordovaProject, path.relative(cordovaProject.root, self.locations.res));
|
||||
updateSplashes(cordovaProject, path.relative(cordovaProject.root, self.locations.res));
|
||||
updateFileResources(cordovaProject, path.relative(cordovaProject.root, self.locations.root));
|
||||
})
|
||||
.then(function () {
|
||||
}).then(function () {
|
||||
events.emit('verbose', 'Prepared android project successfully');
|
||||
});
|
||||
};
|
||||
@ -91,7 +89,7 @@ module.exports.clean = function (options) {
|
||||
* represents current project's configuration. When returned, the
|
||||
* configuration is already dumped to appropriate config.xml file.
|
||||
*/
|
||||
function updateConfigFilesFrom(sourceConfig, configMunger, locations) {
|
||||
function updateConfigFilesFrom (sourceConfig, configMunger, locations) {
|
||||
events.emit('verbose', 'Generating platform-specific config.xml from defaults for android at ' + locations.configXml);
|
||||
|
||||
// First cleanup current config and merge project's one into own
|
||||
@ -106,7 +104,7 @@ function updateConfigFilesFrom(sourceConfig, configMunger, locations) {
|
||||
// Merge changes from app's config.xml into platform's one
|
||||
var config = new ConfigParser(locations.configXml);
|
||||
xmlHelpers.mergeXml(sourceConfig.doc.getroot(),
|
||||
config.doc.getroot(), 'android', /*clobber=*/true);
|
||||
config.doc.getroot(), 'android', /* clobber= */true);
|
||||
|
||||
config.write();
|
||||
return config;
|
||||
@ -115,7 +113,7 @@ function updateConfigFilesFrom(sourceConfig, configMunger, locations) {
|
||||
/**
|
||||
* Logs all file operations via the verbose event stream, indented.
|
||||
*/
|
||||
function logFileOp(message) {
|
||||
function logFileOp (message) {
|
||||
events.emit('verbose', ' ' + message);
|
||||
}
|
||||
|
||||
@ -128,7 +126,7 @@ function logFileOp(message) {
|
||||
* @param {Object} destinations An object that contains destination
|
||||
* paths for www files.
|
||||
*/
|
||||
function updateWww(cordovaProject, destinations) {
|
||||
function updateWww (cordovaProject, destinations) {
|
||||
var sourceDirs = [
|
||||
path.relative(cordovaProject.root, cordovaProject.locations.www),
|
||||
path.relative(cordovaProject.root, destinations.platformWww)
|
||||
@ -151,7 +149,7 @@ function updateWww(cordovaProject, destinations) {
|
||||
/**
|
||||
* Cleans all files from the platform 'www' directory.
|
||||
*/
|
||||
function cleanWww(projectRoot, locations) {
|
||||
function cleanWww (projectRoot, locations) {
|
||||
var targetDir = path.relative(projectRoot, locations.www);
|
||||
events.emit('verbose', 'Cleaning ' + targetDir);
|
||||
|
||||
@ -167,7 +165,7 @@ function cleanWww(projectRoot, locations) {
|
||||
* be used to update project
|
||||
* @param {Object} locations A map of locations for this platform
|
||||
*/
|
||||
function updateProjectAccordingTo(platformConfig, locations) {
|
||||
function updateProjectAccordingTo (platformConfig, locations) {
|
||||
// Update app name by editing res/values/strings.xml
|
||||
var name = platformConfig.name();
|
||||
var strings = xmlHelpers.parseElementtreeSync(locations.strings);
|
||||
@ -202,7 +200,7 @@ function updateProjectAccordingTo(platformConfig, locations) {
|
||||
|
||||
if (java_files.length === 0) {
|
||||
throw new CordovaError('No Java files found that extend CordovaActivity.');
|
||||
} else if(java_files.length > 1) {
|
||||
} else if (java_files.length > 1) {
|
||||
events.emit('log', 'Multiple candidate Java files that extend CordovaActivity found. Guessing at the first one, ' + java_files[0]);
|
||||
}
|
||||
|
||||
@ -213,12 +211,12 @@ function updateProjectAccordingTo(platformConfig, locations) {
|
||||
|
||||
if (orig_pkg !== pkg) {
|
||||
// If package was name changed we need to remove old java with main activity
|
||||
shell.rm('-Rf',java_files[0]);
|
||||
shell.rm('-Rf', java_files[0]);
|
||||
// remove any empty directories
|
||||
var currentDir = path.dirname(java_files[0]);
|
||||
var sourcesRoot = path.resolve(locations.root, 'src');
|
||||
while(currentDir !== sourcesRoot) {
|
||||
if(fs.existsSync(currentDir) && fs.readdirSync(currentDir).length === 0) {
|
||||
while (currentDir !== sourcesRoot) {
|
||||
if (fs.existsSync(currentDir) && fs.readdirSync(currentDir).length === 0) {
|
||||
fs.rmdirSync(currentDir);
|
||||
currentDir = path.resolve(currentDir, '..');
|
||||
} else {
|
||||
@ -231,7 +229,7 @@ function updateProjectAccordingTo(platformConfig, locations) {
|
||||
// Consturct the default value for versionCode as
|
||||
// PATCH + MINOR * 100 + MAJOR * 10000
|
||||
// see http://developer.android.com/tools/publishing/versioning.html
|
||||
function default_versionCode(version) {
|
||||
function default_versionCode (version) {
|
||||
var nums = version.split('-')[0].split('.');
|
||||
var versionCode = 0;
|
||||
if (+nums[0]) {
|
||||
@ -248,7 +246,7 @@ function default_versionCode(version) {
|
||||
return versionCode;
|
||||
}
|
||||
|
||||
function getImageResourcePath(resourcesDir, type, density, name, sourceName) {
|
||||
function getImageResourcePath (resourcesDir, type, density, name, sourceName) {
|
||||
if (/\.9\.png$/.test(sourceName)) {
|
||||
name = name.replace(/\.png$/, '.9.png');
|
||||
}
|
||||
@ -256,7 +254,7 @@ function getImageResourcePath(resourcesDir, type, density, name, sourceName) {
|
||||
return resourcePath;
|
||||
}
|
||||
|
||||
function updateSplashes(cordovaProject, platformResourcesDir) {
|
||||
function updateSplashes (cordovaProject, platformResourcesDir) {
|
||||
var resources = cordovaProject.projectConfig.getSplashScreens('android');
|
||||
|
||||
// if there are "splash" elements in config.xml
|
||||
@ -272,7 +270,7 @@ function updateSplashes(cordovaProject, platformResourcesDir) {
|
||||
if (!resource.density) {
|
||||
return;
|
||||
}
|
||||
if (resource.density == 'mdpi') {
|
||||
if (resource.density === 'mdpi') {
|
||||
hadMdpi = true;
|
||||
}
|
||||
var targetPath = getImageResourcePath(
|
||||
@ -292,7 +290,7 @@ function updateSplashes(cordovaProject, platformResourcesDir) {
|
||||
resourceMap, { rootDir: cordovaProject.root }, logFileOp);
|
||||
}
|
||||
|
||||
function cleanSplashes(projectRoot, projectConfig, platformResourcesDir) {
|
||||
function cleanSplashes (projectRoot, projectConfig, platformResourcesDir) {
|
||||
var resources = projectConfig.getSplashScreens('android');
|
||||
if (resources.length > 0) {
|
||||
var resourceMap = mapImageResources(projectRoot, platformResourcesDir, 'drawable', 'screen.png');
|
||||
@ -304,7 +302,7 @@ function cleanSplashes(projectRoot, projectConfig, platformResourcesDir) {
|
||||
}
|
||||
}
|
||||
|
||||
function updateIcons(cordovaProject, platformResourcesDir) {
|
||||
function updateIcons (cordovaProject, platformResourcesDir) {
|
||||
var icons = cordovaProject.projectConfig.getIcons('android');
|
||||
|
||||
// if there are icon elements in config.xml
|
||||
@ -328,7 +326,7 @@ function updateIcons(cordovaProject, platformResourcesDir) {
|
||||
};
|
||||
// find the best matching icon for a given density or size
|
||||
// @output android_icons
|
||||
var parseIcon = function(icon, icon_size) {
|
||||
var parseIcon = function (icon, icon_size) {
|
||||
// do I have a platform icon for that density already
|
||||
var density = icon.density || sizeToDensityMap[icon_size];
|
||||
if (!density) {
|
||||
@ -343,7 +341,7 @@ function updateIcons(cordovaProject, platformResourcesDir) {
|
||||
};
|
||||
|
||||
// iterate over all icon elements to find the default icon and call parseIcon
|
||||
for (var i=0; i<icons.length; i++) {
|
||||
for (var i = 0; i < icons.length; i++) {
|
||||
var icon = icons[i];
|
||||
var size = icon.width;
|
||||
if (!size) {
|
||||
@ -380,7 +378,7 @@ function updateIcons(cordovaProject, platformResourcesDir) {
|
||||
resourceMap, { rootDir: cordovaProject.root }, logFileOp);
|
||||
}
|
||||
|
||||
function cleanIcons(projectRoot, projectConfig, platformResourcesDir) {
|
||||
function cleanIcons (projectRoot, projectConfig, platformResourcesDir) {
|
||||
var icons = projectConfig.getIcons('android');
|
||||
if (icons.length > 0) {
|
||||
var resourceMap = mapImageResources(projectRoot, platformResourcesDir, 'mipmap', 'icon.png');
|
||||
@ -395,18 +393,16 @@ function cleanIcons(projectRoot, projectConfig, platformResourcesDir) {
|
||||
/**
|
||||
* Gets a map containing resources of a specified name from all drawable folders in a directory.
|
||||
*/
|
||||
function mapImageResources(rootDir, subDir, type, resourceName) {
|
||||
function mapImageResources (rootDir, subDir, type, resourceName) {
|
||||
var pathMap = {};
|
||||
shell.ls(path.join(rootDir, subDir, type + '-*'))
|
||||
.forEach(function (drawableFolder) {
|
||||
shell.ls(path.join(rootDir, subDir, type + '-*')).forEach(function (drawableFolder) {
|
||||
var imagePath = path.join(subDir, path.basename(drawableFolder), resourceName);
|
||||
pathMap[imagePath] = null;
|
||||
});
|
||||
return pathMap;
|
||||
}
|
||||
|
||||
|
||||
function updateFileResources(cordovaProject, platformDir) {
|
||||
function updateFileResources (cordovaProject, platformDir) {
|
||||
var files = cordovaProject.projectConfig.getFileResources('android');
|
||||
|
||||
// if there are resource-file elements in config.xml
|
||||
@ -416,7 +412,7 @@ function updateFileResources(cordovaProject, platformDir) {
|
||||
}
|
||||
|
||||
var resourceMap = {};
|
||||
files.forEach(function(res) {
|
||||
files.forEach(function (res) {
|
||||
var targetPath = path.join(platformDir, res.target);
|
||||
resourceMap[targetPath] = res.src;
|
||||
});
|
||||
@ -426,20 +422,20 @@ function updateFileResources(cordovaProject, platformDir) {
|
||||
resourceMap, { rootDir: cordovaProject.root }, logFileOp);
|
||||
}
|
||||
|
||||
|
||||
function cleanFileResources(projectRoot, projectConfig, platformDir) {
|
||||
function cleanFileResources (projectRoot, projectConfig, platformDir) {
|
||||
var files = projectConfig.getFileResources('android', true);
|
||||
if (files.length > 0) {
|
||||
events.emit('verbose', 'Cleaning resource files at ' + platformDir);
|
||||
|
||||
var resourceMap = {};
|
||||
files.forEach(function(res) {
|
||||
files.forEach(function (res) {
|
||||
var filePath = path.join(platformDir, res.target);
|
||||
resourceMap[filePath] = null;
|
||||
});
|
||||
|
||||
FileUpdater.updatePaths(
|
||||
resourceMap, { rootDir: projectRoot, all: true}, logFileOp);
|
||||
resourceMap, {
|
||||
rootDir: projectRoot, all: true}, logFileOp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -454,7 +450,7 @@ function cleanFileResources(projectRoot, projectConfig, platformDir) {
|
||||
* default value, if there is no such preference. The default value is
|
||||
* 'singleTop'
|
||||
*/
|
||||
function findAndroidLaunchModePreference(platformConfig) {
|
||||
function findAndroidLaunchModePreference (platformConfig) {
|
||||
var launchMode = platformConfig.getPreference('AndroidLaunchMode');
|
||||
if (!launchMode) {
|
||||
// Return a default value
|
||||
|
4
bin/templates/cordova/lib/retry.js
vendored
4
bin/templates/cordova/lib/retry.js
vendored
@ -45,12 +45,12 @@ module.exports.retryPromise = function (attemts_left, promiseFunction) {
|
||||
return promiseFunction.apply(undefined, promiseFunctionArguments).then(
|
||||
|
||||
// on success pass results through
|
||||
function onFulfilled(value) {
|
||||
function onFulfilled (value) {
|
||||
return value;
|
||||
},
|
||||
|
||||
// on rejection either retry, or throw the error
|
||||
function onRejected(error) {
|
||||
function onRejected (error) {
|
||||
|
||||
attemts_left -= 1;
|
||||
|
||||
|
57
bin/templates/cordova/lib/run.js
vendored
57
bin/templates/cordova/lib/run.js
vendored
@ -21,14 +21,14 @@
|
||||
|
||||
/* jshint loopfunc:true */
|
||||
|
||||
var path = require('path'),
|
||||
build = require('./build'),
|
||||
emulator = require('./emulator'),
|
||||
device = require('./device'),
|
||||
Q = require('q'),
|
||||
events = require('cordova-common').events;
|
||||
var path = require('path');
|
||||
var build = require('./build');
|
||||
var emulator = require('./emulator');
|
||||
var device = require('./device');
|
||||
var Q = require('q');
|
||||
var events = require('cordova-common').events;
|
||||
|
||||
function getInstallTarget(runOptions) {
|
||||
function getInstallTarget (runOptions) {
|
||||
var install_target;
|
||||
if (runOptions.target) {
|
||||
install_target = runOptions.target;
|
||||
@ -51,17 +51,15 @@ function getInstallTarget(runOptions) {
|
||||
*
|
||||
* @return {Promise}
|
||||
*/
|
||||
module.exports.run = function(runOptions) {
|
||||
module.exports.run = function (runOptions) {
|
||||
|
||||
var self = this;
|
||||
var install_target = getInstallTarget(runOptions);
|
||||
|
||||
return Q()
|
||||
.then(function() {
|
||||
return Q().then(function () {
|
||||
if (!install_target) {
|
||||
// no target given, deploy to device if available, otherwise use the emulator.
|
||||
return device.list()
|
||||
.then(function(device_list) {
|
||||
return device.list().then(function (device_list) {
|
||||
if (device_list.length > 0) {
|
||||
events.emit('warn', 'No target specified, deploying to device \'' + device_list[0] + '\'.');
|
||||
install_target = device_list[0];
|
||||
@ -71,36 +69,31 @@ function getInstallTarget(runOptions) {
|
||||
}
|
||||
});
|
||||
}
|
||||
}).then(function() {
|
||||
if (install_target == '--device') {
|
||||
}).then(function () {
|
||||
if (install_target === '--device') {
|
||||
return device.resolveTarget(null);
|
||||
} else if (install_target == '--emulator') {
|
||||
} else if (install_target === '--emulator') {
|
||||
// Give preference to any already started emulators. Else, start one.
|
||||
return emulator.list_started()
|
||||
.then(function(started) {
|
||||
return emulator.list_started().then(function (started) {
|
||||
return started && started.length > 0 ? started[0] : emulator.start();
|
||||
}).then(function(emulatorId) {
|
||||
}).then(function (emulatorId) {
|
||||
return emulator.resolveTarget(emulatorId);
|
||||
});
|
||||
}
|
||||
// They specified a specific device/emulator ID.
|
||||
return device.list()
|
||||
.then(function(devices) {
|
||||
return device.list().then(function (devices) {
|
||||
if (devices.indexOf(install_target) > -1) {
|
||||
return device.resolveTarget(install_target);
|
||||
}
|
||||
return emulator.list_started()
|
||||
.then(function(started_emulators) {
|
||||
return emulator.list_started().then(function (started_emulators) {
|
||||
if (started_emulators.indexOf(install_target) > -1) {
|
||||
return emulator.resolveTarget(install_target);
|
||||
}
|
||||
return emulator.list_images()
|
||||
.then(function(avds) {
|
||||
return emulator.list_images().then(function (avds) {
|
||||
// if target emulator isn't started, then start it.
|
||||
for (var avd in avds) {
|
||||
if (avds[avd].name == install_target) {
|
||||
return emulator.start(install_target)
|
||||
.then(function(emulatorId) {
|
||||
if (avds[avd].name === install_target) {
|
||||
return emulator.start(install_target).then(function (emulatorId) {
|
||||
return emulator.resolveTarget(emulatorId);
|
||||
});
|
||||
}
|
||||
@ -109,16 +102,14 @@ function getInstallTarget(runOptions) {
|
||||
});
|
||||
});
|
||||
});
|
||||
}).then(function(resolvedTarget) {
|
||||
}).then(function (resolvedTarget) {
|
||||
// Better just call self.build, but we're doing some processing of
|
||||
// build results (according to platformApi spec) so they are in different
|
||||
// format than emulator.install expects.
|
||||
// TODO: Update emulator/device.install to handle this change
|
||||
return build.run.call(self, runOptions, resolvedTarget)
|
||||
.then(function(buildResults) {
|
||||
return build.run.call(self, runOptions, resolvedTarget).then(function (buildResults) {
|
||||
if (resolvedTarget.isEmulator) {
|
||||
return emulator.wait_for_boot(resolvedTarget.target)
|
||||
.then(function () {
|
||||
return emulator.wait_for_boot(resolvedTarget.target).then(function () {
|
||||
return emulator.install(resolvedTarget, buildResults);
|
||||
});
|
||||
}
|
||||
@ -127,7 +118,7 @@ function getInstallTarget(runOptions) {
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.help = function() {
|
||||
module.exports.help = function () {
|
||||
console.log('Usage: ' + path.relative(process.cwd(), process.argv[1]) + ' [options]');
|
||||
console.log('Build options :');
|
||||
console.log(' --debug : Builds project in debug mode');
|
||||
|
4191
bin/templates/project/assets/www/cordova.js
vendored
4191
bin/templates/project/assets/www/cordova.js
vendored
File diff suppressed because it is too large
Load Diff
@ -18,25 +18,25 @@
|
||||
*/
|
||||
var app = {
|
||||
// Application Constructor
|
||||
initialize: function() {
|
||||
initialize: function () {
|
||||
this.bindEvents();
|
||||
},
|
||||
// Bind Event Listeners
|
||||
//
|
||||
// Bind any events that are required on startup. Common events are:
|
||||
// 'load', 'deviceready', 'offline', and 'online'.
|
||||
bindEvents: function() {
|
||||
bindEvents: function () {
|
||||
document.addEventListener('deviceready', this.onDeviceReady, false);
|
||||
},
|
||||
// deviceready Event Handler
|
||||
//
|
||||
// The scope of 'this' is the event. In order to call the 'receivedEvent'
|
||||
// function, we must explicitly call 'app.receivedEvent(...);'
|
||||
onDeviceReady: function() {
|
||||
onDeviceReady: function () {
|
||||
app.receivedEvent('deviceready');
|
||||
},
|
||||
// Update DOM on a Received Event
|
||||
receivedEvent: function(id) {
|
||||
receivedEvent: function (id) {
|
||||
var parentElement = document.getElementById(id);
|
||||
var listeningElement = parentElement.querySelector('.listening');
|
||||
var receivedElement = parentElement.querySelector('.received');
|
||||
@ -48,4 +48,4 @@ var app = {
|
||||
}
|
||||
};
|
||||
|
||||
app.initialize();
|
||||
app.initialize();
|
||||
|
14
package.json
14
package.json
@ -19,10 +19,10 @@
|
||||
"apache"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "npm run jshint && jasmine",
|
||||
"test": "npm run eslint && jasmine",
|
||||
"cover": "istanbul cover --root bin/templates/cordova --print detail jasmine",
|
||||
"test-build": "jasmine --captureExceptions --color spec/e2e/*.spec.js",
|
||||
"jshint": "jshint bin && jshint spec"
|
||||
"eslint": "eslint bin && eslint spec"
|
||||
},
|
||||
"author": "Apache Software Foundation",
|
||||
"license": "Apache-2.0",
|
||||
@ -43,9 +43,15 @@
|
||||
"shelljs"
|
||||
],
|
||||
"devDependencies": {
|
||||
"eslint": "^3.19.0",
|
||||
"eslint-config-semistandard": "^11.0.0",
|
||||
"eslint-config-standard": "^10.2.1",
|
||||
"eslint-plugin-import": "^2.3.0",
|
||||
"eslint-plugin-node": "^5.0.0",
|
||||
"eslint-plugin-promise": "^3.5.0",
|
||||
"eslint-plugin-standard": "^3.0.1",
|
||||
"istanbul": "^0.4.2",
|
||||
"jasmine": "^2.5.2",
|
||||
"jshint": "^2.6.0",
|
||||
"promise-matchers": "~0",
|
||||
"rewire": "^2.1.3"
|
||||
},
|
||||
@ -53,4 +59,4 @@
|
||||
"node": ">=4.0.0"
|
||||
},
|
||||
"engineStrict": true
|
||||
}
|
||||
}
|
||||
|
2
spec/.eslintrc.yml
Normal file
2
spec/.eslintrc.yml
Normal file
@ -0,0 +1,2 @@
|
||||
env:
|
||||
jasmine: true
|
@ -21,7 +21,7 @@ var actions = require('./helpers/projectActions.js');
|
||||
|
||||
var CREATE_TIMEOUT = 180000;
|
||||
|
||||
function createAndBuild(projectname, projectid, done) {
|
||||
function createAndBuild (projectname, projectid, done) {
|
||||
actions.createProject(projectname, projectid, function (error) {
|
||||
expect(error).toBe(null);
|
||||
actions.buildProject(projectid, function (error) {
|
||||
@ -32,45 +32,44 @@ function createAndBuild(projectname, projectid, done) {
|
||||
});
|
||||
}
|
||||
|
||||
describe('create', function () {
|
||||
|
||||
describe('create', function() {
|
||||
|
||||
it('Test#001 : create project with ascii name, no spaces', function(done) {
|
||||
it('Test#001 : create project with ascii name, no spaces', function (done) {
|
||||
var projectname = 'testcreate';
|
||||
var projectid = 'com.test.create.app1';
|
||||
|
||||
createAndBuild(projectname, projectid, done);
|
||||
}, CREATE_TIMEOUT);
|
||||
|
||||
it('Test#002 : create project with ascii name, and spaces', function(done) {
|
||||
it('Test#002 : create project with ascii name, and spaces', function (done) {
|
||||
var projectname = 'test create';
|
||||
var projectid = 'com.test.create.app2';
|
||||
|
||||
createAndBuild(projectname, projectid, done);
|
||||
}, CREATE_TIMEOUT);
|
||||
|
||||
it('Test#003 : create project with unicode name, no spaces', function(done) {
|
||||
it('Test#003 : create project with unicode name, no spaces', function (done) {
|
||||
var projectname = '応応応応用用用用';
|
||||
var projectid = 'com.test.create.app3';
|
||||
|
||||
createAndBuild(projectname, projectid, done);
|
||||
}, CREATE_TIMEOUT);
|
||||
|
||||
it('Test#004 : create project with unicode name, and spaces', function(done) {
|
||||
it('Test#004 : create project with unicode name, and spaces', function (done) {
|
||||
var projectname = '応応応応 用用用用';
|
||||
var projectid = 'com.test.create.app4';
|
||||
|
||||
createAndBuild(projectname, projectid, done);
|
||||
}, CREATE_TIMEOUT);
|
||||
|
||||
it('Test#005 : create project with ascii+unicode name, no spaces', function(done) {
|
||||
it('Test#005 : create project with ascii+unicode name, no spaces', function (done) {
|
||||
var projectname = '応応応応hello用用用用';
|
||||
var projectid = 'com.test.create.app5';
|
||||
|
||||
createAndBuild(projectname, projectid, done);
|
||||
}, CREATE_TIMEOUT);
|
||||
|
||||
it('Test#006 : create project with ascii+unicode name, and spaces', function(done) {
|
||||
it('Test#006 : create project with ascii+unicode name, and spaces', function (done) {
|
||||
var projectname = '応応応応 hello 用用用用';
|
||||
var projectid = 'com.test.create.app6';
|
||||
|
||||
|
@ -17,11 +17,11 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var PluginInfoProvider = require('cordova-common').PluginInfoProvider,
|
||||
shell = require('shelljs'),
|
||||
cp = require('child_process'),
|
||||
path = require('path'),
|
||||
util = require('util');
|
||||
var PluginInfoProvider = require('cordova-common').PluginInfoProvider;
|
||||
var shell = require('shelljs');
|
||||
var cp = require('child_process');
|
||||
var path = require('path');
|
||||
var util = require('util');
|
||||
|
||||
var cordova_bin = path.join(__dirname, '../../../bin');
|
||||
|
||||
@ -70,7 +70,7 @@ module.exports.updateProject = function (projectid, platformpath, callback) {
|
||||
var projectDirName = getDirName(projectid);
|
||||
var updateScriptPath = platformpath ? path.join(platformpath, 'bin/update') : path.join(cordova_bin, 'update');
|
||||
var command = util.format('%s %s', updateScriptPath, projectDirName);
|
||||
|
||||
|
||||
cp.exec(command, function (error, stdout, stderr) {
|
||||
if (error) {
|
||||
console.log(stdout);
|
||||
@ -78,7 +78,7 @@ module.exports.updateProject = function (projectid, platformpath, callback) {
|
||||
}
|
||||
callback(error);
|
||||
});
|
||||
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@ -115,7 +115,7 @@ module.exports.removeProject = function (projectid) {
|
||||
* @param {function} callback - function which is called (without arguments) when the plugin is added or (with error object) when error occurs
|
||||
*/
|
||||
module.exports.addPlugin = function (projectid, plugindir, callback) {
|
||||
var projectDirName = getDirName(projectid);
|
||||
var projectDirName = getDirName(projectid);
|
||||
var pip = new PluginInfoProvider();
|
||||
var pluginInfo = pip.get(plugindir);
|
||||
var Api = require(path.join(__dirname, '../../..', projectDirName, 'cordova', 'Api.js'));
|
||||
@ -126,7 +126,7 @@ module.exports.addPlugin = function (projectid, plugindir, callback) {
|
||||
}, function (error) {
|
||||
console.error(error);
|
||||
callback(error);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -136,7 +136,7 @@ module.exports.addPlugin = function (projectid, plugindir, callback) {
|
||||
*/
|
||||
module.exports.getPlatformVersion = function (projectid, callback) {
|
||||
var command = path.join(getDirName(projectid), 'cordova/version');
|
||||
|
||||
|
||||
cp.exec(command, function (error, stdout, stderr) {
|
||||
if (error) {
|
||||
console.log(stdout);
|
||||
@ -146,6 +146,6 @@ module.exports.getPlatformVersion = function (projectid, callback) {
|
||||
});
|
||||
};
|
||||
|
||||
function getDirName(projectid) {
|
||||
function getDirName (projectid) {
|
||||
return 'test-' + projectid;
|
||||
}
|
||||
|
@ -17,14 +17,14 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var path = require('path'),
|
||||
actions = require('./helpers/projectActions.js');
|
||||
var path = require('path');
|
||||
var actions = require('./helpers/projectActions.js');
|
||||
|
||||
var PLUGIN_ADD_TIMEOUT = 90000;
|
||||
|
||||
describe('plugin add', function() {
|
||||
describe('plugin add', function () {
|
||||
|
||||
it('Test#001 : create project and add a plugin with framework', function(done) {
|
||||
it('Test#001 : create project and add a plugin with framework', function (done) {
|
||||
var projectname = 'testpluginframework';
|
||||
var projectid = 'com.test.plugin.framework';
|
||||
var fakePluginPath = path.join(__dirname, 'fixtures/cordova-plugin-fake');
|
||||
|
@ -17,22 +17,22 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var actions = require('./helpers/projectActions.js'),
|
||||
shell = require('shelljs'),
|
||||
fs = require('fs'),
|
||||
util = require('util'),
|
||||
platformOld = { version: '4.0.0', path: 'cordova-android-old' },
|
||||
platformEdge = { version: getCurrentVersion(), path: '.' };
|
||||
var actions = require('./helpers/projectActions.js');
|
||||
var shell = require('shelljs');
|
||||
var fs = require('fs');
|
||||
var util = require('util');
|
||||
var platformOld = { version: '4.0.0', path: 'cordova-android-old' };
|
||||
var platformEdge = { version: getCurrentVersion(), path: '.' };
|
||||
|
||||
var DOWNLOAD_TIMEOUT = 2 * 60 * 1000,
|
||||
UPDATE_TIMEOUT = 90 * 1000,
|
||||
PLATFORM_GIT_URL = 'https://github.com/apache/cordova-android';
|
||||
var DOWNLOAD_TIMEOUT = 2 * 60 * 1000;
|
||||
var UPDATE_TIMEOUT = 90 * 1000;
|
||||
var PLATFORM_GIT_URL = 'https://github.com/apache/cordova-android';
|
||||
|
||||
function getCurrentVersion() {
|
||||
function getCurrentVersion () {
|
||||
return fs.readFileSync('VERSION').toString().trim();
|
||||
}
|
||||
|
||||
function testUpdate(projectname, projectid, createfrom, updatefrom, doBuild, done) {
|
||||
function testUpdate (projectname, projectid, createfrom, updatefrom, doBuild, done) {
|
||||
actions.createProject(projectname, projectid, createfrom.path, function (error) {
|
||||
expect(error).toBe(null);
|
||||
actions.updateProject(projectid, updatefrom.path, function (error) {
|
||||
@ -68,9 +68,9 @@ describe('preparing fixtures', function () {
|
||||
|
||||
});
|
||||
|
||||
describe('update', function() {
|
||||
describe('update', function () {
|
||||
|
||||
it('Test#002 : should update major version and build the project', function(done) {
|
||||
it('Test#002 : should update major version and build the project', function (done) {
|
||||
var projectname = 'testupdate';
|
||||
var projectid = 'com.test.update.app1';
|
||||
|
||||
@ -82,7 +82,7 @@ describe('update', function() {
|
||||
|
||||
describe('cleanup', function () {
|
||||
|
||||
it('Test#004 : remove cloned old platform', function() {
|
||||
it('Test#004 : remove cloned old platform', function () {
|
||||
shell.rm('-rf', platformOld.path);
|
||||
});
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
./org.test.plugins.dummyplugin/www/dummyplugin.js
|
@ -21,9 +21,9 @@ var path = require('path');
|
||||
var AndroidProject = require('../../bin/templates/cordova/lib/AndroidProject');
|
||||
var android_project = path.join(__dirname, '../fixtures/android_project');
|
||||
|
||||
describe('AndroidProject class', function() {
|
||||
describe('getPackageName method', function() {
|
||||
it('Test#001 : should return an android project\'s proper package name', function() {
|
||||
describe('AndroidProject class', function () {
|
||||
describe('getPackageName method', function () {
|
||||
it('Test#001 : should return an android project\'s proper package name', function () {
|
||||
expect(AndroidProject.getProjectFile(android_project).getPackageName())
|
||||
.toEqual('com.alunny.childapp');
|
||||
});
|
||||
|
@ -2,16 +2,15 @@
|
||||
var path = require('path');
|
||||
var AndroidStudio = require('../../bin/templates/cordova/lib/AndroidStudio');
|
||||
|
||||
|
||||
describe('AndroidStudio module', function () {
|
||||
it('should return true for Android Studio project', function() {
|
||||
var root = path.join(__dirname,'../fixtures/android_studio_project/');
|
||||
var isAndStud = AndroidStudio.isAndroidStudioProject(root);
|
||||
expect(isAndStud).toBe(true);
|
||||
it('should return true for Android Studio project', function () {
|
||||
var root = path.join(__dirname, '../fixtures/android_studio_project/');
|
||||
var isAndStud = AndroidStudio.isAndroidStudioProject(root);
|
||||
expect(isAndStud).toBe(true);
|
||||
});
|
||||
it('should return false non Android Studio project', function() {
|
||||
var root = path.join(__dirname,'../fixtures/android_project/');
|
||||
var isAndStud = AndroidStudio.isAndroidStudioProject(root);
|
||||
expect(isAndStud).toBe(false);
|
||||
it('should return false non Android Studio project', function () {
|
||||
var root = path.join(__dirname, '../fixtures/android_project/');
|
||||
var isAndStud = AndroidStudio.isAndroidStudioProject(root);
|
||||
expect(isAndStud).toBe(false);
|
||||
});
|
||||
});
|
||||
|
@ -17,8 +17,6 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
/* jshint node:true */
|
||||
|
||||
var Q = require('q');
|
||||
var os = require('os');
|
||||
var path = require('path');
|
||||
@ -37,7 +35,7 @@ describe('addPlugin method', function () {
|
||||
var api, fail, gradleBuilder, oldClean;
|
||||
var Api = rewire('../../bin/templates/cordova/Api');
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(function () {
|
||||
var pluginManager = jasmine.createSpyObj('pluginManager', ['addPlugin']);
|
||||
pluginManager.addPlugin.and.returnValue(Q());
|
||||
spyOn(common.PluginManager, 'get').and.returnValue(pluginManager);
|
||||
@ -58,20 +56,16 @@ describe('addPlugin method', function () {
|
||||
Api.__set__('Api.prototype.clean', oldClean);
|
||||
});
|
||||
|
||||
it('Test#001 : should call gradleBuilder.prepBuildFiles for every plugin with frameworks', function(done) {
|
||||
api.addPlugin(new PluginInfo(path.join(FIXTURES, 'cordova-plugin-fake')))
|
||||
.catch(fail)
|
||||
.fin(function () {
|
||||
it('Test#001 : should call gradleBuilder.prepBuildFiles for every plugin with frameworks', function (done) {
|
||||
api.addPlugin(new PluginInfo(path.join(FIXTURES, 'cordova-plugin-fake'))).catch(fail).fin(function () {
|
||||
expect(fail).not.toHaveBeenCalled();
|
||||
expect(gradleBuilder.prepBuildFiles).toHaveBeenCalled();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Test#002 : shouldn\'t trigger gradleBuilder.prepBuildFiles for plugins without android frameworks', function(done) {
|
||||
api.addPlugin(new PluginInfo(path.join(FIXTURES, 'cordova-plugin-fake-ios-frameworks')))
|
||||
.catch(fail)
|
||||
.fin(function () {
|
||||
it('Test#002 : shouldn\'t trigger gradleBuilder.prepBuildFiles for plugins without android frameworks', function (done) {
|
||||
api.addPlugin(new PluginInfo(path.join(FIXTURES, 'cordova-plugin-fake-ios-frameworks'))).catch(fail).fin(function () {
|
||||
expect(fail).not.toHaveBeenCalled();
|
||||
expect(gradleBuilder.prepBuildFiles).not.toHaveBeenCalled();
|
||||
done();
|
||||
|
@ -16,115 +16,107 @@
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
/* jshint laxcomma:true */
|
||||
|
||||
var android_sdk = require("../../bin/templates/cordova/lib/android_sdk");
|
||||
var superspawn = require("cordova-common").superspawn;
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
var Q = require("q");
|
||||
var android_sdk = require('../../bin/templates/cordova/lib/android_sdk');
|
||||
var superspawn = require('cordova-common').superspawn;
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var Q = require('q');
|
||||
|
||||
describe("android_sdk", function () {
|
||||
describe("list_targets_with_android", function() {
|
||||
it("should invoke `android` with the `list target` command and _not_ the `list targets` command, as the plural form is not supported in some Android SDK Tools versions", function() {
|
||||
describe('android_sdk', function () {
|
||||
describe('list_targets_with_android', function () {
|
||||
it('should invoke `android` with the `list target` command and _not_ the `list targets` command, as the plural form is not supported in some Android SDK Tools versions', function () {
|
||||
var deferred = Q.defer();
|
||||
spyOn(superspawn, "spawn").and.returnValue(deferred.promise);
|
||||
spyOn(superspawn, 'spawn').and.returnValue(deferred.promise);
|
||||
android_sdk.list_targets_with_android();
|
||||
expect(superspawn.spawn).toHaveBeenCalledWith("android", ["list", "target"]);
|
||||
expect(superspawn.spawn).toHaveBeenCalledWith('android', ['list', 'target']);
|
||||
});
|
||||
it("should parse and return results from `android list targets` command", function(done) {
|
||||
it('should parse and return results from `android list targets` command', function (done) {
|
||||
var deferred = Q.defer();
|
||||
spyOn(superspawn, "spawn").and.returnValue(deferred.promise);
|
||||
deferred.resolve(fs.readFileSync(path.join("spec", "fixtures", "sdk25.2-android_list_targets.txt"), "utf-8"));
|
||||
return android_sdk.list_targets_with_android()
|
||||
.then(function(list) {
|
||||
[ "Google Inc.:Google APIs:23",
|
||||
"Google Inc.:Google APIs:22",
|
||||
"Google Inc.:Google APIs:21",
|
||||
"android-25",
|
||||
"android-24",
|
||||
"android-N",
|
||||
"android-23",
|
||||
"android-MNC",
|
||||
"android-22",
|
||||
"android-21",
|
||||
"android-20" ].forEach(function(target) {
|
||||
expect(list).toContain(target);
|
||||
});
|
||||
}).fail(function(err) {
|
||||
spyOn(superspawn, 'spawn').and.returnValue(deferred.promise);
|
||||
deferred.resolve(fs.readFileSync(path.join('spec', 'fixtures', 'sdk25.2-android_list_targets.txt'), 'utf-8'));
|
||||
return android_sdk.list_targets_with_android().then(function (list) {
|
||||
[ 'Google Inc.:Google APIs:23',
|
||||
'Google Inc.:Google APIs:22',
|
||||
'Google Inc.:Google APIs:21',
|
||||
'android-25',
|
||||
'android-24',
|
||||
'android-N',
|
||||
'android-23',
|
||||
'android-MNC',
|
||||
'android-22',
|
||||
'android-21',
|
||||
'android-20' ].forEach(function (target) { expect(list).toContain(target); });
|
||||
}).fail(function (err) {
|
||||
console.log(err);
|
||||
expect(err).toBeUndefined();
|
||||
}).fin(function() {
|
||||
}).fin(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
describe("list_targets_with_avdmanager", function() {
|
||||
it("should parse and return results from `avdmanager list target` command", function(done) {
|
||||
describe('list_targets_with_avdmanager', function () {
|
||||
it('should parse and return results from `avdmanager list target` command', function (done) {
|
||||
var deferred = Q.defer();
|
||||
spyOn(superspawn, "spawn").and.returnValue(deferred.promise);
|
||||
deferred.resolve(fs.readFileSync(path.join("spec", "fixtures", "sdk25.3-avdmanager_list_target.txt"), "utf-8"));
|
||||
return android_sdk.list_targets_with_avdmanager()
|
||||
.then(function(list) {
|
||||
expect(list).toContain("android-25");
|
||||
}).fail(function(err) {
|
||||
spyOn(superspawn, 'spawn').and.returnValue(deferred.promise);
|
||||
deferred.resolve(fs.readFileSync(path.join('spec', 'fixtures', 'sdk25.3-avdmanager_list_target.txt'), 'utf-8'));
|
||||
return android_sdk.list_targets_with_avdmanager().then(function (list) {
|
||||
expect(list).toContain('android-25');
|
||||
}).fail(function (err) {
|
||||
console.log(err);
|
||||
expect(err).toBeUndefined();
|
||||
}).fin(function() {
|
||||
}).fin(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
describe("list_targets", function() {
|
||||
it("should parse Android SDK installed target information with `avdmanager` command first", function() {
|
||||
describe('list_targets', function () {
|
||||
it('should parse Android SDK installed target information with `avdmanager` command first', function () {
|
||||
var deferred = Q.defer();
|
||||
var avdmanager_spy = spyOn(android_sdk, "list_targets_with_avdmanager").and.returnValue(deferred.promise);
|
||||
var avdmanager_spy = spyOn(android_sdk, 'list_targets_with_avdmanager').and.returnValue(deferred.promise);
|
||||
android_sdk.list_targets();
|
||||
expect(avdmanager_spy).toHaveBeenCalled();
|
||||
});
|
||||
it("should parse Android SDK installed target information with `android` command if list_targets_with_avdmanager fails with ENOENT", function(done) {
|
||||
it('should parse Android SDK installed target information with `android` command if list_targets_with_avdmanager fails with ENOENT', function (done) {
|
||||
var deferred = Q.defer();
|
||||
spyOn(android_sdk, "list_targets_with_avdmanager").and.returnValue(deferred.promise);
|
||||
spyOn(android_sdk, 'list_targets_with_avdmanager').and.returnValue(deferred.promise);
|
||||
deferred.reject({
|
||||
code: "ENOENT"
|
||||
code: 'ENOENT'
|
||||
});
|
||||
var twoferred = Q.defer();
|
||||
twoferred.resolve(["target1"]);
|
||||
var avdmanager_spy = spyOn(android_sdk, "list_targets_with_android").and.returnValue(twoferred.promise);
|
||||
return android_sdk.list_targets()
|
||||
.then(function(targets) {
|
||||
twoferred.resolve(['target1']);
|
||||
var avdmanager_spy = spyOn(android_sdk, 'list_targets_with_android').and.returnValue(twoferred.promise);
|
||||
return android_sdk.list_targets().then(function (targets) {
|
||||
expect(avdmanager_spy).toHaveBeenCalled();
|
||||
expect(targets[0]).toEqual("target1");
|
||||
expect(targets[0]).toEqual('target1');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("should parse Android SDK installed target information with `android` command if list_targets_with_avdmanager fails with not-recognized error (Windows)", function(done) {
|
||||
it('should parse Android SDK installed target information with `android` command if list_targets_with_avdmanager fails with not-recognized error (Windows)', function (done) {
|
||||
var deferred = Q.defer();
|
||||
spyOn(android_sdk, "list_targets_with_avdmanager").and.returnValue(deferred.promise);
|
||||
spyOn(android_sdk, 'list_targets_with_avdmanager').and.returnValue(deferred.promise);
|
||||
deferred.reject({
|
||||
code: 1,
|
||||
stderr: "'avdmanager' is not recognized as an internal or external commmand,\r\noperable program or batch file.\r\n"
|
||||
});
|
||||
var twoferred = Q.defer();
|
||||
twoferred.resolve(["target1"]);
|
||||
var avdmanager_spy = spyOn(android_sdk, "list_targets_with_android").and.returnValue(twoferred.promise);
|
||||
return android_sdk.list_targets()
|
||||
.then(function(targets) {
|
||||
twoferred.resolve(['target1']);
|
||||
var avdmanager_spy = spyOn(android_sdk, 'list_targets_with_android').and.returnValue(twoferred.promise);
|
||||
return android_sdk.list_targets().then(function (targets) {
|
||||
expect(avdmanager_spy).toHaveBeenCalled();
|
||||
expect(targets[0]).toEqual("target1");
|
||||
expect(targets[0]).toEqual('target1');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("should throw an error if no Android targets were found.", function(done) {
|
||||
it('should throw an error if no Android targets were found.', function (done) {
|
||||
var deferred = Q.defer();
|
||||
spyOn(android_sdk, "list_targets_with_avdmanager").and.returnValue(deferred.promise);
|
||||
spyOn(android_sdk, 'list_targets_with_avdmanager').and.returnValue(deferred.promise);
|
||||
deferred.resolve([]);
|
||||
return android_sdk.list_targets()
|
||||
.then(function(targets) {
|
||||
return android_sdk.list_targets().then(function (targets) {
|
||||
done.fail();
|
||||
}).catch(function(err) {
|
||||
}).catch(function (err) {
|
||||
expect(err).toBeDefined();
|
||||
expect(err.message).toContain("No android targets (SDKs) installed!");
|
||||
expect(err.message).toContain('No android targets (SDKs) installed!');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -1,22 +1,23 @@
|
||||
var gradle_builder = require('../../../bin/templates/cordova/lib/builders/GradleBuilder.js');
|
||||
|
||||
var Gradle_builder = require('../../../bin/templates/cordova/lib/builders/GradleBuilder.js');
|
||||
var fs = require('fs');
|
||||
var superspawn = require('cordova-common').superspawn;
|
||||
var builder;
|
||||
|
||||
describe('Gradle Builder', function() {
|
||||
beforeEach(function() {
|
||||
describe('Gradle Builder', function () {
|
||||
beforeEach(function () {
|
||||
spyOn(fs, 'existsSync').and.returnValue(true);
|
||||
builder = new gradle_builder('/root');
|
||||
builder = new Gradle_builder('/root');
|
||||
spyOn(superspawn, 'spawn');
|
||||
});
|
||||
|
||||
describe('runGradleWrapper method', function() {
|
||||
it('should run the provided gradle command if a gradle wrapper does not already exist', function() {
|
||||
describe('runGradleWrapper method', function () {
|
||||
it('should run the provided gradle command if a gradle wrapper does not already exist', function () {
|
||||
fs.existsSync.and.returnValue(false);
|
||||
builder.runGradleWrapper('/my/sweet/gradle');
|
||||
expect(superspawn.spawn).toHaveBeenCalledWith('/my/sweet/gradle', jasmine.any(Array), jasmine.any(Object));
|
||||
});
|
||||
it('should do nothing if a gradle wrapper exists in the project directory', function() {
|
||||
it('should do nothing if a gradle wrapper exists in the project directory', function () {
|
||||
fs.existsSync.and.returnValue(true);
|
||||
builder.runGradleWrapper('/my/sweet/gradle');
|
||||
expect(superspawn.spawn).not.toHaveBeenCalledWith('/my/sweet/gradle', jasmine.any(Array), jasmine.any(Object));
|
||||
|
@ -16,234 +16,222 @@
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
/* jshint laxcomma:true */
|
||||
|
||||
var check_reqs = require("../../bin/templates/cordova/lib/check_reqs");
|
||||
var android_sdk = require("../../bin/templates/cordova/lib/android_sdk");
|
||||
var shelljs = require("shelljs");
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
var Q = require("q");
|
||||
var check_reqs = require('../../bin/templates/cordova/lib/check_reqs');
|
||||
var android_sdk = require('../../bin/templates/cordova/lib/android_sdk');
|
||||
var shelljs = require('shelljs');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var Q = require('q');
|
||||
|
||||
describe("check_reqs", function () {
|
||||
describe('check_reqs', function () {
|
||||
var original_env;
|
||||
beforeAll(function() {
|
||||
beforeAll(function () {
|
||||
original_env = Object.create(process.env);
|
||||
});
|
||||
afterEach(function() {
|
||||
Object.keys(original_env).forEach(function(k) {
|
||||
afterEach(function () {
|
||||
Object.keys(original_env).forEach(function (k) {
|
||||
process.env[k] = original_env[k];
|
||||
});
|
||||
});
|
||||
describe("check_android", function() {
|
||||
describe("set ANDROID_HOME if not set", function() {
|
||||
beforeEach(function() {
|
||||
describe('check_android', function () {
|
||||
describe('set ANDROID_HOME if not set', function () {
|
||||
beforeEach(function () {
|
||||
delete process.env.ANDROID_HOME;
|
||||
});
|
||||
describe("even if no Android binaries are on the PATH", function() {
|
||||
beforeEach(function() {
|
||||
spyOn(shelljs, "which").and.returnValue(null);
|
||||
spyOn(fs, "existsSync").and.returnValue(true);
|
||||
describe('even if no Android binaries are on the PATH', function () {
|
||||
beforeEach(function () {
|
||||
spyOn(shelljs, 'which').and.returnValue(null);
|
||||
spyOn(fs, 'existsSync').and.returnValue(true);
|
||||
});
|
||||
it("it should set ANDROID_HOME on Windows", function(done) {
|
||||
spyOn(check_reqs, "isWindows").and.returnValue(true);
|
||||
process.env.LOCALAPPDATA = "windows-local-app-data";
|
||||
process.env.ProgramFiles = "windows-program-files";
|
||||
return check_reqs.check_android()
|
||||
.then(function() {
|
||||
expect(process.env.ANDROID_HOME).toContain("windows-local-app-data");
|
||||
}).fail(function(err) {
|
||||
it('it should set ANDROID_HOME on Windows', function (done) {
|
||||
spyOn(check_reqs, 'isWindows').and.returnValue(true);
|
||||
process.env.LOCALAPPDATA = 'windows-local-app-data';
|
||||
process.env.ProgramFiles = 'windows-program-files';
|
||||
return check_reqs.check_android().then(function () {
|
||||
expect(process.env.ANDROID_HOME).toContain('windows-local-app-data');
|
||||
}).fail(function (err) {
|
||||
expect(err).toBeUndefined();
|
||||
console.log(err);
|
||||
}).fin(function() {
|
||||
}).fin(function () {
|
||||
delete process.env.LOCALAPPDATA;
|
||||
delete process.env.ProgramFiles;
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("it should set ANDROID_HOME on Darwin", function(done) {
|
||||
spyOn(check_reqs, "isWindows").and.returnValue(false);
|
||||
spyOn(check_reqs, "isDarwin").and.returnValue(true);
|
||||
process.env.HOME = "home is where the heart is";
|
||||
return check_reqs.check_android()
|
||||
.then(function() {
|
||||
expect(process.env.ANDROID_HOME).toContain("home is where the heart is");
|
||||
}).fail(function(err) {
|
||||
it('it should set ANDROID_HOME on Darwin', function (done) {
|
||||
spyOn(check_reqs, 'isWindows').and.returnValue(false);
|
||||
spyOn(check_reqs, 'isDarwin').and.returnValue(true);
|
||||
process.env.HOME = 'home is where the heart is';
|
||||
return check_reqs.check_android().then(function () {
|
||||
expect(process.env.ANDROID_HOME).toContain('home is where the heart is');
|
||||
}).fail(function (err) {
|
||||
expect(err).toBeUndefined();
|
||||
console.log(err);
|
||||
}).fin(function() {
|
||||
}).fin(function () {
|
||||
delete process.env.HOME;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
describe("if some Android tooling exists on the PATH", function() {
|
||||
beforeEach(function() {
|
||||
spyOn(fs, "realpathSync").and.callFake(function(path) {
|
||||
describe('if some Android tooling exists on the PATH', function () {
|
||||
beforeEach(function () {
|
||||
spyOn(fs, 'realpathSync').and.callFake(function (path) {
|
||||
return path;
|
||||
});
|
||||
});
|
||||
it("should set ANDROID_HOME based on `android` command if command exists in a SDK-like directory structure", function(done) {
|
||||
spyOn(fs, "existsSync").and.returnValue(true);
|
||||
spyOn(shelljs, "which").and.callFake(function(cmd) {
|
||||
if (cmd == "android") {
|
||||
return "/android/sdk/tools/android";
|
||||
it('should set ANDROID_HOME based on `android` command if command exists in a SDK-like directory structure', function (done) {
|
||||
spyOn(fs, 'existsSync').and.returnValue(true);
|
||||
spyOn(shelljs, 'which').and.callFake(function (cmd) {
|
||||
if (cmd === 'android') {
|
||||
return '/android/sdk/tools/android';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
return check_reqs.check_android()
|
||||
.then(function() {
|
||||
expect(process.env.ANDROID_HOME).toEqual("/android/sdk");
|
||||
return check_reqs.check_android().then(function () {
|
||||
expect(process.env.ANDROID_HOME).toEqual('/android/sdk');
|
||||
done();
|
||||
}).fail(function(err) {
|
||||
}).fail(function (err) {
|
||||
expect(err).toBeUndefined();
|
||||
console.log(err);
|
||||
});
|
||||
});
|
||||
it("should error out if `android` command exists in a non-SDK-like directory structure", function(done) {
|
||||
spyOn(shelljs, "which").and.callFake(function(cmd) {
|
||||
if (cmd == "android") {
|
||||
return "/just/some/random/path/android";
|
||||
it('should error out if `android` command exists in a non-SDK-like directory structure', function (done) {
|
||||
spyOn(shelljs, 'which').and.callFake(function (cmd) {
|
||||
if (cmd === 'android') {
|
||||
return '/just/some/random/path/android';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
return check_reqs.check_android()
|
||||
.then(function() {
|
||||
return check_reqs.check_android().then(function () {
|
||||
done.fail();
|
||||
}).fail(function(err) {
|
||||
}).fail(function (err) {
|
||||
expect(err).toBeDefined();
|
||||
expect(err.message).toContain("update your PATH to include valid path");
|
||||
expect(err.message).toContain('update your PATH to include valid path');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("should set ANDROID_HOME based on `adb` command if command exists in a SDK-like directory structure", function(done) {
|
||||
spyOn(fs, "existsSync").and.returnValue(true);
|
||||
spyOn(shelljs, "which").and.callFake(function(cmd) {
|
||||
if (cmd == "adb") {
|
||||
return "/android/sdk/platform-tools/adb";
|
||||
it('should set ANDROID_HOME based on `adb` command if command exists in a SDK-like directory structure', function (done) {
|
||||
spyOn(fs, 'existsSync').and.returnValue(true);
|
||||
spyOn(shelljs, 'which').and.callFake(function (cmd) {
|
||||
if (cmd === 'adb') {
|
||||
return '/android/sdk/platform-tools/adb';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
return check_reqs.check_android()
|
||||
.then(function() {
|
||||
expect(process.env.ANDROID_HOME).toEqual("/android/sdk");
|
||||
return check_reqs.check_android().then(function () {
|
||||
expect(process.env.ANDROID_HOME).toEqual('/android/sdk');
|
||||
done();
|
||||
}).fail(function(err) {
|
||||
}).fail(function (err) {
|
||||
expect(err).toBeUndefined();
|
||||
console.log(err);
|
||||
});
|
||||
});
|
||||
it("should error out if `adb` command exists in a non-SDK-like directory structure", function(done) {
|
||||
spyOn(shelljs, "which").and.callFake(function(cmd) {
|
||||
if (cmd == "adb") {
|
||||
return "/just/some/random/path/adb";
|
||||
it('should error out if `adb` command exists in a non-SDK-like directory structure', function (done) {
|
||||
spyOn(shelljs, 'which').and.callFake(function (cmd) {
|
||||
if (cmd === 'adb') {
|
||||
return '/just/some/random/path/adb';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
return check_reqs.check_android()
|
||||
.then(function() {
|
||||
return check_reqs.check_android().then(function () {
|
||||
done.fail();
|
||||
}).fail(function(err) {
|
||||
}).fail(function (err) {
|
||||
expect(err).toBeDefined();
|
||||
expect(err.message).toContain("update your PATH to include valid path");
|
||||
expect(err.message).toContain('update your PATH to include valid path');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("should set ANDROID_HOME based on `avdmanager` command if command exists in a SDK-like directory structure", function(done) {
|
||||
spyOn(fs, "existsSync").and.returnValue(true);
|
||||
spyOn(shelljs, "which").and.callFake(function(cmd) {
|
||||
if (cmd == "avdmanager") {
|
||||
return "/android/sdk/tools/bin/avdmanager";
|
||||
it('should set ANDROID_HOME based on `avdmanager` command if command exists in a SDK-like directory structure', function (done) {
|
||||
spyOn(fs, 'existsSync').and.returnValue(true);
|
||||
spyOn(shelljs, 'which').and.callFake(function (cmd) {
|
||||
if (cmd === 'avdmanager') {
|
||||
return '/android/sdk/tools/bin/avdmanager';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
return check_reqs.check_android()
|
||||
.then(function() {
|
||||
expect(process.env.ANDROID_HOME).toEqual("/android/sdk");
|
||||
return check_reqs.check_android().then(function () {
|
||||
expect(process.env.ANDROID_HOME).toEqual('/android/sdk');
|
||||
done();
|
||||
}).fail(function(err) {
|
||||
}).fail(function (err) {
|
||||
expect(err).toBeUndefined();
|
||||
console.log(err);
|
||||
});
|
||||
});
|
||||
it("should error out if `avdmanager` command exists in a non-SDK-like directory structure", function(done) {
|
||||
spyOn(shelljs, "which").and.callFake(function(cmd) {
|
||||
if (cmd == "avdmanager") {
|
||||
return "/just/some/random/path/avdmanager";
|
||||
it('should error out if `avdmanager` command exists in a non-SDK-like directory structure', function (done) {
|
||||
spyOn(shelljs, 'which').and.callFake(function (cmd) {
|
||||
if (cmd === 'avdmanager') {
|
||||
return '/just/some/random/path/avdmanager';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
return check_reqs.check_android()
|
||||
.then(function() {
|
||||
return check_reqs.check_android().then(function () {
|
||||
done.fail();
|
||||
}).fail(function(err) {
|
||||
}).fail(function (err) {
|
||||
expect(err).toBeDefined();
|
||||
expect(err.message).toContain("update your PATH to include valid path");
|
||||
expect(err.message).toContain('update your PATH to include valid path');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
describe("set PATH for various Android binaries if not available", function() {
|
||||
beforeEach(function() {
|
||||
spyOn(shelljs, "which").and.returnValue(null);
|
||||
process.env.ANDROID_HOME = "let the children play";
|
||||
spyOn(fs, "existsSync").and.returnValue(true);
|
||||
describe('set PATH for various Android binaries if not available', function () {
|
||||
beforeEach(function () {
|
||||
spyOn(shelljs, 'which').and.returnValue(null);
|
||||
process.env.ANDROID_HOME = 'let the children play';
|
||||
spyOn(fs, 'existsSync').and.returnValue(true);
|
||||
});
|
||||
afterEach(function() {
|
||||
afterEach(function () {
|
||||
delete process.env.ANDROID_HOME;
|
||||
});
|
||||
it("should add tools/bin,tools,platform-tools to PATH if `avdmanager`,`android`,`adb` is not found", function(done) {
|
||||
return check_reqs.check_android()
|
||||
.then(function() {
|
||||
expect(process.env.PATH).toContain("let the children play" + path.sep + "tools");
|
||||
expect(process.env.PATH).toContain("let the children play" + path.sep + "platform-tools");
|
||||
expect(process.env.PATH).toContain("let the children play" + path.sep + "tools" + path.sep + "bin");
|
||||
it('should add tools/bin,tools,platform-tools to PATH if `avdmanager`,`android`,`adb` is not found', function (done) {
|
||||
return check_reqs.check_android().then(function () {
|
||||
expect(process.env.PATH).toContain('let the children play' + path.sep + 'tools');
|
||||
expect(process.env.PATH).toContain('let the children play' + path.sep + 'platform-tools');
|
||||
expect(process.env.PATH).toContain('let the children play' + path.sep + 'tools' + path.sep + 'bin');
|
||||
done();
|
||||
}).fail(function(err) {
|
||||
}).fail(function (err) {
|
||||
expect(err).toBeUndefined();
|
||||
console.log(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
describe("get_target", function() {
|
||||
it("should retrieve target from framework project.properties file", function() {
|
||||
describe('get_target', function () {
|
||||
it('should retrieve target from framework project.properties file', function () {
|
||||
var target = check_reqs.get_target();
|
||||
expect(target).toBeDefined();
|
||||
expect(target).toContain("android-");
|
||||
expect(target).toContain('android-');
|
||||
});
|
||||
});
|
||||
describe("check_android_target", function() {
|
||||
it("should should return full list of supported targets if there is a match to ideal api level", function(done) {
|
||||
describe('check_android_target', function () {
|
||||
it('should should return full list of supported targets if there is a match to ideal api level', function (done) {
|
||||
var deferred = Q.defer();
|
||||
spyOn(android_sdk, "list_targets").and.returnValue(deferred.promise);
|
||||
var fake_targets = ["you are my fire", "my one desire"];
|
||||
spyOn(android_sdk, 'list_targets').and.returnValue(deferred.promise);
|
||||
var fake_targets = ['you are my fire', 'my one desire'];
|
||||
deferred.resolve(fake_targets);
|
||||
spyOn(check_reqs, "get_target").and.returnValue("you are my fire");
|
||||
return check_reqs.check_android_target()
|
||||
.then(function(targets) {
|
||||
spyOn(check_reqs, 'get_target').and.returnValue('you are my fire');
|
||||
return check_reqs.check_android_target().then(function (targets) {
|
||||
expect(targets).toBeDefined();
|
||||
expect(targets).toEqual(fake_targets);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("should error out if there is no match between ideal api level and installed targets", function(done) {
|
||||
it('should error out if there is no match between ideal api level and installed targets', function (done) {
|
||||
var deferred = Q.defer();
|
||||
spyOn(android_sdk, "list_targets").and.returnValue(deferred.promise);
|
||||
var fake_targets = ["you are my fire", "my one desire"];
|
||||
spyOn(android_sdk, 'list_targets').and.returnValue(deferred.promise);
|
||||
var fake_targets = ['you are my fire', 'my one desire'];
|
||||
deferred.resolve(fake_targets);
|
||||
spyOn(check_reqs, "get_target").and.returnValue("and i knowwwwwwwwwwww");
|
||||
return check_reqs.check_android_target()
|
||||
.catch(function(err) {
|
||||
spyOn(check_reqs, 'get_target').and.returnValue('and i knowwwwwwwwwwww');
|
||||
return check_reqs.check_android_target().catch(function (err) {
|
||||
expect(err).toBeDefined();
|
||||
expect(err.message).toContain("Please install Android target");
|
||||
expect(err.message).toContain('Please install Android target');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -16,97 +16,91 @@
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
/* jshint laxcomma:true */
|
||||
|
||||
var create = require("../../bin/lib/create");
|
||||
var create = require('../../bin/lib/create');
|
||||
|
||||
describe("create", function () {
|
||||
describe("validatePackageName", function() {
|
||||
var valid = [
|
||||
"org.apache.mobilespec"
|
||||
, "com.example"
|
||||
, "com.floors42.package"
|
||||
, "ball8.ball8.ball8ball"
|
||||
];
|
||||
var invalid = [
|
||||
""
|
||||
, "com.class.is.bad"
|
||||
, "0com.example.mobilespec"
|
||||
, "c-m.e@a!p%e.mobilespec"
|
||||
, "notenoughdots"
|
||||
, ".starts.with.a.dot"
|
||||
, "ends.with.a.dot."
|
||||
, "_underscore.anything"
|
||||
, "underscore._something"
|
||||
, "_underscore._all._the._things"
|
||||
, "8.ball"
|
||||
, "8ball.ball"
|
||||
, "ball8.8ball"
|
||||
, "ball8.com.8ball"
|
||||
];
|
||||
describe('create', function () {
|
||||
describe('validatePackageName', function () {
|
||||
var valid = [
|
||||
'org.apache.mobilespec',
|
||||
'com.example',
|
||||
'com.floors42.package',
|
||||
'ball8.ball8.ball8ball'
|
||||
];
|
||||
var invalid = [
|
||||
'',
|
||||
'com.class.is.bad',
|
||||
'0com.example.mobilespec',
|
||||
'c-m.e@a!p%e.mobilespec',
|
||||
'notenoughdots',
|
||||
'.starts.with.a.dot',
|
||||
'ends.with.a.dot.',
|
||||
'_underscore.anything',
|
||||
'underscore._something',
|
||||
'_underscore._all._the._things',
|
||||
'8.ball',
|
||||
'8ball.ball',
|
||||
'ball8.8ball',
|
||||
'ball8.com.8ball'
|
||||
];
|
||||
|
||||
valid.forEach(function(package_name) {
|
||||
it("Test#001 : should accept " + package_name, function(done) {
|
||||
return create.validatePackageName(package_name)
|
||||
.then(function() {
|
||||
//resolved
|
||||
done();
|
||||
}).fail(function(err) {
|
||||
expect(err).toBeUndefined();
|
||||
valid.forEach(function (package_name) {
|
||||
it('Test#001 : should accept ' + package_name, function (done) {
|
||||
return create.validatePackageName(package_name).then(function () {
|
||||
// resolved
|
||||
done();
|
||||
}).fail(function (err) {
|
||||
expect(err).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
invalid.forEach(function(package_name) {
|
||||
it("Test#002 : should reject " + package_name, function(done) {
|
||||
return create.validatePackageName(package_name)
|
||||
.then(function() {
|
||||
//shouldn't be here
|
||||
expect(true).toBe(false);
|
||||
}).fail(function(err) {
|
||||
expect(err).toBeDefined();
|
||||
done();
|
||||
invalid.forEach(function (package_name) {
|
||||
it('Test#002 : should reject ' + package_name, function (done) {
|
||||
return create.validatePackageName(package_name).then(function () {
|
||||
// shouldn't be here
|
||||
expect(true).toBe(false);
|
||||
}).fail(function (err) {
|
||||
expect(err).toBeDefined();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
describe("validateProjectName", function() {
|
||||
var valid = [
|
||||
"mobilespec"
|
||||
, "package_name"
|
||||
, "PackageName"
|
||||
, "CordovaLib"
|
||||
];
|
||||
var invalid = [
|
||||
""
|
||||
, "0startswithdigit"
|
||||
, "CordovaActivity"
|
||||
];
|
||||
describe('validateProjectName', function () {
|
||||
var valid = [
|
||||
'mobilespec',
|
||||
'package_name',
|
||||
'PackageName',
|
||||
'CordovaLib'
|
||||
];
|
||||
var invalid = [
|
||||
'',
|
||||
'0startswithdigit',
|
||||
'CordovaActivity'
|
||||
];
|
||||
|
||||
valid.forEach(function(project_name) {
|
||||
it("Test#003 : should accept " + project_name, function(done) {
|
||||
return create.validateProjectName(project_name)
|
||||
.then(function() {
|
||||
//resolved
|
||||
done();
|
||||
}).fail(function(err) {
|
||||
expect(err).toBeUndefined();
|
||||
valid.forEach(function (project_name) {
|
||||
it('Test#003 : should accept ' + project_name, function (done) {
|
||||
return create.validateProjectName(project_name).then(function () {
|
||||
// resolved
|
||||
done();
|
||||
}).fail(function (err) {
|
||||
expect(err).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
invalid.forEach(function(project_name) {
|
||||
it("Test#004 : should reject " + project_name, function(done) {
|
||||
return create.validateProjectName(project_name)
|
||||
.then(function() {
|
||||
//shouldn't be here
|
||||
expect(true).toBe(false);
|
||||
}).fail(function(err) {
|
||||
expect(err).toBeDefined();
|
||||
done();
|
||||
invalid.forEach(function (project_name) {
|
||||
it('Test#004 : should reject ' + project_name, function (done) {
|
||||
return create.validateProjectName(project_name).then(function () {
|
||||
// shouldn't be here
|
||||
expect(true).toBe(false);
|
||||
}).fail(function (err) {
|
||||
expect(err).toBeDefined();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -16,96 +16,94 @@
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
var emu = require("../../bin/templates/cordova/lib/emulator");
|
||||
var superspawn = require("cordova-common").superspawn;
|
||||
var Q = require("q");
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
var shelljs = require("shelljs");
|
||||
|
||||
describe("emulator", function () {
|
||||
describe("list_images_using_avdmanager", function() {
|
||||
it("should properly parse details of SDK Tools 25.3.1 `avdmanager` output", function(done) {
|
||||
var emu = require('../../bin/templates/cordova/lib/emulator');
|
||||
var superspawn = require('cordova-common').superspawn;
|
||||
var Q = require('q');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var shelljs = require('shelljs');
|
||||
|
||||
describe('emulator', function () {
|
||||
describe('list_images_using_avdmanager', function () {
|
||||
it('should properly parse details of SDK Tools 25.3.1 `avdmanager` output', function (done) {
|
||||
var deferred = Q.defer();
|
||||
spyOn(superspawn, "spawn").and.returnValue(deferred.promise);
|
||||
deferred.resolve(fs.readFileSync(path.join("spec", "fixtures", "sdk25.3-avdmanager_list_avd.txt"), "utf-8"));
|
||||
return emu.list_images_using_avdmanager()
|
||||
.then(function(list) {
|
||||
spyOn(superspawn, 'spawn').and.returnValue(deferred.promise);
|
||||
deferred.resolve(fs.readFileSync(path.join('spec', 'fixtures', 'sdk25.3-avdmanager_list_avd.txt'), 'utf-8'));
|
||||
return emu.list_images_using_avdmanager().then(function (list) {
|
||||
expect(list).toBeDefined();
|
||||
expect(list[0].name).toEqual("nexus5-5.1");
|
||||
expect(list[0].target).toEqual("Android 5.1 (API level 22)");
|
||||
expect(list[1].device).toEqual("pixel (Google)");
|
||||
expect(list[2].abi).toEqual("default/x86_64");
|
||||
}).fail(function(err) {
|
||||
expect(list[0].name).toEqual('nexus5-5.1');
|
||||
expect(list[0].target).toEqual('Android 5.1 (API level 22)');
|
||||
expect(list[1].device).toEqual('pixel (Google)');
|
||||
expect(list[2].abi).toEqual('default/x86_64');
|
||||
}).fail(function (err) {
|
||||
expect(err).toBeUndefined();
|
||||
}).fin(function() {
|
||||
}).fin(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
describe("list_images_using_android", function() {
|
||||
it("should invoke `android` with the `list avd` command and _not_ the `list avds` command, as the plural form is not supported in some Android SDK Tools versions", function() {
|
||||
describe('list_images_using_android', function () {
|
||||
it('should invoke `android` with the `list avd` command and _not_ the `list avds` command, as the plural form is not supported in some Android SDK Tools versions', function () {
|
||||
var deferred = Q.defer();
|
||||
spyOn(superspawn, "spawn").and.returnValue(deferred.promise);
|
||||
spyOn(superspawn, 'spawn').and.returnValue(deferred.promise);
|
||||
emu.list_images_using_android();
|
||||
expect(superspawn.spawn).toHaveBeenCalledWith("android", ["list", "avd"]);
|
||||
expect(superspawn.spawn).toHaveBeenCalledWith('android', ['list', 'avd']);
|
||||
});
|
||||
it("should properly parse details of SDK Tools pre-25.3.1 `android list avd` output", function(done) {
|
||||
it('should properly parse details of SDK Tools pre-25.3.1 `android list avd` output', function (done) {
|
||||
var deferred = Q.defer();
|
||||
spyOn(superspawn, "spawn").and.returnValue(deferred.promise);
|
||||
deferred.resolve(fs.readFileSync(path.join("spec", "fixtures", "sdk25.2-android_list_avd.txt"), "utf-8"));
|
||||
return emu.list_images_using_android()
|
||||
.then(function(list) {
|
||||
spyOn(superspawn, 'spawn').and.returnValue(deferred.promise);
|
||||
deferred.resolve(fs.readFileSync(path.join('spec', 'fixtures', 'sdk25.2-android_list_avd.txt'), 'utf-8'));
|
||||
return emu.list_images_using_android().then(function (list) {
|
||||
expect(list).toBeDefined();
|
||||
expect(list[0].name).toEqual("QWR");
|
||||
expect(list[0].device).toEqual("Nexus 5 (Google)");
|
||||
expect(list[0].path).toEqual("/Users/shazron/.android/avd/QWR.avd");
|
||||
expect(list[0].target).toEqual("Android 7.1.1 (API level 25)");
|
||||
expect(list[0].abi).toEqual("google_apis/x86_64");
|
||||
expect(list[0].skin).toEqual("1080x1920");
|
||||
}).fail(function(err) {
|
||||
expect(list[0].name).toEqual('QWR');
|
||||
expect(list[0].device).toEqual('Nexus 5 (Google)');
|
||||
expect(list[0].path).toEqual('/Users/shazron/.android/avd/QWR.avd');
|
||||
expect(list[0].target).toEqual('Android 7.1.1 (API level 25)');
|
||||
expect(list[0].abi).toEqual('google_apis/x86_64');
|
||||
expect(list[0].skin).toEqual('1080x1920');
|
||||
}).fail(function (err) {
|
||||
expect(err).toBeUndefined();
|
||||
}).fin(function() {
|
||||
}).fin(function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
describe("list_images", function() {
|
||||
beforeEach(function() {
|
||||
spyOn(fs, "realpathSync").and.callFake(function(cmd) {
|
||||
describe('list_images', function () {
|
||||
beforeEach(function () {
|
||||
spyOn(fs, 'realpathSync').and.callFake(function (cmd) {
|
||||
return cmd;
|
||||
});
|
||||
});
|
||||
it("should try to parse AVD information using `avdmanager` first", function() {
|
||||
spyOn(shelljs, "which").and.callFake(function(cmd) {
|
||||
if (cmd == "avdmanager") {
|
||||
it('should try to parse AVD information using `avdmanager` first', function () {
|
||||
spyOn(shelljs, 'which').and.callFake(function (cmd) {
|
||||
if (cmd === 'avdmanager') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
var avdmanager_spy = spyOn(emu, "list_images_using_avdmanager").and.returnValue({catch:function(){}});
|
||||
var avdmanager_spy = spyOn(emu, 'list_images_using_avdmanager').and.returnValue({catch: function () {}});
|
||||
emu.list_images();
|
||||
expect(avdmanager_spy).toHaveBeenCalled();
|
||||
});
|
||||
it("should delegate to `android` if `avdmanager` cant be found and `android` can", function() {
|
||||
spyOn(shelljs, "which").and.callFake(function(cmd) {
|
||||
if (cmd == "avdmanager") {
|
||||
it('should delegate to `android` if `avdmanager` cant be found and `android` can', function () {
|
||||
spyOn(shelljs, 'which').and.callFake(function (cmd) {
|
||||
if (cmd === 'avdmanager') {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
var android_spy = spyOn(emu, "list_images_using_android");
|
||||
var android_spy = spyOn(emu, 'list_images_using_android');
|
||||
emu.list_images();
|
||||
expect(android_spy).toHaveBeenCalled();
|
||||
});
|
||||
it("should throw an error if neither `avdmanager` nor `android` are able to be found", function(done) {
|
||||
spyOn(shelljs, "which").and.returnValue(false);
|
||||
return emu.list_images()
|
||||
.catch(function(err) {
|
||||
it('should throw an error if neither `avdmanager` nor `android` are able to be found', function (done) {
|
||||
spyOn(shelljs, 'which').and.returnValue(false);
|
||||
return emu.list_images().catch(function (err) {
|
||||
expect(err).toBeDefined();
|
||||
expect(err.message).toContain("Could not find either `android` or `avdmanager`");
|
||||
expect(err.message).toContain('Could not find either `android` or `avdmanager`');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -35,25 +35,25 @@ var copyFile = common.__get__('copyFile');
|
||||
var deleteJava = common.__get__('deleteJava');
|
||||
var copyNewFile = common.__get__('copyNewFile');
|
||||
|
||||
describe('common platform handler', function() {
|
||||
describe('common platform handler', function () {
|
||||
|
||||
describe('copyFile', function() {
|
||||
it('Test#001 : should throw if source path not found', function(){
|
||||
describe('copyFile', function () {
|
||||
it('Test#001 : should throw if source path not found', function () {
|
||||
shell.rm('-rf', src);
|
||||
expect(function(){copyFile(test_dir, src, project_dir, dest);})
|
||||
expect(function () { copyFile(test_dir, src, project_dir, dest); })
|
||||
.toThrow(new Error('"' + src + '" not found!'));
|
||||
});
|
||||
|
||||
it('Test#002 : should throw if src not in plugin directory', function(){
|
||||
it('Test#002 : should throw if src not in plugin directory', function () {
|
||||
shell.mkdir('-p', project_dir);
|
||||
fs.writeFileSync(non_plugin_file, 'contents', 'utf-8');
|
||||
var outside_file = '../non_plugin_file';
|
||||
expect(function(){copyFile(test_dir, outside_file, project_dir, dest);}).
|
||||
toThrow(new Error('File "' + path.resolve(test_dir, outside_file) + '" is located outside the plugin directory "' + test_dir + '"'));
|
||||
expect(function () { copyFile(test_dir, outside_file, project_dir, dest); })
|
||||
.toThrow(new Error('File "' + path.resolve(test_dir, outside_file) + '" is located outside the plugin directory "' + test_dir + '"'));
|
||||
shell.rm('-rf', test_dir);
|
||||
});
|
||||
|
||||
it('Test#003 : should allow symlink src, if inside plugin', function(){
|
||||
it('Test#003 : should allow symlink src, if inside plugin', function () {
|
||||
shell.mkdir('-p', java_dir);
|
||||
fs.writeFileSync(java_file, 'contents', 'utf-8');
|
||||
|
||||
@ -66,7 +66,7 @@ describe('common platform handler', function() {
|
||||
shell.rm('-rf', project_dir);
|
||||
});
|
||||
|
||||
it('Test#004 : should throw if symlink is linked to a file outside the plugin', function(){
|
||||
it('Test#004 : should throw if symlink is linked to a file outside the plugin', function () {
|
||||
shell.mkdir('-p', java_dir);
|
||||
fs.writeFileSync(non_plugin_file, 'contents', 'utf-8');
|
||||
|
||||
@ -75,20 +75,20 @@ describe('common platform handler', function() {
|
||||
return;
|
||||
}
|
||||
|
||||
expect(function(){copyFile(test_dir, symlink_file, project_dir, dest);}).
|
||||
toThrow(new Error('File "' + path.resolve(test_dir, symlink_file) + '" is located outside the plugin directory "' + test_dir + '"'));
|
||||
expect(function () { copyFile(test_dir, symlink_file, project_dir, dest); })
|
||||
.toThrow(new Error('File "' + path.resolve(test_dir, symlink_file) + '" is located outside the plugin directory "' + test_dir + '"'));
|
||||
shell.rm('-rf', project_dir);
|
||||
});
|
||||
|
||||
it('Test#005 : should throw if dest is outside the project directory', function(){
|
||||
it('Test#005 : should throw if dest is outside the project directory', function () {
|
||||
shell.mkdir('-p', java_dir);
|
||||
fs.writeFileSync(java_file, 'contents', 'utf-8');
|
||||
expect(function(){copyFile(test_dir, java_file, project_dir, non_plugin_file);}).
|
||||
toThrow(new Error('Destination "' + path.resolve(project_dir, non_plugin_file) + '" for source file "' + path.resolve(test_dir, java_file) + '" is located outside the project'));
|
||||
expect(function () { copyFile(test_dir, java_file, project_dir, non_plugin_file); })
|
||||
.toThrow(new Error('Destination "' + path.resolve(project_dir, non_plugin_file) + '" for source file "' + path.resolve(test_dir, java_file) + '" is located outside the project'));
|
||||
shell.rm('-rf', project_dir);
|
||||
});
|
||||
|
||||
it('Test#006 : should call mkdir -p on target path', function(){
|
||||
it('Test#006 : should call mkdir -p on target path', function () {
|
||||
shell.mkdir('-p', java_dir);
|
||||
fs.writeFileSync(java_file, 'contents', 'utf-8');
|
||||
|
||||
@ -102,7 +102,7 @@ describe('common platform handler', function() {
|
||||
shell.rm('-rf', project_dir);
|
||||
});
|
||||
|
||||
it('Test#007 : should call cp source/dest paths', function(){
|
||||
it('Test#007 : should call cp source/dest paths', function () {
|
||||
shell.mkdir('-p', java_dir);
|
||||
fs.writeFileSync(java_file, 'contents', 'utf-8');
|
||||
|
||||
@ -119,46 +119,46 @@ describe('common platform handler', function() {
|
||||
});
|
||||
|
||||
describe('copyNewFile', function () {
|
||||
it('Test#008 : should throw if target path exists', function(){
|
||||
it('Test#008 : should throw if target path exists', function () {
|
||||
shell.mkdir('-p', dest);
|
||||
expect(function(){copyNewFile(test_dir, src, project_dir, dest);}).
|
||||
toThrow(new Error('"' + dest + '" already exists!'));
|
||||
expect(function () { copyNewFile(test_dir, src, project_dir, dest); })
|
||||
.toThrow(new Error('"' + dest + '" already exists!'));
|
||||
shell.rm('-rf', dest);
|
||||
});
|
||||
});
|
||||
|
||||
describe('deleteJava', function() {
|
||||
beforeEach(function() {
|
||||
describe('deleteJava', function () {
|
||||
beforeEach(function () {
|
||||
shell.mkdir('-p', java_dir);
|
||||
fs.writeFileSync(java_file, 'contents', 'utf-8');
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
afterEach(function () {
|
||||
shell.rm('-rf', java_dir);
|
||||
});
|
||||
|
||||
it('Test#009 : should call fs.unlinkSync on the provided paths', function(){
|
||||
it('Test#009 : should call fs.unlinkSync on the provided paths', function () {
|
||||
var s = spyOn(fs, 'unlinkSync').and.callThrough();
|
||||
deleteJava(project_dir, java_file);
|
||||
expect(s).toHaveBeenCalled();
|
||||
expect(s).toHaveBeenCalledWith(path.resolve(project_dir, java_file));
|
||||
});
|
||||
|
||||
it('Test#010 : should delete empty directories after removing source code in a java src path hierarchy', function(){
|
||||
it('Test#010 : should delete empty directories after removing source code in a java src path hierarchy', function () {
|
||||
deleteJava(project_dir, java_file);
|
||||
expect(fs.existsSync(java_file)).not.toBe(true);
|
||||
expect(fs.existsSync(java_dir)).not.toBe(true);
|
||||
expect(fs.existsSync(path.join(src,'one'))).not.toBe(true);
|
||||
expect(fs.existsSync(path.join(src, 'one'))).not.toBe(true);
|
||||
});
|
||||
|
||||
it('Test#011 : should never delete the top-level src directory, even if all plugins added were removed', function(){
|
||||
it('Test#011 : should never delete the top-level src directory, even if all plugins added were removed', function () {
|
||||
deleteJava(project_dir, java_file);
|
||||
expect(fs.existsSync(src)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function ignoreEPERMonWin32(symlink_src, symlink_dest) {
|
||||
function ignoreEPERMonWin32 (symlink_src, symlink_dest) {
|
||||
try {
|
||||
fs.symlinkSync(symlink_src, symlink_dest);
|
||||
} catch (e) {
|
||||
|
@ -18,13 +18,13 @@
|
||||
*/
|
||||
|
||||
var rewire = require('rewire');
|
||||
var common = rewire('../../../bin/templates/cordova/lib/pluginHandlers');
|
||||
var common = rewire('../../../bin/templates/cordova/lib/pluginHandlers');
|
||||
var android = common.__get__('handlers');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var shell = require('shelljs');
|
||||
var os = require('os');
|
||||
var temp = path.join(os.tmpdir(), 'plugman');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var shell = require('shelljs');
|
||||
var os = require('os');
|
||||
var temp = path.join(os.tmpdir(), 'plugman');
|
||||
var plugins_dir = path.join(temp, 'cordova/plugins');
|
||||
var dummyplugin = path.join(__dirname, '../../fixtures/org.test.plugins.dummyplugin');
|
||||
var faultyplugin = path.join(__dirname, '../../fixtures/org.test.plugins.faultyplugin');
|
||||
@ -34,32 +34,32 @@ var PluginInfo = require('cordova-common').PluginInfo;
|
||||
var AndroidProject = require('../../../bin/templates/cordova/lib/AndroidProject');
|
||||
|
||||
var dummyPluginInfo = new PluginInfo(dummyplugin);
|
||||
var valid_source = dummyPluginInfo.getSourceFiles('android'),
|
||||
valid_resources = dummyPluginInfo.getResourceFiles('android'),
|
||||
valid_libs = dummyPluginInfo.getLibFiles('android');
|
||||
var valid_source = dummyPluginInfo.getSourceFiles('android');
|
||||
var valid_resources = dummyPluginInfo.getResourceFiles('android');
|
||||
var valid_libs = dummyPluginInfo.getLibFiles('android');
|
||||
|
||||
var faultyPluginInfo = new PluginInfo(faultyplugin);
|
||||
var invalid_source = faultyPluginInfo.getSourceFiles('android');
|
||||
|
||||
describe('android project handler', function() {
|
||||
describe('installation', function() {
|
||||
describe('android project handler', function () {
|
||||
describe('installation', function () {
|
||||
var copyFileOrig = common.__get__('copyFile');
|
||||
var copyFileSpy = jasmine.createSpy('copyFile');
|
||||
var dummyProject;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(function () {
|
||||
shell.mkdir('-p', temp);
|
||||
dummyProject = AndroidProject.getProjectFile(temp);
|
||||
copyFileSpy.calls.reset();
|
||||
common.__set__('copyFile', copyFileSpy);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
afterEach(function () {
|
||||
shell.rm('-rf', temp);
|
||||
common.__set__('copyFile', copyFileOrig);
|
||||
});
|
||||
|
||||
describe('of <lib-file> elements', function() {
|
||||
describe('of <lib-file> elements', function () {
|
||||
it('Test#001 : should copy files', function () {
|
||||
android['lib-file'].install(valid_libs[0], dummyPluginInfo, dummyProject);
|
||||
expect(copyFileSpy).toHaveBeenCalledWith(dummyplugin, 'src/android/TestLib.jar', temp, path.join('libs', 'TestLib.jar'), false);
|
||||
@ -70,58 +70,58 @@ describe('android project handler', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('of <resource-file> elements', function() {
|
||||
describe('of <resource-file> elements', function () {
|
||||
it('Test#003 : should copy files', function () {
|
||||
android['resource-file'].install(valid_resources[0], dummyPluginInfo, dummyProject);
|
||||
expect(copyFileSpy).toHaveBeenCalledWith(dummyplugin, 'android-resource.xml', temp, path.join('res', 'xml', 'dummy.xml'), false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('of <source-file> elements', function() {
|
||||
beforeEach(function() {
|
||||
describe('of <source-file> elements', function () {
|
||||
beforeEach(function () {
|
||||
shell.cp('-rf', android_project, temp);
|
||||
});
|
||||
|
||||
it('Test#004 : should copy stuff from one location to another by calling common.copyFile', function() {
|
||||
it('Test#004 : should copy stuff from one location to another by calling common.copyFile', function () {
|
||||
android['source-file'].install(valid_source[0], dummyPluginInfo, dummyProject);
|
||||
expect(copyFileSpy)
|
||||
.toHaveBeenCalledWith(dummyplugin, 'src/android/DummyPlugin.java', temp, path.join('src/com/phonegap/plugins/dummyplugin/DummyPlugin.java'), false);
|
||||
});
|
||||
|
||||
it('Test#005 : should install source files to the right location for Android Studio projects', function() {
|
||||
it('Test#005 : should install source files to the right location for Android Studio projects', function () {
|
||||
android['source-file'].install(valid_source[0], dummyPluginInfo, dummyProject, {android_studio: true});
|
||||
expect(copyFileSpy)
|
||||
.toHaveBeenCalledWith(dummyplugin, 'src/android/DummyPlugin.java', temp, path.join('app/src/main/java/com/phonegap/plugins/dummyplugin/DummyPlugin.java'), false);
|
||||
});
|
||||
|
||||
it('Test#006 : should throw if source file cannot be found', function() {
|
||||
it('Test#006 : should throw if source file cannot be found', function () {
|
||||
common.__set__('copyFile', copyFileOrig);
|
||||
expect(function() {
|
||||
expect(function () {
|
||||
android['source-file'].install(invalid_source[0], faultyPluginInfo, dummyProject);
|
||||
}).toThrow(new Error('"' + path.resolve(faultyplugin, 'src/android/NotHere.java') + '" not found!'));
|
||||
});
|
||||
|
||||
it('Test#007 : should throw if target file already exists', function() {
|
||||
it('Test#007 : should throw if target file already exists', function () {
|
||||
// write out a file
|
||||
var target = path.resolve(temp, 'src/com/phonegap/plugins/dummyplugin');
|
||||
shell.mkdir('-p', target);
|
||||
target = path.join(target, 'DummyPlugin.java');
|
||||
fs.writeFileSync(target, 'some bs', 'utf-8');
|
||||
|
||||
expect(function() {
|
||||
expect(function () {
|
||||
android['source-file'].install(valid_source[0], dummyPluginInfo, dummyProject);
|
||||
}).toThrow(new Error ('"' + target + '" already exists!'));
|
||||
}).toThrow(new Error('"' + target + '" already exists!'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('of <framework> elements', function() {
|
||||
describe('of <framework> elements', function () {
|
||||
|
||||
var someString = jasmine.any(String);
|
||||
|
||||
var copyNewFileOrig = common.__get__('copyNewFile');
|
||||
var copyNewFileSpy = jasmine.createSpy('copyNewFile');
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(function () {
|
||||
shell.cp('-rf', android_project, temp);
|
||||
|
||||
spyOn(dummyProject, 'addSystemLibrary');
|
||||
@ -130,27 +130,27 @@ describe('android project handler', function() {
|
||||
common.__set__('copyNewFile', copyNewFileSpy);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
afterEach(function () {
|
||||
common.__set__('copyNewFile', copyNewFileOrig);
|
||||
});
|
||||
|
||||
it('Test#008 : should throw if framework doesn\'t have "src" attribute', function() {
|
||||
expect(function() { android.framework.install({}, dummyPluginInfo, dummyProject); }).toThrow();
|
||||
it('Test#008 : should throw if framework doesn\'t have "src" attribute', function () {
|
||||
expect(function () { android.framework.install({}, dummyPluginInfo, dummyProject); }).toThrow();
|
||||
});
|
||||
|
||||
it('Test#009 : should install framework without "parent" attribute into project root', function() {
|
||||
it('Test#009 : should install framework without "parent" attribute into project root', function () {
|
||||
var framework = {src: 'plugin-lib'};
|
||||
android.framework.install(framework, dummyPluginInfo, dummyProject);
|
||||
expect(dummyProject.addSystemLibrary).toHaveBeenCalledWith(dummyProject.projectDir, someString);
|
||||
});
|
||||
|
||||
it('Test#010 : should install framework with "parent" attribute into parent framework dir', function() {
|
||||
it('Test#010 : should install framework with "parent" attribute into parent framework dir', function () {
|
||||
var childFramework = {src: 'plugin-lib2', parent: 'plugin-lib'};
|
||||
android.framework.install(childFramework, dummyPluginInfo, dummyProject);
|
||||
expect(dummyProject.addSystemLibrary).toHaveBeenCalledWith(path.resolve(dummyProject.projectDir, childFramework.parent), someString);
|
||||
});
|
||||
|
||||
it('Test#011 : should not copy anything if "custom" attribute is not set', function() {
|
||||
it('Test#011 : should not copy anything if "custom" attribute is not set', function () {
|
||||
var framework = {src: 'plugin-lib'};
|
||||
var cpSpy = spyOn(shell, 'cp');
|
||||
android.framework.install(framework, dummyPluginInfo, dummyProject);
|
||||
@ -158,14 +158,14 @@ describe('android project handler', function() {
|
||||
expect(cpSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Test#012 : should copy framework sources if "custom" attribute is set', function() {
|
||||
it('Test#012 : should copy framework sources if "custom" attribute is set', function () {
|
||||
var framework = {src: 'plugin-lib', custom: true};
|
||||
android.framework.install(framework, dummyPluginInfo, dummyProject);
|
||||
expect(dummyProject.addSubProject).toHaveBeenCalledWith(dummyProject.projectDir, someString);
|
||||
expect(copyNewFileSpy).toHaveBeenCalledWith(dummyPluginInfo.dir, framework.src, dummyProject.projectDir, someString, false);
|
||||
});
|
||||
|
||||
it('Test#013 : should install gradleReference using project.addGradleReference', function() {
|
||||
it('Test#013 : should install gradleReference using project.addGradleReference', function () {
|
||||
var framework = {src: 'plugin-lib', custom: true, type: 'gradleReference'};
|
||||
android.framework.install(framework, dummyPluginInfo, dummyProject);
|
||||
expect(copyNewFileSpy).toHaveBeenCalledWith(dummyPluginInfo.dir, framework.src, dummyProject.projectDir, someString, false);
|
||||
@ -173,7 +173,7 @@ describe('android project handler', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('of <js-module> elements', function() {
|
||||
describe('of <js-module> elements', function () {
|
||||
var jsModule = {src: 'www/dummyplugin.js'};
|
||||
var wwwDest, platformWwwDest;
|
||||
|
||||
@ -196,9 +196,10 @@ describe('android project handler', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('of <asset> elements', function() {
|
||||
describe('of <asset> elements', function () {
|
||||
var asset = {src: 'www/dummyPlugin.js', target: 'foo/dummy.js'};
|
||||
var wwwDest, platformWwwDest;
|
||||
var wwwDest; /* eslint no-unused-vars: "off" */
|
||||
var platformWwwDest; /* eslint no-unused-vars: "off" */
|
||||
|
||||
beforeEach(function () {
|
||||
wwwDest = path.resolve(dummyProject.www, asset.target);
|
||||
@ -219,7 +220,7 @@ describe('android project handler', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('uninstallation', function() {
|
||||
describe('uninstallation', function () {
|
||||
|
||||
var removeFileOrig = common.__get__('removeFile');
|
||||
var deleteJavaOrig = common.__get__('deleteJava');
|
||||
@ -228,7 +229,7 @@ describe('android project handler', function() {
|
||||
var deleteJavaSpy = jasmine.createSpy('deleteJava');
|
||||
var dummyProject;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(function () {
|
||||
shell.mkdir('-p', temp);
|
||||
shell.mkdir('-p', plugins_dir);
|
||||
shell.cp('-rf', android_project, temp);
|
||||
@ -238,26 +239,26 @@ describe('android project handler', function() {
|
||||
common.__set__('deleteJava', deleteJavaSpy);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
afterEach(function () {
|
||||
shell.rm('-rf', temp);
|
||||
common.__set__('removeFile', removeFileOrig);
|
||||
common.__set__('deleteJava', deleteJavaOrig);
|
||||
});
|
||||
|
||||
describe('of <lib-file> elements', function() {
|
||||
describe('of <lib-file> elements', function () {
|
||||
it('Test#018 : should remove jar files', function () {
|
||||
android['lib-file'].install(valid_libs[0], dummyPluginInfo, dummyProject);
|
||||
android['lib-file'].uninstall(valid_libs[0], dummyPluginInfo, dummyProject);
|
||||
expect(removeFileSpy).toHaveBeenCalledWith(temp, path.join('libs/TestLib.jar'));
|
||||
});
|
||||
it('Test#019 : should remove jar files for Android Studio projects', function () {
|
||||
android['lib-file'].install(valid_libs[0], dummyPluginInfo, dummyProject, {android_studio:true});
|
||||
android['lib-file'].uninstall(valid_libs[0], dummyPluginInfo, dummyProject, {android_studio:true});
|
||||
android['lib-file'].install(valid_libs[0], dummyPluginInfo, dummyProject, {android_studio: true});
|
||||
android['lib-file'].uninstall(valid_libs[0], dummyPluginInfo, dummyProject, {android_studio: true});
|
||||
expect(removeFileSpy).toHaveBeenCalledWith(temp, path.join('app/libs/TestLib.jar'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('of <resource-file> elements', function() {
|
||||
describe('of <resource-file> elements', function () {
|
||||
it('Test#020 : should remove files', function () {
|
||||
android['resource-file'].install(valid_resources[0], dummyPluginInfo, dummyProject);
|
||||
android['resource-file'].uninstall(valid_resources[0], dummyPluginInfo, dummyProject);
|
||||
@ -265,24 +266,24 @@ describe('android project handler', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('of <source-file> elements', function() {
|
||||
it('Test#021 : should remove stuff by calling common.deleteJava', function() {
|
||||
describe('of <source-file> elements', function () {
|
||||
it('Test#021 : should remove stuff by calling common.deleteJava', function () {
|
||||
android['source-file'].install(valid_source[0], dummyPluginInfo, dummyProject);
|
||||
android['source-file'].uninstall(valid_source[0], dummyPluginInfo, dummyProject);
|
||||
expect(deleteJavaSpy).toHaveBeenCalledWith(temp, path.join('src/com/phonegap/plugins/dummyplugin/DummyPlugin.java'));
|
||||
});
|
||||
it('Test#022 : should remove stuff by calling common.deleteJava for Android Studio projects', function() {
|
||||
android['source-file'].install(valid_source[0], dummyPluginInfo, dummyProject, {android_studio:true});
|
||||
android['source-file'].uninstall(valid_source[0], dummyPluginInfo, dummyProject, {android_studio:true});
|
||||
it('Test#022 : should remove stuff by calling common.deleteJava for Android Studio projects', function () {
|
||||
android['source-file'].install(valid_source[0], dummyPluginInfo, dummyProject, {android_studio: true});
|
||||
android['source-file'].uninstall(valid_source[0], dummyPluginInfo, dummyProject, {android_studio: true});
|
||||
expect(deleteJavaSpy).toHaveBeenCalledWith(temp, path.join('app/src/main/java/com/phonegap/plugins/dummyplugin/DummyPlugin.java'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('of <framework> elements', function() {
|
||||
describe('of <framework> elements', function () {
|
||||
|
||||
var someString = jasmine.any(String);
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(function () {
|
||||
shell.mkdir(path.join(dummyProject.projectDir, dummyPluginInfo.id));
|
||||
|
||||
spyOn(dummyProject, 'removeSystemLibrary');
|
||||
@ -290,30 +291,30 @@ describe('android project handler', function() {
|
||||
spyOn(dummyProject, 'removeGradleReference');
|
||||
});
|
||||
|
||||
it('Test#023 : should throw if framework doesn\'t have "src" attribute', function() {
|
||||
expect(function() { android.framework.uninstall({}, dummyPluginInfo, dummyProject); }).toThrow();
|
||||
it('Test#023 : should throw if framework doesn\'t have "src" attribute', function () {
|
||||
expect(function () { android.framework.uninstall({}, dummyPluginInfo, dummyProject); }).toThrow();
|
||||
});
|
||||
|
||||
it('Test#024 : should uninstall framework without "parent" attribute into project root', function() {
|
||||
it('Test#024 : should uninstall framework without "parent" attribute into project root', function () {
|
||||
var framework = {src: 'plugin-lib'};
|
||||
android.framework.uninstall(framework, dummyPluginInfo, dummyProject);
|
||||
expect(dummyProject.removeSystemLibrary).toHaveBeenCalledWith(dummyProject.projectDir, someString);
|
||||
});
|
||||
|
||||
it('Test#025 : should uninstall framework with "parent" attribute into parent framework dir', function() {
|
||||
it('Test#025 : should uninstall framework with "parent" attribute into parent framework dir', function () {
|
||||
var childFramework = {src: 'plugin-lib2', parent: 'plugin-lib'};
|
||||
android.framework.uninstall(childFramework, dummyPluginInfo, dummyProject);
|
||||
expect(dummyProject.removeSystemLibrary).toHaveBeenCalledWith(path.resolve(dummyProject.projectDir, childFramework.parent), someString);
|
||||
});
|
||||
|
||||
it('Test#026 : should remove framework sources if "custom" attribute is set', function() {
|
||||
it('Test#026 : should remove framework sources if "custom" attribute is set', function () {
|
||||
var framework = {src: 'plugin-lib', custom: true};
|
||||
android.framework.uninstall(framework, dummyPluginInfo, dummyProject);
|
||||
expect(dummyProject.removeSubProject).toHaveBeenCalledWith(dummyProject.projectDir, someString);
|
||||
expect(removeFileSpy).toHaveBeenCalledWith(dummyProject.projectDir, someString);
|
||||
});
|
||||
|
||||
it('Test#27 : should install gradleReference using project.removeGradleReference', function() {
|
||||
it('Test#27 : should install gradleReference using project.removeGradleReference', function () {
|
||||
var framework = {src: 'plugin-lib', custom: true, type: 'gradleReference'};
|
||||
android.framework.uninstall(framework, dummyPluginInfo, dummyProject);
|
||||
expect(removeFileSpy).toHaveBeenCalledWith(dummyProject.projectDir, someString);
|
||||
@ -321,10 +322,10 @@ describe('android project handler', function() {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('of <js-module> elements', function() {
|
||||
describe('of <js-module> elements', function () {
|
||||
var jsModule = {src: 'www/dummyPlugin.js'};
|
||||
var wwwDest, platformWwwDest;
|
||||
var wwwDest;
|
||||
var platformWwwDest;
|
||||
|
||||
beforeEach(function () {
|
||||
wwwDest = path.resolve(dummyProject.www, 'plugins', dummyPluginInfo.id, jsModule.src);
|
||||
@ -334,7 +335,7 @@ describe('android project handler', function() {
|
||||
|
||||
var existsSyncOrig = fs.existsSync;
|
||||
spyOn(fs, 'existsSync').and.callFake(function (file) {
|
||||
if ([wwwDest, platformWwwDest].indexOf(file) >= 0 ) return true;
|
||||
if ([wwwDest, platformWwwDest].indexOf(file) >= 0) return true;
|
||||
return existsSyncOrig.call(fs, file);
|
||||
});
|
||||
});
|
||||
@ -352,7 +353,7 @@ describe('android project handler', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('of <asset> elements', function() {
|
||||
describe('of <asset> elements', function () {
|
||||
var asset = {src: 'www/dummyPlugin.js', target: 'foo/dummy.js'};
|
||||
var wwwDest, platformWwwDest;
|
||||
|
||||
@ -364,7 +365,7 @@ describe('android project handler', function() {
|
||||
|
||||
var existsSyncOrig = fs.existsSync;
|
||||
spyOn(fs, 'existsSync').and.callFake(function (file) {
|
||||
if ([wwwDest, platformWwwDest].indexOf(file) >= 0 ) return true;
|
||||
if ([wwwDest, platformWwwDest].indexOf(file) >= 0) return true;
|
||||
return existsSyncOrig.call(fs, file);
|
||||
});
|
||||
});
|
||||
|
@ -17,22 +17,22 @@
|
||||
under the License.
|
||||
*/
|
||||
|
||||
var rewire = require("rewire");
|
||||
var run = rewire("../../bin/templates/cordova/lib/run");
|
||||
var getInstallTarget = run.__get__("getInstallTarget");
|
||||
var rewire = require('rewire');
|
||||
var run = rewire('../../bin/templates/cordova/lib/run');
|
||||
var getInstallTarget = run.__get__('getInstallTarget');
|
||||
|
||||
describe("run", function () {
|
||||
describe("getInstallTarget", function() {
|
||||
var targetOpts = { target: "emu" };
|
||||
var deviceOpts = { device: true };
|
||||
var emulatorOpts = { emulator: true };
|
||||
var emptyOpts = {};
|
||||
describe('run', function () {
|
||||
describe('getInstallTarget', function () {
|
||||
var targetOpts = { target: 'emu' };
|
||||
var deviceOpts = { device: true };
|
||||
var emulatorOpts = { emulator: true };
|
||||
var emptyOpts = {};
|
||||
|
||||
it("Test#001 : should select correct target based on the run opts", function() {
|
||||
expect(getInstallTarget(targetOpts)).toBe("emu");
|
||||
expect(getInstallTarget(deviceOpts)).toBe("--device");
|
||||
expect(getInstallTarget(emulatorOpts)).toBe("--emulator");
|
||||
expect(getInstallTarget(emptyOpts)).toBeUndefined();
|
||||
it('Test#001 : should select correct target based on the run opts', function () {
|
||||
expect(getInstallTarget(targetOpts)).toBe('emu');
|
||||
expect(getInstallTarget(deviceOpts)).toBe('--device');
|
||||
expect(getInstallTarget(emulatorOpts)).toBe('--emulator');
|
||||
expect(getInstallTarget(emptyOpts)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user