cordova-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From purplecabb...@apache.org
Subject [04/14] Rewrite tooling/platform scripts from WSH to NodeJS
Date Fri, 08 Aug 2014 23:04:29 GMT
http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/node_modules/shelljs/src/ls.js
----------------------------------------------------------------------
diff --git a/windows/node_modules/shelljs/src/ls.js b/windows/node_modules/shelljs/src/ls.js
new file mode 100644
index 0000000..3345db4
--- /dev/null
+++ b/windows/node_modules/shelljs/src/ls.js
@@ -0,0 +1,126 @@
+var path = require('path');
+var fs = require('fs');
+var common = require('./common');
+var _cd = require('./cd');
+var _pwd = require('./pwd');
+
+//@
+//@ ### ls([options ,] path [,path ...])
+//@ ### ls([options ,] path_array)
+//@ Available options:
+//@
+//@ + `-R`: recursive
+//@ + `-A`: all files (include files beginning with `.`, except for `.` and `..`)
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ ls('projs/*.js');
+//@ ls('-R', '/users/me', '/tmp');
+//@ ls('-R', ['/users/me', '/tmp']); // same as above
+//@ ```
+//@
+//@ Returns array of files in the given path, or in current directory if no path provided.
+function _ls(options, paths) {
+  options = common.parseOptions(options, {
+    'R': 'recursive',
+    'A': 'all',
+    'a': 'all_deprecated'
+  });
+
+  if (options.all_deprecated) {
+    // We won't support the -a option as it's hard to image why it's useful
+    // (it includes '.' and '..' in addition to '.*' files)
+    // For backwards compatibility we'll dump a deprecated message and proceed as before
+    common.log('ls: Option -a is deprecated. Use -A instead');
+    options.all = true;
+  }
+
+  if (!paths)
+    paths = ['.'];
+  else if (typeof paths === 'object')
+    paths = paths; // assume array
+  else if (typeof paths === 'string')
+    paths = [].slice.call(arguments, 1);
+
+  var list = [];
+
+  // Conditionally pushes file to list - returns true if pushed, false otherwise
+  // (e.g. prevents hidden files to be included unless explicitly told so)
+  function pushFile(file, query) {
+    // hidden file?
+    if (path.basename(file)[0] === '.') {
+      // not explicitly asking for hidden files?
+      if (!options.all && !(path.basename(query)[0] === '.' && path.basename(query).length > 1))
+        return false;
+    }
+
+    if (common.platform === 'win')
+      file = file.replace(/\\/g, '/');
+
+    list.push(file);
+    return true;
+  }
+
+  paths.forEach(function(p) {
+    if (fs.existsSync(p)) {
+      var stats = fs.statSync(p);
+      // Simple file?
+      if (stats.isFile()) {
+        pushFile(p, p);
+        return; // continue
+      }
+
+      // Simple dir?
+      if (stats.isDirectory()) {
+        // Iterate over p contents
+        fs.readdirSync(p).forEach(function(file) {
+          if (!pushFile(file, p))
+            return;
+
+          // Recursive?
+          if (options.recursive) {
+            var oldDir = _pwd();
+            _cd('', p);
+            if (fs.statSync(file).isDirectory())
+              list = list.concat(_ls('-R'+(options.all?'A':''), file+'/*'));
+            _cd('', oldDir);
+          }
+        });
+        return; // continue
+      }
+    }
+
+    // p does not exist - possible wildcard present
+
+    var basename = path.basename(p);
+    var dirname = path.dirname(p);
+    // Wildcard present on an existing dir? (e.g. '/tmp/*.js')
+    if (basename.search(/\*/) > -1 && fs.existsSync(dirname) && fs.statSync(dirname).isDirectory) {
+      // Escape special regular expression chars
+      var regexp = basename.replace(/(\^|\$|\(|\)|<|>|\[|\]|\{|\}|\.|\+|\?)/g, '\\$1');
+      // Translates wildcard into regex
+      regexp = '^' + regexp.replace(/\*/g, '.*') + '$';
+      // Iterate over directory contents
+      fs.readdirSync(dirname).forEach(function(file) {
+        if (file.match(new RegExp(regexp))) {
+          if (!pushFile(path.normalize(dirname+'/'+file), basename))
+            return;
+
+          // Recursive?
+          if (options.recursive) {
+            var pp = dirname + '/' + file;
+            if (fs.lstatSync(pp).isDirectory())
+              list = list.concat(_ls('-R'+(options.all?'A':''), pp+'/*'));
+          } // recursive
+        } // if file matches
+      }); // forEach
+      return;
+    }
+
+    common.error('no such file or directory: ' + p, true);
+  });
+
+  return list;
+}
+module.exports = _ls;

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/node_modules/shelljs/src/mkdir.js
----------------------------------------------------------------------
diff --git a/windows/node_modules/shelljs/src/mkdir.js b/windows/node_modules/shelljs/src/mkdir.js
new file mode 100644
index 0000000..5a7088f
--- /dev/null
+++ b/windows/node_modules/shelljs/src/mkdir.js
@@ -0,0 +1,68 @@
+var common = require('./common');
+var fs = require('fs');
+var path = require('path');
+
+// Recursively creates 'dir'
+function mkdirSyncRecursive(dir) {
+  var baseDir = path.dirname(dir);
+
+  // Base dir exists, no recursion necessary
+  if (fs.existsSync(baseDir)) {
+    fs.mkdirSync(dir, parseInt('0777', 8));
+    return;
+  }
+
+  // Base dir does not exist, go recursive
+  mkdirSyncRecursive(baseDir);
+
+  // Base dir created, can create dir
+  fs.mkdirSync(dir, parseInt('0777', 8));
+}
+
+//@
+//@ ### mkdir([options ,] dir [, dir ...])
+//@ ### mkdir([options ,] dir_array)
+//@ Available options:
+//@
+//@ + `p`: full path (will create intermediate dirs if necessary)
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ mkdir('-p', '/tmp/a/b/c/d', '/tmp/e/f/g');
+//@ mkdir('-p', ['/tmp/a/b/c/d', '/tmp/e/f/g']); // same as above
+//@ ```
+//@
+//@ Creates directories.
+function _mkdir(options, dirs) {
+  options = common.parseOptions(options, {
+    'p': 'fullpath'
+  });
+  if (!dirs)
+    common.error('no paths given');
+
+  if (typeof dirs === 'string')
+    dirs = [].slice.call(arguments, 1);
+  // if it's array leave it as it is
+
+  dirs.forEach(function(dir) {
+    if (fs.existsSync(dir)) {
+      if (!options.fullpath)
+          common.error('path already exists: ' + dir, true);
+      return; // skip dir
+    }
+
+    // Base dir does not exist, and no -p option given
+    var baseDir = path.dirname(dir);
+    if (!fs.existsSync(baseDir) && !options.fullpath) {
+      common.error('no such file or directory: ' + baseDir, true);
+      return; // skip dir
+    }
+
+    if (options.fullpath)
+      mkdirSyncRecursive(dir);
+    else
+      fs.mkdirSync(dir, parseInt('0777', 8));
+  });
+} // mkdir
+module.exports = _mkdir;

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/node_modules/shelljs/src/mv.js
----------------------------------------------------------------------
diff --git a/windows/node_modules/shelljs/src/mv.js b/windows/node_modules/shelljs/src/mv.js
new file mode 100644
index 0000000..11f9607
--- /dev/null
+++ b/windows/node_modules/shelljs/src/mv.js
@@ -0,0 +1,80 @@
+var fs = require('fs');
+var path = require('path');
+var common = require('./common');
+
+//@
+//@ ### mv(source [, source ...], dest')
+//@ ### mv(source_array, dest')
+//@ Available options:
+//@
+//@ + `f`: force
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ mv('-f', 'file', 'dir/');
+//@ mv('file1', 'file2', 'dir/');
+//@ mv(['file1', 'file2'], 'dir/'); // same as above
+//@ ```
+//@
+//@ Moves files. The wildcard `*` is accepted.
+function _mv(options, sources, dest) {
+  options = common.parseOptions(options, {
+    'f': 'force'
+  });
+
+  // Get sources, dest
+  if (arguments.length < 3) {
+    common.error('missing <source> and/or <dest>');
+  } else if (arguments.length > 3) {
+    sources = [].slice.call(arguments, 1, arguments.length - 1);
+    dest = arguments[arguments.length - 1];
+  } else if (typeof sources === 'string') {
+    sources = [sources];
+  } else if ('length' in sources) {
+    sources = sources; // no-op for array
+  } else {
+    common.error('invalid arguments');
+  }
+
+  sources = common.expand(sources);
+
+  var exists = fs.existsSync(dest),
+      stats = exists && fs.statSync(dest);
+
+  // Dest is not existing dir, but multiple sources given
+  if ((!exists || !stats.isDirectory()) && sources.length > 1)
+    common.error('dest is not a directory (too many sources)');
+
+  // Dest is an existing file, but no -f given
+  if (exists && stats.isFile() && !options.force)
+    common.error('dest file already exists: ' + dest);
+
+  sources.forEach(function(src) {
+    if (!fs.existsSync(src)) {
+      common.error('no such file or directory: '+src, true);
+      return; // skip file
+    }
+
+    // If here, src exists
+
+    // When copying to '/path/dir':
+    //    thisDest = '/path/dir/file1'
+    var thisDest = dest;
+    if (fs.existsSync(dest) && fs.statSync(dest).isDirectory())
+      thisDest = path.normalize(dest + '/' + path.basename(src));
+
+    if (fs.existsSync(thisDest) && !options.force) {
+      common.error('dest file already exists: ' + thisDest, true);
+      return; // skip file
+    }
+
+    if (path.resolve(src) === path.dirname(path.resolve(thisDest))) {
+      common.error('cannot move to self: '+src, true);
+      return; // skip file
+    }
+
+    fs.renameSync(src, thisDest);
+  }); // forEach(src)
+} // mv
+module.exports = _mv;

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/node_modules/shelljs/src/popd.js
----------------------------------------------------------------------
diff --git a/windows/node_modules/shelljs/src/popd.js b/windows/node_modules/shelljs/src/popd.js
new file mode 100644
index 0000000..11ea24f
--- /dev/null
+++ b/windows/node_modules/shelljs/src/popd.js
@@ -0,0 +1 @@
+// see dirs.js
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/node_modules/shelljs/src/pushd.js
----------------------------------------------------------------------
diff --git a/windows/node_modules/shelljs/src/pushd.js b/windows/node_modules/shelljs/src/pushd.js
new file mode 100644
index 0000000..11ea24f
--- /dev/null
+++ b/windows/node_modules/shelljs/src/pushd.js
@@ -0,0 +1 @@
+// see dirs.js
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/node_modules/shelljs/src/pwd.js
----------------------------------------------------------------------
diff --git a/windows/node_modules/shelljs/src/pwd.js b/windows/node_modules/shelljs/src/pwd.js
new file mode 100644
index 0000000..41727bb
--- /dev/null
+++ b/windows/node_modules/shelljs/src/pwd.js
@@ -0,0 +1,11 @@
+var path = require('path');
+var common = require('./common');
+
+//@
+//@ ### pwd()
+//@ Returns the current directory.
+function _pwd(options) {
+  var pwd = path.resolve(process.cwd());
+  return common.ShellString(pwd);
+}
+module.exports = _pwd;

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/node_modules/shelljs/src/rm.js
----------------------------------------------------------------------
diff --git a/windows/node_modules/shelljs/src/rm.js b/windows/node_modules/shelljs/src/rm.js
new file mode 100644
index 0000000..3abe6e1
--- /dev/null
+++ b/windows/node_modules/shelljs/src/rm.js
@@ -0,0 +1,145 @@
+var common = require('./common');
+var fs = require('fs');
+
+// Recursively removes 'dir'
+// Adapted from https://github.com/ryanmcgrath/wrench-js
+//
+// Copyright (c) 2010 Ryan McGrath
+// Copyright (c) 2012 Artur Adib
+//
+// Licensed under the MIT License
+// http://www.opensource.org/licenses/mit-license.php
+function rmdirSyncRecursive(dir, force) {
+  var files;
+
+  files = fs.readdirSync(dir);
+
+  // Loop through and delete everything in the sub-tree after checking it
+  for(var i = 0; i < files.length; i++) {
+    var file = dir + "/" + files[i],
+        currFile = fs.lstatSync(file);
+
+    if(currFile.isDirectory()) { // Recursive function back to the beginning
+      rmdirSyncRecursive(file, force);
+    }
+
+    else if(currFile.isSymbolicLink()) { // Unlink symlinks
+      if (force || isWriteable(file)) {
+        try {
+          common.unlinkSync(file);
+        } catch (e) {
+          common.error('could not remove file (code '+e.code+'): ' + file, true);
+        }
+      }
+    }
+
+    else // Assume it's a file - perhaps a try/catch belongs here?
+      if (force || isWriteable(file)) {
+        try {
+          common.unlinkSync(file);
+        } catch (e) {
+          common.error('could not remove file (code '+e.code+'): ' + file, true);
+        }
+      }
+  }
+
+  // Now that we know everything in the sub-tree has been deleted, we can delete the main directory.
+  // Huzzah for the shopkeep.
+
+  var result;
+  try {
+    result = fs.rmdirSync(dir);
+  } catch(e) {
+    common.error('could not remove directory (code '+e.code+'): ' + dir, true);
+  }
+
+  return result;
+} // rmdirSyncRecursive
+
+// Hack to determine if file has write permissions for current user
+// Avoids having to check user, group, etc, but it's probably slow
+function isWriteable(file) {
+  var writePermission = true;
+  try {
+    var __fd = fs.openSync(file, 'a');
+    fs.closeSync(__fd);
+  } catch(e) {
+    writePermission = false;
+  }
+
+  return writePermission;
+}
+
+//@
+//@ ### rm([options ,] file [, file ...])
+//@ ### rm([options ,] file_array)
+//@ Available options:
+//@
+//@ + `-f`: force
+//@ + `-r, -R`: recursive
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ rm('-rf', '/tmp/*');
+//@ rm('some_file.txt', 'another_file.txt');
+//@ rm(['some_file.txt', 'another_file.txt']); // same as above
+//@ ```
+//@
+//@ Removes files. The wildcard `*` is accepted.
+function _rm(options, files) {
+  options = common.parseOptions(options, {
+    'f': 'force',
+    'r': 'recursive',
+    'R': 'recursive'
+  });
+  if (!files)
+    common.error('no paths given');
+
+  if (typeof files === 'string')
+    files = [].slice.call(arguments, 1);
+  // if it's array leave it as it is
+
+  files = common.expand(files);
+
+  files.forEach(function(file) {
+    if (!fs.existsSync(file)) {
+      // Path does not exist, no force flag given
+      if (!options.force)
+        common.error('no such file or directory: '+file, true);
+
+      return; // skip file
+    }
+
+    // If here, path exists
+
+    var stats = fs.lstatSync(file);
+    if (stats.isFile() || stats.isSymbolicLink()) {
+
+      // Do not check for file writing permissions
+      if (options.force) {
+        common.unlinkSync(file);
+        return;
+      }
+
+      if (isWriteable(file))
+        common.unlinkSync(file);
+      else
+        common.error('permission denied: '+file, true);
+
+      return;
+    } // simple file
+
+    // Path is an existing directory, but no -r flag given
+    if (stats.isDirectory() && !options.recursive) {
+      common.error('path is a directory', true);
+      return; // skip path
+    }
+
+    // Recursively remove existing directory
+    if (stats.isDirectory() && options.recursive) {
+      rmdirSyncRecursive(file, options.force);
+    }
+  }); // forEach(file)
+} // rm
+module.exports = _rm;

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/node_modules/shelljs/src/sed.js
----------------------------------------------------------------------
diff --git a/windows/node_modules/shelljs/src/sed.js b/windows/node_modules/shelljs/src/sed.js
new file mode 100644
index 0000000..65f7cb4
--- /dev/null
+++ b/windows/node_modules/shelljs/src/sed.js
@@ -0,0 +1,43 @@
+var common = require('./common');
+var fs = require('fs');
+
+//@
+//@ ### sed([options ,] search_regex, replacement, file)
+//@ Available options:
+//@
+//@ + `-i`: Replace contents of 'file' in-place. _Note that no backups will be created!_
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ sed('-i', 'PROGRAM_VERSION', 'v0.1.3', 'source.js');
+//@ sed(/.*DELETE_THIS_LINE.*\n/, '', 'source.js');
+//@ ```
+//@
+//@ Reads an input string from `file` and performs a JavaScript `replace()` on the input
+//@ using the given search regex and replacement string or function. Returns the new string after replacement.
+function _sed(options, regex, replacement, file) {
+  options = common.parseOptions(options, {
+    'i': 'inplace'
+  });
+
+  if (typeof replacement === 'string' || typeof replacement === 'function')
+    replacement = replacement; // no-op
+  else if (typeof replacement === 'number')
+    replacement = replacement.toString(); // fallback
+  else
+    common.error('invalid replacement string');
+
+  if (!file)
+    common.error('no file given');
+
+  if (!fs.existsSync(file))
+    common.error('no such file or directory: ' + file);
+
+  var result = fs.readFileSync(file, 'utf8').replace(regex, replacement);
+  if (options.inplace)
+    fs.writeFileSync(file, result, 'utf8');
+
+  return common.ShellString(result);
+}
+module.exports = _sed;

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/node_modules/shelljs/src/tempdir.js
----------------------------------------------------------------------
diff --git a/windows/node_modules/shelljs/src/tempdir.js b/windows/node_modules/shelljs/src/tempdir.js
new file mode 100644
index 0000000..45953c2
--- /dev/null
+++ b/windows/node_modules/shelljs/src/tempdir.js
@@ -0,0 +1,56 @@
+var common = require('./common');
+var os = require('os');
+var fs = require('fs');
+
+// Returns false if 'dir' is not a writeable directory, 'dir' otherwise
+function writeableDir(dir) {
+  if (!dir || !fs.existsSync(dir))
+    return false;
+
+  if (!fs.statSync(dir).isDirectory())
+    return false;
+
+  var testFile = dir+'/'+common.randomFileName();
+  try {
+    fs.writeFileSync(testFile, ' ');
+    common.unlinkSync(testFile);
+    return dir;
+  } catch (e) {
+    return false;
+  }
+}
+
+
+//@
+//@ ### tempdir()
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ var tmp = tempdir(); // "/tmp" for most *nix platforms
+//@ ```
+//@
+//@ Searches and returns string containing a writeable, platform-dependent temporary directory.
+//@ Follows Python's [tempfile algorithm](http://docs.python.org/library/tempfile.html#tempfile.tempdir).
+function _tempDir() {
+  var state = common.state;
+  if (state.tempDir)
+    return state.tempDir; // from cache
+
+  state.tempDir = writeableDir(os.tempDir && os.tempDir()) || // node 0.8+
+                  writeableDir(process.env['TMPDIR']) ||
+                  writeableDir(process.env['TEMP']) ||
+                  writeableDir(process.env['TMP']) ||
+                  writeableDir(process.env['Wimp$ScrapDir']) || // RiscOS
+                  writeableDir('C:\\TEMP') || // Windows
+                  writeableDir('C:\\TMP') || // Windows
+                  writeableDir('\\TEMP') || // Windows
+                  writeableDir('\\TMP') || // Windows
+                  writeableDir('/tmp') ||
+                  writeableDir('/var/tmp') ||
+                  writeableDir('/usr/tmp') ||
+                  writeableDir('.'); // last resort
+
+  return state.tempDir;
+}
+module.exports = _tempDir;

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/node_modules/shelljs/src/test.js
----------------------------------------------------------------------
diff --git a/windows/node_modules/shelljs/src/test.js b/windows/node_modules/shelljs/src/test.js
new file mode 100644
index 0000000..8a4ac7d
--- /dev/null
+++ b/windows/node_modules/shelljs/src/test.js
@@ -0,0 +1,85 @@
+var common = require('./common');
+var fs = require('fs');
+
+//@
+//@ ### test(expression)
+//@ Available expression primaries:
+//@
+//@ + `'-b', 'path'`: true if path is a block device
+//@ + `'-c', 'path'`: true if path is a character device
+//@ + `'-d', 'path'`: true if path is a directory
+//@ + `'-e', 'path'`: true if path exists
+//@ + `'-f', 'path'`: true if path is a regular file
+//@ + `'-L', 'path'`: true if path is a symboilc link
+//@ + `'-p', 'path'`: true if path is a pipe (FIFO)
+//@ + `'-S', 'path'`: true if path is a socket
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ if (test('-d', path)) { /* do something with dir */ };
+//@ if (!test('-f', path)) continue; // skip if it's a regular file
+//@ ```
+//@
+//@ Evaluates expression using the available primaries and returns corresponding value.
+function _test(options, path) {
+  if (!path)
+    common.error('no path given');
+
+  // hack - only works with unary primaries
+  options = common.parseOptions(options, {
+    'b': 'block',
+    'c': 'character',
+    'd': 'directory',
+    'e': 'exists',
+    'f': 'file',
+    'L': 'link',
+    'p': 'pipe',
+    'S': 'socket'
+  });
+
+  var canInterpret = false;
+  for (var key in options)
+    if (options[key] === true) {
+      canInterpret = true;
+      break;
+    }
+
+  if (!canInterpret)
+    common.error('could not interpret expression');
+
+  if (options.link) {
+    try {
+      return fs.lstatSync(path).isSymbolicLink();
+    } catch(e) {
+      return false;
+    }
+  }
+
+  if (!fs.existsSync(path))
+    return false;
+
+  if (options.exists)
+    return true;
+
+  var stats = fs.statSync(path);
+
+  if (options.block)
+    return stats.isBlockDevice();
+
+  if (options.character)
+    return stats.isCharacterDevice();
+
+  if (options.directory)
+    return stats.isDirectory();
+
+  if (options.file)
+    return stats.isFile();
+
+  if (options.pipe)
+    return stats.isFIFO();
+
+  if (options.socket)
+    return stats.isSocket();
+} // test
+module.exports = _test;

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/node_modules/shelljs/src/to.js
----------------------------------------------------------------------
diff --git a/windows/node_modules/shelljs/src/to.js b/windows/node_modules/shelljs/src/to.js
new file mode 100644
index 0000000..f029999
--- /dev/null
+++ b/windows/node_modules/shelljs/src/to.js
@@ -0,0 +1,29 @@
+var common = require('./common');
+var fs = require('fs');
+var path = require('path');
+
+//@
+//@ ### 'string'.to(file)
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ cat('input.txt').to('output.txt');
+//@ ```
+//@
+//@ Analogous to the redirection operator `>` in Unix, but works with JavaScript strings (such as
+//@ those returned by `cat`, `grep`, etc). _Like Unix redirections, `to()` will overwrite any existing file!_
+function _to(options, file) {
+  if (!file)
+    common.error('wrong arguments');
+
+  if (!fs.existsSync( path.dirname(file) ))
+      common.error('no such file or directory: ' + path.dirname(file));
+
+  try {
+    fs.writeFileSync(file, this.toString(), 'utf8');
+  } catch(e) {
+    common.error('could not write to file (code '+e.code+'): '+file, true);
+  }
+}
+module.exports = _to;

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/node_modules/shelljs/src/toEnd.js
----------------------------------------------------------------------
diff --git a/windows/node_modules/shelljs/src/toEnd.js b/windows/node_modules/shelljs/src/toEnd.js
new file mode 100644
index 0000000..f6d099d
--- /dev/null
+++ b/windows/node_modules/shelljs/src/toEnd.js
@@ -0,0 +1,29 @@
+var common = require('./common');
+var fs = require('fs');
+var path = require('path');
+
+//@
+//@ ### 'string'.toEnd(file)
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ cat('input.txt').toEnd('output.txt');
+//@ ```
+//@
+//@ Analogous to the redirect-and-append operator `>>` in Unix, but works with JavaScript strings (such as
+//@ those returned by `cat`, `grep`, etc).
+function _toEnd(options, file) {
+  if (!file)
+    common.error('wrong arguments');
+
+  if (!fs.existsSync( path.dirname(file) ))
+      common.error('no such file or directory: ' + path.dirname(file));
+
+  try {
+    fs.appendFileSync(file, this.toString(), 'utf8');
+  } catch(e) {
+    common.error('could not append to file (code '+e.code+'): '+file, true);
+  }
+}
+module.exports = _toEnd;

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/node_modules/shelljs/src/which.js
----------------------------------------------------------------------
diff --git a/windows/node_modules/shelljs/src/which.js b/windows/node_modules/shelljs/src/which.js
new file mode 100644
index 0000000..2822ecf
--- /dev/null
+++ b/windows/node_modules/shelljs/src/which.js
@@ -0,0 +1,83 @@
+var common = require('./common');
+var fs = require('fs');
+var path = require('path');
+
+// Cross-platform method for splitting environment PATH variables
+function splitPath(p) {
+  for (i=1;i<2;i++) {}
+
+  if (!p)
+    return [];
+
+  if (common.platform === 'win')
+    return p.split(';');
+  else
+    return p.split(':');
+}
+
+function checkPath(path) {
+  return fs.existsSync(path) && fs.statSync(path).isDirectory() == false;
+}
+
+//@
+//@ ### which(command)
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ var nodeExec = which('node');
+//@ ```
+//@
+//@ Searches for `command` in the system's PATH. On Windows looks for `.exe`, `.cmd`, and `.bat` extensions.
+//@ Returns string containing the absolute path to the command.
+function _which(options, cmd) {
+  if (!cmd)
+    common.error('must specify command');
+
+  var pathEnv = process.env.path || process.env.Path || process.env.PATH,
+      pathArray = splitPath(pathEnv),
+      where = null;
+
+  // No relative/absolute paths provided?
+  if (cmd.search(/\//) === -1) {
+    // Search for command in PATH
+    pathArray.forEach(function(dir) {
+      if (where)
+        return; // already found it
+
+      var attempt = path.resolve(dir + '/' + cmd);
+      if (checkPath(attempt)) {
+        where = attempt;
+        return;
+      }
+
+      if (common.platform === 'win') {
+        var baseAttempt = attempt;
+        attempt = baseAttempt + '.exe';
+        if (checkPath(attempt)) {
+          where = attempt;
+          return;
+        }
+        attempt = baseAttempt + '.cmd';
+        if (checkPath(attempt)) {
+          where = attempt;
+          return;
+        }
+        attempt = baseAttempt + '.bat';
+        if (checkPath(attempt)) {
+          where = attempt;
+          return;
+        }
+      } // if 'win'
+    });
+  }
+
+  // Command not found anywhere?
+  if (!checkPath(cmd) && !where)
+    return null;
+
+  where = where || path.resolve(cmd);
+
+  return common.ShellString(where);
+}
+module.exports = _which;

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/package.json
----------------------------------------------------------------------
diff --git a/windows/package.json b/windows/package.json
index 7e71acd..abb83e8 100644
--- a/windows/package.json
+++ b/windows/package.json
@@ -12,6 +12,12 @@
     "cordova",
     "apache"
   ],
+  "dependencies": {
+    "q": "^0.9.0",
+    "nopt": "~3",
+    "node-uuid": "~1.4",
+    "shelljs": "~0.3"
+  },
   "author": "Apache Software Foundation",
   "license": "Apache Version 2.0"
 }

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/template/CordovaApp.Store80.jsproj
----------------------------------------------------------------------
diff --git a/windows/template/CordovaApp.Store80.jsproj b/windows/template/CordovaApp.Store80.jsproj
index df2593c..075d999 100644
--- a/windows/template/CordovaApp.Store80.jsproj
+++ b/windows/template/CordovaApp.Store80.jsproj
@@ -88,7 +88,7 @@
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\$(WMSJSProjectDirectory)\Microsoft.VisualStudio.$(WMSJSProject).targets" />
   <PropertyGroup>
     <PreBuildEvent>
-      Powershell -ExecutionPolicy RemoteSigned Unblock-File '$(ProjectDir)\cordova\lib\ApplyPlatformConfig.ps1'; Powershell -File '$(ProjectDir)\cordova\lib\ApplyPlatformConfig.ps1' '$(ProjectDir)\';
+      Powershell -ExecutionPolicy RemoteSigned Unblock-File '..\..\..\..\cordova\lib\ApplyPlatformConfig.ps1'; Powershell -File '..\..\..\..\cordova\lib\ApplyPlatformConfig.ps1' '..\..\..\..\';
     </PreBuildEvent>
   </PropertyGroup>
 </Project>

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/template/cordova/build
----------------------------------------------------------------------
diff --git a/windows/template/cordova/build b/windows/template/cordova/build
new file mode 100644
index 0000000..ad0c8cc
--- /dev/null
+++ b/windows/template/cordova/build
@@ -0,0 +1,34 @@
+#!/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 build = require('./lib/build'),
+    args  = process.argv;
+
+// Support basic help commands
+if(args[2] == '--help' || args[2] == '/?' || args[2] == '-h' ||
+                    args[2] == 'help' || args[2] == '-help' || args[2] == '/help') {
+    build.help();
+} else {
+    build.run(args).done(null, function(err) {
+        console.error(err);
+        process.exit(2);
+    });
+}

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/template/cordova/build.bat
----------------------------------------------------------------------
diff --git a/windows/template/cordova/build.bat b/windows/template/cordova/build.bat
index a4d2112..f367400 100644
--- a/windows/template/cordova/build.bat
+++ b/windows/template/cordova/build.bat
@@ -15,11 +15,11 @@
 :: specific language governing permissions and limitations
 :: under the License
 @ECHO OFF
-SET full_path=%~dp0
-IF EXIST "%full_path%lib\build.js" (
-    cscript "%full_path%lib\build.js" %* //nologo
+SET script_path="%~dp0build"
+IF EXIST %script_path% (
+        node %script_path% %*
 ) ELSE (
     ECHO.
-    ECHO ERROR: Could not find 'build.js' in cordova/lib, aborting...>&2
+    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-windows/blob/5ce7b168/windows/template/cordova/clean
----------------------------------------------------------------------
diff --git a/windows/template/cordova/clean b/windows/template/cordova/clean
new file mode 100644
index 0000000..ce10f23
--- /dev/null
+++ b/windows/template/cordova/clean
@@ -0,0 +1,32 @@
+#!/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 clean = require('./lib/clean');
+
+// Usage support for when args are given
+if(process.argv.length > 2) {
+    clean.help();
+} else {
+    clean.run().done(null, function(err) {
+        console.error('ERROR: ' + err);
+        process.exit(2);
+    });
+}

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/template/cordova/clean.bat
----------------------------------------------------------------------
diff --git a/windows/template/cordova/clean.bat b/windows/template/cordova/clean.bat
index 955ec6f..25f1790 100644
--- a/windows/template/cordova/clean.bat
+++ b/windows/template/cordova/clean.bat
@@ -15,11 +15,11 @@
 :: specific language governing permissions and limitations
 :: under the License
 @ECHO OFF
-SET full_path=%~dp0
-IF EXIST "%full_path%lib\clean.js" (
-    cscript "%full_path%lib\clean.js" %* //nologo
+SET script_path="%~dp0clean"
+IF EXIST %script_path% (
+        node %script_path% %*
 ) ELSE (
     ECHO.
-    ECHO ERROR: Could not find 'clean.js' in cordova/lib, aborting...>&2
+    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-windows/blob/5ce7b168/windows/template/cordova/lib/ApplyPlatformConfig.ps1
----------------------------------------------------------------------
diff --git a/windows/template/cordova/lib/ApplyPlatformConfig.ps1 b/windows/template/cordova/lib/ApplyPlatformConfig.ps1
index 310c15b..8fdb026 100644
--- a/windows/template/cordova/lib/ApplyPlatformConfig.ps1
+++ b/windows/template/cordova/lib/ApplyPlatformConfig.ps1
@@ -27,8 +27,8 @@ Write-Host "Applying Platform Config..."
 Function UpdateManifest ($manifestFile)
 {
   $configFile = "$platformRoot\config.xml"
-  [xml]$config = Get-Content $configFile
-  [xml]$manifest = Get-Content $manifestFile
+  [xml]$config = Get-Content $configFile -Encoding UTF8
+  [xml]$manifest = Get-Content $manifestFile -Encoding UTF8
 
   # Replace app start page with config.xml setting.
 

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/template/cordova/lib/build.js
----------------------------------------------------------------------
diff --git a/windows/template/cordova/lib/build.js b/windows/template/cordova/lib/build.js
index 77879a6..5b82342 100644
--- a/windows/template/cordova/lib/build.js
+++ b/windows/template/cordova/lib/build.js
@@ -17,250 +17,79 @@
        under the License.
 */
 
-
-var fso = WScript.CreateObject('Scripting.FileSystemObject');
-var wscript_shell = WScript.CreateObject("WScript.Shell");
-
-var args = WScript.Arguments;
-
-// build type. Possible values: "debug", "release"
-var buildType = null,
-// list of build architectures. list of strings
-buildArchs = null;
-
-// working dir
-var ROOT = WScript.ScriptFullName.split('\\cordova\\lib\\build.js').join('');
-
-// help/usage function
-function Usage() {
-    Log("");
-    Log("Usage: build [ --debug | --release ] [--archs=\"<list of architectures...>\"]");
-    Log("    --help    : Displays this dialog.");
-    Log("    --debug   : builds project in debug mode. (Default)");
-    Log("    --release : builds project in release mode.");
-    Log("    -r        : shortcut :: builds project in release mode.");
-    Log("    --archs   : Builds project binaries for specific chip architectures. `arm` + `x86` + `x64` are supported.");
-    Log("examples:");
-    Log("    build ");
-    Log("    build --debug");
-    Log("    build --release");
-    Log("    build --release --archs=\"arm x86\"");
-    Log("");
-}
-
-// logs messaged to stdout and stderr
-function Log(msg, error) {
-    if (error) {
-        WScript.StdErr.WriteLine(msg);
-    }
-    else {
-        WScript.StdOut.WriteLine(msg);
-    }
-}
-
-// executes a commmand in the shell
-function exec_verbose(command) {
-    //Log("Command: " + command);
-    var oShell=wscript_shell.Exec(command);
-    while (oShell.Status === 0) {
-        //Wait a little bit so we're not super looping
-        WScript.sleep(100);
-        //Print any stdout output from the script
-        while (!oShell.StdOut.AtEndOfStream) {
-            var line = oShell.StdOut.ReadLine();
-            Log(line);
-        }
-    }
-    //Check to make sure our scripts did not encounter an error
-    if (!oShell.StdErr.AtEndOfStream) {
-        var line = oShell.StdErr.ReadAll();
-        Log(line, true);
-        WScript.Quit(2);
-    }
-    return oShell.ExitCode;
-}
-
-// checks to see if a .jsproj file exists in the project root
-function is_cordova_project(path) {
-    if (fso.FolderExists(path)) {
-        var proj_folder = fso.GetFolder(path);
-        var proj_files = new Enumerator(proj_folder.Files);
-        for (;!proj_files.atEnd(); proj_files.moveNext()) {
-            if (fso.GetExtensionName(proj_files.item()) == 'shproj') {
-                return true;
-            }
-        }
-    }
-    return false;
-}
-
-// escapes a path so that it can be passed to shell command. 
-function escapePath(path) {
-    return '"' + path + '"';
-}
-
-// returns full path to msbuild tools required to build the project and tools version
-function getMSBuildTools() {
-    // use the latest version of the msbuild tools available on this machine
-    var toolsVersions = ['12.0', '4.0'];
-    for (var idx in toolsVersions) {
-        try {
-            return  {
-                version: toolsVersions[idx],
-                path: wscript_shell.RegRead('HKLM\\SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\' + toolsVersions[idx] + '\\MSBuildToolsPath')
-            };
-        } catch(err) {}
-    }
-    Log('MSBuild tools have not been found. Please install Microsoft Visual Studio 2013 or later', true);
-    WScript.Quit(2);
-}
-
-// builds the project and .xap in debug mode
-function build_appx(path, buildtype, buildarchs) {
-
-    if (!buildtype) {
-        Log("WARNING: [ --debug | --release ] not specified, defaulting to debug...");
-        buildtype = "debug";
+var Q     = require('Q'),
+    path  = require('path'),
+    nopt  = require('nopt'),
+    spawn = require('./spawn'),
+    utils = require('./utils');
+
+var ROOT = path.join(__dirname, '..', '..');
+
+// builds cordova-windows application with parameters provided.
+// See 'help' function for args list
+module.exports.run = function run (argv) {
+    // reject promise if project is not valid
+    if (!utils.isCordovaProject(ROOT)){
+        return Q.reject("Could not find project at " + ROOT);
     }
 
-    if (!buildarchs) {
-        Log("WARNING: target architecture not specified, defaulting to AnyCPU...");
-        buildarchs = ["Any CPU"];
+    // parse args
+    var args = nopt({"debug": Boolean, "release": Boolean, "archs": [String]}, {"-r": "--release"}, argv);
+   
+    // Validate args
+    if (args.debug && args.release) {
+        return Q.reject('Only one of "debug"/"release" options should be specified');
     }
+    
+    // get build options/defaults
+    var buildType = args.release ? "release" : "debug",
+        buildArchs = args.archs ? args.archs.split(' ') : ["anycpu"];
 
-    for (var i = 0; i < buildarchs.length; i++) {
-
-        var buildarch = buildarchs[i].toLowerCase();
+    // chain promises each for previous for each array member
+    return buildArchs.reduce(function(promise, arch) {
         // support for "any cpu" specified with or without space
-        buildarch = buildarch !== "anycpu" ? buildarch : "any cpu";
-
-        Log("Building Cordova Windows Project:");
-        Log("\tConfiguration : " + buildtype);
-        Log("\tPlatform      : " + buildarch);
-        Log("\tDirectory     : " + path);
-
-        try {
-            wscript_shell.CurrentDirectory = path;
-
-            // Get the latest build tools available on this machine
-            var msbuild = getMSBuildTools();
-            Log("\tMSBuildToolsPath: " + msbuild.path);
-
-            var solutionFilePath = path+'\\CordovaApp.sln'; // default sln file
-
+        var buildarch = arch !== "anycpu" ? arch : "any cpu";
+        return promise.then(function() {
+            return utils.getMSBuild();
+        }).then(function(msbuild) {
+            console.log("\nBuilding Cordova Windows Project:");
+            console.log("\tConfiguration : " + buildType);
+            console.log("\tPlatform      : " + buildarch);
+            console.log("\tDirectory     : " + ROOT);
+            console.log("\tMSBuildToolsPath: " + msbuild.path);
+            
             if (msbuild.version == '4.0') {
-                Log("\r\nWarning. Windows 8.1 and Windows Phone 8.1 target platforms are not supported on this development machine and will be skipped.");
-                Log("Please install OS Windows 8.1 and Visual Studio 2013 Update2 in order to build for Windows 8.1 and Windows Phone 8.1.\r\n");
-                solutionFilePath = path+'\\CordovaApp.vs2012.sln';
+                console.warn("\r\nWarning. Windows 8.1 and Windows Phone 8.1 target platforms are not supported on this development machine and will be skipped.");
+                console.warn("Please install OS Windows 8.1 and Visual Studio 2013 Update2 in order to build for Windows 8.1 and Windows Phone 8.1.\r\n");
             }
-
-            var buildCommand = escapePath(msbuild.path + 'msbuild') +
-                ' ' + escapePath(solutionFilePath) +
-                ' /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo' +
-                ' /p:Configuration=' + buildtype +
-                ' /p:Platform="' + buildarch + '"';
+            var solution = msbuild.version == '4.0' ?
+                path.join(ROOT, 'CordovaApp.vs2012.sln') :
+                path.join(ROOT, 'CordovaApp.sln');
+
+            var args = [solution,
+                '/clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal', '/nologo',
+                '/p:Configuration=' + buildType,
+                '/p:Platform=' + buildarch];
             
-            // hack to get rid of 'Access is denied.' error when running the shell w/ access to C:\path..
-            buildCommand = 'cmd /c "' + buildCommand + '"';
-            Log(buildCommand);
-            if (exec_verbose(buildCommand) !== 0) {
-                // msbuild failed
-                WScript.Quit(2);
-            }
-        } catch (err) {
-            Log("Build failed: " + err.message, true);
-        }
-    }
-
-    // TODO: there could be multiple AppPackages
-    // check if AppPackages created
-    if (fso.FolderExists(path + '\\AppPackages')) {
-        var out_folder = fso.GetFolder(path + '\\AppPackages');
-        var subFolders = new Enumerator(out_folder.SubFolders);
-        for(;!subFolders.atEnd();subFolders.moveNext())
-        {
-            var subFolder = subFolders.item();
-            var files = new Enumerator(subFolder.Files);
-            for(;!files.atEnd();files.moveNext())
-            {
-                if(fso.GetExtensionName(files.item()) == "ps1")
-                {
-                    // app was built, installation script exists
-                    return "\nSUCCESS";
-                }
-            }
-
-        }
-
-    }
-    Log("Error : AppPackages were not built");
-    WScript.Quit(2);
-
-}
-
-// parses script args and set global variables for build
-// throws error if unknown argument specified.
-function parseArgs () {
-
-    // return build type, specified by input string, or null, if not build type parameter
-    function getBuildType (arg) {
-        arg = arg.toLowerCase();
-        if (arg == "--debug" || arg == "-d") {
-            return "debug";
-        }
-        else if (arg == "--release" || arg == "-r") {
-            return "release";
-        }
-        return null;
-    }
+            return spawn(path.join(msbuild.path, 'msbuild'), args);
+        });
+    }, Q());
+};
 
-    // returns build architectures list, specified by input string
-    // or null if nothing specified, or not --archs parameter
-    function getBuildArchs (arg) {
-        arg = arg.toLowerCase();
-        var archs = /--archs=(.+)/.exec(arg);
-        if (archs) {
-            // if architectures list contains commas, suppose that is comma delimited
-            if (archs[1].indexOf(',') != -1){
-                return archs[1].split(',');
-            }
-            // else space delimited
-            return archs[1].split(/\s/);
-        }
-        return null;
-    }
-
-    for (var i = 0; i < args.Length; i++) {
-        if (getBuildType(args(i))) {
-            buildType = getBuildType(args(i));
-        } else if (getBuildArchs(args(i))) {
-            buildArchs = getBuildArchs(args(i));
-        } else {
-            // Skip unknown args. Build could be called from run/emulate commands,
-            // so there could be additional args (specific for run/emulate)
-
-            // Log("Error: \"" + args(i) + "\" is not recognized as a build option", true);
-            // Usage();
-            // WScript.Quit(2);
-        }
-    }
-}
-
-Log("");
-
-if (args.Count() > 0) {
-    // support help flags
-    if (args(0) == "--help" || args(0) == "/?" ||
-            args(0) == "help" || args(0) == "-help" || args(0) == "/help") {
-        Usage();
-        WScript.Quit(2);
-    }
-    else if (!fso.FolderExists(ROOT) || !is_cordova_project(ROOT)) {
-        Log("Error: could not find project at " + ROOT, true);
-        WScript.Quit(2);
-    }
-
-    parseArgs();
-}
-
-Log(build_appx(ROOT, buildType, buildArchs));
+// help/usage function
+module.exports.help = function help() {
+    console.log("");
+    console.log("Usage: build [ --debug | --release ] [--archs=\"<list of architectures...>\"]");
+    console.log("    --help    : Displays this dialog.");
+    console.log("    --debug   : builds project in debug mode. (Default)");
+    console.log("    --release : builds project in release mode.");
+    console.log("    -r        : shortcut :: builds project in release mode.");
+    console.log("    --archs   : Builds project binaries for specific chip architectures. `anycpu` + `arm` + `x86` + `x64` are supported.");
+    console.log("examples:");
+    console.log("    build ");
+    console.log("    build --debug");
+    console.log("    build --release");
+    console.log("    build --release --archs=\"arm x86\"");
+    console.log("");
+    process.exit(0);
+};

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/template/cordova/lib/clean.js
----------------------------------------------------------------------
diff --git a/windows/template/cordova/lib/clean.js b/windows/template/cordova/lib/clean.js
index 9b77ccc..672b675 100644
--- a/windows/template/cordova/lib/clean.js
+++ b/windows/template/cordova/lib/clean.js
@@ -17,75 +17,14 @@
        under the License.
 */
 
-
-var fso = WScript.CreateObject('Scripting.FileSystemObject');
-var wscript_shell = WScript.CreateObject("WScript.Shell");
-var args = WScript.Arguments;
-// working dir
-var ROOT = WScript.ScriptFullName.split('\\cordova\\lib\\clean.js').join('');
-
-
-// help function
-function Usage() {
-    Log("");
-    Log("Usage: clean");
-    Log("   - deletes all generated files in project");
-    Log("");
-}
-
-//  logs to stdout or stderr
-function Log(msg, error) {
-    if (error) {
-        WScript.StdErr.WriteLine(msg);
-    }
-    else {
-        WScript.StdOut.WriteLine(msg);
-    }
-}
-
-// cleans any generated files in the cordova project
-function clean_project(path) {
-    delete_if_exists(path + "\\Windows\\bld");
-    delete_if_exists(path + "\\WindowsPhone\\bld");
-    delete_if_exists(path + "\\Windows\\bin");
-    delete_if_exists(path + "\\WindowsPhone\\bin");
-}
-
-
-// deletes the path element if it exists
-function delete_if_exists(path) {
-    if (fso.FolderExists(path)) {
-        Log('Deleting folder: ' + path);
-        fso.DeleteFolder(path);
-    }
-    else if (fso.FileExists(path)) {
-        Log('Deleting file: ' + path);
-        fso.DeleteFile(path);
-    }
-}
-
-
-if (args.Count() > 0) {
-    // support help flags
-    if (args(0) == "--help" || args(0) == "/?" ||
-            args(0) == "help" || args(0) == "-help" || args(0) == "/help") {
-        Usage();
-        WScript.Quit(2);
-    }
-    else if (args.Count() > 1) {
-        Log("Error: Too many arguments.", true);
-        Usage();
-        WScript.Quit(2);
-    }
-}
-else {
-   if (fso.FolderExists(ROOT)) {
-        Log("Cleaning cordova project...");
-        clean_project(ROOT);
-    }
-    else {
-        Log("Error: Project directory not found,", true);
-        Usage();
-        WScript.Quit(2);
-    }
-}
\ No newline at end of file
+var Q     = require('q'),
+    path  = require('path'),
+    shell = require('shelljs');
+
+// cleans the project, removes AppPackages and build folders.
+module.exports.run = function (platformpath) {
+    ['AppPackages', 'build'].forEach(function(dir) {
+        shell.rm('-rf', path.join(platformpath, dir));
+    });
+    return Q.resolve();
+};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/template/cordova/lib/deploy.js
----------------------------------------------------------------------
diff --git a/windows/template/cordova/lib/deploy.js b/windows/template/cordova/lib/deploy.js
deleted file mode 100644
index 0bc9f1b..0000000
--- a/windows/template/cordova/lib/deploy.js
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
-       Licensed to the Apache Software Foundation (ASF) under one
-       or more contributor license agreements.  See the NOTICE file
-       distributed with this work for additional information
-       regarding copyright ownership.  The ASF licenses this file
-       to you under the Apache License, Version 2.0 (the
-       "License"); you may not use this file except in compliance
-       with the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing,
-       software distributed under the License is distributed on an
-       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-       KIND, either express or implied.  See the License for the
-       specific language governing permissions and limitations
-       under the License.
-*/
-
-var fso = WScript.CreateObject('Scripting.FileSystemObject');
-var wscript_shell = WScript.CreateObject("WScript.Shell");
-
-var args = WScript.Arguments;
-// working dir
-var ROOT = WScript.ScriptFullName.split('\\cordova\\lib\\deploy.js').join('');
-// path to WindowsStoreAppUtils.ps1; provides helper functions to install/unistall/start Windows Store app
-var WINDOWS_STORE_UTILS = fso.GetAbsolutePathName(ROOT+'\\cordova\\lib\\WindowsStoreAppUtils.ps1');
-// path to AppDeploy util from Windows Phone 8.1 SDK
-var APP_DEPLOY_UTILS = (wscript_shell.Environment("Process")("ProgramFiles(x86)") ||
-        wscript_shell.Environment("Process")("ProgramFiles")) +
-        '\\Microsoft SDKs\\Windows Phone\\v8.1\\Tools\\AppDeploy\\AppDeployCmd.exe';
-// Check if AppDeployCmd is exists
-if (!fso.FileExists(APP_DEPLOY_UTILS)) {
-    Log("WARNING: AppDeploy tool (AppDeployCmd.exe) didn't found. Assume that it's in %PATH%");
-    APP_DEPLOY_UTILS = "AppDeployCmd";
-}
-
-// build type. Possible values: "debug", "release"
-// required to determine which package should be deployed
-var buildType = null,
-    // nobuild flag
-    noBuild = false,
-    // list of build architectures. list of strings
-    // required to determine which package should be deployed
-    buildArchs = null,
-    // build target. Possible values: "device", "emulator", "<target_name>"
-    buildTarget = null,
-    // project type. Possible values are "phone", "store" == "store81", "store80"
-    projectType = null;
-
-
-var PACKAGE_NAME = '$namespace$';
-
-// help function
-function Usage() {
-    Log("");
-    Log("Usage: run [ --device | --emulator | --target=<id> ] [ --debug | --release | --nobuild ]");
-    Log("");
-    Log("           [ --x86 | --x64 | --arm ] [--phone | --store | --store81 | --store80]");
-    Log("    --device      : Deploys and runs the project on the connected device.");
-    Log("    --emulator    : Deploys and runs the project on an emulator.");
-    Log("    --target=<id> : Deploys and runs the project on the specified target.");
-    Log("    --debug       : Builds project in debug mode.");
-    Log("    --release     : Builds project in release mode.");
-    Log("    --nobuild     : Uses pre-built xap, or errors if project is not built.");
-    Log("    --x86, --x64, --arm");
-    Log("                  : Specifies chip architecture.");
-    Log("    --phone, --store, --store81, --store80");
-    Log("                  : Specifies, what type of project to deploy");
-    Log("");
-    Log("Examples:");
-    Log("    run");
-    Log("    run --emulator");
-    Log("    run --device");
-    Log("    run --target=7988B8C3-3ADE-488d-BA3E-D052AC9DC710");
-    Log("    run --device --release");
-    Log("    run --emulator --debug");
-    Log("");
-}
-
-// log to stdout or stderr
-function Log(msg, error) {
-    if (error) {
-        WScript.StdErr.WriteLine(msg);
-    }
-    else {
-        WScript.StdOut.WriteLine(msg);
-    }
-}
-
-// executes a commmand in the shell
-function exec(command) {
-    var oShell=wscript_shell.Exec(command);
-    while (oShell.Status === 0) {
-        WScript.sleep(100);
-    }
-}
-
-// executes a commmand in the shell
-function exec_verbose(command) {
-    //Log("Command: " + command);
-    var oShell=wscript_shell.Exec(command),
-        line;
-    while (oShell.Status === 0) {
-        //Wait a little bit so we're not super looping
-        WScript.sleep(100);
-        //Print any stdout output from the script
-        while (!oShell.StdOut.AtEndOfStream) {
-            line = oShell.StdOut.ReadLine();
-            Log(line);
-        }
-    }
-    //Check to make sure our scripts did not encounter an error
-    if (!oShell.StdErr.AtEndOfStream) {
-        line = oShell.StdErr.ReadAll();
-        Log(line, true);
-        WScript.Quit(2);
-    }
-}
-
-// returns folder that contains package with chip architecture,
-// build and project types specified by script parameters
-function getPackage (path, projecttype, buildtype, buildarchs) {
-    wscript_shell.CurrentDirectory = path;
-
-    // check if AppPackages created
-    if (fso.FolderExists(path + '\\AppPackages')) {
-        var out_folder = fso.GetFolder(path + '\\AppPackages');
-
-        // set default values
-        // because "store81" and "store" are synonims, replace "store81" with "store" due to appx naming.
-        projecttype = projecttype && projecttype != "store81" ? projecttype : "store";
-        buildtype = buildtype ? buildtype : "debug";
-        buildarchs = buildarchs ? buildarchs : ["anycpu"];
-        // if "Any CPU" is arch to deploy, remove space because folder name will contain
-        // smth like CordovaApp_0.0.1.0_AnyCPU_Test
-        var buildarch = buildarchs[0].toLowerCase() == "any cpu" ? "anycpu" : buildarchs[0].toLowerCase();
-
-        // Iterating over AppPackages subfolders with built packages
-        var subFolders = new Enumerator(out_folder.SubFolders);
-        for(;!subFolders.atEnd();subFolders.moveNext())
-        {
-            var subFolder = subFolders.item();
-            var appx_props = /^.*\.(Phone|Store|Store80)_((?:\d\.)*\d)_(AnyCPU|x64|x86|ARM)(?:_(Debug))?_Test$/.exec(subFolder.Name);
-            // This RE matches with package folder name like:
-            // CordovaApp.Phone_0.0.1.0_AnyCPU_Debug_Test
-            // Group:     ( 1 ) (  2  ) (  3 ) ( 4 )
-            if (appx_props){
-                var appx_projecttype = appx_props[1].toLowerCase();
-                var appx_buildarch = appx_props[3].toLowerCase();
-                var appx_buildtype = appx_props[4] ? appx_props[4].toLowerCase() : "release";
-                // compare chip architecture and build type of package found with
-                // chip architecture and build type specified in script arguments
-                if (appx_buildarch == buildarch && appx_buildtype == buildtype && appx_projecttype == projecttype) {
-                    // Appropriate package found
-                    Log('Appropriate package found at ' + subFolder.Path);
-                    return subFolder.Path;
-                }
-            }
-        }
-    }
-    Log('Error : AppPackages were not built or appropriate package was not found', true);
-    WScript.Quit(2);
-}
-
-// launches project on local machine
-function localMachine(path, projecttype, buildtype, buildarchs) {
-    Log('Deploying to local machine ...');
-    makeAppStoreUtils(path);
-    uninstallApp(path);
-    installApp(path, projecttype, buildtype, buildarchs);
-
-    var command = "powershell -ExecutionPolicy RemoteSigned \". " + WINDOWS_STORE_UTILS + "; Start-Locally '" + PACKAGE_NAME + "'\"";
-    Log(command);
-    exec_verbose(command);
-}
-
-function readAppIdWindowsPhone() {
-    var manifestPath = ROOT + '\\package.phone.appxmanifest';
-
-    if (!fso.FileExists(manifestPath)) {
-        Log('Error: ' + manifestPath + ' does not exist', true);
-        WScript.Quit(2);
-    }
-    var manifestFile = fso.OpenTextFile(manifestPath, 1);
-    var manifest = manifestFile.ReadAll();
-    manifestFile.Close();
-    return /PhoneProductId="(.*?)"/i.exec(manifest)[1];
-}
-
-function deployWindowsPhone(appxPath, target) {
-    // /installlaunch option sometimes fails with 'Error: The parameter is incorrect.'
-    // so we use separate steps to /install and then /launch
-    // install
-    var cmd = '"' + APP_DEPLOY_UTILS + '" /install "' + appxPath + '" /targetdevice:' + target;
-    Log(cmd);
-    exec_verbose(cmd);
-    // launch
-    cmd = '"' + APP_DEPLOY_UTILS + '" /launch "' + readAppIdWindowsPhone() + '" /targetdevice:' + target;
-    Log(cmd);
-    exec_verbose(cmd);
-}
-
-// launches project on device
-function device(path, projecttype, buildtype, buildarchs) {
-    if (projecttype != "phone") {
-        // on windows8 platform we treat this command as running application on local machine
-        localMachine(path, projecttype, buildtype, buildarchs);
-    } else {
-        Log('Deploying to device ...');
-        var appxFolder = getPackage(path, projecttype, buildtype, buildarchs);
-        var appxPath = appxFolder + '\\' + fso.GetFolder(appxFolder).Name.split('_Test').join('') + '.appx';
-        deployWindowsPhone(appxPath, 'de');
-    }
-}
-
-// launches project on emulator
-function emulator(path, projecttype, buildtype, buildarchs) {
-    if (projecttype != "phone") {
-        // TODO: currently we can run application on local machine only
-        localMachine(path, projecttype, buildtype, buildarchs);
-    } else {
-        Log('Deploying to emulator ...');
-        var appxFolder = getPackage(path, projecttype, buildtype, buildarchs);
-        var appxPath = appxFolder + '\\' + fso.GetFolder(appxFolder).Name.split('_Test').join('') + '.appx';
-        deployWindowsPhone(appxPath, 'xd');
-    }
-}
-
-// builds and launches the project on the specified target
-function target(path, projecttype, buildtype, buildarchs, buildtarget) {
-    if (projecttype != "phone"){
-        Log('ERROR: not supported yet', true);
-        Log('DEPLOY FAILED.', true);
-        WScript.Quit(2);
-    } else {
-        // We're deploying package on phone device/emulator
-        // Let's find target specified by script arguments
-        var cmd = APP_DEPLOY_UTILS + ' /enumeratedevices';
-        var out = wscript_shell.Exec(cmd);
-        while(out.Status === 0) {
-            WScript.Sleep(100);
-        }
-        if (!out.StdErr.AtEndOfStream) {
-            var error = out.StdErr.ReadAll();
-            Log("ERROR: Error calling AppDeploy : ", true);
-            Log(error, true);
-            WScript.Quit(2);
-        }
-        else {
-            if (!out.StdOut.AtEndOfStream) {
-                // get output from AppDeployCmd
-                var lines = out.StdOut.ReadAll().split('\r\n');
-                // regular expression, that matches with AppDeploy /enumeratedevices output
-                // e.g. ' 1              Emulator 8.1 WVGA 4 inch 512MB'
-                var deviceRe = /^\s?(\d)+\s+(.*)$/;
-                // iterate over lines
-                for (var line in lines){
-                    var deviceMatch = lines[line].match(deviceRe);
-                    // check that line contains device id and name
-                    // and match with 'target' parameter of script
-                    if (deviceMatch && deviceMatch[1] == buildtarget) {
-                        // start deploy to target specified
-                        var appxFolder = getPackage(path, projecttype, buildtype, buildarchs);
-                        var appxPath = appxFolder + '\\' + fso.GetFolder(appxFolder).Name.split('_Test').join('') + '.appx';
-                        Log('Deploying to target with id: ' + buildtarget);
-                        deployWindowsPhone(appxPath, deviceMatch[1]);
-                        return;
-                    }
-                }
-                Log('Error : target ' + buildtarget + ' was not found.', true);
-                Log('DEPLOY FAILED.', true);
-                WScript.Quit(2);
-            }
-            else {
-                Log('Error : CordovaDeploy Failed to find any devices', true);
-                Log('DEPLOY FAILED.', true);
-                WScript.Quit(2);
-            }
-        }
-    }
-}
-
-function makeAppStoreUtils(path) {
-    if (fso.FileExists(WINDOWS_STORE_UTILS)) {
-        Log("Removing execution restrictions from AppStoreUtils...");
-        var command = "powershell \"Unblock-File \'" + WINDOWS_STORE_UTILS + "\'\"";
-        exec_verbose(command);
-        return;
-    }
-}
-
-// uninstalls previous application instance (if exists)
-function uninstallApp(path) {
-    Log("Attempt to uninstall previous application version...");
-    Log("\tDirectory : " + path);
-
-    wscript_shell.CurrentDirectory = path;
-    var command = "powershell -ExecutionPolicy RemoteSigned \". " + WINDOWS_STORE_UTILS + "; Uninstall-App " + PACKAGE_NAME;
-    Log(command);
-    exec_verbose(command);
-}
-
-// executes store application installation script (Add-AppDevPackage.ps1)
-function installApp(path, projecttype, buildtype, buildarchs) {
-
-    Log("Attempt to install application...");
-    Log("\tDirectory : " + path);
-
-    var command = "powershell -ExecutionPolicy RemoteSigned \". " + WINDOWS_STORE_UTILS + "; Install-App " + "'" + getPackage(path, projecttype, buildtype, buildarchs) + "\\Add-AppDevPackage.ps1" + "'\"";
-    Log(command);
-    exec_verbose(command);
-    return;
-}
-
-// builds project with arguments specified
-// all arguments passes directly into build script without changes
-function build(path, buildtype, buildarchs) {
-    // if --nobuild flag is specified, no action required here
-    if (noBuild) return;
-
-    var cmd = '%comspec% /c ""' + path + '\\cordova\\build"';
-    if (buildtype){
-        cmd += " --" + buildtype;
-    }
-    if (buildarchs){
-        cmd += ' --archs="' + buildarchs.join(",") + '"';
-    }
-    cmd += '"';
-    exec_verbose(cmd);
-}
-
-function run(path, projecttype, buildtype, buildarchs, buildtarget) {
-    build(path, buildtype, buildarchs);
-    switch (buildtarget){
-        case "device":
-            device(path, projecttype, buildtype, buildarchs);
-            break;
-        case "emulator":
-            emulator(path, projecttype, buildtype, buildarchs);
-            break;
-        case null:
-            Log("WARNING: [ --target=<ID> | --emulator | --device ] not specified, defaulting to --emulator");
-            emulator(path, projecttype, buildtype, buildarchs);
-            break;
-        default:
-            // if buildTarget is neither "device", "emulator" or null
-            // then it is a name of target
-            target(path, projecttype, buildtype, buildarchs, buildtarget);
-            break;
-    }
-}
-
-// parses script args and set global variables for build/deploy
-// throws error if unknown argument specified.
-function parseArgs () {
-
-    // return build type, specified by input string, or null, if not build type parameter
-    function getBuildType (arg) {
-        arg = arg.toLowerCase();
-        if (arg == "--debug" || arg == "-d") {
-            return "debug";
-        }
-        else if (arg == "--release" || arg == "-r") {
-            return "release";
-        }
-        return null;
-    }
-
-    // returns build architectures list, specified by input string
-    // or null if nothing specified, or not --archs parameter
-    function getBuildArchs (arg) {
-        arg = arg.toLowerCase();
-        var archs = /--archs=(.+)/.exec(arg);
-        if (archs) {
-            // if architectures list contains commas, suppose that is comma delimited
-            if (archs[1].indexOf(',') != -1){
-                return archs[1].split(',');
-            }
-            // else space delimited
-            return archs[1].split(/\s/);
-        }
-        return null;
-    }
-
-    // returns deploy target, specified by input string or null, if not deploy target parameter
-    function getBuildTarget (arg) {
-        arg = arg.toLowerCase();
-        if (arg == "--device"){
-            return "device";
-        }
-        else if (arg == "--emulator"){
-            return "emulator";
-        }
-        else {
-            var target = /--target=(.*)/.exec(arg);
-            if (target){
-                return target[1];
-            }
-        }
-        return null;
-    }
-
-    // returns project type, specified by input string or null, if not project type parameter
-    function getProjectType (arg) {
-        arg = arg.toLowerCase();
-        if (arg == "--phone"){
-            return "phone";
-        }
-        else if (arg == "--store80"){
-            return "store80";
-        }
-        else if (arg == "--store81" || arg == "--store"){
-            return "store";
-        }
-        return null;
-    }
-
-    // returns true if nobuild option is specified else false
-    function getNoBuildOption (arg) {
-        if (arg.toLowerCase() == "--nobuild") {
-            return true;
-        }
-        return false;
-    }
-
-    for (var i = 0; i < args.Length; i++) {
-        if (getBuildType(args(i))) {
-            buildType = getBuildType(args(i));
-        } else if (getBuildArchs(args(i))) {
-            buildArchs = getBuildArchs(args(i));
-        } else if (getBuildTarget(args(i))){
-            buildTarget = getBuildTarget(args(i));
-        } else if (getProjectType(args(i))){
-            projectType = getProjectType(args(i));
-        } else if (getNoBuildOption(args(i))) {
-            noBuild = getNoBuildOption(args(i));
-        } else {
-            Log("Error: \"" + args(i) + "\" is not recognized as a build/deploy option", true);
-            Usage();
-            WScript.Quit(2);
-        }
-    }
-}
-
-if (args.Count() > 0) {
-    // support help flags
-    if (args(0) == "--help" || args(0) == "/?" ||
-            args(0) == "help" || args(0) == "-help" || args(0) == "/help") {
-        Usage();
-        WScript.Quit(2);
-    }
-    else if (!fso.FolderExists(ROOT)) {
-        Log('Error: Project directory not found,', true);
-        Usage();
-        WScript.Quit(2);
-    }
-    parseArgs();
-}
-
-run(ROOT, projectType, buildType, buildArchs, buildTarget);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/template/cordova/lib/exec.js
----------------------------------------------------------------------
diff --git a/windows/template/cordova/lib/exec.js b/windows/template/cordova/lib/exec.js
new file mode 100644
index 0000000..d71eda7
--- /dev/null
+++ b/windows/template/cordova/lib/exec.js
@@ -0,0 +1,38 @@
+/*
+       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 child_process = require('child_process'),
+    Q       = require('q');
+
+// Takes a command and optional current working directory.
+// Returns a promise that either resolves with the stdout, or
+// rejects with an error message and the stderr.
+module.exports = function(cmd, opt_cwd) {
+    var d = Q.defer();
+    try {
+        child_process.exec(cmd, {cwd: opt_cwd, maxBuffer: 1024000}, function(err, stdout, stderr) {
+            if (err) d.reject('Error executing "' + cmd + '": ' + stderr);
+            else d.resolve(stdout);
+        });
+    } catch(e) {
+        console.error('error caught: ' + e);
+        d.reject(e);
+    }
+    return d.promise;
+};

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/template/cordova/lib/list-devices.bat
----------------------------------------------------------------------
diff --git a/windows/template/cordova/lib/list-devices.bat b/windows/template/cordova/lib/list-devices.bat
index df794b2..016fcfc 100644
--- a/windows/template/cordova/lib/list-devices.bat
+++ b/windows/template/cordova/lib/list-devices.bat
@@ -15,5 +15,11 @@
 :: specific language governing permissions and limitations
 :: under the License
 @ECHO OFF
-ECHO Error! Windows 8 Cordova CLI tools do not support multiple devices currently.
-EXIT /B 1
\ No newline at end of file
+SET script_path="%~dp0package.js"
+IF EXIST %script_path% (
+        node -e "require('./%script_path%').listDevices().done(function(devices){console.log(devices)})"
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'package' script in 'cordova/lib' folder, aborting...>&2
+    EXIT /B 1
+)

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/template/cordova/lib/log.js
----------------------------------------------------------------------
diff --git a/windows/template/cordova/lib/log.js b/windows/template/cordova/lib/log.js
deleted file mode 100644
index 0b4ea7d..0000000
--- a/windows/template/cordova/lib/log.js
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-       Licensed to the Apache Software Foundation (ASF) under one
-       or more contributor license agreements.  See the NOTICE file
-       distributed with this work for additional information
-       regarding copyright ownership.  The ASF licenses this file
-       to you under the Apache License, Version 2.0 (the
-       "License"); you may not use this file except in compliance
-       with the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing,
-       software distributed under the License is distributed on an
-       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-       KIND, either express or implied.  See the License for the
-       specific language governing permissions and limitations
-       under the License.
-*/
-
-
-var fso = WScript.CreateObject('Scripting.FileSystemObject');
-var wscript_shell = WScript.CreateObject("WScript.Shell");
-var args = WScript.Arguments;
-// working dir
-var ROOT = WScript.ScriptFullName.split('\\cordova\\lib\\log.js').join('');
-
-
-// help function
-function Usage() {
-    Log("");
-    Log("Usage: log");
-    Log("examples:");
-    Log("    log");
-    Log("         - logs output from running application  *NOT IMPLIMENTED*");
-    Log("");
-}
-
-//  logs to stdout or stderr
-function Log(msg, error) {
-    if (error) {
-        WScript.StdErr.WriteLine(msg);
-    }
-    else {
-        WScript.StdOut.WriteLine(msg);
-    }
-}
-
-// log output from running projects *NOT IMPLEMENTED*
-function log_output(path) {
-    Log("ERROR: Logging is not supported on Windows Phone", true);
-    WScript.Quit(1);
-}
-
-
-if (args.Count() > 0) {
-    // support help flags
-    if (args(0) == "--help" || args(0) == "/?" ||
-            args(0) == "help" || args(0) == "-help" || args(0) == "/help") {
-        Usage();
-        WScript.Quit(2);
-    }
-    else {
-        Log("Error: \"" + args(0) + "\" is not recognized as a log option.", true);
-        Usage();
-        WScript.Quit(2);
-    }
-}
-else {
-   if (fso.FolderExists(ROOT)) {
-        log_output(ROOT);
-    }
-    else {
-        Log("Error: Project directory not found,", true);
-        Usage();
-        WScript.Quit(2);
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/template/cordova/lib/package.js
----------------------------------------------------------------------
diff --git a/windows/template/cordova/lib/package.js b/windows/template/cordova/lib/package.js
new file mode 100644
index 0000000..76175f1
--- /dev/null
+++ b/windows/template/cordova/lib/package.js
@@ -0,0 +1,183 @@
+/*
+       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'),
+    fs    = require('fs'),
+    path  = require('path'),
+    exec  = require('./exec'),
+    spawn = require('./spawn'),
+    utils = require('./utils');
+
+// returns folder that contains package with chip architecture,
+// build and project types specified by script parameters
+module.exports.getPackage = function (projectType, buildtype, buildArch) {
+    var appPackages = path.resolve(path.join(__dirname, '..', '..', 'AppPackages'));
+    // reject promise if apppackages folder doesn't exists
+    if (!fs.existsSync(appPackages)) {
+        return Q.reject('AppPackages doesn\'t exists');
+    }
+    // find out and resolve paths for all folders inside AppPackages
+    var pkgDirs = fs.readdirSync(appPackages).map(function(relative) {
+        // resolve path to folder
+        return path.join(appPackages, relative);
+    }).filter(function(pkgDir) {
+        // check that it is a directory
+        return fs.statSync(pkgDir).isDirectory();
+    });
+
+    // Retrieve package infos for all packages found
+    // that corresponds to package properties provided
+    return Q.all(pkgDirs.map(function (pkgDir) {
+        // get info about package
+        return module.exports.getInfo(pkgDir).then(function(pkgInfo) {
+            if (pkgInfo && pkgInfo.type == projectType &&
+                pkgInfo.arch == buildArch && pkgInfo.buildtype == buildtype) {
+                // if package's properties are corresponds to properties provided
+                // resolve the promise with this package's info
+                return Q.resolve(pkgInfo);
+            }
+            // else resove with no info
+            return Q.resolve();
+        });
+    })).then(function (packages) {
+        for (var idx in packages) {
+            // iterate through infos found and resolve with first
+            if (packages[idx]) {
+                return Q.resolve(packages[idx]);
+            }
+        }
+        // else reject because seems that no corresponding packages found
+        return Q.reject('Package with specified parameters not found in AppPackages folder');
+    });
+};
+
+// returns package info object or null if it is not valid package
+module.exports.getInfo = function (packagePath) {
+    if (!fs.statSync(packagePath).isDirectory()){
+        return Q.reject('Provided path is not a directory');
+    }
+    // This RE matches with package folder name like:
+    // CordovaApp.Phone_0.0.1.0_AnyCPU_Debug_Test
+    // Group:     ( 1 ) (  2  ) (  3 ) ( 4 )
+    var props = /.*\.(Phone|Store|Store80)_((?:\d\.)*\d)_(AnyCPU|x64|x86|ARM)(?:_(Debug))?_Test$/i.exec(path.basename(packagePath));
+    if (props){
+        // return package info object inside of promise
+        return Q.resolve({path: packagePath,
+            type      : props[1].toLowerCase(),
+            arch      : props[3].toLowerCase(),
+            buildtype : props[4] ? props[4].toLowerCase() : "release",
+            file      : props[1].toLowerCase() != "phone" ?
+                path.join(packagePath, 'Add-AppDevPackage.ps1') :
+                path.join(packagePath, path.basename(packagePath).replace(/_test$/i, '') + '.appx')
+        });
+    }
+    return Q.reject('Can\'t fetch info for package at ' + packagePath);
+};
+
+// return package app ID fetched from appxmanifest
+// return rejected promise if appxmanifest not valid
+module.exports.getAppId = function (platformPath) {
+    var manifest = path.join(platformPath, 'package.phone.appxmanifest');
+    try {
+        return Q.resolve(/PhoneProductId="(.*?)"/gi.exec(fs.readFileSync(manifest, 'utf8'))[1]);
+    } catch (e) {
+        return Q.reject('Can\'t read appId from phone manifest' + e);
+    }
+};
+
+// return package name fetched from appxmanifest
+// return rejected promise if appxmanifest not valid
+module.exports.getPackageName = function (platformPath) {
+    var manifest = path.join(platformPath, 'package.store.appxmanifest');
+    try {
+        return Q.resolve(/Application Id="(.*?)"/gi.exec(fs.readFileSync(manifest, 'utf8'))[1]);
+    } catch (e) {
+        return Q.reject('Can\'t read package name from manifest ' + e);
+    }
+};
+
+// returns one of available devices which name match with parovided string
+// return rejected promise if device with name specified not found
+module.exports.findDevice = function (target) {
+    return module.exports.listDevices().then(function(deviceList) {
+        for (var idx in deviceList){
+            if (deviceList[idx].indexOf(target) > -1) {
+                return Q.resolve(idx);
+            }
+        }
+        return Q.reject('Specified device not found');
+    });
+};
+
+// returns array of available devices names
+module.exports.listDevices = function () {
+    return utils.getAppDeployUtils().then(function(appDeployUtils) {
+        return exec('"' + appDeployUtils + '" /enumeratedevices').then(function(output) {
+            return Q.resolve(output.split('\n').map(function(line) {
+                var match = /\s*(\d)+\s+(.*)/.exec(line);
+                return match && match[2];
+            }).filter(function (line) {
+                return line;
+            }));
+        });
+    });
+};
+
+// deploys specified phone package to device/emulator
+module.exports.deployToPhone = function (appxPath, deployTarget) {
+    var getTarget = deployTarget == "device" ? Q("de") :
+        deployTarget == "emulator" ? Q("xd") : module.exports.findDevice(deployTarget);
+
+    // /installlaunch option sometimes fails with 'Error: The parameter is incorrect.'
+    // so we use separate steps to /install and then /launch
+    return getTarget.then(function(target) {
+        return utils.getAppDeployUtils().then(function(appDeployUtils) {
+            console.log('Installing application');
+            return spawn(appDeployUtils, ['/install', appxPath, '/targetdevice:' + target]).then(function() {
+                // TODO: resolve AppId without specifying project root;
+                return module.exports.getAppId(path.join(__dirname, '..', '..'));
+            }).then(function(appId) {
+                console.log('Running application');
+                return spawn(appDeployUtils, ['/launch', appId, '/targetdevice:' + target]);
+            });
+        });
+    });
+};
+
+// deploys specified package to desktop
+module.exports.deployToDesktop = function (appxScript, deployTarget) {
+    if (deployTarget != "device" && deployTarget != "emulator") {
+        return Q.reject("Deploying desktop apps to specific target not supported");
+    }
+
+    return utils.getAppStoreUtils().then(function(appStoreUtils) {
+        return module.exports.getPackageName(path.join(__dirname, '..', '..')).then(function(pkgname) {
+            // uninstalls previous application instance (if exists)
+            console.log("Attempt to uninstall previous application version...");
+            return spawn('powershell', ['-ExecutionPolicy', 'RemoteSigned', 'Import-Module "' + appStoreUtils + '"; Uninstall-App ' + pkgname])
+            .then(function() {
+                console.log("Attempt to install application...");
+                return spawn('powershell', ['-ExecutionPolicy', 'RemoteSigned', 'Import-Module "' + appStoreUtils + '"; Install-App', utils.quote(appxScript)]);
+            }).then(function() {
+                console.log("Starting application...");
+                return spawn('powershell', ['-ExecutionPolicy', 'RemoteSigned', 'Import-Module "' + appStoreUtils + '"; Start-Locally', pkgname]);
+            });
+        });
+    });
+};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/template/cordova/lib/run.js
----------------------------------------------------------------------
diff --git a/windows/template/cordova/lib/run.js b/windows/template/cordova/lib/run.js
new file mode 100644
index 0000000..de220bd
--- /dev/null
+++ b/windows/template/cordova/lib/run.js
@@ -0,0 +1,93 @@
+/*
+       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'),
+    nopt  = require('nopt'),
+    path  = require('path'),
+    build = require('./build'),
+    utils = require('./utils'),
+    packages = require('./package');
+
+var ROOT = path.join(__dirname, '..', '..');
+
+module.exports.run = function (argv) {
+    if (!utils.isCordovaProject(ROOT)){
+        return Q.reject("Could not find project at " + ROOT);
+    }
+
+    // parse args
+    var args  = nopt({"debug": Boolean, "release": Boolean, "nobuild": Boolean,
+        "device": Boolean, "emulator": Boolean, "target": String, "archs": String,
+        "phone": Boolean, "store": Boolean, "store80": Boolean
+    }, {"store81": "--store", "r" : "--release"}, argv);
+
+    // Validate args
+    if (args.debug && args.release) {
+        return Q.reject('Only one of "debug"/"release" options should be specified');
+    }
+    if ((args.device && args.emulator) || ((args.device || args.emulator) && args.target)) {
+        return Q.reject('Only one of "device"/"emulator"/"target" options should be specified');
+    }
+    if ((args.phone && args.store) || ((args.phone || args.store) && args.store80)) {
+        return Q.reject('Only one of "phone"/"store"/"store80" options should be specified');
+    }
+
+    // Get build/deploy options
+    var buildType    = args.release ? "release" : "debug",
+        buildArchs   = args.archs ? args.archs.split(' ') : ["anycpu"],
+        projectType  = args.phone ? "phone" : args.store80 ? "store80" : "store",
+        deployTarget = args.target ? args.target : args.device ? "device" : "emulator";
+
+    // if --nobuild isn't specified then build app first
+    var buildPackages = args.nobuild ? Q() : build.run(argv);
+
+    return buildPackages.then(function () {
+        return packages.getPackage(projectType, buildType, buildArchs[0]);
+    }).then(function(pkg) {
+        console.log('\nDeploying ' + pkg.type + ' package to ' + deployTarget);
+        return pkg.type == "phone" ?
+            packages.deployToPhone(pkg.file, deployTarget) :
+            packages.deployToDesktop(pkg.file, deployTarget);
+    });
+};
+
+module.exports.help = function () {
+    console.log("\nUsage: run [ --device | --emulator | --target=<id> ] [ --debug | --release | --nobuild ]");
+    console.log("           [ --x86 | --x64 | --arm ] [--phone | --store | --store81 | --store80]");
+    console.log("    --device      : Deploys and runs the project on the connected device.");
+    console.log("    --emulator    : Deploys and runs the project on an emulator.");
+    console.log("    --target=<id> : Deploys and runs the project on the specified target.");
+    console.log("    --debug       : Builds project in debug mode.");
+    console.log("    --release     : Builds project in release mode.");
+    console.log("    --nobuild     : Uses pre-built xap, or errors if project is not built.");
+    console.log("    --x86, --x64, --arm");
+    console.log("                  : Specifies chip architecture.");
+    console.log("    --phone, --store, --store81, --store80");
+    console.log("                  : Specifies, what type of project to deploy");
+    console.log("");
+    console.log("Examples:");
+    console.log("    run");
+    console.log("    run --emulator");
+    console.log("    run --device");
+    console.log("    run --target=7988B8C3-3ADE-488d-BA3E-D052AC9DC710");
+    console.log("    run --device --release");
+    console.log("    run --emulator --debug");
+    console.log("");
+    process.exit(0);
+};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/5ce7b168/windows/template/cordova/lib/spawn.js
----------------------------------------------------------------------
diff --git a/windows/template/cordova/lib/spawn.js b/windows/template/cordova/lib/spawn.js
new file mode 100644
index 0000000..0ccb0f5
--- /dev/null
+++ b/windows/template/cordova/lib/spawn.js
@@ -0,0 +1,40 @@
+/*
+       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'),
+    proc = require('child_process');
+
+// Takes a command and optional current working directory.
+module.exports = function(cmd, args, opt_cwd) {
+    var d = Q.defer();
+    try {
+        var child = proc.spawn(cmd, args, {cwd: opt_cwd, stdio: 'inherit'});
+        child.on('exit', function(code) {
+            if (code) {
+                d.reject('Error code ' + code + ' for command: ' + cmd + ' with args: ' + args);
+            } else {
+                d.resolve();
+            }
+        });
+    } catch(e) {
+        console.error('error caught: ' + e);
+        d.reject(e);
+    }
+    return d.promise;
+};


Mime
View raw message