Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id CC8CE200C81 for ; Sat, 15 Apr 2017 03:10:28 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id CA5F7160B8C; Sat, 15 Apr 2017 01:10:28 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 5B74D160BB2 for ; Sat, 15 Apr 2017 03:10:26 +0200 (CEST) Received: (qmail 34964 invoked by uid 500); 15 Apr 2017 01:10:25 -0000 Mailing-List: contact commits-help@cordova.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Delivered-To: mailing list commits@cordova.apache.org Received: (qmail 32934 invoked by uid 99); 15 Apr 2017 01:10:23 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 15 Apr 2017 01:10:23 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 88A02DFC8E; Sat, 15 Apr 2017 01:10:23 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: shazron@apache.org To: commits@cordova.apache.org Date: Sat, 15 Apr 2017 01:10:43 -0000 Message-Id: In-Reply-To: <9ef2b49651994bf19f1745ea630bd919@git.apache.org> References: <9ef2b49651994bf19f1745ea630bd919@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [22/39] cordova-lib git commit: CB-11346: added tests for support of 3rd party platforms archived-at: Sat, 15 Apr 2017 01:10:29 -0000 http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/da952e07/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/Api.js ---------------------------------------------------------------------- diff --git a/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/Api.js b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/Api.js new file mode 100644 index 0000000..8e4711c --- /dev/null +++ b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/Api.js @@ -0,0 +1,415 @@ +/** + 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 Q = require('q'); + +var AndroidProject = require('./lib/AndroidProject'); +var AndroidStudio = require('./lib/AndroidStudio'); +var PluginManager = require('cordova-common').PluginManager; + +var CordovaLogger = require('cordova-common').CordovaLogger; +var selfEvents = require('cordova-common').events; + +var PLATFORM = 'android'; + + +function setupEvents(externalEventEmitter) { + if (externalEventEmitter) { + // This will make the platform internal events visible outside + selfEvents.forwardEventsTo(externalEventEmitter); + return externalEventEmitter; + } + + // There is no logger if external emitter is not present, + // so attach a console logger + CordovaLogger.get().subscribe(selfEvents); + return selfEvents; +} + + +/** + * 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, '..'); + + setupEvents(events); + + var self = this; + + this.locations = { + root: self.root, + www: path.join(self.root, 'assets/www'), + res: path.join(self.root, 'res'), + 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'), + build: path.join(self.root, 'build'), + // NOTE: Due to platformApi spec we need to return relative paths here + cordovaJs: 'bin/templates/project/assets/www/cordova.js', + cordovaJsSrc: 'cordova-js-src' + }; + + // XXX Override some locations for Android Studio projects + if(AndroidStudio.isAndroidStudioProject(self.root) === true) { + selfEvents.emit('log', 'Android Studio project detected'); + this.android_studio = true; + this.locations.configXml = path.join(self.root, 'app/src/main/res/xml/config.xml'); + this.locations.strings = path.join(self.root, 'app/src/main/res/xml/strings.xml'); + this.locations.manifest = path.join(self.root, 'app/src/main/AndroidManifest.xml'); + this.locations.www = path.join(self.root, 'app/src/main/assets/www'); + this.locations.res = path.join(self.root, 'app/src/main/res'); + } +} + +/** + * 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} Promise either fulfilled with PlatformApi + * instance or rejected with CordovaError. + */ +Api.createPlatform = function (destination, config, options, events) { + events = setupEvents(events); + var result; + try { + result = require('../../lib/create') + .create(destination, config, options, events) + .then(function (destination) { + var PlatformApi = require(path.resolve(destination, 'cordova/Api')); + return new PlatformApi(PLATFORM, destination, events); + }); + } + catch (e) { + events.emit('error','createPlatform is not callable from the android project API.'); + throw(e); + } + return result; +}; + +/** + * 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} Promise either fulfilled with PlatformApi + * instance or rejected with CordovaError. + */ +Api.updatePlatform = function (destination, options, events) { + events = setupEvents(events); + var result; + try { + result = require('../../lib/create') + .update(destination, options, events) + .then(function (destination) { + var PlatformApi = require(path.resolve(destination, 'cordova/Api')); + return new PlatformApi('android', destination, events); + }); + } + catch (e) { + events.emit('error','updatePlatform is not callable from the android project API, you will need to do this manually.'); + throw(e); + } + return result; +}; + +/** + * 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, prepareOptions) { + return require('./lib/prepare').prepare.call(this, cordovaProject, prepareOptions); +}; + +/** + * 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) { + var project = AndroidProject.getProjectFile(this.root); + var self = this; + + installOptions = installOptions || {}; + installOptions.variables = installOptions.variables || {}; + // Add PACKAGE_NAME variable into vars + if (!installOptions.variables.PACKAGE_NAME) { + installOptions.variables.PACKAGE_NAME = project.getPackageName(); + } + + if(this.android_studio === true) { + installOptions.android_studio = true; + } + + return Q() + .then(function () { + //CB-11964: Do a clean when installing the plugin code to get around + //the Gradle bug introduced by the Android Gradle Plugin Version 2.2 + //TODO: Delete when the next version of Android Gradle plugin comes out + + // Since clean doesn't just clean the build, it also wipes out www, we need + // to pass additional options. + + // Do some basic argument parsing + var opts = {}; + + // Skip cleaning prepared files when not invoking via cordova CLI. + opts.noPrepare = true; + + if(!AndroidStudio.isAndroidStudioProject(self.root) && !project.isClean()) { + return self.clean(opts); + } + }) + .then(function () { + return PluginManager.get(self.platform, self.locations, project) + .addPlugin(plugin, installOptions); + }) + .then(function () { + if (plugin.getFrameworks(this.platform).length === 0) return; + + selfEvents.emit('verbose', 'Updating build files since android plugin contained '); + require('./lib/builders/builders').getBuilder('gradle').prepBuildFiles(); + }.bind(this)) + // CB-11022 Return truthy value to prevent running prepare after + .thenResolve(true); +}; + +/** + * 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) { + var project = AndroidProject.getProjectFile(this.root); + + if(uninstallOptions && uninstallOptions.usePlatformWww === true && this.android_studio === true) { + uninstallOptions.usePlatformWww = false; + uninstallOptions.android_studio = true; + } + + return PluginManager.get(this.platform, this.locations, project) + .removePlugin(plugin, uninstallOptions) + .then(function () { + if (plugin.getFrameworks(this.platform).length === 0) return; + + selfEvents.emit('verbose', 'Updating build files since android plugin contained '); + require('./lib/builders/builders').getBuilder('gradle').prepBuildFiles(); + }.bind(this)) + // CB-11022 Return truthy value to prevent running prepare after + .thenResolve(true); +}; + +/** + * 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} 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, and also + * cleans out the platform www directory if called without options specified. + * + * @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); + }) + .then(function () { + return require('./lib/prepare').clean.call(self, cleanOptions); + }); +}; + + + +/** + * Performs a requirements check for current platform. Each platform defines its + * own set of requirements, which should be resolved before platform can be + * built successfully. + * + * @return {Promise} Promise, resolved with set of Requirement + * objects for current platform. + */ +Api.prototype.requirements = function() { + return require('./lib/check_reqs').check_all(); +}; + +module.exports = Api; http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/da952e07/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/build ---------------------------------------------------------------------- diff --git a/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/build b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/build new file mode 100755 index 0000000..222e84a --- /dev/null +++ b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/build @@ -0,0 +1,50 @@ +#!/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 args = process.argv; +var Api = require('./Api'); +var nopt = require('nopt'); +var path = require('path'); + +// Support basic help commands +if(['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >= 0) + require('./lib/build').help(); + +// Do some basic argument parsing +var buildOpts = nopt({ + 'verbose' : Boolean, + 'silent' : Boolean, + 'debug' : Boolean, + 'release' : Boolean, + 'nobuild': Boolean, + 'buildConfig' : path +}, { 'd' : '--verbose' }); + +// Make buildOptions compatible with PlatformApi build method spec +buildOpts.argv = buildOpts.argv.original; + +require('./loggingHelper').adjustLoggerLevel(buildOpts); + +new Api().build(buildOpts) +.catch(function(err) { + console.error(err.stack); + process.exit(2); +}); http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/da952e07/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/build.bat ---------------------------------------------------------------------- diff --git a/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/build.bat b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/build.bat new file mode 100644 index 0000000..46e966a --- /dev/null +++ b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/build.bat @@ -0,0 +1,26 @@ +:: 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. + +@ECHO OFF +SET script_path="%~dp0build" +IF EXIST %script_path% ( + node %script_path% %* +) ELSE ( + ECHO. + ECHO ERROR: Could not find 'build' script in 'cordova' folder, aborting...>&2 + EXIT /B 1 +) \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/da952e07/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/clean ---------------------------------------------------------------------- diff --git a/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/clean b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/clean new file mode 100755 index 0000000..22065cc --- /dev/null +++ b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/clean @@ -0,0 +1,51 @@ +#!/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 Api = require('./Api'); +var path = require('path'); +var nopt = require('nopt'); + +// Support basic help commands +if(['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >= 0) { + console.log('Usage: ' + path.relative(process.cwd(), process.argv[1])); + console.log('Cleans the project directory.'); + process.exit(0); +} + +// Do some basic argument parsing +var opts = nopt({ + 'verbose' : Boolean, + 'silent' : Boolean +}, { 'd' : '--verbose' }); + +// Make buildOptions compatible with PlatformApi clean method spec +opts.argv = opts.argv.original; + +// Skip cleaning prepared files when not invoking via cordova CLI. +opts.noPrepare = true; + +require('./loggingHelper').adjustLoggerLevel(opts); + +new Api().clean(opts) +.catch(function(err) { + console.error(err.stack); + process.exit(2); +}); http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/da952e07/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/clean.bat ---------------------------------------------------------------------- diff --git a/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/clean.bat b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/clean.bat new file mode 100644 index 0000000..445ef6e --- /dev/null +++ b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/clean.bat @@ -0,0 +1,26 @@ +:: 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. + +@ECHO OFF +SET script_path="%~dp0clean" +IF EXIST %script_path% ( + node %script_path% %* +) ELSE ( + ECHO. + ECHO ERROR: Could not find 'clean' script in 'cordova' folder, aborting...>&2 + EXIT /B 1 +) \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/da952e07/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/defaults.xml ---------------------------------------------------------------------- diff --git a/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/defaults.xml b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/defaults.xml new file mode 100644 index 0000000..5286ab9 --- /dev/null +++ b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/defaults.xml @@ -0,0 +1,26 @@ + + + + + + + http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/da952e07/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/Adb.js ---------------------------------------------------------------------- diff --git a/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/Adb.js b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/Adb.js new file mode 100644 index 0000000..84ae707 --- /dev/null +++ b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/Adb.js @@ -0,0 +1,105 @@ +/** + 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 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} 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 ' + 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/)) { + if (output.match(/INSTALL_PARSE_FAILED_NO_CERTIFICATES/)) { + output += '\n\n' + 'Sign the build using \'-- --keystore\' or \'--buildConfig\'' + + ' or sign and deploy the unsigned apk manually using Android tools.'; + } else if (output.match(/INSTALL_FAILED_VERSION_DOWNGRADE/)) { + output += '\n\n' + 'You\'re trying to install apk with a lower versionCode that is already installed.' + + '\nEither uninstall an app or increment the versionCode.'; + } + + return Q.reject(new CordovaError('Failed to install apk to device: ' + output)); + } + }); +}; + +Adb.uninstall = function (target, packageId) { + events.emit('verbose', 'Uninstalling package ' + packageId + ' from target ' + target + '...'); + return spawn('adb', ['-s', target, 'uninstall', packageId], {cwd: os.tmpdir()}); +}; + +Adb.shell = function (target, shellCommand) { + events.emit('verbose', 'Running adb shell command "' + shellCommand + '" on target ' + target + '...'); + var args = ['-s', target, 'shell']; + shellCommand = shellCommand.split(/\s+/); + return spawn('adb', args.concat(shellCommand), {cwd: os.tmpdir()}) + .catch(function (output) { + return 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 ' + 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-lib/blob/da952e07/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/AndroidManifest.js ---------------------------------------------------------------------- diff --git a/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/AndroidManifest.js b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/AndroidManifest.js new file mode 100644 index 0000000..8248f59 --- /dev/null +++ b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/AndroidManifest.js @@ -0,0 +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('AndroidManifest at ' + 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-lib/blob/da952e07/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/AndroidProject.js ---------------------------------------------------------------------- diff --git a/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/AndroidProject.js b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/AndroidProject.js new file mode 100644 index 0000000..fa1c612 --- /dev/null +++ b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/AndroidProject.js @@ -0,0 +1,210 @@ +/** + 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 AndroidStudio = require('./AndroidStudio'); +var pluginHandlers = require('./pluginHandlers'); + +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'); + if(AndroidStudio.isAndroidStudioProject(projectDir) === true) { + this.www = path.join(this.projectDir, 'app/src/main/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() { + var manifestPath = path.join(this.projectDir, 'AndroidManifest.xml'); + if(AndroidStudio.isAndroidStudioProject(this.projectDir) === true) { + manifestPath = path.join(this.projectDir, 'app/src/main/AndroidManifest.xml'); + } + return new AndroidManifest(manifestPath).getPackageId(); +}; + +AndroidProject.prototype.getCustomSubprojectRelativeDir = function(plugin_id, src) { + // 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]; +}; + +AndroidProject.prototype.getInstaller = function (type) { + return pluginHandlers.getInstaller(type); +}; + +AndroidProject.prototype.getUninstaller = function (type) { + return pluginHandlers.getUninstaller(type); +}; + +/* + * This checks if an Android project is clean or has old build artifacts + */ + +AndroidProject.prototype.isClean = function() { + var build_path = path.join(this.projectDir, 'build'); + //If the build directory doesn't exist, it's clean + return !(fs.existsSync(build_path)); +}; + +module.exports = AndroidProject; http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/da952e07/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/AndroidStudio.js ---------------------------------------------------------------------- diff --git a/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/AndroidStudio.js b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/AndroidStudio.js new file mode 100644 index 0000000..335b334 --- /dev/null +++ b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/AndroidStudio.js @@ -0,0 +1,42 @@ +/* + * This is a simple routine that checks if project is an Android Studio Project + * + * @param {String} root Root folder of the project + */ + +/*jshint esnext: false */ + +var path = require('path'); +var fs = require('fs'); +var CordovaError = require('cordova-common').CordovaError; + +module.exports.isAndroidStudioProject = function isAndroidStudioProject(root) { + var eclipseFiles = ['AndroidManifest.xml', 'libs', 'res', 'project.properties', 'platform_www']; + var androidStudioFiles = ['app', 'gradle', 'app/src/main/res']; + + // assume it is an AS project and not an Eclipse project + var isEclipse = false; + var isAS = true; + + if(!fs.existsSync(root)) { + throw new CordovaError('AndroidStudio.js:inAndroidStudioProject root does not exist: ' + root); + } + + // if any of the following exists, then we are not an ASProj + eclipseFiles.forEach(function(file) { + if(fs.existsSync(path.join(root, file))) { + isEclipse = true; + } + }); + + // if it is NOT an eclipse project, check that all required files exist + if(!isEclipse) { + androidStudioFiles.forEach(function(file){ + if(!fs.existsSync(path.join(root, file))) { + console.log('missing file :: ' + file); + isAS = false; + } + }); + } + return (!isEclipse && isAS); +}; http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/da952e07/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/build.js ---------------------------------------------------------------------- diff --git a/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/build.js b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/build.js new file mode 100644 index 0000000..bd613da --- /dev/null +++ b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/build.js @@ -0,0 +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, projectRoot) { + options = options || {}; + options.argv = nopt({ + gradle: Boolean, + ant: Boolean, + prepenv: Boolean, + versionCode: String, + minSdkVersion: String, + gradleArg: [String, Array], + 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.argv.versionCode); + + if (options.argv.minSdkVersion) + ret.extraArgs.push('-PcdvMinSdkVersion=' + options.argv.minSdkVersion); + + if (options.argv.gradleArg) { + ret.extraArgs = ret.extraArgs.concat(options.argv.gradleArg); + } + + var packageArgs = {}; + + if (options.argv.keystore) + packageArgs.keystore = path.relative(projectRoot, path.resolve(options.argv.keystore)); + + ['alias','storePassword','password','keystoreType'].forEach(function (flagName) { + if (options.argv[flagName]) + packageArgs[flagName] = options.argv[flagName]; + }); + + 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 buildjson = fs.readFileSync(buildConfig, 'utf8'); + var config = JSON.parse(buildjson.replace(/^\ufeff/, '')); // Remove BOM + if (config.android && config.android[ret.buildType]) { + var androidInfo = config.android[ret.buildType]; + if(androidInfo.keystore && !packageArgs.keystore) { + if(androidInfo.keystore.substr(0,1) === '~') { + androidInfo.keystore = process.env.HOME + androidInfo.keystore.substr(1); + } + packageArgs.keystore = path.resolve(path.dirname(buildConfig), androidInfo.keystore); + events.emit('log', 'Reading the keystore from: ' + packageArgs.keystore); + } + + ['alias', 'storePassword', 'password','keystoreType'].forEach(function (key){ + 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, null, this.root); + 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} Promise, resolved with built packages + * information. + */ +module.exports.run = function(options, optResolvedTarget) { + var opts = parseOpts(options, optResolvedTarget, this.root); + var builder = builders.getBuilder(opts.buildMethod); + return builder.prepEnv(opts) + .then(function() { + if (opts.prepEnv) { + events.emit('verbose', 'Build file successfully prepared.'); + return; + } + return builder.build(opts) + .then(function() { + var apkPaths = builder.findOutputApks(opts.buildType, opts.arch); + events.emit('log', 'Built the following apk(s): \n\t' + apkPaths.join('\n\t')); + return { + apkPaths: apkPaths, + buildType: opts.buildType, + buildMethod: opts.buildMethod + }; + }); + }); +}; + +/* + * 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. + events.emit('verbose', 'adb timed out while detecting device/emulator architecture. Killing adb and trying again.'); + return spawn('killall', ['adb']) + .then(function() { + return helper() + .then(null, function() { + // The double kill is sadly often necessary, at least on mac. + events.emit('warn', 'adb timed out a second time while detecting device/emulator architecture. Killing adb and trying again.'); + return spawn('killall', ['adb']) + .then(function() { + return helper() + .then(null, function() { + return Q.reject(new CordovaError('adb timed out a third time while detecting device/emulator architecture. 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=\': 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=\': 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-lib/blob/da952e07/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/builders/AntBuilder.js ---------------------------------------------------------------------- diff --git a/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/builders/AntBuilder.js b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/builders/AntBuilder.js new file mode 100644 index 0000000..4e0f71a --- /dev/null +++ b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/builders/AntBuilder.js @@ -0,0 +1,156 @@ +/* + 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(this.root)) { + 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. Use gradle instead.'); + } + + 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(this.root)) { + // 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: 'pipe'}); + }).progress(function (stdio){ + if (stdio.stderr) { + process.stderr.write(stdio.stderr); + } else { + process.stdout.write(stdio.stdout); + } + }).catch(function (error) { + if (error.toString().indexOf('Unable to resolve project target') >= 0) { + return check_reqs.check_android_target(error).then(function() { + // If due to some odd reason - check_android_target succeeds + // we should still fail here. + return Q.reject(error); + }); + } + return Q.reject(error); + }); +}; + +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-lib/blob/da952e07/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/builders/GenericBuilder.js ---------------------------------------------------------------------- diff --git a/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/builders/GenericBuilder.js b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/builders/GenericBuilder.js new file mode 100644 index 0000000..362da43 --- /dev/null +++ b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/builders/GenericBuilder.js @@ -0,0 +1,147 @@ +/* + 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 CordovaError = require('cordova-common').CordovaError; + +function GenericBuilder (projectDir) { + this.root = projectDir || path.resolve(__dirname, '../../..'); + this.binDirs = { + ant: path.join(this.root, hasCustomRules(this.root) ? 'ant-build' : 'bin'), + gradle: path.join(this.root, 'build', 'outputs', 'apk') + }; +} + +function hasCustomRules(projectRoot) { + return fs.existsSync(path.join(projectRoot, 'custom_rules.xml')); +} + +GenericBuilder.prototype.prepEnv = function() { + return Q(); +}; + +GenericBuilder.prototype.build = function() { + events.emit('log', 'Skipping build...'); + return Q(null); +}; + +GenericBuilder.prototype.clean = function() { + return Q(); +}; + +GenericBuilder.prototype.findOutputApks = function(build_type, arch) { + var self = this; + return Object.keys(this.binDirs) + .reduce(function (result, builderName) { + var binDir = self.binDirs[builderName]; + return result.concat(findOutputApksHelper(binDir, build_type, builderName === 'ant' ? null : arch)); + }, []) + .sort(apkSorter); +}; + +GenericBuilder.prototype.readProjectProperties = function () { + function findAllUniq(data, r) { + var s = {}; + var m; + while ((m = r.exec(data))) { + s[m[1]] = 1; + } + return Object.keys(s); + } + + var data = fs.readFileSync(path.join(this.root, 'project.properties'), 'utf8'); + return { + libs: findAllUniq(data, /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg), + gradleIncludes: findAllUniq(data, /^\s*cordova\.gradle\.include\.\d+=(.*)(?:\s|$)/mg), + systemLibs: findAllUniq(data, /^\s*cordova\.system\.library\.\d+=(.*)(?:\s|$)/mg) + }; +}; + +GenericBuilder.prototype.extractRealProjectNameFromManifest = function () { + var manifestPath = path.join(this.root, 'AndroidManifest.xml'); + var manifestData = fs.readFileSync(manifestPath, 'utf8'); + var m = / 1 && arch) { + ret = ret.filter(function(p) { + return path.basename(p).indexOf('-' + arch) != -1; + }); + } + + return ret; +} http://git-wip-us.apache.org/repos/asf/cordova-lib/blob/da952e07/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/builders/GradleBuilder.js ---------------------------------------------------------------------- diff --git a/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/builders/GradleBuilder.js b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/builders/GradleBuilder.js new file mode 100644 index 0000000..5b5ce13 --- /dev/null +++ b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/builders/GradleBuilder.js @@ -0,0 +1,279 @@ +/* + 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'); + // to allow dex in process + args.push('-Dorg.gradle.jvmargs=-Xmx2048m'); + // allow NDK to be used - required by Gradle 1.5 plugin + args.push('-Pandroid.useDeprecatedNdk=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; +}; + +/* + * This returns a promise + */ + +GradleBuilder.prototype.runGradleWrapper = function(gradle_cmd) { + var gradlePath = path.join(this.root, 'gradlew'); + var wrapperGradle = path.join(this.root, 'wrapper.gradle'); + if(fs.existsSync(gradlePath)) { + //Literally do nothing, for some reason this works, while !fs.existsSync didn't on Windows + } else { + return spawn(gradle_cmd, ['-p', this.root, 'wrapper', '-b', wrapperGradle], {stdio: 'inherit'}); + } +}; + + +// 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; + var checkAndCopy = function(subProject, root) { + var subProjectGradle = path.join(root, subProject, 'build.gradle'); + // This is the future-proof way of checking if a file exists + // This must be synchronous to satisfy a Travis test + try { + fs.accessSync(subProjectGradle, fs.F_OK); + } catch (e) { + shell.cp('-f', pluginBuildGradle, subProjectGradle); + } + }; + for (var i = 0; i < subProjects.length; ++i) { + if (subProjects[i] !== 'CordovaLib') { + checkAndCopy(subProjects[i], this.root); + } + } + var name = this.extractRealProjectNameFromManifest(); + //Remove the proj.id/name- prefix from projects: https://issues.apache.org/jira/browse/CB-9149 + var settingsGradlePaths = subProjects.map(function(p){ + var realDir=p.replace(/[/\\]/g, ':'); + var libName=realDir.replace(name+'-',''); + var str='include ":'+libName+'"\n'; + if(realDir.indexOf(name+'-')!==-1) + str+='project(":'+libName+'").projectDir = new File("'+p+'")\n'; + 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 = ''; + var root = this.root; + var insertExclude = function(p) { + var gradlePath = path.join(root, p, 'build.gradle'); + var projectGradleFile = fs.readFileSync(gradlePath, 'utf-8'); + if(projectGradleFile.indexOf('CordovaLib') != -1) { + depsList += '{\n exclude module:("CordovaLib")\n }\n'; + } + else { + depsList +='\n'; + } + }; + subProjects.forEach(function(p) { + console.log('Subproject Path: ' + p); + var libName=p.replace(/[/\\]/g, ':').replace(name+'-',''); + depsList += ' debugCompile(project(path: "' + libName + '", configuration: "debug"))'; + insertExclude(p); + depsList += ' releaseCompile(project(path: "' + libName + '", configuration: "release"))'; + insertExclude(p); + }); + // 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(gradlePath) { + return self.runGradleWrapper(gradlePath); + }).then(function() { + return self.prepBuildFiles(); + }).then(function() { + // We now copy the gradle out of the framework + // This is a dirty patch to get the build working + /* + var wrapperDir = path.join(self.root, 'CordovaLib'); + 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'] || 'https\\://services.gradle.org/distributions/gradle-3.3-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 spawn(wrapper, args, {stdio: 'pipe'}) + .progress(function (stdio){ + if (stdio.stderr) { + /* + * Workaround for the issue with Java printing some unwanted information to + * stderr instead of stdout. + * This function suppresses 'Picked up _JAVA_OPTIONS' message from being + * printed to stderr. See https://issues.apache.org/jira/browse/CB-9971 for + * explanation. + */ + var suppressThisLine = /^Picked up _JAVA_OPTIONS: /i.test(stdio.stderr.toString()); + if (suppressThisLine) { + return; + } + process.stderr.write(stdio.stderr); + } else { + process.stdout.write(stdio.stdout); + } + }).catch(function (error) { + if (error.toString().indexOf('failed to find target with hash string') >= 0) { + return check_reqs.check_android_target(error).then(function() { + // If due to some odd reason - check_android_target succeeds + // we should still fail here. + return Q.reject(error); + }); + } + return Q.reject(error); + }); +}; + +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-lib/blob/da952e07/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/builders/builders.js ---------------------------------------------------------------------- diff --git a/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/builders/builders.js b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/builders/builders.js new file mode 100644 index 0000000..4921c49 --- /dev/null +++ b/cordova-lib/spec-cordova/fixtures/platforms/atari/bin/templates/cordova/lib/builders/builders.js @@ -0,0 +1,47 @@ +/* + 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 CordovaError = require('cordova-common').CordovaError; + +var knownBuilders = { + ant: 'AntBuilder', + gradle: 'GradleBuilder', + none: 'GenericBuilder' +}; + +/** + * Helper method that instantiates and returns a builder for specified build + * type. + * + * @param {String} builderType Builder name to construct and return. Must + * be one of 'ant', 'gradle' or 'none' + * + * @return {Builder} A builder instance for specified build type. + */ +module.exports.getBuilder = function (builderType, projectRoot) { + if (!knownBuilders[builderType]) + throw new CordovaError('Builder ' + builderType + ' is not supported.'); + + try { + var Builder = require('./' + knownBuilders[builderType]); + return new Builder(projectRoot); + } catch (err) { + throw new CordovaError('Failed to instantiate ' + knownBuilders[builderType] + ' builder: ' + err); + } +}; --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org For additional commands, e-mail: commits-help@cordova.apache.org