You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by db...@apache.org on 2015/04/30 02:35:55 UTC
[2/8] cordova-medic git commit: [CB-8870] Splitting medic file into
subcommands and adding missing commands.
[CB-8870] Splitting medic file into subcommands and adding missing commands.
Project: http://git-wip-us.apache.org/repos/asf/cordova-medic/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-medic/commit/49da31f2
Tree: http://git-wip-us.apache.org/repos/asf/cordova-medic/tree/49da31f2
Diff: http://git-wip-us.apache.org/repos/asf/cordova-medic/diff/49da31f2
Branch: refs/heads/master
Commit: 49da31f2aed90d4c1cff5175a7cb27abc99ae9e3
Parents: 0ad8700
Author: Dmitry Blotsky <dm...@gmail.com>
Authored: Wed Apr 29 15:27:45 2015 -0700
Committer: Dmitry Blotsky <dm...@gmail.com>
Committed: Wed Apr 29 15:27:45 2015 -0700
----------------------------------------------------------------------
bin/checkout.js | 53 ------
bin/medic.js | 136 ----------------
lib/util.js | 56 +++++++
medic/medic-check.js | 58 +++++++
medic/medic-checkout.js | 80 +++++++++
medic/medic-clean.js | 111 +++++++++++++
medic/medic-kill.js | 110 +++++++++++++
medic/medic-run.js | 380 +++++++++++++++++++++++++++++++++++++++++++
medic/medic.js | 40 +++++
9 files changed, 835 insertions(+), 189 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-medic/blob/49da31f2/bin/checkout.js
----------------------------------------------------------------------
diff --git a/bin/checkout.js b/bin/checkout.js
deleted file mode 100644
index 29c6e6f..0000000
--- a/bin/checkout.js
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/usr/bin/env node
-
-// node dependencies
-var fs = require('fs');
-
-// external dependencies
-var shell = require('shelljs');
-
-// parse args
-var argv = require('optimist')
- .usage('Usage: $0 --config {path} --exclude {name[,name[,...]]}')
- .demand('config')
- .argv;
-
-function cloneProject(projectName, projectsConfig) {
-
- var project = projectsConfig[projectName];
- var codebase = project.codebases[project.codebase];
- var command = 'git clone ' + codebase.repo + ' --branch=' + codebase.branch + ' --depth 1'
-
- shell.exec(command, {silent: false}, function (returnCode, output) {
- if (returnCode !== 0) {
- throw 'Command \'' + command + '\' failed with code ' + returnCode;
- }
- });
-}
-
-function main () {
-
- // get args
- var configFile = argv.config;
- var excludedNames = [];
-
- if (argv.exclude) {
- excludedNames = argv.exclude.split(',');
- }
-
- // shell config
- shell.config.fatal = true;
- shell.config.silent = false;
-
- // read in config
- var projectsConfig = JSON.parse(fs.readFileSync(configFile, 'utf8'));
-
- // clone all projects in the config
- for (projectName in projectsConfig) {
- if (excludedNames.indexOf(projectName) === (-1)) {
- cloneProject(projectName, projectsConfig);
- }
- }
-}
-
-main();
http://git-wip-us.apache.org/repos/asf/cordova-medic/blob/49da31f2/bin/medic.js
----------------------------------------------------------------------
diff --git a/bin/medic.js b/bin/medic.js
deleted file mode 100755
index eaa5a05..0000000
--- a/bin/medic.js
+++ /dev/null
@@ -1,136 +0,0 @@
-#!/usr/bin/env node
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-"use strict";
-
-// node dependencies
-var fs = require("fs");
-var os = require("os");
-
-// external dependencies
-var shelljs = require("shelljs");
-var optimist = require("optimist");
-
-// constants
-var MAX_REMOVAL_ATTEMPTS = 3;
-
-// parse args
-var argv = optimist
- .usage("Usage: $0 [command]")
- .demand(1)
- .argv;
-
-// helpers
-function fatal(message) {
- console.error("ERROR: " + message);
- process.exit(1);
-}
-
-function contains(collection, item) {
- return collection.indexOf(item) != (-1);
-}
-
-function exclusiveLs(lsPath, excludes) {
- var paths = fs.readdirSync(lsPath);
- return paths.filter(function (pathName) {
- return !contains(excludes, pathName);
- });
-}
-
-// subcommands
-function commandClean() {
-
- // command-specific args
- argv = optimist
- .usage("Usage: $0 --exclude {name[,name[,...]]}")
- .argv;
-
- // get args
- var excludeString = argv.exclude;
- var excludedPaths = [".", ".."];
-
- if (argv.exclude) {
- excludedPaths = excludedPaths.concat(excludeString.split(","));
- }
-
- // get all directories except excluded ones
- var pathsToRemove = exclusiveLs(".", excludedPaths);
-
- console.log("NOT removing the following paths:");
- console.log(excludedPaths);
- console.log("removing the following paths:");
- console.log(pathsToRemove);
-
- // skip if no paths to delete
- if (pathsToRemove.length <= 0) {
- return;
- }
-
- // attempt to delete the paths
- var attempts = 0;
- var success = false;
- while (success === false) {
-
- // try to remove the paths
- shelljs.rm("-rf", pathsToRemove);
-
- // check if any of them remain
- var remainingPaths = exclusiveLs(".", excludedPaths);
- if (remainingPaths.length === 0) {
- success = true;
- } else {
- console.error("cleanup attempt #" + attempts + " failed");
- }
-
- // limit the number of attempts
- attempts += 1;
- if (attempts >= MAX_REMOVAL_ATTEMPTS) {
- break;
- }
- }
-
- // if loop exited without success, return an error
- if (success === false) {
- fatal("failed to remove files");
- }
-}
-
-// main
-function main() {
-
- // shell config
- shelljs.config.fatal = false;
- shelljs.config.silent = false;
-
- // get args
- var command = argv._[0];
-
- // run command
- switch (command) {
- case "clean":
- commandClean();
- break;
- default:
- fatal("unknown command " + command);
- }
-}
-
-main();
http://git-wip-us.apache.org/repos/asf/cordova-medic/blob/49da31f2/lib/util.js
----------------------------------------------------------------------
diff --git a/lib/util.js b/lib/util.js
new file mode 100644
index 0000000..d5d514d
--- /dev/null
+++ b/lib/util.js
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* jshint node: true */
+
+module.exports = function () {
+
+ var os = require("os");
+
+ return {
+
+ ANDROID: "android",
+ BLACKBERRY: "blackberry10",
+ IOS: "ios",
+ WINDOWS: "windows",
+ WP8: "wp8",
+
+ fatal: function (message) {
+ console.error("FATAL: " + message);
+ process.exit(1);
+ },
+
+ isWindows: function () {
+ // NOTE:
+ // - including "^" because otherwise "Darwin" matches
+ // - only "win" and not "windows" because "win32" should also match
+ return /^win/.test(os.platform());
+ },
+
+ medicLog: function (message) {
+ var RED_COLOR = "\033[31m";
+ var NO_COLOR = "\033[m";
+ console.log(RED_COLOR + "[MEDIC LOG]" + NO_COLOR + " " + message);
+ },
+
+ contains: function (collection, item) {
+ return collection.indexOf(item) != (-1);
+ }
+ };
+}();
http://git-wip-us.apache.org/repos/asf/cordova-medic/blob/49da31f2/medic/medic-check.js
----------------------------------------------------------------------
diff --git a/medic/medic-check.js b/medic/medic-check.js
new file mode 100644
index 0000000..cbff9fb
--- /dev/null
+++ b/medic/medic-check.js
@@ -0,0 +1,58 @@
+#!/usr/bin/env node
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* jshint node: true */
+
+"use strict";
+
+var optimist = require("optimist");
+
+var testcheck = require("../lib/testcheck");
+
+function main() {
+
+ // get args
+ var argv = optimist
+ .usage("Usage: $0 {options}")
+ .demand("id")
+ .demand("couchdb")
+ .argv;
+
+ var buildId = argv.id;
+ var couchdbURI = argv.couchdb;
+
+ var result = testcheck(buildId, couchdbURI);
+ result.then(
+ function onFulfilled(value) {
+ if (value === true) {
+ process.exitCode = 0;
+ } else {
+ process.exitCode = 1;
+ }
+ },
+ function onRejected(error) {
+ console.error("test check failed: " + error);
+ process.exitCode = 1;
+ }
+ );
+}
+
+main();
http://git-wip-us.apache.org/repos/asf/cordova-medic/blob/49da31f2/medic/medic-checkout.js
----------------------------------------------------------------------
diff --git a/medic/medic-checkout.js b/medic/medic-checkout.js
new file mode 100644
index 0000000..0cb978a
--- /dev/null
+++ b/medic/medic-checkout.js
@@ -0,0 +1,80 @@
+#!/usr/bin/env node
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* jshint node: true */
+
+"use strict";
+
+var fs = require("fs");
+
+var shelljs = require("shelljs");
+var optimist = require("optimist");
+
+var util = require("../lib/util");
+
+// helpers
+function cloneProject(projectName, projectsConfig) {
+
+ var project = projectsConfig[projectName];
+ var codebase = project.codebases[project.codebase];
+ var command = "git clone " + codebase.repo + " --branch=" + codebase.branch + " --depth 1"
+
+ shelljs.exec(command, {silent: false, async: true}, function (returnCode, output) {
+ if (returnCode !== 0) {
+ util.fatal("command \"" + command + "\" failed with code " + returnCode);
+ }
+ });
+}
+
+// main
+function main() {
+
+ // shell config
+ shelljs.config.fatal = false;
+ shelljs.config.silent = false;
+
+ // get args
+ var argv = optimist
+ .usage("Usage: $0 --config {path} --exclude {name[,name[,...]]}")
+ .demand("config")
+ .describe("exclude", "repositories not to clone")
+ .argv;
+
+ var configFile = argv.config;
+ var excludedNames = [];
+
+ // parse excludes
+ if (argv.exclude) {
+ excludedNames = argv.exclude.split(",");
+ }
+
+ // read in config
+ var projectsConfig = JSON.parse(fs.readFileSync(configFile, "utf-8"));
+
+ // clone all projects in the config
+ for (var projectName in projectsConfig) {
+ if (excludedNames.indexOf(projectName) === (-1)) {
+ cloneProject(projectName, projectsConfig);
+ }
+ }
+}
+
+main();
http://git-wip-us.apache.org/repos/asf/cordova-medic/blob/49da31f2/medic/medic-clean.js
----------------------------------------------------------------------
diff --git a/medic/medic-clean.js b/medic/medic-clean.js
new file mode 100644
index 0000000..5a93acf
--- /dev/null
+++ b/medic/medic-clean.js
@@ -0,0 +1,111 @@
+#!/usr/bin/env node
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* jshint node: true */
+
+"use strict";
+
+var fs = require("fs");
+
+var shelljs = require("shelljs");
+var optimist = require("optimist");
+
+var util = require("../lib/util");
+
+// constants
+var MAX_REMOVAL_ATTEMPTS = 3;
+
+// helpers
+function exclusiveLs(lsPath, excludes) {
+ var paths = fs.readdirSync(lsPath);
+ return paths.filter(function (pathName) {
+ return !util.contains(excludes, pathName);
+ });
+}
+
+// main
+function main() {
+
+ // shell config
+ shelljs.config.fatal = false;
+ shelljs.config.silent = false;
+
+ // get args
+ var argv = optimist
+ .usage("Usage: $0 --exclude {name[,name[,...]]}")
+ .argv;
+
+ var excludeString = argv.exclude;
+ var excludedPaths = [".", ".."];
+
+ // parse excludes
+ if (argv.exclude) {
+ excludedPaths = excludedPaths.concat(excludeString.split(","));
+ }
+
+ // get all directories except excluded ones
+ var pathsToRemove = exclusiveLs(".", excludedPaths);
+
+ util.medicLog("NOT removing the following paths:");
+ util.medicLog("[ " + excludedPaths.join(" , ") + " ]");
+ util.medicLog("removing the following paths:");
+ util.medicLog("[ " + pathsToRemove.join(" , ") + " ]");
+
+ // skip if there are no paths to delete
+ if (pathsToRemove.length <= 0) {
+ return;
+ }
+
+ // attempt to delete the paths
+ var attempts = 0;
+ var success = false;
+ while (success === false) {
+
+ util.medicLog("cleanup attempt #" + attempts + " started");
+
+ // try to remove the paths
+ shelljs.rm("-rf", pathsToRemove);
+
+ // check if any of them remain
+ var remainingPaths = exclusiveLs(".", excludedPaths);
+ if (remainingPaths.length === 0) {
+ success = true;
+ } else {
+ console.error("cleanup attempt #" + attempts + " failed");
+ }
+
+ // limit the number of attempts
+ attempts += 1;
+ if (attempts >= MAX_REMOVAL_ATTEMPTS) {
+ break;
+ }
+ }
+
+ // if loop exited without success, return an error
+ if (success === false) {
+ console.error("failed to remove files");
+ process.exitCode = 1;
+ } else {
+ util.medicLog("cleanup succeeded");
+ }
+}
+
+main();
http://git-wip-us.apache.org/repos/asf/cordova-medic/blob/49da31f2/medic/medic-kill.js
----------------------------------------------------------------------
diff --git a/medic/medic-kill.js b/medic/medic-kill.js
new file mode 100644
index 0000000..998509f
--- /dev/null
+++ b/medic/medic-kill.js
@@ -0,0 +1,110 @@
+#!/usr/bin/env node
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* jshint node: true */
+
+"use strict";
+
+var shelljs = require("shelljs");
+var optimist = require("optimist");
+
+var util = require("../lib/util");
+
+// helpers
+function tasksOnPlatform(platformName) {
+ switch (platformName) {
+ case util.WINDOWS:
+ return ["WWAHost.exe"];
+ case util.WP8:
+ return ["Xde.exe"];
+ case util.IOS:
+ return ["iOS Simulator"];
+ case util.ANDROID:
+ if (util.isWindows()) {
+ return ["emulator-arm.exe", "adb.exe"];
+ } else {
+ return ["emulator64-x86"];
+ }
+ case util.BLACKBERRY:
+ return [];
+ default:
+ util.fatal("unknown platform " + platformName);
+ }
+}
+
+function getKillCommand(taskNames) {
+
+ if (util.isWindows()) {
+ var cli = "taskkill /F";
+ var args = taskNames.map(function (name) { return "/IM \"" + name + "\""; });
+ } else {
+ var cli = "killall";
+ var args = taskNames.map(function (name) { return "\"" + name + "\""; });
+ }
+
+ return cli + " " + args.join(" ");
+}
+
+function killTasks(taskNames) {
+
+ if (!taskNames || taskNames.length < 1) {
+ return;
+ }
+
+ var command = getKillCommand(taskNames);
+
+ util.medicLog("running the following command:");
+ util.medicLog(" " + command);
+
+ shelljs.exec(command, {silent: false, async: true}, function (returnCode, output) {
+ if (returnCode !== 0) {
+ console.warn("WARNING: kill command returned " + returnCode);
+ }
+ });
+}
+
+// main
+function main() {
+
+ // shell config
+ shelljs.config.fatal = false;
+ shelljs.config.silent = false;
+
+ // get args
+ var argv = optimist
+ .usage("Usage: $0 --platform {platform}")
+ .demand("platform")
+ .argv;
+
+ var platform = argv.platform;
+
+ // get platform tasks
+ var platformTasks = tasksOnPlatform(platform);
+
+ if (platformTasks.length < 1) {
+ console.warn("no known tasks to kill");
+ }
+
+ // kill them
+ killTasks(platformTasks);
+}
+
+main();
http://git-wip-us.apache.org/repos/asf/cordova-medic/blob/49da31f2/medic/medic-run.js
----------------------------------------------------------------------
diff --git a/medic/medic-run.js b/medic/medic-run.js
new file mode 100644
index 0000000..a953a80
--- /dev/null
+++ b/medic/medic-run.js
@@ -0,0 +1,380 @@
+#!/usr/bin/env node
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* jshint node: true */
+
+"use strict";
+
+var fs = require("fs");
+var path = require("path");
+
+var shelljs = require("shelljs");
+var optimist = require("optimist");
+
+var util = require("../lib/util");
+var testwait = require("../lib/testwait");
+
+// constants
+var DEFAULT_ENCODING = "utf-8";
+var CORDOVA_MEDIC_DIR = "cordova-medic";
+var DEFAULT_APP_PATH = "mobilespec";
+var DEFAULT_APP_ENTRY = "index.html";
+var ANDROID_TIMEOUT = 120000; // in milliseconds
+var MEDIC_BUILD_PREFIX = "medic-cli-build";
+var DEFAULT_WINDOWS_VERSION = "store";
+var WINDOWS_VERSION_CHOICES = ["store", "store80", "phone"];
+var DEFAULT_TIMEOUT = 600; // in seconds
+
+// helpers
+function currentMillisecond() {
+ // NOTE:
+ // coercing a Date to a Number returns
+ // the Date's representation in milliseconds
+ return Number(new Date());
+}
+
+function generateBuildID() {
+ var components = [MEDIC_BUILD_PREFIX, currentMillisecond()];
+ return components.join("-");
+}
+
+function getConfigPath(appPath) {
+ return path.join(appPath, "config.xml");
+}
+
+function getCSPPath(appPath) {
+ return path.join(appPath, "www", "csp-incl.js");
+}
+
+function createMedicJson(appPath, buildId, couchdbURI) {
+
+ util.medicLog("Writing medic.json to " + appPath);
+ util.medicLog(" sha: " + buildId);
+ util.medicLog(" couchdb: " + couchdbURI);
+
+ // NOTE:
+ // the "sha" name is a misnomer, but is kept
+ // to be compatible with plugin-test-framework
+ var medicConfig = {
+ sha: buildId,
+ couchdb: couchdbURI
+ };
+
+ var medicConfigContents = JSON.stringify(medicConfig) + "\n";
+ var medicConfigPath = path.join(appPath, "www", "medic.json");
+
+ fs.writeFileSync(medicConfigPath, medicConfigContents, DEFAULT_ENCODING);
+}
+
+function addURIToWhitelist(appPath, uri) {
+
+ var configFile = getConfigPath(appPath);
+ var cspFile = getCSPPath(appPath);
+
+ var configContent = fs.readFileSync(configFile, DEFAULT_ENCODING);
+ var cspContent = fs.readFileSync(cspFile, DEFAULT_ENCODING);
+
+ // add whitelisting rule allow access to couch server
+ util.medicLog("Adding whitelist rule for CouchDB host: " + uri);
+ var accessOriginTag = "<access origin=\"" + uri + "\" />";
+ if (!util.contains(configContent, accessOriginTag)) {
+ configContent = configContent.split("</widget>").join("");
+ configContent += " " + accessOriginTag + "\n</widget>\n";
+ fs.writeFileSync(configFile, configContent, DEFAULT_ENCODING);
+ }
+
+ // add couchdb address to csp rules
+ util.medicLog("Adding CSP rule for CouchDB host: " + uri);
+ var cspRule = "connect-src " + uri;
+ if (!util.contains(cspContent, cspRule)) {
+ cspContent = cspContent.replace("connect-src", cspRule);
+ fs.writeFileSync(cspFile, cspContent, DEFAULT_ENCODING);
+ }
+}
+
+function setEntryPoint(appPath, entryPoint) {
+
+ var configFile = getConfigPath(appPath);
+ var configContent = fs.readFileSync(configFile, DEFAULT_ENCODING);
+
+ // replace/add start page preference
+ // check if config.xml already contains <content /> element
+ util.medicLog("Setting entry point to " + entryPoint + " in config.xml");
+
+ if (configContent.match(/<content\s*src=".*"\s*\/>/gi)) {
+ configContent = configContent.replace(
+ /<content\s*src=".*"\s*\/>/gi,
+ "<content src=\"" + entryPoint + "\" />"
+ );
+
+ } else {
+
+ // add entry point to config
+ configContent = configContent.split("</widget>").join("") +
+ " <content src=\"" + entryPoint + "\" />\n</widget>";
+ }
+
+ // write the changes
+ fs.writeFileSync(configFile, configContent, DEFAULT_ENCODING);
+}
+
+function changeAndroidLoadTimeout(appPath, timeout) {
+
+ util.medicLog("Increasing url loading timeout for android to " + timeout);
+
+ var timeoutRegex = /<preference\s*name\s *= \s*"?loadUrlTimeoutValue"?.*?((\/>)|(>.*?<\/\s*preference>))/i;
+ var timeoutTag = "<preference name=\"loadUrlTimeoutValue\" value=\"" + timeout + "\" />";
+ var timeoutTagWithPlatform = " <platform name=\"android\">\n <preference name=\"loadUrlTimeoutValue\" value=\"120000\" />\n </platform>\n";
+ var platformRegex = /<platform\s*name\s *= \s*"android"\s*>/i;
+ var widgetRegex = /<\/s*widget\s*>/i;
+
+ var configFile = getConfigPath(appPath);
+ var configContent = fs.readFileSync(configFile, DEFAULT_ENCODING);
+
+ if (timeoutRegex.test(configContent)) {
+ configContent = configContent.replace(timeoutRegex, timeoutTag);
+ util.medicLog("Found \"loadUrlTimeoutValue\" preference, replacing with desired value");
+ } else if (platformRegex.test(configContent)) {
+ var oldPlatformTag = platformRegex.exec(configContent)[0];
+ configContent = configContent.replace(platformRegex, oldPlatformTag + "\n " + timeoutTag);
+ util.medicLog("Found platform tag, appending \"loadUrlTimeoutValue\" preference");
+ } else if (widgetRegex.test(configContent)) {
+ var oldWidgetTag = widgetRegex.exec(configContent)[0];
+ configContent = configContent.replace(widgetRegex, timeoutTagWithPlatform + oldWidgetTag);
+ util.medicLog("Did not find platform tag, adding preference with platform tag");
+ } else {
+ util.medicLog("Warning: could not modify config.xml for android: no <widget> tag found!");
+ }
+
+ // write the changes
+ fs.writeFileSync(configFile, configContent, DEFAULT_ENCODING);
+}
+
+function setWindowsTargetStoreVersion(appPath, version) {
+
+ util.medicLog('setting target store version to ' + version);
+
+ var configFile = getConfigPath(appPath);
+ var configContent = fs.readFileSync(configFile, DEFAULT_ENCODING);
+
+ var versionPreference = ' <preference name="windows-target-version" value="' + version + '" />';
+ configContent = configContent.replace('</widget>', versionPreference + '\r\n</widget>');
+
+ fs.writeFileSync(configFile, configContent, "utf8");
+}
+
+function androidSpecificPreparation(argv) {
+
+ var appPath = argv.app;
+ var extraArgs = "--ant";
+
+ changeAndroidLoadTimeout(appPath, ANDROID_TIMEOUT);
+
+ return extraArgs;
+}
+
+function windowsSpecificPreparation(argv) {
+
+ var appPath = argv.app;
+ var winVersion = argv.winvers;
+ var extraArgs = "";
+
+ if (!util.contains(WINDOWS_VERSION_CHOICES, winVersion)) {
+ util.fatal("invalid windows version: " + winVersion);
+ }
+
+ // set windows target store version
+ if (winVersion === "store80") {
+ setWindowsTargetStoreVersion(appPath, "8.0");
+ extraArgs = "--win";
+
+ } else if (winVersion === "store") {
+ setWindowsTargetStoreVersion(appPath, "8.1");
+ extraArgs = "--win";
+
+ } else if (winVersion === "phone") {
+ setWindowsTargetStoreVersion(appPath, "8.1");
+ extraArgs = "--phone";
+ }
+
+ // patch WindowsStoreAppUtils script to allow app run w/out active desktop/remote session
+ if (winVersion === "store80" || winVersion === "store") {
+
+ util.medicLog('Patching WindowsStoreAppUtils to allow app to be run in automated mode');
+
+ var platformPath = path.join(appPath, 'platforms', 'windows');
+
+ var libPath = path.join(platformPath, 'cordova', 'lib');
+ var appUtilsPath = path.join(libPath, 'WindowsStoreAppUtils.ps1');
+ var srcScriptPath = path.join('cordova-medic', 'lib', 'patches', 'EnableDebuggingForPackage.ps1');
+ var destScriptPath = path.join(libPath, 'EnableDebuggingForPackage.ps1');
+
+ // copy over the patch
+ shelljs.cp('-f', srcScriptPath, libPath);
+
+ // add extra code to patch
+ shelljs.sed(
+ '-i', /^\s*\$appActivator .*$/gim,
+ '$&\n' +
+ ' powershell ' + destScriptPath + ' $$ID\n' +
+ ' $Ole32 = Add-Type -MemberDefinition \'[DllImport("Ole32.dll")]public static extern int CoAllowSetForegroundWindow(IntPtr pUnk, IntPtr lpvReserved);\' -Name \'Ole32\' -Namespace \'Win32\' -PassThru\n' +
+ ' $Ole32::CoAllowSetForegroundWindow([System.Runtime.InteropServices.Marshal]::GetIUnknownForObject($appActivator), [System.IntPtr]::Zero)',
+ appUtilsPath
+ );
+ }
+
+ return extraArgs;
+}
+
+function wp8SpecificPreparation(argv) {
+
+ var appPath = argv.app;
+
+ // set permanent guid to prevent multiple installations
+ var guid = '{8449DEEE-16EB-4A4A-AFCC-8446E8F06FF7}';
+ var manifestPath = path.join(appPath, 'platforms', 'wp8', 'Properties', 'WMAppManifest.xml');
+ var xml = fs.readFileSync(manifestPath).toString().split('\n');
+
+ for (var i in xml) if (xml[i].indexOf('<App') != -1) {
+ if (xml[i].toLowerCase().indexOf('productid') != -1) {
+ var index = xml[i].toLowerCase().indexOf('productid');
+ var spaceIndex = xml[i].indexOf(' ', index);
+ var stringAsArray = xml[i].split('');
+ stringAsArray.splice(index, spaceIndex - index);
+ xml[i] = stringAsArray.join('');
+ }
+ xml[i] = xml[i].substr(0, xml[i].length - 1);
+ xml[i] += ' ProductID="' + guid + '">';
+ break;
+ }
+
+ fs.writeFileSync(manifestPath, xml.join('\n'));
+
+ var extraArgs = "";
+ return extraArgs;
+}
+
+function getLocalCLI() {
+ if (util.isWindows()) {
+ return "cordova.bat";
+ } else {
+ return "./cordova";
+ }
+}
+
+// main
+function main() {
+
+ // shell config
+ shelljs.config.fatal = false;
+ shelljs.config.silent = false;
+
+ // get args
+ var argv = optimist
+ .usage("Usage: $0 {options}")
+ .demand("platform")
+ .demand("couchdb")
+ .default("entry", DEFAULT_APP_ENTRY)
+ .default("id", generateBuildID())
+ .default("app", DEFAULT_APP_PATH)
+ .default("timeout", DEFAULT_TIMEOUT).describe("timeout", "timeout in seconds")
+ .default("winvers", DEFAULT_WINDOWS_VERSION).describe("winvers", "[" + WINDOWS_VERSION_CHOICES.join("|") + "]")
+ .argv;
+
+ var platform = argv.platform;
+ var buildId = argv.id;
+ var appPath = argv.app;
+ var couchdbURI = argv.couchdb;
+ var entryPoint = argv.entry;
+ var timeout = argv.timeout;
+
+ var cli = getLocalCLI();
+
+ // check that the app exists
+ if (!fs.existsSync(appPath)) {
+ util.fatal("app " + appPath + " does not exist");
+ }
+
+ // modify the app to run autonomously
+ createMedicJson(appPath, buildId, couchdbURI);
+ setEntryPoint(appPath, entryPoint);
+ addURIToWhitelist(appPath, couchdbURI);
+
+ // do platform-specific preparations
+ var platformArgs = "";
+ if (platform === util.ANDROID) {
+ platformArgs = androidSpecificPreparation(argv);
+ } else if (platform === util.WINDOWS) {
+ platformArgs = windowsSpecificPreparation(argv);
+ } else if (platform === util.WP8) {
+ platformArgs = wp8SpecificPreparation(argv);
+ }
+
+ // enter the app directory
+ shelljs.pushd(appPath);
+
+ // build the code (synchronously)
+ var buildCommand = cli + " build " + platform + " -- " + platformArgs;
+ util.medicLog("building:");
+ util.medicLog(" " + buildCommand);
+
+ var result = shelljs.exec(buildCommand, {silent: false, async: false});
+ if (result.code != 0) {
+ console.error("BUILD FAILED:\n" + result.output);
+ util.fatal("build failed");
+ }
+
+ // run the code (asynchronously)
+ var runCommand = cli + " run " + platform + " -- " + platformArgs;
+ util.medicLog("running:");
+ util.medicLog(" " + runCommand);
+
+ shelljs.exec(runCommand, {silent: false, async: true}, function (returnCode, output) {
+ if (returnCode != 0) {
+ console.error("RUN FAILED:\n" + result.output);
+ util.fatal("run failed");
+ }
+ });
+
+ // exit the app directory
+ shelljs.popd();
+
+ // wait for test results
+ // NOTE:
+ // timeout needs to be in milliseconds, but it's
+ // given in seconds, so we multiply by 1000
+ util.medicLog("watching for test results");
+ testwait.init(couchdbURI);
+ testwait.waitTestsCompleted(buildId, timeout * 1000).then(
+ function onFulfilled(value) {
+ util.medicLog("got test results");
+ process.exit(process.exitCode);
+ },
+ function onRejected(error) {
+ console.error("didn't get test results: " + error);
+ process.exitCode = 1;
+ }
+ );
+
+ util.medicLog("waiting ...");
+}
+
+main();
http://git-wip-us.apache.org/repos/asf/cordova-medic/blob/49da31f2/medic/medic.js
----------------------------------------------------------------------
diff --git a/medic/medic.js b/medic/medic.js
new file mode 100755
index 0000000..f58a39a
--- /dev/null
+++ b/medic/medic.js
@@ -0,0 +1,40 @@
+#!/usr/bin/env node
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* jshint node: true */
+
+"use strict";
+
+var commander = require("commander");
+
+function main() {
+
+ // delegate work to subcommands
+ commander
+ .command("clean", "clean the current directory")
+ .command("kill", "kill tasks spawned by a platform run")
+ .command("checkout", "check out repositories")
+ .command("run", "run a cordova app in automated mode")
+ .command("check", "analyze test runs from a medic DB")
+ .parse(process.argv);
+}
+
+main();
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org