You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by an...@apache.org on 2016/03/04 13:32:08 UTC
[04/14] cordova-browser git commit: CB-10755 Updated checked in
node_modules
http://git-wip-us.apache.org/repos/asf/cordova-browser/blob/012b9d3b/node_modules/shelljs/build/output.js
----------------------------------------------------------------------
diff --git a/node_modules/shelljs/build/output.js b/node_modules/shelljs/build/output.js
new file mode 100644
index 0000000..1b778b9
--- /dev/null
+++ b/node_modules/shelljs/build/output.js
@@ -0,0 +1,2411 @@
+var common = require('./common');
+var fs = require('fs');
+
+//@
+//@ ### cat(file [, file ...])
+//@ ### cat(file_array)
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ var str = cat('file*.txt');
+//@ var str = cat('file1', 'file2');
+//@ var str = cat(['file1', 'file2']); // same as above
+//@ ```
+//@
+//@ Returns a string containing the given file, or a concatenated string
+//@ containing the files if more than one file is given (a new line character is
+//@ introduced between each file). Wildcard `*` accepted.
+function _cat(options, files) {
+ var cat = '';
+
+ 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))
+ common.error('no such file or directory: ' + file);
+
+ cat += fs.readFileSync(file, 'utf8');
+ });
+
+ return common.ShellString(cat);
+}
+module.exports = _cat;
+
+var fs = require('fs');
+var common = require('./common');
+
+//@
+//@ ### cd([dir])
+//@ Changes to directory `dir` for the duration of the script. Changes to home
+//@ directory if no argument is supplied.
+function _cd(options, dir) {
+ if (!dir)
+ dir = common.getUserHome();
+
+ if (dir === '-') {
+ if (!common.state.previousDir)
+ common.error('could not find previous directory');
+ else
+ dir = common.state.previousDir;
+ }
+
+ if (!fs.existsSync(dir))
+ common.error('no such file or directory: ' + dir);
+
+ if (!fs.statSync(dir).isDirectory())
+ common.error('not a directory: ' + dir);
+
+ common.state.previousDir = process.cwd();
+ process.chdir(dir);
+}
+module.exports = _cd;
+
+var common = require('./common');
+var fs = require('fs');
+var path = require('path');
+
+var PERMS = (function (base) {
+ return {
+ OTHER_EXEC : base.EXEC,
+ OTHER_WRITE : base.WRITE,
+ OTHER_READ : base.READ,
+
+ GROUP_EXEC : base.EXEC << 3,
+ GROUP_WRITE : base.WRITE << 3,
+ GROUP_READ : base.READ << 3,
+
+ OWNER_EXEC : base.EXEC << 6,
+ OWNER_WRITE : base.WRITE << 6,
+ OWNER_READ : base.READ << 6,
+
+ // Literal octal numbers are apparently not allowed in "strict" javascript. Using parseInt is
+ // the preferred way, else a jshint warning is thrown.
+ STICKY : parseInt('01000', 8),
+ SETGID : parseInt('02000', 8),
+ SETUID : parseInt('04000', 8),
+
+ TYPE_MASK : parseInt('0770000', 8)
+ };
+})({
+ EXEC : 1,
+ WRITE : 2,
+ READ : 4
+});
+
+//@
+//@ ### chmod(octal_mode || octal_string, file)
+//@ ### chmod(symbolic_mode, file)
+//@
+//@ Available options:
+//@
+//@ + `-v`: output a diagnostic for every file processed//@
+//@ + `-c`: like verbose but report only when a change is made//@
+//@ + `-R`: change files and directories recursively//@
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ chmod(755, '/Users/brandon');
+//@ chmod('755', '/Users/brandon'); // same as above
+//@ chmod('u+x', '/Users/brandon');
+//@ ```
+//@
+//@ Alters the permissions of a file or directory by either specifying the
+//@ absolute permissions in octal form or expressing the changes in symbols.
+//@ This command tries to mimic the POSIX behavior as much as possible.
+//@ Notable exceptions:
+//@
+//@ + In symbolic modes, 'a-r' and '-r' are identical. No consideration is
+//@ given to the umask.
+//@ + There is no "quiet" option since default behavior is to run silent.
+function _chmod(options, mode, filePattern) {
+ if (!filePattern) {
+ if (options.length > 0 && options.charAt(0) === '-') {
+ // Special case where the specified file permissions started with - to subtract perms, which
+ // get picked up by the option parser as command flags.
+ // If we are down by one argument and options starts with -, shift everything over.
+ filePattern = mode;
+ mode = options;
+ options = '';
+ }
+ else {
+ common.error('You must specify a file.');
+ }
+ }
+
+ options = common.parseOptions(options, {
+ 'R': 'recursive',
+ 'c': 'changes',
+ 'v': 'verbose'
+ });
+
+ if (typeof filePattern === 'string') {
+ filePattern = [ filePattern ];
+ }
+
+ var files;
+
+ if (options.recursive) {
+ files = [];
+ common.expand(filePattern).forEach(function addFile(expandedFile) {
+ var stat = fs.lstatSync(expandedFile);
+
+ if (!stat.isSymbolicLink()) {
+ files.push(expandedFile);
+
+ if (stat.isDirectory()) { // intentionally does not follow symlinks.
+ fs.readdirSync(expandedFile).forEach(function (child) {
+ addFile(expandedFile + '/' + child);
+ });
+ }
+ }
+ });
+ }
+ else {
+ files = common.expand(filePattern);
+ }
+
+ files.forEach(function innerChmod(file) {
+ file = path.resolve(file);
+ if (!fs.existsSync(file)) {
+ common.error('File not found: ' + file);
+ }
+
+ // When recursing, don't follow symlinks.
+ if (options.recursive && fs.lstatSync(file).isSymbolicLink()) {
+ return;
+ }
+
+ var stat = fs.statSync(file);
+ var isDir = stat.isDirectory();
+ var perms = stat.mode;
+ var type = perms & PERMS.TYPE_MASK;
+
+ var newPerms = perms;
+
+ if (isNaN(parseInt(mode, 8))) {
+ // parse options
+ mode.split(',').forEach(function (symbolicMode) {
+ /*jshint regexdash:true */
+ var pattern = /([ugoa]*)([=\+-])([rwxXst]*)/i;
+ var matches = pattern.exec(symbolicMode);
+
+ if (matches) {
+ var applyTo = matches[1];
+ var operator = matches[2];
+ var change = matches[3];
+
+ var changeOwner = applyTo.indexOf('u') != -1 || applyTo === 'a' || applyTo === '';
+ var changeGroup = applyTo.indexOf('g') != -1 || applyTo === 'a' || applyTo === '';
+ var changeOther = applyTo.indexOf('o') != -1 || applyTo === 'a' || applyTo === '';
+
+ var changeRead = change.indexOf('r') != -1;
+ var changeWrite = change.indexOf('w') != -1;
+ var changeExec = change.indexOf('x') != -1;
+ var changeExecDir = change.indexOf('X') != -1;
+ var changeSticky = change.indexOf('t') != -1;
+ var changeSetuid = change.indexOf('s') != -1;
+
+ if (changeExecDir && isDir)
+ changeExec = true;
+
+ var mask = 0;
+ if (changeOwner) {
+ mask |= (changeRead ? PERMS.OWNER_READ : 0) + (changeWrite ? PERMS.OWNER_WRITE : 0) + (changeExec ? PERMS.OWNER_EXEC : 0) + (changeSetuid ? PERMS.SETUID : 0);
+ }
+ if (changeGroup) {
+ mask |= (changeRead ? PERMS.GROUP_READ : 0) + (changeWrite ? PERMS.GROUP_WRITE : 0) + (changeExec ? PERMS.GROUP_EXEC : 0) + (changeSetuid ? PERMS.SETGID : 0);
+ }
+ if (changeOther) {
+ mask |= (changeRead ? PERMS.OTHER_READ : 0) + (changeWrite ? PERMS.OTHER_WRITE : 0) + (changeExec ? PERMS.OTHER_EXEC : 0);
+ }
+
+ // Sticky bit is special - it's not tied to user, group or other.
+ if (changeSticky) {
+ mask |= PERMS.STICKY;
+ }
+
+ switch (operator) {
+ case '+':
+ newPerms |= mask;
+ break;
+
+ case '-':
+ newPerms &= ~mask;
+ break;
+
+ case '=':
+ newPerms = type + mask;
+
+ // According to POSIX, when using = to explicitly set the permissions, setuid and setgid can never be cleared.
+ if (fs.statSync(file).isDirectory()) {
+ newPerms |= (PERMS.SETUID + PERMS.SETGID) & perms;
+ }
+ break;
+ }
+
+ if (options.verbose) {
+ console.log(file + ' -> ' + newPerms.toString(8));
+ }
+
+ if (perms != newPerms) {
+ if (!options.verbose && options.changes) {
+ console.log(file + ' -> ' + newPerms.toString(8));
+ }
+ fs.chmodSync(file, newPerms);
+ perms = newPerms; // for the next round of changes!
+ }
+ }
+ else {
+ common.error('Invalid symbolic mode change: ' + symbolicMode);
+ }
+ });
+ }
+ else {
+ // they gave us a full number
+ newPerms = type + parseInt(mode, 8);
+
+ // POSIX rules are that setuid and setgid can only be added using numeric form, but not cleared.
+ if (fs.statSync(file).isDirectory()) {
+ newPerms |= (PERMS.SETUID + PERMS.SETGID) & perms;
+ }
+
+ fs.chmodSync(file, newPerms);
+ }
+ });
+}
+module.exports = _chmod;
+
+var os = require('os');
+var fs = require('fs');
+var _ls = require('./ls');
+
+// Module globals
+var config = {
+ silent: false,
+ fatal: false,
+ verbose: false,
+};
+exports.config = config;
+
+var state = {
+ error: null,
+ currentCmd: 'shell.js',
+ previousDir: null,
+ tempDir: null
+};
+exports.state = state;
+
+var platform = os.type().match(/^Win/) ? 'win' : 'unix';
+exports.platform = platform;
+
+function log() {
+ if (!config.silent)
+ console.error.apply(console, arguments);
+}
+exports.log = log;
+
+// Shows error message. Throws unless _continue or config.fatal are true
+function error(msg, _continue) {
+ if (state.error === null)
+ state.error = '';
+ var log_entry = state.currentCmd + ': ' + msg;
+ if (state.error === '')
+ state.error = log_entry;
+ else
+ state.error += '\n' + log_entry;
+
+ if (msg.length > 0)
+ log(log_entry);
+
+ if (config.fatal)
+ process.exit(1);
+
+ if (!_continue)
+ throw '';
+}
+exports.error = error;
+
+// In the future, when Proxies are default, we can add methods like `.to()` to primitive strings.
+// For now, this is a dummy function to bookmark places we need such strings
+function ShellString(str) {
+ return str;
+}
+exports.ShellString = ShellString;
+
+// Return the home directory in a platform-agnostic way, with consideration for
+// older versions of node
+function getUserHome() {
+ var result;
+ if (os.homedir)
+ result = os.homedir(); // node 3+
+ else
+ result = process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME'];
+ return result;
+}
+exports.getUserHome = getUserHome;
+
+// Returns {'alice': true, 'bob': false} when passed a dictionary, e.g.:
+// parseOptions('-a', {'a':'alice', 'b':'bob'});
+function parseOptions(str, map) {
+ if (!map)
+ error('parseOptions() internal error: no map given');
+
+ // All options are false by default
+ var options = {};
+ for (var letter in map) {
+ if (!map[letter].match('^!'))
+ options[map[letter]] = false;
+ }
+
+ if (!str)
+ return options; // defaults
+
+ if (typeof str !== 'string')
+ error('parseOptions() internal error: wrong str');
+
+ // e.g. match[1] = 'Rf' for str = '-Rf'
+ var match = str.match(/^\-(.+)/);
+ if (!match)
+ return options;
+
+ // e.g. chars = ['R', 'f']
+ var chars = match[1].split('');
+
+ var opt;
+ chars.forEach(function(c) {
+ if (c in map) {
+ opt = map[c];
+ if (opt.match('^!'))
+ options[opt.slice(1, opt.length-1)] = false;
+ else
+ options[opt] = true;
+ } else {
+ error('option not recognized: '+c);
+ }
+ });
+
+ return options;
+}
+exports.parseOptions = parseOptions;
+
+// Expands wildcards with matching (ie. existing) file names.
+// For example:
+// expand(['file*.js']) = ['file1.js', 'file2.js', ...]
+// (if the files 'file1.js', 'file2.js', etc, exist in the current dir)
+function expand(list) {
+ var expanded = [];
+ list.forEach(function(listEl) {
+ // Wildcard present on directory names ?
+ if(listEl.search(/\*[^\/]*\//) > -1 || listEl.search(/\*\*[^\/]*\//) > -1) {
+ var match = listEl.match(/^([^*]+\/|)(.*)/);
+ var root = match[1];
+ var rest = match[2];
+ var restRegex = rest.replace(/\*\*/g, ".*").replace(/\*/g, "[^\\/]*");
+ restRegex = new RegExp(restRegex);
+
+ _ls('-R', root).filter(function (e) {
+ return restRegex.test(e);
+ }).forEach(function(file) {
+ expanded.push(file);
+ });
+ }
+ // Wildcard present on file names ?
+ else if (listEl.search(/\*/) > -1) {
+ _ls('', listEl).forEach(function(file) {
+ expanded.push(file);
+ });
+ } else {
+ expanded.push(listEl);
+ }
+ });
+ return expanded;
+}
+exports.expand = expand;
+
+// Normalizes _unlinkSync() across platforms to match Unix behavior, i.e.
+// file can be unlinked even if it's read-only, see https://github.com/joyent/node/issues/3006
+function unlinkSync(file) {
+ try {
+ fs.unlinkSync(file);
+ } catch(e) {
+ // Try to override file permission
+ if (e.code === 'EPERM') {
+ fs.chmodSync(file, '0666');
+ fs.unlinkSync(file);
+ } else {
+ throw e;
+ }
+ }
+}
+exports.unlinkSync = unlinkSync;
+
+// e.g. 'shelljs_a5f185d0443ca...'
+function randomFileName() {
+ function randomHash(count) {
+ if (count === 1)
+ return parseInt(16*Math.random(), 10).toString(16);
+ else {
+ var hash = '';
+ for (var i=0; i<count; i++)
+ hash += randomHash(1);
+ return hash;
+ }
+ }
+
+ return 'shelljs_'+randomHash(20);
+}
+exports.randomFileName = randomFileName;
+
+// extend(target_obj, source_obj1 [, source_obj2 ...])
+// Shallow extend, e.g.:
+// extend({A:1}, {b:2}, {c:3}) returns {A:1, b:2, c:3}
+function extend(target) {
+ var sources = [].slice.call(arguments, 1);
+ sources.forEach(function(source) {
+ for (var key in source)
+ target[key] = source[key];
+ });
+
+ return target;
+}
+exports.extend = extend;
+
+// Common wrapper for all Unix-like commands
+function wrap(cmd, fn, options) {
+ return function() {
+ var retValue = null;
+
+ state.currentCmd = cmd;
+ state.error = null;
+
+ try {
+ var args = [].slice.call(arguments, 0);
+
+ if (config.verbose) {
+ args.unshift(cmd);
+ console.log.apply(console, args);
+ args.shift();
+ }
+
+ if (options && options.notUnix) {
+ retValue = fn.apply(this, args);
+ } else {
+ if (args.length === 0 || typeof args[0] !== 'string' || args[0].length <= 1 || args[0][0] !== '-')
+ args.unshift(''); // only add dummy option if '-option' not already present
+ // Expand the '~' if appropriate
+ var homeDir = getUserHome();
+ args = args.map(function(arg) {
+ if (typeof arg === 'string' && arg.slice(0, 2) === '~/' || arg === '~')
+ return arg.replace(/^~/, homeDir);
+ else
+ return arg;
+ });
+ retValue = fn.apply(this, args);
+ }
+ } catch (e) {
+ if (!state.error) {
+ // If state.error hasn't been set it's an error thrown by Node, not us - probably a bug...
+ console.log('shell.js: internal error');
+ console.log(e.stack || e);
+ process.exit(1);
+ }
+ if (config.fatal)
+ throw e;
+ }
+
+ state.currentCmd = 'shell.js';
+ return retValue;
+ };
+} // wrap
+exports.wrap = wrap;
+
+var fs = require('fs');
+var path = require('path');
+var common = require('./common');
+var os = require('os');
+
+// Buffered file copy, synchronous
+// (Using readFileSync() + writeFileSync() could easily cause a memory overflow
+// with large files)
+function copyFileSync(srcFile, destFile) {
+ if (!fs.existsSync(srcFile))
+ common.error('copyFileSync: no such file or directory: ' + srcFile);
+
+ var BUF_LENGTH = 64*1024,
+ buf = new Buffer(BUF_LENGTH),
+ bytesRead = BUF_LENGTH,
+ pos = 0,
+ fdr = null,
+ fdw = null;
+
+ try {
+ fdr = fs.openSync(srcFile, 'r');
+ } catch(e) {
+ common.error('copyFileSync: could not read src file ('+srcFile+')');
+ }
+
+ try {
+ fdw = fs.openSync(destFile, 'w');
+ } catch(e) {
+ common.error('copyFileSync: could not write to dest file (code='+e.code+'):'+destFile);
+ }
+
+ while (bytesRead === BUF_LENGTH) {
+ bytesRead = fs.readSync(fdr, buf, 0, BUF_LENGTH, pos);
+ fs.writeSync(fdw, buf, 0, bytesRead);
+ pos += bytesRead;
+ }
+
+ fs.closeSync(fdr);
+ fs.closeSync(fdw);
+
+ fs.chmodSync(destFile, fs.statSync(srcFile).mode);
+}
+
+// Recursively copies 'sourceDir' into 'destDir'
+// 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 cpdirSyncRecursive(sourceDir, destDir, opts) {
+ if (!opts) opts = {};
+
+ /* Create the directory where all our junk is moving to; read the mode of the source directory and mirror it */
+ var checkDir = fs.statSync(sourceDir);
+ try {
+ fs.mkdirSync(destDir, checkDir.mode);
+ } catch (e) {
+ //if the directory already exists, that's okay
+ if (e.code !== 'EEXIST') throw e;
+ }
+
+ var files = fs.readdirSync(sourceDir);
+
+ for (var i = 0; i < files.length; i++) {
+ var srcFile = sourceDir + "/" + files[i];
+ var destFile = destDir + "/" + files[i];
+ var srcFileStat = fs.lstatSync(srcFile);
+
+ if (srcFileStat.isDirectory()) {
+ /* recursion this thing right on back. */
+ cpdirSyncRecursive(srcFile, destFile, opts);
+ } else if (srcFileStat.isSymbolicLink()) {
+ var symlinkFull = fs.readlinkSync(srcFile);
+ fs.symlinkSync(symlinkFull, destFile, os.platform() === "win32" ? "junction" : null);
+ } else {
+ /* At this point, we've hit a file actually worth copying... so copy it on over. */
+ if (fs.existsSync(destFile) && opts.no_force) {
+ common.log('skipping existing file: ' + files[i]);
+ } else {
+ copyFileSync(srcFile, destFile);
+ }
+ }
+
+ } // for files
+} // cpdirSyncRecursive
+
+
+//@
+//@ ### cp([options,] source [, source ...], dest)
+//@ ### cp([options,] source_array, dest)
+//@ Available options:
+//@
+//@ + `-f`: force (default behavior)
+//@ + `-n`: no-clobber
+//@ + `-r, -R`: recursive
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ cp('file1', 'dir1');
+//@ cp('-Rf', '/tmp/*', '/usr/local/*', '/home/tmp');
+//@ cp('-Rf', ['/tmp/*', '/usr/local/*'], '/home/tmp'); // same as above
+//@ ```
+//@
+//@ Copies files. The wildcard `*` is accepted.
+function _cp(options, sources, dest) {
+ options = common.parseOptions(options, {
+ 'f': '!no_force',
+ 'n': 'no_force',
+ 'R': 'recursive',
+ 'r': 'recursive'
+ });
+
+ // 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');
+ }
+
+ 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.no_force)
+ common.error('dest file already exists: ' + dest);
+
+ if (options.recursive) {
+ // Recursive allows the shortcut syntax "sourcedir/" for "sourcedir/*"
+ // (see Github issue #15)
+ sources.forEach(function(src, i) {
+ if (src[src.length - 1] === '/') {
+ sources[i] += '*';
+ // If src is a directory and dest doesn't exist, 'cp -r src dest' should copy src/* into dest
+ } else if (fs.statSync(src).isDirectory() && !exists) {
+ sources[i] += '/*';
+ }
+ });
+
+ // Create dest
+ try {
+ fs.mkdirSync(dest, parseInt('0777', 8));
+ } catch (e) {
+ // like Unix's cp, keep going even if we can't create dest dir
+ }
+ }
+
+ sources = common.expand(sources);
+
+ sources.forEach(function(src) {
+ if (!fs.existsSync(src)) {
+ common.error('no such file or directory: '+src, true);
+ return; // skip file
+ }
+
+ // If here, src exists
+ if (fs.statSync(src).isDirectory()) {
+ if (!options.recursive) {
+ // Non-Recursive
+ common.log(src + ' is a directory (not copied)');
+ } else {
+ // Recursive
+ // 'cp /a/source dest' should create 'source' in 'dest'
+ var newDest = path.join(dest, path.basename(src)),
+ checkDir = fs.statSync(src);
+ try {
+ fs.mkdirSync(newDest, checkDir.mode);
+ } catch (e) {
+ //if the directory already exists, that's okay
+ if (e.code !== 'EEXIST') {
+ common.error('dest file no such file or directory: ' + newDest, true);
+ throw e;
+ }
+ }
+
+ cpdirSyncRecursive(src, newDest, {no_force: options.no_force});
+ }
+ return; // done with dir
+ }
+
+ // If here, src is a file
+
+ // 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.no_force) {
+ common.error('dest file already exists: ' + thisDest, true);
+ return; // skip file
+ }
+
+ copyFileSync(src, thisDest);
+ }); // forEach(src)
+}
+module.exports = _cp;
+
+var common = require('./common');
+var _cd = require('./cd');
+var path = require('path');
+
+// Pushd/popd/dirs internals
+var _dirStack = [];
+
+function _isStackIndex(index) {
+ return (/^[\-+]\d+$/).test(index);
+}
+
+function _parseStackIndex(index) {
+ if (_isStackIndex(index)) {
+ if (Math.abs(index) < _dirStack.length + 1) { // +1 for pwd
+ return (/^-/).test(index) ? Number(index) - 1 : Number(index);
+ } else {
+ common.error(index + ': directory stack index out of range');
+ }
+ } else {
+ common.error(index + ': invalid number');
+ }
+}
+
+function _actualDirStack() {
+ return [process.cwd()].concat(_dirStack);
+}
+
+//@
+//@ ### pushd([options,] [dir | '-N' | '+N'])
+//@
+//@ Available options:
+//@
+//@ + `-n`: Suppresses the normal change of directory when adding directories to the stack, so that only the stack is manipulated.
+//@
+//@ Arguments:
+//@
+//@ + `dir`: Makes the current working directory be the top of the stack, and then executes the equivalent of `cd dir`.
+//@ + `+N`: Brings the Nth directory (counting from the left of the list printed by dirs, starting with zero) to the top of the list by rotating the stack.
+//@ + `-N`: Brings the Nth directory (counting from the right of the list printed by dirs, starting with zero) to the top of the list by rotating the stack.
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ // process.cwd() === '/usr'
+//@ pushd('/etc'); // Returns /etc /usr
+//@ pushd('+1'); // Returns /usr /etc
+//@ ```
+//@
+//@ Save the current directory on the top of the directory stack and then cd to `dir`. With no arguments, pushd exchanges the top two directories. Returns an array of paths in the stack.
+function _pushd(options, dir) {
+ if (_isStackIndex(options)) {
+ dir = options;
+ options = '';
+ }
+
+ options = common.parseOptions(options, {
+ 'n' : 'no-cd'
+ });
+
+ var dirs = _actualDirStack();
+
+ if (dir === '+0') {
+ return dirs; // +0 is a noop
+ } else if (!dir) {
+ if (dirs.length > 1) {
+ dirs = dirs.splice(1, 1).concat(dirs);
+ } else {
+ return common.error('no other directory');
+ }
+ } else if (_isStackIndex(dir)) {
+ var n = _parseStackIndex(dir);
+ dirs = dirs.slice(n).concat(dirs.slice(0, n));
+ } else {
+ if (options['no-cd']) {
+ dirs.splice(1, 0, dir);
+ } else {
+ dirs.unshift(dir);
+ }
+ }
+
+ if (options['no-cd']) {
+ dirs = dirs.slice(1);
+ } else {
+ dir = path.resolve(dirs.shift());
+ _cd('', dir);
+ }
+
+ _dirStack = dirs;
+ return _dirs('');
+}
+exports.pushd = _pushd;
+
+//@
+//@ ### popd([options,] ['-N' | '+N'])
+//@
+//@ Available options:
+//@
+//@ + `-n`: Suppresses the normal change of directory when removing directories from the stack, so that only the stack is manipulated.
+//@
+//@ Arguments:
+//@
+//@ + `+N`: Removes the Nth directory (counting from the left of the list printed by dirs), starting with zero.
+//@ + `-N`: Removes the Nth directory (counting from the right of the list printed by dirs), starting with zero.
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ echo(process.cwd()); // '/usr'
+//@ pushd('/etc'); // '/etc /usr'
+//@ echo(process.cwd()); // '/etc'
+//@ popd(); // '/usr'
+//@ echo(process.cwd()); // '/usr'
+//@ ```
+//@
+//@ When no arguments are given, popd removes the top directory from the stack and performs a cd to the new top directory. The elements are numbered from 0 starting at the first directory listed with dirs; i.e., popd is equivalent to popd +0. Returns an array of paths in the stack.
+function _popd(options, index) {
+ if (_isStackIndex(options)) {
+ index = options;
+ options = '';
+ }
+
+ options = common.parseOptions(options, {
+ 'n' : 'no-cd'
+ });
+
+ if (!_dirStack.length) {
+ return common.error('directory stack empty');
+ }
+
+ index = _parseStackIndex(index || '+0');
+
+ if (options['no-cd'] || index > 0 || _dirStack.length + index === 0) {
+ index = index > 0 ? index - 1 : index;
+ _dirStack.splice(index, 1);
+ } else {
+ var dir = path.resolve(_dirStack.shift());
+ _cd('', dir);
+ }
+
+ return _dirs('');
+}
+exports.popd = _popd;
+
+//@
+//@ ### dirs([options | '+N' | '-N'])
+//@
+//@ Available options:
+//@
+//@ + `-c`: Clears the directory stack by deleting all of the elements.
+//@
+//@ Arguments:
+//@
+//@ + `+N`: Displays the Nth directory (counting from the left of the list printed by dirs when invoked without options), starting with zero.
+//@ + `-N`: Displays the Nth directory (counting from the right of the list printed by dirs when invoked without options), starting with zero.
+//@
+//@ Display the list of currently remembered directories. Returns an array of paths in the stack, or a single path if +N or -N was specified.
+//@
+//@ See also: pushd, popd
+function _dirs(options, index) {
+ if (_isStackIndex(options)) {
+ index = options;
+ options = '';
+ }
+
+ options = common.parseOptions(options, {
+ 'c' : 'clear'
+ });
+
+ if (options['clear']) {
+ _dirStack = [];
+ return _dirStack;
+ }
+
+ var stack = _actualDirStack();
+
+ if (index) {
+ index = _parseStackIndex(index);
+
+ if (index < 0) {
+ index = stack.length + index;
+ }
+
+ common.log(stack[index]);
+ return stack[index];
+ }
+
+ common.log(stack.join(' '));
+
+ return stack;
+}
+exports.dirs = _dirs;
+
+var common = require('./common');
+
+//@
+//@ ### echo(string [, string ...])
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ echo('hello world');
+//@ var str = echo('hello world');
+//@ ```
+//@
+//@ Prints string to stdout, and returns string with additional utility methods
+//@ like `.to()`.
+function _echo() {
+ var messages = [].slice.call(arguments, 0);
+ console.log.apply(console, messages);
+ return common.ShellString(messages.join(' '));
+}
+module.exports = _echo;
+
+var common = require('./common');
+
+//@
+//@ ### error()
+//@ Tests if error occurred in the last command. Returns `null` if no error occurred,
+//@ otherwise returns string explaining the error
+function error() {
+ return common.state.error;
+}
+module.exports = error;
+
+var common = require('./common');
+var _tempDir = require('./tempdir');
+var _pwd = require('./pwd');
+var path = require('path');
+var fs = require('fs');
+var child = require('child_process');
+
+// Hack to run child_process.exec() synchronously (sync avoids callback hell)
+// Uses a custom wait loop that checks for a flag file, created when the child process is done.
+// (Can't do a wait loop that checks for internal Node variables/messages as
+// Node is single-threaded; callbacks and other internal state changes are done in the
+// event loop).
+function execSync(cmd, opts) {
+ var tempDir = _tempDir();
+ var stdoutFile = path.resolve(tempDir+'/'+common.randomFileName()),
+ stderrFile = path.resolve(tempDir+'/'+common.randomFileName()),
+ codeFile = path.resolve(tempDir+'/'+common.randomFileName()),
+ scriptFile = path.resolve(tempDir+'/'+common.randomFileName()),
+ sleepFile = path.resolve(tempDir+'/'+common.randomFileName());
+
+ var options = common.extend({
+ silent: common.config.silent
+ }, opts);
+
+ var previousStdoutContent = '',
+ previousStderrContent = '';
+ // Echoes stdout and stderr changes from running process, if not silent
+ function updateStream(streamFile) {
+ if (options.silent || !fs.existsSync(streamFile))
+ return;
+
+ var previousStreamContent,
+ proc_stream;
+ if (streamFile === stdoutFile) {
+ previousStreamContent = previousStdoutContent;
+ proc_stream = process.stdout;
+ } else { // assume stderr
+ previousStreamContent = previousStderrContent;
+ proc_stream = process.stderr;
+ }
+
+ var streamContent = fs.readFileSync(streamFile, 'utf8');
+ // No changes since last time?
+ if (streamContent.length <= previousStreamContent.length)
+ return;
+
+ proc_stream.write(streamContent.substr(previousStreamContent.length));
+ previousStreamContent = streamContent;
+ }
+
+ function escape(str) {
+ return (str+'').replace(/([\\"'])/g, "\\$1").replace(/\0/g, "\\0");
+ }
+
+ if (fs.existsSync(scriptFile)) common.unlinkSync(scriptFile);
+ if (fs.existsSync(stdoutFile)) common.unlinkSync(stdoutFile);
+ if (fs.existsSync(stderrFile)) common.unlinkSync(stderrFile);
+ if (fs.existsSync(codeFile)) common.unlinkSync(codeFile);
+
+ var execCommand = '"'+process.execPath+'" '+scriptFile;
+ var execOptions = {
+ env: process.env,
+ cwd: _pwd(),
+ maxBuffer: 20*1024*1024
+ };
+
+ var script;
+
+ if (typeof child.execSync === 'function') {
+ script = [
+ "var child = require('child_process')",
+ " , fs = require('fs');",
+ "var childProcess = child.exec('"+escape(cmd)+"', {env: process.env, maxBuffer: 20*1024*1024}, function(err) {",
+ " fs.writeFileSync('"+escape(codeFile)+"', err ? err.code.toString() : '0');",
+ "});",
+ "var stdoutStream = fs.createWriteStream('"+escape(stdoutFile)+"');",
+ "var stderrStream = fs.createWriteStream('"+escape(stderrFile)+"');",
+ "childProcess.stdout.pipe(stdoutStream, {end: false});",
+ "childProcess.stderr.pipe(stderrStream, {end: false});",
+ "childProcess.stdout.pipe(process.stdout);",
+ "childProcess.stderr.pipe(process.stderr);",
+ "var stdoutEnded = false, stderrEnded = false;",
+ "function tryClosingStdout(){ if(stdoutEnded){ stdoutStream.end(); } }",
+ "function tryClosingStderr(){ if(stderrEnded){ stderrStream.end(); } }",
+ "childProcess.stdout.on('end', function(){ stdoutEnded = true; tryClosingStdout(); });",
+ "childProcess.stderr.on('end', function(){ stderrEnded = true; tryClosingStderr(); });"
+ ].join('\n');
+
+ fs.writeFileSync(scriptFile, script);
+
+ if (options.silent) {
+ execOptions.stdio = 'ignore';
+ } else {
+ execOptions.stdio = [0, 1, 2];
+ }
+
+ // Welcome to the future
+ child.execSync(execCommand, execOptions);
+ } else {
+ cmd += ' > '+stdoutFile+' 2> '+stderrFile; // works on both win/unix
+
+ script = [
+ "var child = require('child_process')",
+ " , fs = require('fs');",
+ "var childProcess = child.exec('"+escape(cmd)+"', {env: process.env, maxBuffer: 20*1024*1024}, function(err) {",
+ " fs.writeFileSync('"+escape(codeFile)+"', err ? err.code.toString() : '0');",
+ "});"
+ ].join('\n');
+
+ fs.writeFileSync(scriptFile, script);
+
+ child.exec(execCommand, execOptions);
+
+ // The wait loop
+ // sleepFile is used as a dummy I/O op to mitigate unnecessary CPU usage
+ // (tried many I/O sync ops, writeFileSync() seems to be only one that is effective in reducing
+ // CPU usage, though apparently not so much on Windows)
+ while (!fs.existsSync(codeFile)) { updateStream(stdoutFile); fs.writeFileSync(sleepFile, 'a'); }
+ while (!fs.existsSync(stdoutFile)) { updateStream(stdoutFile); fs.writeFileSync(sleepFile, 'a'); }
+ while (!fs.existsSync(stderrFile)) { updateStream(stderrFile); fs.writeFileSync(sleepFile, 'a'); }
+ }
+
+ // At this point codeFile exists, but it's not necessarily flushed yet.
+ // Keep reading it until it is.
+ var code = parseInt('', 10);
+ while (isNaN(code)) {
+ code = parseInt(fs.readFileSync(codeFile, 'utf8'), 10);
+ }
+
+ var stdout = fs.readFileSync(stdoutFile, 'utf8');
+ var stderr = fs.readFileSync(stderrFile, 'utf8');
+
+ // No biggie if we can't erase the files now -- they're in a temp dir anyway
+ try { common.unlinkSync(scriptFile); } catch(e) {}
+ try { common.unlinkSync(stdoutFile); } catch(e) {}
+ try { common.unlinkSync(stderrFile); } catch(e) {}
+ try { common.unlinkSync(codeFile); } catch(e) {}
+ try { common.unlinkSync(sleepFile); } catch(e) {}
+
+ // some shell return codes are defined as errors, per http://tldp.org/LDP/abs/html/exitcodes.html
+ if (code === 1 || code === 2 || code >= 126) {
+ common.error('', true); // unix/shell doesn't really give an error message after non-zero exit codes
+ }
+ // True if successful, false if not
+ var obj = {
+ code: code,
+ output: stdout, // deprecated
+ stdout: stdout,
+ stderr: stderr
+ };
+ return obj;
+} // execSync()
+
+// Wrapper around exec() to enable echoing output to console in real time
+function execAsync(cmd, opts, callback) {
+ var stdout = '';
+ var stderr = '';
+
+ var options = common.extend({
+ silent: common.config.silent
+ }, opts);
+
+ var c = child.exec(cmd, {env: process.env, maxBuffer: 20*1024*1024}, function(err) {
+ if (callback)
+ callback(err ? err.code : 0, stdout, stderr);
+ });
+
+ c.stdout.on('data', function(data) {
+ stdout += data;
+ if (!options.silent)
+ process.stdout.write(data);
+ });
+
+ c.stderr.on('data', function(data) {
+ stderr += data;
+ if (!options.silent)
+ process.stderr.write(data);
+ });
+
+ return c;
+}
+
+//@
+//@ ### exec(command [, options] [, callback])
+//@ Available options (all `false` by default):
+//@
+//@ + `async`: Asynchronous execution. If a callback is provided, it will be set to
+//@ `true`, regardless of the passed value.
+//@ + `silent`: Do not echo program output to console.
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ var version = exec('node --version', {silent:true}).stdout;
+//@
+//@ var child = exec('some_long_running_process', {async:true});
+//@ child.stdout.on('data', function(data) {
+//@ /* ... do something with data ... */
+//@ });
+//@
+//@ exec('some_long_running_process', function(code, stdout, stderr) {
+//@ console.log('Exit code:', code);
+//@ console.log('Program output:', stdout);
+//@ console.log('Program stderr:', stderr);
+//@ });
+//@ ```
+//@
+//@ Executes the given `command` _synchronously_, unless otherwise specified. When in synchronous
+//@ mode returns the object `{ code:..., stdout:... , stderr:... }`, containing the program's
+//@ `stdout`, `stderr`, and its exit `code`. Otherwise returns the child process object,
+//@ and the `callback` gets the arguments `(code, stdout, stderr)`.
+//@
+//@ **Note:** For long-lived processes, it's best to run `exec()` asynchronously as
+//@ the current synchronous implementation uses a lot of CPU. This should be getting
+//@ fixed soon.
+function _exec(command, options, callback) {
+ if (!command)
+ common.error('must specify command');
+
+ // Callback is defined instead of options.
+ if (typeof options === 'function') {
+ callback = options;
+ options = { async: true };
+ }
+
+ // Callback is defined with options.
+ if (typeof options === 'object' && typeof callback === 'function') {
+ options.async = true;
+ }
+
+ options = common.extend({
+ silent: common.config.silent,
+ async: false
+ }, options);
+
+ if (options.async)
+ return execAsync(command, options, callback);
+ else
+ return execSync(command, options);
+}
+module.exports = _exec;
+
+var fs = require('fs');
+var common = require('./common');
+var _ls = require('./ls');
+
+//@
+//@ ### find(path [, path ...])
+//@ ### find(path_array)
+//@ Examples:
+//@
+//@ ```javascript
+//@ find('src', 'lib');
+//@ find(['src', 'lib']); // same as above
+//@ find('.').filter(function(file) { return file.match(/\.js$/); });
+//@ ```
+//@
+//@ Returns array of all files (however deep) in the given paths.
+//@
+//@ The main difference from `ls('-R', path)` is that the resulting file names
+//@ include the base directories, e.g. `lib/resources/file1` instead of just `file1`.
+function _find(options, paths) {
+ if (!paths)
+ common.error('no path specified');
+ else if (typeof paths === 'object')
+ paths = paths; // assume array
+ else if (typeof paths === 'string')
+ paths = [].slice.call(arguments, 1);
+
+ var list = [];
+
+ function pushFile(file) {
+ if (common.platform === 'win')
+ file = file.replace(/\\/g, '/');
+ list.push(file);
+ }
+
+ // why not simply do ls('-R', paths)? because the output wouldn't give the base dirs
+ // to get the base dir in the output, we need instead ls('-R', 'dir/*') for every directory
+
+ paths.forEach(function(file) {
+ pushFile(file);
+
+ if (fs.statSync(file).isDirectory()) {
+ _ls('-RA', file+'/*').forEach(function(subfile) {
+ pushFile(subfile);
+ });
+ }
+ });
+
+ return list;
+}
+module.exports = _find;
+
+var common = require('./common');
+var fs = require('fs');
+
+//@
+//@ ### grep([options,] regex_filter, file [, file ...])
+//@ ### grep([options,] regex_filter, file_array)
+//@ Available options:
+//@
+//@ + `-v`: Inverse the sense of the regex and print the lines not matching the criteria.
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ grep('-v', 'GLOBAL_VARIABLE', '*.js');
+//@ grep('GLOBAL_VARIABLE', '*.js');
+//@ ```
+//@
+//@ Reads input string from given files and returns a string containing all lines of the
+//@ file that match the given `regex_filter`. Wildcard `*` accepted.
+function _grep(options, regex, files) {
+ options = common.parseOptions(options, {
+ 'v': 'inverse'
+ });
+
+ if (!files)
+ common.error('no paths given');
+
+ if (typeof files === 'string')
+ files = [].slice.call(arguments, 2);
+ // if it's array leave it as it is
+
+ files = common.expand(files);
+
+ var grep = '';
+ files.forEach(function(file) {
+ if (!fs.existsSync(file)) {
+ common.error('no such file or directory: ' + file, true);
+ return;
+ }
+
+ var contents = fs.readFileSync(file, 'utf8'),
+ lines = contents.split(/\r*\n/);
+ lines.forEach(function(line) {
+ var matched = line.match(regex);
+ if ((options.inverse && !matched) || (!options.inverse && matched))
+ grep += line + '\n';
+ });
+ });
+
+ return common.ShellString(grep);
+}
+module.exports = _grep;
+
+var fs = require('fs');
+var path = require('path');
+var common = require('./common');
+
+//@
+//@ ### ln([options,] source, dest)
+//@ Available options:
+//@
+//@ + `-s`: symlink
+//@ + `-f`: force
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ ln('file', 'newlink');
+//@ ln('-sf', 'file', 'existing');
+//@ ```
+//@
+//@ Links source to dest. Use -f to force the link, should dest already exist.
+function _ln(options, source, dest) {
+ options = common.parseOptions(options, {
+ 's': 'symlink',
+ 'f': 'force'
+ });
+
+ if (!source || !dest) {
+ common.error('Missing <source> and/or <dest>');
+ }
+
+ source = String(source);
+ var sourcePath = path.normalize(source).replace(RegExp(path.sep + '$'), '');
+ var isAbsolute = (path.resolve(source) === sourcePath);
+ dest = path.resolve(process.cwd(), String(dest));
+
+ if (fs.existsSync(dest)) {
+ if (!options.force) {
+ common.error('Destination file exists', true);
+ }
+
+ fs.unlinkSync(dest);
+ }
+
+ if (options.symlink) {
+ var isWindows = common.platform === 'win';
+ var linkType = isWindows ? 'file' : null;
+ var resolvedSourcePath = isAbsolute ? sourcePath : path.resolve(process.cwd(), path.dirname(dest), source);
+ if (!fs.existsSync(resolvedSourcePath)) {
+ common.error('Source file does not exist', true);
+ } else if (isWindows && fs.statSync(resolvedSourcePath).isDirectory()) {
+ linkType = 'junction';
+ }
+
+ try {
+ fs.symlinkSync(linkType === 'junction' ? resolvedSourcePath: source, dest, linkType);
+ } catch (err) {
+ common.error(err.message);
+ }
+ } else {
+ if (!fs.existsSync(source)) {
+ common.error('Source file does not exist', true);
+ }
+ try {
+ fs.linkSync(source, dest);
+ } catch (err) {
+ common.error(err.message);
+ }
+ }
+}
+module.exports = _ln;
+
+var path = require('path');
+var fs = require('fs');
+var common = require('./common');
+var _cd = require('./cd');
+var _pwd = require('./pwd');
+
+//@
+//@ ### ls([options,] [path, ...])
+//@ ### ls([options,] path_array)
+//@ Available options:
+//@
+//@ + `-R`: recursive
+//@ + `-A`: all files (include files beginning with `.`, except for `.` and `..`)
+//@ + `-d`: list directories themselves, not their contents
+//@ + `-l`: list objects representing each file, each with fields containing `ls
+//@ -l` output fields. See
+//@ [fs.Stats](https://nodejs.org/api/fs.html#fs_class_fs_stats)
+//@ for more info
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ ls('projs/*.js');
+//@ ls('-R', '/users/me', '/tmp');
+//@ ls('-R', ['/users/me', '/tmp']); // same as above
+//@ ls('-l', 'file.txt'); // { name: 'file.txt', mode: 33188, nlink: 1, ...}
+//@ ```
+//@
+//@ 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',
+ 'd': 'directory',
+ 'l': 'long'
+ });
+
+ 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) {
+ var name = file.name || file;
+ // hidden file?
+ if (path.basename(name)[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')
+ name = name.replace(/\\/g, '/');
+
+ if (file.name) {
+ file.name = name;
+ } else {
+ file = name;
+ }
+ list.push(file);
+ return true;
+ }
+
+ paths.forEach(function(p) {
+ if (fs.existsSync(p)) {
+ var stats = ls_stat(p);
+ // Simple file?
+ if (stats.isFile()) {
+ if (options.long) {
+ pushFile(stats, p);
+ } else {
+ pushFile(p, p);
+ }
+ return; // continue
+ }
+
+ // Simple dir?
+ if (options.directory) {
+ pushFile(p, p);
+ return;
+ } else if (stats.isDirectory()) {
+ // Iterate over p contents
+ fs.readdirSync(p).forEach(function(file) {
+ var orig_file = file;
+ if (options.long)
+ file = ls_stat(path.join(p, file));
+ if (!pushFile(file, p))
+ return;
+
+ // Recursive?
+ if (options.recursive) {
+ var oldDir = _pwd();
+ _cd('', p);
+ if (fs.statSync(orig_file).isDirectory())
+ list = list.concat(_ls('-R'+(options.all?'A':''), orig_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))) {
+ var file_path = path.join(dirname, file);
+ file_path = options.long ? ls_stat(file_path) : file_path;
+ if (file_path.name)
+ file_path.name = path.normalize(file_path.name);
+ else
+ file_path = path.normalize(file_path);
+ if (!pushFile(file_path, 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;
+
+
+function ls_stat(path) {
+ var stats = fs.statSync(path);
+ // Note: this object will contain more information than .toString() returns
+ stats.name = path;
+ stats.toString = function() {
+ // Return a string resembling unix's `ls -l` format
+ return [this.mode, this.nlink, this.uid, this.gid, this.size, this.mtime, this.name].join(' ');
+ };
+ return stats;
+}
+
+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;
+
+var fs = require('fs');
+var path = require('path');
+var common = require('./common');
+
+//@
+//@ ### mv([options ,] source [, source ...], dest')
+//@ ### mv([options ,] source_array, dest')
+//@ Available options:
+//@
+//@ + `-f`: force (default behavior)
+//@ + `-n`: no-clobber
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ mv('-n', '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': '!no_force',
+ 'n': 'no_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.no_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.no_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;
+
+// see dirs.js
+// see dirs.js
+var path = require('path');
+var common = require('./common');
+
+//@
+//@ ### pwd()
+//@ Returns the current directory.
+function _pwd() {
+ var pwd = path.resolve(process.cwd());
+ return common.ShellString(pwd);
+}
+module.exports = _pwd;
+
+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 {
+ // Retry on windows, sometimes it takes a little time before all the files in the directory are gone
+ var start = Date.now();
+ while (true) {
+ try {
+ result = fs.rmdirSync(dir);
+ if (fs.existsSync(dir)) throw { code: "EAGAIN" };
+ break;
+ } catch(er) {
+ // In addition to error codes, also check if the directory still exists and loop again if true
+ if (process.platform === "win32" && (er.code === "ENOTEMPTY" || er.code === "EBUSY" || er.code === "EPERM" || er.code === "EAGAIN")) {
+ if (Date.now() - start > 1000) throw er;
+ } else if (er.code === "ENOENT") {
+ // Directory did not exist, deletion was successful
+ break;
+ } else {
+ throw er;
+ }
+ }
+ }
+ } 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;
+
+var common = require('./common');
+var fs = require('fs');
+
+//@
+//@ ### sed([options,] search_regex, replacement, file [, file ...])
+//@ ### sed([options,] search_regex, replacement, file_array)
+//@ 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 `files` 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, files) {
+ 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');
+
+ // Convert all search strings to RegExp
+ if (typeof regex === 'string')
+ regex = RegExp(regex);
+
+ if (!files)
+ common.error('no files given');
+
+ if (typeof files === 'string')
+ files = [].slice.call(arguments, 3);
+ // if it's array leave it as it is
+
+ files = common.expand(files);
+
+ var sed = [];
+ files.forEach(function(file) {
+ if (!fs.existsSync(file)) {
+ common.error('no such file or directory: ' + file, true);
+ return;
+ }
+
+ var result = fs.readFileSync(file, 'utf8').split('\n').map(function (line) {
+ return line.replace(regex, replacement);
+ }).join('\n');
+
+ sed.push(result);
+
+ if (options.inplace)
+ fs.writeFileSync(file, result, 'utf8');
+ });
+
+ return common.ShellString(sed.join('\n'));
+}
+module.exports = _sed;
+
+var common = require('./common');
+
+//@
+//@ ### set(options)
+//@ Available options:
+//@
+//@ + `+/-e`: exit upon error (`config.fatal`)
+//@ + `+/-v`: verbose: show all commands (`config.verbose`)
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ set('-e'); // exit upon first error
+//@ set('+e'); // this undoes a "set('-e')"
+//@ ```
+//@
+//@ Sets global configuration variables
+function _set(options) {
+ if (!options) {
+ var args = [].slice.call(arguments, 0);
+ if (args.length < 2)
+ common.error('must provide an argument');
+ options = args[1];
+ }
+ var negate = (options[0] === '+');
+ if (negate) {
+ options = '-' + options.slice(1); // parseOptions needs a '-' prefix
+ }
+ options = common.parseOptions(options, {
+ 'e': 'fatal',
+ 'v': 'verbose'
+ });
+
+ var key;
+ if (negate) {
+ for (key in options)
+ options[key] = !options[key];
+ }
+
+ for (key in options) {
+ // Only change the global config if `negate` is false and the option is true
+ // or if `negate` is true and the option is false (aka negate !== option)
+ if (negate !== options[key]) {
+ common.config[key] = options[key];
+ }
+ }
+ return;
+}
+module.exports = _set;
+
+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.tmpdir && os.tmpdir()) || // node 0.10+
+ writeableDir(os.tmpDir && os.tmpDir()) || // 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;
+
+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 symbolic 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;
+
+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');
+ return this;
+ } catch(e) {
+ common.error('could not write to file (code '+e.code+'): '+file, true);
+ }
+}
+module.exports = _to;
+
+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');
+ return this;
+ } catch(e) {
+ common.error('could not append to file (code '+e.code+'): '+file, true);
+ }
+}
+module.exports = _toEnd;
+
+var common = require('./common');
+var fs = require('fs');
+
+//@
+//@ ### touch([options,] file)
+//@ Available options:
+//@
+//@ + `-a`: Change only the access time
+//@ + `-c`: Do not create any files
+//@ + `-m`: Change only the modification time
+//@ + `-d DATE`: Parse DATE and use it instead of current time
+//@ + `-r FILE`: Use FILE's times instead of current time
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ touch('source.js');
+//@ touch('-c', '/path/to/some/dir/source.js');
+//@ touch({ '-r': FILE }, '/path/to/some/dir/source.js');
+//@ ```
+//@
+//@ Update the access and modification times of each FILE to the current time.
+//@ A FILE argument that does not exist is created empty, unless -c is supplied.
+//@ This is a partial implementation of *[touch(1)](http://linux.die.net/man/1/touch)*.
+function _touch(opts, files) {
+ opts = common.parseOptions(opts, {
+ 'a': 'atime_only',
+ 'c': 'no_create',
+ 'd': 'date',
+ 'm': 'mtime_only',
+ 'r': 'reference',
+ });
+
+ if (!files) {
+ common.error('no paths given');
+ }
+
+
+ if (Array.isArray(files)) {
+ files.forEach(function(f) {
+ touchFile(opts, f);
+ });
+ } else if (typeof files === 'string') {
+ touchFile(opts, files);
+ } else {
+ common.error('file arg should be a string file path or an Array of string file paths');
+ }
+
+}
+
+function touchFile(opts, file) {
+ var stat = tryStatFile(file);
+
+ if (stat && stat.isDirectory()) {
+ // don't error just exit
+ return;
+ }
+
+ // if the file doesn't already exist and the user has specified --no-create then
+ // this script is finished
+ if (!stat && opts.no_create) {
+ return;
+ }
+
+ // open the file and then close it. this will create it if it doesn't exist but will
+ // not truncate the file
+ fs.closeSync(fs.openSync(file, 'a'));
+
+ //
+ // Set timestamps
+ //
+
+ // setup some defaults
+ var now = new Date();
+ var mtime = opts.date || now;
+ var atime = opts.date || now;
+
+ // use reference file
+ if (opts.reference) {
+ var refStat = tryStatFile(opts.reference);
+ if (!refStat) {
+ common.error('failed to get attributess of ' + opts.reference);
+ }
+ mtime = refStat.mtime;
+ atime = refStat.atime;
+ } else if (opts.date) {
+ mtime = opts.date;
+ atime = opts.date;
+ }
+
+ if (opts.atime_only && opts.mtime_only) {
+ // keep the new values of mtime and atime like GNU
+ } else if (opts.atime_only) {
+ mtime = stat.mtime;
+ } else if (opts.mtime_only) {
+ atime = stat.atime;
+ }
+
+ fs.utimesSync(file, atime, mtime);
+}
+
+module.exports = _touch;
+
+function tryStatFile(filePath) {
+ try {
+ return fs.statSync(filePath);
+ } catch (e) {
+ return null;
+ }
+}
+
+var common = require('./common');
+var fs = require('fs');
+var path = require('path');
+
+// XP's system default value for PATHEXT system variable, just in case it's not
+// set on Windows.
+var XP_DEFAULT_PATHEXT = '.com;.exe;.bat;.cmd;.vbs;.vbe;.js;.jse;.wsf;.wsh';
+
+// Cross-platform method for splitting environment PATH variables
+function splitPath(p) {
+ 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();
+}
+
+//@
+//@ ### which(command)
+//@
+//@ Examples:
+//@
+//@ ```javascript
+//@ var nodeExec = which('node');
+//@ ```
+//@
+//@ Searches for `command` in the system's PATH. On Windows, this uses the
+//@ `PATHEXT` variable to append the extension if it's not already executable.
+//@ 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 (common.platform === 'win') {
+ attempt = attempt.toUpperCase();
+
+ // In case the PATHEXT variable is somehow not set (e.g.
+ // child_process.spawn with an empty environment), use the XP default.
+ var pathExtEnv = process.env.PATHEXT || XP_DEFAULT_PATHEXT;
+ var pathExtArray = splitPath(pathExtEnv.toUpperCase());
+ var i;
+
+ // If the extension is already in PATHEXT, just return that.
+ for (i = 0; i < pathExtArray.length; i++) {
+ var ext = pathExtArray[i];
+ if (attempt.slice(-ext.length) === ext && checkPath(attempt)) {
+ where = attempt;
+ return;
+ }
+ }
+
+ // Cycle through the PATHEXT variable
+ var baseAttempt = attempt;
+ for (i = 0; i < pathExtArray.length; i++) {
+ attempt = baseAttempt + pathExtArray[i];
+ if (checkPath(attempt)) {
+ where = attempt;
+ return;
+ }
+ }
+ } else {
+ // Assume it's Unix-like
+ if (checkPath(attempt)) {
+ where = attempt;
+ return;
+ }
+ }
+ });
+ }
+
+ // 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-browser/blob/012b9d3b/node_modules/shelljs/jshint.json
----------------------------------------------------------------------
diff --git a/node_modules/shelljs/jshint.json b/node_modules/shelljs/jshint.json
deleted file mode 100644
index 205ed9c..0000000
--- a/node_modules/shelljs/jshint.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "loopfunc": true,
- "sub": true
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cordova-browser/blob/012b9d3b/node_modules/shelljs/make.js
----------------------------------------------------------------------
diff --git a/node_modules/shelljs/make.js b/node_modules/shelljs/make.js
index b636447..a8438c8 100644
--- a/node_modules/shelljs/make.js
+++ b/node_modules/shelljs/make.js
@@ -1,48 +1,57 @@
require('./global');
-config.fatal = true;
+global.config.fatal = true;
global.target = {};
+var args = process.argv.slice(2),
+ targetArgs,
+ dashesLoc = args.indexOf('--');
+
+// split args, everything after -- if only for targets
+if (dashesLoc > -1) {
+ targetArgs = args.slice(dashesLoc + 1, args.length);
+ args = args.slice(0, dashesLoc);
+}
+
// This ensures we only execute the script targets after the entire script has
// been evaluated
-var args = process.argv.slice(2);
setTimeout(function() {
var t;
if (args.length === 1 && args[0] === '--help') {
console.log('Available targets:');
- for (t in target)
+ for (t in global.target)
console.log(' ' + t);
return;
}
// Wrap targets to prevent duplicate execution
- for (t in target) {
+ for (t in global.target) {
(function(t, oldTarget){
// Wrap it
- target[t] = function(force) {
- if (oldTarget.done && !force)
- return;
- oldTarget.done = true;
- return oldTarget.apply(oldTarget, arguments);
+ global.target[t] = function() {
+ if (!oldTarget.done){
+ oldTarget.done = true;
+ oldTarget.result = oldTarget.apply(oldTarget, arguments);
+ }
+ return oldTarget.result;
};
- })(t, target[t]);
+ })(t, global.target[t]);
}
// Execute desired targets
if (args.length > 0) {
args.forEach(function(arg) {
- if (arg in target)
- target[arg]();
+ if (arg in global.target)
+ global.target[arg](targetArgs);
else {
console.log('no such target: ' + arg);
- exit(1);
}
});
- } else if ('all' in target) {
- target.all();
+ } else if ('all' in global.target) {
+ global.target.all(targetArgs);
}
}, 0);
http://git-wip-us.apache.org/repos/asf/cordova-browser/blob/012b9d3b/node_modules/shelljs/package.json
----------------------------------------------------------------------
diff --git a/node_modules/shelljs/package.json b/node_modules/shelljs/package.json
index 5e65061..44cb880 100644
--- a/node_modules/shelljs/package.json
+++ b/node_modules/shelljs/package.json
@@ -1,9 +1,9 @@
{
"name": "shelljs",
- "version": "0.1.4",
+ "version": "0.6.0",
"author": {
"name": "Artur Adib",
- "email": "aadib@mozilla.com"
+ "email": "arturadib@gmail.com"
},
"description": "Portable Unix shell commands for Node.js",
"keywords": [
@@ -14,11 +14,23 @@
"jake",
"synchronous"
],
+ "contributors": [
+ {
+ "name": "Ari Porad",
+ "email": "ari@ariporad.com",
+ "url": "http://ariporad.com/"
+ },
+ {
+ "name": "Nate Fischer",
+ "email": "ntfschr@gmail.com"
+ }
+ ],
"repository": {
"type": "git",
- "url": "git://github.com/arturadib/shelljs.git"
+ "url": "git://github.com/shelljs/shelljs.git"
},
- "homepage": "http://github.com/arturadib/shelljs",
+ "license": "BSD-3-Clause",
+ "homepage": "http://github.com/shelljs/shelljs",
"main": "./shell.js",
"scripts": {
"test": "node scripts/run-tests"
@@ -28,34 +40,49 @@
},
"dependencies": {},
"devDependencies": {
- "jshint": "~1.1.0"
+ "coffee-script": "^1.10.0",
+ "jshint": "~2.1.11"
},
"optionalDependencies": {},
"engines": {
- "node": "*"
+ "node": ">=0.10.0"
},
- "_id": "shelljs@0.1.4",
- "dist": {
- "shasum": "dfbbe78d56c3c0168d2fb79e10ecd1dbcb07ec0e",
- "tarball": "http://registry.npmjs.org/shelljs/-/shelljs-0.1.4.tgz"
+ "gitHead": "fe06baf1173ec6f0a70cd58ddb7d373f4c6446f5",
+ "bugs": {
+ "url": "https://github.com/shelljs/shelljs/issues"
},
- "_from": "shelljs@>=0.1.4 <0.2.0",
- "_npmVersion": "1.2.14",
+ "_id": "shelljs@0.6.0",
+ "_shasum": "ce1ed837b4b0e55b5ec3dab84251ab9dbdc0c7ec",
+ "_from": "shelljs@>=0.6.0 <0.7.0",
+ "_npmVersion": "3.6.0",
+ "_nodeVersion": "5.4.0",
"_npmUser": {
- "name": "artur",
- "email": "arturadib@gmail.com"
+ "name": "ariporad",
+ "email": "ari@ariporad.com"
+ },
+ "dist": {
+ "shasum": "ce1ed837b4b0e55b5ec3dab84251ab9dbdc0c7ec",
+ "tarball": "http://registry.npmjs.org/shelljs/-/shelljs-0.6.0.tgz"
},
"maintainers": [
{
+ "name": "ariporad",
+ "email": "ari@ariporad.com"
+ },
+ {
"name": "artur",
"email": "arturadib@gmail.com"
+ },
+ {
+ "name": "nfischer",
+ "email": "ntfschr@gmail.com"
}
],
- "directories": {},
- "_shasum": "dfbbe78d56c3c0168d2fb79e10ecd1dbcb07ec0e",
- "_resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.1.4.tgz",
- "bugs": {
- "url": "https://github.com/arturadib/shelljs/issues"
+ "_npmOperationalInternal": {
+ "host": "packages-6-west.internal.npmjs.com",
+ "tmp": "tmp/shelljs-0.6.0.tgz_1454632811074_0.5800695188809186"
},
+ "directories": {},
+ "_resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.6.0.tgz",
"readme": "ERROR: No README data found!"
}
http://git-wip-us.apache.org/repos/asf/cordova-browser/blob/012b9d3b/node_modules/shelljs/scripts/docs.js
----------------------------------------------------------------------
diff --git a/node_modules/shelljs/scripts/docs.js b/node_modules/shelljs/scripts/docs.js
deleted file mode 100755
index 68a2138..0000000
--- a/node_modules/shelljs/scripts/docs.js
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env node
-require('../global');
-
-echo('Appending docs to README.md');
-
-cd(__dirname + '/..');
-
-// Extract docs from shell.js
-var docs = grep('//@', 'shell.js');
-// Remove '//@'
-docs = docs.replace(/\/\/\@ ?/g, '');
-// Append docs to README
-sed('-i', /## Command reference(.|\n)*/, '## Command reference\n\n' + docs, 'README.md');
-
-echo('All done.');
http://git-wip-us.apache.org/repos/asf/cordova-browser/blob/012b9d3b/node_modules/shelljs/scripts/generate-docs.js
----------------------------------------------------------------------
diff --git a/node_modules/shelljs/scripts/generate-docs.js b/node_modules/shelljs/scripts/generate-docs.js
new file mode 100644
index 0000000..3a31a91
--- /dev/null
+++ b/node_modules/shelljs/scripts/generate-docs.js
@@ -0,0 +1,26 @@
+#!/usr/bin/env node
+/* globals cat, cd, echo, grep, sed */
+require('../global');
+
+echo('Appending docs to README.md');
+
+cd(__dirname + '/..');
+
+// Extract docs from shell.js
+var docs = grep('//@', 'shell.js');
+
+docs = docs.replace(/\/\/\@include (.+)/g, function(match, path) {
+ var file = path.match('.js$') ? path : path+'.js';
+ return grep('//@', file);
+});
+
+// Remove '//@'
+docs = docs.replace(/\/\/\@ ?/g, '');
+
+// Wipe out the old docs
+cat('README.md').replace(/## Command reference(.|\n)*/, '## Command reference').to('README.md');
+
+// Append new docs to README
+sed('-i', /## Command reference/, '## Command reference\n\n' + docs, 'README.md');
+
+echo('All done.');
http://git-wip-us.apache.org/repos/asf/cordova-browser/blob/012b9d3b/node_modules/shelljs/scripts/run-tests.js
----------------------------------------------------------------------
diff --git a/node_modules/shelljs/scripts/run-tests.js b/node_modules/shelljs/scripts/run-tests.js
index a9d32fc..e8e7ff2 100755
--- a/node_modules/shelljs/scripts/run-tests.js
+++ b/node_modules/shelljs/scripts/run-tests.js
@@ -1,14 +1,14 @@
#!/usr/bin/env node
+/* globals cd, echo, exec, exit, ls, pwd, test */
require('../global');
-
-var path = require('path');
+var common = require('../src/common');
var failed = false;
//
// Lint
//
-JSHINT_BIN = './node_modules/jshint/bin/jshint';
+var JSHINT_BIN = 'node_modules/jshint/bin/jshint';
cd(__dirname + '/..');
if (!test('-f', JSHINT_BIN)) {
@@ -16,7 +16,12 @@ if (!test('-f', JSHINT_BIN)) {
exit(1);
}
-if (exec(JSHINT_BIN + ' --config jshint.json *.js test/*.js').code !== 0) {
+var jsfiles = common.expand([pwd() + '/*.js',
+ pwd() + '/scripts/*.js',
+ pwd() + '/src/*.js',
+ pwd() + '/test/*.js'
+ ]).join(' ');
+if (exec('node ' + pwd() + '/' + JSHINT_BIN + ' ' + jsfiles).code !== 0) {
failed = true;
echo('*** JSHINT FAILED! (return code != 0)');
echo();
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org