You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by an...@apache.org on 2015/05/29 12:02:11 UTC

android commit: CB-8954 Adds `requirements` command support to check_reqs module

Repository: cordova-android
Updated Branches:
  refs/heads/master ce4256872 -> 4bf705a3d


CB-8954 Adds `requirements` command support to check_reqs module


Project: http://git-wip-us.apache.org/repos/asf/cordova-android/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-android/commit/4bf705a3
Tree: http://git-wip-us.apache.org/repos/asf/cordova-android/tree/4bf705a3
Diff: http://git-wip-us.apache.org/repos/asf/cordova-android/diff/4bf705a3

Branch: refs/heads/master
Commit: 4bf705a3d39b34400388265381a9975b246e3779
Parents: ce42568
Author: Vladimir Kotikov <v-...@microsoft.com>
Authored: Wed May 27 12:41:07 2015 +0300
Committer: Vladimir Kotikov <v-...@microsoft.com>
Committed: Fri May 29 13:00:38 2015 +0300

----------------------------------------------------------------------
 bin/lib/check_reqs.js | 128 ++++++++++++++++++++++++++++++++++++---------
 bin/lib/create.js     |   2 +-
 2 files changed, 103 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-android/blob/4bf705a3/bin/lib/check_reqs.js
----------------------------------------------------------------------
diff --git a/bin/lib/check_reqs.js b/bin/lib/check_reqs.js
index 92ddc19..46c3213 100644
--- a/bin/lib/check_reqs.js
+++ b/bin/lib/check_reqs.js
@@ -40,11 +40,13 @@ function forgivingWhichSync(cmd) {
     }
 }
 
-function tryCommand(cmd, errMsg) {
+function tryCommand(cmd, errMsg, catchStderr) {
     var d = Q.defer();
     child_process.exec(cmd, function(err, stdout, stderr) {
         if (err) d.reject(new Error(errMsg));
-        else d.resolve(stdout);
+        // 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;
 }
@@ -70,18 +72,25 @@ module.exports.get_target = function() {
 
 // 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.');
+    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'];
-    var wrapperDir = path.join(sdkDir, 'tools', 'templates', 'gradle', 'wrapper');
-    if (!fs.existsSync(wrapperDir)) {
-        return Q.reject(new Error('Could not find gradle wrapper within android sdk. Might need to update your Android SDK.\n' +
-            'Looked here: ' + wrapperDir));
-    }
-    return Q.when();
+    var message = 'Could not find gradle wrapper within Android SDK. ';
+    if (!sdkDir) return Q.reject(message + 'Might need to install Android SDK or set up \'ADROID_HOME\' env variable.');
+    var wrapper = path.join(sdkDir, 'tools', 'templates', 'gradle', 'wrapper', 'gradlew');
+    return tryCommand(wrapper + ' -v', message + 'Might need to update your Android SDK.\n' +
+            'Looked here: ' + path.basename(wrapper))
+    .then(function (output) {
+        // Parse Gradle version from command output
+        return/^gradle ((?:\d+\.)+(?:\d+))/gim.exec(output)[1];
+    });
 };
 
 // Returns a promise.
@@ -96,9 +105,10 @@ module.exports.check_java = function() {
             }
         } 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', 'Failed to run: /usr/libexec/java_home')
+                    return tryCommand('/usr/libexec/java_home', msg)
                     .then(function(stdout) {
                         process.env['JAVA_HOME'] = stdout.trim();
                     });
@@ -109,7 +119,7 @@ module.exports.check_java = function() {
                     if (fs.existsSync(path.join(maybeJavaHome, 'lib', 'tools.jar'))) {
                         process.env['JAVA_HOME'] = maybeJavaHome;
                     } else {
-                        throw new Error('Could not find JAVA_HOME. Try setting the environment variable manually');
+                        throw new Error(msg);
                     }
                 }
             } else if (isWindows) {
@@ -140,7 +150,11 @@ module.exports.check_java = function() {
         }
         return tryCommand('java -version', msg)
         .then(function() {
-            return tryCommand('javac -version', msg);
+            // 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) {
+            return /^javac ((?:\d+\.)+(?:\d+))/i.exec(output)[1];
         });
     });
 };
@@ -196,20 +210,22 @@ module.exports.check_android = function() {
                 process.env['ANDROID_HOME'] = grandParentDir;
                 hasAndroidHome = true;
             } else {
-                throw new Error('ANDROID_HOME is not set and no "tools" directory found at ' + parentDir);
+                throw new Error('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 Error('ANDROID_HOME is not set and "android" command not in your PATH. You must fulfill at least one of these conditions.');
+            throw new Error('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 Error('ANDROID_HOME is set to a non-existant path: ' + process.env['ANDROID_HOME']);
+            throw new Error('\'ANDROID_HOME\' environment variable is set to non-existent path: ' + process.env['ANDROID_HOME'] +
+                '\nTry update it manually to point to valid SDK directory.');
         }
-        // Check that the target sdk level is installed.
-        return module.exports.check_android_target(module.exports.get_target());
     });
 };
 
@@ -223,27 +239,87 @@ module.exports.check_android_target = function(valid_target) {
     //   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) {
-        if (output.split('\n').indexOf(valid_target) == -1) {
-            var androidCmd = module.exports.getAbsoluteAndroidCmd();
-            throw new Error('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)');
+        var targets = output.split('\n');
+        if (targets.indexOf(valid_target) >= 0) {
+            return targets;
         }
+
+        var androidCmd = module.exports.getAbsoluteAndroidCmd();
+        throw new Error('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()])
+    return Q.all([this.check_java(), this.check_android(), 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;
+        });
+    }, 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/4bf705a3/bin/lib/create.js
----------------------------------------------------------------------
diff --git a/bin/lib/create.js b/bin/lib/create.js
index c7f5656..0815870 100755
--- a/bin/lib/create.js
+++ b/bin/lib/create.js
@@ -128,7 +128,7 @@ function copyScripts(projectPath) {
     // Copy in the new ones.
     shell.cp('-r', srcScriptsDir, projectPath);
     shell.cp('-r', path.join(ROOT, 'bin', 'node_modules'), destScriptsDir);
-    shell.cp(path.join(ROOT, 'bin', 'check_reqs'), path.join(destScriptsDir, 'check_reqs'));
+    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'));


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org