You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by st...@apache.org on 2015/10/21 01:16:12 UTC
[1/4] android commit: Fixed line endings
Repository: cordova-android
Updated Branches:
refs/heads/master 400282282 -> 0ac822c57
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/0ac822c5/bin/templates/cordova/lib/emulator.js
----------------------------------------------------------------------
diff --git a/bin/templates/cordova/lib/emulator.js b/bin/templates/cordova/lib/emulator.js
index 3233502..9e214b1 100644
--- a/bin/templates/cordova/lib/emulator.js
+++ b/bin/templates/cordova/lib/emulator.js
@@ -1,372 +1,372 @@
-#!/usr/bin/env node
-
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-/* jshint sub:true */
-
-var retry = require('./retry');
-var build = require('./build');
-var check_reqs = require('./check_reqs');
-var path = require('path');
-var Adb = require('./Adb');
-var AndroidManifest = require('./AndroidManifest');
-var events = require('cordova-common').events;
-var spawn = require('cordova-common').superspawn.spawn;
-var CordovaError = require('cordova-common').CordovaError;
-
-var Q = require('q');
-var os = require('os');
-var child_process = require('child_process');
-
-// constants
-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 EXEC_KILL_SIGNAL = 'SIGKILL';
-
-/**
- * Returns a Promise for a list of emulator images in the form of objects
- * {
- name : <emulator_name>,
- path : <path_to_emulator_image>,
- target : <api_target>,
- abi : <cpu>,
- skin : <skin>
- }
- */
-module.exports.list_images = function() {
- return spawn('android', ['list', 'avds'])
- .then(function(output) {
- var response = output.split('\n');
- var emulator_list = [];
- for (var i = 1; i < response.length; i++) {
- // To return more detailed information use img_obj
- var img_obj = {};
- if (response[i].match(/Name:\s/)) {
- img_obj['name'] = response[i].split('Name: ')[1].replace('\r', '');
- if (response[i + 1].match(/Path:\s/)) {
- i++;
- img_obj['path'] = response[i].split('Path: ')[1].replace('\r', '');
- }
- if (response[i + 1].match(/\(API\slevel\s/)) {
- i++;
- img_obj['target'] = response[i].replace('\r', '');
- }
- if (response[i + 1].match(/ABI:\s/)) {
- i++;
- img_obj['abi'] = response[i].split('ABI: ')[1].replace('\r', '');
- }
- if (response[i + 1].match(/Skin:\s/)) {
- i++;
- img_obj['skin'] = response[i].split('Skin: ')[1].replace('\r', '');
- }
-
- emulator_list.push(img_obj);
- }
- /* 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;
- });
-};
-
-/**
- * Will return the closest avd to the projects target
- * or undefined if no avds exist.
- * Returns a promise.
- */
-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;
-
- var closest = 9999;
- var best = images[0];
- var project_target = check_reqs.get_target().replace('android-', '');
- for (var i in images) {
- var target = images[i].target;
- if(target) {
- var num = target.split('(API level ')[1].replace(')', '');
- if (num == project_target) {
- return images[i];
- } else if (project_target - num < closest && project_target > num) {
- closest = project_target - num;
- best = images[i];
- }
- }
- }
- return best;
- });
-};
-
-// Returns a promise.
-module.exports.list_started = function() {
- return Adb.devices({emulators: true});
-};
-
-// Returns a promise.
-module.exports.list_targets = function() {
- return 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:/)) {
- targets.push(targets[i].split(' ')[1]);
- }
- }
- return targets;
- });
-};
-
-/*
- * Starts an emulator with the given ID,
- * and returns the started ID of that emulator.
- * If no ID is given it will use the first image available,
- * if no image is available it will error out (maybe create one?).
- *
- * Returns a promise.
- */
-module.exports.start = function(emulator_ID) {
- var self = this;
-
- return Q().then(function() {
- if (emulator_ID) return Q(emulator_ID);
-
- return self.best_image()
- .then(function(best) {
- if (best && best.name) {
- events.emit('warn', 'No emulator specified, defaulting to ' + best.name);
- return best.name;
- }
-
- var androidCmd = check_reqs.getAbsoluteAndroidCmd();
- return Q.reject(new CordovaError('No emulator images (avds) found.\n' +
- '1. Download desired System Image by running: ' + androidCmd + ' sdk\n' +
- '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) {
- var uuid = 'cordova_emulator_' + new Date().getTime();
- var uuidProp = 'emu.uuid=' + uuid;
- var args = ['-avd', emulatorId, '-prop', uuidProp];
- // Don't wait for it to finish, since the emulator will probably keep running for a long time.
- child_process
- .spawn('emulator', args, { stdio: 'inherit', detached: true })
- .unref();
-
- // wait for emulator to start
- events.emit('log', 'Waiting for emulator...');
- return self.wait_for_emulator(uuid);
- }).then(function(emulatorId) {
- if (!emulatorId)
- return Q.reject(new CordovaError('Failed to start emulator'));
-
- //wait for emulator to boot up
- process.stdout.write('Booting up emulator (this may take a while)...');
- return self.wait_for_boot(emulatorId)
- .then(function() {
- 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;
- });
- });
-};
-
-/*
- * Waits for an emulator with given uuid to apear on the started-emulator list.
- * Returns a promise with this emulator's ID.
- */
-module.exports.wait_for_emulator = function(uuid) {
- var self = this;
- return self.list_started()
- .then(function(new_started) {
- var emulator_id = null;
- var promises = [];
-
- new_started.forEach(function (emulator) {
- promises.push(
- Adb.shell(emulator, 'getprop emu.uuid')
- .then(function (output) {
- if (output.indexOf(uuid) >= 0) {
- emulator_id = emulator;
- }
- })
- );
- });
-
- return Q.all(promises).then(function () {
- return emulator_id || self.wait_for_emulator(uuid);
- });
- });
-};
-
-/*
- * Waits for the core android process of the emulator to start
- */
-module.exports.wait_for_boot = function(emulator_id) {
- var self = this;
- return Adb.shell(emulator_id, 'ps')
- .then(function(output) {
- if (output.match(/android\.process\.acore/)) {
- return;
- } else {
- process.stdout.write('.');
- return Q.delay(3000).then(function() {
- return self.wait_for_boot(emulator_id);
- });
- }
- });
-};
-
-/*
- * Create avd
- * TODO : Enter the stdin input required to complete the creation of an avd.
- * Returns a promise.
- */
-module.exports.create_image = function(name, target) {
- console.log('Creating avd named ' + name);
- if (target) {
- return 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);
- });
- } else {
- console.log('WARNING : Project target not found, creating avd with a different target but the project may fail to install.');
- return 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('Please insure you have targets available by running the "android" command');
- return Q.reject();
- }, 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) {
- if (emulator_list.length < 1) {
- return Q.reject('No started emulators found, please start an emultor before deploying your project.');
- }
-
- // default emulator
- target = target || emulator_list[0];
- if (emulator_list.indexOf(target) < 0) {
- 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};
- });
- });
-};
-
-/*
- * Installs a previously built application on the emulator and launches it.
- * If no target is specified, then it picks one.
- * If no started emulators are found, error out.
- * Returns a promise.
- */
-module.exports.install = function(givenTarget, buildResults) {
-
- var target;
- var manifest = new AndroidManifest(path.join(__dirname, '../../AndroidManifest.xml'));
- var pkgName = manifest.getPackageId();
-
- // resolve the target emulator
- return Q().then(function () {
- if (givenTarget && typeof givenTarget == 'object') {
- return givenTarget;
- } else {
- return module.exports.resolveTarget(givenTarget);
- }
-
- // set the resolved target
- }).then(function (resolvedTarget) {
- target = resolvedTarget;
-
- // install the app
- }).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 Adb.uninstall(target.target, pkgName)
- .then(function() {
-
- var apk_path = build.findBestApkForArchitecture(buildResults, target.arch);
- var execOptions = {
- cwd: os.tmpdir(),
- timeout: INSTALL_COMMAND_TIMEOUT, // in milliseconds
- killSignal: EXEC_KILL_SIGNAL
- };
-
- events.emit('log', 'Using apk: ' + apk_path);
- events.emit('verbose', 'Installing app on emulator...');
-
- function exec(command, opts) {
- return Q.promise(function (resolve, reject) {
- child_process.exec(command, opts, function(err, stdout, stderr) {
- if (err) reject(new CordovaError('Error executing "' + command + '": ' + stderr));
- else resolve(stdout);
- });
- });
- }
-
- var retriedInstall = retry.retryPromise(
- NUM_INSTALL_RETRIES,
- exec, 'adb -s ' + target.target + ' install -r "' + apk_path + '"', execOptions
- );
-
- return retriedInstall.then(function (output) {
- if (output.match(/Failure/)) {
- return Q.reject(new CordovaError('Failed to install apk to emulator: ' + output));
- } else {
- events.emit('log', 'INSTALL SUCCESS');
- }
- }, function (err) {
- return Q.reject(new CordovaError('Failed to install apk to emulator: ' + err));
- });
- });
- // unlock screen
- }).then(function () {
-
- events.emit('verbose', 'Unlocking screen...');
- return Adb.shell(target.target, 'input keyevent 82');
- }).then(function () {
- Adb.start(target.target, pkgName + '/.' + manifest.getActivity().getName());
- // report success or failure
- }).then(function (output) {
- events.emit('log', 'LAUNCH SUCCESS');
- });
-};
+#!/usr/bin/env node
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+/* jshint sub:true */
+
+var retry = require('./retry');
+var build = require('./build');
+var check_reqs = require('./check_reqs');
+var path = require('path');
+var Adb = require('./Adb');
+var AndroidManifest = require('./AndroidManifest');
+var events = require('cordova-common').events;
+var spawn = require('cordova-common').superspawn.spawn;
+var CordovaError = require('cordova-common').CordovaError;
+
+var Q = require('q');
+var os = require('os');
+var child_process = require('child_process');
+
+// constants
+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 EXEC_KILL_SIGNAL = 'SIGKILL';
+
+/**
+ * Returns a Promise for a list of emulator images in the form of objects
+ * {
+ name : <emulator_name>,
+ path : <path_to_emulator_image>,
+ target : <api_target>,
+ abi : <cpu>,
+ skin : <skin>
+ }
+ */
+module.exports.list_images = function() {
+ return spawn('android', ['list', 'avds'])
+ .then(function(output) {
+ var response = output.split('\n');
+ var emulator_list = [];
+ for (var i = 1; i < response.length; i++) {
+ // To return more detailed information use img_obj
+ var img_obj = {};
+ if (response[i].match(/Name:\s/)) {
+ img_obj['name'] = response[i].split('Name: ')[1].replace('\r', '');
+ if (response[i + 1].match(/Path:\s/)) {
+ i++;
+ img_obj['path'] = response[i].split('Path: ')[1].replace('\r', '');
+ }
+ if (response[i + 1].match(/\(API\slevel\s/)) {
+ i++;
+ img_obj['target'] = response[i].replace('\r', '');
+ }
+ if (response[i + 1].match(/ABI:\s/)) {
+ i++;
+ img_obj['abi'] = response[i].split('ABI: ')[1].replace('\r', '');
+ }
+ if (response[i + 1].match(/Skin:\s/)) {
+ i++;
+ img_obj['skin'] = response[i].split('Skin: ')[1].replace('\r', '');
+ }
+
+ emulator_list.push(img_obj);
+ }
+ /* 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;
+ });
+};
+
+/**
+ * Will return the closest avd to the projects target
+ * or undefined if no avds exist.
+ * Returns a promise.
+ */
+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;
+
+ var closest = 9999;
+ var best = images[0];
+ var project_target = check_reqs.get_target().replace('android-', '');
+ for (var i in images) {
+ var target = images[i].target;
+ if(target) {
+ var num = target.split('(API level ')[1].replace(')', '');
+ if (num == project_target) {
+ return images[i];
+ } else if (project_target - num < closest && project_target > num) {
+ closest = project_target - num;
+ best = images[i];
+ }
+ }
+ }
+ return best;
+ });
+};
+
+// Returns a promise.
+module.exports.list_started = function() {
+ return Adb.devices({emulators: true});
+};
+
+// Returns a promise.
+module.exports.list_targets = function() {
+ return 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:/)) {
+ targets.push(targets[i].split(' ')[1]);
+ }
+ }
+ return targets;
+ });
+};
+
+/*
+ * Starts an emulator with the given ID,
+ * and returns the started ID of that emulator.
+ * If no ID is given it will use the first image available,
+ * if no image is available it will error out (maybe create one?).
+ *
+ * Returns a promise.
+ */
+module.exports.start = function(emulator_ID) {
+ var self = this;
+
+ return Q().then(function() {
+ if (emulator_ID) return Q(emulator_ID);
+
+ return self.best_image()
+ .then(function(best) {
+ if (best && best.name) {
+ events.emit('warn', 'No emulator specified, defaulting to ' + best.name);
+ return best.name;
+ }
+
+ var androidCmd = check_reqs.getAbsoluteAndroidCmd();
+ return Q.reject(new CordovaError('No emulator images (avds) found.\n' +
+ '1. Download desired System Image by running: ' + androidCmd + ' sdk\n' +
+ '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) {
+ var uuid = 'cordova_emulator_' + new Date().getTime();
+ var uuidProp = 'emu.uuid=' + uuid;
+ var args = ['-avd', emulatorId, '-prop', uuidProp];
+ // Don't wait for it to finish, since the emulator will probably keep running for a long time.
+ child_process
+ .spawn('emulator', args, { stdio: 'inherit', detached: true })
+ .unref();
+
+ // wait for emulator to start
+ events.emit('log', 'Waiting for emulator...');
+ return self.wait_for_emulator(uuid);
+ }).then(function(emulatorId) {
+ if (!emulatorId)
+ return Q.reject(new CordovaError('Failed to start emulator'));
+
+ //wait for emulator to boot up
+ process.stdout.write('Booting up emulator (this may take a while)...');
+ return self.wait_for_boot(emulatorId)
+ .then(function() {
+ 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;
+ });
+ });
+};
+
+/*
+ * Waits for an emulator with given uuid to apear on the started-emulator list.
+ * Returns a promise with this emulator's ID.
+ */
+module.exports.wait_for_emulator = function(uuid) {
+ var self = this;
+ return self.list_started()
+ .then(function(new_started) {
+ var emulator_id = null;
+ var promises = [];
+
+ new_started.forEach(function (emulator) {
+ promises.push(
+ Adb.shell(emulator, 'getprop emu.uuid')
+ .then(function (output) {
+ if (output.indexOf(uuid) >= 0) {
+ emulator_id = emulator;
+ }
+ })
+ );
+ });
+
+ return Q.all(promises).then(function () {
+ return emulator_id || self.wait_for_emulator(uuid);
+ });
+ });
+};
+
+/*
+ * Waits for the core android process of the emulator to start
+ */
+module.exports.wait_for_boot = function(emulator_id) {
+ var self = this;
+ return Adb.shell(emulator_id, 'ps')
+ .then(function(output) {
+ if (output.match(/android\.process\.acore/)) {
+ return;
+ } else {
+ process.stdout.write('.');
+ return Q.delay(3000).then(function() {
+ return self.wait_for_boot(emulator_id);
+ });
+ }
+ });
+};
+
+/*
+ * Create avd
+ * TODO : Enter the stdin input required to complete the creation of an avd.
+ * Returns a promise.
+ */
+module.exports.create_image = function(name, target) {
+ console.log('Creating avd named ' + name);
+ if (target) {
+ return 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);
+ });
+ } else {
+ console.log('WARNING : Project target not found, creating avd with a different target but the project may fail to install.');
+ return 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('Please insure you have targets available by running the "android" command');
+ return Q.reject();
+ }, 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) {
+ if (emulator_list.length < 1) {
+ return Q.reject('No started emulators found, please start an emultor before deploying your project.');
+ }
+
+ // default emulator
+ target = target || emulator_list[0];
+ if (emulator_list.indexOf(target) < 0) {
+ 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};
+ });
+ });
+};
+
+/*
+ * Installs a previously built application on the emulator and launches it.
+ * If no target is specified, then it picks one.
+ * If no started emulators are found, error out.
+ * Returns a promise.
+ */
+module.exports.install = function(givenTarget, buildResults) {
+
+ var target;
+ var manifest = new AndroidManifest(path.join(__dirname, '../../AndroidManifest.xml'));
+ var pkgName = manifest.getPackageId();
+
+ // resolve the target emulator
+ return Q().then(function () {
+ if (givenTarget && typeof givenTarget == 'object') {
+ return givenTarget;
+ } else {
+ return module.exports.resolveTarget(givenTarget);
+ }
+
+ // set the resolved target
+ }).then(function (resolvedTarget) {
+ target = resolvedTarget;
+
+ // install the app
+ }).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 Adb.uninstall(target.target, pkgName)
+ .then(function() {
+
+ var apk_path = build.findBestApkForArchitecture(buildResults, target.arch);
+ var execOptions = {
+ cwd: os.tmpdir(),
+ timeout: INSTALL_COMMAND_TIMEOUT, // in milliseconds
+ killSignal: EXEC_KILL_SIGNAL
+ };
+
+ events.emit('log', 'Using apk: ' + apk_path);
+ events.emit('verbose', 'Installing app on emulator...');
+
+ function exec(command, opts) {
+ return Q.promise(function (resolve, reject) {
+ child_process.exec(command, opts, function(err, stdout, stderr) {
+ if (err) reject(new CordovaError('Error executing "' + command + '": ' + stderr));
+ else resolve(stdout);
+ });
+ });
+ }
+
+ var retriedInstall = retry.retryPromise(
+ NUM_INSTALL_RETRIES,
+ exec, 'adb -s ' + target.target + ' install -r "' + apk_path + '"', execOptions
+ );
+
+ return retriedInstall.then(function (output) {
+ if (output.match(/Failure/)) {
+ return Q.reject(new CordovaError('Failed to install apk to emulator: ' + output));
+ } else {
+ events.emit('log', 'INSTALL SUCCESS');
+ }
+ }, function (err) {
+ return Q.reject(new CordovaError('Failed to install apk to emulator: ' + err));
+ });
+ });
+ // unlock screen
+ }).then(function () {
+
+ events.emit('verbose', 'Unlocking screen...');
+ return Adb.shell(target.target, 'input keyevent 82');
+ }).then(function () {
+ Adb.start(target.target, pkgName + '/.' + manifest.getActivity().getName());
+ // report success or failure
+ }).then(function (output) {
+ events.emit('log', 'LAUNCH SUCCESS');
+ });
+};
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/0ac822c5/bin/templates/cordova/lib/pluginHandlers.js
----------------------------------------------------------------------
diff --git a/bin/templates/cordova/lib/pluginHandlers.js b/bin/templates/cordova/lib/pluginHandlers.js
index cad95c2..381734d 100644
--- a/bin/templates/cordova/lib/pluginHandlers.js
+++ b/bin/templates/cordova/lib/pluginHandlers.js
@@ -1,252 +1,252 @@
-/*
- *
- * Copyright 2013 Anis Kadri
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-/* jshint unused: vars */
-
-var fs = require('fs');
-var path = require('path');
-var shell = require('shelljs');
-var events = require('cordova-common').events;
-var CordovaError = require('cordova-common').CordovaError;
-
-var handlers = {
- 'source-file':{
- install:function(obj, plugin, project, options) {
- if (!obj.src) throw new CordovaError('<source-file> element is missing "src" attribute for plugin: ' + plugin.id);
- if (!obj.targetDir) throw new CordovaError('<source-file> element is missing "target-dir" attribute for plugin: ' + plugin.id);
- var dest = path.join(obj.targetDir, path.basename(obj.src));
- copyNewFile(plugin.dir, obj.src, project.projectDir, dest, options && options.link);
- },
- uninstall:function(obj, plugin, project, options) {
- var dest = path.join(obj.targetDir, path.basename(obj.src));
- deleteJava(project.projectDir, dest);
- }
- },
- 'lib-file':{
- install:function(obj, plugin, project, options) {
- var dest = path.join('libs', path.basename(obj.src));
- copyFile(plugin.dir, obj.src, project.projectDir, dest, options && options.link);
- },
- uninstall:function(obj, plugin, project, options) {
- var dest = path.join('libs', path.basename(obj.src));
- removeFile(project.projectDir, dest);
- }
- },
- '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) {
- removeFile(project.projectDir, path.normalize(obj.target));
- }
- },
- 'framework': {
- install:function(obj, plugin, project, options) {
- var src = obj.src;
- if (!src) throw new CordovaError('src not specified in <framework> for plugin: ' + plugin.id);
-
- events.emit('verbose', 'Installing Android library: ' + src);
- var parentDir = obj.parent ? path.resolve(project.projectDir, obj.parent) : project.projectDir;
- var subDir;
-
- if (obj.custom) {
- var subRelativeDir = project.getCustomSubprojectRelativeDir(plugin.id, src);
- copyNewFile(plugin.dir, src, project.projectDir, subRelativeDir, options && options.link);
- subDir = path.resolve(project.projectDir, subRelativeDir);
- } else {
- obj.type = 'sys';
- subDir = src;
- }
-
- if (obj.type == 'gradleReference') {
- project.addGradleReference(parentDir, subDir);
- } else if (obj.type == 'sys') {
- project.addSystemLibrary(parentDir, subDir);
- } else {
- project.addSubProject(parentDir, subDir);
- }
- },
- uninstall:function(obj, plugin, project, options) {
- var src = obj.src;
- if (!src) throw new CordovaError('src not specified in <framework> for plugin: ' + plugin.id);
-
- events.emit('verbose', 'Uninstalling Android library: ' + src);
- var parentDir = obj.parent ? path.resolve(project.projectDir, obj.parent) : project.projectDir;
- var subDir;
-
- if (obj.custom) {
- var subRelativeDir = project.getCustomSubprojectRelativeDir(plugin.id, src);
- removeFile(project.projectDir, subRelativeDir);
- subDir = path.resolve(project.projectDir, subRelativeDir);
- // If it's the last framework in the plugin, remove the parent directory.
- var parDir = path.dirname(subDir);
- if (fs.readdirSync(parDir).length === 0) {
- fs.rmdirSync(parDir);
- }
- } else {
- obj.type = 'sys';
- subDir = src;
- }
-
- if (obj.type == 'gradleReference') {
- project.removeGradleReference(parentDir, subDir);
- } else if (obj.type == 'sys') {
- project.removeSystemLibrary(parentDir, subDir);
- } else {
- project.removeSubProject(parentDir, subDir);
- }
- }
- },
- asset:{
- install:function(obj, plugin, project, options) {
- if (!obj.src) {
- throw new CordovaError('<asset> tag without required "src" attribute. plugin=' + plugin.dir);
- }
- if (!obj.target) {
- throw new CordovaError('<asset> tag without required "target" attribute');
- }
-
- var www = options.usePlatformWww ? project.platformWww : project.www;
- copyFile(plugin.dir, obj.src, www, obj.target);
- },
- uninstall:function(obj, plugin, project, options) {
- var target = obj.target || obj.src;
-
- if (!target) throw new CordovaError('<asset> tag without required "target" attribute');
-
- var www = options.usePlatformWww ? project.platformWww : project.www;
- removeFile(www, target);
- removeFileF(path.resolve(www, 'plugins', plugin.id));
- }
- },
- 'js-module': {
- 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.parse(obj.src).name);
-
- // Read in the file, prepend the cordova.define, and write it back out.
- var scriptContent = fs.readFileSync(moduleSource, 'utf-8').replace(/^\ufeff/, ''); // Window BOM
- if (moduleSource.match(/.*\.json$/)) {
- scriptContent = 'module.exports = ' + scriptContent;
- }
- scriptContent = 'cordova.define("' + moduleName + '", function(require, exports, module) {\n' + scriptContent + '\n});\n';
-
- var www = options.usePlatformWww ? project.platformWww : project.www;
- var moduleDestination = path.resolve(www, 'plugins', plugin.id, obj.src);
- shell.mkdir('-p', path.dirname(moduleDestination));
- fs.writeFileSync(moduleDestination, scriptContent, 'utf-8');
- },
- uninstall: function (obj, plugin, project, options) {
- var pluginRelativePath = path.join('plugins', plugin.id, obj.src);
- var www = options.usePlatformWww ? project.platformWww : project.www;
- removeFileAndParents(www, pluginRelativePath);
- }
- }
-};
-
-module.exports.getInstaller = function (type) {
- if (handlers[type] && handlers[type].install) {
- return handlers[type].install;
- }
-
- events.emit('verbose', '<' + type + '> is not supported for android plugins');
-};
-
-module.exports.getUninstaller = function(type) {
- if (handlers[type] && handlers[type].uninstall) {
- return handlers[type].uninstall;
- }
-
- events.emit('verbose', '<' + type + '> is not supported for android plugins');
-};
-
-function copyFile (plugin_dir, src, project_dir, dest, link) {
- src = path.resolve(plugin_dir, src);
- if (!fs.existsSync(src)) throw new CordovaError('"' + src + '" not found!');
-
- // 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('"' + src + '" not located within plugin!');
-
- dest = path.resolve(project_dir, dest);
-
- // check that dest path is located in project directory
- if (dest.indexOf(project_dir) !== 0)
- throw new CordovaError('"' + dest + '" not located within project!');
-
- shell.mkdir('-p', path.dirname(dest));
-
- if (link) {
- fs.symlinkSync(path.relative(path.dirname(dest), 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);
- } else {
- shell.cp('-f', src, dest);
- }
-}
-
-// 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!');
-
- copyFile(plugin_dir, src, project_dir, dest, !!link);
-}
-
-// checks if file exists and then deletes. Error if doesn't exist
-function removeFile (project_dir, src) {
- var file = path.resolve(project_dir, src);
- shell.rm('-Rf', file);
-}
-
-// deletes file/directory without checking
-function removeFileF (file) {
- shell.rm('-Rf', file);
-}
-
-// Sometimes we want to remove some java, and prune any unnecessary empty directories
-function deleteJava (project_dir, destFile) {
- removeFileAndParents(project_dir, destFile, 'src');
-}
-
-function removeFileAndParents (baseDir, destFile, stopper) {
- stopper = stopper || '.';
- var file = path.resolve(baseDir, destFile);
- if (!fs.existsSync(file)) return;
-
- removeFileF(file);
-
- // 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) {
- fs.rmdirSync(curDir);
- curDir = path.resolve(curDir, '..');
- } else {
- // directory not empty...do nothing
- break;
- }
- }
-}
+/*
+ *
+ * Copyright 2013 Anis Kadri
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+/* jshint unused: vars */
+
+var fs = require('fs');
+var path = require('path');
+var shell = require('shelljs');
+var events = require('cordova-common').events;
+var CordovaError = require('cordova-common').CordovaError;
+
+var handlers = {
+ 'source-file':{
+ install:function(obj, plugin, project, options) {
+ if (!obj.src) throw new CordovaError('<source-file> element is missing "src" attribute for plugin: ' + plugin.id);
+ if (!obj.targetDir) throw new CordovaError('<source-file> element is missing "target-dir" attribute for plugin: ' + plugin.id);
+ var dest = path.join(obj.targetDir, path.basename(obj.src));
+ copyNewFile(plugin.dir, obj.src, project.projectDir, dest, options && options.link);
+ },
+ uninstall:function(obj, plugin, project, options) {
+ var dest = path.join(obj.targetDir, path.basename(obj.src));
+ deleteJava(project.projectDir, dest);
+ }
+ },
+ 'lib-file':{
+ install:function(obj, plugin, project, options) {
+ var dest = path.join('libs', path.basename(obj.src));
+ copyFile(plugin.dir, obj.src, project.projectDir, dest, options && options.link);
+ },
+ uninstall:function(obj, plugin, project, options) {
+ var dest = path.join('libs', path.basename(obj.src));
+ removeFile(project.projectDir, dest);
+ }
+ },
+ '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) {
+ removeFile(project.projectDir, path.normalize(obj.target));
+ }
+ },
+ 'framework': {
+ install:function(obj, plugin, project, options) {
+ var src = obj.src;
+ if (!src) throw new CordovaError('src not specified in <framework> for plugin: ' + plugin.id);
+
+ events.emit('verbose', 'Installing Android library: ' + src);
+ var parentDir = obj.parent ? path.resolve(project.projectDir, obj.parent) : project.projectDir;
+ var subDir;
+
+ if (obj.custom) {
+ var subRelativeDir = project.getCustomSubprojectRelativeDir(plugin.id, src);
+ copyNewFile(plugin.dir, src, project.projectDir, subRelativeDir, options && options.link);
+ subDir = path.resolve(project.projectDir, subRelativeDir);
+ } else {
+ obj.type = 'sys';
+ subDir = src;
+ }
+
+ if (obj.type == 'gradleReference') {
+ project.addGradleReference(parentDir, subDir);
+ } else if (obj.type == 'sys') {
+ project.addSystemLibrary(parentDir, subDir);
+ } else {
+ project.addSubProject(parentDir, subDir);
+ }
+ },
+ uninstall:function(obj, plugin, project, options) {
+ var src = obj.src;
+ if (!src) throw new CordovaError('src not specified in <framework> for plugin: ' + plugin.id);
+
+ events.emit('verbose', 'Uninstalling Android library: ' + src);
+ var parentDir = obj.parent ? path.resolve(project.projectDir, obj.parent) : project.projectDir;
+ var subDir;
+
+ if (obj.custom) {
+ var subRelativeDir = project.getCustomSubprojectRelativeDir(plugin.id, src);
+ removeFile(project.projectDir, subRelativeDir);
+ subDir = path.resolve(project.projectDir, subRelativeDir);
+ // If it's the last framework in the plugin, remove the parent directory.
+ var parDir = path.dirname(subDir);
+ if (fs.readdirSync(parDir).length === 0) {
+ fs.rmdirSync(parDir);
+ }
+ } else {
+ obj.type = 'sys';
+ subDir = src;
+ }
+
+ if (obj.type == 'gradleReference') {
+ project.removeGradleReference(parentDir, subDir);
+ } else if (obj.type == 'sys') {
+ project.removeSystemLibrary(parentDir, subDir);
+ } else {
+ project.removeSubProject(parentDir, subDir);
+ }
+ }
+ },
+ asset:{
+ install:function(obj, plugin, project, options) {
+ if (!obj.src) {
+ throw new CordovaError('<asset> tag without required "src" attribute. plugin=' + plugin.dir);
+ }
+ if (!obj.target) {
+ throw new CordovaError('<asset> tag without required "target" attribute');
+ }
+
+ var www = options.usePlatformWww ? project.platformWww : project.www;
+ copyFile(plugin.dir, obj.src, www, obj.target);
+ },
+ uninstall:function(obj, plugin, project, options) {
+ var target = obj.target || obj.src;
+
+ if (!target) throw new CordovaError('<asset> tag without required "target" attribute');
+
+ var www = options.usePlatformWww ? project.platformWww : project.www;
+ removeFile(www, target);
+ removeFileF(path.resolve(www, 'plugins', plugin.id));
+ }
+ },
+ 'js-module': {
+ 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.parse(obj.src).name);
+
+ // Read in the file, prepend the cordova.define, and write it back out.
+ var scriptContent = fs.readFileSync(moduleSource, 'utf-8').replace(/^\ufeff/, ''); // Window BOM
+ if (moduleSource.match(/.*\.json$/)) {
+ scriptContent = 'module.exports = ' + scriptContent;
+ }
+ scriptContent = 'cordova.define("' + moduleName + '", function(require, exports, module) {\n' + scriptContent + '\n});\n';
+
+ var www = options.usePlatformWww ? project.platformWww : project.www;
+ var moduleDestination = path.resolve(www, 'plugins', plugin.id, obj.src);
+ shell.mkdir('-p', path.dirname(moduleDestination));
+ fs.writeFileSync(moduleDestination, scriptContent, 'utf-8');
+ },
+ uninstall: function (obj, plugin, project, options) {
+ var pluginRelativePath = path.join('plugins', plugin.id, obj.src);
+ var www = options.usePlatformWww ? project.platformWww : project.www;
+ removeFileAndParents(www, pluginRelativePath);
+ }
+ }
+};
+
+module.exports.getInstaller = function (type) {
+ if (handlers[type] && handlers[type].install) {
+ return handlers[type].install;
+ }
+
+ events.emit('verbose', '<' + type + '> is not supported for android plugins');
+};
+
+module.exports.getUninstaller = function(type) {
+ if (handlers[type] && handlers[type].uninstall) {
+ return handlers[type].uninstall;
+ }
+
+ events.emit('verbose', '<' + type + '> is not supported for android plugins');
+};
+
+function copyFile (plugin_dir, src, project_dir, dest, link) {
+ src = path.resolve(plugin_dir, src);
+ if (!fs.existsSync(src)) throw new CordovaError('"' + src + '" not found!');
+
+ // 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('"' + src + '" not located within plugin!');
+
+ dest = path.resolve(project_dir, dest);
+
+ // check that dest path is located in project directory
+ if (dest.indexOf(project_dir) !== 0)
+ throw new CordovaError('"' + dest + '" not located within project!');
+
+ shell.mkdir('-p', path.dirname(dest));
+
+ if (link) {
+ fs.symlinkSync(path.relative(path.dirname(dest), 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);
+ } else {
+ shell.cp('-f', src, dest);
+ }
+}
+
+// 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!');
+
+ copyFile(plugin_dir, src, project_dir, dest, !!link);
+}
+
+// checks if file exists and then deletes. Error if doesn't exist
+function removeFile (project_dir, src) {
+ var file = path.resolve(project_dir, src);
+ shell.rm('-Rf', file);
+}
+
+// deletes file/directory without checking
+function removeFileF (file) {
+ shell.rm('-Rf', file);
+}
+
+// Sometimes we want to remove some java, and prune any unnecessary empty directories
+function deleteJava (project_dir, destFile) {
+ removeFileAndParents(project_dir, destFile, 'src');
+}
+
+function removeFileAndParents (baseDir, destFile, stopper) {
+ stopper = stopper || '.';
+ var file = path.resolve(baseDir, destFile);
+ if (!fs.existsSync(file)) return;
+
+ removeFileF(file);
+
+ // 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) {
+ fs.rmdirSync(curDir);
+ curDir = path.resolve(curDir, '..');
+ } else {
+ // directory not empty...do nothing
+ break;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/0ac822c5/bin/templates/cordova/lib/prepare.js
----------------------------------------------------------------------
diff --git a/bin/templates/cordova/lib/prepare.js b/bin/templates/cordova/lib/prepare.js
index 67ac174..a514c8c 100644
--- a/bin/templates/cordova/lib/prepare.js
+++ b/bin/templates/cordova/lib/prepare.js
@@ -1,364 +1,364 @@
-/**
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-var Q = require('q');
-var fs = require('fs');
-var path = require('path');
-var shell = require('shelljs');
-var events = require('cordova-common').events;
-var AndroidManifest = require('./AndroidManifest');
-var xmlHelpers = require('cordova-common').xmlHelpers;
-var CordovaError = require('cordova-common').CordovaError;
-var ConfigParser = require('cordova-common').ConfigParser;
-
-module.exports.prepare = function (cordovaProject) {
-
- var self = this;
-
- this._config = updateConfigFilesFrom(cordovaProject.projectConfig,
- this._munger, this.locations);
-
- // Update own www dir with project's www assets and plugins' assets and js-files
- return Q.when(updateWwwFrom(cordovaProject, this.locations))
- .then(function () {
- // update project according to config.xml changes.
- return updateProjectAccordingTo(self._config, self.locations);
- })
- .then(function () {
- handleIcons(cordovaProject.projectConfig, self.root);
- handleSplashes(cordovaProject.projectConfig, self.root);
- })
- .then(function () {
- self.events.emit('verbose', 'updated project successfully');
- });
-};
-
-/**
- * Updates config files in project based on app's config.xml and config munge,
- * generated by plugins.
- *
- * @param {ConfigParser} sourceConfig A project's configuration that will
- * be merged into platform's config.xml
- * @param {ConfigChanges} configMunger An initialized ConfigChanges instance
- * for this platform.
- * @param {Object} locations A map of locations for this platform
- *
- * @return {ConfigParser} An instance of ConfigParser, that
- * represents current project's configuration. When returned, the
- * configuration is already dumped to appropriate config.xml file.
- */
-function updateConfigFilesFrom(sourceConfig, configMunger, locations) {
- events.emit('verbose', 'Generating config.xml from defaults for platform "android"');
-
- // First cleanup current config and merge project's one into own
- // Overwrite platform config.xml with defaults.xml.
- shell.cp('-f', locations.defaultConfigXml, locations.configXml);
-
- // Then apply config changes from global munge to all config files
- // in project (including project's config)
- configMunger.reapply_global_munge().save_all();
-
- // 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.write();
- return config;
-}
-
-/**
- * Updates platform 'www' directory by replacing it with contents of
- * 'platform_www' and app www. Also copies project's overrides' folder into
- * the platform 'www' folder
- *
- * @param {Object} cordovaProject An object which describes cordova project.
- * @param {Object} destinations An object that contains destination
- * paths for www files.
- */
-function updateWwwFrom(cordovaProject, destinations) {
- shell.rm('-rf', destinations.www);
- shell.mkdir('-p', destinations.www);
- // Copy source files from project's www directory
- shell.cp('-rf', path.join(cordovaProject.locations.www, '*'), destinations.www);
- // Override www sources by files in 'platform_www' directory
- shell.cp('-rf', path.join(destinations.platformWww, '*'), destinations.www);
-
- // If project contains 'merges' for our platform, use them as another overrides
- var merges_path = path.join(cordovaProject.root, 'merges', 'android');
- if (fs.existsSync(merges_path)) {
- events.emit('verbose', 'Found "merges" for android platform. Copying over existing "www" files.');
- var overrides = path.join(merges_path, '*');
- shell.cp('-rf', overrides, destinations.www);
- }
-}
-
-/**
- * Updates project structure and AndroidManifest according to project's configuration.
- *
- * @param {ConfigParser} platformConfig A project's configuration that will
- * be used to update project
- * @param {Object} locations A map of locations for this platform
- */
-function updateProjectAccordingTo(platformConfig, locations) {
- // Update app name by editing res/values/strings.xml
- var name = platformConfig.name();
- var strings = xmlHelpers.parseElementtreeSync(locations.strings);
- strings.find('string[@name="app_name"]').text = name;
- fs.writeFileSync(locations.strings, strings.write({indent: 4}), 'utf-8');
- events.emit('verbose', 'Wrote out Android application name to "' + name + '"');
-
- // Java packages cannot support dashes
- var pkg = (platformConfig.android_packageName() || platformConfig.packageName()).replace(/-/g, '_');
-
- var manifest = new AndroidManifest(locations.manifest);
- var orig_pkg = manifest.getPackageId();
-
- manifest.getActivity()
- .setOrientation(findOrientationValue(platformConfig))
- .setLaunchMode(findAndroidLaunchModePreference(platformConfig));
-
- manifest.setVersionName(platformConfig.version())
- .setVersionCode(platformConfig.android_versionCode() || default_versionCode(platformConfig.version()))
- .setPackageId(pkg)
- .setMinSdkVersion(platformConfig.getPreference('android-minSdkVersion', 'android'))
- .setMaxSdkVersion(platformConfig.getPreference('android-maxSdkVersion', 'android'))
- .setTargetSdkVersion(platformConfig.getPreference('android-targetSdkVersion', 'android'))
- .write();
-
- var javaPattern = path.join(locations.root, 'src', orig_pkg.replace(/\./g, '/'), '*.java');
- var java_files = shell.ls(javaPattern).filter(function(f) {
- return shell.grep(/extends\s+CordovaActivity/g, f);
- });
-
- if (java_files.length === 0) {
- throw new CordovaError('No Java files found which extend CordovaActivity.');
- } else if(java_files.length > 1) {
- events.emit('log', 'Multiple candidate Java files (.java files which extend CordovaActivity) found. Guessing at the first one, ' + java_files[0]);
- }
-
- var destFile = path.join(locations.root, 'src', pkg.replace(/\./g, '/'), path.basename(java_files[0]));
- shell.mkdir('-p', path.dirname(destFile));
- shell.sed(/package [\w\.]*;/, 'package ' + pkg + ';', java_files[0]).to(destFile);
- events.emit('verbose', 'Wrote out Android package name to "' + pkg + '"');
-}
-
-
-// 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) {
- var nums = version.split('-')[0].split('.');
- var versionCode = 0;
- if (+nums[0]) {
- versionCode += +nums[0] * 10000;
- }
- if (+nums[1]) {
- versionCode += +nums[1] * 100;
- }
- if (+nums[2]) {
- versionCode += +nums[2];
- }
- return versionCode;
-}
-
-function copyImage(src, resourcesDir, density, name) {
- var destFolder = path.join(resourcesDir, (density ? 'drawable-': 'drawable') + density);
- var isNinePatch = !!/\.9\.png$/.exec(src);
- var ninePatchName = name.replace(/\.png$/, '.9.png');
-
- // default template does not have default asset for this density
- if (!fs.existsSync(destFolder)) {
- fs.mkdirSync(destFolder);
- }
-
- var destFilePath = path.join(destFolder, isNinePatch ? ninePatchName : name);
- events.emit('verbose', 'copying image from ' + src + ' to ' + destFilePath);
- shell.cp('-f', src, destFilePath);
-}
-
-function handleSplashes(projectConfig, platformRoot) {
- var resources = projectConfig.getSplashScreens('android');
- // if there are "splash" elements in config.xml
- if (resources.length > 0) {
- deleteDefaultResourceAt(platformRoot, 'screen.png');
- events.emit('verbose', 'splash screens: ' + JSON.stringify(resources));
-
- // The source paths for icons and splashes are relative to
- // project's config.xml location, so we use it as base path.
- var projectRoot = path.dirname(projectConfig.path);
- var destination = path.join(platformRoot, 'res');
-
- var hadMdpi = false;
- resources.forEach(function (resource) {
- if (!resource.density) {
- return;
- }
- if (resource.density == 'mdpi') {
- hadMdpi = true;
- }
- copyImage(path.join(projectRoot, resource.src), destination, resource.density, 'screen.png');
- });
- // There's no "default" drawable, so assume default == mdpi.
- if (!hadMdpi && resources.defaultResource) {
- copyImage(path.join(projectRoot, resources.defaultResource.src), destination, 'mdpi', 'screen.png');
- }
- }
-}
-
-function handleIcons(projectConfig, platformRoot) {
- var icons = projectConfig.getIcons('android');
-
- // if there are icon elements in config.xml
- if (icons.length === 0) {
- events.emit('verbose', 'This app does not have launcher icons defined');
- return;
- }
-
- deleteDefaultResourceAt(platformRoot, 'icon.png');
-
- var android_icons = {};
- var default_icon;
- // http://developer.android.com/design/style/iconography.html
- var sizeToDensityMap = {
- 36: 'ldpi',
- 48: 'mdpi',
- 72: 'hdpi',
- 96: 'xhdpi',
- 144: 'xxhdpi',
- 192: 'xxxhdpi'
- };
- // find the best matching icon for a given density or size
- // @output android_icons
- 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) {
- // invalid icon defition ( or unsupported size)
- return;
- }
- var previous = android_icons[density];
- if (previous && previous.platform) {
- return;
- }
- android_icons[density] = icon;
- };
-
- // iterate over all icon elements to find the default icon and call parseIcon
- for (var i=0; i<icons.length; i++) {
- var icon = icons[i];
- var size = icon.width;
- if (!size) {
- size = icon.height;
- }
- if (!size && !icon.density) {
- if (default_icon) {
- events.emit('verbose', 'more than one default icon: ' + JSON.stringify(icon));
- } else {
- default_icon = icon;
- }
- } else {
- parseIcon(icon, size);
- }
- }
-
- // The source paths for icons and splashes are relative to
- // project's config.xml location, so we use it as base path.
- var projectRoot = path.dirname(projectConfig.path);
- var destination = path.join(platformRoot, 'res');
- for (var density in android_icons) {
- copyImage(path.join(projectRoot, android_icons[density].src), destination, density, 'icon.png');
- }
- // There's no "default" drawable, so assume default == mdpi.
- if (default_icon && !android_icons.mdpi) {
- copyImage(path.join(projectRoot, default_icon.src), destination, 'mdpi', 'icon.png');
- }
-}
-
-// remove the default resource name from all drawable folders
-function deleteDefaultResourceAt(baseDir, resourceName) {
- shell.ls(path.join(baseDir, 'res/drawable-*'))
- .forEach(function (drawableFolder) {
- var imagePath = path.join(drawableFolder, resourceName);
- shell.rm('-f', [imagePath, imagePath.replace(/\.png$/, '.9.png')]);
- events.emit('verbose', 'Deleted ' + imagePath);
- });
-}
-
-/**
- * Gets and validates 'AndroidLaunchMode' prepference from config.xml. Returns
- * preference value and warns if it doesn't seems to be valid
- *
- * @param {ConfigParser} platformConfig A configParser instance for
- * platform.
- *
- * @return {String} Preference's value from config.xml or
- * default value, if there is no such preference. The default value is
- * 'singleTop'
- */
-function findAndroidLaunchModePreference(platformConfig) {
- var launchMode = platformConfig.getPreference('AndroidLaunchMode');
- if (!launchMode) {
- // Return a default value
- return 'singleTop';
- }
-
- var expectedValues = ['standard', 'singleTop', 'singleTask', 'singleInstance'];
- var valid = expectedValues.indexOf(launchMode) >= 0;
- if (!valid) {
- // Note: warn, but leave the launch mode as developer wanted, in case the list of options changes in the future
- events.emit('warn', 'Unrecognized value for AndroidLaunchMode preference: ' +
- launchMode + '. Expected values are: ' + expectedValues.join(', '));
- }
-
- return launchMode;
-}
-
-/**
- * Queries ConfigParser object for the orientation <preference> value. Warns if
- * global preference value is not supported by platform.
- *
- * @param {Object} platformConfig ConfigParser object
- *
- * @return {String} Global/platform-specific orientation in lower-case
- * (or empty string if both are undefined).
- */
-function findOrientationValue(platformConfig) {
-
- var ORIENTATION_DEFAULT = 'default';
-
- var orientation = platformConfig.getPreference('orientation');
- if (!orientation) {
- return ORIENTATION_DEFAULT;
- }
-
- var GLOBAL_ORIENTATIONS = ['default', 'portrait','landscape'];
- function isSupported(orientation) {
- return GLOBAL_ORIENTATIONS.indexOf(orientation.toLowerCase()) >= 0;
- }
-
- // Check if the given global orientation is supported
- if (orientation && isSupported(orientation)) {
- return orientation;
- }
-
- events.emit('warn', 'Unsupported global orientation: ' + orientation +
- '. Defaulting to value: ' + ORIENTATION_DEFAULT);
- return ORIENTATION_DEFAULT;
-}
+/**
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+var Q = require('q');
+var fs = require('fs');
+var path = require('path');
+var shell = require('shelljs');
+var events = require('cordova-common').events;
+var AndroidManifest = require('./AndroidManifest');
+var xmlHelpers = require('cordova-common').xmlHelpers;
+var CordovaError = require('cordova-common').CordovaError;
+var ConfigParser = require('cordova-common').ConfigParser;
+
+module.exports.prepare = function (cordovaProject) {
+
+ var self = this;
+
+ this._config = updateConfigFilesFrom(cordovaProject.projectConfig,
+ this._munger, this.locations);
+
+ // Update own www dir with project's www assets and plugins' assets and js-files
+ return Q.when(updateWwwFrom(cordovaProject, this.locations))
+ .then(function () {
+ // update project according to config.xml changes.
+ return updateProjectAccordingTo(self._config, self.locations);
+ })
+ .then(function () {
+ handleIcons(cordovaProject.projectConfig, self.root);
+ handleSplashes(cordovaProject.projectConfig, self.root);
+ })
+ .then(function () {
+ self.events.emit('verbose', 'updated project successfully');
+ });
+};
+
+/**
+ * Updates config files in project based on app's config.xml and config munge,
+ * generated by plugins.
+ *
+ * @param {ConfigParser} sourceConfig A project's configuration that will
+ * be merged into platform's config.xml
+ * @param {ConfigChanges} configMunger An initialized ConfigChanges instance
+ * for this platform.
+ * @param {Object} locations A map of locations for this platform
+ *
+ * @return {ConfigParser} An instance of ConfigParser, that
+ * represents current project's configuration. When returned, the
+ * configuration is already dumped to appropriate config.xml file.
+ */
+function updateConfigFilesFrom(sourceConfig, configMunger, locations) {
+ events.emit('verbose', 'Generating config.xml from defaults for platform "android"');
+
+ // First cleanup current config and merge project's one into own
+ // Overwrite platform config.xml with defaults.xml.
+ shell.cp('-f', locations.defaultConfigXml, locations.configXml);
+
+ // Then apply config changes from global munge to all config files
+ // in project (including project's config)
+ configMunger.reapply_global_munge().save_all();
+
+ // 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.write();
+ return config;
+}
+
+/**
+ * Updates platform 'www' directory by replacing it with contents of
+ * 'platform_www' and app www. Also copies project's overrides' folder into
+ * the platform 'www' folder
+ *
+ * @param {Object} cordovaProject An object which describes cordova project.
+ * @param {Object} destinations An object that contains destination
+ * paths for www files.
+ */
+function updateWwwFrom(cordovaProject, destinations) {
+ shell.rm('-rf', destinations.www);
+ shell.mkdir('-p', destinations.www);
+ // Copy source files from project's www directory
+ shell.cp('-rf', path.join(cordovaProject.locations.www, '*'), destinations.www);
+ // Override www sources by files in 'platform_www' directory
+ shell.cp('-rf', path.join(destinations.platformWww, '*'), destinations.www);
+
+ // If project contains 'merges' for our platform, use them as another overrides
+ var merges_path = path.join(cordovaProject.root, 'merges', 'android');
+ if (fs.existsSync(merges_path)) {
+ events.emit('verbose', 'Found "merges" for android platform. Copying over existing "www" files.');
+ var overrides = path.join(merges_path, '*');
+ shell.cp('-rf', overrides, destinations.www);
+ }
+}
+
+/**
+ * Updates project structure and AndroidManifest according to project's configuration.
+ *
+ * @param {ConfigParser} platformConfig A project's configuration that will
+ * be used to update project
+ * @param {Object} locations A map of locations for this platform
+ */
+function updateProjectAccordingTo(platformConfig, locations) {
+ // Update app name by editing res/values/strings.xml
+ var name = platformConfig.name();
+ var strings = xmlHelpers.parseElementtreeSync(locations.strings);
+ strings.find('string[@name="app_name"]').text = name;
+ fs.writeFileSync(locations.strings, strings.write({indent: 4}), 'utf-8');
+ events.emit('verbose', 'Wrote out Android application name to "' + name + '"');
+
+ // Java packages cannot support dashes
+ var pkg = (platformConfig.android_packageName() || platformConfig.packageName()).replace(/-/g, '_');
+
+ var manifest = new AndroidManifest(locations.manifest);
+ var orig_pkg = manifest.getPackageId();
+
+ manifest.getActivity()
+ .setOrientation(findOrientationValue(platformConfig))
+ .setLaunchMode(findAndroidLaunchModePreference(platformConfig));
+
+ manifest.setVersionName(platformConfig.version())
+ .setVersionCode(platformConfig.android_versionCode() || default_versionCode(platformConfig.version()))
+ .setPackageId(pkg)
+ .setMinSdkVersion(platformConfig.getPreference('android-minSdkVersion', 'android'))
+ .setMaxSdkVersion(platformConfig.getPreference('android-maxSdkVersion', 'android'))
+ .setTargetSdkVersion(platformConfig.getPreference('android-targetSdkVersion', 'android'))
+ .write();
+
+ var javaPattern = path.join(locations.root, 'src', orig_pkg.replace(/\./g, '/'), '*.java');
+ var java_files = shell.ls(javaPattern).filter(function(f) {
+ return shell.grep(/extends\s+CordovaActivity/g, f);
+ });
+
+ if (java_files.length === 0) {
+ throw new CordovaError('No Java files found which extend CordovaActivity.');
+ } else if(java_files.length > 1) {
+ events.emit('log', 'Multiple candidate Java files (.java files which extend CordovaActivity) found. Guessing at the first one, ' + java_files[0]);
+ }
+
+ var destFile = path.join(locations.root, 'src', pkg.replace(/\./g, '/'), path.basename(java_files[0]));
+ shell.mkdir('-p', path.dirname(destFile));
+ shell.sed(/package [\w\.]*;/, 'package ' + pkg + ';', java_files[0]).to(destFile);
+ events.emit('verbose', 'Wrote out Android package name to "' + pkg + '"');
+}
+
+
+// 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) {
+ var nums = version.split('-')[0].split('.');
+ var versionCode = 0;
+ if (+nums[0]) {
+ versionCode += +nums[0] * 10000;
+ }
+ if (+nums[1]) {
+ versionCode += +nums[1] * 100;
+ }
+ if (+nums[2]) {
+ versionCode += +nums[2];
+ }
+ return versionCode;
+}
+
+function copyImage(src, resourcesDir, density, name) {
+ var destFolder = path.join(resourcesDir, (density ? 'drawable-': 'drawable') + density);
+ var isNinePatch = !!/\.9\.png$/.exec(src);
+ var ninePatchName = name.replace(/\.png$/, '.9.png');
+
+ // default template does not have default asset for this density
+ if (!fs.existsSync(destFolder)) {
+ fs.mkdirSync(destFolder);
+ }
+
+ var destFilePath = path.join(destFolder, isNinePatch ? ninePatchName : name);
+ events.emit('verbose', 'copying image from ' + src + ' to ' + destFilePath);
+ shell.cp('-f', src, destFilePath);
+}
+
+function handleSplashes(projectConfig, platformRoot) {
+ var resources = projectConfig.getSplashScreens('android');
+ // if there are "splash" elements in config.xml
+ if (resources.length > 0) {
+ deleteDefaultResourceAt(platformRoot, 'screen.png');
+ events.emit('verbose', 'splash screens: ' + JSON.stringify(resources));
+
+ // The source paths for icons and splashes are relative to
+ // project's config.xml location, so we use it as base path.
+ var projectRoot = path.dirname(projectConfig.path);
+ var destination = path.join(platformRoot, 'res');
+
+ var hadMdpi = false;
+ resources.forEach(function (resource) {
+ if (!resource.density) {
+ return;
+ }
+ if (resource.density == 'mdpi') {
+ hadMdpi = true;
+ }
+ copyImage(path.join(projectRoot, resource.src), destination, resource.density, 'screen.png');
+ });
+ // There's no "default" drawable, so assume default == mdpi.
+ if (!hadMdpi && resources.defaultResource) {
+ copyImage(path.join(projectRoot, resources.defaultResource.src), destination, 'mdpi', 'screen.png');
+ }
+ }
+}
+
+function handleIcons(projectConfig, platformRoot) {
+ var icons = projectConfig.getIcons('android');
+
+ // if there are icon elements in config.xml
+ if (icons.length === 0) {
+ events.emit('verbose', 'This app does not have launcher icons defined');
+ return;
+ }
+
+ deleteDefaultResourceAt(platformRoot, 'icon.png');
+
+ var android_icons = {};
+ var default_icon;
+ // http://developer.android.com/design/style/iconography.html
+ var sizeToDensityMap = {
+ 36: 'ldpi',
+ 48: 'mdpi',
+ 72: 'hdpi',
+ 96: 'xhdpi',
+ 144: 'xxhdpi',
+ 192: 'xxxhdpi'
+ };
+ // find the best matching icon for a given density or size
+ // @output android_icons
+ 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) {
+ // invalid icon defition ( or unsupported size)
+ return;
+ }
+ var previous = android_icons[density];
+ if (previous && previous.platform) {
+ return;
+ }
+ android_icons[density] = icon;
+ };
+
+ // iterate over all icon elements to find the default icon and call parseIcon
+ for (var i=0; i<icons.length; i++) {
+ var icon = icons[i];
+ var size = icon.width;
+ if (!size) {
+ size = icon.height;
+ }
+ if (!size && !icon.density) {
+ if (default_icon) {
+ events.emit('verbose', 'more than one default icon: ' + JSON.stringify(icon));
+ } else {
+ default_icon = icon;
+ }
+ } else {
+ parseIcon(icon, size);
+ }
+ }
+
+ // The source paths for icons and splashes are relative to
+ // project's config.xml location, so we use it as base path.
+ var projectRoot = path.dirname(projectConfig.path);
+ var destination = path.join(platformRoot, 'res');
+ for (var density in android_icons) {
+ copyImage(path.join(projectRoot, android_icons[density].src), destination, density, 'icon.png');
+ }
+ // There's no "default" drawable, so assume default == mdpi.
+ if (default_icon && !android_icons.mdpi) {
+ copyImage(path.join(projectRoot, default_icon.src), destination, 'mdpi', 'icon.png');
+ }
+}
+
+// remove the default resource name from all drawable folders
+function deleteDefaultResourceAt(baseDir, resourceName) {
+ shell.ls(path.join(baseDir, 'res/drawable-*'))
+ .forEach(function (drawableFolder) {
+ var imagePath = path.join(drawableFolder, resourceName);
+ shell.rm('-f', [imagePath, imagePath.replace(/\.png$/, '.9.png')]);
+ events.emit('verbose', 'Deleted ' + imagePath);
+ });
+}
+
+/**
+ * Gets and validates 'AndroidLaunchMode' prepference from config.xml. Returns
+ * preference value and warns if it doesn't seems to be valid
+ *
+ * @param {ConfigParser} platformConfig A configParser instance for
+ * platform.
+ *
+ * @return {String} Preference's value from config.xml or
+ * default value, if there is no such preference. The default value is
+ * 'singleTop'
+ */
+function findAndroidLaunchModePreference(platformConfig) {
+ var launchMode = platformConfig.getPreference('AndroidLaunchMode');
+ if (!launchMode) {
+ // Return a default value
+ return 'singleTop';
+ }
+
+ var expectedValues = ['standard', 'singleTop', 'singleTask', 'singleInstance'];
+ var valid = expectedValues.indexOf(launchMode) >= 0;
+ if (!valid) {
+ // Note: warn, but leave the launch mode as developer wanted, in case the list of options changes in the future
+ events.emit('warn', 'Unrecognized value for AndroidLaunchMode preference: ' +
+ launchMode + '. Expected values are: ' + expectedValues.join(', '));
+ }
+
+ return launchMode;
+}
+
+/**
+ * Queries ConfigParser object for the orientation <preference> value. Warns if
+ * global preference value is not supported by platform.
+ *
+ * @param {Object} platformConfig ConfigParser object
+ *
+ * @return {String} Global/platform-specific orientation in lower-case
+ * (or empty string if both are undefined).
+ */
+function findOrientationValue(platformConfig) {
+
+ var ORIENTATION_DEFAULT = 'default';
+
+ var orientation = platformConfig.getPreference('orientation');
+ if (!orientation) {
+ return ORIENTATION_DEFAULT;
+ }
+
+ var GLOBAL_ORIENTATIONS = ['default', 'portrait','landscape'];
+ function isSupported(orientation) {
+ return GLOBAL_ORIENTATIONS.indexOf(orientation.toLowerCase()) >= 0;
+ }
+
+ // Check if the given global orientation is supported
+ if (orientation && isSupported(orientation)) {
+ return orientation;
+ }
+
+ events.emit('warn', 'Unsupported global orientation: ' + orientation +
+ '. Defaulting to value: ' + ORIENTATION_DEFAULT);
+ return ORIENTATION_DEFAULT;
+}
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/0ac822c5/bin/update
----------------------------------------------------------------------
diff --git a/bin/update b/bin/update
index 4000df2..861c8d0 100755
--- a/bin/update
+++ b/bin/update
@@ -1,35 +1,35 @@
-#!/usr/bin/env node
-
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-var path = require('path');
-var Api = require('./templates/cordova/Api');
-var args = require('nopt')({
- 'link': Boolean,
- 'shared': Boolean,
- 'help': Boolean
-});
-
-if (args.help || args.argv.remain.length === 0) {
- console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'update')) + ' <path_to_project> [--link]');
- console.log(' --link will use the CordovaLib project directly instead of making a copy.');
- process.exit(1);
-}
-
-Api.updatePlatform(args.argv.remain[0], {link: (args.link || args.shared)}).done();
+#!/usr/bin/env node
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+var path = require('path');
+var Api = require('./templates/cordova/Api');
+var args = require('nopt')({
+ 'link': Boolean,
+ 'shared': Boolean,
+ 'help': Boolean
+});
+
+if (args.help || args.argv.remain.length === 0) {
+ console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'update')) + ' <path_to_project> [--link]');
+ console.log(' --link will use the CordovaLib project directly instead of making a copy.');
+ process.exit(1);
+}
+
+Api.updatePlatform(args.argv.remain[0], {link: (args.link || args.shared)}).done();
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/0ac822c5/package.json
----------------------------------------------------------------------
diff --git a/package.json b/package.json
index f49ca79..de7e9aa 100644
--- a/package.json
+++ b/package.json
@@ -1,46 +1,46 @@
-{
- "name": "cordova-android",
- "version": "5.0.0-dev",
- "description": "cordova-android release",
- "bin": {
- "create": "bin/create"
- },
- "main": "bin/templates/cordova/Api.js",
- "repository": {
- "type": "git",
- "url": "https://git-wip-us.apache.org/repos/asf/cordova-android.git"
- },
- "keywords": [
- "android",
- "cordova",
- "apache"
- ],
- "scripts": {
- "test": "npm run jshint && jasmine-node --color spec",
- "test-build": "rm -rf \"test create\" && node ./bin/create \"test create\" com.test.app 応用 && \"./test create/cordova/build\" && rm -rf \"test create\"",
- "jshint": "node node_modules/jshint/bin/jshint bin && node node_modules/jshint/bin/jshint spec"
- },
- "author": "Apache Software Foundation",
- "license": "Apache version 2.0",
- "dependencies": {
- "cordova-common": "^0.1.0",
- "elementtree": "^0.1.6",
- "nopt": "^3.0.1",
- "properties-parser": "^0.3.0",
- "q": "^1.4.1",
- "shelljs": "^0.5.3"
- },
- "bundledDependencies": [
- "cordova-common",
- "elementtree",
- "nopt",
- "properties-parser",
- "q",
- "shelljs"
- ],
- "devDependencies": {
- "jasmine-node": "^1.14.5",
- "jshint": "^2.6.0",
- "promise-matchers": "~0"
- }
-}
+{
+ "name": "cordova-android",
+ "version": "5.0.0-dev",
+ "description": "cordova-android release",
+ "bin": {
+ "create": "bin/create"
+ },
+ "main": "bin/templates/cordova/Api.js",
+ "repository": {
+ "type": "git",
+ "url": "https://git-wip-us.apache.org/repos/asf/cordova-android.git"
+ },
+ "keywords": [
+ "android",
+ "cordova",
+ "apache"
+ ],
+ "scripts": {
+ "test": "npm run jshint && jasmine-node --color spec",
+ "test-build": "rm -rf \"test create\" && node ./bin/create \"test create\" com.test.app 応用 && \"./test create/cordova/build\" && rm -rf \"test create\"",
+ "jshint": "node node_modules/jshint/bin/jshint bin && node node_modules/jshint/bin/jshint spec"
+ },
+ "author": "Apache Software Foundation",
+ "license": "Apache version 2.0",
+ "dependencies": {
+ "cordova-common": "^0.1.0",
+ "elementtree": "^0.1.6",
+ "nopt": "^3.0.1",
+ "properties-parser": "^0.3.0",
+ "q": "^1.4.1",
+ "shelljs": "^0.5.3"
+ },
+ "bundledDependencies": [
+ "cordova-common",
+ "elementtree",
+ "nopt",
+ "properties-parser",
+ "q",
+ "shelljs"
+ ],
+ "devDependencies": {
+ "jasmine-node": "^1.14.5",
+ "jshint": "^2.6.0",
+ "promise-matchers": "~0"
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org
[3/4] android commit: Fixed line endings
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/0ac822c5/bin/templates/cordova/Api.js
----------------------------------------------------------------------
diff --git a/bin/templates/cordova/Api.js b/bin/templates/cordova/Api.js
index 62899ef..7b7731f 100644
--- a/bin/templates/cordova/Api.js
+++ b/bin/templates/cordova/Api.js
@@ -1,492 +1,492 @@
-/**
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-var Q = require('q');
-var fs = require('fs');
-var path = require('path');
-var shell = require('shelljs');
-
-var CordovaError = require('cordova-common').CordovaError;
-var PlatformJson = require('cordova-common').PlatformJson;
-var ActionStack = require('cordova-common').ActionStack;
-var AndroidProject = require('./lib/AndroidProject');
-var PlatformMunger = require('cordova-common').ConfigChanges.PlatformMunger;
-var PluginInfoProvider = require('cordova-common').PluginInfoProvider;
-
-var ConsoleLogger = require('./lib/ConsoleLogger');
-var pluginHandlers = require('./lib/pluginHandlers');
-
-var PLATFORM = 'android';
-
-/**
- * Class, that acts as abstraction over particular platform. Encapsulates the
- * platform's properties and methods.
- *
- * Platform that implements own PlatformApi instance _should implement all
- * prototype methods_ of this class to be fully compatible with cordova-lib.
- *
- * The PlatformApi instance also should define the following field:
- *
- * * platform: String that defines a platform name.
- */
-function Api(platform, platformRootDir, events) {
- this.platform = PLATFORM;
- this.root = path.resolve(__dirname, '..');
- this.events = events || ConsoleLogger.get();
- // NOTE: trick to share one EventEmitter instance across all js code
- require('cordova-common').events = this.events;
-
- this._platformJson = PlatformJson.load(this.root, platform);
- this._pluginInfoProvider = new PluginInfoProvider();
- this._munger = new PlatformMunger(this.platform, this.root, this._platformJson, this._pluginInfoProvider);
-
- var self = this;
-
- this.locations = {
- root: self.root,
- www: path.join(self.root, 'assets/www'),
- platformWww: path.join(self.root, 'platform_www'),
- configXml: path.join(self.root, 'res/xml/config.xml'),
- defaultConfigXml: path.join(self.root, 'cordova/defaults.xml'),
- strings: path.join(self.root, 'res/values/strings.xml'),
- manifest: path.join(self.root, 'AndroidManifest.xml'),
- // NOTE: Due to platformApi spec we need to return relative paths here
- cordovaJs: 'bin/templates/project/assets/www/cordova.js',
- cordovaJsSrc: 'cordova-js-src'
- };
-}
-
-/**
- * Installs platform to specified directory and creates a platform project.
- *
- * @param {String} destination Destination directory, where insatll platform to
- * @param {ConfigParser} [config] ConfgiParser instance, used to retrieve
- * project creation options, such as package id and project name.
- * @param {Object} [options] An options object. The most common options are:
- * @param {String} [options.customTemplate] A path to custom template, that
- * should override the default one from platform.
- * @param {Boolean} [options.link] Flag that indicates that platform's
- * sources will be linked to installed platform instead of copying.
- * @param {EventEmitter} [events] An EventEmitter instance that will be used for
- * logging purposes. If no EventEmitter provided, all events will be logged to
- * console
- *
- * @return {Promise<PlatformApi>} Promise either fulfilled with PlatformApi
- * instance or rejected with CordovaError.
- */
-Api.createPlatform = function (destination, config, options, events) {
- return require('../../lib/create')
- .create(destination, config, options, events || ConsoleLogger.get())
- .then(function (destination) {
- var PlatformApi = require(path.resolve(destination, 'cordova/Api'));
- return new PlatformApi(PLATFORM, destination, events);
- });
-};
-
-/**
- * Updates already installed platform.
- *
- * @param {String} destination Destination directory, where platform installed
- * @param {Object} [options] An options object. The most common options are:
- * @param {String} [options.customTemplate] A path to custom template, that
- * should override the default one from platform.
- * @param {Boolean} [options.link] Flag that indicates that platform's
- * sources will be linked to installed platform instead of copying.
- * @param {EventEmitter} [events] An EventEmitter instance that will be used for
- * logging purposes. If no EventEmitter provided, all events will be logged to
- * console
- *
- * @return {Promise<PlatformApi>} Promise either fulfilled with PlatformApi
- * instance or rejected with CordovaError.
- */
-Api.updatePlatform = function (destination, options, events) {
- return require('../../lib/create')
- .update(destination, options, events || ConsoleLogger.get())
- .then(function (destination) {
- var PlatformApi = require(path.resolve(destination, 'cordova/Api'));
- return new PlatformApi('android', destination, events);
- });
-};
-
-/**
- * Gets a CordovaPlatform object, that represents the platform structure.
- *
- * @return {CordovaPlatform} A structure that contains the description of
- * platform's file structure and other properties of platform.
- */
-Api.prototype.getPlatformInfo = function () {
- var result = {};
- result.locations = this.locations;
- result.root = this.root;
- result.name = this.platform;
- result.version = require('./version');
- result.projectConfig = this._config;
-
- return result;
-};
-
-/**
- * Updates installed platform with provided www assets and new app
- * configuration. This method is required for CLI workflow and will be called
- * each time before build, so the changes, made to app configuration and www
- * code, will be applied to platform.
- *
- * @param {CordovaProject} cordovaProject A CordovaProject instance, that defines a
- * project structure and configuration, that should be applied to platform
- * (contains project's www location and ConfigParser instance for project's
- * config).
- *
- * @return {Promise} Return a promise either fulfilled, or rejected with
- * CordovaError instance.
- */
-Api.prototype.prepare = function (cordovaProject) {
- return require('./lib/prepare').prepare.call(this, cordovaProject);
-};
-
-/**
- * Installs a new plugin into platform. This method only copies non-www files
- * (sources, libs, etc.) to platform. It also doesn't resolves the
- * dependencies of plugin. Both of handling of www files, such as assets and
- * js-files and resolving dependencies are the responsibility of caller.
- *
- * @param {PluginInfo} plugin A PluginInfo instance that represents plugin
- * that will be installed.
- * @param {Object} installOptions An options object. Possible options below:
- * @param {Boolean} installOptions.link: Flag that specifies that plugin
- * sources will be symlinked to app's directory instead of copying (if
- * possible).
- * @param {Object} installOptions.variables An object that represents
- * variables that will be used to install plugin. See more details on plugin
- * variables in documentation:
- * https://cordova.apache.org/docs/en/4.0.0/plugin_ref_spec.md.html
- *
- * @return {Promise} Return a promise either fulfilled, or rejected with
- * CordovaError instance.
- */
-Api.prototype.addPlugin = function (plugin, installOptions) {
-
- if (!plugin || plugin.constructor.name !== 'PluginInfo')
- return Q.reject(new CordovaError('The parameter is incorrect. The first parameter to addPlugin should be a PluginInfo instance'));
-
- installOptions = installOptions || {};
- installOptions.variables = installOptions.variables || {};
-
- var self = this;
- var actions = new ActionStack();
- var project = AndroidProject.getProjectFile(this.root);
-
- // gather all files needs to be handled during install
- plugin.getFilesAndFrameworks(this.platform)
- .concat(plugin.getAssets(this.platform))
- .concat(plugin.getJsModules(this.platform))
- .forEach(function(item) {
- actions.push(actions.createAction(
- pluginHandlers.getInstaller(item.itemType), [item, plugin, project, installOptions],
- pluginHandlers.getUninstaller(item.itemType), [item, plugin, project, installOptions]));
- });
-
- // run through the action stack
- return actions.process(this.platform)
- .then(function () {
- if (project) {
- project.write();
- }
-
- // Add PACKAGE_NAME variable into vars
- if (!installOptions.variables.PACKAGE_NAME) {
- installOptions.variables.PACKAGE_NAME = project.getPackageName();
- }
-
- self._munger
- // Ignore passed `is_top_level` option since platform itself doesn't know
- // anything about managing dependencies - it's responsibility of caller.
- .add_plugin_changes(plugin, installOptions.variables, /*is_top_level=*/true, /*should_increment=*/true)
- .save_all();
-
- var targetDir = installOptions.usePlatformWww ?
- self.locations.platformWww :
- self.locations.www;
-
- self._addModulesInfo(plugin, targetDir);
- });
-};
-
-/**
- * Removes an installed plugin from platform.
- *
- * Since method accepts PluginInfo instance as input parameter instead of plugin
- * id, caller shoud take care of managing/storing PluginInfo instances for
- * future uninstalls.
- *
- * @param {PluginInfo} plugin A PluginInfo instance that represents plugin
- * that will be installed.
- *
- * @return {Promise} Return a promise either fulfilled, or rejected with
- * CordovaError instance.
- */
-Api.prototype.removePlugin = function (plugin, uninstallOptions) {
-
- if (!plugin || plugin.constructor.name !== 'PluginInfo')
- return Q.reject(new CordovaError('The parameter is incorrect. The first parameter to addPlugin should be a PluginInfo instance'));
-
- var self = this;
- var actions = new ActionStack();
- var project = AndroidProject.getProjectFile(this.root);
-
- // queue up plugin files
- plugin.getFilesAndFrameworks(this.platform)
- .concat(plugin.getAssets(this.platform))
- .concat(plugin.getJsModules(this.platform))
- .forEach(function(item) {
- actions.push(actions.createAction(
- pluginHandlers.getUninstaller(item.itemType), [item, plugin, project, uninstallOptions],
- pluginHandlers.getInstaller(item.itemType), [item, plugin, project, uninstallOptions]));
- });
-
- // run through the action stack
- return actions.process(this.platform)
- .then(function() {
- if (project) {
- project.write();
- }
-
- self._munger
- // Ignore passed `is_top_level` option since platform itself doesn't know
- // anything about managing dependencies - it's responsibility of caller.
- .remove_plugin_changes(plugin, /*is_top_level=*/true)
- .save_all();
-
- var targetDir = uninstallOptions.usePlatformWww ?
- self.locations.platformWww :
- self.locations.www;
-
- self._removeModulesInfo(plugin, targetDir);
- });
-};
-
-/**
- * Builds an application package for current platform.
- *
- * @param {Object} buildOptions A build options. This object's structure is
- * highly depends on platform's specific. The most common options are:
- * @param {Boolean} buildOptions.debug Indicates that packages should be
- * built with debug configuration. This is set to true by default unless the
- * 'release' option is not specified.
- * @param {Boolean} buildOptions.release Indicates that packages should be
- * built with release configuration. If not set to true, debug configuration
- * will be used.
- * @param {Boolean} buildOptions.device Specifies that built app is intended
- * to run on device
- * @param {Boolean} buildOptions.emulator: Specifies that built app is
- * intended to run on emulator
- * @param {String} buildOptions.target Specifies the device id that will be
- * used to run built application.
- * @param {Boolean} buildOptions.nobuild Indicates that this should be a
- * dry-run call, so no build artifacts will be produced.
- * @param {String[]} buildOptions.archs Specifies chip architectures which
- * app packages should be built for. List of valid architectures is depends on
- * platform.
- * @param {String} buildOptions.buildConfig The path to build configuration
- * file. The format of this file is depends on platform.
- * @param {String[]} buildOptions.argv Raw array of command-line arguments,
- * passed to `build` command. The purpose of this property is to pass a
- * platform-specific arguments, and eventually let platform define own
- * arguments processing logic.
- *
- * @return {Promise<Object[]>} A promise either fulfilled with an array of build
- * artifacts (application packages) if package was built successfully,
- * or rejected with CordovaError. The resultant build artifact objects is not
- * strictly typed and may conatin arbitrary set of fields as in sample below.
- *
- * {
- * architecture: 'x86',
- * buildType: 'debug',
- * path: '/path/to/build',
- * type: 'app'
- * }
- *
- * The return value in most cases will contain only one item but in some cases
- * there could be multiple items in output array, e.g. when multiple
- * arhcitectures is specified.
- */
-Api.prototype.build = function (buildOptions) {
- var self = this;
- return require('./lib/check_reqs').run()
- .then(function () {
- return require('./lib/build').run.call(self, buildOptions);
- })
- .then(function (buildResults) {
- // Cast build result to array of build artifacts
- return buildResults.apkPaths.map(function (apkPath) {
- return {
- buildType: buildResults.buildType,
- buildMethod: buildResults.buildMethod,
- path: apkPath,
- type: 'apk'
- };
- });
- });
-};
-
-/**
- * Builds an application package for current platform and runs it on
- * specified/default device. If no 'device'/'emulator'/'target' options are
- * specified, then tries to run app on default device if connected, otherwise
- * runs the app on emulator.
- *
- * @param {Object} runOptions An options object. The structure is the same
- * as for build options.
- *
- * @return {Promise} A promise either fulfilled if package was built and ran
- * successfully, or rejected with CordovaError.
- */
-Api.prototype.run = function(runOptions) {
- var self = this;
- return require('./lib/check_reqs').run()
- .then(function () {
- return require('./lib/run').run.call(self, runOptions);
- });
-};
-
-/**
- * Cleans out the build artifacts from platform's directory.
- *
- * @return {Promise} Return a promise either fulfilled, or rejected with
- * CordovaError.
- */
-Api.prototype.clean = function(cleanOptions) {
- var self = this;
- return require('./lib/check_reqs').run()
- .then(function () {
- return require('./lib/build').runClean.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
- * built successfully.
- *
- * @return {Promise<Requirement[]>} Promise, resolved with set of Requirement
- * objects for current platform.
- */
-Api.prototype.requirements = function() {
- return require('./lib/check_reqs').check_all();
-};
-
-module.exports = Api;
-
-/**
- * Removes the specified modules from list of installed modules and updates
- * platform_json and cordova_plugins.js on disk.
- *
- * @param {PluginInfo} plugin PluginInfo instance for plugin, which modules
- * needs to be added.
- * @param {String} targetDir The directory, where updated cordova_plugins.js
- * should be written to.
- */
-Api.prototype._addModulesInfo = function(plugin, targetDir) {
- var installedModules = this._platformJson.root.modules || [];
-
- var installedPaths = installedModules.map(function (installedModule) {
- return installedModule.file;
- });
-
- var modulesToInstall = plugin.getJsModules(this.platform)
- .filter(function (moduleToInstall) {
- return installedPaths.indexOf(moduleToInstall.file) === -1;
- }).map(function (moduleToInstall) {
- var moduleName = plugin.id + '.' + ( moduleToInstall.name || moduleToInstall.src.match(/([^\/]+)\.js/)[1] );
- var obj = {
- file: ['plugins', plugin.id, moduleToInstall.src].join('/'),
- id: moduleName
- };
- if (moduleToInstall.clobbers.length > 0) {
- obj.clobbers = moduleToInstall.clobbers.map(function(o) { return o.target; });
- }
- if (moduleToInstall.merges.length > 0) {
- obj.merges = moduleToInstall.merges.map(function(o) { return o.target; });
- }
- if (moduleToInstall.runs) {
- obj.runs = true;
- }
-
- return obj;
- });
-
- this._platformJson.root.modules = installedModules.concat(modulesToInstall);
- this._writePluginModules(targetDir);
- this._platformJson.save();
-};
-
-/**
- * Removes the specified modules from list of installed modules and updates
- * platform_json and cordova_plugins.js on disk.
- *
- * @param {PluginInfo} plugin PluginInfo instance for plugin, which modules
- * needs to be removed.
- * @param {String} targetDir The directory, where updated cordova_plugins.js
- * should be written to.
- */
-Api.prototype._removeModulesInfo = function(plugin, targetDir) {
- var installedModules = this._platformJson.root.modules || [];
- var modulesToRemove = plugin.getJsModules(this.platform)
- .map(function (jsModule) {
- return ['plugins', plugin.id, jsModule.src].join('/');
- });
-
- var updatedModules = installedModules
- .filter(function (installedModule) {
- return (modulesToRemove.indexOf(installedModule.file) === -1);
- });
-
- this._platformJson.root.modules = updatedModules;
- this._writePluginModules(targetDir);
- this._platformJson.save();
-};
-
-/**
- * Fetches all installed modules, generates cordova_plugins contents and writes
- * it to file.
- *
- * @param {String} targetDir Directory, where write cordova_plugins.js to.
- * Ususally it is either <platform>/www or <platform>/platform_www
- * directories.
- */
-Api.prototype._writePluginModules = function (targetDir) {
- var self = this;
- // Write out moduleObjects as JSON wrapped in a cordova module to cordova_plugins.js
- var final_contents = 'cordova.define(\'cordova/plugin_list\', function(require, exports, module) {\n';
- final_contents += 'module.exports = ' + JSON.stringify(this._platformJson.root.modules, null, ' ') + ';\n';
- final_contents += 'module.exports.metadata = \n';
- final_contents += '// TOP OF METADATA\n';
-
- var pluginMetadata = Object.keys(this._platformJson.root.installed_plugins)
- .reduce(function (metadata, plugin) {
- metadata[plugin] = self._platformJson.root.installed_plugins[plugin].version;
- return metadata;
- }, {});
-
- final_contents += JSON.stringify(pluginMetadata, null, 4) + '\n';
- final_contents += '// BOTTOM OF METADATA\n';
- final_contents += '});'; // Close cordova.define.
-
- shell.mkdir('-p', targetDir);
- fs.writeFileSync(path.join(targetDir, 'cordova_plugins.js'), final_contents, 'utf-8');
-};
+/**
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+var Q = require('q');
+var fs = require('fs');
+var path = require('path');
+var shell = require('shelljs');
+
+var CordovaError = require('cordova-common').CordovaError;
+var PlatformJson = require('cordova-common').PlatformJson;
+var ActionStack = require('cordova-common').ActionStack;
+var AndroidProject = require('./lib/AndroidProject');
+var PlatformMunger = require('cordova-common').ConfigChanges.PlatformMunger;
+var PluginInfoProvider = require('cordova-common').PluginInfoProvider;
+
+var ConsoleLogger = require('./lib/ConsoleLogger');
+var pluginHandlers = require('./lib/pluginHandlers');
+
+var PLATFORM = 'android';
+
+/**
+ * Class, that acts as abstraction over particular platform. Encapsulates the
+ * platform's properties and methods.
+ *
+ * Platform that implements own PlatformApi instance _should implement all
+ * prototype methods_ of this class to be fully compatible with cordova-lib.
+ *
+ * The PlatformApi instance also should define the following field:
+ *
+ * * platform: String that defines a platform name.
+ */
+function Api(platform, platformRootDir, events) {
+ this.platform = PLATFORM;
+ this.root = path.resolve(__dirname, '..');
+ this.events = events || ConsoleLogger.get();
+ // NOTE: trick to share one EventEmitter instance across all js code
+ require('cordova-common').events = this.events;
+
+ this._platformJson = PlatformJson.load(this.root, platform);
+ this._pluginInfoProvider = new PluginInfoProvider();
+ this._munger = new PlatformMunger(this.platform, this.root, this._platformJson, this._pluginInfoProvider);
+
+ var self = this;
+
+ this.locations = {
+ root: self.root,
+ www: path.join(self.root, 'assets/www'),
+ platformWww: path.join(self.root, 'platform_www'),
+ configXml: path.join(self.root, 'res/xml/config.xml'),
+ defaultConfigXml: path.join(self.root, 'cordova/defaults.xml'),
+ strings: path.join(self.root, 'res/values/strings.xml'),
+ manifest: path.join(self.root, 'AndroidManifest.xml'),
+ // NOTE: Due to platformApi spec we need to return relative paths here
+ cordovaJs: 'bin/templates/project/assets/www/cordova.js',
+ cordovaJsSrc: 'cordova-js-src'
+ };
+}
+
+/**
+ * Installs platform to specified directory and creates a platform project.
+ *
+ * @param {String} destination Destination directory, where insatll platform to
+ * @param {ConfigParser} [config] ConfgiParser instance, used to retrieve
+ * project creation options, such as package id and project name.
+ * @param {Object} [options] An options object. The most common options are:
+ * @param {String} [options.customTemplate] A path to custom template, that
+ * should override the default one from platform.
+ * @param {Boolean} [options.link] Flag that indicates that platform's
+ * sources will be linked to installed platform instead of copying.
+ * @param {EventEmitter} [events] An EventEmitter instance that will be used for
+ * logging purposes. If no EventEmitter provided, all events will be logged to
+ * console
+ *
+ * @return {Promise<PlatformApi>} Promise either fulfilled with PlatformApi
+ * instance or rejected with CordovaError.
+ */
+Api.createPlatform = function (destination, config, options, events) {
+ return require('../../lib/create')
+ .create(destination, config, options, events || ConsoleLogger.get())
+ .then(function (destination) {
+ var PlatformApi = require(path.resolve(destination, 'cordova/Api'));
+ return new PlatformApi(PLATFORM, destination, events);
+ });
+};
+
+/**
+ * Updates already installed platform.
+ *
+ * @param {String} destination Destination directory, where platform installed
+ * @param {Object} [options] An options object. The most common options are:
+ * @param {String} [options.customTemplate] A path to custom template, that
+ * should override the default one from platform.
+ * @param {Boolean} [options.link] Flag that indicates that platform's
+ * sources will be linked to installed platform instead of copying.
+ * @param {EventEmitter} [events] An EventEmitter instance that will be used for
+ * logging purposes. If no EventEmitter provided, all events will be logged to
+ * console
+ *
+ * @return {Promise<PlatformApi>} Promise either fulfilled with PlatformApi
+ * instance or rejected with CordovaError.
+ */
+Api.updatePlatform = function (destination, options, events) {
+ return require('../../lib/create')
+ .update(destination, options, events || ConsoleLogger.get())
+ .then(function (destination) {
+ var PlatformApi = require(path.resolve(destination, 'cordova/Api'));
+ return new PlatformApi('android', destination, events);
+ });
+};
+
+/**
+ * Gets a CordovaPlatform object, that represents the platform structure.
+ *
+ * @return {CordovaPlatform} A structure that contains the description of
+ * platform's file structure and other properties of platform.
+ */
+Api.prototype.getPlatformInfo = function () {
+ var result = {};
+ result.locations = this.locations;
+ result.root = this.root;
+ result.name = this.platform;
+ result.version = require('./version');
+ result.projectConfig = this._config;
+
+ return result;
+};
+
+/**
+ * Updates installed platform with provided www assets and new app
+ * configuration. This method is required for CLI workflow and will be called
+ * each time before build, so the changes, made to app configuration and www
+ * code, will be applied to platform.
+ *
+ * @param {CordovaProject} cordovaProject A CordovaProject instance, that defines a
+ * project structure and configuration, that should be applied to platform
+ * (contains project's www location and ConfigParser instance for project's
+ * config).
+ *
+ * @return {Promise} Return a promise either fulfilled, or rejected with
+ * CordovaError instance.
+ */
+Api.prototype.prepare = function (cordovaProject) {
+ return require('./lib/prepare').prepare.call(this, cordovaProject);
+};
+
+/**
+ * Installs a new plugin into platform. This method only copies non-www files
+ * (sources, libs, etc.) to platform. It also doesn't resolves the
+ * dependencies of plugin. Both of handling of www files, such as assets and
+ * js-files and resolving dependencies are the responsibility of caller.
+ *
+ * @param {PluginInfo} plugin A PluginInfo instance that represents plugin
+ * that will be installed.
+ * @param {Object} installOptions An options object. Possible options below:
+ * @param {Boolean} installOptions.link: Flag that specifies that plugin
+ * sources will be symlinked to app's directory instead of copying (if
+ * possible).
+ * @param {Object} installOptions.variables An object that represents
+ * variables that will be used to install plugin. See more details on plugin
+ * variables in documentation:
+ * https://cordova.apache.org/docs/en/4.0.0/plugin_ref_spec.md.html
+ *
+ * @return {Promise} Return a promise either fulfilled, or rejected with
+ * CordovaError instance.
+ */
+Api.prototype.addPlugin = function (plugin, installOptions) {
+
+ if (!plugin || plugin.constructor.name !== 'PluginInfo')
+ return Q.reject(new CordovaError('The parameter is incorrect. The first parameter to addPlugin should be a PluginInfo instance'));
+
+ installOptions = installOptions || {};
+ installOptions.variables = installOptions.variables || {};
+
+ var self = this;
+ var actions = new ActionStack();
+ var project = AndroidProject.getProjectFile(this.root);
+
+ // gather all files needs to be handled during install
+ plugin.getFilesAndFrameworks(this.platform)
+ .concat(plugin.getAssets(this.platform))
+ .concat(plugin.getJsModules(this.platform))
+ .forEach(function(item) {
+ actions.push(actions.createAction(
+ pluginHandlers.getInstaller(item.itemType), [item, plugin, project, installOptions],
+ pluginHandlers.getUninstaller(item.itemType), [item, plugin, project, installOptions]));
+ });
+
+ // run through the action stack
+ return actions.process(this.platform)
+ .then(function () {
+ if (project) {
+ project.write();
+ }
+
+ // Add PACKAGE_NAME variable into vars
+ if (!installOptions.variables.PACKAGE_NAME) {
+ installOptions.variables.PACKAGE_NAME = project.getPackageName();
+ }
+
+ self._munger
+ // Ignore passed `is_top_level` option since platform itself doesn't know
+ // anything about managing dependencies - it's responsibility of caller.
+ .add_plugin_changes(plugin, installOptions.variables, /*is_top_level=*/true, /*should_increment=*/true)
+ .save_all();
+
+ var targetDir = installOptions.usePlatformWww ?
+ self.locations.platformWww :
+ self.locations.www;
+
+ self._addModulesInfo(plugin, targetDir);
+ });
+};
+
+/**
+ * Removes an installed plugin from platform.
+ *
+ * Since method accepts PluginInfo instance as input parameter instead of plugin
+ * id, caller shoud take care of managing/storing PluginInfo instances for
+ * future uninstalls.
+ *
+ * @param {PluginInfo} plugin A PluginInfo instance that represents plugin
+ * that will be installed.
+ *
+ * @return {Promise} Return a promise either fulfilled, or rejected with
+ * CordovaError instance.
+ */
+Api.prototype.removePlugin = function (plugin, uninstallOptions) {
+
+ if (!plugin || plugin.constructor.name !== 'PluginInfo')
+ return Q.reject(new CordovaError('The parameter is incorrect. The first parameter to addPlugin should be a PluginInfo instance'));
+
+ var self = this;
+ var actions = new ActionStack();
+ var project = AndroidProject.getProjectFile(this.root);
+
+ // queue up plugin files
+ plugin.getFilesAndFrameworks(this.platform)
+ .concat(plugin.getAssets(this.platform))
+ .concat(plugin.getJsModules(this.platform))
+ .forEach(function(item) {
+ actions.push(actions.createAction(
+ pluginHandlers.getUninstaller(item.itemType), [item, plugin, project, uninstallOptions],
+ pluginHandlers.getInstaller(item.itemType), [item, plugin, project, uninstallOptions]));
+ });
+
+ // run through the action stack
+ return actions.process(this.platform)
+ .then(function() {
+ if (project) {
+ project.write();
+ }
+
+ self._munger
+ // Ignore passed `is_top_level` option since platform itself doesn't know
+ // anything about managing dependencies - it's responsibility of caller.
+ .remove_plugin_changes(plugin, /*is_top_level=*/true)
+ .save_all();
+
+ var targetDir = uninstallOptions.usePlatformWww ?
+ self.locations.platformWww :
+ self.locations.www;
+
+ self._removeModulesInfo(plugin, targetDir);
+ });
+};
+
+/**
+ * Builds an application package for current platform.
+ *
+ * @param {Object} buildOptions A build options. This object's structure is
+ * highly depends on platform's specific. The most common options are:
+ * @param {Boolean} buildOptions.debug Indicates that packages should be
+ * built with debug configuration. This is set to true by default unless the
+ * 'release' option is not specified.
+ * @param {Boolean} buildOptions.release Indicates that packages should be
+ * built with release configuration. If not set to true, debug configuration
+ * will be used.
+ * @param {Boolean} buildOptions.device Specifies that built app is intended
+ * to run on device
+ * @param {Boolean} buildOptions.emulator: Specifies that built app is
+ * intended to run on emulator
+ * @param {String} buildOptions.target Specifies the device id that will be
+ * used to run built application.
+ * @param {Boolean} buildOptions.nobuild Indicates that this should be a
+ * dry-run call, so no build artifacts will be produced.
+ * @param {String[]} buildOptions.archs Specifies chip architectures which
+ * app packages should be built for. List of valid architectures is depends on
+ * platform.
+ * @param {String} buildOptions.buildConfig The path to build configuration
+ * file. The format of this file is depends on platform.
+ * @param {String[]} buildOptions.argv Raw array of command-line arguments,
+ * passed to `build` command. The purpose of this property is to pass a
+ * platform-specific arguments, and eventually let platform define own
+ * arguments processing logic.
+ *
+ * @return {Promise<Object[]>} A promise either fulfilled with an array of build
+ * artifacts (application packages) if package was built successfully,
+ * or rejected with CordovaError. The resultant build artifact objects is not
+ * strictly typed and may conatin arbitrary set of fields as in sample below.
+ *
+ * {
+ * architecture: 'x86',
+ * buildType: 'debug',
+ * path: '/path/to/build',
+ * type: 'app'
+ * }
+ *
+ * The return value in most cases will contain only one item but in some cases
+ * there could be multiple items in output array, e.g. when multiple
+ * arhcitectures is specified.
+ */
+Api.prototype.build = function (buildOptions) {
+ var self = this;
+ return require('./lib/check_reqs').run()
+ .then(function () {
+ return require('./lib/build').run.call(self, buildOptions);
+ })
+ .then(function (buildResults) {
+ // Cast build result to array of build artifacts
+ return buildResults.apkPaths.map(function (apkPath) {
+ return {
+ buildType: buildResults.buildType,
+ buildMethod: buildResults.buildMethod,
+ path: apkPath,
+ type: 'apk'
+ };
+ });
+ });
+};
+
+/**
+ * Builds an application package for current platform and runs it on
+ * specified/default device. If no 'device'/'emulator'/'target' options are
+ * specified, then tries to run app on default device if connected, otherwise
+ * runs the app on emulator.
+ *
+ * @param {Object} runOptions An options object. The structure is the same
+ * as for build options.
+ *
+ * @return {Promise} A promise either fulfilled if package was built and ran
+ * successfully, or rejected with CordovaError.
+ */
+Api.prototype.run = function(runOptions) {
+ var self = this;
+ return require('./lib/check_reqs').run()
+ .then(function () {
+ return require('./lib/run').run.call(self, runOptions);
+ });
+};
+
+/**
+ * Cleans out the build artifacts from platform's directory.
+ *
+ * @return {Promise} Return a promise either fulfilled, or rejected with
+ * CordovaError.
+ */
+Api.prototype.clean = function(cleanOptions) {
+ var self = this;
+ return require('./lib/check_reqs').run()
+ .then(function () {
+ return require('./lib/build').runClean.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
+ * built successfully.
+ *
+ * @return {Promise<Requirement[]>} Promise, resolved with set of Requirement
+ * objects for current platform.
+ */
+Api.prototype.requirements = function() {
+ return require('./lib/check_reqs').check_all();
+};
+
+module.exports = Api;
+
+/**
+ * Removes the specified modules from list of installed modules and updates
+ * platform_json and cordova_plugins.js on disk.
+ *
+ * @param {PluginInfo} plugin PluginInfo instance for plugin, which modules
+ * needs to be added.
+ * @param {String} targetDir The directory, where updated cordova_plugins.js
+ * should be written to.
+ */
+Api.prototype._addModulesInfo = function(plugin, targetDir) {
+ var installedModules = this._platformJson.root.modules || [];
+
+ var installedPaths = installedModules.map(function (installedModule) {
+ return installedModule.file;
+ });
+
+ var modulesToInstall = plugin.getJsModules(this.platform)
+ .filter(function (moduleToInstall) {
+ return installedPaths.indexOf(moduleToInstall.file) === -1;
+ }).map(function (moduleToInstall) {
+ var moduleName = plugin.id + '.' + ( moduleToInstall.name || moduleToInstall.src.match(/([^\/]+)\.js/)[1] );
+ var obj = {
+ file: ['plugins', plugin.id, moduleToInstall.src].join('/'),
+ id: moduleName
+ };
+ if (moduleToInstall.clobbers.length > 0) {
+ obj.clobbers = moduleToInstall.clobbers.map(function(o) { return o.target; });
+ }
+ if (moduleToInstall.merges.length > 0) {
+ obj.merges = moduleToInstall.merges.map(function(o) { return o.target; });
+ }
+ if (moduleToInstall.runs) {
+ obj.runs = true;
+ }
+
+ return obj;
+ });
+
+ this._platformJson.root.modules = installedModules.concat(modulesToInstall);
+ this._writePluginModules(targetDir);
+ this._platformJson.save();
+};
+
+/**
+ * Removes the specified modules from list of installed modules and updates
+ * platform_json and cordova_plugins.js on disk.
+ *
+ * @param {PluginInfo} plugin PluginInfo instance for plugin, which modules
+ * needs to be removed.
+ * @param {String} targetDir The directory, where updated cordova_plugins.js
+ * should be written to.
+ */
+Api.prototype._removeModulesInfo = function(plugin, targetDir) {
+ var installedModules = this._platformJson.root.modules || [];
+ var modulesToRemove = plugin.getJsModules(this.platform)
+ .map(function (jsModule) {
+ return ['plugins', plugin.id, jsModule.src].join('/');
+ });
+
+ var updatedModules = installedModules
+ .filter(function (installedModule) {
+ return (modulesToRemove.indexOf(installedModule.file) === -1);
+ });
+
+ this._platformJson.root.modules = updatedModules;
+ this._writePluginModules(targetDir);
+ this._platformJson.save();
+};
+
+/**
+ * Fetches all installed modules, generates cordova_plugins contents and writes
+ * it to file.
+ *
+ * @param {String} targetDir Directory, where write cordova_plugins.js to.
+ * Ususally it is either <platform>/www or <platform>/platform_www
+ * directories.
+ */
+Api.prototype._writePluginModules = function (targetDir) {
+ var self = this;
+ // Write out moduleObjects as JSON wrapped in a cordova module to cordova_plugins.js
+ var final_contents = 'cordova.define(\'cordova/plugin_list\', function(require, exports, module) {\n';
+ final_contents += 'module.exports = ' + JSON.stringify(this._platformJson.root.modules, null, ' ') + ';\n';
+ final_contents += 'module.exports.metadata = \n';
+ final_contents += '// TOP OF METADATA\n';
+
+ var pluginMetadata = Object.keys(this._platformJson.root.installed_plugins)
+ .reduce(function (metadata, plugin) {
+ metadata[plugin] = self._platformJson.root.installed_plugins[plugin].version;
+ return metadata;
+ }, {});
+
+ final_contents += JSON.stringify(pluginMetadata, null, 4) + '\n';
+ final_contents += '// BOTTOM OF METADATA\n';
+ final_contents += '});'; // Close cordova.define.
+
+ shell.mkdir('-p', targetDir);
+ fs.writeFileSync(path.join(targetDir, 'cordova_plugins.js'), final_contents, 'utf-8');
+};
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/0ac822c5/bin/templates/cordova/lib/Adb.js
----------------------------------------------------------------------
diff --git a/bin/templates/cordova/lib/Adb.js b/bin/templates/cordova/lib/Adb.js
index e4fc363..fc97f66 100644
--- a/bin/templates/cordova/lib/Adb.js
+++ b/bin/templates/cordova/lib/Adb.js
@@ -1,78 +1,78 @@
-
-var Q = require('q');
-var os = require('os');
-var events = require('cordova-common').events;
-var spawn = require('cordova-common').superspawn.spawn;
-var CordovaError = require('cordova-common').CordovaError;
-
-var Adb = {};
-
-function isDevice(line) {
- return line.match(/\w+\tdevice/) && !line.match(/emulator/);
-}
-
-function isEmulator(line) {
- return line.match(/device/) && line.match(/emulator/);
-}
-
-/**
- * Lists available/connected devices and emulators
- *
- * @param {Object} opts Various options
- * @param {Boolean} opts.emulators Specifies whether this method returns
- * emulators only
- *
- * @return {Promise<String[]>} list of available/connected
- * devices/emulators
- */
-Adb.devices = function (opts) {
- 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);
- }).map(function (line) {
- return line.replace(/\tdevice/, '').replace('\r', '');
- });
- });
-};
-
-Adb.install = function (target, packagePath, opts) {
- events.emit('verbose', 'Installing apk ' + packagePath + ' on ' + 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) {
- // 'adb install' seems to always returns no error, even if installation fails
- // so we catching output to detect installation failure
- if (output.match(/Failure/))
- return Q.reject(new CordovaError('Failed to install apk to device: ' + output));
- });
-};
-
-Adb.uninstall = function (target, packageId) {
- events.emit('verbose', 'Uninstalling ' + packageId + ' from ' + target + '...');
- return spawn('adb', ['-s', target, 'uninstall', packageId], {cwd: os.tmpdir()});
-};
-
-Adb.shell = function (target, shellCommand) {
- events.emit('verbose', 'Running command "' + shellCommand + '" on ' + target + '...');
- var args = ['-s', target, 'shell'];
- shellCommand = shellCommand.split(/\s+/);
- 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));
- });
-};
-
-Adb.start = function (target, activityName) {
- events.emit('verbose', 'Starting application "' + activityName + '" on ' + target + '...');
- 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));
- });
-};
-
-module.exports = Adb;
+
+var Q = require('q');
+var os = require('os');
+var events = require('cordova-common').events;
+var spawn = require('cordova-common').superspawn.spawn;
+var CordovaError = require('cordova-common').CordovaError;
+
+var Adb = {};
+
+function isDevice(line) {
+ return line.match(/\w+\tdevice/) && !line.match(/emulator/);
+}
+
+function isEmulator(line) {
+ return line.match(/device/) && line.match(/emulator/);
+}
+
+/**
+ * Lists available/connected devices and emulators
+ *
+ * @param {Object} opts Various options
+ * @param {Boolean} opts.emulators Specifies whether this method returns
+ * emulators only
+ *
+ * @return {Promise<String[]>} list of available/connected
+ * devices/emulators
+ */
+Adb.devices = function (opts) {
+ 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);
+ }).map(function (line) {
+ return line.replace(/\tdevice/, '').replace('\r', '');
+ });
+ });
+};
+
+Adb.install = function (target, packagePath, opts) {
+ events.emit('verbose', 'Installing apk ' + packagePath + ' on ' + 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) {
+ // 'adb install' seems to always returns no error, even if installation fails
+ // so we catching output to detect installation failure
+ if (output.match(/Failure/))
+ return Q.reject(new CordovaError('Failed to install apk to device: ' + output));
+ });
+};
+
+Adb.uninstall = function (target, packageId) {
+ events.emit('verbose', 'Uninstalling ' + packageId + ' from ' + target + '...');
+ return spawn('adb', ['-s', target, 'uninstall', packageId], {cwd: os.tmpdir()});
+};
+
+Adb.shell = function (target, shellCommand) {
+ events.emit('verbose', 'Running command "' + shellCommand + '" on ' + target + '...');
+ var args = ['-s', target, 'shell'];
+ shellCommand = shellCommand.split(/\s+/);
+ 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));
+ });
+};
+
+Adb.start = function (target, activityName) {
+ events.emit('verbose', 'Starting application "' + activityName + '" on ' + target + '...');
+ 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));
+ });
+};
+
+module.exports = Adb;
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/0ac822c5/bin/templates/cordova/lib/AndroidManifest.js
----------------------------------------------------------------------
diff --git a/bin/templates/cordova/lib/AndroidManifest.js b/bin/templates/cordova/lib/AndroidManifest.js
index 770d527..3654ada 100644
--- a/bin/templates/cordova/lib/AndroidManifest.js
+++ b/bin/templates/cordova/lib/AndroidManifest.js
@@ -1,161 +1,161 @@
-/**
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-var fs = require('fs');
-var et = require('elementtree');
-var xml= require('cordova-common').xmlHelpers;
-
-var DEFAULT_ORIENTATION = 'default';
-
-/** Wraps an AndroidManifest file */
-function AndroidManifest(path) {
- this.path = path;
- this.doc = xml.parseElementtreeSync(path);
- if (this.doc.getroot().tag !== 'manifest') {
- throw new Error(path + ' has incorrect root node name (expected "manifest")');
- }
-}
-
-AndroidManifest.prototype.getVersionName = function() {
- return this.doc.getroot().attrib['android:versionName'];
-};
-
-AndroidManifest.prototype.setVersionName = function(versionName) {
- this.doc.getroot().attrib['android:versionName'] = versionName;
- return this;
-};
-
-AndroidManifest.prototype.getVersionCode = function() {
- return this.doc.getroot().attrib['android:versionCode'];
-};
-
-AndroidManifest.prototype.setVersionCode = function(versionCode) {
- this.doc.getroot().attrib['android:versionCode'] = versionCode;
- return this;
-};
-
-AndroidManifest.prototype.getPackageId = function() {
- /*jshint -W069 */
- return this.doc.getroot().attrib['package'];
- /*jshint +W069 */
-};
-
-AndroidManifest.prototype.setPackageId = function(pkgId) {
- /*jshint -W069 */
- this.doc.getroot().attrib['package'] = pkgId;
- /*jshint +W069 */
- return this;
-};
-
-AndroidManifest.prototype.getActivity = function() {
- var activity = this.doc.getroot().find('./application/activity');
- return {
- getName: function () {
- return activity.attrib['android:name'];
- },
- setName: function (name) {
- if (!name) {
- delete activity.attrib['android:name'];
- } else {
- activity.attrib['android:name'] = name;
- }
- return this;
- },
- getOrientation: function () {
- return activity.attrib['android:screenOrientation'];
- },
- setOrientation: function (orientation) {
- if (!orientation || orientation.toLowerCase() === DEFAULT_ORIENTATION) {
- delete activity.attrib['android:screenOrientation'];
- } else {
- activity.attrib['android:screenOrientation'] = orientation;
- }
- return this;
- },
- getLaunchMode: function () {
- return activity.attrib['android:launchMode'];
- },
- setLaunchMode: function (launchMode) {
- if (!launchMode) {
- delete activity.attrib['android:launchMode'];
- } else {
- activity.attrib['android:launchMode'] = launchMode;
- }
- return this;
- }
- };
-};
-
-['minSdkVersion', 'maxSdkVersion', 'targetSdkVersion']
-.forEach(function(sdkPrefName) {
- // Copy variable reference to avoid closure issues
- var prefName = sdkPrefName;
-
- 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) {
- var usesSdk = this.doc.getroot().find('./uses-sdk');
-
- if (!usesSdk && prefValue) { // if there is no required uses-sdk element, we should create it first
- usesSdk = new et.Element('uses-sdk');
- this.doc.getroot().append(usesSdk);
- }
-
- if (prefValue) {
- usesSdk.attrib['android:' + prefName] = prefValue;
- }
-
- return this;
- };
-});
-
-AndroidManifest.prototype.getDebuggable = function() {
- return this.doc.getroot().find('./application').attrib['android:debuggable'] === 'true';
-};
-
-AndroidManifest.prototype.setDebuggable = function(value) {
- var application = this.doc.getroot().find('./application');
- if (value) {
- application.attrib['android:debuggable'] = 'true';
- } else {
- // The default value is "false", so we can remove attribute at all.
- delete application.attrib['android:debuggable'];
- }
- return this;
-};
-
-/**
- * Writes manifest to disk syncronously. If filename is specified, then manifest
- * will be written to that file
- *
- * @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) {
- fs.writeFileSync(destPath || this.path, this.doc.write({indent: 4}), 'utf-8');
-};
-
-module.exports = AndroidManifest;
-
-function capitalize (str) {
- return str.charAt(0).toUpperCase() + str.slice(1);
-}
+/**
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+var fs = require('fs');
+var et = require('elementtree');
+var xml= require('cordova-common').xmlHelpers;
+
+var DEFAULT_ORIENTATION = 'default';
+
+/** Wraps an AndroidManifest file */
+function AndroidManifest(path) {
+ this.path = path;
+ this.doc = xml.parseElementtreeSync(path);
+ if (this.doc.getroot().tag !== 'manifest') {
+ throw new Error(path + ' has incorrect root node name (expected "manifest")');
+ }
+}
+
+AndroidManifest.prototype.getVersionName = function() {
+ return this.doc.getroot().attrib['android:versionName'];
+};
+
+AndroidManifest.prototype.setVersionName = function(versionName) {
+ this.doc.getroot().attrib['android:versionName'] = versionName;
+ return this;
+};
+
+AndroidManifest.prototype.getVersionCode = function() {
+ return this.doc.getroot().attrib['android:versionCode'];
+};
+
+AndroidManifest.prototype.setVersionCode = function(versionCode) {
+ this.doc.getroot().attrib['android:versionCode'] = versionCode;
+ return this;
+};
+
+AndroidManifest.prototype.getPackageId = function() {
+ /*jshint -W069 */
+ return this.doc.getroot().attrib['package'];
+ /*jshint +W069 */
+};
+
+AndroidManifest.prototype.setPackageId = function(pkgId) {
+ /*jshint -W069 */
+ this.doc.getroot().attrib['package'] = pkgId;
+ /*jshint +W069 */
+ return this;
+};
+
+AndroidManifest.prototype.getActivity = function() {
+ var activity = this.doc.getroot().find('./application/activity');
+ return {
+ getName: function () {
+ return activity.attrib['android:name'];
+ },
+ setName: function (name) {
+ if (!name) {
+ delete activity.attrib['android:name'];
+ } else {
+ activity.attrib['android:name'] = name;
+ }
+ return this;
+ },
+ getOrientation: function () {
+ return activity.attrib['android:screenOrientation'];
+ },
+ setOrientation: function (orientation) {
+ if (!orientation || orientation.toLowerCase() === DEFAULT_ORIENTATION) {
+ delete activity.attrib['android:screenOrientation'];
+ } else {
+ activity.attrib['android:screenOrientation'] = orientation;
+ }
+ return this;
+ },
+ getLaunchMode: function () {
+ return activity.attrib['android:launchMode'];
+ },
+ setLaunchMode: function (launchMode) {
+ if (!launchMode) {
+ delete activity.attrib['android:launchMode'];
+ } else {
+ activity.attrib['android:launchMode'] = launchMode;
+ }
+ return this;
+ }
+ };
+};
+
+['minSdkVersion', 'maxSdkVersion', 'targetSdkVersion']
+.forEach(function(sdkPrefName) {
+ // Copy variable reference to avoid closure issues
+ var prefName = sdkPrefName;
+
+ 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) {
+ var usesSdk = this.doc.getroot().find('./uses-sdk');
+
+ if (!usesSdk && prefValue) { // if there is no required uses-sdk element, we should create it first
+ usesSdk = new et.Element('uses-sdk');
+ this.doc.getroot().append(usesSdk);
+ }
+
+ if (prefValue) {
+ usesSdk.attrib['android:' + prefName] = prefValue;
+ }
+
+ return this;
+ };
+});
+
+AndroidManifest.prototype.getDebuggable = function() {
+ return this.doc.getroot().find('./application').attrib['android:debuggable'] === 'true';
+};
+
+AndroidManifest.prototype.setDebuggable = function(value) {
+ var application = this.doc.getroot().find('./application');
+ if (value) {
+ application.attrib['android:debuggable'] = 'true';
+ } else {
+ // The default value is "false", so we can remove attribute at all.
+ delete application.attrib['android:debuggable'];
+ }
+ return this;
+};
+
+/**
+ * Writes manifest to disk syncronously. If filename is specified, then manifest
+ * will be written to that file
+ *
+ * @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) {
+ fs.writeFileSync(destPath || this.path, this.doc.write({indent: 4}), 'utf-8');
+};
+
+module.exports = AndroidManifest;
+
+function capitalize (str) {
+ return str.charAt(0).toUpperCase() + str.slice(1);
+}
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/0ac822c5/bin/templates/cordova/lib/AndroidProject.js
----------------------------------------------------------------------
diff --git a/bin/templates/cordova/lib/AndroidProject.js b/bin/templates/cordova/lib/AndroidProject.js
index 918a39b..458b84e 100644
--- a/bin/templates/cordova/lib/AndroidProject.js
+++ b/bin/templates/cordova/lib/AndroidProject.js
@@ -1,184 +1,184 @@
-/**
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-var fs = require('fs');
-var path = require('path');
-var properties_parser = require('properties-parser');
-var AndroidManifest = require('./AndroidManifest');
-
-var projectFileCache = {};
-
-function addToPropertyList(projectProperties, key, value) {
- var i = 1;
- while (projectProperties.get(key + '.' + i))
- i++;
-
- projectProperties.set(key + '.' + i, value);
- projectProperties.dirty = true;
-}
-
-function removeFromPropertyList(projectProperties, key, value) {
- var i = 1;
- var currentValue;
- while ((currentValue = projectProperties.get(key + '.' + i))) {
- if (currentValue === value) {
- while ((currentValue = projectProperties.get(key + '.' + (i + 1)))) {
- projectProperties.set(key + '.' + i, currentValue);
- i++;
- }
- projectProperties.set(key + '.' + i);
- break;
- }
- i++;
- }
- projectProperties.dirty = true;
-}
-
-function getRelativeLibraryPath (parentDir, subDir) {
- var libraryPath = path.relative(parentDir, subDir);
- return (path.sep == '\\') ? libraryPath.replace(/\\/g, '/') : libraryPath;
-}
-
-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');
-}
-
-AndroidProject.getProjectFile = function (projectDir) {
- if (!projectFileCache[projectDir]) {
- projectFileCache[projectDir] = new AndroidProject(projectDir);
- }
-
- return projectFileCache[projectDir];
-};
-
-AndroidProject.purgeCache = function (projectDir) {
- if (projectDir) {
- delete projectFileCache[projectDir];
- } else {
- projectFileCache = {};
- }
-};
-
-/**
- * Reads the package name out of the Android Manifest file
- *
- * @param {String} projectDir The absolute path to the directory containing the project
- *
- * @return {String} The name of the package
- */
-AndroidProject.prototype.getPackageName = function() {
- return new AndroidManifest(path.join(this.projectDir, 'AndroidManifest.xml')).getPackageId();
-};
-
-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();
- var lastDotIndex = packageName.lastIndexOf('.');
- var prefix = packageName.substring(lastDotIndex + 1);
- var subRelativeDir = path.join(plugin_id, prefix + '-' + path.basename(src));
- return subRelativeDir;
-};
-
-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);
- // TODO: Setting the target needs to happen only for pre-3.7.0 projects
- if (fs.existsSync(subProjectFile)) {
- var subProperties = this._getPropertiesFile(subProjectFile);
- subProperties.set('target', parentProperties.get('target'));
- subProperties.dirty = true;
- this._subProjectDirs[subDir] = true;
- }
- addToPropertyList(parentProperties, 'android.library.reference', getRelativeLibraryPath(parentDir, subDir));
-
- this._dirty = true;
-};
-
-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));
- delete this._subProjectDirs[subDir];
- this._dirty = true;
-};
-
-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) {
- 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) {
- 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) {
- 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() {
- if (!this._dirty) {
- return;
- }
- this._dirty = false;
-
- for (var filename in this._propertiesEditors) {
- var editor = this._propertiesEditors[filename];
- if (editor.dirty) {
- fs.writeFileSync(filename, editor.toString());
- editor.dirty = false;
- }
- }
-};
-
-AndroidProject.prototype._getPropertiesFile = function (filename) {
- if (!this._propertiesEditors[filename]) {
- if (fs.existsSync(filename)) {
- this._propertiesEditors[filename] = properties_parser.createEditor(filename);
- } else {
- this._propertiesEditors[filename] = properties_parser.createEditor();
- }
- }
-
- return this._propertiesEditors[filename];
-};
-
-
-module.exports = AndroidProject;
+/**
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+var fs = require('fs');
+var path = require('path');
+var properties_parser = require('properties-parser');
+var AndroidManifest = require('./AndroidManifest');
+
+var projectFileCache = {};
+
+function addToPropertyList(projectProperties, key, value) {
+ var i = 1;
+ while (projectProperties.get(key + '.' + i))
+ i++;
+
+ projectProperties.set(key + '.' + i, value);
+ projectProperties.dirty = true;
+}
+
+function removeFromPropertyList(projectProperties, key, value) {
+ var i = 1;
+ var currentValue;
+ while ((currentValue = projectProperties.get(key + '.' + i))) {
+ if (currentValue === value) {
+ while ((currentValue = projectProperties.get(key + '.' + (i + 1)))) {
+ projectProperties.set(key + '.' + i, currentValue);
+ i++;
+ }
+ projectProperties.set(key + '.' + i);
+ break;
+ }
+ i++;
+ }
+ projectProperties.dirty = true;
+}
+
+function getRelativeLibraryPath (parentDir, subDir) {
+ var libraryPath = path.relative(parentDir, subDir);
+ return (path.sep == '\\') ? libraryPath.replace(/\\/g, '/') : libraryPath;
+}
+
+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');
+}
+
+AndroidProject.getProjectFile = function (projectDir) {
+ if (!projectFileCache[projectDir]) {
+ projectFileCache[projectDir] = new AndroidProject(projectDir);
+ }
+
+ return projectFileCache[projectDir];
+};
+
+AndroidProject.purgeCache = function (projectDir) {
+ if (projectDir) {
+ delete projectFileCache[projectDir];
+ } else {
+ projectFileCache = {};
+ }
+};
+
+/**
+ * Reads the package name out of the Android Manifest file
+ *
+ * @param {String} projectDir The absolute path to the directory containing the project
+ *
+ * @return {String} The name of the package
+ */
+AndroidProject.prototype.getPackageName = function() {
+ return new AndroidManifest(path.join(this.projectDir, 'AndroidManifest.xml')).getPackageId();
+};
+
+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();
+ var lastDotIndex = packageName.lastIndexOf('.');
+ var prefix = packageName.substring(lastDotIndex + 1);
+ var subRelativeDir = path.join(plugin_id, prefix + '-' + path.basename(src));
+ return subRelativeDir;
+};
+
+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);
+ // TODO: Setting the target needs to happen only for pre-3.7.0 projects
+ if (fs.existsSync(subProjectFile)) {
+ var subProperties = this._getPropertiesFile(subProjectFile);
+ subProperties.set('target', parentProperties.get('target'));
+ subProperties.dirty = true;
+ this._subProjectDirs[subDir] = true;
+ }
+ addToPropertyList(parentProperties, 'android.library.reference', getRelativeLibraryPath(parentDir, subDir));
+
+ this._dirty = true;
+};
+
+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));
+ delete this._subProjectDirs[subDir];
+ this._dirty = true;
+};
+
+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) {
+ 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) {
+ 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) {
+ 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() {
+ if (!this._dirty) {
+ return;
+ }
+ this._dirty = false;
+
+ for (var filename in this._propertiesEditors) {
+ var editor = this._propertiesEditors[filename];
+ if (editor.dirty) {
+ fs.writeFileSync(filename, editor.toString());
+ editor.dirty = false;
+ }
+ }
+};
+
+AndroidProject.prototype._getPropertiesFile = function (filename) {
+ if (!this._propertiesEditors[filename]) {
+ if (fs.existsSync(filename)) {
+ this._propertiesEditors[filename] = properties_parser.createEditor(filename);
+ } else {
+ this._propertiesEditors[filename] = properties_parser.createEditor();
+ }
+ }
+
+ return this._propertiesEditors[filename];
+};
+
+
+module.exports = AndroidProject;
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/0ac822c5/bin/templates/cordova/lib/ConsoleLogger.js
----------------------------------------------------------------------
diff --git a/bin/templates/cordova/lib/ConsoleLogger.js b/bin/templates/cordova/lib/ConsoleLogger.js
index 19b03ec..cee2dc1 100644
--- a/bin/templates/cordova/lib/ConsoleLogger.js
+++ b/bin/templates/cordova/lib/ConsoleLogger.js
@@ -1,75 +1,75 @@
-/**
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-var loggerInstance;
-var util = require('util');
-var EventEmitter = require('events').EventEmitter;
-var CordovaError = require('cordova-common').CordovaError;
-
-/**
- * @class ConsoleLogger
- * @extends EventEmitter
- *
- * Implementing basic logging for platform. Inherits regular NodeJS
- * EventEmitter. All events, emitted on this class instance are immediately
- * logged to console.
- *
- * Also attaches handler to process' uncaught exceptions, so these exceptions
- * logged to console similar to regular error events.
- */
-function ConsoleLogger() {
- EventEmitter.call(this);
-
- var isVerbose = process.argv.indexOf('-d') >= 0 || process.argv.indexOf('--verbose') >= 0;
- // For CordovaError print only the message without stack trace unless we
- // are in a verbose mode.
- process.on('uncaughtException', function(err){
- if ((err instanceof CordovaError) && isVerbose) {
- console.error(err.stack);
- } else {
- console.error(err.message);
- }
- process.exit(1);
- });
-
- this.on('results', console.log);
- this.on('verbose', function () {
- if (isVerbose)
- console.log.apply(console, arguments);
- });
- this.on('info', console.log);
- this.on('log', console.log);
- this.on('warn', console.warn);
-}
-util.inherits(ConsoleLogger, EventEmitter);
-
-/**
- * Returns already instantiated/newly created instance of ConsoleLogger class.
- * This method should be used instead of creating ConsoleLogger directly,
- * otherwise we'll get multiple handlers attached to process'
- * uncaughtException
- *
- * @return {ConsoleLogger} New or already created instance of ConsoleLogger
- */
-ConsoleLogger.get = function () {
- loggerInstance = loggerInstance || new ConsoleLogger();
- return loggerInstance;
-};
-
-module.exports = ConsoleLogger;
+/**
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+var loggerInstance;
+var util = require('util');
+var EventEmitter = require('events').EventEmitter;
+var CordovaError = require('cordova-common').CordovaError;
+
+/**
+ * @class ConsoleLogger
+ * @extends EventEmitter
+ *
+ * Implementing basic logging for platform. Inherits regular NodeJS
+ * EventEmitter. All events, emitted on this class instance are immediately
+ * logged to console.
+ *
+ * Also attaches handler to process' uncaught exceptions, so these exceptions
+ * logged to console similar to regular error events.
+ */
+function ConsoleLogger() {
+ EventEmitter.call(this);
+
+ var isVerbose = process.argv.indexOf('-d') >= 0 || process.argv.indexOf('--verbose') >= 0;
+ // For CordovaError print only the message without stack trace unless we
+ // are in a verbose mode.
+ process.on('uncaughtException', function(err){
+ if ((err instanceof CordovaError) && isVerbose) {
+ console.error(err.stack);
+ } else {
+ console.error(err.message);
+ }
+ process.exit(1);
+ });
+
+ this.on('results', console.log);
+ this.on('verbose', function () {
+ if (isVerbose)
+ console.log.apply(console, arguments);
+ });
+ this.on('info', console.log);
+ this.on('log', console.log);
+ this.on('warn', console.warn);
+}
+util.inherits(ConsoleLogger, EventEmitter);
+
+/**
+ * Returns already instantiated/newly created instance of ConsoleLogger class.
+ * This method should be used instead of creating ConsoleLogger directly,
+ * otherwise we'll get multiple handlers attached to process'
+ * uncaughtException
+ *
+ * @return {ConsoleLogger} New or already created instance of ConsoleLogger
+ */
+ConsoleLogger.get = function () {
+ loggerInstance = loggerInstance || new ConsoleLogger();
+ return loggerInstance;
+};
+
+module.exports = ConsoleLogger;
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org
[4/4] android commit: Fixed line endings
Posted by st...@apache.org.
Fixed line endings
Project: http://git-wip-us.apache.org/repos/asf/cordova-android/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-android/commit/0ac822c5
Tree: http://git-wip-us.apache.org/repos/asf/cordova-android/tree/0ac822c5
Diff: http://git-wip-us.apache.org/repos/asf/cordova-android/diff/0ac822c5
Branch: refs/heads/master
Commit: 0ac822c57737ddf0a252b5da6406eef3ba426285
Parents: 4002822
Author: Steve Gill <st...@gmail.com>
Authored: Tue Oct 20 16:15:57 2015 -0700
Committer: Steve Gill <st...@gmail.com>
Committed: Tue Oct 20 16:15:57 2015 -0700
----------------------------------------------------------------------
LICENSE | 2 +-
bin/check_reqs.bat | 4 +-
bin/create | 112 +--
bin/lib/check_reqs.js | 652 ++++++------
bin/lib/create.js | 664 ++++++-------
bin/templates/cordova/Api.js | 984 +++++++++----------
bin/templates/cordova/lib/Adb.js | 156 +--
bin/templates/cordova/lib/AndroidManifest.js | 322 +++---
bin/templates/cordova/lib/AndroidProject.js | 368 +++----
bin/templates/cordova/lib/ConsoleLogger.js | 150 +--
bin/templates/cordova/lib/build.js | 602 ++++++------
.../cordova/lib/builders/AntBuilder.js | 282 +++---
.../cordova/lib/builders/GradleBuilder.js | 426 ++++----
bin/templates/cordova/lib/device.js | 212 ++--
bin/templates/cordova/lib/emulator.js | 744 +++++++-------
bin/templates/cordova/lib/pluginHandlers.js | 504 +++++-----
bin/templates/cordova/lib/prepare.js | 728 +++++++-------
bin/update | 70 +-
package.json | 92 +-
19 files changed, 3537 insertions(+), 3537 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/0ac822c5/LICENSE
----------------------------------------------------------------------
diff --git a/LICENSE b/LICENSE
index fd26dc7..c47288d 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-
+
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/0ac822c5/bin/check_reqs.bat
----------------------------------------------------------------------
diff --git a/bin/check_reqs.bat b/bin/check_reqs.bat
index cb2c6f5..fd7b7d1 100644
--- a/bin/check_reqs.bat
+++ b/bin/check_reqs.bat
@@ -5,9 +5,9 @@
:: to you under the Apache License, Version 2.0 (the
:: "License"); you may not use this file except in compliance
:: with the License. You may obtain a copy of the License at
-::
+::
:: http://www.apache.org/licenses/LICENSE-2.0
-::
+::
:: Unless required by applicable law or agreed to in writing,
:: software distributed under the License is distributed on an
:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/0ac822c5/bin/create
----------------------------------------------------------------------
diff --git a/bin/create b/bin/create
index bdbbc80..2052a27 100755
--- a/bin/create
+++ b/bin/create
@@ -1,56 +1,56 @@
-#!/usr/bin/env node
-
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-var path = require('path');
-var ConfigParser = require('cordova-common').ConfigParser;
-var Api = require('./templates/cordova/Api');
-
-var argv = require('nopt')({
- 'help' : Boolean,
- 'cli' : Boolean,
- 'shared' : Boolean,
- 'link' : Boolean,
- 'activity-name' : [String, undefined]
-});
-
-if (argv.help || argv.argv.remain.length === 0) {
- console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'create')) + ' <path_to_new_project> <package_name> <project_name> [<template_path>] [--activity-name <activity_name>] [--link]');
- console.log(' <path_to_new_project>: Path to your new Cordova Android project');
- console.log(' <package_name>: Package name, following reverse-domain style convention');
- console.log(' <project_name>: Project name');
- console.log(' <template_path>: Path to a custom application template to use');
- console.log(' --activity-name <activity_name>: Activity name');
- console.log(' --link will use the CordovaLib project directly instead of making a copy.');
- process.exit(1);
-}
-
-var config = new ConfigParser(path.resolve(__dirname, 'templates/project/res/xml/config.xml'));
-
-if (argv.argv.remain[1]) config.setPackageName(argv.argv.remain[1]);
-if (argv.argv.remain[2]) config.setName(argv.argv.remain[2]);
-if (argv['activity-name']) config.setName(argv['activity-name']);
-
-var options = {
- link: argv.link || argv.shared,
- customTemplate: argv.argv.remain[3],
- activityName: argv['activity-name']
-};
-
-Api.createPlatform(argv.argv.remain[0], config, options).done();
+#!/usr/bin/env node
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+var path = require('path');
+var ConfigParser = require('cordova-common').ConfigParser;
+var Api = require('./templates/cordova/Api');
+
+var argv = require('nopt')({
+ 'help' : Boolean,
+ 'cli' : Boolean,
+ 'shared' : Boolean,
+ 'link' : Boolean,
+ 'activity-name' : [String, undefined]
+});
+
+if (argv.help || argv.argv.remain.length === 0) {
+ console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'create')) + ' <path_to_new_project> <package_name> <project_name> [<template_path>] [--activity-name <activity_name>] [--link]');
+ console.log(' <path_to_new_project>: Path to your new Cordova Android project');
+ console.log(' <package_name>: Package name, following reverse-domain style convention');
+ console.log(' <project_name>: Project name');
+ console.log(' <template_path>: Path to a custom application template to use');
+ console.log(' --activity-name <activity_name>: Activity name');
+ console.log(' --link will use the CordovaLib project directly instead of making a copy.');
+ process.exit(1);
+}
+
+var config = new ConfigParser(path.resolve(__dirname, 'templates/project/res/xml/config.xml'));
+
+if (argv.argv.remain[1]) config.setPackageName(argv.argv.remain[1]);
+if (argv.argv.remain[2]) config.setName(argv.argv.remain[2]);
+if (argv['activity-name']) config.setName(argv['activity-name']);
+
+var options = {
+ link: argv.link || argv.shared,
+ customTemplate: argv.argv.remain[3],
+ activityName: argv['activity-name']
+};
+
+Api.createPlatform(argv.argv.remain[0], config, options).done();
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/0ac822c5/bin/lib/check_reqs.js
----------------------------------------------------------------------
diff --git a/bin/lib/check_reqs.js b/bin/lib/check_reqs.js
index 57e1f47..d3a93e1 100644
--- a/bin/lib/check_reqs.js
+++ b/bin/lib/check_reqs.js
@@ -1,326 +1,326 @@
-#!/usr/bin/env node
-
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-/* jshint sub:true */
-
-var shelljs = require('shelljs'),
- child_process = require('child_process'),
- Q = require('q'),
- path = require('path'),
- fs = require('fs'),
- ROOT = path.join(__dirname, '..', '..');
-var CordovaError = require('cordova-common').CordovaError;
-
-var isWindows = process.platform == 'win32';
-
-function forgivingWhichSync(cmd) {
- try {
- return fs.realpathSync(shelljs.which(cmd));
- } catch (e) {
- return '';
- }
-}
-
-function tryCommand(cmd, errMsg, catchStderr) {
- var d = Q.defer();
- 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
- else d.resolve((catchStderr ? stderr : stdout).trim());
- });
- return d.promise;
-}
-
-// Get valid target from framework/project.properties
-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);
- }
- return target.split('=')[1].trim();
- }
- if (fs.existsSync(path.join(ROOT, 'framework', 'project.properties'))) {
- return extractFromFile(path.join(ROOT, 'framework', 'project.properties'));
- }
- if (fs.existsSync(path.join(ROOT, 'project.properties'))) {
- // if no target found, we're probably in a project and project.properties is in ROOT.
- return extractFromFile(path.join(ROOT, 'project.properties'));
- }
- throw new Error('Could not find android target. File missing: ' + path.join(ROOT, 'project.properties'));
-};
-
-// Returns a promise. Called only by build and clean commands.
-module.exports.check_ant = function() {
- return tryCommand('ant -version', 'Failed to run "ant -version", make sure you have ant installed and added to your PATH.')
- .then(function (output) {
- // Parse Ant version from command output
- return /version ((?:\d+\.)+(?:\d+))/i.exec(output)[1];
- });
-};
-
-// Returns a promise. Called only by build and clean commands.
-module.exports.check_gradle = function() {
- var sdkDir = process.env['ANDROID_HOME'];
- 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 wrapperDir = path.join(sdkDir, 'tools', 'templates', 'gradle', 'wrapper');
- if (!fs.existsSync(wrapperDir)) {
- return Q.reject(new CordovaError('Could not find gradle wrapper within Android SDK. Might need to update your Android SDK.\n' +
- 'Looked here: ' + wrapperDir));
- }
- return Q.when();
-};
-
-// Returns a promise.
-module.exports.check_java = function() {
- var javacPath = forgivingWhichSync('javac');
- var hasJavaHome = !!process.env['JAVA_HOME'];
- return Q().then(function() {
- if (hasJavaHome) {
- // Windows java installer doesn't add javac to PATH, nor set JAVA_HOME (ugh).
- if (!javacPath) {
- process.env['PATH'] += path.delimiter + path.join(process.env['JAVA_HOME'], 'bin');
- }
- } else {
- if (javacPath) {
- var msg = 'Failed to find \'JAVA_HOME\' environment variable. Try setting setting it manually.';
- // OS X has a command for finding JAVA_HOME.
- if (fs.existsSync('/usr/libexec/java_home')) {
- return tryCommand('/usr/libexec/java_home', msg)
- .then(function(stdout) {
- process.env['JAVA_HOME'] = stdout.trim();
- });
- } else {
- // See if we can derive it from javac's location.
- // fs.realpathSync is require on Ubuntu, which symplinks from /usr/bin -> JDK
- var maybeJavaHome = path.dirname(path.dirname(javacPath));
- if (fs.existsSync(path.join(maybeJavaHome, 'lib', 'tools.jar'))) {
- process.env['JAVA_HOME'] = maybeJavaHome;
- } else {
- throw new CordovaError(msg);
- }
- }
- } else if (isWindows) {
- // Try to auto-detect java in the default install paths.
- var oldSilent = shelljs.config.silent;
- shelljs.config.silent = true;
- var firstJdkDir =
- shelljs.ls(process.env['ProgramFiles'] + '\\java\\jdk*')[0] ||
- shelljs.ls('C:\\Program Files\\java\\jdk*')[0] ||
- shelljs.ls('C:\\Program Files (x86)\\java\\jdk*')[0];
- shelljs.config.silent = oldSilent;
- if (firstJdkDir) {
- // shelljs always uses / in paths.
- firstJdkDir = firstJdkDir.replace(/\//g, path.sep);
- if (!javacPath) {
- process.env['PATH'] += path.delimiter + path.join(firstJdkDir, 'bin');
- }
- process.env['JAVA_HOME'] = firstJdkDir;
- }
- }
- }
- }).then(function() {
- var msg =
- 'Failed to run "java -version", make sure that you have a JDK installed.\n' +
- 'You can get it from: http://www.oracle.com/technetwork/java/javase/downloads.\n';
- if (process.env['JAVA_HOME']) {
- msg += 'Your JAVA_HOME is invalid: ' + process.env['JAVA_HOME'] + '\n';
- }
- return tryCommand('java -version', msg)
- .then(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) {
- var match = /javac ((?:\d+\.)+(?:\d+))/i.exec(output)[1];
- return match && match[1];
- });
- });
-};
-
-// Returns a promise.
-module.exports.check_android = function() {
- return Q().then(function() {
- var androidCmdPath = forgivingWhichSync('android');
- var adbInPath = !!forgivingWhichSync('adb');
- var hasAndroidHome = !!process.env['ANDROID_HOME'] && fs.existsSync(process.env['ANDROID_HOME']);
- function maybeSetAndroidHome(value) {
- if (!hasAndroidHome && fs.existsSync(value)) {
- hasAndroidHome = true;
- process.env['ANDROID_HOME'] = value;
- }
- }
- if (!hasAndroidHome && !androidCmdPath) {
- if (isWindows) {
- // Android Studio 1.0 installer
- maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'sdk'));
- maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'sdk'));
- // Android Studio pre-1.0 installer
- maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-studio', 'sdk'));
- maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-studio', 'sdk'));
- // Stand-alone installer
- maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-sdk'));
- maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-sdk'));
- } else if (process.platform == 'darwin') {
- // Android Studio 1.0 installer
- maybeSetAndroidHome(path.join(process.env['HOME'], 'Library', 'Android', 'sdk'));
- // Android Studio pre-1.0 installer
- maybeSetAndroidHome('/Applications/Android Studio.app/sdk');
- // Stand-alone zip file that user might think to put under /Applications
- maybeSetAndroidHome('/Applications/android-sdk-macosx');
- maybeSetAndroidHome('/Applications/android-sdk');
- }
- if (process.env['HOME']) {
- // Stand-alone zip file that user might think to put under their home directory
- maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk-macosx'));
- maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk'));
- }
- }
- if (hasAndroidHome && !androidCmdPath) {
- process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'tools');
- }
- if (androidCmdPath && !hasAndroidHome) {
- var parentDir = path.dirname(androidCmdPath);
- var grandParentDir = path.dirname(parentDir);
- if (path.basename(parentDir) == 'tools') {
- process.env['ANDROID_HOME'] = path.dirname(parentDir);
- hasAndroidHome = true;
- } else if (fs.existsSync(path.join(grandParentDir, 'tools', 'android'))) {
- process.env['ANDROID_HOME'] = grandParentDir;
- hasAndroidHome = true;
- } else {
- throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' +
- 'Detected \'android\' command at ' + parentDir + ' but no \'tools\' directory found near.\n' +
- 'Try reinstall Android SDK or update your PATH to include path to valid SDK directory.');
- }
- }
- if (hasAndroidHome && !adbInPath) {
- process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'platform-tools');
- }
- if (!process.env['ANDROID_HOME']) {
- throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' +
- 'Failed to find \'android\' command in your \'PATH\'. Try update your \'PATH\' to include path to valid SDK directory.');
- }
- if (!fs.existsSync(process.env['ANDROID_HOME'])) {
- throw new CordovaError('\'ANDROID_HOME\' environment variable is set to non-existent path: ' + process.env['ANDROID_HOME'] +
- '\nTry update it manually to point to valid SDK directory.');
- }
- });
-};
-
-module.exports.getAbsoluteAndroidCmd = function() {
- return forgivingWhichSync('android').replace(/(\s)/g, '\\$1');
-};
-
-module.exports.check_android_target = function(valid_target) {
- // valid_target can look like:
- // android-19
- // android-L
- // Google Inc.:Google APIs:20
- // Google Inc.:Glass Development Kit Preview:20
- if (!valid_target) valid_target = module.exports.get_target();
- var msg = 'Android SDK not found. Make sure that it is installed. If it is not at the default location, set the ANDROID_HOME environment variable.';
- return tryCommand('android list targets --compact', msg)
- .then(function(output) {
- var targets = output.split('\n');
- if (targets.indexOf(valid_target) >= 0) {
- return targets;
- }
-
- var androidCmd = module.exports.getAbsoluteAndroidCmd();
- throw new CordovaError('Please install Android target: "' + valid_target + '".\n\n' +
- 'Hint: Open the SDK manager by running: ' + androidCmd + '\n' +
- 'You will require:\n' +
- '1. "SDK Platform" for ' + valid_target + '\n' +
- '2. "Android SDK Platform-tools (latest)\n' +
- '3. "Android SDK Build-tools" (latest)');
- });
-};
-
-// Returns a promise.
-module.exports.run = function() {
- return Q.all([this.check_java(), this.check_android().then(this.check_android_target)])
- .then(function() {
- console.log('ANDROID_HOME=' + process.env['ANDROID_HOME']);
- console.log('JAVA_HOME=' + process.env['JAVA_HOME']);
- });
-};
-
-/**
- * Object thar represents one of requirements for current platform.
- * @param {String} id The unique identifier for this requirements.
- * @param {String} name The name of requirements. Human-readable field.
- * @param {String} version The version of requirement installed. In some cases could be an array of strings
- * (for example, check_android_target returns an array of android targets installed)
- * @param {Boolean} installed Indicates whether the requirement is installed or not
- */
-var Requirement = function (id, name, version, installed) {
- this.id = id;
- this.name = name;
- this.installed = installed || false;
- this.metadata = {
- version: version,
- };
-};
-
-/**
- * Methods that runs all checks one by one and returns a result of checks
- * as an array of Requirement objects. This method intended to be used by cordova-lib check_reqs method
- *
- * @return Promise<Requirement[]> Array of requirements. Due to implementation, promise is always fulfilled.
- */
-module.exports.check_all = function() {
-
- var requirements = [
- new Requirement('java', 'Java JDK'),
- new Requirement('androidSdk', 'Android SDK'),
- new Requirement('androidTarget', 'Android target'),
- new Requirement('gradle', 'Gradle')
- ];
-
- var checkFns = [
- this.check_java,
- this.check_android,
- this.check_android_target,
- this.check_gradle
- ];
-
- // Then execute requirement checks one-by-one
- return checkFns.reduce(function (promise, checkFn, idx) {
- // Update each requirement with results
- var requirement = requirements[idx];
- 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 () {
- // When chain is completed, return requirements array to upstream API
- return requirements;
- });
-};
+#!/usr/bin/env node
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+/* jshint sub:true */
+
+var shelljs = require('shelljs'),
+ child_process = require('child_process'),
+ Q = require('q'),
+ path = require('path'),
+ fs = require('fs'),
+ ROOT = path.join(__dirname, '..', '..');
+var CordovaError = require('cordova-common').CordovaError;
+
+var isWindows = process.platform == 'win32';
+
+function forgivingWhichSync(cmd) {
+ try {
+ return fs.realpathSync(shelljs.which(cmd));
+ } catch (e) {
+ return '';
+ }
+}
+
+function tryCommand(cmd, errMsg, catchStderr) {
+ var d = Q.defer();
+ 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
+ else d.resolve((catchStderr ? stderr : stdout).trim());
+ });
+ return d.promise;
+}
+
+// Get valid target from framework/project.properties
+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);
+ }
+ return target.split('=')[1].trim();
+ }
+ if (fs.existsSync(path.join(ROOT, 'framework', 'project.properties'))) {
+ return extractFromFile(path.join(ROOT, 'framework', 'project.properties'));
+ }
+ if (fs.existsSync(path.join(ROOT, 'project.properties'))) {
+ // if no target found, we're probably in a project and project.properties is in ROOT.
+ return extractFromFile(path.join(ROOT, 'project.properties'));
+ }
+ throw new Error('Could not find android target. File missing: ' + path.join(ROOT, 'project.properties'));
+};
+
+// Returns a promise. Called only by build and clean commands.
+module.exports.check_ant = function() {
+ return tryCommand('ant -version', 'Failed to run "ant -version", make sure you have ant installed and added to your PATH.')
+ .then(function (output) {
+ // Parse Ant version from command output
+ return /version ((?:\d+\.)+(?:\d+))/i.exec(output)[1];
+ });
+};
+
+// Returns a promise. Called only by build and clean commands.
+module.exports.check_gradle = function() {
+ var sdkDir = process.env['ANDROID_HOME'];
+ 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 wrapperDir = path.join(sdkDir, 'tools', 'templates', 'gradle', 'wrapper');
+ if (!fs.existsSync(wrapperDir)) {
+ return Q.reject(new CordovaError('Could not find gradle wrapper within Android SDK. Might need to update your Android SDK.\n' +
+ 'Looked here: ' + wrapperDir));
+ }
+ return Q.when();
+};
+
+// Returns a promise.
+module.exports.check_java = function() {
+ var javacPath = forgivingWhichSync('javac');
+ var hasJavaHome = !!process.env['JAVA_HOME'];
+ return Q().then(function() {
+ if (hasJavaHome) {
+ // Windows java installer doesn't add javac to PATH, nor set JAVA_HOME (ugh).
+ if (!javacPath) {
+ process.env['PATH'] += path.delimiter + path.join(process.env['JAVA_HOME'], 'bin');
+ }
+ } else {
+ if (javacPath) {
+ var msg = 'Failed to find \'JAVA_HOME\' environment variable. Try setting setting it manually.';
+ // OS X has a command for finding JAVA_HOME.
+ if (fs.existsSync('/usr/libexec/java_home')) {
+ return tryCommand('/usr/libexec/java_home', msg)
+ .then(function(stdout) {
+ process.env['JAVA_HOME'] = stdout.trim();
+ });
+ } else {
+ // See if we can derive it from javac's location.
+ // fs.realpathSync is require on Ubuntu, which symplinks from /usr/bin -> JDK
+ var maybeJavaHome = path.dirname(path.dirname(javacPath));
+ if (fs.existsSync(path.join(maybeJavaHome, 'lib', 'tools.jar'))) {
+ process.env['JAVA_HOME'] = maybeJavaHome;
+ } else {
+ throw new CordovaError(msg);
+ }
+ }
+ } else if (isWindows) {
+ // Try to auto-detect java in the default install paths.
+ var oldSilent = shelljs.config.silent;
+ shelljs.config.silent = true;
+ var firstJdkDir =
+ shelljs.ls(process.env['ProgramFiles'] + '\\java\\jdk*')[0] ||
+ shelljs.ls('C:\\Program Files\\java\\jdk*')[0] ||
+ shelljs.ls('C:\\Program Files (x86)\\java\\jdk*')[0];
+ shelljs.config.silent = oldSilent;
+ if (firstJdkDir) {
+ // shelljs always uses / in paths.
+ firstJdkDir = firstJdkDir.replace(/\//g, path.sep);
+ if (!javacPath) {
+ process.env['PATH'] += path.delimiter + path.join(firstJdkDir, 'bin');
+ }
+ process.env['JAVA_HOME'] = firstJdkDir;
+ }
+ }
+ }
+ }).then(function() {
+ var msg =
+ 'Failed to run "java -version", make sure that you have a JDK installed.\n' +
+ 'You can get it from: http://www.oracle.com/technetwork/java/javase/downloads.\n';
+ if (process.env['JAVA_HOME']) {
+ msg += 'Your JAVA_HOME is invalid: ' + process.env['JAVA_HOME'] + '\n';
+ }
+ return tryCommand('java -version', msg)
+ .then(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) {
+ var match = /javac ((?:\d+\.)+(?:\d+))/i.exec(output)[1];
+ return match && match[1];
+ });
+ });
+};
+
+// Returns a promise.
+module.exports.check_android = function() {
+ return Q().then(function() {
+ var androidCmdPath = forgivingWhichSync('android');
+ var adbInPath = !!forgivingWhichSync('adb');
+ var hasAndroidHome = !!process.env['ANDROID_HOME'] && fs.existsSync(process.env['ANDROID_HOME']);
+ function maybeSetAndroidHome(value) {
+ if (!hasAndroidHome && fs.existsSync(value)) {
+ hasAndroidHome = true;
+ process.env['ANDROID_HOME'] = value;
+ }
+ }
+ if (!hasAndroidHome && !androidCmdPath) {
+ if (isWindows) {
+ // Android Studio 1.0 installer
+ maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'sdk'));
+ maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'sdk'));
+ // Android Studio pre-1.0 installer
+ maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-studio', 'sdk'));
+ maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-studio', 'sdk'));
+ // Stand-alone installer
+ maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-sdk'));
+ maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-sdk'));
+ } else if (process.platform == 'darwin') {
+ // Android Studio 1.0 installer
+ maybeSetAndroidHome(path.join(process.env['HOME'], 'Library', 'Android', 'sdk'));
+ // Android Studio pre-1.0 installer
+ maybeSetAndroidHome('/Applications/Android Studio.app/sdk');
+ // Stand-alone zip file that user might think to put under /Applications
+ maybeSetAndroidHome('/Applications/android-sdk-macosx');
+ maybeSetAndroidHome('/Applications/android-sdk');
+ }
+ if (process.env['HOME']) {
+ // Stand-alone zip file that user might think to put under their home directory
+ maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk-macosx'));
+ maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk'));
+ }
+ }
+ if (hasAndroidHome && !androidCmdPath) {
+ process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'tools');
+ }
+ if (androidCmdPath && !hasAndroidHome) {
+ var parentDir = path.dirname(androidCmdPath);
+ var grandParentDir = path.dirname(parentDir);
+ if (path.basename(parentDir) == 'tools') {
+ process.env['ANDROID_HOME'] = path.dirname(parentDir);
+ hasAndroidHome = true;
+ } else if (fs.existsSync(path.join(grandParentDir, 'tools', 'android'))) {
+ process.env['ANDROID_HOME'] = grandParentDir;
+ hasAndroidHome = true;
+ } else {
+ throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' +
+ 'Detected \'android\' command at ' + parentDir + ' but no \'tools\' directory found near.\n' +
+ 'Try reinstall Android SDK or update your PATH to include path to valid SDK directory.');
+ }
+ }
+ if (hasAndroidHome && !adbInPath) {
+ process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'platform-tools');
+ }
+ if (!process.env['ANDROID_HOME']) {
+ throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting setting it manually.\n' +
+ 'Failed to find \'android\' command in your \'PATH\'. Try update your \'PATH\' to include path to valid SDK directory.');
+ }
+ if (!fs.existsSync(process.env['ANDROID_HOME'])) {
+ throw new CordovaError('\'ANDROID_HOME\' environment variable is set to non-existent path: ' + process.env['ANDROID_HOME'] +
+ '\nTry update it manually to point to valid SDK directory.');
+ }
+ });
+};
+
+module.exports.getAbsoluteAndroidCmd = function() {
+ return forgivingWhichSync('android').replace(/(\s)/g, '\\$1');
+};
+
+module.exports.check_android_target = function(valid_target) {
+ // valid_target can look like:
+ // android-19
+ // android-L
+ // Google Inc.:Google APIs:20
+ // Google Inc.:Glass Development Kit Preview:20
+ if (!valid_target) valid_target = module.exports.get_target();
+ var msg = 'Android SDK not found. Make sure that it is installed. If it is not at the default location, set the ANDROID_HOME environment variable.';
+ return tryCommand('android list targets --compact', msg)
+ .then(function(output) {
+ var targets = output.split('\n');
+ if (targets.indexOf(valid_target) >= 0) {
+ return targets;
+ }
+
+ var androidCmd = module.exports.getAbsoluteAndroidCmd();
+ throw new CordovaError('Please install Android target: "' + valid_target + '".\n\n' +
+ 'Hint: Open the SDK manager by running: ' + androidCmd + '\n' +
+ 'You will require:\n' +
+ '1. "SDK Platform" for ' + valid_target + '\n' +
+ '2. "Android SDK Platform-tools (latest)\n' +
+ '3. "Android SDK Build-tools" (latest)');
+ });
+};
+
+// Returns a promise.
+module.exports.run = function() {
+ return Q.all([this.check_java(), this.check_android().then(this.check_android_target)])
+ .then(function() {
+ console.log('ANDROID_HOME=' + process.env['ANDROID_HOME']);
+ console.log('JAVA_HOME=' + process.env['JAVA_HOME']);
+ });
+};
+
+/**
+ * Object thar represents one of requirements for current platform.
+ * @param {String} id The unique identifier for this requirements.
+ * @param {String} name The name of requirements. Human-readable field.
+ * @param {String} version The version of requirement installed. In some cases could be an array of strings
+ * (for example, check_android_target returns an array of android targets installed)
+ * @param {Boolean} installed Indicates whether the requirement is installed or not
+ */
+var Requirement = function (id, name, version, installed) {
+ this.id = id;
+ this.name = name;
+ this.installed = installed || false;
+ this.metadata = {
+ version: version,
+ };
+};
+
+/**
+ * Methods that runs all checks one by one and returns a result of checks
+ * as an array of Requirement objects. This method intended to be used by cordova-lib check_reqs method
+ *
+ * @return Promise<Requirement[]> Array of requirements. Due to implementation, promise is always fulfilled.
+ */
+module.exports.check_all = function() {
+
+ var requirements = [
+ new Requirement('java', 'Java JDK'),
+ new Requirement('androidSdk', 'Android SDK'),
+ new Requirement('androidTarget', 'Android target'),
+ new Requirement('gradle', 'Gradle')
+ ];
+
+ var checkFns = [
+ this.check_java,
+ this.check_android,
+ this.check_android_target,
+ this.check_gradle
+ ];
+
+ // Then execute requirement checks one-by-one
+ return checkFns.reduce(function (promise, checkFn, idx) {
+ // Update each requirement with results
+ var requirement = requirements[idx];
+ 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 () {
+ // When chain is completed, return requirements array to upstream API
+ return requirements;
+ });
+};
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/0ac822c5/bin/lib/create.js
----------------------------------------------------------------------
diff --git a/bin/lib/create.js b/bin/lib/create.js
index 799836f..9d4b4ae 100755
--- a/bin/lib/create.js
+++ b/bin/lib/create.js
@@ -1,332 +1,332 @@
-#!/usr/bin/env node
-
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-var shell = require('shelljs'),
- Q = require('q'),
- path = require('path'),
- fs = require('fs'),
- check_reqs = require('./check_reqs'),
- ROOT = path.join(__dirname, '..', '..');
-
-var MIN_SDK_VERSION = 14;
-
-var CordovaError = require('cordova-common').CordovaError;
-var AndroidManifest = require('../templates/cordova/lib/AndroidManifest');
-
-function setShellFatal(value, func) {
- var oldVal = shell.config.fatal;
- shell.config.fatal = value;
- func();
- shell.config.fatal = oldVal;
-}
-
-function getFrameworkDir(projectPath, shared) {
- return shared ? path.join(ROOT, 'framework') : path.join(projectPath, 'CordovaLib');
-}
-
-function copyJsAndLibrary(projectPath, shared, projectName) {
- var nestedCordovaLibPath = getFrameworkDir(projectPath, false);
- var srcCordovaJsPath = path.join(ROOT, 'bin', 'templates', 'project', 'assets', 'www', 'cordova.js');
- shell.cp('-f', srcCordovaJsPath, path.join(projectPath, 'assets', 'www', 'cordova.js'));
-
- // Copy the cordova.js file to platforms/<platform>/platform_www/
- // The www dir is nuked on each prepare so we keep cordova.js in platform_www
- shell.mkdir('-p', path.join(projectPath, 'platform_www'));
- shell.cp('-f', srcCordovaJsPath, path.join(projectPath, 'platform_www'));
-
- // Copy cordova-js-src directory into platform_www directory.
- // 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.
- setShellFatal(false, function() {
- shell.ls(path.join(projectPath, 'libs', 'cordova-*.jar')).forEach(function(oldJar) {
- console.log('Deleting ' + oldJar);
- shell.rm('-f', oldJar);
- });
- var wasSymlink = true;
- try {
- // Delete the symlink if it was one.
- fs.unlinkSync(nestedCordovaLibPath);
- } catch (e) {
- wasSymlink = false;
- }
- // Delete old library project if it existed.
- if (shared) {
- shell.rm('-rf', nestedCordovaLibPath);
- } else if (!wasSymlink) {
- // Delete only the src, since Eclipse / Android Studio can't handle their project files being deleted.
- shell.rm('-rf', path.join(nestedCordovaLibPath, 'src'));
- }
- });
- if (shared) {
- var relativeFrameworkPath = path.relative(projectPath, getFrameworkDir(projectPath, true));
- fs.symlinkSync(relativeFrameworkPath, nestedCordovaLibPath, 'dir');
- } else {
- shell.mkdir('-p', nestedCordovaLibPath);
- shell.cp('-f', path.join(ROOT, 'framework', 'AndroidManifest.xml'), nestedCordovaLibPath);
- shell.cp('-f', path.join(ROOT, 'framework', 'project.properties'), nestedCordovaLibPath);
- shell.cp('-f', path.join(ROOT, 'framework', 'build.gradle'), nestedCordovaLibPath);
- shell.cp('-f', path.join(ROOT, 'framework', 'cordova.gradle'), nestedCordovaLibPath);
- shell.cp('-r', path.join(ROOT, 'framework', 'src'), nestedCordovaLibPath);
- }
-}
-
-function extractSubProjectPaths(data) {
- var ret = {};
- var r = /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg;
- var m;
- while ((m = r.exec(data))) {
- ret[m[1]] = 1;
- }
- return Object.keys(ret);
-}
-
-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;
-
- var data = fs.readFileSync(srcPath, 'utf8');
- data = data.replace(/^target=.*/m, 'target=' + target_api);
- var subProjects = extractSubProjectPaths(data);
- subProjects = subProjects.filter(function(p) {
- return !(/^CordovaLib$/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, '');
- if (!/\n$/.exec(data)) {
- data += '\n';
- }
- for (var i = 0; i < subProjects.length; ++i) {
- data += 'android.library.reference.' + (i+1) + '=' + subProjects[i] + '\n';
- }
- fs.writeFileSync(dstPath, data);
-}
-
-function prepBuildFiles(projectPath) {
- var buildModule = require(path.join(path.resolve(projectPath), 'cordova', 'lib', 'build'));
- buildModule.prepBuildFiles();
-}
-
-function copyBuildRules(projectPath) {
- var srcDir = path.join(ROOT, 'bin', 'templates', 'project');
-
- shell.cp('-f', path.join(srcDir, 'build.gradle'), projectPath);
-}
-
-function copyScripts(projectPath) {
- var srcScriptsDir = path.join(ROOT, 'bin', 'templates', 'cordova');
- var destScriptsDir = path.join(projectPath, 'cordova');
- // Delete old scripts directory if this is an update.
- shell.rm('-rf', destScriptsDir);
- // Copy in the new ones.
- shell.cp('-r', srcScriptsDir, projectPath);
- shell.cp('-r', path.join(ROOT, 'node_modules'), destScriptsDir);
- shell.cp(path.join(ROOT, 'bin', 'check_reqs*'), destScriptsDir);
- shell.cp(path.join(ROOT, 'bin', 'lib', 'check_reqs.js'), path.join(projectPath, 'cordova', 'lib', 'check_reqs.js'));
- shell.cp(path.join(ROOT, 'bin', 'android_sdk_version'), path.join(destScriptsDir, 'android_sdk_version'));
- shell.cp(path.join(ROOT, 'bin', 'lib', 'android_sdk_version.js'), path.join(projectPath, 'cordova', 'lib', 'android_sdk_version.js'));
-}
-
-/**
- * Test whether a package name is acceptable for use as an android project.
- * 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
- 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)) {
- return Q.reject(new CordovaError(msg + '"class" is a reserved word'));
- }
-
- return Q.resolve();
-}
-
-/**
- * Test whether a project name is acceptable for use as an android class.
- * Returns a promise, fulfilled if the project name is acceptable; rejected
- * otherwise.
- */
-function validateProjectName(project_name) {
- var msg = 'Error validating project name. ';
- //Make sure there's something there
- if (project_name === '') {
- return Q.reject(new CordovaError(msg + 'Project name cannot be empty'));
- }
-
- //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
- if (/^[0-9]/.test(project_name)) {
- return Q.reject(new CordovaError(msg + 'Project name must not begin with a number'));
- }
-
- return Q.resolve();
-}
-
-/**
- * Creates an android application with the given options.
- *
- * @param {String} project_path Path to the new Cordova android project.
- * @param {ConfigParser} config Instance of ConfigParser to retrieve basic
- * project properties.
- * @param {Object} [options={}] Various options
- * @param {String} [options.activityName='MainActivity'] Name for the
- * activity
- * @param {Boolean} [options.link=false] Specifies whether javascript files
- * and CordovaLib framework will be symlinked to created application.
- * @param {String} [options.customTemplate] Path to project template
- * (override)
- * @param {EventEmitter} [events] An EventEmitter instance for logging
- * events
- *
- * @return {Promise<String>} Directory where application has been created
- */
-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)) {
- 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';
-
- var safe_activity_name = config.android_activityName() || options.activityName || 'MainActivity';
- var target_api = check_reqs.get_target();
-
- //Make the package conform to Java package types
- return validatePackageName(package_name)
- .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);
- events.emit('log', '\tPackage: ' + package_name);
- events.emit('log', '\tName: ' + project_name);
- events.emit('log', '\tActivity: ' + safe_activity_name);
- events.emit('log', '\tAndroid target: ' + target_api);
-
- events.emit('verbose', 'Copying template files...');
-
- setShellFatal(true, function() {
- var project_template_dir = options.customTemplate || path.join(ROOT, 'bin', 'templates', 'project');
- // copy project template
- shell.cp('-r', path.join(project_template_dir, 'assets'), project_path);
- shell.cp('-r', path.join(project_template_dir, 'res'), project_path);
- shell.cp(path.join(project_template_dir, 'gitignore'), path.join(project_path, '.gitignore'));
-
- // Manually create directories that would be empty within the template (since git doesn't track directories).
- shell.mkdir(path.join(project_path, 'libs'));
-
- // copy cordova.js, cordova.jar
- copyJsAndLibrary(project_path, options.link, safe_activity_name);
-
- // interpolate the activity name and package
- var packagePath = package_name.replace(/\./g, path.sep);
- var activity_dir = path.join(project_path, 'src', packagePath);
- var activity_path = path.join(activity_dir, safe_activity_name + '.java');
- shell.mkdir('-p', activity_dir);
- shell.cp('-f', path.join(project_template_dir, 'Activity.java'), activity_path);
- shell.sed('-i', /__ACTIVITY__/, safe_activity_name, activity_path);
- shell.sed('-i', /__NAME__/, project_name, path.join(project_path, 'res', 'values', 'strings.xml'));
- shell.sed('-i', /__ID__/, package_name, activity_path);
-
- var manifest = new AndroidManifest(path.join(project_template_dir, 'AndroidManifest.xml'));
- manifest.setPackageId(package_name)
- .setTargetSdkVersion(target_api.split('-')[1])
- .getActivity().setName(safe_activity_name);
-
- var manifest_path = path.join(project_path, 'AndroidManifest.xml');
- manifest.write(manifest_path);
-
- copyScripts(project_path);
- copyBuildRules(project_path);
- });
- // Link it to local android install.
- writeProjectProperties(project_path, target_api);
- prepBuildFiles(project_path);
- events.emit('log', generateDoneMessage('create', options.link));
- }).thenResolve(project_path);
-};
-
-function generateDoneMessage(type, link) {
- var pkg = require('../../package');
- var msg = 'Android project ' + (type == 'update' ? 'updated ' : 'created ') + 'with ' + pkg.name + '@' + pkg.version;
- if (link) {
- msg += ' and has a linked CordovaLib';
- }
- return msg;
-}
-
-// Returns a promise.
-exports.update = function(projectPath, options, events) {
- options = options || {};
-
- return Q()
- .then(function() {
-
- var manifest = new AndroidManifest(path.join(projectPath, 'AndroidManifest.xml'));
-
- 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();
-
- var projectName = manifest.getActivity().getName();
- var target_api = check_reqs.get_target();
-
- copyJsAndLibrary(projectPath, options.link, projectName);
- copyScripts(projectPath);
- copyBuildRules(projectPath);
- writeProjectProperties(projectPath, target_api);
- prepBuildFiles(projectPath);
- events.emit('log', generateDoneMessage('update', options.link));
- }).thenResolve(projectPath);
-};
-
-
-// For testing
-exports.validatePackageName = validatePackageName;
-exports.validateProjectName = validateProjectName;
+#!/usr/bin/env node
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+var shell = require('shelljs'),
+ Q = require('q'),
+ path = require('path'),
+ fs = require('fs'),
+ check_reqs = require('./check_reqs'),
+ ROOT = path.join(__dirname, '..', '..');
+
+var MIN_SDK_VERSION = 14;
+
+var CordovaError = require('cordova-common').CordovaError;
+var AndroidManifest = require('../templates/cordova/lib/AndroidManifest');
+
+function setShellFatal(value, func) {
+ var oldVal = shell.config.fatal;
+ shell.config.fatal = value;
+ func();
+ shell.config.fatal = oldVal;
+}
+
+function getFrameworkDir(projectPath, shared) {
+ return shared ? path.join(ROOT, 'framework') : path.join(projectPath, 'CordovaLib');
+}
+
+function copyJsAndLibrary(projectPath, shared, projectName) {
+ var nestedCordovaLibPath = getFrameworkDir(projectPath, false);
+ var srcCordovaJsPath = path.join(ROOT, 'bin', 'templates', 'project', 'assets', 'www', 'cordova.js');
+ shell.cp('-f', srcCordovaJsPath, path.join(projectPath, 'assets', 'www', 'cordova.js'));
+
+ // Copy the cordova.js file to platforms/<platform>/platform_www/
+ // The www dir is nuked on each prepare so we keep cordova.js in platform_www
+ shell.mkdir('-p', path.join(projectPath, 'platform_www'));
+ shell.cp('-f', srcCordovaJsPath, path.join(projectPath, 'platform_www'));
+
+ // Copy cordova-js-src directory into platform_www directory.
+ // 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.
+ setShellFatal(false, function() {
+ shell.ls(path.join(projectPath, 'libs', 'cordova-*.jar')).forEach(function(oldJar) {
+ console.log('Deleting ' + oldJar);
+ shell.rm('-f', oldJar);
+ });
+ var wasSymlink = true;
+ try {
+ // Delete the symlink if it was one.
+ fs.unlinkSync(nestedCordovaLibPath);
+ } catch (e) {
+ wasSymlink = false;
+ }
+ // Delete old library project if it existed.
+ if (shared) {
+ shell.rm('-rf', nestedCordovaLibPath);
+ } else if (!wasSymlink) {
+ // Delete only the src, since Eclipse / Android Studio can't handle their project files being deleted.
+ shell.rm('-rf', path.join(nestedCordovaLibPath, 'src'));
+ }
+ });
+ if (shared) {
+ var relativeFrameworkPath = path.relative(projectPath, getFrameworkDir(projectPath, true));
+ fs.symlinkSync(relativeFrameworkPath, nestedCordovaLibPath, 'dir');
+ } else {
+ shell.mkdir('-p', nestedCordovaLibPath);
+ shell.cp('-f', path.join(ROOT, 'framework', 'AndroidManifest.xml'), nestedCordovaLibPath);
+ shell.cp('-f', path.join(ROOT, 'framework', 'project.properties'), nestedCordovaLibPath);
+ shell.cp('-f', path.join(ROOT, 'framework', 'build.gradle'), nestedCordovaLibPath);
+ shell.cp('-f', path.join(ROOT, 'framework', 'cordova.gradle'), nestedCordovaLibPath);
+ shell.cp('-r', path.join(ROOT, 'framework', 'src'), nestedCordovaLibPath);
+ }
+}
+
+function extractSubProjectPaths(data) {
+ var ret = {};
+ var r = /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg;
+ var m;
+ while ((m = r.exec(data))) {
+ ret[m[1]] = 1;
+ }
+ return Object.keys(ret);
+}
+
+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;
+
+ var data = fs.readFileSync(srcPath, 'utf8');
+ data = data.replace(/^target=.*/m, 'target=' + target_api);
+ var subProjects = extractSubProjectPaths(data);
+ subProjects = subProjects.filter(function(p) {
+ return !(/^CordovaLib$/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, '');
+ if (!/\n$/.exec(data)) {
+ data += '\n';
+ }
+ for (var i = 0; i < subProjects.length; ++i) {
+ data += 'android.library.reference.' + (i+1) + '=' + subProjects[i] + '\n';
+ }
+ fs.writeFileSync(dstPath, data);
+}
+
+function prepBuildFiles(projectPath) {
+ var buildModule = require(path.join(path.resolve(projectPath), 'cordova', 'lib', 'build'));
+ buildModule.prepBuildFiles();
+}
+
+function copyBuildRules(projectPath) {
+ var srcDir = path.join(ROOT, 'bin', 'templates', 'project');
+
+ shell.cp('-f', path.join(srcDir, 'build.gradle'), projectPath);
+}
+
+function copyScripts(projectPath) {
+ var srcScriptsDir = path.join(ROOT, 'bin', 'templates', 'cordova');
+ var destScriptsDir = path.join(projectPath, 'cordova');
+ // Delete old scripts directory if this is an update.
+ shell.rm('-rf', destScriptsDir);
+ // Copy in the new ones.
+ shell.cp('-r', srcScriptsDir, projectPath);
+ shell.cp('-r', path.join(ROOT, 'node_modules'), destScriptsDir);
+ shell.cp(path.join(ROOT, 'bin', 'check_reqs*'), destScriptsDir);
+ shell.cp(path.join(ROOT, 'bin', 'lib', 'check_reqs.js'), path.join(projectPath, 'cordova', 'lib', 'check_reqs.js'));
+ shell.cp(path.join(ROOT, 'bin', 'android_sdk_version'), path.join(destScriptsDir, 'android_sdk_version'));
+ shell.cp(path.join(ROOT, 'bin', 'lib', 'android_sdk_version.js'), path.join(projectPath, 'cordova', 'lib', 'android_sdk_version.js'));
+}
+
+/**
+ * Test whether a package name is acceptable for use as an android project.
+ * 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
+ 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)) {
+ return Q.reject(new CordovaError(msg + '"class" is a reserved word'));
+ }
+
+ return Q.resolve();
+}
+
+/**
+ * Test whether a project name is acceptable for use as an android class.
+ * Returns a promise, fulfilled if the project name is acceptable; rejected
+ * otherwise.
+ */
+function validateProjectName(project_name) {
+ var msg = 'Error validating project name. ';
+ //Make sure there's something there
+ if (project_name === '') {
+ return Q.reject(new CordovaError(msg + 'Project name cannot be empty'));
+ }
+
+ //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
+ if (/^[0-9]/.test(project_name)) {
+ return Q.reject(new CordovaError(msg + 'Project name must not begin with a number'));
+ }
+
+ return Q.resolve();
+}
+
+/**
+ * Creates an android application with the given options.
+ *
+ * @param {String} project_path Path to the new Cordova android project.
+ * @param {ConfigParser} config Instance of ConfigParser to retrieve basic
+ * project properties.
+ * @param {Object} [options={}] Various options
+ * @param {String} [options.activityName='MainActivity'] Name for the
+ * activity
+ * @param {Boolean} [options.link=false] Specifies whether javascript files
+ * and CordovaLib framework will be symlinked to created application.
+ * @param {String} [options.customTemplate] Path to project template
+ * (override)
+ * @param {EventEmitter} [events] An EventEmitter instance for logging
+ * events
+ *
+ * @return {Promise<String>} Directory where application has been created
+ */
+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)) {
+ 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';
+
+ var safe_activity_name = config.android_activityName() || options.activityName || 'MainActivity';
+ var target_api = check_reqs.get_target();
+
+ //Make the package conform to Java package types
+ return validatePackageName(package_name)
+ .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);
+ events.emit('log', '\tPackage: ' + package_name);
+ events.emit('log', '\tName: ' + project_name);
+ events.emit('log', '\tActivity: ' + safe_activity_name);
+ events.emit('log', '\tAndroid target: ' + target_api);
+
+ events.emit('verbose', 'Copying template files...');
+
+ setShellFatal(true, function() {
+ var project_template_dir = options.customTemplate || path.join(ROOT, 'bin', 'templates', 'project');
+ // copy project template
+ shell.cp('-r', path.join(project_template_dir, 'assets'), project_path);
+ shell.cp('-r', path.join(project_template_dir, 'res'), project_path);
+ shell.cp(path.join(project_template_dir, 'gitignore'), path.join(project_path, '.gitignore'));
+
+ // Manually create directories that would be empty within the template (since git doesn't track directories).
+ shell.mkdir(path.join(project_path, 'libs'));
+
+ // copy cordova.js, cordova.jar
+ copyJsAndLibrary(project_path, options.link, safe_activity_name);
+
+ // interpolate the activity name and package
+ var packagePath = package_name.replace(/\./g, path.sep);
+ var activity_dir = path.join(project_path, 'src', packagePath);
+ var activity_path = path.join(activity_dir, safe_activity_name + '.java');
+ shell.mkdir('-p', activity_dir);
+ shell.cp('-f', path.join(project_template_dir, 'Activity.java'), activity_path);
+ shell.sed('-i', /__ACTIVITY__/, safe_activity_name, activity_path);
+ shell.sed('-i', /__NAME__/, project_name, path.join(project_path, 'res', 'values', 'strings.xml'));
+ shell.sed('-i', /__ID__/, package_name, activity_path);
+
+ var manifest = new AndroidManifest(path.join(project_template_dir, 'AndroidManifest.xml'));
+ manifest.setPackageId(package_name)
+ .setTargetSdkVersion(target_api.split('-')[1])
+ .getActivity().setName(safe_activity_name);
+
+ var manifest_path = path.join(project_path, 'AndroidManifest.xml');
+ manifest.write(manifest_path);
+
+ copyScripts(project_path);
+ copyBuildRules(project_path);
+ });
+ // Link it to local android install.
+ writeProjectProperties(project_path, target_api);
+ prepBuildFiles(project_path);
+ events.emit('log', generateDoneMessage('create', options.link));
+ }).thenResolve(project_path);
+};
+
+function generateDoneMessage(type, link) {
+ var pkg = require('../../package');
+ var msg = 'Android project ' + (type == 'update' ? 'updated ' : 'created ') + 'with ' + pkg.name + '@' + pkg.version;
+ if (link) {
+ msg += ' and has a linked CordovaLib';
+ }
+ return msg;
+}
+
+// Returns a promise.
+exports.update = function(projectPath, options, events) {
+ options = options || {};
+
+ return Q()
+ .then(function() {
+
+ var manifest = new AndroidManifest(path.join(projectPath, 'AndroidManifest.xml'));
+
+ 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();
+
+ var projectName = manifest.getActivity().getName();
+ var target_api = check_reqs.get_target();
+
+ copyJsAndLibrary(projectPath, options.link, projectName);
+ copyScripts(projectPath);
+ copyBuildRules(projectPath);
+ writeProjectProperties(projectPath, target_api);
+ prepBuildFiles(projectPath);
+ events.emit('log', generateDoneMessage('update', options.link));
+ }).thenResolve(projectPath);
+};
+
+
+// For testing
+exports.validatePackageName = validatePackageName;
+exports.validateProjectName = validateProjectName;
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org
[2/4] android commit: Fixed line endings
Posted by st...@apache.org.
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/0ac822c5/bin/templates/cordova/lib/build.js
----------------------------------------------------------------------
diff --git a/bin/templates/cordova/lib/build.js b/bin/templates/cordova/lib/build.js
index db692e9..9e57cb8 100644
--- a/bin/templates/cordova/lib/build.js
+++ b/bin/templates/cordova/lib/build.js
@@ -1,301 +1,301 @@
-#!/usr/bin/env node
-
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-var Q = require('q'),
- path = require('path'),
- fs = require('fs'),
- nopt = require('nopt');
-
-var Adb = require('./Adb');
-
-var builders = require('./builders/builders');
-var events = require('cordova-common').events;
-var spawn = require('cordova-common').superspawn.spawn;
-var CordovaError = require('cordova-common').CordovaError;
-
-function parseOpts(options, resolvedTarget) {
- options = options || {};
- options.argv = nopt({
- gradle: Boolean,
- ant: Boolean,
- prepenv: Boolean,
- versionCode: String,
- minSdkVersion: String,
- gradleArg: String,
- keystore: path,
- alias: String,
- storePassword: String,
- password: String,
- keystoreType: String
- }, {}, options.argv, 0);
-
- var ret = {
- buildType: options.release ? 'release' : 'debug',
- buildMethod: process.env.ANDROID_BUILD || 'gradle',
- prepEnv: options.argv.prepenv,
- arch: resolvedTarget && resolvedTarget.arch,
- extraArgs: []
- };
-
- if (options.argv.ant || options.argv.gradle)
- ret.buildMethod = options.argv.ant ? 'ant' : 'gradle';
-
- if (options.nobuild) ret.buildMethod = 'none';
-
- if (options.argv.versionCode)
- ret.extraArgs.push('-PcdvVersionCode=' + options.versionCode);
-
- if (options.argv.minSdkVersion)
- ret.extraArgs.push('-PcdvMinSdkVersion=' + options.minSdkVersion);
-
- if (options.argv.gradleArg)
- ret.extraArgs.push(options.gradleArg);
-
- var packageArgs = {};
-
- if (options.argv.keystore)
- packageArgs.keystore = path.relative(this.root, path.resolve(options.argv.keystore));
-
- ['alias','storePassword','password','keystoreType'].forEach(function (flagName) {
- if (options.argv[flagName])
- packageArgs[flagName] = options.argv[flagName];
- });
-
- var buildConfig = options.buildConfig;
-
- // If some values are not specified as command line arguments - use build config to supplement them.
- // Command line arguemnts have precedence over build config.
- if (buildConfig) {
- 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));
- var config = JSON.parse(fs.readFileSync(buildConfig, 'utf8'));
- if (config.android && config.android[ret.buildType]) {
- var androidInfo = config.android[ret.buildType];
- if(androidInfo.keystore && !packageArgs.keystore) {
- packageArgs.keystore = path.resolve(path.dirname(buildConfig), androidInfo.keystore);
- }
-
- ['alias', 'storePassword', 'password','keystoreType'].forEach(function (key){
- packageArgs[key] = packageArgs[key] || androidInfo[key];
- });
- }
- }
-
- if (packageArgs.keystore && packageArgs.alias) {
- ret.packageInfo = new PackageInfo(packageArgs.keystore, packageArgs.alias, packageArgs.storePassword,
- packageArgs.password, packageArgs.keystoreType);
- }
-
- if(!ret.packageInfo) {
- if(Object.keys(packageArgs).length > 0) {
- events.emit('warn', '\'keystore\' and \'alias\' need to be specified to generate a signed archive.');
- }
- }
-
- return ret;
-}
-
-/*
- * Builds the project with the specifed options
- * Returns a promise.
- */
-module.exports.runClean = function(options) {
- var opts = parseOpts(options);
- var builder = builders.getBuilder(opts.buildMethod);
- return builder.prepEnv(opts)
- .then(function() {
- return builder.clean(opts);
- });
-};
-
-/**
- * Builds the project with the specifed options.
- *
- * @param {BuildOptions} options A set of options. See PlatformApi.build
- * method documentation for reference.
- * @param {Object} optResolvedTarget A deployment target. Used to pass
- * target architecture from upstream 'run' call. TODO: remove this option in
- * favor of setting buildOptions.archs field.
- *
- * @return {Promise<Object>} Promise, resolved with built packages
- * information.
- */
-module.exports.run = function(options, optResolvedTarget) {
- var opts = parseOpts(options, optResolvedTarget);
- var builder = builders.getBuilder(opts.buildMethod);
- var self = this;
- return builder.prepEnv(opts)
- .then(function() {
- if (opts.prepEnv) {
- self.events.emit('verbose', 'Build file successfully prepared.');
- return;
- }
- return builder.build(opts)
- .then(function() {
- var apkPaths = builder.findOutputApks(opts.buildType, opts.arch);
- self.events.emit('log', 'Built the following apk(s): \n\t' + apkPaths.join('\n\t'));
- return {
- apkPaths: apkPaths,
- buildType: opts.buildType,
- buildMethod: opts.buildMethod
- };
- });
- });
-};
-
-// Called by plugman after installing plugins, and by create script after creating project.
-module.exports.prepBuildFiles = function() {
- return builders.getBuilder('gradle').prepBuildFiles();
-};
-
-/*
- * 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) {
- 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) {
- 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.
- return spawn('killall', ['adb'])
- .then(function() {
- events.emit('verbose', 'adb seems hung. retrying.');
- return helper()
- .then(null, function() {
- // The double kill is sadly often necessary, at least on mac.
- events.emit('warn', 'Now device not found... restarting adb again.');
- return spawn('killall', ['adb'])
- .then(function() {
- return helper()
- .then(null, function() {
- return Q.reject(new CordovaError('USB is flakey. Try unplugging & replugging the device.'));
- });
- });
- });
- }, function() {
- // For non-killall OS's.
- return Q.reject(err);
- });
- }
- throw err;
- });
-};
-
-module.exports.findBestApkForArchitecture = function(buildResults, arch) {
- var paths = buildResults.apkPaths.filter(function(p) {
- var apkName = path.basename(p);
- if (buildResults.buildType == 'debug') {
- return /-debug/.exec(apkName);
- }
- return !/-debug/.exec(apkName);
- });
- var archPattern = new RegExp('-' + arch);
- var hasArchPattern = /-x86|-arm/;
- for (var i = 0; i < paths.length; ++i) {
- var apkName = path.basename(paths[i]);
- if (hasArchPattern.exec(apkName)) {
- if (archPattern.exec(apkName)) {
- return paths[i];
- }
- } else {
- return paths[i];
- }
- }
- throw new Error('Could not find apk architecture: ' + arch + ' build-type: ' + buildResults.buildType);
-};
-
-function PackageInfo(keystore, alias, storePassword, password, keystoreType) {
- this.keystore = {
- 'name': 'key.store',
- 'value': keystore
- };
- this.alias = {
- 'name': 'key.alias',
- 'value': alias
- };
- if (storePassword) {
- this.storePassword = {
- 'name': 'key.store.password',
- 'value': storePassword
- };
- }
- if (password) {
- this.password = {
- 'name': 'key.alias.password',
- 'value': password
- };
- }
- if (keystoreType) {
- this.keystoreType = {
- 'name': 'key.store.type',
- 'value': keystoreType
- };
- }
-}
-
-PackageInfo.prototype = {
- toProperties: function() {
- var self = this;
- var result = '';
- Object.keys(self).forEach(function(key) {
- result += self[key].name;
- result += '=';
- result += self[key].value.replace(/\\/g, '\\\\');
- result += '\n';
- });
- return result;
- }
-};
-
-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)');
- console.log(' \'--release\': will build project for release');
- console.log(' \'--ant\': will build project with ant');
- console.log(' \'--gradle\': will build project with gradle (default)');
- console.log(' \'--nobuild\': will skip build process (useful when using run command)');
- console.log(' \'--prepenv\': don\'t build, but copy in build scripts where necessary');
- console.log(' \'--versionCode=#\': Override versionCode for this build. Useful for uploading multiple APKs. Requires --gradle.');
- console.log(' \'--minSdkVersion=#\': Override minSdkVersion for this build. Useful for uploading multiple APKs. Requires --gradle.');
- console.log(' \'--gradleArg=<gradle command line arg>\': Extra args to pass to the gradle command. Use one flag per arg. Ex. --gradleArg=-PcdvBuildMultipleApks=true');
- console.log('');
- console.log('Signed APK flags (overwrites debug/release-signing.proprties) :');
- console.log(' \'--keystore=<path to keystore>\': Key store used to build a signed archive. (Required)');
- console.log(' \'--alias=\': Alias for the key store. (Required)');
- console.log(' \'--storePassword=\': Password for the key store. (Optional - prompted)');
- console.log(' \'--password=\': Password for the key. (Optional - prompted)');
- console.log(' \'--keystoreType\': Type of the keystore. (Optional)');
- process.exit(0);
-};
+#!/usr/bin/env node
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+var Q = require('q'),
+ path = require('path'),
+ fs = require('fs'),
+ nopt = require('nopt');
+
+var Adb = require('./Adb');
+
+var builders = require('./builders/builders');
+var events = require('cordova-common').events;
+var spawn = require('cordova-common').superspawn.spawn;
+var CordovaError = require('cordova-common').CordovaError;
+
+function parseOpts(options, resolvedTarget) {
+ options = options || {};
+ options.argv = nopt({
+ gradle: Boolean,
+ ant: Boolean,
+ prepenv: Boolean,
+ versionCode: String,
+ minSdkVersion: String,
+ gradleArg: String,
+ keystore: path,
+ alias: String,
+ storePassword: String,
+ password: String,
+ keystoreType: String
+ }, {}, options.argv, 0);
+
+ var ret = {
+ buildType: options.release ? 'release' : 'debug',
+ buildMethod: process.env.ANDROID_BUILD || 'gradle',
+ prepEnv: options.argv.prepenv,
+ arch: resolvedTarget && resolvedTarget.arch,
+ extraArgs: []
+ };
+
+ if (options.argv.ant || options.argv.gradle)
+ ret.buildMethod = options.argv.ant ? 'ant' : 'gradle';
+
+ if (options.nobuild) ret.buildMethod = 'none';
+
+ if (options.argv.versionCode)
+ ret.extraArgs.push('-PcdvVersionCode=' + options.versionCode);
+
+ if (options.argv.minSdkVersion)
+ ret.extraArgs.push('-PcdvMinSdkVersion=' + options.minSdkVersion);
+
+ if (options.argv.gradleArg)
+ ret.extraArgs.push(options.gradleArg);
+
+ var packageArgs = {};
+
+ if (options.argv.keystore)
+ packageArgs.keystore = path.relative(this.root, path.resolve(options.argv.keystore));
+
+ ['alias','storePassword','password','keystoreType'].forEach(function (flagName) {
+ if (options.argv[flagName])
+ packageArgs[flagName] = options.argv[flagName];
+ });
+
+ var buildConfig = options.buildConfig;
+
+ // If some values are not specified as command line arguments - use build config to supplement them.
+ // Command line arguemnts have precedence over build config.
+ if (buildConfig) {
+ 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));
+ var config = JSON.parse(fs.readFileSync(buildConfig, 'utf8'));
+ if (config.android && config.android[ret.buildType]) {
+ var androidInfo = config.android[ret.buildType];
+ if(androidInfo.keystore && !packageArgs.keystore) {
+ packageArgs.keystore = path.resolve(path.dirname(buildConfig), androidInfo.keystore);
+ }
+
+ ['alias', 'storePassword', 'password','keystoreType'].forEach(function (key){
+ packageArgs[key] = packageArgs[key] || androidInfo[key];
+ });
+ }
+ }
+
+ if (packageArgs.keystore && packageArgs.alias) {
+ ret.packageInfo = new PackageInfo(packageArgs.keystore, packageArgs.alias, packageArgs.storePassword,
+ packageArgs.password, packageArgs.keystoreType);
+ }
+
+ if(!ret.packageInfo) {
+ if(Object.keys(packageArgs).length > 0) {
+ events.emit('warn', '\'keystore\' and \'alias\' need to be specified to generate a signed archive.');
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * Builds the project with the specifed options
+ * Returns a promise.
+ */
+module.exports.runClean = function(options) {
+ var opts = parseOpts(options);
+ var builder = builders.getBuilder(opts.buildMethod);
+ return builder.prepEnv(opts)
+ .then(function() {
+ return builder.clean(opts);
+ });
+};
+
+/**
+ * Builds the project with the specifed options.
+ *
+ * @param {BuildOptions} options A set of options. See PlatformApi.build
+ * method documentation for reference.
+ * @param {Object} optResolvedTarget A deployment target. Used to pass
+ * target architecture from upstream 'run' call. TODO: remove this option in
+ * favor of setting buildOptions.archs field.
+ *
+ * @return {Promise<Object>} Promise, resolved with built packages
+ * information.
+ */
+module.exports.run = function(options, optResolvedTarget) {
+ var opts = parseOpts(options, optResolvedTarget);
+ var builder = builders.getBuilder(opts.buildMethod);
+ var self = this;
+ return builder.prepEnv(opts)
+ .then(function() {
+ if (opts.prepEnv) {
+ self.events.emit('verbose', 'Build file successfully prepared.');
+ return;
+ }
+ return builder.build(opts)
+ .then(function() {
+ var apkPaths = builder.findOutputApks(opts.buildType, opts.arch);
+ self.events.emit('log', 'Built the following apk(s): \n\t' + apkPaths.join('\n\t'));
+ return {
+ apkPaths: apkPaths,
+ buildType: opts.buildType,
+ buildMethod: opts.buildMethod
+ };
+ });
+ });
+};
+
+// Called by plugman after installing plugins, and by create script after creating project.
+module.exports.prepBuildFiles = function() {
+ return builders.getBuilder('gradle').prepBuildFiles();
+};
+
+/*
+ * 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) {
+ 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) {
+ 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.
+ return spawn('killall', ['adb'])
+ .then(function() {
+ events.emit('verbose', 'adb seems hung. retrying.');
+ return helper()
+ .then(null, function() {
+ // The double kill is sadly often necessary, at least on mac.
+ events.emit('warn', 'Now device not found... restarting adb again.');
+ return spawn('killall', ['adb'])
+ .then(function() {
+ return helper()
+ .then(null, function() {
+ return Q.reject(new CordovaError('USB is flakey. Try unplugging & replugging the device.'));
+ });
+ });
+ });
+ }, function() {
+ // For non-killall OS's.
+ return Q.reject(err);
+ });
+ }
+ throw err;
+ });
+};
+
+module.exports.findBestApkForArchitecture = function(buildResults, arch) {
+ var paths = buildResults.apkPaths.filter(function(p) {
+ var apkName = path.basename(p);
+ if (buildResults.buildType == 'debug') {
+ return /-debug/.exec(apkName);
+ }
+ return !/-debug/.exec(apkName);
+ });
+ var archPattern = new RegExp('-' + arch);
+ var hasArchPattern = /-x86|-arm/;
+ for (var i = 0; i < paths.length; ++i) {
+ var apkName = path.basename(paths[i]);
+ if (hasArchPattern.exec(apkName)) {
+ if (archPattern.exec(apkName)) {
+ return paths[i];
+ }
+ } else {
+ return paths[i];
+ }
+ }
+ throw new Error('Could not find apk architecture: ' + arch + ' build-type: ' + buildResults.buildType);
+};
+
+function PackageInfo(keystore, alias, storePassword, password, keystoreType) {
+ this.keystore = {
+ 'name': 'key.store',
+ 'value': keystore
+ };
+ this.alias = {
+ 'name': 'key.alias',
+ 'value': alias
+ };
+ if (storePassword) {
+ this.storePassword = {
+ 'name': 'key.store.password',
+ 'value': storePassword
+ };
+ }
+ if (password) {
+ this.password = {
+ 'name': 'key.alias.password',
+ 'value': password
+ };
+ }
+ if (keystoreType) {
+ this.keystoreType = {
+ 'name': 'key.store.type',
+ 'value': keystoreType
+ };
+ }
+}
+
+PackageInfo.prototype = {
+ toProperties: function() {
+ var self = this;
+ var result = '';
+ Object.keys(self).forEach(function(key) {
+ result += self[key].name;
+ result += '=';
+ result += self[key].value.replace(/\\/g, '\\\\');
+ result += '\n';
+ });
+ return result;
+ }
+};
+
+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)');
+ console.log(' \'--release\': will build project for release');
+ console.log(' \'--ant\': will build project with ant');
+ console.log(' \'--gradle\': will build project with gradle (default)');
+ console.log(' \'--nobuild\': will skip build process (useful when using run command)');
+ console.log(' \'--prepenv\': don\'t build, but copy in build scripts where necessary');
+ console.log(' \'--versionCode=#\': Override versionCode for this build. Useful for uploading multiple APKs. Requires --gradle.');
+ console.log(' \'--minSdkVersion=#\': Override minSdkVersion for this build. Useful for uploading multiple APKs. Requires --gradle.');
+ console.log(' \'--gradleArg=<gradle command line arg>\': Extra args to pass to the gradle command. Use one flag per arg. Ex. --gradleArg=-PcdvBuildMultipleApks=true');
+ console.log('');
+ console.log('Signed APK flags (overwrites debug/release-signing.proprties) :');
+ console.log(' \'--keystore=<path to keystore>\': Key store used to build a signed archive. (Required)');
+ console.log(' \'--alias=\': Alias for the key store. (Required)');
+ console.log(' \'--storePassword=\': Password for the key store. (Optional - prompted)');
+ console.log(' \'--password=\': Password for the key. (Optional - prompted)');
+ console.log(' \'--keystoreType\': Type of the keystore. (Optional)');
+ process.exit(0);
+};
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/0ac822c5/bin/templates/cordova/lib/builders/AntBuilder.js
----------------------------------------------------------------------
diff --git a/bin/templates/cordova/lib/builders/AntBuilder.js b/bin/templates/cordova/lib/builders/AntBuilder.js
index dd47227..d214f48 100644
--- a/bin/templates/cordova/lib/builders/AntBuilder.js
+++ b/bin/templates/cordova/lib/builders/AntBuilder.js
@@ -1,141 +1,141 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-var Q = require('q');
-var fs = require('fs');
-var path = require('path');
-var util = require('util');
-var shell = require('shelljs');
-var spawn = require('cordova-common').superspawn.spawn;
-var CordovaError = require('cordova-common').CordovaError;
-var check_reqs = require('../check_reqs');
-
-var SIGNING_PROPERTIES = '-signing.properties';
-var MARKER = 'YOUR CHANGES WILL BE ERASED!';
-var TEMPLATE =
- '# This file is automatically generated.\n' +
- '# Do not modify this file -- ' + MARKER + '\n';
-
-var GenericBuilder = require('./GenericBuilder');
-
-function AntBuilder (projectRoot) {
- GenericBuilder.call(this, projectRoot);
-
- this.binDirs = {ant: this.binDirs.ant};
-}
-
-util.inherits(AntBuilder, GenericBuilder);
-
-AntBuilder.prototype.getArgs = function(cmd, opts) {
- var args = [cmd, '-f', path.join(this.root, 'build.xml')];
- // custom_rules.xml is required for incremental builds.
- if (hasCustomRules()) {
- args.push('-Dout.dir=ant-build', '-Dgen.absolute.dir=ant-gen');
- }
- if(opts.packageInfo) {
- args.push('-propertyfile=' + path.join(this.root, opts.buildType + SIGNING_PROPERTIES));
- }
- return args;
-};
-
-AntBuilder.prototype.prepEnv = function(opts) {
- var self = this;
- return check_reqs.check_ant()
- .then(function() {
- // Copy in build.xml on each build so that:
- // A) we don't require the Android SDK at project creation time, and
- // B) we always use the SDK's latest version of it.
- /*jshint -W069 */
- var sdkDir = process.env['ANDROID_HOME'];
- /*jshint +W069 */
- var buildTemplate = fs.readFileSync(path.join(sdkDir, 'tools', 'lib', 'build.template'), 'utf8');
- function writeBuildXml(projectPath) {
- var newData = buildTemplate.replace('PROJECT_NAME', self.extractRealProjectNameFromManifest());
- fs.writeFileSync(path.join(projectPath, 'build.xml'), newData);
- if (!fs.existsSync(path.join(projectPath, 'local.properties'))) {
- fs.writeFileSync(path.join(projectPath, 'local.properties'), TEMPLATE);
- }
- }
- writeBuildXml(self.root);
- var propertiesObj = self.readProjectProperties();
- var subProjects = propertiesObj.libs;
- for (var i = 0; i < subProjects.length; ++i) {
- writeBuildXml(path.join(self.root, subProjects[i]));
- }
- if (propertiesObj.systemLibs.length > 0) {
- throw new CordovaError('Project contains at least one plugin that requires a system library. This is not supported with ANT. Please build using gradle.');
- }
-
- var propertiesFile = opts.buildType + SIGNING_PROPERTIES;
- var propertiesFilePath = path.join(self.root, propertiesFile);
- if (opts.packageInfo) {
- fs.writeFileSync(propertiesFilePath, TEMPLATE + opts.packageInfo.toProperties());
- } else if(isAutoGenerated(propertiesFilePath)) {
- shell.rm('-f', propertiesFilePath);
- }
- });
-};
-
-/*
- * Builds the project with ant.
- * Returns a promise.
- */
-AntBuilder.prototype.build = function(opts) {
- // Without our custom_rules.xml, we need to clean before building.
- var ret = Q();
- if (!hasCustomRules()) {
- // clean will call check_ant() for us.
- ret = this.clean(opts);
- }
-
- var args = this.getArgs(opts.buildType == 'debug' ? 'debug' : 'release', opts);
- return check_reqs.check_ant()
- .then(function() {
- return spawn('ant', args, {stdio: 'inherit'});
- });
-};
-
-AntBuilder.prototype.clean = function(opts) {
- var args = this.getArgs('clean', opts);
- var self = this;
- return check_reqs.check_ant()
- .then(function() {
- return spawn('ant', args, {stdio: 'inherit'});
- })
- .then(function () {
- shell.rm('-rf', path.join(self.root, 'out'));
-
- ['debug', 'release'].forEach(function(config) {
- var propertiesFilePath = path.join(self.root, config + SIGNING_PROPERTIES);
- if(isAutoGenerated(propertiesFilePath)){
- shell.rm('-f', propertiesFilePath);
- }
- });
- });
-};
-
-module.exports = AntBuilder;
-
-function hasCustomRules(projectRoot) {
- return fs.existsSync(path.join(projectRoot, 'custom_rules.xml'));
-}
-
-function isAutoGenerated(file) {
- return fs.existsSync(file) && fs.readFileSync(file, 'utf8').indexOf(MARKER) > 0;
-}
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+var Q = require('q');
+var fs = require('fs');
+var path = require('path');
+var util = require('util');
+var shell = require('shelljs');
+var spawn = require('cordova-common').superspawn.spawn;
+var CordovaError = require('cordova-common').CordovaError;
+var check_reqs = require('../check_reqs');
+
+var SIGNING_PROPERTIES = '-signing.properties';
+var MARKER = 'YOUR CHANGES WILL BE ERASED!';
+var TEMPLATE =
+ '# This file is automatically generated.\n' +
+ '# Do not modify this file -- ' + MARKER + '\n';
+
+var GenericBuilder = require('./GenericBuilder');
+
+function AntBuilder (projectRoot) {
+ GenericBuilder.call(this, projectRoot);
+
+ this.binDirs = {ant: this.binDirs.ant};
+}
+
+util.inherits(AntBuilder, GenericBuilder);
+
+AntBuilder.prototype.getArgs = function(cmd, opts) {
+ var args = [cmd, '-f', path.join(this.root, 'build.xml')];
+ // custom_rules.xml is required for incremental builds.
+ if (hasCustomRules()) {
+ args.push('-Dout.dir=ant-build', '-Dgen.absolute.dir=ant-gen');
+ }
+ if(opts.packageInfo) {
+ args.push('-propertyfile=' + path.join(this.root, opts.buildType + SIGNING_PROPERTIES));
+ }
+ return args;
+};
+
+AntBuilder.prototype.prepEnv = function(opts) {
+ var self = this;
+ return check_reqs.check_ant()
+ .then(function() {
+ // Copy in build.xml on each build so that:
+ // A) we don't require the Android SDK at project creation time, and
+ // B) we always use the SDK's latest version of it.
+ /*jshint -W069 */
+ var sdkDir = process.env['ANDROID_HOME'];
+ /*jshint +W069 */
+ var buildTemplate = fs.readFileSync(path.join(sdkDir, 'tools', 'lib', 'build.template'), 'utf8');
+ function writeBuildXml(projectPath) {
+ var newData = buildTemplate.replace('PROJECT_NAME', self.extractRealProjectNameFromManifest());
+ fs.writeFileSync(path.join(projectPath, 'build.xml'), newData);
+ if (!fs.existsSync(path.join(projectPath, 'local.properties'))) {
+ fs.writeFileSync(path.join(projectPath, 'local.properties'), TEMPLATE);
+ }
+ }
+ writeBuildXml(self.root);
+ var propertiesObj = self.readProjectProperties();
+ var subProjects = propertiesObj.libs;
+ for (var i = 0; i < subProjects.length; ++i) {
+ writeBuildXml(path.join(self.root, subProjects[i]));
+ }
+ if (propertiesObj.systemLibs.length > 0) {
+ throw new CordovaError('Project contains at least one plugin that requires a system library. This is not supported with ANT. Please build using gradle.');
+ }
+
+ var propertiesFile = opts.buildType + SIGNING_PROPERTIES;
+ var propertiesFilePath = path.join(self.root, propertiesFile);
+ if (opts.packageInfo) {
+ fs.writeFileSync(propertiesFilePath, TEMPLATE + opts.packageInfo.toProperties());
+ } else if(isAutoGenerated(propertiesFilePath)) {
+ shell.rm('-f', propertiesFilePath);
+ }
+ });
+};
+
+/*
+ * Builds the project with ant.
+ * Returns a promise.
+ */
+AntBuilder.prototype.build = function(opts) {
+ // Without our custom_rules.xml, we need to clean before building.
+ var ret = Q();
+ if (!hasCustomRules()) {
+ // clean will call check_ant() for us.
+ ret = this.clean(opts);
+ }
+
+ var args = this.getArgs(opts.buildType == 'debug' ? 'debug' : 'release', opts);
+ return check_reqs.check_ant()
+ .then(function() {
+ return spawn('ant', args, {stdio: 'inherit'});
+ });
+};
+
+AntBuilder.prototype.clean = function(opts) {
+ var args = this.getArgs('clean', opts);
+ var self = this;
+ return check_reqs.check_ant()
+ .then(function() {
+ return spawn('ant', args, {stdio: 'inherit'});
+ })
+ .then(function () {
+ shell.rm('-rf', path.join(self.root, 'out'));
+
+ ['debug', 'release'].forEach(function(config) {
+ var propertiesFilePath = path.join(self.root, config + SIGNING_PROPERTIES);
+ if(isAutoGenerated(propertiesFilePath)){
+ shell.rm('-f', propertiesFilePath);
+ }
+ });
+ });
+};
+
+module.exports = AntBuilder;
+
+function hasCustomRules(projectRoot) {
+ return fs.existsSync(path.join(projectRoot, 'custom_rules.xml'));
+}
+
+function isAutoGenerated(file) {
+ return fs.existsSync(file) && fs.readFileSync(file, 'utf8').indexOf(MARKER) > 0;
+}
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/0ac822c5/bin/templates/cordova/lib/builders/GradleBuilder.js
----------------------------------------------------------------------
diff --git a/bin/templates/cordova/lib/builders/GradleBuilder.js b/bin/templates/cordova/lib/builders/GradleBuilder.js
index 7611423..0f613cc 100644
--- a/bin/templates/cordova/lib/builders/GradleBuilder.js
+++ b/bin/templates/cordova/lib/builders/GradleBuilder.js
@@ -1,213 +1,213 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-var Q = require('q');
-var fs = require('fs');
-var util = require('util');
-var path = require('path');
-var shell = require('shelljs');
-var spawn = require('cordova-common').superspawn.spawn;
-var CordovaError = require('cordova-common').CordovaError;
-var check_reqs = require('../check_reqs');
-
-var GenericBuilder = require('./GenericBuilder');
-
-var MARKER = 'YOUR CHANGES WILL BE ERASED!';
-var SIGNING_PROPERTIES = '-signing.properties';
-var TEMPLATE =
- '# This file is automatically generated.\n' +
- '# Do not modify this file -- ' + MARKER + '\n';
-
-function GradleBuilder (projectRoot) {
- GenericBuilder.call(this, projectRoot);
-
- this.binDirs = {gradle: this.binDirs.gradle};
-}
-
-util.inherits(GradleBuilder, GenericBuilder);
-
-GradleBuilder.prototype.getArgs = function(cmd, opts) {
- if (cmd == 'release') {
- cmd = 'cdvBuildRelease';
- } else if (cmd == 'debug') {
- cmd = 'cdvBuildDebug';
- }
- var args = [cmd, '-b', path.join(this.root, 'build.gradle')];
- if (opts.arch) {
- args.push('-PcdvBuildArch=' + opts.arch);
- }
-
- // 10 seconds -> 6 seconds
- args.push('-Dorg.gradle.daemon=true');
- args.push.apply(args, opts.extraArgs);
- // Shaves another 100ms, but produces a "try at own risk" warning. Not worth it (yet):
- // args.push('-Dorg.gradle.parallel=true');
- return args;
-};
-
-// Makes the project buildable, minus the gradle wrapper.
-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();
- var subProjects = propertiesObj.libs;
- for (var i = 0; i < subProjects.length; ++i) {
- if (subProjects[i] !== 'CordovaLib') {
- shell.cp('-f', pluginBuildGradle, path.join(this.root, subProjects[i], 'build.gradle'));
- }
- }
-
- 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';
- return str;
- });
-
- // Write the settings.gradle file.
- fs.writeFileSync(path.join(this.root, 'settings.gradle'),
- '// GENERATED FILE - DO NOT EDIT\n' +
- 'include ":"\n' + settingsGradlePaths.join(''));
- // Update dependencies within build.gradle.
- var buildGradle = fs.readFileSync(path.join(this.root, 'build.gradle'), 'utf8');
- var depsList = '';
- subProjects.forEach(function(p) {
- var libName=p.replace(/[/\\]/g, ':').replace(name+'-','');
- depsList += ' debugCompile project(path: "' + libName + '", configuration: "debug")\n';
- depsList += ' releaseCompile project(path: "' + libName + '", configuration: "release")\n';
- });
- // For why we do this mapping: https://issues.apache.org/jira/browse/CB-8390
- var SYSTEM_LIBRARY_MAPPINGS = [
- [/^\/?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) {
- var mavenRef;
- // It's already in gradle form if it has two ':'s
- if (/:.*:/.exec(p)) {
- mavenRef = p;
- } else {
- for (var i = 0; i < SYSTEM_LIBRARY_MAPPINGS.length; ++i) {
- var pair = SYSTEM_LIBRARY_MAPPINGS[i];
- if (pair[0].exec(p)) {
- mavenRef = p.replace(pair[0], pair[1]);
- break;
- }
- }
- if (!mavenRef) {
- throw new CordovaError('Unsupported system library (does not work with gradle): ' + p);
- }
- }
- depsList += ' compile "' + mavenRef + '"\n';
- });
- buildGradle = buildGradle.replace(/(SUB-PROJECT DEPENDENCIES START)[\s\S]*(\/\/ SUB-PROJECT DEPENDENCIES END)/, '$1\n' + depsList + ' $2');
- var includeList = '';
- 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) {
- var self = this;
- return check_reqs.check_gradle()
- .then(function() {
- return self.prepBuildFiles();
- }).then(function() {
- // Copy the gradle wrapper on each build so that:
- // A) we don't require the Android SDK at project creation time, and
- // B) we always use the SDK's latest version of it.
- // check_reqs ensures that this is set.
- /*jshint -W069 */
- var sdkDir = process.env['ANDROID_HOME'];
- /*jshint +W069 */
- var wrapperDir = path.join(sdkDir, 'tools', 'templates', 'gradle', 'wrapper');
- if (process.platform == 'win32') {
- shell.rm('-f', path.join(self.root, 'gradlew.bat'));
- shell.cp(path.join(wrapperDir, 'gradlew.bat'), self.root);
- } else {
- shell.rm('-f', path.join(self.root, 'gradlew'));
- shell.cp(path.join(wrapperDir, 'gradlew'), self.root);
- }
- shell.rm('-rf', path.join(self.root, 'gradle', 'wrapper'));
- shell.mkdir('-p', path.join(self.root, 'gradle'));
- shell.cp('-r', path.join(wrapperDir, 'gradle', 'wrapper'), path.join(self.root, 'gradle'));
-
- // If the gradle distribution URL is set, make sure it points to version we want.
- // 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 */
- var distributionUrl = process.env['CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL'] || 'http\\://services.gradle.org/distributions/gradle-2.2.1-all.zip';
- /*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);
-
- var propertiesFile = opts.buildType + SIGNING_PROPERTIES;
- var propertiesFilePath = path.join(self.root, propertiesFile);
- if (opts.packageInfo) {
- fs.writeFileSync(propertiesFilePath, TEMPLATE + opts.packageInfo.toProperties());
- } else if (isAutoGenerated(propertiesFilePath)) {
- shell.rm('-f', propertiesFilePath);
- }
- });
-};
-
-/*
- * Builds the project with gradle.
- * Returns a promise.
- */
-GradleBuilder.prototype.build = function(opts) {
- var wrapper = path.join(this.root, 'gradlew');
- var args = this.getArgs(opts.buildType == 'debug' ? 'debug' : 'release', opts);
- return Q().then(function() {
- return spawn(wrapper, args, {stdio: 'inherit'});
- });
-};
-
-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 spawn(wrapper, args, {stdio: 'inherit'});
- })
- .then(function () {
- shell.rm('-rf', path.join(builder.root, 'out'));
-
- ['debug', 'release'].forEach(function(config) {
- var propertiesFilePath = path.join(builder.root, config + SIGNING_PROPERTIES);
- if(isAutoGenerated(propertiesFilePath)){
- shell.rm('-f', propertiesFilePath);
- }
- });
- });
-};
-
-module.exports = GradleBuilder;
-
-function isAutoGenerated(file) {
- return fs.existsSync(file) && fs.readFileSync(file, 'utf8').indexOf(MARKER) > 0;
-}
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+var Q = require('q');
+var fs = require('fs');
+var util = require('util');
+var path = require('path');
+var shell = require('shelljs');
+var spawn = require('cordova-common').superspawn.spawn;
+var CordovaError = require('cordova-common').CordovaError;
+var check_reqs = require('../check_reqs');
+
+var GenericBuilder = require('./GenericBuilder');
+
+var MARKER = 'YOUR CHANGES WILL BE ERASED!';
+var SIGNING_PROPERTIES = '-signing.properties';
+var TEMPLATE =
+ '# This file is automatically generated.\n' +
+ '# Do not modify this file -- ' + MARKER + '\n';
+
+function GradleBuilder (projectRoot) {
+ GenericBuilder.call(this, projectRoot);
+
+ this.binDirs = {gradle: this.binDirs.gradle};
+}
+
+util.inherits(GradleBuilder, GenericBuilder);
+
+GradleBuilder.prototype.getArgs = function(cmd, opts) {
+ if (cmd == 'release') {
+ cmd = 'cdvBuildRelease';
+ } else if (cmd == 'debug') {
+ cmd = 'cdvBuildDebug';
+ }
+ var args = [cmd, '-b', path.join(this.root, 'build.gradle')];
+ if (opts.arch) {
+ args.push('-PcdvBuildArch=' + opts.arch);
+ }
+
+ // 10 seconds -> 6 seconds
+ args.push('-Dorg.gradle.daemon=true');
+ args.push.apply(args, opts.extraArgs);
+ // Shaves another 100ms, but produces a "try at own risk" warning. Not worth it (yet):
+ // args.push('-Dorg.gradle.parallel=true');
+ return args;
+};
+
+// Makes the project buildable, minus the gradle wrapper.
+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();
+ var subProjects = propertiesObj.libs;
+ for (var i = 0; i < subProjects.length; ++i) {
+ if (subProjects[i] !== 'CordovaLib') {
+ shell.cp('-f', pluginBuildGradle, path.join(this.root, subProjects[i], 'build.gradle'));
+ }
+ }
+
+ 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';
+ return str;
+ });
+
+ // Write the settings.gradle file.
+ fs.writeFileSync(path.join(this.root, 'settings.gradle'),
+ '// GENERATED FILE - DO NOT EDIT\n' +
+ 'include ":"\n' + settingsGradlePaths.join(''));
+ // Update dependencies within build.gradle.
+ var buildGradle = fs.readFileSync(path.join(this.root, 'build.gradle'), 'utf8');
+ var depsList = '';
+ subProjects.forEach(function(p) {
+ var libName=p.replace(/[/\\]/g, ':').replace(name+'-','');
+ depsList += ' debugCompile project(path: "' + libName + '", configuration: "debug")\n';
+ depsList += ' releaseCompile project(path: "' + libName + '", configuration: "release")\n';
+ });
+ // For why we do this mapping: https://issues.apache.org/jira/browse/CB-8390
+ var SYSTEM_LIBRARY_MAPPINGS = [
+ [/^\/?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) {
+ var mavenRef;
+ // It's already in gradle form if it has two ':'s
+ if (/:.*:/.exec(p)) {
+ mavenRef = p;
+ } else {
+ for (var i = 0; i < SYSTEM_LIBRARY_MAPPINGS.length; ++i) {
+ var pair = SYSTEM_LIBRARY_MAPPINGS[i];
+ if (pair[0].exec(p)) {
+ mavenRef = p.replace(pair[0], pair[1]);
+ break;
+ }
+ }
+ if (!mavenRef) {
+ throw new CordovaError('Unsupported system library (does not work with gradle): ' + p);
+ }
+ }
+ depsList += ' compile "' + mavenRef + '"\n';
+ });
+ buildGradle = buildGradle.replace(/(SUB-PROJECT DEPENDENCIES START)[\s\S]*(\/\/ SUB-PROJECT DEPENDENCIES END)/, '$1\n' + depsList + ' $2');
+ var includeList = '';
+ 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) {
+ var self = this;
+ return check_reqs.check_gradle()
+ .then(function() {
+ return self.prepBuildFiles();
+ }).then(function() {
+ // Copy the gradle wrapper on each build so that:
+ // A) we don't require the Android SDK at project creation time, and
+ // B) we always use the SDK's latest version of it.
+ // check_reqs ensures that this is set.
+ /*jshint -W069 */
+ var sdkDir = process.env['ANDROID_HOME'];
+ /*jshint +W069 */
+ var wrapperDir = path.join(sdkDir, 'tools', 'templates', 'gradle', 'wrapper');
+ if (process.platform == 'win32') {
+ shell.rm('-f', path.join(self.root, 'gradlew.bat'));
+ shell.cp(path.join(wrapperDir, 'gradlew.bat'), self.root);
+ } else {
+ shell.rm('-f', path.join(self.root, 'gradlew'));
+ shell.cp(path.join(wrapperDir, 'gradlew'), self.root);
+ }
+ shell.rm('-rf', path.join(self.root, 'gradle', 'wrapper'));
+ shell.mkdir('-p', path.join(self.root, 'gradle'));
+ shell.cp('-r', path.join(wrapperDir, 'gradle', 'wrapper'), path.join(self.root, 'gradle'));
+
+ // If the gradle distribution URL is set, make sure it points to version we want.
+ // 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 */
+ var distributionUrl = process.env['CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL'] || 'http\\://services.gradle.org/distributions/gradle-2.2.1-all.zip';
+ /*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);
+
+ var propertiesFile = opts.buildType + SIGNING_PROPERTIES;
+ var propertiesFilePath = path.join(self.root, propertiesFile);
+ if (opts.packageInfo) {
+ fs.writeFileSync(propertiesFilePath, TEMPLATE + opts.packageInfo.toProperties());
+ } else if (isAutoGenerated(propertiesFilePath)) {
+ shell.rm('-f', propertiesFilePath);
+ }
+ });
+};
+
+/*
+ * Builds the project with gradle.
+ * Returns a promise.
+ */
+GradleBuilder.prototype.build = function(opts) {
+ var wrapper = path.join(this.root, 'gradlew');
+ var args = this.getArgs(opts.buildType == 'debug' ? 'debug' : 'release', opts);
+ return Q().then(function() {
+ return spawn(wrapper, args, {stdio: 'inherit'});
+ });
+};
+
+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 spawn(wrapper, args, {stdio: 'inherit'});
+ })
+ .then(function () {
+ shell.rm('-rf', path.join(builder.root, 'out'));
+
+ ['debug', 'release'].forEach(function(config) {
+ var propertiesFilePath = path.join(builder.root, config + SIGNING_PROPERTIES);
+ if(isAutoGenerated(propertiesFilePath)){
+ shell.rm('-f', propertiesFilePath);
+ }
+ });
+ });
+};
+
+module.exports = GradleBuilder;
+
+function isAutoGenerated(file) {
+ return fs.existsSync(file) && fs.readFileSync(file, 'utf8').indexOf(MARKER) > 0;
+}
http://git-wip-us.apache.org/repos/asf/cordova-android/blob/0ac822c5/bin/templates/cordova/lib/device.js
----------------------------------------------------------------------
diff --git a/bin/templates/cordova/lib/device.js b/bin/templates/cordova/lib/device.js
index 5dd79b5..e62e3db 100644
--- a/bin/templates/cordova/lib/device.js
+++ b/bin/templates/cordova/lib/device.js
@@ -1,106 +1,106 @@
-#!/usr/bin/env node
-
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-var Q = require('q'),
- build = require('./build');
-var path = require('path');
-var Adb = require('./Adb');
-var AndroidManifest = require('./AndroidManifest');
-var spawn = require('cordova-common').superspawn.spawn;
-var CordovaError = require('cordova-common').CordovaError;
-var events = require('cordova-common').events;
-
-/**
- * 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) {
- 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() {
- events.emit('verbose', 'Restarting adb to see if more devices are detected.');
- return Adb.devices();
- }, function() {
- // For non-killall OS's.
- return list;
- });
- }
- return 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.'));
- }
- // default device
- target = target || device_list[0];
-
- if (device_list.indexOf(target) < 0) {
- return Q.reject('ERROR: Unable to find target \'' + target + '\'.');
- }
-
- return build.detectArchitecture(target)
- .then(function(arch) {
- return { target: target, arch: arch, isEmulator: false };
- });
- });
-};
-
-/*
- * Installs a previously built application on the device
- * and launches it.
- * Returns a promise.
- */
-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) {
- var apk_path = build.findBestApkForArchitecture(buildResults, resolvedTarget.arch);
- var manifest = new AndroidManifest(path.join(__dirname, '../../AndroidManifest.xml'));
- var pkgName = manifest.getPackageId();
- var launchName = pkgName + '/.' + manifest.getActivity().getName();
- events.emit('log', 'Using apk: ' + apk_path);
- // 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.install(resolvedTarget.target, apk_path, {replace: true});
- }).then(function() {
- //unlock screen
- return Adb.shell(resolvedTarget.target, 'input keyevent 82');
- }).then(function() {
- return Adb.start(resolvedTarget.target, launchName);
- }).then(function() {
- events.emit('log', 'LAUNCH SUCCESS');
- });
- });
-};
+#!/usr/bin/env node
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+var Q = require('q'),
+ build = require('./build');
+var path = require('path');
+var Adb = require('./Adb');
+var AndroidManifest = require('./AndroidManifest');
+var spawn = require('cordova-common').superspawn.spawn;
+var CordovaError = require('cordova-common').CordovaError;
+var events = require('cordova-common').events;
+
+/**
+ * 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) {
+ 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() {
+ events.emit('verbose', 'Restarting adb to see if more devices are detected.');
+ return Adb.devices();
+ }, function() {
+ // For non-killall OS's.
+ return list;
+ });
+ }
+ return 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.'));
+ }
+ // default device
+ target = target || device_list[0];
+
+ if (device_list.indexOf(target) < 0) {
+ return Q.reject('ERROR: Unable to find target \'' + target + '\'.');
+ }
+
+ return build.detectArchitecture(target)
+ .then(function(arch) {
+ return { target: target, arch: arch, isEmulator: false };
+ });
+ });
+};
+
+/*
+ * Installs a previously built application on the device
+ * and launches it.
+ * Returns a promise.
+ */
+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) {
+ var apk_path = build.findBestApkForArchitecture(buildResults, resolvedTarget.arch);
+ var manifest = new AndroidManifest(path.join(__dirname, '../../AndroidManifest.xml'));
+ var pkgName = manifest.getPackageId();
+ var launchName = pkgName + '/.' + manifest.getActivity().getName();
+ events.emit('log', 'Using apk: ' + apk_path);
+ // 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.install(resolvedTarget.target, apk_path, {replace: true});
+ }).then(function() {
+ //unlock screen
+ return Adb.shell(resolvedTarget.target, 'input keyevent 82');
+ }).then(function() {
+ return Adb.start(resolvedTarget.target, launchName);
+ }).then(function() {
+ events.emit('log', 'LAUNCH SUCCESS');
+ });
+ });
+};
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org