Comparing version 0.7.6 to 0.7.7
# Change Log | ||
## [Unreleased](https://github.com/shelljs/shelljs/tree/HEAD) | ||
## [v0.7.6](https://github.com/shelljs/shelljs/tree/v0.7.6) (2017-01-08) | ||
[Full Changelog](https://github.com/shelljs/shelljs/compare/v0.7.5...v0.7.6) | ||
[Full Changelog](https://github.com/shelljs/shelljs/compare/v0.7.5...HEAD) | ||
**Closed issues:** | ||
- unable to execute ionic command with shell js [\#640](https://github.com/shelljs/shelljs/issues/640) | ||
- How to increase ShellJS buffer size? [\#639](https://github.com/shelljs/shelljs/issues/639) | ||
- mkdir fails with non-normalized path [\#634](https://github.com/shelljs/shelljs/issues/634) | ||
- Move execPath into common [\#633](https://github.com/shelljs/shelljs/issues/633) | ||
- QUESTION: Feedback while an operation is running? [\#629](https://github.com/shelljs/shelljs/issues/629) | ||
@@ -38,2 +41,3 @@ - Test setup/cleanup is broken [\#621](https://github.com/shelljs/shelljs/issues/621) | ||
- \[ Feature idea \] synchronous sleep command [\#441](https://github.com/shelljs/shelljs/issues/441) | ||
- Improve test coverage [\#347](https://github.com/shelljs/shelljs/issues/347) | ||
- Add a way to prevent shell-expansion on commands \(this issue is not for exec\) [\#345](https://github.com/shelljs/shelljs/issues/345) | ||
@@ -48,2 +52,6 @@ - Chown [\#183](https://github.com/shelljs/shelljs/issues/183) | ||
- refactor: add config.reset\(\) and .resetForTesting\(\) [\#641](https://github.com/shelljs/shelljs/pull/641) ([nfischer](https://github.com/nfischer)) | ||
- chore: set up test coverage [\#638](https://github.com/shelljs/shelljs/pull/638) ([nfischer](https://github.com/nfischer)) | ||
- refactor: create common.execPath [\#636](https://github.com/shelljs/shelljs/pull/636) ([nfischer](https://github.com/nfischer)) | ||
- fix: allow non-normalized paths as input to mkdir [\#635](https://github.com/shelljs/shelljs/pull/635) ([nfischer](https://github.com/nfischer)) | ||
- Finalize moving to ava [\#630](https://github.com/shelljs/shelljs/pull/630) ([freitagbr](https://github.com/freitagbr)) | ||
@@ -50,0 +58,0 @@ - test: refactor pushd tests to AVA [\#627](https://github.com/shelljs/shelljs/pull/627) ([nfischer](https://github.com/nfischer)) |
{ | ||
"name": "shelljs", | ||
"version": "0.7.6", | ||
"version": "0.7.7", | ||
"description": "Portable Unix shell commands for Node.js", | ||
@@ -27,3 +27,3 @@ "keywords": [ | ||
"files": [ | ||
"commands.json", | ||
"commands.js", | ||
"global.js", | ||
@@ -44,2 +44,3 @@ "make.js", | ||
"changelog": "shelljs-changelog", | ||
"codecov": "codecov", | ||
"release:major": "shelljs-release major", | ||
@@ -59,2 +60,3 @@ "release:minor": "shelljs-release minor", | ||
"ava": "^0.16.0", | ||
"codecov": "^1.0.1", | ||
"coffee-script": "^1.10.0", | ||
@@ -61,0 +63,0 @@ "eslint": "^2.0.0", |
108
README.md
@@ -6,17 +6,19 @@ # ShellJS - Unix shell commands for Node.js | ||
[![AppVeyor](https://img.shields.io/appveyor/ci/shelljs/shelljs/master.svg?style=flat-square&label=windows)](https://ci.appveyor.com/project/shelljs/shelljs/branch/master) | ||
[![Codecov](https://img.shields.io/codecov/c/github/shelljs/shelljs/master.svg?style=flat-square&label=coverage)](https://codecov.io/gh/shelljs/shelljs) | ||
[![npm version](https://img.shields.io/npm/v/shelljs.svg?style=flat-square)](https://www.npmjs.com/package/shelljs) | ||
[![npm downloads](https://img.shields.io/npm/dm/shelljs.svg?style=flat-square)](https://www.npmjs.com/package/shelljs) | ||
ShellJS is a portable **(Windows/Linux/OS X)** implementation of Unix shell commands on top of the | ||
Node.js API. You can use it to eliminate your shell script's dependency on Unix while still keeping | ||
its familiar and powerful commands. You can also install it globally so you can run it from outside | ||
Node projects - say goodbye to those gnarly Bash scripts! | ||
ShellJS is a portable **(Windows/Linux/OS X)** implementation of Unix shell | ||
commands on top of the Node.js API. You can use it to eliminate your shell | ||
script's dependency on Unix while still keeping its familiar and powerful | ||
commands. You can also install it globally so you can run it from outside Node | ||
projects - say goodbye to those gnarly Bash scripts! | ||
ShellJS is proudly tested on every node release since `v0.11`! | ||
The project is [unit-tested](http://travis-ci.org/shelljs/shelljs) and battled-tested in projects like: | ||
The project is [unit-tested](http://travis-ci.org/shelljs/shelljs) and battle-tested in projects like: | ||
+ [PDF.js](http://github.com/mozilla/pdf.js) - Firefox's next-gen PDF reader | ||
+ [Firebug](http://getfirebug.com/) - Firefox's infamous debugger | ||
+ [JSHint](http://jshint.com) - Most popular JavaScript linter | ||
+ [JSHint](http://jshint.com) & [ESLint](http://eslint.org/) - popular JavaScript linters | ||
+ [Zepto](http://zeptojs.com) - jQuery-compatible JavaScript library for modern browsers | ||
@@ -27,7 +29,7 @@ + [Yeoman](http://yeoman.io/) - Web application stack and development tool | ||
If you have feedback, suggestions, or need help, feel free to post in our [issue tracker](https://github.com/shelljs/shelljs/issues). | ||
If you have feedback, suggestions, or need help, feel free to post in our [issue | ||
tracker](https://github.com/shelljs/shelljs/issues). | ||
Think ShellJS is cool? Check out some related projects (like | ||
[cash](https://github.com/dthree/cash)--a javascript-based POSIX shell) | ||
in our [Wiki page](https://github.com/shelljs/shelljs/wiki)! | ||
Think ShellJS is cool? Check out some related projects in our [Wiki | ||
page](https://github.com/shelljs/shelljs/wiki)! | ||
@@ -68,75 +70,39 @@ Upgrading from an older version? Check out our [breaking | ||
If the global option `-g` is specified, the binary `shjs` will be installed. This makes it possible to | ||
run ShellJS scripts much like any shell script from the command line, i.e. without requiring a `node_modules` folder: | ||
```bash | ||
$ shjs my_script | ||
``` | ||
## Examples | ||
### JavaScript | ||
```javascript | ||
require('shelljs/global'); | ||
var shell = require('shelljs'); | ||
if (!which('git')) { | ||
echo('Sorry, this script requires git'); | ||
exit(1); | ||
if (!shell.which('git')) { | ||
shell.echo('Sorry, this script requires git'); | ||
shell.exit(1); | ||
} | ||
// Copy files to release dir | ||
rm('-rf', 'out/Release'); | ||
cp('-R', 'stuff/', 'out/Release'); | ||
shell.rm('-rf', 'out/Release'); | ||
shell.cp('-R', 'stuff/', 'out/Release'); | ||
// Replace macros in each .js file | ||
cd('lib'); | ||
ls('*.js').forEach(function(file) { | ||
sed('-i', 'BUILD_VERSION', 'v0.1.2', file); | ||
sed('-i', /^.*REMOVE_THIS_LINE.*$/, '', file); | ||
sed('-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, cat('macro.js'), file); | ||
shell.cd('lib'); | ||
shell.ls('*.js').forEach(function (file) { | ||
shell.sed('-i', 'BUILD_VERSION', 'v0.1.2', file); | ||
shell.sed('-i', /^.*REMOVE_THIS_LINE.*$/, '', file); | ||
shell.sed('-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, shell.cat('macro.js'), file); | ||
}); | ||
cd('..'); | ||
shell.cd('..'); | ||
// Run external tool synchronously | ||
if (exec('git commit -am "Auto-commit"').code !== 0) { | ||
echo('Error: Git commit failed'); | ||
exit(1); | ||
if (shell.exec('git commit -am "Auto-commit"').code !== 0) { | ||
shell.echo('Error: Git commit failed'); | ||
shell.exit(1); | ||
} | ||
``` | ||
### CoffeeScript | ||
CoffeeScript is also supported automatically: | ||
```coffeescript | ||
require 'shelljs/global' | ||
if not which 'git' | ||
echo 'Sorry, this script requires git' | ||
exit 1 | ||
# Copy files to release dir | ||
rm '-rf', 'out/Release' | ||
cp '-R', 'stuff/', 'out/Release' | ||
# Replace macros in each .js file | ||
cd 'lib' | ||
for file in ls '*.js' | ||
sed '-i', 'BUILD_VERSION', 'v0.1.2', file | ||
sed '-i', /^.*REMOVE_THIS_LINE.*$/, '', file | ||
sed '-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, cat('macro.js'), file | ||
cd '..' | ||
# Run external tool synchronously | ||
if (exec 'git commit -am "Auto-commit"').code != 0 | ||
echo 'Error: Git commit failed' | ||
exit 1 | ||
``` | ||
## Global vs. Local | ||
The example above uses the convenience script `shelljs/global` to reduce verbosity. If polluting your global namespace is not desirable, simply require `shelljs`. | ||
We no longer recommend using a global-import for ShellJS (i.e. | ||
`require('shelljs/global')`). While still supported for convenience, this | ||
pollutes the global namespace, and should therefore only be used with caution. | ||
Example: | ||
Instead, we recommend a local import (standard for npm packages): | ||
@@ -183,4 +149,4 @@ ```javascript | ||
### chmod(octal_mode || octal_string, file) | ||
### chmod(symbolic_mode, file) | ||
### chmod([options,] octal_mode || octal_string, file) | ||
### chmod([options,] symbolic_mode, file) | ||
@@ -199,2 +165,3 @@ Available options: | ||
chmod('u+x', '/Users/brandon'); | ||
chmod('-R', 'a-w', '/Users/brandon'); | ||
``` | ||
@@ -318,3 +285,3 @@ | ||
+ `silent`: Do not echo program output to console. | ||
+ and any option available to NodeJS's | ||
+ and any option available to Node.js's | ||
[child_process.exec()](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback) | ||
@@ -426,2 +393,3 @@ | ||
+ `-A`: all files (include files beginning with `.`, except for `.` and `..`) | ||
+ `-L`: follow symlinks | ||
+ `-d`: list directories themselves, not their contents | ||
@@ -822,4 +790,4 @@ + `-l`: list objects representing each file, each with fields containing `ls | ||
| [![Nate Fischer](https://avatars.githubusercontent.com/u/5801521?s=130)](https://github.com/nfischer) | [![Ari Porad](https://avatars1.githubusercontent.com/u/1817508?v=3&s=130)](http://github.com/ariporad) | | ||
| [![Nate Fischer](https://avatars.githubusercontent.com/u/5801521?s=130)](https://github.com/nfischer) | [![Brandon Freitag](https://avatars1.githubusercontent.com/u/5988055?v=3&s=130)](http://github.com/freitagbr) | | ||
|:---:|:---:| | ||
| [Nate Fischer](https://github.com/nfischer) | [Ari Porad](http://github.com/ariporad) | | ||
| [Nate Fischer](https://github.com/nfischer) | [Brandon Freitag](http://github.com/freitagbr) | |
@@ -24,3 +24,3 @@ // | ||
// Load all default commands | ||
require('./commands.json').forEach(function (command) { | ||
require('./commands').forEach(function (command) { | ||
require('./src/' + command); | ||
@@ -27,0 +27,0 @@ }); |
@@ -24,3 +24,3 @@ var common = require('./common'); | ||
TYPE_MASK: parseInt('0770000', 8) | ||
TYPE_MASK: parseInt('0770000', 8), | ||
}; | ||
@@ -30,3 +30,3 @@ }({ | ||
WRITE: 2, | ||
READ: 4 | ||
READ: 4, | ||
})); | ||
@@ -38,4 +38,4 @@ | ||
//@ | ||
//@ ### chmod(octal_mode || octal_string, file) | ||
//@ ### chmod(symbolic_mode, file) | ||
//@ ### chmod([options,] octal_mode || octal_string, file) | ||
//@ ### chmod([options,] symbolic_mode, file) | ||
//@ | ||
@@ -54,2 +54,3 @@ //@ Available options: | ||
//@ chmod('u+x', '/Users/brandon'); | ||
//@ chmod('-R', 'a-w', '/Users/brandon'); | ||
//@ ``` | ||
@@ -80,3 +81,3 @@ //@ | ||
'c': 'changes', | ||
'v': 'verbose' | ||
'v': 'verbose', | ||
}); | ||
@@ -83,0 +84,0 @@ |
@@ -63,3 +63,3 @@ // Ignore warning about 'new String()' | ||
currentCmd: 'shell.js', | ||
tempDir: null | ||
tempDir: null, | ||
}; | ||
@@ -76,3 +76,10 @@ exports.state = state; | ||
// Reliably test if something is any sort of javascript object | ||
function isObject(a) { | ||
return typeof a === 'object' && a !== null; | ||
} | ||
exports.isObject = isObject; | ||
function log() { | ||
/* istanbul ignore next */ | ||
if (!config.silent) { | ||
@@ -84,2 +91,13 @@ console.error.apply(console, arguments); | ||
// Converts strings to be equivalent across all platforms. Primarily responsible | ||
// for making sure we use '/' instead of '\' as path separators, but this may be | ||
// expanded in the future if necessary | ||
function convertErrorOutput(msg) { | ||
if (typeof msg !== 'string') { | ||
throw new TypeError('input must be a string'); | ||
} | ||
return msg.replace(/\\/g, '/'); | ||
} | ||
exports.convertErrorOutput = convertErrorOutput; | ||
// Shows error message. Throws if config.fatal is true | ||
@@ -97,5 +115,5 @@ function error(msg, _code, options) { | ||
if (typeof _code === 'number' && typeof options === 'object') { | ||
if (typeof _code === 'number' && isObject(options)) { | ||
options.code = _code; | ||
} else if (typeof _code === 'object') { // no 'code' | ||
} else if (isObject(_code)) { // no 'code' | ||
options = _code; | ||
@@ -111,3 +129,3 @@ } else if (typeof _code === 'number') { // no 'options' | ||
var logEntry = options.prefix + msg; | ||
var logEntry = convertErrorOutput(options.prefix + msg); | ||
state.error = state.error ? state.error + '\n' : ''; | ||
@@ -123,3 +141,3 @@ state.error += logEntry; | ||
msg: 'earlyExit', | ||
retValue: (new ShellString('', state.error, state.errorCode)) | ||
retValue: (new ShellString('', state.error, state.errorCode)), | ||
}; | ||
@@ -181,3 +199,10 @@ } | ||
function parseOptions(opt, map, errorOptions) { | ||
if (!map) error('parseOptions() internal error: no map given'); | ||
// Validate input | ||
if (typeof opt !== 'string' && !isObject(opt)) { | ||
throw new Error('options must be strings or key-value pairs'); | ||
} else if (!isObject(map)) { | ||
throw new Error('parseOptions() internal error: map must be an object'); | ||
} else if (errorOptions && !isObject(errorOptions)) { | ||
throw new Error('parseOptions() internal error: errorOptions must be object'); | ||
} | ||
@@ -187,13 +212,13 @@ // All options are false by default | ||
Object.keys(map).forEach(function (letter) { | ||
if (map[letter][0] !== '!') { | ||
options[map[letter]] = false; | ||
var optName = map[letter]; | ||
if (optName[0] !== '!') { | ||
options[optName] = false; | ||
} | ||
}); | ||
if (!opt) return options; // defaults | ||
if (opt === '') return options; // defaults | ||
var optionName; | ||
if (typeof opt === 'string') { | ||
if (opt[0] !== '-') { | ||
return options; | ||
error("Options string must start with a '-'", errorOptions || {}); | ||
} | ||
@@ -206,3 +231,3 @@ | ||
if (c in map) { | ||
optionName = map[c]; | ||
var optionName = map[c]; | ||
if (optionName[0] === '!') { | ||
@@ -213,9 +238,7 @@ options[optionName.slice(1)] = false; | ||
} | ||
} else if (typeof errorOptions === 'object') { | ||
error('option not recognized: ' + c, errorOptions); | ||
} else { | ||
error('option not recognized: ' + c); | ||
error('option not recognized: ' + c, errorOptions || {}); | ||
} | ||
}); | ||
} else if (typeof opt === 'object') { | ||
} else { // opt is an Object | ||
Object.keys(opt).forEach(function (key) { | ||
@@ -225,14 +248,8 @@ // key is a string of the form '-r', '-d', etc. | ||
if (c in map) { | ||
optionName = map[c]; | ||
var optionName = map[c]; | ||
options[optionName] = opt[key]; // assign the given value | ||
} else if (typeof errorOptions === 'object') { | ||
error('option not recognized: ' + c, errorOptions); | ||
} else { | ||
error('option not recognized: ' + c); | ||
error('option not recognized: ' + c, errorOptions || {}); | ||
} | ||
}); | ||
} else if (typeof errorOptions === 'object') { | ||
error('options must be strings or key-value pairs', errorOptions); | ||
} else { | ||
error('options must be strings or key-value pairs'); | ||
} | ||
@@ -273,2 +290,3 @@ return options; | ||
// Try to override file permission | ||
/* istanbul ignore next */ | ||
if (e.code === 'EPERM') { | ||
@@ -330,3 +348,3 @@ fs.chmodSync(file, '0666'); | ||
} else { // and this branch is for everything else | ||
if (args[0] instanceof Object && args[0].constructor.name === 'Object') { | ||
if (isObject(args[0]) && args[0].constructor.name === 'Object') { | ||
// a no-op, allowing the syntax `touch({'-r': file}, ...)` | ||
@@ -351,3 +369,3 @@ } else if (args.length === 0 || typeof args[0] !== 'string' || args[0].length <= 1 || args[0][0] !== '-') { | ||
args = args.map(function (arg) { | ||
if (arg instanceof Object && arg.constructor.name === 'String') { | ||
if (isObject(arg) && arg.constructor.name === 'String') { | ||
return arg.toString(); | ||
@@ -375,3 +393,3 @@ } | ||
// parse options if options are provided | ||
if (typeof options.cmdOptions === 'object') { | ||
if (isObject(options.cmdOptions)) { | ||
args[0] = parseOptions(args[0], options.cmdOptions); | ||
@@ -382,2 +400,3 @@ } | ||
} catch (e) { | ||
/* istanbul ignore else */ | ||
if (e.msg === 'earlyExit') { | ||
@@ -391,2 +410,3 @@ retValue = e.retValue; | ||
} catch (e) { | ||
/* istanbul ignore next */ | ||
if (!state.error) { | ||
@@ -393,0 +413,0 @@ // If state.error hasn't been set it's an error thrown by Node, not us - probably a bug... |
@@ -57,2 +57,3 @@ var fs = require('fs'); | ||
} catch (e) { | ||
/* istanbul ignore next */ | ||
common.error('copyFileSync: could not read src file (' + srcFile + ')'); | ||
@@ -64,2 +65,3 @@ } | ||
} catch (e) { | ||
/* istanbul ignore next */ | ||
common.error('copyFileSync: could not write to dest file (code=' + e.code + '):' + destFile); | ||
@@ -248,2 +250,3 @@ } | ||
} catch (e) { | ||
/* istanbul ignore next */ | ||
common.error("cannot create directory '" + dest + "': No such file or directory"); | ||
@@ -266,7 +269,14 @@ } | ||
if (path.relative(src, thisDest) === '') { | ||
// a file cannot be copied to itself, but we want to continue copying other files | ||
common.error("'" + thisDest + "' and '" + src + "' are the same file", { continue: true }); | ||
return; | ||
} | ||
copyFileSync(src, thisDest, options); | ||
} | ||
}); // forEach(src) | ||
return new common.ShellString('', common.state.error, common.state.errorCode); | ||
} | ||
module.exports = _cp; |
@@ -66,3 +66,3 @@ var common = require('./common'); | ||
options = common.parseOptions(options, { | ||
'n': 'no-cd' | ||
'n': 'no-cd', | ||
}); | ||
@@ -133,3 +133,3 @@ | ||
options = common.parseOptions(options, { | ||
'n': 'no-cd' | ||
'n': 'no-cd', | ||
}); | ||
@@ -177,3 +177,3 @@ | ||
options = common.parseOptions(options, { | ||
'c': 'clear' | ||
'c': 'clear', | ||
}); | ||
@@ -180,0 +180,0 @@ |
@@ -37,3 +37,3 @@ var common = require('./common'); | ||
env: process.env, | ||
maxBuffer: DEFAULT_MAXBUFFER_SIZE | ||
maxBuffer: DEFAULT_MAXBUFFER_SIZE, | ||
}, opts); | ||
@@ -194,3 +194,3 @@ | ||
env: process.env, | ||
maxBuffer: DEFAULT_MAXBUFFER_SIZE | ||
maxBuffer: DEFAULT_MAXBUFFER_SIZE, | ||
}, opts); | ||
@@ -233,3 +233,3 @@ | ||
//@ + `silent`: Do not echo program output to console. | ||
//@ + and any option available to NodeJS's | ||
//@ + and any option available to Node.js's | ||
//@ [child_process.exec()](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback) | ||
@@ -285,3 +285,3 @@ //@ | ||
silent: common.config.silent, | ||
async: false | ||
async: false, | ||
}, options); | ||
@@ -288,0 +288,0 @@ |
@@ -43,5 +43,12 @@ var fs = require('fs'); | ||
paths.forEach(function (file) { | ||
var stat; | ||
try { | ||
stat = fs.statSync(file); | ||
} catch (e) { | ||
common.error('no such file or directory: ' + file); | ||
} | ||
pushFile(file); | ||
if (fs.statSync(file).isDirectory()) { | ||
if (stat.isDirectory()) { | ||
_ls({ recursive: true, all: true }, file).forEach(function (subfile) { | ||
@@ -48,0 +55,0 @@ pushFile(path.join(file, subfile)); |
@@ -6,3 +6,3 @@ var path = require('path'); | ||
var globPatternRecursive = path.sep + '**' + path.sep + '*'; | ||
var globPatternRecursive = path.sep + '**'; | ||
@@ -13,2 +13,3 @@ common.register('ls', _ls, { | ||
'A': 'all', | ||
'L': 'link', | ||
'a': 'all_deprecated', | ||
@@ -27,2 +28,3 @@ 'd': 'directory', | ||
//@ + `-A`: all files (include files beginning with `.`, except for `.` and `..`) | ||
//@ + `-L`: follow symlinks | ||
//@ + `-d`: list directories themselves, not their contents | ||
@@ -66,3 +68,3 @@ //@ + `-l`: list objects representing each file, each with fields containing `ls | ||
if (options.long) { | ||
stat = stat || fs.lstatSync(abs); | ||
stat = stat || (options.link ? fs.statSync(abs) : fs.lstatSync(abs)); | ||
list.push(addLsAttributes(relName, stat)); | ||
@@ -79,3 +81,3 @@ } else { | ||
try { | ||
stat = fs.lstatSync(p); | ||
stat = options.link ? fs.statSync(p) : fs.lstatSync(p); | ||
} catch (e) { | ||
@@ -90,5 +92,8 @@ common.error('no such file or directory: ' + p, 2, { continue: true }); | ||
// use glob, because it's simple | ||
glob.sync(p + globPatternRecursive, { dot: options.all }) | ||
glob.sync(p + globPatternRecursive, { dot: options.all, follow: options.link }) | ||
.forEach(function (item) { | ||
pushFile(item, path.relative(p, item)); | ||
// Glob pattern returns the directory itself and needs to be filtered out. | ||
if (path.relative(p, item)) { | ||
pushFile(item, path.relative(p, item)); | ||
} | ||
}); | ||
@@ -95,0 +100,0 @@ } else if (options.all) { |
@@ -86,2 +86,3 @@ var common = require('./common'); | ||
} else { | ||
/* istanbul ignore next */ | ||
throw e; | ||
@@ -88,0 +89,0 @@ } |
@@ -41,2 +41,3 @@ var fs = require('fs'); | ||
} else { | ||
// TODO(nate): figure out if we actually need this line | ||
common.error('invalid arguments'); | ||
@@ -86,5 +87,8 @@ } | ||
} catch (e) { | ||
if (e.code === 'EXDEV') { // external partition | ||
// if either of these fails, the appropriate error message will bubble | ||
// up to the top level automatically | ||
/* istanbul ignore next */ | ||
if (e.code === 'EXDEV') { | ||
// If we're trying to `mv` to an external partition, we'll actually need | ||
// to perform a copy and then clean up the original file. If either the | ||
// copy or the rm fails with an exception, we should allow this | ||
// exception to pass up to the top level. | ||
cp('-r', src, thisDest); | ||
@@ -91,0 +95,0 @@ rm('-rf', src); |
@@ -37,3 +37,6 @@ var common = require('./common'); | ||
} catch (e) { | ||
common.error('could not remove file (code ' + e.code + '): ' + file, { continue: true }); | ||
/* istanbul ignore next */ | ||
common.error('could not remove file (code ' + e.code + '): ' + file, { | ||
continue: true, | ||
}); | ||
} | ||
@@ -59,2 +62,3 @@ } | ||
} catch (er) { | ||
/* istanbul ignore next */ | ||
// In addition to error codes, also check if the directory still exists and loop again if true | ||
@@ -142,3 +146,3 @@ if (process.platform === 'win32' && (er.code === 'ENOTEMPTY' || er.code === 'EBUSY' || er.code === 'EPERM' || er.code === 'EAGAIN')) { | ||
} | ||
} else if (stats.isSymbolicLink()) { | ||
} else if (stats.isSymbolicLink() || stats.isFIFO()) { | ||
common.unlinkSync(file); | ||
@@ -145,0 +149,0 @@ } |
@@ -37,3 +37,3 @@ var common = require('./common'); | ||
'v': 'verbose', | ||
'f': 'noglob' | ||
'f': 'noglob', | ||
}); | ||
@@ -40,0 +40,0 @@ |
@@ -22,2 +22,3 @@ var common = require('./common'); | ||
} catch (e) { | ||
/* istanbul ignore next */ | ||
return false; | ||
@@ -24,0 +25,0 @@ } |
@@ -75,8 +75,11 @@ var common = require('./common'); | ||
/* istanbul ignore next */ | ||
if (options.pipe) return stats.isFIFO(); | ||
/* istanbul ignore next */ | ||
if (options.socket) return stats.isSocket(); | ||
/* istanbul ignore next */ | ||
return false; // fallback | ||
} // test | ||
module.exports = _test; |
@@ -33,2 +33,3 @@ var common = require('./common'); | ||
} catch (e) { | ||
/* istanbul ignore next */ | ||
common.error('could not write to file (code ' + e.code + '): ' + file, { continue: true }); | ||
@@ -35,0 +36,0 @@ } |
@@ -32,2 +32,3 @@ var common = require('./common'); | ||
} catch (e) { | ||
/* istanbul ignore next */ | ||
common.error('could not append to file (code ' + e.code + '): ' + file, { continue: true }); | ||
@@ -34,0 +35,0 @@ } |
@@ -7,2 +7,5 @@ var common = require('./common'); | ||
allowGlobbing: false, | ||
cmdOptions: { | ||
'a': 'all', | ||
}, | ||
}); | ||
@@ -16,9 +19,3 @@ | ||
function splitPath(p) { | ||
if (!p) return []; | ||
if (common.platform === 'win') { | ||
return p.split(';'); | ||
} else { | ||
return p.split(':'); | ||
} | ||
return p ? p.split(path.delimiter) : []; | ||
} | ||
@@ -47,56 +44,58 @@ | ||
var pathArray = splitPath(pathEnv); | ||
var where = null; | ||
var queryMatches = []; | ||
// No relative/absolute paths provided? | ||
if (cmd.search(/\//) === -1) { | ||
if (cmd.indexOf('/') === -1) { | ||
// Assume that there are no extensions to append to queries (this is the | ||
// case for unix) | ||
var pathExtArray = ['']; | ||
if (common.platform === 'win') { | ||
// 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; | ||
pathExtArray = splitPath(pathExtEnv.toUpperCase()); | ||
} | ||
// Search for command in PATH | ||
pathArray.forEach(function (dir) { | ||
if (where) return; // already found it | ||
for (var k = 0; k < pathArray.length; k++) { | ||
// already found it | ||
if (queryMatches.length > 0 && !options.all) break; | ||
var attempt = path.resolve(dir, cmd); | ||
var attempt = path.resolve(pathArray[k], 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 match = attempt.match(/\.[^<>:"/\|?*.]+$/); | ||
if (match && pathExtArray.indexOf(match[0]) >= 0) { // this is Windows-only | ||
// The user typed a query with the file extension, like | ||
// `which('node.exe')` | ||
if (checkPath(attempt)) { | ||
queryMatches.push(attempt); | ||
break; | ||
} | ||
} else { // All-platforms | ||
// Cycle through the PATHEXT array, and check each extension | ||
// Note: the array is always [''] on Unix | ||
for (var i = 0; i < pathExtArray.length; i++) { | ||
var ext = pathExtArray[i]; | ||
if (attempt.slice(-ext.length) === ext && checkPath(attempt)) { | ||
where = attempt; | ||
return; | ||
var newAttempt = attempt + ext; | ||
if (checkPath(newAttempt)) { | ||
queryMatches.push(newAttempt); | ||
break; | ||
} | ||
} | ||
// 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; | ||
} | ||
} | ||
}); | ||
} | ||
} else if (checkPath(cmd)) { // a valid absolute or relative path | ||
queryMatches.push(path.resolve(cmd)); | ||
} | ||
// Command not found anywhere? | ||
if (!checkPath(cmd) && !where) return null; | ||
where = where || path.resolve(cmd); | ||
return where; | ||
if (queryMatches.length > 0) { | ||
return options.all ? queryMatches : queryMatches[0]; | ||
} | ||
return options.all ? [] : null; | ||
} | ||
module.exports = _which; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
203999
42
3008
1
11
786