diff options
Diffstat (limited to 'tools/eslint/node_modules/shelljs/src')
24 files changed, 543 insertions, 180 deletions
diff --git a/tools/eslint/node_modules/shelljs/src/cat.js b/tools/eslint/node_modules/shelljs/src/cat.js index f6f4d254ae..5840b4ea77 100644 --- a/tools/eslint/node_modules/shelljs/src/cat.js +++ b/tools/eslint/node_modules/shelljs/src/cat.js @@ -32,12 +32,9 @@ function _cat(options, files) { if (!fs.existsSync(file)) common.error('no such file or directory: ' + file); - cat += fs.readFileSync(file, 'utf8') + '\n'; + cat += fs.readFileSync(file, 'utf8'); }); - if (cat[cat.length-1] === '\n') - cat = cat.substring(0, cat.length-1); - return common.ShellString(cat); } module.exports = _cat; diff --git a/tools/eslint/node_modules/shelljs/src/cd.js b/tools/eslint/node_modules/shelljs/src/cd.js index 230f432651..b7b9931b8f 100644 --- a/tools/eslint/node_modules/shelljs/src/cd.js +++ b/tools/eslint/node_modules/shelljs/src/cd.js @@ -2,11 +2,19 @@ var fs = require('fs'); var common = require('./common'); //@ -//@ ### cd('dir') -//@ Changes to directory `dir` for the duration of the script +//@ ### 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) - common.error('directory not specified'); + 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); @@ -14,6 +22,7 @@ function _cd(options, dir) { if (!fs.statSync(dir).isDirectory()) common.error('not a directory: ' + dir); + common.state.previousDir = process.cwd(); process.chdir(dir); } module.exports = _cd; diff --git a/tools/eslint/node_modules/shelljs/src/chmod.js b/tools/eslint/node_modules/shelljs/src/chmod.js index f2888930b3..6c6de10ce1 100644 --- a/tools/eslint/node_modules/shelljs/src/chmod.js +++ b/tools/eslint/node_modules/shelljs/src/chmod.js @@ -114,7 +114,9 @@ function _chmod(options, mode, filePattern) { return; } - var perms = fs.statSync(file).mode; + var stat = fs.statSync(file); + var isDir = stat.isDirectory(); + var perms = stat.mode; var type = perms & PERMS.TYPE_MASK; var newPerms = perms; @@ -135,11 +137,15 @@ function _chmod(options, mode, filePattern) { 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 changeSticky = change.indexOf('t') != -1; - var changeSetuid = change.indexOf('s') != -1; + 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) { @@ -177,14 +183,15 @@ function _chmod(options, mode, filePattern) { } if (options.verbose) { - log(file + ' -> ' + newPerms.toString(8)); + console.log(file + ' -> ' + newPerms.toString(8)); } if (perms != newPerms) { if (!options.verbose && options.changes) { - log(file + ' -> ' + newPerms.toString(8)); + console.log(file + ' -> ' + newPerms.toString(8)); } fs.chmodSync(file, newPerms); + perms = newPerms; // for the next round of changes! } } else { diff --git a/tools/eslint/node_modules/shelljs/src/common.js b/tools/eslint/node_modules/shelljs/src/common.js index 8d10f3dde7..33198bd8a0 100644 --- a/tools/eslint/node_modules/shelljs/src/common.js +++ b/tools/eslint/node_modules/shelljs/src/common.js @@ -5,13 +5,15 @@ var _ls = require('./ls'); // Module globals var config = { silent: false, - fatal: false + fatal: false, + verbose: false, }; exports.config = config; var state = { error: null, currentCmd: 'shell.js', + previousDir: null, tempDir: null }; exports.state = state; @@ -21,7 +23,7 @@ exports.platform = platform; function log() { if (!config.silent) - console.log.apply(this, arguments); + console.error.apply(console, arguments); } exports.log = log; @@ -29,10 +31,14 @@ exports.log = log; function error(msg, _continue) { if (state.error === null) state.error = ''; - state.error += state.currentCmd + ': ' + msg + '\n'; + var log_entry = state.currentCmd + ': ' + msg; + if (state.error === '') + state.error = log_entry; + else + state.error += '\n' + log_entry; if (msg.length > 0) - log(state.error); + log(log_entry); if (config.fatal) process.exit(1); @@ -49,38 +55,69 @@ function ShellString(str) { } exports.ShellString = ShellString; -// Returns {'alice': true, 'bob': false} when passed a dictionary, e.g.: +// 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 string and dictionary as follows: // parseOptions('-a', {'a':'alice', 'b':'bob'}); -function parseOptions(str, map) { +// Returns {'reference': 'string-value', 'bob': false} when passed two dictionaries of the form: +// parseOptions({'-r': 'string-value'}, {'r':'reference', 'b':'bob'}); +function parseOptions(opt, map) { if (!map) error('parseOptions() internal error: no map given'); // All options are false by default var options = {}; - for (var letter in map) - options[map[letter]] = false; + for (var letter in map) { + if (map[letter][0] !== '!') + options[map[letter]] = false; + } - if (!str) + if (!opt) 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; + var optionName; + if (typeof opt === 'string') { + if (opt[0] !== '-') + return options; - // e.g. chars = ['R', 'f'] - var chars = match[1].split(''); - - chars.forEach(function(c) { - if (c in map) - options[map[c]] = true; - else - error('option not recognized: '+c); - }); + // e.g. chars = ['R', 'f'] + var chars = opt.slice(1).split(''); + chars.forEach(function(c) { + if (c in map) { + optionName = map[c]; + if (optionName[0] === '!') + options[optionName.slice(1, optionName.length-1)] = false; + else + options[optionName] = true; + } else { + error('option not recognized: '+c); + } + }); + } else if (typeof opt === 'object') { + for (var key in opt) { + // key is a string of the form '-r', '-d', etc. + var c = key[1]; + if (c in map) { + optionName = map[c]; + options[optionName] = opt[key]; // assign the given value + } else { + error('option not recognized: '+c); + } + } + } else { + error('options must be strings or key-value pairs'); + } return options; } exports.parseOptions = parseOptions; @@ -178,11 +215,28 @@ function wrap(cmd, fn, options) { 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][0] !== '-') + if (typeof args[0] === 'object' && args[0].constructor.name === 'Object') { + args = args; // object count as options + } 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) { diff --git a/tools/eslint/node_modules/shelljs/src/cp.js b/tools/eslint/node_modules/shelljs/src/cp.js index ef19f96ecf..54404efb16 100644 --- a/tools/eslint/node_modules/shelljs/src/cp.js +++ b/tools/eslint/node_modules/shelljs/src/cp.js @@ -76,7 +76,7 @@ function cpdirSyncRecursive(sourceDir, destDir, opts) { 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.force) { + if (fs.existsSync(destFile) && opts.no_force) { common.log('skipping existing file: ' + files[i]); } else { copyFileSync(srcFile, destFile); @@ -88,11 +88,12 @@ function cpdirSyncRecursive(sourceDir, destDir, opts) { //@ -//@ ### cp([options ,] source [,source ...], dest) -//@ ### cp([options ,] source_array, dest) +//@ ### cp([options,] source [, source ...], dest) +//@ ### cp([options,] source_array, dest) //@ Available options: //@ -//@ + `-f`: force +//@ + `-f`: force (default behavior) +//@ + `-n`: no-clobber //@ + `-r, -R`: recursive //@ //@ Examples: @@ -106,7 +107,8 @@ function cpdirSyncRecursive(sourceDir, destDir, opts) { //@ Copies files. The wildcard `*` is accepted. function _cp(options, sources, dest) { options = common.parseOptions(options, { - 'f': 'force', + 'f': '!no_force', + 'n': 'no_force', 'R': 'recursive', 'r': 'recursive' }); @@ -133,15 +135,19 @@ function _cp(options, sources, dest) { 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) + 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] === '/') + 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 @@ -180,7 +186,7 @@ function _cp(options, sources, dest) { } } - cpdirSyncRecursive(src, newDest, {force: options.force}); + cpdirSyncRecursive(src, newDest, {no_force: options.no_force}); } return; // done with dir } @@ -193,7 +199,7 @@ function _cp(options, sources, dest) { if (fs.existsSync(dest) && fs.statSync(dest).isDirectory()) thisDest = path.normalize(dest + '/' + path.basename(src)); - if (fs.existsSync(thisDest) && !options.force) { + if (fs.existsSync(thisDest) && options.no_force) { common.error('dest file already exists: ' + thisDest, true); return; // skip file } diff --git a/tools/eslint/node_modules/shelljs/src/echo.js b/tools/eslint/node_modules/shelljs/src/echo.js index 760ea840f0..b574adc5c3 100644 --- a/tools/eslint/node_modules/shelljs/src/echo.js +++ b/tools/eslint/node_modules/shelljs/src/echo.js @@ -1,7 +1,7 @@ var common = require('./common'); //@ -//@ ### echo(string [,string ...]) +//@ ### echo(string [, string ...]) //@ //@ Examples: //@ @@ -14,7 +14,7 @@ var common = require('./common'); //@ like `.to()`. function _echo() { var messages = [].slice.call(arguments, 0); - console.log.apply(this, messages); + console.log.apply(console, messages); return common.ShellString(messages.join(' ')); } module.exports = _echo; diff --git a/tools/eslint/node_modules/shelljs/src/error.js b/tools/eslint/node_modules/shelljs/src/error.js index cca3efb608..112563db80 100644 --- a/tools/eslint/node_modules/shelljs/src/error.js +++ b/tools/eslint/node_modules/shelljs/src/error.js @@ -6,5 +6,5 @@ var common = require('./common'); //@ otherwise returns string explaining the error function error() { return common.state.error; -}; +} module.exports = error; diff --git a/tools/eslint/node_modules/shelljs/src/exec.js b/tools/eslint/node_modules/shelljs/src/exec.js index d259a9f26c..4174adbd32 100644 --- a/tools/eslint/node_modules/shelljs/src/exec.js +++ b/tools/eslint/node_modules/shelljs/src/exec.js @@ -5,6 +5,8 @@ var path = require('path'); var fs = require('fs'); var child = require('child_process'); +var DEFAULT_MAXBUFFER_SIZE = 20*1024*1024; + // 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 @@ -13,27 +15,42 @@ var child = require('child_process'); 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 = common.extend({ + silent: common.config.silent, + cwd: _pwd(), + env: process.env, + maxBuffer: DEFAULT_MAXBUFFER_SIZE }, opts); - var previousStdoutContent = ''; - // Echoes stdout changes from running process, if not silent - function updateStdout() { - if (options.silent || !fs.existsSync(stdoutFile)) + var previousStdoutContent = '', + previousStderrContent = ''; + // Echoes stdout and stderr changes from running process, if not silent + function updateStream(streamFile) { + if (opts.silent || !fs.existsSync(streamFile)) return; - var stdoutContent = fs.readFileSync(stdoutFile, 'utf8'); + 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 (stdoutContent.length <= previousStdoutContent.length) + if (streamContent.length <= previousStreamContent.length) return; - process.stdout.write(stdoutContent.substr(previousStdoutContent.length)); - previousStdoutContent = stdoutContent; + proc_stream.write(streamContent.substr(previousStreamContent.length)); + previousStreamContent = streamContent; } function escape(str) { @@ -42,64 +59,64 @@ function execSync(cmd, opts) { 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') { - var script = [ + script = [ "var child = require('child_process')", " , fs = require('fs');", - "var childProcess = child.exec('"+escape(cmd)+"', {env: process.env, maxBuffer: 20*1024*1024}, function(err) {", + "var childProcess = child.exec('"+escape(cmd)+"', {env: process.env, maxBuffer: "+opts.maxBuffer+"}, 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(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 tryClosing(){ if(stdoutEnded && stderrEnded){ stdoutStream.end(); } }", - "childProcess.stdout.on('end', function(){ stdoutEnded = true; tryClosing(); });", - "childProcess.stderr.on('end', function(){ stderrEnded = true; tryClosing(); });" + "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'; + if (opts.silent) { + opts.stdio = 'ignore'; } else { - execOptions.stdio = [0, 1, 2]; + opts.stdio = [0, 1, 2]; } // Welcome to the future - child.execSync(execCommand, execOptions); + child.execSync(execCommand, opts); } else { - cmd += ' > '+stdoutFile+' 2>&1'; // works on both win/unix + cmd += ' > '+stdoutFile+' 2> '+stderrFile; // works on both win/unix - var script = [ + script = [ "var child = require('child_process')", " , fs = require('fs');", - "var childProcess = child.exec('"+escape(cmd)+"', {env: process.env, maxBuffer: 20*1024*1024}, function(err) {", + "var childProcess = child.exec('"+escape(cmd)+"', {env: process.env, maxBuffer: "+opts.maxBuffer+"}, function(err) {", " fs.writeFileSync('"+escape(codeFile)+"', err ? err.code.toString() : '0');", "});" ].join('\n'); fs.writeFileSync(scriptFile, script); - child.exec(execCommand, execOptions); + child.exec(execCommand, opts); // 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)) { updateStdout(); fs.writeFileSync(sleepFile, 'a'); } - while (!fs.existsSync(stdoutFile)) { updateStdout(); fs.writeFileSync(sleepFile, 'a'); } + 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. @@ -110,10 +127,12 @@ function execSync(cmd, opts) { } 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) {} @@ -124,34 +143,40 @@ function execSync(cmd, opts) { // True if successful, false if not var obj = { code: code, - output: stdout + 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 output = ''; + var stdout = ''; + var stderr = ''; - var options = common.extend({ - silent: common.config.silent + opts = common.extend({ + silent: common.config.silent, + cwd: _pwd(), + env: process.env, + maxBuffer: DEFAULT_MAXBUFFER_SIZE }, opts); - var c = child.exec(cmd, {env: process.env, maxBuffer: 20*1024*1024}, function(err) { + var c = child.exec(cmd, opts, function(err) { if (callback) - callback(err ? err.code : 0, output); + callback(err ? err.code : 0, stdout, stderr); }); c.stdout.on('data', function(data) { - output += data; - if (!options.silent) + stdout += data; + if (!opts.silent) process.stdout.write(data); }); c.stderr.on('data', function(data) { - output += data; - if (!options.silent) - process.stdout.write(data); + stderr += data; + if (!opts.silent) + process.stderr.write(data); }); return c; @@ -161,29 +186,33 @@ function execAsync(cmd, opts, callback) { //@ ### exec(command [, options] [, callback]) //@ Available options (all `false` by default): //@ -//@ + `async`: Asynchronous execution. Defaults to true if a callback is provided. +//@ + `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. +//@ + and any option available to NodeJS's +//@ [child_process.exec()](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback) //@ //@ Examples: //@ //@ ```javascript -//@ var version = exec('node --version', {silent:true}).output; +//@ 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, output) { +//@ exec('some_long_running_process', function(code, stdout, stderr) { //@ console.log('Exit code:', code); -//@ console.log('Program output:', output); +//@ 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:..., output:... }`, containing the program's -//@ `output` (stdout + stderr) and its exit `code`. Otherwise returns the child process object, and -//@ the `callback` gets the arguments `(code, output)`. +//@ 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 @@ -208,9 +237,13 @@ function _exec(command, options, callback) { async: false }, options); - if (options.async) - return execAsync(command, options, callback); - else - return execSync(command, options); + try { + if (options.async) + return execAsync(command, options, callback); + else + return execSync(command, options); + } catch (e) { + common.error('internal error'); + } } module.exports = _exec; diff --git a/tools/eslint/node_modules/shelljs/src/find.js b/tools/eslint/node_modules/shelljs/src/find.js index d9eeec26a9..c96fb2f7ad 100644 --- a/tools/eslint/node_modules/shelljs/src/find.js +++ b/tools/eslint/node_modules/shelljs/src/find.js @@ -3,7 +3,7 @@ var common = require('./common'); var _ls = require('./ls'); //@ -//@ ### find(path [,path ...]) +//@ ### find(path [, path ...]) //@ ### find(path_array) //@ Examples: //@ diff --git a/tools/eslint/node_modules/shelljs/src/grep.js b/tools/eslint/node_modules/shelljs/src/grep.js index 00c7d6a406..78008ce19e 100644 --- a/tools/eslint/node_modules/shelljs/src/grep.js +++ b/tools/eslint/node_modules/shelljs/src/grep.js @@ -2,8 +2,8 @@ var common = require('./common'); var fs = require('fs'); //@ -//@ ### grep([options ,] regex_filter, file [, file ...]) -//@ ### grep([options ,] regex_filter, file_array) +//@ ### 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. diff --git a/tools/eslint/node_modules/shelljs/src/ln.js b/tools/eslint/node_modules/shelljs/src/ln.js index a7b9701b37..878fda13e2 100644 --- a/tools/eslint/node_modules/shelljs/src/ln.js +++ b/tools/eslint/node_modules/shelljs/src/ln.js @@ -1,15 +1,13 @@ var fs = require('fs'); var path = require('path'); var common = require('./common'); -var os = require('os'); //@ -//@ ### ln(options, source, dest) -//@ ### ln(source, dest) +//@ ### ln([options,] source, dest) //@ Available options: //@ -//@ + `s`: symlink -//@ + `f`: force +//@ + `-s`: symlink +//@ + `-f`: force //@ //@ Examples: //@ @@ -29,13 +27,11 @@ function _ln(options, source, dest) { common.error('Missing <source> and/or <dest>'); } - source = path.resolve(process.cwd(), String(source)); + 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(source)) { - common.error('Source file does not exist', true); - } - if (fs.existsSync(dest)) { if (!options.force) { common.error('Destination file exists', true); @@ -45,9 +41,29 @@ function _ln(options, source, dest) { } if (options.symlink) { - fs.symlinkSync(source, dest, os.platform() === "win32" ? "junction" : null); + 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 { - fs.linkSync(source, dest, os.platform() === "win32" ? "junction" : null); + 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; diff --git a/tools/eslint/node_modules/shelljs/src/ls.js b/tools/eslint/node_modules/shelljs/src/ls.js index 3345db4466..6a54b3a8d8 100644 --- a/tools/eslint/node_modules/shelljs/src/ls.js +++ b/tools/eslint/node_modules/shelljs/src/ls.js @@ -5,12 +5,17 @@ var _cd = require('./cd'); var _pwd = require('./pwd'); //@ -//@ ### ls([options ,] path [,path ...]) -//@ ### ls([options ,] path_array) +//@ ### 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: //@ @@ -18,6 +23,7 @@ var _pwd = require('./pwd'); //@ 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. @@ -25,7 +31,9 @@ function _ls(options, paths) { options = common.parseOptions(options, { 'R': 'recursive', 'A': 'all', - 'a': 'all_deprecated' + 'a': 'all_deprecated', + 'd': 'directory', + 'l': 'long' }); if (options.all_deprecated) { @@ -48,33 +56,49 @@ function _ls(options, paths) { // 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(file)[0] === '.') { + 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') - file = file.replace(/\\/g, '/'); + 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 = fs.statSync(p); + var stats = ls_stat(p); // Simple file? if (stats.isFile()) { - pushFile(p, p); + if (options.long) { + pushFile(stats, p); + } else { + pushFile(p, p); + } return; // continue } // Simple dir? - if (stats.isDirectory()) { + 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; @@ -82,8 +106,8 @@ function _ls(options, paths) { if (options.recursive) { var oldDir = _pwd(); _cd('', p); - if (fs.statSync(file).isDirectory()) - list = list.concat(_ls('-R'+(options.all?'A':''), file+'/*')); + if (fs.statSync(orig_file).isDirectory()) + list = list.concat(_ls('-R'+(options.all?'A':''), orig_file+'/*')); _cd('', oldDir); } }); @@ -104,7 +128,13 @@ function _ls(options, paths) { // Iterate over directory contents fs.readdirSync(dirname).forEach(function(file) { if (file.match(new RegExp(regexp))) { - if (!pushFile(path.normalize(dirname+'/'+file), basename)) + 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? @@ -124,3 +154,15 @@ function _ls(options, paths) { 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; +} diff --git a/tools/eslint/node_modules/shelljs/src/mkdir.js b/tools/eslint/node_modules/shelljs/src/mkdir.js index 5a7088f260..8b4fd99075 100644 --- a/tools/eslint/node_modules/shelljs/src/mkdir.js +++ b/tools/eslint/node_modules/shelljs/src/mkdir.js @@ -20,11 +20,11 @@ function mkdirSyncRecursive(dir) { } //@ -//@ ### mkdir([options ,] dir [, dir ...]) -//@ ### mkdir([options ,] dir_array) +//@ ### mkdir([options,] dir [, dir ...]) +//@ ### mkdir([options,] dir_array) //@ Available options: //@ -//@ + `p`: full path (will create intermediate dirs if necessary) +//@ + `-p`: full path (will create intermediate dirs if necessary) //@ //@ Examples: //@ diff --git a/tools/eslint/node_modules/shelljs/src/mv.js b/tools/eslint/node_modules/shelljs/src/mv.js index 11f9607187..69cc03fe1e 100644 --- a/tools/eslint/node_modules/shelljs/src/mv.js +++ b/tools/eslint/node_modules/shelljs/src/mv.js @@ -3,16 +3,17 @@ var path = require('path'); var common = require('./common'); //@ -//@ ### mv(source [, source ...], dest') -//@ ### mv(source_array, dest') +//@ ### mv([options ,] source [, source ...], dest') +//@ ### mv([options ,] source_array, dest') //@ Available options: //@ -//@ + `f`: force +//@ + `-f`: force (default behavior) +//@ + `-n`: no-clobber //@ //@ Examples: //@ //@ ```javascript -//@ mv('-f', 'file', 'dir/'); +//@ mv('-n', 'file', 'dir/'); //@ mv('file1', 'file2', 'dir/'); //@ mv(['file1', 'file2'], 'dir/'); // same as above //@ ``` @@ -20,7 +21,8 @@ var common = require('./common'); //@ Moves files. The wildcard `*` is accepted. function _mv(options, sources, dest) { options = common.parseOptions(options, { - 'f': 'force' + 'f': '!no_force', + 'n': 'no_force' }); // Get sources, dest @@ -47,7 +49,7 @@ function _mv(options, sources, dest) { 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) + if (exists && stats.isFile() && options.no_force) common.error('dest file already exists: ' + dest); sources.forEach(function(src) { @@ -64,7 +66,7 @@ function _mv(options, sources, dest) { if (fs.existsSync(dest) && fs.statSync(dest).isDirectory()) thisDest = path.normalize(dest + '/' + path.basename(src)); - if (fs.existsSync(thisDest) && !options.force) { + if (fs.existsSync(thisDest) && options.no_force) { common.error('dest file already exists: ' + thisDest, true); return; // skip file } diff --git a/tools/eslint/node_modules/shelljs/src/pwd.js b/tools/eslint/node_modules/shelljs/src/pwd.js index 41727bb918..26cefe0a04 100644 --- a/tools/eslint/node_modules/shelljs/src/pwd.js +++ b/tools/eslint/node_modules/shelljs/src/pwd.js @@ -4,7 +4,7 @@ var common = require('./common'); //@ //@ ### pwd() //@ Returns the current directory. -function _pwd(options) { +function _pwd() { var pwd = path.resolve(process.cwd()); return common.ShellString(pwd); } diff --git a/tools/eslint/node_modules/shelljs/src/rm.js b/tools/eslint/node_modules/shelljs/src/rm.js index bd608cb09a..cf2e95b6d8 100644 --- a/tools/eslint/node_modules/shelljs/src/rm.js +++ b/tools/eslint/node_modules/shelljs/src/rm.js @@ -53,7 +53,7 @@ function rmdirSyncRecursive(dir, force) { while (true) { try { result = fs.rmdirSync(dir); - if (fs.existsSync(dir)) throw { code: "EAGAIN" } + 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 @@ -89,8 +89,8 @@ function isWriteable(file) { } //@ -//@ ### rm([options ,] file [, file ...]) -//@ ### rm([options ,] file_array) +//@ ### rm([options,] file [, file ...]) +//@ ### rm([options,] file_array) //@ Available options: //@ //@ + `-f`: force diff --git a/tools/eslint/node_modules/shelljs/src/sed.js b/tools/eslint/node_modules/shelljs/src/sed.js index 65f7cb49d1..baa385ba11 100644 --- a/tools/eslint/node_modules/shelljs/src/sed.js +++ b/tools/eslint/node_modules/shelljs/src/sed.js @@ -2,7 +2,8 @@ var common = require('./common'); var fs = require('fs'); //@ -//@ ### sed([options ,] search_regex, replacement, file) +//@ ### 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!_ @@ -14,9 +15,9 @@ var fs = require('fs'); //@ sed(/.*DELETE_THIS_LINE.*\n/, '', 'source.js'); //@ ``` //@ -//@ Reads an input string from `file` and performs a JavaScript `replace()` on the input +//@ 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, file) { +function _sed(options, regex, replacement, files) { options = common.parseOptions(options, { 'i': 'inplace' }); @@ -28,16 +29,36 @@ function _sed(options, regex, replacement, file) { else common.error('invalid replacement string'); - if (!file) - common.error('no file given'); + // Convert all search strings to RegExp + if (typeof regex === 'string') + regex = RegExp(regex); - if (!fs.existsSync(file)) - common.error('no such file or directory: ' + file); + if (!files) + common.error('no files given'); - var result = fs.readFileSync(file, 'utf8').replace(regex, replacement); - if (options.inplace) - fs.writeFileSync(file, result, 'utf8'); + if (typeof files === 'string') + files = [].slice.call(arguments, 3); + // if it's array leave it as it is - return common.ShellString(result); + 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; diff --git a/tools/eslint/node_modules/shelljs/src/set.js b/tools/eslint/node_modules/shelljs/src/set.js new file mode 100644 index 0000000000..19e26d979d --- /dev/null +++ b/tools/eslint/node_modules/shelljs/src/set.js @@ -0,0 +1,49 @@ +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; diff --git a/tools/eslint/node_modules/shelljs/src/tempdir.js b/tools/eslint/node_modules/shelljs/src/tempdir.js index 45953c24e9..79b949f0d4 100644 --- a/tools/eslint/node_modules/shelljs/src/tempdir.js +++ b/tools/eslint/node_modules/shelljs/src/tempdir.js @@ -37,7 +37,8 @@ function _tempDir() { if (state.tempDir) return state.tempDir; // from cache - state.tempDir = writeableDir(os.tempDir && os.tempDir()) || // node 0.8+ + 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']) || diff --git a/tools/eslint/node_modules/shelljs/src/test.js b/tools/eslint/node_modules/shelljs/src/test.js index 8a4ac7d4d1..068a1ce06e 100644 --- a/tools/eslint/node_modules/shelljs/src/test.js +++ b/tools/eslint/node_modules/shelljs/src/test.js @@ -10,7 +10,7 @@ var fs = require('fs'); //@ + `'-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 +//@ + `'-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 //@ diff --git a/tools/eslint/node_modules/shelljs/src/to.js b/tools/eslint/node_modules/shelljs/src/to.js index f0299993a7..65d6d54af9 100644 --- a/tools/eslint/node_modules/shelljs/src/to.js +++ b/tools/eslint/node_modules/shelljs/src/to.js @@ -22,6 +22,7 @@ function _to(options, file) { try { fs.writeFileSync(file, this.toString(), 'utf8'); + return this; } catch(e) { common.error('could not write to file (code '+e.code+'): '+file, true); } diff --git a/tools/eslint/node_modules/shelljs/src/toEnd.js b/tools/eslint/node_modules/shelljs/src/toEnd.js index f6d099d9a3..bf29a6526d 100644 --- a/tools/eslint/node_modules/shelljs/src/toEnd.js +++ b/tools/eslint/node_modules/shelljs/src/toEnd.js @@ -22,6 +22,7 @@ function _toEnd(options, file) { try { fs.appendFileSync(file, this.toString(), 'utf8'); + return this; } catch(e) { common.error('could not append to file (code '+e.code+'): '+file, true); } diff --git a/tools/eslint/node_modules/shelljs/src/touch.js b/tools/eslint/node_modules/shelljs/src/touch.js new file mode 100644 index 0000000000..bbc2c19686 --- /dev/null +++ b/tools/eslint/node_modules/shelljs/src/touch.js @@ -0,0 +1,109 @@ +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; + } +} diff --git a/tools/eslint/node_modules/shelljs/src/which.js b/tools/eslint/node_modules/shelljs/src/which.js index 2822ecfb14..d17634ee94 100644 --- a/tools/eslint/node_modules/shelljs/src/which.js +++ b/tools/eslint/node_modules/shelljs/src/which.js @@ -2,10 +2,12 @@ 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) { - for (i=1;i<2;i++) {} - if (!p) return []; @@ -16,7 +18,7 @@ function splitPath(p) { } function checkPath(path) { - return fs.existsSync(path) && fs.statSync(path).isDirectory() == false; + return fs.existsSync(path) && !fs.statSync(path).isDirectory(); } //@ @@ -28,7 +30,8 @@ function checkPath(path) { //@ var nodeExec = which('node'); //@ ``` //@ -//@ Searches for `command` in the system's PATH. On Windows looks for `.exe`, `.cmd`, and `.bat` extensions. +//@ 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) @@ -45,30 +48,42 @@ function _which(options, cmd) { if (where) return; // already found it - var attempt = path.resolve(dir + '/' + cmd); - if (checkPath(attempt)) { - where = attempt; - return; - } + var attempt = path.resolve(dir, cmd); if (common.platform === 'win') { - var baseAttempt = attempt; - attempt = baseAttempt + '.exe'; - if (checkPath(attempt)) { - where = attempt; - return; + 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; + } } - attempt = baseAttempt + '.cmd'; - if (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; + } } - attempt = baseAttempt + '.bat'; + } else { + // Assume it's Unix-like if (checkPath(attempt)) { where = attempt; return; } - } // if 'win' + } }); } |