pax_global_header00006660000000000000000000000064130043126220014503gustar00rootroot0000000000000052 comment=1a15022f2747d322d771dd7ae0c00840e469a52a shelljs-0.7.5/000077500000000000000000000000001300431262200131605ustar00rootroot00000000000000shelljs-0.7.5/.documentup.json000066400000000000000000000000661300431262200163160ustar00rootroot00000000000000{ "name": "ShellJS", "twitter": [ "r2r" ] } shelljs-0.7.5/.editorconfig000066400000000000000000000003331300431262200156340ustar00rootroot00000000000000# editorconfig.org root = true [*] charset = utf-8 end_of_line = lf indent_size = 2 indent_style = space insert_final_newline = true trim_trailing_whitespace = true [*.{md,markdown}] trim_trailing_whitespace = false shelljs-0.7.5/.eslintignore000066400000000000000000000000461300431262200156630ustar00rootroot00000000000000test/resources/ node_modules/ make.js shelljs-0.7.5/.eslintrc.json000066400000000000000000000013421300431262200157540ustar00rootroot00000000000000{ "env": { "node": true }, "extends": "airbnb-base/legacy", "rules": { "comma-dangle": 0, "global-require": 0, "vars-on-top": 0, "spaced-comment": [2, "always", { "markers": ["@", "@include"], "exceptions": ["@"] }], "no-param-reassign": 0, "no-console": 0, "curly": [2, "multi-line"], "func-names": 0, "quote-props": 0, "no-underscore-dangle": 0, "max-len": 0, "no-use-before-define": 0, "no-empty": 0, "no-else-return": 0, "no-throw-literal": 0, "newline-per-chained-call": 0, "consistent-return": 0, "no-mixed-operators": 0, "no-prototype-builtins": 0, "new-cap": [2, { "capIsNewExceptions": [ "ShellString" ]} ] } } shelljs-0.7.5/.gitattributes000066400000000000000000000000161300431262200160500ustar00rootroot00000000000000* text eol=lf shelljs-0.7.5/.github/000077500000000000000000000000001300431262200145205ustar00rootroot00000000000000shelljs-0.7.5/.github/ISSUE_TEMPLATE.md000066400000000000000000000004361300431262200172300ustar00rootroot00000000000000### Node version (or tell us if you're using electron or some other framework): ### ShellJS version (the most recent version/Github branch you see the bug on): ### Operating system: ### Description of the bug: ### Example ShellJS command to reproduce the error: ```javascript ``` shelljs-0.7.5/.gitignore000066400000000000000000000002151300431262200151460ustar00rootroot00000000000000# Project npm-debug.log* node_modules tmp # Linux *~ # JetBrains .idea # Vim ## swap [._]*.s[a-w][a-z] [._]s[a-w][a-z] # OS X .DS_Store shelljs-0.7.5/.lgtm000066400000000000000000000000701300431262200141210ustar00rootroot00000000000000approvals = 1 pattern = "(?i):shipit:|:\\+1:|LGTM|\\+1" shelljs-0.7.5/.npmignore000066400000000000000000000002211300431262200151520ustar00rootroot00000000000000test/ tmp/ .github/ .documentup.json .gitignore .eslintrc .eslintignore .lgtm .travis.yml .gitattributes appveyor.yml RELEASE.md CONTRIBUTING.md shelljs-0.7.5/.travis.yml000066400000000000000000000021401300431262200152660ustar00rootroot00000000000000language: c++ sudo: false env: - NODE_VERSION="0.10" - NODE_VERSION="0.11" - NODE_VERSION="0.12" - NODE_VERSION="iojs-v1" - NODE_VERSION="iojs-v2" - NODE_VERSION="iojs-v3" - NODE_VERSION="4" - NODE_VERSION="5" - NODE_VERSION="6" matrix: allow_failures: - NODE_VERSION="0.10" # keep this blank to make sure there are no before_install steps before_install: install: - rm -rf ~/.nvm - git clone https://github.com/creationix/nvm.git ~/.nvm - source ~/.nvm/nvm.sh - nvm install $NODE_VERSION - node --version - npm install os: - linux - osx script: - npm test # make sure when the docs are generated nothing changes (a.k.a. the docs have already been generated) - npm run gendocs - npm run after-travis "Make sure to generate docs!" # Gitter notifications: email: false webhooks: urls: - https://webhooks.gitter.im/e/743dc6b83b6dd05111ee on_success: change # options: [always|never|change] default: always on_failure: always # options: [always|never|change] default: always on_start: never # options: [always|never|change] default: always shelljs-0.7.5/CHANGELOG.md000066400000000000000000001356351300431262200150060ustar00rootroot00000000000000# Change Log ## [Unreleased](https://github.com/shelljs/shelljs/tree/HEAD) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.7.4...HEAD) **Closed issues:** - Project objectives: there is some higher goal to achieve? [\#533](https://github.com/shelljs/shelljs/issues/533) - fs.existsSync is un-deprecated [\#531](https://github.com/shelljs/shelljs/issues/531) - Inadvertent breaking change to shell.test\(\) [\#529](https://github.com/shelljs/shelljs/issues/529) - Add -u flag support for cp [\#526](https://github.com/shelljs/shelljs/issues/526) - API request: allow `plugin.error\(\)` to take an options parameter [\#522](https://github.com/shelljs/shelljs/issues/522) - FS Real Path error thrown when requiring shelljs [\#521](https://github.com/shelljs/shelljs/issues/521) - Question: passing code via pipe? [\#520](https://github.com/shelljs/shelljs/issues/520) - The performance in `cp` is different between `0.6.0` and `0.7.4` [\#517](https://github.com/shelljs/shelljs/issues/517) - ShellJS in Electron package don't find ffmpeg anymore [\#516](https://github.com/shelljs/shelljs/issues/516) - Exec issues with string option introduced in 0.7.4 [\#515](https://github.com/shelljs/shelljs/issues/515) - \[ Feature \] SSH command [\#435](https://github.com/shelljs/shelljs/issues/435) - Synchronous exec stalls permenantly when there is an error/w the shell [\#7](https://github.com/shelljs/shelljs/issues/7) **Merged pull requests:** - feat: plugin.error\(\) takes an options parameter [\#535](https://github.com/shelljs/shelljs/pull/535) ([nfischer](https://github.com/nfischer)) - Revert "refactor: replace fs.existsSync" fixes\(\#531\) [\#532](https://github.com/shelljs/shelljs/pull/532) ([gyandeeps](https://github.com/gyandeeps)) - Fix: Remove default glob from shell.test \(fixes \#529\) [\#530](https://github.com/shelljs/shelljs/pull/530) ([gyandeeps](https://github.com/gyandeeps)) - feat: cp -u option [\#527](https://github.com/shelljs/shelljs/pull/527) ([nfischer](https://github.com/nfischer)) - chore: add downloads per month on README [\#513](https://github.com/shelljs/shelljs/pull/513) ([nfischer](https://github.com/nfischer)) ## [v0.7.4](https://github.com/shelljs/shelljs/tree/v0.7.4) (2016-08-26) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.7.3...v0.7.4) **Closed issues:** - fix: echo -e should not print "-e" [\#510](https://github.com/shelljs/shelljs/issues/510) - Wrong method signature in doc [\#498](https://github.com/shelljs/shelljs/issues/498) - readFromPipe should be a function with no arguments [\#485](https://github.com/shelljs/shelljs/issues/485) - TypeError: Cannot read property 'toString' of undefined [\#471](https://github.com/shelljs/shelljs/issues/471) **Merged pull requests:** - fix: echo supports -e option properly [\#511](https://github.com/shelljs/shelljs/pull/511) ([nfischer](https://github.com/nfischer)) - refactor: replace fs.existsSync [\#509](https://github.com/shelljs/shelljs/pull/509) ([nfischer](https://github.com/nfischer)) - refactor: readFromPipe\(\) requires no arguments [\#506](https://github.com/shelljs/shelljs/pull/506) ([nfischer](https://github.com/nfischer)) - chore: switch to eslint [\#504](https://github.com/shelljs/shelljs/pull/504) ([nfischer](https://github.com/nfischer)) - feat: add overWrite option for commands [\#503](https://github.com/shelljs/shelljs/pull/503) ([nfischer](https://github.com/nfischer)) - chore: update issue template [\#502](https://github.com/shelljs/shelljs/pull/502) ([nfischer](https://github.com/nfischer)) - fixed head/tail readme [\#499](https://github.com/shelljs/shelljs/pull/499) ([charlesread](https://github.com/charlesread)) ## [v0.7.3](https://github.com/shelljs/shelljs/tree/v0.7.3) (2016-07-27) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.7.2...v0.7.3) **Closed issues:** - expose execSync [\#494](https://github.com/shelljs/shelljs/issues/494) - Add a way to create commands that can receive from a pipe without being standalone commands [\#487](https://github.com/shelljs/shelljs/issues/487) - cp -r breaks when the directory contains a softlink [\#193](https://github.com/shelljs/shelljs/issues/193) - Redirect output to file fails [\#60](https://github.com/shelljs/shelljs/issues/60) - We need sed -n ? [\#38](https://github.com/shelljs/shelljs/issues/38) **Merged pull requests:** - refactor: allow pipeOnly commands \(methods on ShellStrings\) [\#493](https://github.com/shelljs/shelljs/pull/493) ([nfischer](https://github.com/nfischer)) - refactor: glob by default for commands [\#492](https://github.com/shelljs/shelljs/pull/492) ([nfischer](https://github.com/nfischer)) - refactor: switch from notUnix to unix in wrap\(\) [\#491](https://github.com/shelljs/shelljs/pull/491) ([nfischer](https://github.com/nfischer)) - refactor: switch common.extend\(\) to Object.assign ponyfill [\#490](https://github.com/shelljs/shelljs/pull/490) ([nfischer](https://github.com/nfischer)) - fix: conflicting options now properly override each other [\#489](https://github.com/shelljs/shelljs/pull/489) ([nfischer](https://github.com/nfischer)) - refactor: expose plugin utils & add initial tests [\#484](https://github.com/shelljs/shelljs/pull/484) ([nfischer](https://github.com/nfischer)) ## [v0.7.2](https://github.com/shelljs/shelljs/tree/v0.7.2) (2016-07-25) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.7.1...v0.7.2) **Closed issues:** - shelljs should not kill process if node call throws exception [\#473](https://github.com/shelljs/shelljs/issues/473) - `cp` work incorrectly when folder name contains '@' [\#463](https://github.com/shelljs/shelljs/issues/463) - Something went wrong [\#158](https://github.com/shelljs/shelljs/issues/158) **Merged pull requests:** - fix: resolve a cylcic-dependency problem [\#482](https://github.com/shelljs/shelljs/pull/482) ([nfischer](https://github.com/nfischer)) - refactor: add wrapOutput option to auto-ShellString-ify command output [\#481](https://github.com/shelljs/shelljs/pull/481) ([nfischer](https://github.com/nfischer)) - refactor: move option parsing into common.wrap\(\) [\#479](https://github.com/shelljs/shelljs/pull/479) ([nfischer](https://github.com/nfischer)) - refactor: hook new uniq\(\) command using new format [\#478](https://github.com/shelljs/shelljs/pull/478) ([nfischer](https://github.com/nfischer)) - Fix mkdir malformed path [\#477](https://github.com/shelljs/shelljs/pull/477) ([nfischer](https://github.com/nfischer)) - fix: mkdir for invalid perms does not kill process [\#474](https://github.com/shelljs/shelljs/pull/474) ([nfischer](https://github.com/nfischer)) - feat\(command\): new command: uniq\(\) [\#453](https://github.com/shelljs/shelljs/pull/453) ([joshi-sh](https://github.com/joshi-sh)) ## [v0.7.1](https://github.com/shelljs/shelljs/tree/v0.7.1) (2016-07-22) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.7.0...v0.7.1) **Closed issues:** - cp -n doesn't work correctly [\#465](https://github.com/shelljs/shelljs/issues/465) - how can i run sudo apt-get install xtodotool by your plugin? [\#448](https://github.com/shelljs/shelljs/issues/448) - shell.js grep: internal error, Invalid regular expression [\#447](https://github.com/shelljs/shelljs/issues/447) - Stdout is empty on Git log command [\#439](https://github.com/shelljs/shelljs/issues/439) - Cannot read toString of null when using execSync [\#415](https://github.com/shelljs/shelljs/issues/415) - cp -R dir/ target fails to copy hidden files in dir [\#140](https://github.com/shelljs/shelljs/issues/140) - Adding callback to basic commands [\#102](https://github.com/shelljs/shelljs/issues/102) - \#mv Won't Work Across Disks [\#1](https://github.com/shelljs/shelljs/issues/1) **Merged pull requests:** - refactor: commands now register themselves [\#475](https://github.com/shelljs/shelljs/pull/475) ([nfischer](https://github.com/nfischer)) - chore: switch to shields.io, and add npm badge [\#470](https://github.com/shelljs/shelljs/pull/470) ([nfischer](https://github.com/nfischer)) - fix\(cp\): -n option no longer raises error [\#466](https://github.com/shelljs/shelljs/pull/466) ([nfischer](https://github.com/nfischer)) - refactor: expose pipe-ability to command configuration [\#464](https://github.com/shelljs/shelljs/pull/464) ([nfischer](https://github.com/nfischer)) - fix\(mv\): works across partitions [\#461](https://github.com/shelljs/shelljs/pull/461) ([nfischer](https://github.com/nfischer)) - chore: switch to shelljs-changelog [\#460](https://github.com/shelljs/shelljs/pull/460) ([nfischer](https://github.com/nfischer)) - chore: update release process [\#459](https://github.com/shelljs/shelljs/pull/459) ([nfischer](https://github.com/nfischer)) - chore: revert depreciate shelljs/make \(\#431\) [\#458](https://github.com/shelljs/shelljs/pull/458) ([zephraph](https://github.com/zephraph)) - chore: clarify message for when docs are not generated [\#457](https://github.com/shelljs/shelljs/pull/457) ([nfischer](https://github.com/nfischer)) - chore\(gendocs\): add `npm run gendocs` command [\#455](https://github.com/shelljs/shelljs/pull/455) ([nfischer](https://github.com/nfischer)) - chore: update jshint and move it to an npm script [\#454](https://github.com/shelljs/shelljs/pull/454) ([nfischer](https://github.com/nfischer)) - test\(ls\): add case for trailing slash on dir name [\#450](https://github.com/shelljs/shelljs/pull/450) ([nfischer](https://github.com/nfischer)) - docs\(exec\): explicitly mention the `shell` option [\#449](https://github.com/shelljs/shelljs/pull/449) ([nfischer](https://github.com/nfischer)) - chore: setup changelog [\#443](https://github.com/shelljs/shelljs/pull/443) ([levithomason](https://github.com/levithomason)) - docs: comment code better to help contributors [\#437](https://github.com/shelljs/shelljs/pull/437) ([nfischer](https://github.com/nfischer)) - chore\(CI\): update appveyor [\#436](https://github.com/shelljs/shelljs/pull/436) ([nfischer](https://github.com/nfischer)) - chore: test against node v6 [\#433](https://github.com/shelljs/shelljs/pull/433) ([nfischer](https://github.com/nfischer)) - chore\(make\): depreciate shelljs/make [\#431](https://github.com/shelljs/shelljs/pull/431) ([ariporad](https://github.com/ariporad)) - docs: warn that README contains newest features [\#410](https://github.com/shelljs/shelljs/pull/410) ([nfischer](https://github.com/nfischer)) ## [v0.7.0](https://github.com/shelljs/shelljs/tree/v0.7.0) (2016-04-25) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.6.0...v0.7.0) **Closed issues:** - exec\('nohup node some.js &'\) [\#426](https://github.com/shelljs/shelljs/issues/426) - cp copy to symlinked folder [\#414](https://github.com/shelljs/shelljs/issues/414) - Invalid version number \(0.0.1alpha1\) [\#399](https://github.com/shelljs/shelljs/issues/399) - shelljs Breaks SemVer for Alpha and Pre-Release Versions [\#390](https://github.com/shelljs/shelljs/issues/390) - Copy not accepting source end with wildcards \* when using -r on v0.6.0 [\#389](https://github.com/shelljs/shelljs/issues/389) - Support globbing in `shjs` [\#388](https://github.com/shelljs/shelljs/issues/388) - Refactor more commands to return ShellString [\#373](https://github.com/shelljs/shelljs/issues/373) - ln\('-sf', './', '\'\) is not linking the right folder [\#363](https://github.com/shelljs/shelljs/issues/363) - v0.6.0 - shell.cp\('r', '/foo/\*, '/bar'\) fails with /foo/\* no such file or directory [\#342](https://github.com/shelljs/shelljs/issues/342) - Add documentup as a webhook [\#327](https://github.com/shelljs/shelljs/issues/327) - Dir glob breaks when in the middle of path [\#245](https://github.com/shelljs/shelljs/issues/245) - could you switch off wiki page? [\#233](https://github.com/shelljs/shelljs/issues/233) - ls globbing does not behave like shell, consider using glob.sync [\#225](https://github.com/shelljs/shelljs/issues/225) - Cannot run shell.exec\('heroku config:push'\) -- just hangs [\#218](https://github.com/shelljs/shelljs/issues/218) - `cp` does not overwrite files by default [\#210](https://github.com/shelljs/shelljs/issues/210) - exec failed to return [\#208](https://github.com/shelljs/shelljs/issues/208) - CLI Version [\#202](https://github.com/shelljs/shelljs/issues/202) - Bracket expansion not working [\#176](https://github.com/shelljs/shelljs/issues/176) - "exec" causes LiveScript interpreter \(lsc\) to hang [\#160](https://github.com/shelljs/shelljs/issues/160) - Don't modify string prototype [\#159](https://github.com/shelljs/shelljs/issues/159) - `exec\(...\).to\(file\)` should work [\#154](https://github.com/shelljs/shelljs/issues/154) - Would like to see more async variants for cp/rm etc [\#144](https://github.com/shelljs/shelljs/issues/144) - Can't install shelljs locally instead of globally [\#136](https://github.com/shelljs/shelljs/issues/136) - shelljs and node 0.10.28 [\#125](https://github.com/shelljs/shelljs/issues/125) - Use case for global installed shelljs [\#123](https://github.com/shelljs/shelljs/issues/123) - Only get stdout from `exec` [\#92](https://github.com/shelljs/shelljs/issues/92) - What about other commands? [\#90](https://github.com/shelljs/shelljs/issues/90) - Flesh out example of exit\(\) [\#73](https://github.com/shelljs/shelljs/issues/73) - exec doesn't work with qualified paths on windows [\#41](https://github.com/shelljs/shelljs/issues/41) - exec does not working in mingw bash in windows [\#17](https://github.com/shelljs/shelljs/issues/17) - Add support for cp -P option [\#413](https://github.com/shelljs/shelljs/issues/413) - cp -L: Incorrect behavior for symlinks to regular files [\#407](https://github.com/shelljs/shelljs/issues/407) - Edit the docs to emphasize ShellStrings and Pipes [\#398](https://github.com/shelljs/shelljs/issues/398) - Error message isn't always printed [\#372](https://github.com/shelljs/shelljs/issues/372) - Standardize command output [\#356](https://github.com/shelljs/shelljs/issues/356) - exec\(\) doesn't clean up all temp files [\#353](https://github.com/shelljs/shelljs/issues/353) - Document that exec\(\) options don't work on early versions of node [\#350](https://github.com/shelljs/shelljs/issues/350) - Add -f option to set\(\) [\#344](https://github.com/shelljs/shelljs/issues/344) - Glob commands by default [\#343](https://github.com/shelljs/shelljs/issues/343) - rm -rf incorrect behaviour [\#332](https://github.com/shelljs/shelljs/issues/332) - Switch `exec\(\)` to use bash by default [\#281](https://github.com/shelljs/shelljs/issues/281) - pipe to proc [\#148](https://github.com/shelljs/shelljs/issues/148) - shell builtin [\#138](https://github.com/shelljs/shelljs/issues/138) - add timeout option for exec [\#132](https://github.com/shelljs/shelljs/issues/132) - shelljs cp handling symlinks badly [\#69](https://github.com/shelljs/shelljs/issues/69) **Merged pull requests:** - chore: add "Team" section to README [\#423](https://github.com/shelljs/shelljs/pull/423) ([nfischer](https://github.com/nfischer)) - Contributing guidelines [\#422](https://github.com/shelljs/shelljs/pull/422) ([nfischer](https://github.com/nfischer)) - feat\(glob\): expose config.globOptions. [\#400](https://github.com/shelljs/shelljs/pull/400) ([nfischer](https://github.com/nfischer)) - Add shelljs as a keyword in package.json [\#393](https://github.com/shelljs/shelljs/pull/393) ([nfischer](https://github.com/nfischer)) - docs: add link to wiki page [\#392](https://github.com/shelljs/shelljs/pull/392) ([nfischer](https://github.com/nfischer)) - refactor\(cd\): use process.env.OLDPWD to store previous dir [\#383](https://github.com/shelljs/shelljs/pull/383) ([nfischer](https://github.com/nfischer)) - chore\(appveyor\): add in node 4 for appveyor [\#381](https://github.com/shelljs/shelljs/pull/381) ([nfischer](https://github.com/nfischer)) - Add Cash cross-reference [\#375](https://github.com/shelljs/shelljs/pull/375) ([dthree](https://github.com/dthree)) - Ignore gitattributes from npm package [\#361](https://github.com/shelljs/shelljs/pull/361) ([nfischer](https://github.com/nfischer)) - Consistently use LF line endings [\#355](https://github.com/shelljs/shelljs/pull/355) ([TimothyGu](https://github.com/TimothyGu)) - Release v0.7.0 [\#429](https://github.com/shelljs/shelljs/pull/429) ([nfischer](https://github.com/nfischer)) - fix: null is no longer confused for an object [\#428](https://github.com/shelljs/shelljs/pull/428) ([nfischer](https://github.com/nfischer)) - fix\(ls\): no trailing newline for empty directories [\#425](https://github.com/shelljs/shelljs/pull/425) ([nfischer](https://github.com/nfischer)) - feat\(cp\): -P option, plus better handling of symlinks [\#421](https://github.com/shelljs/shelljs/pull/421) ([nfischer](https://github.com/nfischer)) - docs\(exec\): fix docs about exec return type [\#419](https://github.com/shelljs/shelljs/pull/419) ([nfischer](https://github.com/nfischer)) - docs\(error\): deprecate relying on string value [\#418](https://github.com/shelljs/shelljs/pull/418) ([nfischer](https://github.com/nfischer)) - fix: error message now printed for fatal failures [\#417](https://github.com/shelljs/shelljs/pull/417) ([nfischer](https://github.com/nfischer)) - issue-407: Add regular files unit tests and fix symlink copy behavior [\#409](https://github.com/shelljs/shelljs/pull/409) ([charlesverge](https://github.com/charlesverge)) - refactor\(rm\): Remove duplicate code [\#408](https://github.com/shelljs/shelljs/pull/408) ([nfischer](https://github.com/nfischer)) - docs: wildcards for all commands, other docs cleanups [\#404](https://github.com/shelljs/shelljs/pull/404) ([nfischer](https://github.com/nfischer)) - test\(rm\): add tests to prevent a future regression [\#403](https://github.com/shelljs/shelljs/pull/403) ([nfischer](https://github.com/nfischer)) - refactor\(string\): modify string protoype, but only for shelljs/global [\#401](https://github.com/shelljs/shelljs/pull/401) ([nfischer](https://github.com/nfischer)) - feat: adding error codes to ShellJS [\#394](https://github.com/shelljs/shelljs/pull/394) ([nfischer](https://github.com/nfischer)) - feature: use rechoir [\#384](https://github.com/shelljs/shelljs/pull/384) ([nfischer](https://github.com/nfischer)) - refactor\(cp\): clean up code and fix \#376 [\#380](https://github.com/shelljs/shelljs/pull/380) ([nfischer](https://github.com/nfischer)) - New commands: sort\(\), head\(\), and tail\(\) [\#379](https://github.com/shelljs/shelljs/pull/379) ([nfischer](https://github.com/nfischer)) - Add unit tests to prevent regression \(see \#376\) [\#378](https://github.com/shelljs/shelljs/pull/378) ([nfischer](https://github.com/nfischer)) - feat\(pipe\): add support for pipes between commands [\#370](https://github.com/shelljs/shelljs/pull/370) ([nfischer](https://github.com/nfischer)) - refactor\(ls\): greatly simplify ls implimentation [\#369](https://github.com/shelljs/shelljs/pull/369) ([ariporad](https://github.com/ariporad)) - chore: drop node v0.10 support [\#368](https://github.com/shelljs/shelljs/pull/368) ([ariporad](https://github.com/ariporad)) - perf\(cd\): only run `stat` once [\#367](https://github.com/shelljs/shelljs/pull/367) ([ariporad](https://github.com/ariporad)) - fix\(exec\): properly handles paths with spaces and quotes [\#365](https://github.com/shelljs/shelljs/pull/365) ([nfischer](https://github.com/nfischer)) - test\(ln\): add tests for linking to cwd [\#364](https://github.com/shelljs/shelljs/pull/364) ([nfischer](https://github.com/nfischer)) - fix\(verbose\): verbose-style logging is consistent [\#362](https://github.com/shelljs/shelljs/pull/362) ([nfischer](https://github.com/nfischer)) - Refactor shellstring [\#360](https://github.com/shelljs/shelljs/pull/360) ([nfischer](https://github.com/nfischer)) - feat\(glob\): use glob module for globbing [\#359](https://github.com/shelljs/shelljs/pull/359) ([nfischer](https://github.com/nfischer)) - feat\(set\): add -f option to disable globbing [\#358](https://github.com/shelljs/shelljs/pull/358) ([nfischer](https://github.com/nfischer)) - config.fatal now throws an exception [\#357](https://github.com/shelljs/shelljs/pull/357) ([jrmclaurin](https://github.com/jrmclaurin)) - fix\(exec\): temp files are now cleaned up [\#354](https://github.com/shelljs/shelljs/pull/354) ([nfischer](https://github.com/nfischer)) - feat\(glob\): glob support for \(almost\) all commands [\#352](https://github.com/shelljs/shelljs/pull/352) ([nfischer](https://github.com/nfischer)) - feat\(grep\): add -l option [\#349](https://github.com/shelljs/shelljs/pull/349) ([nfischer](https://github.com/nfischer)) - fix\(exec\): now actually supports shell option [\#348](https://github.com/shelljs/shelljs/pull/348) ([nfischer](https://github.com/nfischer)) - feat\(touch\): supports multiple files [\#346](https://github.com/shelljs/shelljs/pull/346) ([nfischer](https://github.com/nfischer)) ## [v0.6.0](https://github.com/shelljs/shelljs/tree/v0.6.0) (2016-02-05) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.5.3...v0.6.0) **Closed issues:** - option not recognized [\#334](https://github.com/shelljs/shelljs/issues/334) - Feature request: Metadata with `ls` [\#323](https://github.com/shelljs/shelljs/issues/323) - Gen-docs is broken [\#309](https://github.com/shelljs/shelljs/issues/309) - `link -s` is broken for files on Windows [\#301](https://github.com/shelljs/shelljs/issues/301) - Shelljs quits unexpectedly: [\#300](https://github.com/shelljs/shelljs/issues/300) - Failing tests on Windows [\#296](https://github.com/shelljs/shelljs/issues/296) - run-tests.js is broken for cmd.exe [\#294](https://github.com/shelljs/shelljs/issues/294) - Support echo-ing environment variables [\#291](https://github.com/shelljs/shelljs/issues/291) - Add Windows CI [\#287](https://github.com/shelljs/shelljs/issues/287) - Add tests for the shjs utility [\#280](https://github.com/shelljs/shelljs/issues/280) - Allow shjs utility to infer the extension for "filename." [\#278](https://github.com/shelljs/shelljs/issues/278) - Ability to read the stdout buffer line-by-line [\#277](https://github.com/shelljs/shelljs/issues/277) - Poor output for commands with multiple errors [\#267](https://github.com/shelljs/shelljs/issues/267) - Travis ci build status says "unknown" [\#266](https://github.com/shelljs/shelljs/issues/266) - wild card characters in filename not working as expected [\#262](https://github.com/shelljs/shelljs/issues/262) - shell.exec - read internal variable [\#260](https://github.com/shelljs/shelljs/issues/260) - cp and rename directory with -r doesn't match unix behavior [\#256](https://github.com/shelljs/shelljs/issues/256) - console.log.apply throwing TypeError: Illegal Invocation [\#255](https://github.com/shelljs/shelljs/issues/255) - How to exit on first error [\#253](https://github.com/shelljs/shelljs/issues/253) - why not support set 'cwd' when invoke execAsync ? [\#250](https://github.com/shelljs/shelljs/issues/250) - Not possible to check the failure of cd? [\#247](https://github.com/shelljs/shelljs/issues/247) - By default shelljs runs command in root [\#246](https://github.com/shelljs/shelljs/issues/246) - /usr/bin/env: node: No such file or directory [\#243](https://github.com/shelljs/shelljs/issues/243) - "Which" command not working properly on Windows Platform. [\#238](https://github.com/shelljs/shelljs/issues/238) - Arguments [\#237](https://github.com/shelljs/shelljs/issues/237) - sed\(\) should accept multiple file arguments [\#231](https://github.com/shelljs/shelljs/issues/231) - shelljs.exec\('aaa && bbb'\) blocks [\#229](https://github.com/shelljs/shelljs/issues/229) - Consider creating a GitHub Organization with more maintainers [\#223](https://github.com/shelljs/shelljs/issues/223) - Doesn't work inside Electron [\#220](https://github.com/shelljs/shelljs/issues/220) - \[idea\] Add chmodr function. [\#219](https://github.com/shelljs/shelljs/issues/219) - Execute a file [\#211](https://github.com/shelljs/shelljs/issues/211) - Where is standard error going to? [\#209](https://github.com/shelljs/shelljs/issues/209) - boolean return value for string.to\(\) [\#205](https://github.com/shelljs/shelljs/issues/205) - `common.error` doesn't throw [\#199](https://github.com/shelljs/shelljs/issues/199) - Problems with exec \(sync\) on 0.12/io.js [\#197](https://github.com/shelljs/shelljs/issues/197) - cp --update flag [\#172](https://github.com/shelljs/shelljs/issues/172) - Is there a way to suppress pushd/popd output? [\#171](https://github.com/shelljs/shelljs/issues/171) - Cannot recursively list all \*.js files [\#162](https://github.com/shelljs/shelljs/issues/162) - exec\(\) breaks if executed in a deleted directory [\#157](https://github.com/shelljs/shelljs/issues/157) - shjs command always exits with zero code [\#133](https://github.com/shelljs/shelljs/issues/133) - Windows failing tests [\#127](https://github.com/shelljs/shelljs/issues/127) - touch command [\#122](https://github.com/shelljs/shelljs/issues/122) - Symbolic links are broken! [\#100](https://github.com/shelljs/shelljs/issues/100) - interpret `--` as stdin [\#55](https://github.com/shelljs/shelljs/issues/55) - Error ENOTEMPTY when deleting a directory recursively. [\#49](https://github.com/shelljs/shelljs/issues/49) - Cross-platform way to add to PATH [\#32](https://github.com/shelljs/shelljs/issues/32) - `mv` fails on block, character, fifo [\#25](https://github.com/shelljs/shelljs/issues/25) - ls -l [\#22](https://github.com/shelljs/shelljs/issues/22) **Merged pull requests:** - feat\(set\): add new set\(\) command [\#329](https://github.com/shelljs/shelljs/pull/329) ([nfischer](https://github.com/nfischer)) - Fix symlinking on Windows [\#322](https://github.com/shelljs/shelljs/pull/322) ([BYK](https://github.com/BYK)) - Rewrite .gitignore to be more comprehensive [\#321](https://github.com/shelljs/shelljs/pull/321) ([BYK](https://github.com/BYK)) - chore\(gitter/travis\): add gitter webhook to travis [\#313](https://github.com/shelljs/shelljs/pull/313) ([ariporad](https://github.com/ariporad)) - chore\(LGTM\): add LGTM config files [\#312](https://github.com/shelljs/shelljs/pull/312) ([ariporad](https://github.com/ariporad)) - feat\(ls\): add -d flag to ls\(\) [\#311](https://github.com/shelljs/shelljs/pull/311) ([nfischer](https://github.com/nfischer)) - fix\(gen-docs\): fix issue where docs are generated wrong [\#310](https://github.com/shelljs/shelljs/pull/310) ([nfischer](https://github.com/nfischer)) - chore\(package\): remove v0.8 from engines list [\#308](https://github.com/shelljs/shelljs/pull/308) ([nfischer](https://github.com/nfischer)) - travis: Mark as not using `sudo` and do not test 0.11 [\#307](https://github.com/shelljs/shelljs/pull/307) ([TimothyGu](https://github.com/TimothyGu)) - fix: jshint works on Windows [\#295](https://github.com/shelljs/shelljs/pull/295) ([nfischer](https://github.com/nfischer)) - feat: add tilde expansion to expand\(\) [\#293](https://github.com/shelljs/shelljs/pull/293) ([nfischer](https://github.com/nfischer)) - style: make docs more consistent [\#292](https://github.com/shelljs/shelljs/pull/292) ([nfischer](https://github.com/nfischer)) - update `exec` docs to match implemented behaviour [\#289](https://github.com/shelljs/shelljs/pull/289) ([vise890](https://github.com/vise890)) - chore: update github URL in package.json [\#288](https://github.com/shelljs/shelljs/pull/288) ([nfischer](https://github.com/nfischer)) - docs\(spelling\): fix typo in source comment [\#285](https://github.com/shelljs/shelljs/pull/285) ([nfischer](https://github.com/nfischer)) - chore\(travis\): add OS X to Travis CI [\#283](https://github.com/shelljs/shelljs/pull/283) ([nfischer](https://github.com/nfischer)) - Don't do `console.log.apply\(this, ...\)`. [\#274](https://github.com/shelljs/shelljs/pull/274) ([ariporad](https://github.com/ariporad)) - Implementing cd\('-'\) to behave like Bash's "cd -" [\#273](https://github.com/shelljs/shelljs/pull/273) ([nfischer](https://github.com/nfischer)) - Fix cp to match unix behavior [\#271](https://github.com/shelljs/shelljs/pull/271) ([freitagbr](https://github.com/freitagbr)) - Commands that have multiple errors now produce cleaner log output [\#268](https://github.com/shelljs/shelljs/pull/268) ([nfischer](https://github.com/nfischer)) - Support exit code in shjs. [\#252](https://github.com/shelljs/shelljs/pull/252) ([bryce-gibson](https://github.com/bryce-gibson)) - add touch\(1\) [\#249](https://github.com/shelljs/shelljs/pull/249) ([blockloop](https://github.com/blockloop)) - Fix `os.tmpdir` bug [\#240](https://github.com/shelljs/shelljs/pull/240) ([BYK](https://github.com/BYK)) - Make sure Which\(\) on Windows platform always return the command with … [\#239](https://github.com/shelljs/shelljs/pull/239) ([TingluoHuang](https://github.com/TingluoHuang)) - Add target node.js \(iojs v1, v2, v3\) [\#230](https://github.com/shelljs/shelljs/pull/230) ([sanemat](https://github.com/sanemat)) - feat-multisymbolic + Support for directory entry \(capital X in chmod terms\) [\#228](https://github.com/shelljs/shelljs/pull/228) ([rezonant](https://github.com/rezonant)) - Fixes an issue with multi-symbolic mode specification \(ie a-rwx,u+rw\) [\#227](https://github.com/shelljs/shelljs/pull/227) ([rezonant](https://github.com/rezonant)) - Memoized the result of target invocation [\#216](https://github.com/shelljs/shelljs/pull/216) ([rizowski](https://github.com/rizowski)) - remove empty for loop and leaked i var [\#166](https://github.com/shelljs/shelljs/pull/166) ([ratbeard](https://github.com/ratbeard)) - Wrap script name in double quotes [\#135](https://github.com/shelljs/shelljs/pull/135) ([ndelitski](https://github.com/ndelitski)) - Fixed coffeescript syntax in top example [\#99](https://github.com/shelljs/shelljs/pull/99) ([maxnordlund](https://github.com/maxnordlund)) - fix\(touch\): enhance parseOptions and fix touch's -r flag [\#341](https://github.com/shelljs/shelljs/pull/341) ([nfischer](https://github.com/nfischer)) - chore\(.npmignore\): update npmignore [\#339](https://github.com/shelljs/shelljs/pull/339) ([ariporad](https://github.com/ariporad)) - Release v0.6.0 [\#338](https://github.com/shelljs/shelljs/pull/338) ([ariporad](https://github.com/ariporad)) - docs\(README\): remove coffeescript from README [\#337](https://github.com/shelljs/shelljs/pull/337) ([ariporad](https://github.com/ariporad)) - fix\(cp\): add -n option, make -f default behavior [\#336](https://github.com/shelljs/shelljs/pull/336) ([nfischer](https://github.com/nfischer)) - feat\(exec\): allow all exec options to pass through [\#335](https://github.com/shelljs/shelljs/pull/335) ([nfischer](https://github.com/nfischer)) - fix\(mv\): add -n option, make -f default behavior [\#328](https://github.com/shelljs/shelljs/pull/328) ([nfischer](https://github.com/nfischer)) - fix\(cat\): make behavior more like unix [\#326](https://github.com/shelljs/shelljs/pull/326) ([nfischer](https://github.com/nfischer)) - feat\(ls\): add -l option [\#324](https://github.com/shelljs/shelljs/pull/324) ([nfischer](https://github.com/nfischer)) - style\(test/which\): make test/which.js conform to the style guidelines [\#320](https://github.com/shelljs/shelljs/pull/320) ([ariporad](https://github.com/ariporad)) - chore\(appveyor\): add badge [\#316](https://github.com/shelljs/shelljs/pull/316) ([nfischer](https://github.com/nfischer)) - fix\(windows\): fix shjs commands for windows [\#315](https://github.com/shelljs/shelljs/pull/315) ([nfischer](https://github.com/nfischer)) - feat\(sed\): support multiple file names [\#314](https://github.com/shelljs/shelljs/pull/314) ([nfischer](https://github.com/nfischer)) - feat\(cd\): cd\(\) \(no args\) changes to home directory [\#306](https://github.com/shelljs/shelljs/pull/306) ([nfischer](https://github.com/nfischer)) - test\(shjs\): add tests for shjs [\#304](https://github.com/shelljs/shelljs/pull/304) ([ariporad](https://github.com/ariporad)) - fix: regexes are more consistent with sed and grep [\#303](https://github.com/shelljs/shelljs/pull/303) ([nfischer](https://github.com/nfischer)) - Add appveyor.yml config file [\#299](https://github.com/shelljs/shelljs/pull/299) ([nfischer](https://github.com/nfischer)) - Fix tests on Windows [\#297](https://github.com/shelljs/shelljs/pull/297) ([BYK](https://github.com/BYK)) - Search PATHEXT instead of 3 hardcoded values [\#290](https://github.com/shelljs/shelljs/pull/290) ([isiahmeadows](https://github.com/isiahmeadows)) - Fix relative symlinks [\#282](https://github.com/shelljs/shelljs/pull/282) ([freitagbr](https://github.com/freitagbr)) - Make to and toEnd chainable [\#276](https://github.com/shelljs/shelljs/pull/276) ([TimothyGu](https://github.com/TimothyGu)) ## [v0.5.3](https://github.com/shelljs/shelljs/tree/v0.5.3) (2015-08-11) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.5.2...v0.5.3) **Merged pull requests:** - Manually closing streams [\#222](https://github.com/shelljs/shelljs/pull/222) ([JulianLaval](https://github.com/JulianLaval)) ## [v0.5.2](https://github.com/shelljs/shelljs/tree/v0.5.2) (2015-08-10) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.5.1...v0.5.2) **Closed issues:** - Cannot run shell.exec [\#217](https://github.com/shelljs/shelljs/issues/217) - write after end: internal error [\#206](https://github.com/shelljs/shelljs/issues/206) **Merged pull requests:** - Update README.md [\#221](https://github.com/shelljs/shelljs/pull/221) ([giosh94mhz](https://github.com/giosh94mhz)) - prevent internal error: write after end [\#214](https://github.com/shelljs/shelljs/pull/214) ([charlierudolph](https://github.com/charlierudolph)) ## [v0.5.1](https://github.com/shelljs/shelljs/tree/v0.5.1) (2015-06-05) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.5.0...v0.5.1) **Closed issues:** - cd into home directory [\#9](https://github.com/shelljs/shelljs/issues/9) **Merged pull requests:** - Fix issue \#49: Retry rmdirSync on Windows for up to 1 second if files still exist. [\#179](https://github.com/shelljs/shelljs/pull/179) ([andreialecu](https://github.com/andreialecu)) ## [v0.5.0](https://github.com/shelljs/shelljs/tree/v0.5.0) (2015-05-19) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.3.0...v0.5.0) **Closed issues:** - Enter text to prompt [\#203](https://github.com/shelljs/shelljs/issues/203) - Find which shell is being used [\#195](https://github.com/shelljs/shelljs/issues/195) - Pass command line params to the make tool [\#188](https://github.com/shelljs/shelljs/issues/188) - Is it possible to call exec with a command containing new lines ? [\#177](https://github.com/shelljs/shelljs/issues/177) - The installation would break on Windows 7 [\#161](https://github.com/shelljs/shelljs/issues/161) - Q.ninvoke\(\) returns undefined [\#153](https://github.com/shelljs/shelljs/issues/153) - installed shelljs on osx but reported error: npm ERR! 404 '%5B-g%5D' is not in the npm registry. [\#124](https://github.com/shelljs/shelljs/issues/124) - "ln" not found \(OS X\) [\#106](https://github.com/shelljs/shelljs/issues/106) - Using shelljs in a CLI app. [\#91](https://github.com/shelljs/shelljs/issues/91) **Merged pull requests:** - Breaking: Allow -- as args separators \(fixes \#188\) [\#207](https://github.com/shelljs/shelljs/pull/207) ([nzakas](https://github.com/nzakas)) - Update .travis.yml [\#190](https://github.com/shelljs/shelljs/pull/190) ([arturadib](https://github.com/arturadib)) - Use new child\_process.execSync instead of busywaiting [\#189](https://github.com/shelljs/shelljs/pull/189) ([devTristan](https://github.com/devTristan)) - Update README.md: explains how to access "config" [\#145](https://github.com/shelljs/shelljs/pull/145) ([kerphi](https://github.com/kerphi)) - Fix to set state.error before throw the exception [\#120](https://github.com/shelljs/shelljs/pull/120) ([abdul-martinez](https://github.com/abdul-martinez)) - Add -l and -s support to grep. [\#116](https://github.com/shelljs/shelljs/pull/116) ([idearat](https://github.com/idearat)) ## [v0.3.0](https://github.com/shelljs/shelljs/tree/v0.3.0) (2014-05-08) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.2.6...v0.3.0) **Closed issues:** - grep\(\) should fully support globing [\#118](https://github.com/shelljs/shelljs/issues/118) - sed\(\) could support replacement function [\#115](https://github.com/shelljs/shelljs/issues/115) - How would you close an exec process that runs indefinitely? [\#113](https://github.com/shelljs/shelljs/issues/113) - listen for intermittent output of a long-running child process [\#111](https://github.com/shelljs/shelljs/issues/111) - Cannot find module 'shelljs' after installing shelljs with npm [\#109](https://github.com/shelljs/shelljs/issues/109) - Massive CPU usage on exec\(\) windows [\#108](https://github.com/shelljs/shelljs/issues/108) - cp skipping dot files? [\#79](https://github.com/shelljs/shelljs/issues/79) - $variables in exec\(\) aren't handled correctly [\#11](https://github.com/shelljs/shelljs/issues/11) - debug flag that prints commands instead of executing [\#8](https://github.com/shelljs/shelljs/issues/8) **Merged pull requests:** - grep\(\) support for globing, fixes \#118 [\#119](https://github.com/shelljs/shelljs/pull/119) ([utensil](https://github.com/utensil)) - make sed\(\) support replacement function, fixes \#115 [\#117](https://github.com/shelljs/shelljs/pull/117) ([utensil](https://github.com/utensil)) - which\(\) should only find files, not directories [\#110](https://github.com/shelljs/shelljs/pull/110) ([panrafal](https://github.com/panrafal)) - Added the New BSD license to the package.json. [\#105](https://github.com/shelljs/shelljs/pull/105) ([keskival](https://github.com/keskival)) - Added win32 support to ln [\#104](https://github.com/shelljs/shelljs/pull/104) ([jamon](https://github.com/jamon)) - Fix ln using bad paths when given abspaths. [\#89](https://github.com/shelljs/shelljs/pull/89) ([Schoonology](https://github.com/Schoonology)) - Add ln support, including both -s and -f options. [\#88](https://github.com/shelljs/shelljs/pull/88) ([Schoonology](https://github.com/Schoonology)) - add support for symlinking \(junctions\) on win32 [\#87](https://github.com/shelljs/shelljs/pull/87) ([jamon](https://github.com/jamon)) ## [v0.2.6](https://github.com/shelljs/shelljs/tree/v0.2.6) (2013-09-22) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.2.5...v0.2.6) **Closed issues:** - Versions 0.2.4 and 0.2.3 keep throwing strange errors [\#82](https://github.com/shelljs/shelljs/issues/82) - Add global pollution tests [\#33](https://github.com/shelljs/shelljs/issues/33) ## [v0.2.5](https://github.com/shelljs/shelljs/tree/v0.2.5) (2013-09-11) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.2.4...v0.2.5) **Closed issues:** - shelljs.exec stalls on Red Hat when script is invoked with 'sudo -u username' [\#72](https://github.com/shelljs/shelljs/issues/72) ## [v0.2.4](https://github.com/shelljs/shelljs/tree/v0.2.4) (2013-09-11) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.2.3...v0.2.4) ## [v0.2.3](https://github.com/shelljs/shelljs/tree/v0.2.3) (2013-09-09) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.2.2...v0.2.3) **Merged pull requests:** - Make shell.exec\(\) treat process error return codes as shelljs errors [\#80](https://github.com/shelljs/shelljs/pull/80) ([nilsbunger](https://github.com/nilsbunger)) ## [v0.2.2](https://github.com/shelljs/shelljs/tree/v0.2.2) (2013-09-02) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.1.4...v0.2.2) **Closed issues:** - which and node\_modules [\#63](https://github.com/shelljs/shelljs/issues/63) - cannot install with nodejs 0.10.2 [\#57](https://github.com/shelljs/shelljs/issues/57) **Merged pull requests:** - Addition of a toEnd\(\) function modeled after the Unix \>\> pipe. [\#78](https://github.com/shelljs/shelljs/pull/78) ([andreweduffy](https://github.com/andreweduffy)) - Added appendTo\(\) function to imitate '\>\>' redirect-and-append pipe. [\#75](https://github.com/shelljs/shelljs/pull/75) ([andreweduffy](https://github.com/andreweduffy)) - Fix a small typo in README.md [\#71](https://github.com/shelljs/shelljs/pull/71) ([asmblah](https://github.com/asmblah)) - adding an `.npmignore` file [\#70](https://github.com/shelljs/shelljs/pull/70) ([stephenmathieson](https://github.com/stephenmathieson)) - tempdir: use `os.tmpDir` when possible [\#67](https://github.com/shelljs/shelljs/pull/67) ([stephenmathieson](https://github.com/stephenmathieson)) ## [v0.1.4](https://github.com/shelljs/shelljs/tree/v0.1.4) (2013-05-10) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.1.3...v0.1.4) **Merged pull requests:** - removing extra fs calls [\#62](https://github.com/shelljs/shelljs/pull/62) ([stephenmathieson](https://github.com/stephenmathieson)) - moving \_jshint\_ to a development dependency [\#61](https://github.com/shelljs/shelljs/pull/61) ([stephenmathieson](https://github.com/stephenmathieson)) - Make the maximum buffersize 20 MB. [\#59](https://github.com/shelljs/shelljs/pull/59) ([waddlesplash](https://github.com/waddlesplash)) ## [v0.1.3](https://github.com/shelljs/shelljs/tree/v0.1.3) (2013-04-21) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.1.2...v0.1.3) **Merged pull requests:** - test\('-L', badlink\) should return true [\#56](https://github.com/shelljs/shelljs/pull/56) ([lge88](https://github.com/lge88)) - exec options now allows `silent:true` with callback. [\#54](https://github.com/shelljs/shelljs/pull/54) ([iapain](https://github.com/iapain)) - Add Zepto to README [\#53](https://github.com/shelljs/shelljs/pull/53) ([madrobby](https://github.com/madrobby)) ## [v0.1.2](https://github.com/shelljs/shelljs/tree/v0.1.2) (2013-01-08) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.1.1...v0.1.2) **Closed issues:** - pushd/popd [\#24](https://github.com/shelljs/shelljs/issues/24) **Merged pull requests:** - Implemented chmod command. Github issue 35 [\#48](https://github.com/shelljs/shelljs/pull/48) ([brandonramirez](https://github.com/brandonramirez)) ## [v0.1.1](https://github.com/shelljs/shelljs/tree/v0.1.1) (2013-01-01) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.1.0...v0.1.1) **Merged pull requests:** - Work in progress: pushd/popd/dirs [\#47](https://github.com/shelljs/shelljs/pull/47) ([mstade](https://github.com/mstade)) ## [v0.1.0](https://github.com/shelljs/shelljs/tree/v0.1.0) (2012-12-26) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.0.9...v0.1.0) **Closed issues:** - test\(\) for binary file? [\#45](https://github.com/shelljs/shelljs/issues/45) - Inconsistent behaviour of cp command with directories. [\#44](https://github.com/shelljs/shelljs/issues/44) - Executing SSH with ShellJs [\#43](https://github.com/shelljs/shelljs/issues/43) **Merged pull requests:** - Fix for \#44 [\#46](https://github.com/shelljs/shelljs/pull/46) ([mstade](https://github.com/mstade)) - Fix single/double quotes in exec [\#42](https://github.com/shelljs/shelljs/pull/42) ([danielepolencic](https://github.com/danielepolencic)) ## [v0.0.9](https://github.com/shelljs/shelljs/tree/v0.0.9) (2012-12-01) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.0.8...v0.0.9) **Closed issues:** - silent output [\#40](https://github.com/shelljs/shelljs/issues/40) - asynchronous exec [\#34](https://github.com/shelljs/shelljs/issues/34) **Merged pull requests:** - Passed process arguments to executable script [\#36](https://github.com/shelljs/shelljs/pull/36) ([Zanisimo](https://github.com/Zanisimo)) ## [v0.0.8](https://github.com/shelljs/shelljs/tree/v0.0.8) (2012-10-11) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.0.7...v0.0.8) **Closed issues:** - exec with callback should automatically be async [\#31](https://github.com/shelljs/shelljs/issues/31) - Exporting variables. [\#30](https://github.com/shelljs/shelljs/issues/30) - Detecting shelljs/node [\#27](https://github.com/shelljs/shelljs/issues/27) **Merged pull requests:** - fix: global leak 'stats' [\#29](https://github.com/shelljs/shelljs/pull/29) ([ando-takahiro](https://github.com/ando-takahiro)) - -a includes . and ..; -A does not [\#28](https://github.com/shelljs/shelljs/pull/28) ([aeosynth](https://github.com/aeosynth)) ## [v0.0.7](https://github.com/shelljs/shelljs/tree/v0.0.7) (2012-09-23) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.0.6...v0.0.7) **Closed issues:** - gh-pages: clicking 'fork me' just reloads the page [\#26](https://github.com/shelljs/shelljs/issues/26) - Not declared local var implies possible memory leak [\#21](https://github.com/shelljs/shelljs/issues/21) - Cannot echo a string that starts with - [\#20](https://github.com/shelljs/shelljs/issues/20) - Unexpected cp behaviour with directories [\#15](https://github.com/shelljs/shelljs/issues/15) **Merged pull requests:** - add primaries to \_test [\#23](https://github.com/shelljs/shelljs/pull/23) ([aeosynth](https://github.com/aeosynth)) ## [v0.0.6](https://github.com/shelljs/shelljs/tree/v0.0.6) (2012-08-07) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.0.6pre2...v0.0.6) **Merged pull requests:** - Fixed a global variable leak [\#16](https://github.com/shelljs/shelljs/pull/16) ([dallonf](https://github.com/dallonf)) ## [v0.0.6pre2](https://github.com/shelljs/shelljs/tree/v0.0.6pre2) (2012-05-25) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.0.6pre1...v0.0.6pre2) ## [v0.0.6pre1](https://github.com/shelljs/shelljs/tree/v0.0.6pre1) (2012-05-25) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.0.5...v0.0.6pre1) ## [v0.0.5](https://github.com/shelljs/shelljs/tree/v0.0.5) (2012-05-24) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.0.5pre4...v0.0.5) **Closed issues:** - global.key assigned value 'async' as a result of shell.exec\(...\) [\#12](https://github.com/shelljs/shelljs/issues/12) **Merged pull requests:** - Add support for grep option -v. [\#13](https://github.com/shelljs/shelljs/pull/13) ([kkujala](https://github.com/kkujala)) ## [v0.0.5pre4](https://github.com/shelljs/shelljs/tree/v0.0.5pre4) (2012-03-27) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.0.5pre3...v0.0.5pre4) ## [v0.0.5pre3](https://github.com/shelljs/shelljs/tree/v0.0.5pre3) (2012-03-27) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.0.5pre2...v0.0.5pre3) ## [v0.0.5pre2](https://github.com/shelljs/shelljs/tree/v0.0.5pre2) (2012-03-26) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.0.5pre1...v0.0.5pre2) ## [v0.0.5pre1](https://github.com/shelljs/shelljs/tree/v0.0.5pre1) (2012-03-26) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.0.4...v0.0.5pre1) **Closed issues:** - rm\(\) does not respect read/write modes [\#6](https://github.com/shelljs/shelljs/issues/6) ## [v0.0.4](https://github.com/shelljs/shelljs/tree/v0.0.4) (2012-03-22) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.0.3...v0.0.4) **Closed issues:** - "For convenient iteration via `for in`, ..."? [\#4](https://github.com/shelljs/shelljs/issues/4) ## [v0.0.3](https://github.com/shelljs/shelljs/tree/v0.0.3) (2012-03-21) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.0.2...v0.0.3) ## [v0.0.2](https://github.com/shelljs/shelljs/tree/v0.0.2) (2012-03-15) [Full Changelog](https://github.com/shelljs/shelljs/compare/v0.0.2pre1...v0.0.2) ## [v0.0.2pre1](https://github.com/shelljs/shelljs/tree/v0.0.2pre1) (2012-03-03) \* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*shelljs-0.7.5/CONTRIBUTING.md000066400000000000000000000022041300431262200154070ustar00rootroot00000000000000# Contributing ## Filing a bug report We love to receive bug reports (we're always trying to make ShellJS more stable). If you've found a bug, please follow these steps: - Search for any issues that may have been created already. We often receive duplicates, and cutting down on this is helpful. If someone else has already reported it, please ping that issue thread. - Let us know your version of NodeJS (`node -v`), your version of ShellJS (from `package.json`), your OS, and any other useful information. - Give an example ShellJS command to reproduce the error. ## Pull requests PRs are welcome! However, we ask that you follow a few guidelines: - Please add tests for all changes/new features. - Make sure your code passes `npm test`. Please check the CI (both Appveyor and Travis). If you can't figure out why something doesn't work, feel free to ask for help. - Make changes to the documentation *within the source files*, not in the README. Then update the README by running `node scripts/generate-docs.js`. - Please keep your PR up to date (either via rebase or by pressing the "update branch" button on Github). shelljs-0.7.5/LICENSE000066400000000000000000000030601300431262200141640ustar00rootroot00000000000000Copyright (c) 2012, Artur Adib All rights reserved. You may use this project under the terms of the New BSD license as follows: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Artur Adib nor the names of the contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARTUR ADIB BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. shelljs-0.7.5/MAINTAINERS000066400000000000000000000002041300431262200146510ustar00rootroot00000000000000Ari Porad (@ariporad) Nate Fischer (@nfischer) Artur Adib (@arturadib) shelljs-0.7.5/README.md000066400000000000000000000520371300431262200144460ustar00rootroot00000000000000# ShellJS - Unix shell commands for Node.js [![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg?style=flat-square)](https://gitter.im/shelljs/shelljs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Travis](https://img.shields.io/travis/shelljs/shelljs/master.svg?style=flat-square&label=unix)](https://travis-ci.org/shelljs/shelljs) [![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) [![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 supports node `v0.11`, `v0.12`, `v4`, `v5`, `v6`, and all releases of iojs. The project is [unit-tested](http://travis-ci.org/shelljs/shelljs) and battled-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 + [Zepto](http://zeptojs.com) - jQuery-compatible JavaScript library for modern browsers + [Yeoman](http://yeoman.io/) - Web application stack and development tool + [Deployd.com](http://deployd.com) - Open source PaaS for quick API backend generation + And [many more](https://npmjs.org/browse/depended/shelljs). 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)! Upgrading from an older version? Check out our [breaking changes](https://github.com/shelljs/shelljs/wiki/Breaking-Changes) page to see what changes to watch out for while upgrading. ## Command line use If you just want cross platform UNIX commands, checkout our new project [shelljs/shx](https://github.com/shelljs/shx), a utility to expose `shelljs` to the command line. For example: ``` $ shx mkdir -p foo $ shx touch foo/bar.txt $ shx rm -rf foo ``` ## A quick note about the docs For documentation on all the latest features, check out our [README](https://github.com/shelljs/shelljs). To read docs that are consistent with the latest release, check out [the npm page](https://www.npmjs.com/package/shelljs) or [shelljs.org](http://documentup.com/shelljs/shelljs). ## Installing Via npm: ```bash $ npm install [-g] shelljs ``` 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'); if (!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'); 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); }); cd('..'); // Run external tool synchronously if (exec('git commit -am "Auto-commit"').code !== 0) { echo('Error: Git commit failed'); 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`. Example: ```javascript var shell = require('shelljs'); shell.echo('hello world'); ``` ## Command reference All commands run synchronously, unless otherwise stated. All commands accept standard bash globbing characters (`*`, `?`, etc.), compatible with the [node glob module](https://github.com/isaacs/node-glob). For less-commonly used commands and features, please check out our [wiki page](https://github.com/shelljs/shelljs/wiki). ### cd([dir]) Changes to directory `dir` for the duration of the script. Changes to home directory if no argument is supplied. ### pwd() Returns the current directory. ### 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. ### 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`. ### cp([options,] source [, source ...], dest) ### cp([options,] source_array, dest) Available options: + `-f`: force (default behavior) + `-n`: no-clobber + `-u`: only copy if source is newer than dest + `-r`, `-R`: recursive + `-L`: follow symlinks + `-P`: don't follow symlinks Examples: ```javascript cp('file1', 'dir1'); cp('-R', 'path/to/dir/', '~/newCopy/'); cp('-Rf', '/tmp/*', '/usr/local/*', '/home/tmp'); cp('-Rf', ['/tmp/*', '/usr/local/*'], '/home/tmp'); // same as above ``` Copies files. ### 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. ### 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. ### 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. ### 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. ### 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). ### head([{'-n': \},] file [, file ...]) ### head([{'-n': \},] file_array) Available options: + `-n `: Show the first `` lines of the files Examples: ```javascript var str = head({'-n': 1}, 'file*.txt'); var str = head('file1', 'file2'); var str = head(['file1', 'file2']); // same as above ``` Read the start of a file. ### tail([{'-n': \},] file [, file ...]) ### tail([{'-n': \},] file_array) Available options: + `-n `: Show the last `` lines of the files Examples: ```javascript var str = tail({'-n': 1}, 'file*.txt'); var str = tail('file1', 'file2'); var str = tail(['file1', 'file2']); // same as above ``` Read the end of a file. ### ShellString.prototype.to(file) Examples: ```javascript cat('input.txt').to('output.txt'); ``` Analogous to the redirection operator `>` in Unix, but works with ShellStrings (such as those returned by `cat`, `grep`, etc). _Like Unix redirections, `to()` will overwrite any existing file!_ ### ShellString.prototype.toEnd(file) Examples: ```javascript cat('input.txt').toEnd('output.txt'); ``` Analogous to the redirect-and-append operator `>>` in Unix, but works with ShellStrings (such as those returned by `cat`, `grep`, etc). ### 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. ### sort([options,] file [, file ...]) ### sort([options,] file_array) Available options: + `-r`: Reverse the result of comparisons + `-n`: Compare according to numerical value Examples: ```javascript sort('foo.txt', 'bar.txt'); sort('-r', 'foo.txt'); ``` Return the contents of the files, sorted line-by-line. Sorting multiple files mixes their content, just like unix sort does. ### uniq([options,] [input, [output]]) Available options: + `-i`: Ignore case while comparing + `-c`: Prefix lines by the number of occurrences + `-d`: Only print duplicate lines, one for each group of identical lines Examples: ```javascript uniq('foo.txt'); uniq('-i', 'foo.txt'); uniq('-cd', 'foo.txt', 'bar.txt'); ``` Filter adjacent matching lines from input ### 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. + `-l`: Print only filenames of matching files 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`. ### 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. ### echo([options,] string [, string ...]) Available options: + `-e`: interpret backslash escapes (default) Examples: ```javascript echo('hello world'); var str = echo('hello world'); ``` Prints string to stdout, and returns string with additional utility methods like `.to()`. ### 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. ### 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. ### 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 ### 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. ### exit(code) Exits the current process with the given exit code. ### env['VAR_NAME'] Object containing environment variables (both getter and setter). Shortcut to process.env. ### 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. + 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}).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, this returns a ShellString (compatible with ShellJS v0.6.x, which returns an object of the form `{ code:..., stdout:... , stderr:... }`). Otherwise, this returns the child process object, and the `callback` gets the arguments `(code, stdout, stderr)`. Not seeing the behavior you want? `exec()` runs everything through `sh` by default (or `cmd.exe` on Windows), which differs from `bash`. If you need bash-specific behavior, try out the `{shell: 'path/to/bash'}` option. **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. ### 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. ### touch([options,] file [, file ...]) ### touch([options,] file_array) 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)*. ### set(options) Available options: + `+/-e`: exit upon error (`config.fatal`) + `+/-v`: verbose: show all commands (`config.verbose`) + `+/-f`: disable filename expansion (globbing) Examples: ```javascript set('-e'); // exit upon first error set('+e'); // this undoes a "set('-e')" ``` Sets global configuration variables ## Non-Unix commands ### 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). ### error() Tests if error occurred in the last command. Returns a truthy value if an error returned and a falsy value otherwise. **Note**: do not rely on the return value to be an error message. If you need the last error message, use the `.stderr` attribute from the last command's return value instead. ### ShellString(str) Examples: ```javascript var foo = ShellString('hello world'); ``` Turns a regular string into a string-like object similar to what each command returns. This has special methods, like `.to()` and `.toEnd()` ### Pipes Examples: ```javascript grep('foo', 'file1.txt', 'file2.txt').sed(/o/g, 'a').to('output.txt'); echo('files with o\'s in the name:\n' + ls().grep('o')); cat('test.js').exec('node'); // pipe to exec() call ``` Commands can send their output to another command in a pipe-like fashion. `sed`, `grep`, `cat`, `exec`, `to`, and `toEnd` can appear on the right-hand side of a pipe. Pipes can be chained. ## Configuration ### config.silent Example: ```javascript var sh = require('shelljs'); var silentState = sh.config.silent; // save old silent state sh.config.silent = true; /* ... */ sh.config.silent = silentState; // restore old silent state ``` Suppresses all command output if `true`, except for `echo()` calls. Default is `false`. ### config.fatal Example: ```javascript require('shelljs/global'); config.fatal = true; // or set('-e'); cp('this_file_does_not_exist', '/dev/null'); // throws Error here /* more commands... */ ``` If `true` the script will throw a Javascript error when any shell.js command encounters an error. Default is `false`. This is analogous to Bash's `set -e` ### config.verbose Example: ```javascript config.verbose = true; // or set('-v'); cd('dir/'); ls('subdir/'); ``` Will print each command as follows: ``` cd dir/ ls subdir/ ``` ### config.globOptions Example: ```javascript config.globOptions = {nodir: true}; ``` Use this value for calls to `glob.sync()` instead of the default options. ## Team | [![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://github.com/nfischer) | [Ari Porad](http://github.com/ariporad) | shelljs-0.7.5/RELEASE.md000066400000000000000000000007531300431262200145670ustar00rootroot00000000000000# Release steps 1. Ensure master passes CI tests 2. `npm run gendocs` 3. Bump version, create tags, push, and release: - `$ npm run ` >`major` - breaking API changes >`minor` - backwards-compatible features >`patch` - backwards-compatible bug fixes 4. Update CHANGELOG.md - `$ npm run changelog` - `$ git push` 5. Generate the documentup website by visiting [http://documentup.com/shelljs/shelljs/__recompile] in your browser shelljs-0.7.5/appveyor.yml000066400000000000000000000007001300431262200155450ustar00rootroot00000000000000environment: matrix: - nodejs_version: '6' - nodejs_version: '5' - nodejs_version: '4' version: '{build}' # Install scripts. (runs after repo cloning) install: - ps: Install-Product node $env:nodejs_version - npm -g install npm@latest - set PATH=%APPDATA%\npm;%PATH% - node --version - npm --version - npm install matrix: fast_finish: true # No need for MSBuild on this project build: off test_script: - npm test shelljs-0.7.5/bin/000077500000000000000000000000001300431262200137305ustar00rootroot00000000000000shelljs-0.7.5/bin/shjs000077500000000000000000000017431300431262200146320ustar00rootroot00000000000000#!/usr/bin/env node require('../global'); if (process.argv.length < 3) { console.log('ShellJS: missing argument (script name)'); console.log(); process.exit(1); } var args, scriptName = process.argv[2]; env['NODE_PATH'] = __dirname + '/../..'; if (!scriptName.match(/\.js/) && !scriptName.match(/\.coffee/)) { if (test('-f', scriptName + '.js')) scriptName += '.js'; if (test('-f', scriptName + '.coffee')) scriptName += '.coffee'; } if (!test('-f', scriptName)) { console.log('ShellJS: script not found ('+scriptName+')'); console.log(); process.exit(1); } args = process.argv.slice(3); for (var i = 0, l = args.length; i < l; i++) { if (args[i][0] !== "-"){ args[i] = '"' + args[i] + '"'; // fixes arguments with multiple words } } var path = require('path'); var extensions = require('interpret').extensions; var rechoir = require('rechoir'); rechoir.prepare(extensions, scriptName); require(require.resolve(path.resolve(process.cwd(), scriptName))); shelljs-0.7.5/global.js000066400000000000000000000005411300431262200147560ustar00rootroot00000000000000/* eslint no-extend-native: 0 */ var shell = require('./shell.js'); var common = require('./src/common'); Object.keys(shell).forEach(function (cmd) { global[cmd] = shell[cmd]; }); var _to = require('./src/to'); String.prototype.to = common.wrap('to', _to); var _toEnd = require('./src/toEnd'); String.prototype.toEnd = common.wrap('toEnd', _toEnd); shelljs-0.7.5/make.js000066400000000000000000000024521300431262200144360ustar00rootroot00000000000000require('./global'); 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 setTimeout(function() { var t; if (args.length === 1 && args[0] === '--help') { console.log('Available targets:'); for (t in global.target) console.log(' ' + t); return; } // Wrap targets to prevent duplicate execution for (t in global.target) { (function(t, oldTarget){ // Wrap it global.target[t] = function() { if (!oldTarget.done){ oldTarget.done = true; oldTarget.result = oldTarget.apply(oldTarget, arguments); } return oldTarget.result; }; })(t, global.target[t]); } // Execute desired targets if (args.length > 0) { args.forEach(function(arg) { if (arg in global.target) global.target[arg](targetArgs); else { console.log('no such target: ' + arg); } }); } else if ('all' in global.target) { global.target.all(targetArgs); } }, 0); shelljs-0.7.5/package.json000066400000000000000000000026711300431262200154540ustar00rootroot00000000000000{ "name": "shelljs", "version": "0.7.5", "description": "Portable Unix shell commands for Node.js", "keywords": [ "shelljs", "bash", "unix", "shell", "makefile", "make", "jake", "synchronous" ], "contributors": [ "Ari Porad (http://ariporad.com/)", "Nate Fischer (https://github.com/nfischer)" ], "repository": { "type": "git", "url": "git://github.com/shelljs/shelljs.git" }, "license": "BSD-3-Clause", "homepage": "http://github.com/shelljs/shelljs", "main": "./shell.js", "scripts": { "posttest": "npm run lint", "test": "node scripts/run-tests", "gendocs": "node scripts/generate-docs", "lint": "eslint .", "after-travis": "travis-check-changes", "changelog": "shelljs-changelog", "release:major": "shelljs-release major", "release:minor": "shelljs-release minor", "release:patch": "shelljs-release patch" }, "bin": { "shjs": "./bin/shjs" }, "dependencies": { "glob": "^7.0.0", "interpret": "^1.0.0", "rechoir": "^0.6.2" }, "devDependencies": { "eslint": "^2.0.0", "eslint-config-airbnb-base": "^3.0.0", "eslint-plugin-import": "^1.11.1", "coffee-script": "^1.10.0", "shelljs-changelog": "^0.2.0", "shelljs-release": "^0.2.0", "travis-check-changes": "^0.2.0" }, "optionalDependencies": {}, "engines": { "node": ">=0.11.0", "iojs": "*" } } shelljs-0.7.5/plugin.js000066400000000000000000000007371300431262200150230ustar00rootroot00000000000000// Various utilties exposed to plugins require('./shell'); // Create the ShellJS instance (mandatory) var common = require('./src/common'); var exportedAttributes = [ 'error', // For signaling errors from within commands 'parseOptions', // For custom option parsing 'readFromPipe', // For commands with the .canReceivePipe attribute 'register', // For registering plugins ]; exportedAttributes.forEach(function (attr) { exports[attr] = common[attr]; }); shelljs-0.7.5/scripts/000077500000000000000000000000001300431262200146475ustar00rootroot00000000000000shelljs-0.7.5/scripts/generate-docs.js000077500000000000000000000014111300431262200177250ustar00rootroot00000000000000#!/usr/bin/env node /* globals cat, cd, echo, grep, sed, ShellString */ require('../global'); echo('Appending docs to README.md'); cd(__dirname + '/..'); // Extract docs from shell.js var docs = grep('^//@', 'shell.js'); // Now extract docs from the appropriate src/*.js files 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 ShellString(cat('README.md').replace(/## Command reference(.|\n)*\n## Team/, '## Command reference\n## Team')).to('README.md'); // Append new docs to README sed('-i', /## Command reference/, '## Command reference\n\n' + docs, 'README.md'); echo('All done.'); shelljs-0.7.5/scripts/run-tests.js000077500000000000000000000012661300431262200171610ustar00rootroot00000000000000#!/usr/bin/env node /* globals cd, echo, exec, exit, ls */ require('../global'); var failed = false; // // Unit tests // cd(__dirname + '/../test'); ls('*.js').forEach(function (file) { echo('Running test:', file); if (exec(JSON.stringify(process.execPath) + ' ' + file).code !== 123) { // 123 avoids false positives (e.g. premature exit) failed = true; echo('*** TEST FAILED! (missing exit code "123")'); echo(); } }); echo(); if (failed) { echo('*******************************************************'); echo('WARNING: Some tests did not pass!'); echo('*******************************************************'); exit(1); } else { echo('All tests passed.'); } shelljs-0.7.5/shell.js000066400000000000000000000106461300431262200146340ustar00rootroot00000000000000// // ShellJS // Unix shell commands on top of Node's API // // Copyright (c) 2012 Artur Adib // http://github.com/arturadib/shelljs // var common = require('./src/common'); //@ //@ All commands run synchronously, unless otherwise stated. //@ All commands accept standard bash globbing characters (`*`, `?`, etc.), //@ compatible with the [node glob module](https://github.com/isaacs/node-glob). //@ //@ For less-commonly used commands and features, please check out our [wiki //@ page](https://github.com/shelljs/shelljs/wiki). //@ // Boilerplate // ----------- // Copy the code block below here & replace variables with appropiate values // ``` // //@include ./src/fileName // var functionName = require('./src/fileName'); // exports.nameOfCommand = common.wrap(nameOfCommand, functionName, {globStart: firstIndexToExpand}); // ``` // // The //@include includes the docs for that command // // firstIndexToExpand should usually be 1 (so, put {globStart: 1}) // Increase this value if the command takes arguments that shouldn't be expanded // with wildcards, such as with the regexes for sed & grep //@include ./src/cd require('./src/cd'); //@include ./src/pwd require('./src/pwd'); //@include ./src/ls require('./src/ls'); //@include ./src/find require('./src/find'); //@include ./src/cp require('./src/cp'); //@include ./src/rm require('./src/rm'); //@include ./src/mv require('./src/mv'); //@include ./src/mkdir require('./src/mkdir'); //@include ./src/test require('./src/test'); //@include ./src/cat require('./src/cat'); //@include ./src/head require('./src/head'); //@include ./src/tail require('./src/tail'); //@include ./src/to require('./src/to'); //@include ./src/toEnd require('./src/toEnd'); //@include ./src/sed require('./src/sed'); //@include ./src/sort require('./src/sort'); //@include ./src/uniq require('./src/uniq'); //@include ./src/grep require('./src/grep'); //@include ./src/which require('./src/which'); //@include ./src/echo require('./src/echo'); //@include ./src/dirs require('./src/dirs'); //@include ./src/ln require('./src/ln'); //@ //@ ### exit(code) //@ Exits the current process with the given exit code. exports.exit = process.exit; //@ //@ ### env['VAR_NAME'] //@ Object containing environment variables (both getter and setter). Shortcut to process.env. exports.env = process.env; //@include ./src/exec require('./src/exec'); //@include ./src/chmod require('./src/chmod'); //@include ./src/touch require('./src/touch'); //@include ./src/set require('./src/set'); //@ //@ ## Non-Unix commands //@ //@include ./src/tempdir require('./src/tempdir'); //@include ./src/error exports.error = require('./src/error'); //@include ./src/common exports.ShellString = common.ShellString; //@ //@ ### Pipes //@ //@ Examples: //@ //@ ```javascript //@ grep('foo', 'file1.txt', 'file2.txt').sed(/o/g, 'a').to('output.txt'); //@ echo('files with o\'s in the name:\n' + ls().grep('o')); //@ cat('test.js').exec('node'); // pipe to exec() call //@ ``` //@ //@ Commands can send their output to another command in a pipe-like fashion. //@ `sed`, `grep`, `cat`, `exec`, `to`, and `toEnd` can appear on the right-hand //@ side of a pipe. Pipes can be chained. //@ //@ ## Configuration //@ exports.config = common.config; //@ //@ ### config.silent //@ //@ Example: //@ //@ ```javascript //@ var sh = require('shelljs'); //@ var silentState = sh.config.silent; // save old silent state //@ sh.config.silent = true; //@ /* ... */ //@ sh.config.silent = silentState; // restore old silent state //@ ``` //@ //@ Suppresses all command output if `true`, except for `echo()` calls. //@ Default is `false`. //@ //@ ### config.fatal //@ //@ Example: //@ //@ ```javascript //@ require('shelljs/global'); //@ config.fatal = true; // or set('-e'); //@ cp('this_file_does_not_exist', '/dev/null'); // throws Error here //@ /* more commands... */ //@ ``` //@ //@ If `true` the script will throw a Javascript error when any shell.js //@ command encounters an error. Default is `false`. This is analogous to //@ Bash's `set -e` //@ //@ ### config.verbose //@ //@ Example: //@ //@ ```javascript //@ config.verbose = true; // or set('-v'); //@ cd('dir/'); //@ ls('subdir/'); //@ ``` //@ //@ Will print each command as follows: //@ //@ ``` //@ cd dir/ //@ ls subdir/ //@ ``` //@ //@ ### config.globOptions //@ //@ Example: //@ //@ ```javascript //@ config.globOptions = {nodir: true}; //@ ``` //@ //@ Use this value for calls to `glob.sync()` instead of the default options. shelljs-0.7.5/src/000077500000000000000000000000001300431262200137475ustar00rootroot00000000000000shelljs-0.7.5/src/cat.js000066400000000000000000000016361300431262200150620ustar00rootroot00000000000000var common = require('./common'); var fs = require('fs'); common.register('cat', _cat, { canReceivePipe: true, }); //@ //@ ### 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). function _cat(options, files) { var cat = common.readFromPipe(); if (!files && !cat) common.error('no paths given'); files = [].slice.call(arguments, 1); files.forEach(function (file) { if (!fs.existsSync(file)) { common.error('no such file or directory: ' + file); } cat += fs.readFileSync(file, 'utf8'); }); return cat; } module.exports = _cat; shelljs-0.7.5/src/cd.js000066400000000000000000000016321300431262200146750ustar00rootroot00000000000000var fs = require('fs'); var common = require('./common'); common.register('cd', _cd, {}); //@ //@ ### 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 (!process.env.OLDPWD) { common.error('could not find previous directory'); } else { dir = process.env.OLDPWD; } } try { var curDir = process.cwd(); process.chdir(dir); process.env.OLDPWD = curDir; } catch (e) { // something went wrong, let's figure out the error var err; try { fs.statSync(dir); // if this succeeds, it must be some sort of file err = 'not a directory: ' + dir; } catch (e2) { err = 'no such file or directory: ' + dir; } if (err) common.error(err); } return ''; } module.exports = _cd; shelljs-0.7.5/src/chmod.js000066400000000000000000000150501300431262200154000ustar00rootroot00000000000000var 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. STICKY: parseInt('01000', 8), SETGID: parseInt('02000', 8), SETUID: parseInt('04000', 8), TYPE_MASK: parseInt('0770000', 8) }; }({ EXEC: 1, WRITE: 2, READ: 4 })); common.register('chmod', _chmod, { }); //@ //@ ### 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. [].unshift.call(arguments, ''); } else { common.error('You must specify a file.'); } } options = common.parseOptions(options, { 'R': 'recursive', 'c': 'changes', 'v': 'verbose' }); filePattern = [].slice.call(arguments, 2); var files; // TODO: replace this with a call to common.expand() if (options.recursive) { files = []; 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 = 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) { 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; default: common.error('Could not recognize operator: `' + operator + '`'); } 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); } }); return ''; } module.exports = _chmod; shelljs-0.7.5/src/common.js000066400000000000000000000264001300431262200155770ustar00rootroot00000000000000// Ignore warning about 'new String()' /* eslint no-new-wrappers: 0 */ 'use strict'; var os = require('os'); var fs = require('fs'); var glob = require('glob'); var shell = require('..'); var shellMethods = Object.create(shell); // Module globals var config = { silent: false, fatal: false, verbose: false, noglob: false, globOptions: {}, maxdepth: 255 }; exports.config = config; var state = { error: null, errorCode: 0, currentCmd: 'shell.js', tempDir: null }; exports.state = state; delete process.env.OLDPWD; // initially, there's no previous directory var platform = os.type().match(/^Win/) ? 'win' : 'unix'; exports.platform = platform; // This is populated by calls to commonl.wrap() var pipeMethods = []; function log() { if (!config.silent) { console.error.apply(console, arguments); } } exports.log = log; // Shows error message. Throws if config.fatal is true function error(msg, _code, options) { // Validate input if (typeof msg !== 'string') throw new Error('msg must be a string'); var DEFAULT_OPTIONS = { continue: false, code: 1, prefix: state.currentCmd + ': ', silent: false, }; if (typeof _code === 'number' && typeof options === 'object') { options.code = _code; } else if (typeof _code === 'object') { // no 'code' options = _code; } else if (typeof _code === 'number') { // no 'options' options = { code: _code }; } else if (typeof _code !== 'number') { // only 'msg' options = {}; } options = objectAssign({}, DEFAULT_OPTIONS, options); if (!state.errorCode) state.errorCode = options.code; var logEntry = options.prefix + msg; state.error = state.error ? state.error + '\n' : ''; state.error += logEntry; // Throw an error, or log the entry if (config.fatal) throw new Error(logEntry); if (msg.length > 0 && !options.silent) log(logEntry); if (!options.continue) { throw { msg: 'earlyExit', retValue: (new ShellString('', state.error, state.errorCode)) }; } } exports.error = error; //@ //@ ### ShellString(str) //@ //@ Examples: //@ //@ ```javascript //@ var foo = ShellString('hello world'); //@ ``` //@ //@ Turns a regular string into a string-like object similar to what each //@ command returns. This has special methods, like `.to()` and `.toEnd()` function ShellString(stdout, stderr, code) { var that; if (stdout instanceof Array) { that = stdout; that.stdout = stdout.join('\n'); if (stdout.length > 0) that.stdout += '\n'; } else { that = new String(stdout); that.stdout = stdout; } that.stderr = stderr; that.code = code; // A list of all commands that can appear on the right-hand side of a pipe // (populated by calls to common.wrap()) pipeMethods.forEach(function (cmd) { that[cmd] = shellMethods[cmd].bind(that); }); return that; } 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 string and dictionary as follows: // parseOptions('-a', {'a':'alice', 'b':'bob'}); // 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 = {}; Object.keys(map).forEach(function (letter) { if (map[letter][0] !== '!') { options[map[letter]] = false; } }); if (!opt) return options; // defaults var optionName; if (typeof opt === 'string') { if (opt[0] !== '-') { return options; } // 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)] = false; } else { options[optionName] = true; } } else { error('option not recognized: ' + c); } }); } else if (typeof opt === 'object') { Object.keys(opt).forEach(function (key) { // 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; // 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) { if (!Array.isArray(list)) { throw new TypeError('must be an array'); } var expanded = []; list.forEach(function (listEl) { // Don't expand non-strings if (typeof listEl !== 'string') { expanded.push(listEl); } else { var ret = glob.sync(listEl, config.globOptions); // if glob fails, interpret the string literally expanded = expanded.concat(ret.length > 0 ? ret : [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); } var hash = ''; for (var i = 0; i < count; i++) { hash += randomHash(1); } return hash; } return 'shelljs_' + randomHash(20); } exports.randomFileName = randomFileName; // objectAssign(target_obj, source_obj1 [, source_obj2 ...]) // Ponyfill for Object.assign // objectAssign({A:1}, {b:2}, {c:3}) returns {A:1, b:2, c:3} function objectAssign(target) { var sources = [].slice.call(arguments, 1); sources.forEach(function (source) { Object.keys(source).forEach(function (key) { target[key] = source[key]; }); }); return target; } exports.extend = Object.assign || objectAssign; // Common wrapper for all Unix-like commands that performs glob expansion, // command-logging, and other nice things function wrap(cmd, fn, options) { options = options || {}; if (options.canReceivePipe) { pipeMethods.push(cmd); } return function () { var retValue = null; state.currentCmd = cmd; state.error = null; state.errorCode = 0; try { var args = [].slice.call(arguments, 0); // Log the command to stderr, if appropriate if (config.verbose) { console.error.apply(console, [cmd].concat(args)); } // If this is coming from a pipe, let's set the pipedValue (otherwise, set // it to the empty string) state.pipedValue = (this && typeof this.stdout === 'string') ? this.stdout : ''; if (options.unix === false) { // this branch is for exec() retValue = fn.apply(this, args); } else { // and this branch is for everything else if (args[0] instanceof Object && args[0].constructor.name === 'Object') { // a no-op, allowing the syntax `touch({'-r': file}, ...)` } 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 } // flatten out arrays that are arguments, to make the syntax: // `cp([file1, file2, file3], dest);` // equivalent to: // `cp(file1, file2, file3, dest);` args = args.reduce(function (accum, cur) { if (Array.isArray(cur)) { return accum.concat(cur); } accum.push(cur); return accum; }, []); // Convert ShellStrings (basically just String objects) to regular strings args = args.map(function (arg) { if (arg instanceof Object && arg.constructor.name === 'String') { return arg.toString(); } return arg; }); // 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); } return arg; }); // Perform glob-expansion on all arguments after globStart, but preserve // the arguments before it (like regexes for sed and grep) if (!config.noglob && options.allowGlobbing === true) { args = args.slice(0, options.globStart).concat(expand(args.slice(options.globStart))); } try { // parse options if options are provided if (typeof options.cmdOptions === 'object') { args[0] = parseOptions(args[0], options.cmdOptions); } retValue = fn.apply(this, args); } catch (e) { if (e.msg === 'earlyExit') { retValue = e.retValue; } else { throw e; // this is probably a bug that should be thrown up the call stack } } } } 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.error('ShellJS: internal error'); console.error(e.stack || e); process.exit(1); } if (config.fatal) throw e; } if (options.wrapOutput && (typeof retValue === 'string' || Array.isArray(retValue))) { retValue = new ShellString(retValue, state.error, state.errorCode); } state.currentCmd = 'shell.js'; return retValue; }; } // wrap exports.wrap = wrap; // This returns all the input that is piped into the current command (or the // empty string, if this isn't on the right-hand side of a pipe function _readFromPipe() { return state.pipedValue; } exports.readFromPipe = _readFromPipe; var DEFAULT_WRAP_OPTIONS = { allowGlobbing: true, canReceivePipe: false, cmdOptions: false, globStart: 1, pipeOnly: false, unix: true, wrapOutput: true, overWrite: false, }; // Register a new ShellJS command function _register(name, implementation, wrapOptions) { wrapOptions = wrapOptions || {}; // If an option isn't specified, use the default wrapOptions = objectAssign({}, DEFAULT_WRAP_OPTIONS, wrapOptions); if (shell[name] && !wrapOptions.overWrite) { throw new Error('unable to overwrite `' + name + '` command'); } if (wrapOptions.pipeOnly) { wrapOptions.canReceivePipe = true; shellMethods[name] = wrap(name, implementation, wrapOptions); } else { shell[name] = wrap(name, implementation, wrapOptions); } } exports.register = _register; shelljs-0.7.5/src/cp.js000066400000000000000000000202521300431262200147100ustar00rootroot00000000000000var fs = require('fs'); var path = require('path'); var common = require('./common'); var os = require('os'); common.register('cp', _cp, { cmdOptions: { 'f': '!no_force', 'n': 'no_force', 'u': 'update', 'R': 'recursive', 'r': 'recursive', 'L': 'followsymlink', 'P': 'noFollowsymlink', }, wrapOutput: false, }); // Buffered file copy, synchronous // (Using readFileSync() + writeFileSync() could easily cause a memory overflow // with large files) function copyFileSync(srcFile, destFile, options) { if (!fs.existsSync(srcFile)) { common.error('copyFileSync: no such file or directory: ' + srcFile); } // Check the mtimes of the files if the '-u' flag is provided try { if (options.update && fs.statSync(srcFile).mtime < fs.statSync(destFile).mtime) { return; } } catch (e) { // If we're here, destFile probably doesn't exist, so just do a normal copy } if (fs.lstatSync(srcFile).isSymbolicLink() && !options.followsymlink) { try { fs.lstatSync(destFile); common.unlinkSync(destFile); // re-link it } catch (e) { // it doesn't exist, so no work needs to be done } var symlinkFull = fs.readlinkSync(srcFile); fs.symlinkSync(symlinkFull, destFile, os.platform() === 'win32' ? 'junction' : null); } else { var BUF_LENGTH = 64 * 1024; var buf = new Buffer(BUF_LENGTH); var bytesRead = BUF_LENGTH; var pos = 0; var fdr = null; var 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 = {}; /* Ensure there is not a run away recursive copy. */ if (typeof opts.depth === 'undefined') { opts.depth = 0; } if (opts.depth >= common.config.maxdepth) { // Max depth has been reached, end copy. return; } opts.depth++; // Create the directory where all our junk is moving to; read the mode of the // source directory and mirror it try { var checkDir = fs.statSync(sourceDir); 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); var symlinkFull; if (opts.followsymlink) { if (cpcheckcycle(sourceDir, srcFile)) { // Cycle link found. console.error('Cycle link found.'); symlinkFull = fs.readlinkSync(srcFile); fs.symlinkSync(symlinkFull, destFile, os.platform() === 'win32' ? 'junction' : null); continue; } } if (srcFileStat.isDirectory()) { /* recursion this thing right on back. */ cpdirSyncRecursive(srcFile, destFile, opts); } else if (srcFileStat.isSymbolicLink() && !opts.followsymlink) { symlinkFull = fs.readlinkSync(srcFile); try { fs.lstatSync(destFile); common.unlinkSync(destFile); // re-link it } catch (e) { // it doesn't exist, so no work needs to be done } fs.symlinkSync(symlinkFull, destFile, os.platform() === 'win32' ? 'junction' : null); } else if (srcFileStat.isSymbolicLink() && opts.followsymlink) { srcFileStat = fs.statSync(srcFile); if (srcFileStat.isDirectory()) { cpdirSyncRecursive(srcFile, destFile, opts); } else { copyFileSync(srcFile, destFile, opts); } } 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, opts); } } } // for files } // cpdirSyncRecursive function cpcheckcycle(sourceDir, srcFile) { var srcFileStat = fs.lstatSync(srcFile); if (srcFileStat.isSymbolicLink()) { // Do cycle check. For example: // $ mkdir -p 1/2/3/4 // $ cd 1/2/3/4 // $ ln -s ../../3 link // $ cd ../../../.. // $ cp -RL 1 copy var cyclecheck = fs.statSync(srcFile); if (cyclecheck.isDirectory()) { var sourcerealpath = fs.realpathSync(sourceDir); var symlinkrealpath = fs.realpathSync(srcFile); var re = new RegExp(symlinkrealpath); if (re.test(sourcerealpath)) { return true; } } } return false; } //@ //@ ### cp([options,] source [, source ...], dest) //@ ### cp([options,] source_array, dest) //@ Available options: //@ //@ + `-f`: force (default behavior) //@ + `-n`: no-clobber //@ + `-u`: only copy if source is newer than dest //@ + `-r`, `-R`: recursive //@ + `-L`: follow symlinks //@ + `-P`: don't follow symlinks //@ //@ Examples: //@ //@ ```javascript //@ cp('file1', 'dir1'); //@ cp('-R', 'path/to/dir/', '~/newCopy/'); //@ cp('-Rf', '/tmp/*', '/usr/local/*', '/home/tmp'); //@ cp('-Rf', ['/tmp/*', '/usr/local/*'], '/home/tmp'); // same as above //@ ``` //@ //@ Copies files. function _cp(options, sources, dest) { // If we're missing -R, it actually implies -L (unless -P is explicit) if (options.followsymlink) { options.noFollowsymlink = false; } if (!options.recursive && !options.noFollowsymlink) { options.followsymlink = true; } // Get sources, dest if (arguments.length < 3) { common.error('missing and/or '); } else { sources = [].slice.call(arguments, 1, arguments.length - 1); dest = arguments[arguments.length - 1]; } var destExists = fs.existsSync(dest); var destStat = destExists && fs.statSync(dest); // Dest is not existing dir, but multiple sources given if ((!destExists || !destStat.isDirectory()) && sources.length > 1) { common.error('dest is not a directory (too many sources)'); } // Dest is an existing file, but -n is given if (destExists && destStat.isFile() && options.no_force) { return new common.ShellString('', '', 0); } sources.forEach(function (src) { if (!fs.existsSync(src)) { common.error('no such file or directory: ' + src, { continue: true }); return; // skip file } var srcStat = fs.statSync(src); if (!options.noFollowsymlink && srcStat.isDirectory()) { if (!options.recursive) { // Non-Recursive common.error("omitting directory '" + src + "'", { continue: true }); } else { // Recursive // 'cp /a/source dest' should create 'source' in 'dest' var newDest = (destStat && destStat.isDirectory()) ? path.join(dest, path.basename(src)) : dest; try { fs.statSync(path.dirname(dest)); cpdirSyncRecursive(src, newDest, { no_force: options.no_force, followsymlink: options.followsymlink }); } catch (e) { common.error("cannot create directory '" + dest + "': No such file or directory"); } } } else { // If here, src is a file // When copying to '/path/dir': // thisDest = '/path/dir/file1' var thisDest = dest; if (destStat && destStat.isDirectory()) { thisDest = path.normalize(dest + '/' + path.basename(src)); } if (fs.existsSync(thisDest) && options.no_force) { return; // skip file } copyFileSync(src, thisDest, options); } }); // forEach(src) return new common.ShellString('', common.state.error, common.state.errorCode); } module.exports = _cp; shelljs-0.7.5/src/dirs.js000066400000000000000000000124001300431262200152430ustar00rootroot00000000000000var common = require('./common'); var _cd = require('./cd'); var path = require('path'); common.register('dirs', _dirs, { wrapOutput: false, }); common.register('pushd', _pushd, { wrapOutput: false, }); common.register('popd', _popd, { wrapOutput: false, }); // 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); } 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; shelljs-0.7.5/src/echo.js000066400000000000000000000013471300431262200152300ustar00rootroot00000000000000var common = require('./common'); common.register('echo', _echo, { allowGlobbing: false, }); //@ //@ ### echo([options,] string [, string ...]) //@ Available options: //@ //@ + `-e`: interpret backslash escapes (default) //@ //@ 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(opts, messages) { // allow strings starting with '-', see issue #20 messages = [].slice.call(arguments, opts ? 0 : 1); if (messages[0] === '-e') { // ignore -e messages.shift(); } console.log.apply(console, messages); return messages.join(' '); } module.exports = _echo; shelljs-0.7.5/src/error.js000066400000000000000000000006771300431262200154500ustar00rootroot00000000000000var common = require('./common'); //@ //@ ### error() //@ Tests if error occurred in the last command. Returns a truthy value if an //@ error returned and a falsy value otherwise. //@ //@ **Note**: do not rely on the //@ return value to be an error message. If you need the last error message, use //@ the `.stderr` attribute from the last command's return value instead. function error() { return common.state.error; } module.exports = error; shelljs-0.7.5/src/exec.js000066400000000000000000000227171300431262200152420ustar00rootroot00000000000000var common = require('./common'); var _tempDir = require('./tempdir'); var _pwd = require('./pwd'); var path = require('path'); var fs = require('fs'); var child = require('child_process'); var DEFAULT_MAXBUFFER_SIZE = 20 * 1024 * 1024; common.register('exec', _exec, { unix: false, canReceivePipe: true, wrapOutput: false, }); // 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, pipe) { var tempDir = _tempDir(); var stdoutFile = path.resolve(tempDir + '/' + common.randomFileName()); var stderrFile = path.resolve(tempDir + '/' + common.randomFileName()); var codeFile = path.resolve(tempDir + '/' + common.randomFileName()); var scriptFile = path.resolve(tempDir + '/' + common.randomFileName()); var sleepFile = path.resolve(tempDir + '/' + common.randomFileName()); opts = common.extend({ silent: common.config.silent, cwd: _pwd().toString(), env: process.env, maxBuffer: DEFAULT_MAXBUFFER_SIZE }, opts); var previousStdoutContent = ''; var previousStderrContent = ''; // Echoes stdout and stderr changes from running process, if not silent function updateStream(streamFile) { if (opts.silent || !fs.existsSync(streamFile)) { return; } var previousStreamContent; var procStream; if (streamFile === stdoutFile) { previousStreamContent = previousStdoutContent; procStream = process.stdout; } else { // assume stderr previousStreamContent = previousStderrContent; procStream = process.stderr; } var streamContent = fs.readFileSync(streamFile, 'utf8'); // No changes since last time? if (streamContent.length <= previousStreamContent.length) { return; } procStream.write(streamContent.substr(previousStreamContent.length)); previousStreamContent = streamContent; } 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 = JSON.stringify(process.execPath) + ' ' + JSON.stringify(scriptFile); var script; opts.cwd = path.resolve(opts.cwd); var optString = JSON.stringify(opts); if (typeof child.execSync === 'function') { script = [ "var child = require('child_process')", " , fs = require('fs');", 'var childProcess = child.exec(' + JSON.stringify(cmd) + ', ' + optString + ', function(err) {', ' fs.writeFileSync(' + JSON.stringify(codeFile) + ", err ? err.code.toString() : '0');", '});', 'var stdoutStream = fs.createWriteStream(' + JSON.stringify(stdoutFile) + ');', 'var stderrStream = fs.createWriteStream(' + JSON.stringify(stderrFile) + ');', 'childProcess.stdout.pipe(stdoutStream, {end: false});', 'childProcess.stderr.pipe(stderrStream, {end: false});', 'childProcess.stdout.pipe(process.stdout);', 'childProcess.stderr.pipe(process.stderr);' ].join('\n') + (pipe ? '\nchildProcess.stdin.end(' + JSON.stringify(pipe) + ');\n' : '\n') + [ '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 (opts.silent) { opts.stdio = 'ignore'; } else { opts.stdio = [0, 1, 2]; } // Welcome to the future try { child.execSync(execCommand, opts); } catch (e) { // Clean up immediately if we have an exception try { common.unlinkSync(scriptFile); } catch (e2) {} try { common.unlinkSync(stdoutFile); } catch (e2) {} try { common.unlinkSync(stderrFile); } catch (e2) {} try { common.unlinkSync(codeFile); } catch (e2) {} throw e; } } else { cmd += ' > ' + stdoutFile + ' 2> ' + stderrFile; // works on both win/unix script = [ "var child = require('child_process')", " , fs = require('fs');", 'var childProcess = child.exec(' + JSON.stringify(cmd) + ', ' + optString + ', function(err) {', ' fs.writeFileSync(' + JSON.stringify(codeFile) + ", err ? err.code.toString() : '0');", '});' ].join('\n') + (pipe ? '\nchildProcess.stdin.end(' + JSON.stringify(pipe) + ');\n' : '\n'); fs.writeFileSync(scriptFile, script); 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)) { 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'); } try { common.unlinkSync(sleepFile); } catch (e) {} } // 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) {} if (code !== 0) { common.error('', code, { continue: true }); } var obj = common.ShellString(stdout, stderr, code); return obj; } // execSync() // Wrapper around exec() to enable echoing output to console in real time function execAsync(cmd, opts, pipe, callback) { var stdout = ''; var stderr = ''; opts = common.extend({ silent: common.config.silent, cwd: _pwd().toString(), env: process.env, maxBuffer: DEFAULT_MAXBUFFER_SIZE }, opts); var c = child.exec(cmd, opts, function (err) { if (callback) { callback(err ? err.code : 0, stdout, stderr); } }); if (pipe) c.stdin.end(pipe); c.stdout.on('data', function (data) { stdout += data; if (!opts.silent) process.stdout.write(data); }); c.stderr.on('data', function (data) { stderr += data; if (!opts.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. //@ + 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}).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, this returns a ShellString (compatible with ShellJS v0.6.x, which returns an object //@ of the form `{ code:..., stdout:... , stderr:... }`). Otherwise, this returns the child process //@ object, and the `callback` gets the arguments `(code, stdout, stderr)`. //@ //@ Not seeing the behavior you want? `exec()` runs everything through `sh` //@ by default (or `cmd.exe` on Windows), which differs from `bash`. If you //@ need bash-specific behavior, try out the `{shell: 'path/to/bash'}` option. //@ //@ **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) { options = options || {}; if (!command) common.error('must specify command'); var pipe = common.readFromPipe(); // 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); try { if (options.async) { return execAsync(command, options, pipe, callback); } else { return execSync(command, options, pipe); } } catch (e) { common.error('internal error'); } } module.exports = _exec; shelljs-0.7.5/src/find.js000066400000000000000000000026231300431262200152300ustar00rootroot00000000000000var fs = require('fs'); var path = require('path'); var common = require('./common'); var _ls = require('./ls'); common.register('find', _find, {}); //@ //@ ### 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 === '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({ recursive: true, all: true }, file).forEach(function (subfile) { pushFile(path.join(file, subfile)); }); } }); return list; } module.exports = _find; shelljs-0.7.5/src/grep.js000066400000000000000000000033071300431262200152450ustar00rootroot00000000000000var common = require('./common'); var fs = require('fs'); common.register('grep', _grep, { globStart: 2, // don't glob-expand the regex canReceivePipe: true, cmdOptions: { 'v': 'inverse', 'l': 'nameOnly', }, }); //@ //@ ### 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. //@ + `-l`: Print only filenames of matching files //@ //@ 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`. function _grep(options, regex, files) { // Check if this is coming from a pipe var pipe = common.readFromPipe(); if (!files && !pipe) common.error('no paths given', 2); files = [].slice.call(arguments, 2); if (pipe) { files.unshift('-'); } var grep = []; files.forEach(function (file) { if (!fs.existsSync(file) && file !== '-') { common.error('no such file or directory: ' + file, 2, { continue: true }); return; } var contents = file === '-' ? pipe : fs.readFileSync(file, 'utf8'); var lines = contents.split(/\r*\n/); if (options.nameOnly) { if (contents.match(regex)) { grep.push(file); } } else { lines.forEach(function (line) { var matched = line.match(regex); if ((options.inverse && !matched) || (!options.inverse && matched)) { grep.push(line); } }); } }); return grep.join('\n') + '\n'; } module.exports = _grep; shelljs-0.7.5/src/head.js000066400000000000000000000050201300431262200152030ustar00rootroot00000000000000var common = require('./common'); var fs = require('fs'); common.register('head', _head, { canReceivePipe: true, cmdOptions: { 'n': 'numLines', }, }); // This reads n or more lines, or the entire file, whichever is less. function readSomeLines(file, numLines) { var BUF_LENGTH = 64 * 1024; var buf = new Buffer(BUF_LENGTH); var bytesRead = BUF_LENGTH; var pos = 0; var fdr = null; try { fdr = fs.openSync(file, 'r'); } catch (e) { common.error('cannot read file: ' + file); } var numLinesRead = 0; var ret = ''; while (bytesRead === BUF_LENGTH && numLinesRead < numLines) { bytesRead = fs.readSync(fdr, buf, 0, BUF_LENGTH, pos); var bufStr = buf.toString('utf8', 0, bytesRead); numLinesRead += bufStr.split('\n').length - 1; ret += bufStr; pos += bytesRead; } fs.closeSync(fdr); return ret; } //@ //@ ### head([{'-n': \},] file [, file ...]) //@ ### head([{'-n': \},] file_array) //@ Available options: //@ //@ + `-n `: Show the first `` lines of the files //@ //@ Examples: //@ //@ ```javascript //@ var str = head({'-n': 1}, 'file*.txt'); //@ var str = head('file1', 'file2'); //@ var str = head(['file1', 'file2']); // same as above //@ ``` //@ //@ Read the start of a file. function _head(options, files) { var head = []; var pipe = common.readFromPipe(); if (!files && !pipe) common.error('no paths given'); var idx = 1; if (options.numLines === true) { idx = 2; options.numLines = Number(arguments[1]); } else if (options.numLines === false) { options.numLines = 10; } files = [].slice.call(arguments, idx); if (pipe) { files.unshift('-'); } var shouldAppendNewline = false; files.forEach(function (file) { if (!fs.existsSync(file) && file !== '-') { common.error('no such file or directory: ' + file, { continue: true }); return; } var contents; if (file === '-') { contents = pipe; } else if (options.numLines < 0) { contents = fs.readFileSync(file, 'utf8'); } else { contents = readSomeLines(file, options.numLines); } var lines = contents.split('\n'); var hasTrailingNewline = (lines[lines.length - 1] === ''); if (hasTrailingNewline) { lines.pop(); } shouldAppendNewline = (hasTrailingNewline || options.numLines < lines.length); head = head.concat(lines.slice(0, options.numLines)); }); if (shouldAppendNewline) { head.push(''); // to add a trailing newline once we join } return head.join('\n'); } module.exports = _head; shelljs-0.7.5/src/ln.js000066400000000000000000000035041300431262200147200ustar00rootroot00000000000000var fs = require('fs'); var path = require('path'); var common = require('./common'); common.register('ln', _ln, { cmdOptions: { 's': 'symlink', 'f': 'force', }, }); //@ //@ ### 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) { if (!source || !dest) { common.error('Missing and/or '); } 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', { continue: 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', { continue: 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', { continue: true }); } try { fs.linkSync(source, dest); } catch (err) { common.error(err.message); } } return ''; } module.exports = _ln; shelljs-0.7.5/src/ls.js000066400000000000000000000066071300431262200147340ustar00rootroot00000000000000var path = require('path'); var fs = require('fs'); var common = require('./common'); var glob = require('glob'); var globPatternRecursive = path.sep + '**' + path.sep + '*'; common.register('ls', _ls, { cmdOptions: { 'R': 'recursive', 'A': 'all', 'a': 'all_deprecated', 'd': 'directory', 'l': 'long', }, }); //@ //@ ### 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) { 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 { paths = [].slice.call(arguments, 1); } var list = []; function pushFile(abs, relName, stat) { if (process.platform === 'win32') { relName = relName.replace(/\\/g, '/'); } if (options.long) { stat = stat || fs.lstatSync(abs); list.push(addLsAttributes(relName, stat)); } else { // list.push(path.relative(rel || '.', file)); list.push(relName); } } paths.forEach(function (p) { var stat; try { stat = fs.lstatSync(p); } catch (e) { common.error('no such file or directory: ' + p, 2, { continue: true }); return; } // If the stat succeeded if (stat.isDirectory() && !options.directory) { if (options.recursive) { // use glob, because it's simple glob.sync(p + globPatternRecursive, { dot: options.all }) .forEach(function (item) { pushFile(item, path.relative(p, item)); }); } else if (options.all) { // use fs.readdirSync, because it's fast fs.readdirSync(p).forEach(function (item) { pushFile(path.join(p, item), item); }); } else { // use fs.readdirSync and then filter out secret files fs.readdirSync(p).forEach(function (item) { if (item[0] !== '.') { pushFile(path.join(p, item), item); } }); } } else { pushFile(p, p, stat); } }); // Add methods, to make this more compatible with ShellStrings return list; } function addLsAttributes(pathName, stats) { // Note: this object will contain more information than .toString() returns stats.name = pathName; 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; } module.exports = _ls; shelljs-0.7.5/src/mkdir.js000066400000000000000000000042621300431262200154170ustar00rootroot00000000000000var common = require('./common'); var fs = require('fs'); var path = require('path'); common.register('mkdir', _mkdir, { cmdOptions: { 'p': 'fullpath', }, }); // Recursively creates 'dir' function mkdirSyncRecursive(dir) { var baseDir = path.dirname(dir); // Prevents some potential problems arising from malformed UNCs or // insufficient permissions. /* istanbul ignore next */ if (baseDir === dir) { common.error('dirname() failed: [' + 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) { 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) { try { fs.lstatSync(dir); if (!options.fullpath) { common.error('path already exists: ' + dir, { continue: true }); } return; // skip dir } catch (e) { // do nothing } // 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, { continue: true }); return; // skip dir } try { if (options.fullpath) { mkdirSyncRecursive(dir); } else { fs.mkdirSync(dir, parseInt('0777', 8)); } } catch (e) { if (e.code === 'EACCES') { common.error('cannot create directory ' + dir + ': Permission denied'); } else { throw e; } } }); return ''; } // mkdir module.exports = _mkdir; shelljs-0.7.5/src/mv.js000066400000000000000000000051011300431262200147240ustar00rootroot00000000000000var fs = require('fs'); var path = require('path'); var common = require('./common'); var cp = require('./cp'); var rm = require('./rm'); common.register('mv', _mv, { cmdOptions: { 'f': '!no_force', 'n': 'no_force', }, }); //@ //@ ### 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. function _mv(options, sources, dest) { // Get sources, dest if (arguments.length < 3) { common.error('missing and/or '); } 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 { common.error('invalid arguments'); } var exists = fs.existsSync(dest); var 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, { continue: 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, { continue: true }); return; // skip file } if (path.resolve(src) === path.dirname(path.resolve(thisDest))) { common.error('cannot move to self: ' + src, { continue: true }); return; // skip file } try { fs.renameSync(src, thisDest); } 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 cp('-r', src, thisDest); rm('-rf', src); } } }); // forEach(src) return ''; } // mv module.exports = _mv; shelljs-0.7.5/src/popd.js000066400000000000000000000000171300431262200152450ustar00rootroot00000000000000// see dirs.js shelljs-0.7.5/src/pushd.js000066400000000000000000000000171300431262200154260ustar00rootroot00000000000000// see dirs.js shelljs-0.7.5/src/pwd.js000066400000000000000000000004221300431262200150750ustar00rootroot00000000000000var path = require('path'); var common = require('./common'); common.register('pwd', _pwd, { allowGlobbing: false, }); //@ //@ ### pwd() //@ Returns the current directory. function _pwd() { var pwd = path.resolve(process.cwd()); return pwd; } module.exports = _pwd; shelljs-0.7.5/src/rm.js000066400000000000000000000102101300431262200147150ustar00rootroot00000000000000var common = require('./common'); var fs = require('fs'); common.register('rm', _rm, { cmdOptions: { 'f': 'force', 'r': 'recursive', 'R': 'recursive', }, }); // 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]; var currFile = fs.lstatSync(file); if (currFile.isDirectory()) { // Recursive function back to the beginning rmdirSyncRecursive(file, force); } 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, { continue: 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, { continue: 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. function _rm(options, files) { if (!files) common.error('no paths given'); // Convert to array files = [].slice.call(arguments, 1); files.forEach(function (file) { var stats; try { stats = fs.lstatSync(file); // test for existence } catch (e) { // Path does not exist, no force flag given if (!options.force) { common.error('no such file or directory: ' + file, { continue: true }); } return; // skip file } // If here, path exists 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, { continue: 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', { continue: true }); return; // skip path } // Recursively remove existing directory if (stats.isDirectory() && options.recursive) { rmdirSyncRecursive(file, options.force); } }); // forEach(file) return ''; } // rm module.exports = _rm; shelljs-0.7.5/src/sed.js000066400000000000000000000037711300431262200150700ustar00rootroot00000000000000var common = require('./common'); var fs = require('fs'); common.register('sed', _sed, { globStart: 3, // don't glob-expand regexes canReceivePipe: true, cmdOptions: { 'i': 'inplace', }, }); //@ //@ ### 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) { // Check if this is coming from a pipe var pipe = common.readFromPipe(); if (typeof replacement !== 'string' && typeof replacement !== 'function') { 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 && !pipe) { common.error('no files given'); } files = [].slice.call(arguments, 3); if (pipe) { files.unshift('-'); } var sed = []; files.forEach(function (file) { if (!fs.existsSync(file) && file !== '-') { common.error('no such file or directory: ' + file, 2, { continue: true }); return; } var contents = file === '-' ? pipe : fs.readFileSync(file, 'utf8'); var lines = contents.split(/\r*\n/); var result = lines.map(function (line) { return line.replace(regex, replacement); }).join('\n'); sed.push(result); if (options.inplace) { fs.writeFileSync(file, result, 'utf8'); } }); return sed.join('\n'); } module.exports = _sed; shelljs-0.7.5/src/set.js000066400000000000000000000025251300431262200151040ustar00rootroot00000000000000var common = require('./common'); common.register('set', _set, { allowGlobbing: false, wrapOutput: false, }); //@ //@ ### set(options) //@ Available options: //@ //@ + `+/-e`: exit upon error (`config.fatal`) //@ + `+/-v`: verbose: show all commands (`config.verbose`) //@ + `+/-f`: disable filename expansion (globbing) //@ //@ 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', 'f': 'noglob' }); if (negate) { Object.keys(options).forEach(function (key) { options[key] = !options[key]; }); } Object.keys(options).forEach(function (key) { // 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; shelljs-0.7.5/src/sort.js000066400000000000000000000044671300431262200153070ustar00rootroot00000000000000var common = require('./common'); var fs = require('fs'); common.register('sort', _sort, { canReceivePipe: true, cmdOptions: { 'r': 'reverse', 'n': 'numerical', }, }); // parse out the number prefix of a line function parseNumber(str) { var match = str.match(/^\s*(\d*)\s*(.*)$/); return { num: Number(match[1]), value: match[2] }; } // compare two strings case-insensitively, but examine case for strings that are // case-insensitive equivalent function unixCmp(a, b) { var aLower = a.toLowerCase(); var bLower = b.toLowerCase(); return (aLower === bLower ? -1 * a.localeCompare(b) : // unix sort treats case opposite how javascript does aLower.localeCompare(bLower)); } // compare two strings in the fashion that unix sort's -n option works function numericalCmp(a, b) { var objA = parseNumber(a); var objB = parseNumber(b); if (objA.hasOwnProperty('num') && objB.hasOwnProperty('num')) { return ((objA.num !== objB.num) ? (objA.num - objB.num) : unixCmp(objA.value, objB.value)); } else { return unixCmp(objA.value, objB.value); } } //@ //@ ### sort([options,] file [, file ...]) //@ ### sort([options,] file_array) //@ Available options: //@ //@ + `-r`: Reverse the result of comparisons //@ + `-n`: Compare according to numerical value //@ //@ Examples: //@ //@ ```javascript //@ sort('foo.txt', 'bar.txt'); //@ sort('-r', 'foo.txt'); //@ ``` //@ //@ Return the contents of the files, sorted line-by-line. Sorting multiple //@ files mixes their content, just like unix sort does. function _sort(options, files) { // Check if this is coming from a pipe var pipe = common.readFromPipe(); if (!files && !pipe) common.error('no files given'); files = [].slice.call(arguments, 1); if (pipe) { files.unshift('-'); } var lines = []; files.forEach(function (file) { if (!fs.existsSync(file) && file !== '-') { // exit upon any sort of error common.error('no such file or directory: ' + file); } var contents = file === '-' ? pipe : fs.readFileSync(file, 'utf8'); lines = lines.concat(contents.trimRight().split(/\r*\n/)); }); var sorted; sorted = lines.sort(options.numerical ? numericalCmp : unixCmp); if (options.reverse) { sorted = sorted.reverse(); } return sorted.join('\n') + '\n'; } module.exports = _sort; shelljs-0.7.5/src/tail.js000066400000000000000000000032641300431262200152430ustar00rootroot00000000000000var common = require('./common'); var fs = require('fs'); common.register('tail', _tail, { canReceivePipe: true, cmdOptions: { 'n': 'numLines', }, }); //@ //@ ### tail([{'-n': \},] file [, file ...]) //@ ### tail([{'-n': \},] file_array) //@ Available options: //@ //@ + `-n `: Show the last `` lines of the files //@ //@ Examples: //@ //@ ```javascript //@ var str = tail({'-n': 1}, 'file*.txt'); //@ var str = tail('file1', 'file2'); //@ var str = tail(['file1', 'file2']); // same as above //@ ``` //@ //@ Read the end of a file. function _tail(options, files) { var tail = []; var pipe = common.readFromPipe(); if (!files && !pipe) common.error('no paths given'); var idx = 1; if (options.numLines === true) { idx = 2; options.numLines = Number(arguments[1]); } else if (options.numLines === false) { options.numLines = 10; } options.numLines = -1 * Math.abs(options.numLines); files = [].slice.call(arguments, idx); if (pipe) { files.unshift('-'); } var shouldAppendNewline = false; files.forEach(function (file) { if (!fs.existsSync(file) && file !== '-') { common.error('no such file or directory: ' + file, { continue: true }); return; } var contents = file === '-' ? pipe : fs.readFileSync(file, 'utf8'); var lines = contents.split('\n'); if (lines[lines.length - 1] === '') { lines.pop(); shouldAppendNewline = true; } else { shouldAppendNewline = false; } tail = tail.concat(lines.slice(options.numLines)); }); if (shouldAppendNewline) { tail.push(''); // to add a trailing newline once we join } return tail.join('\n'); } module.exports = _tail; shelljs-0.7.5/src/tempdir.js000066400000000000000000000034671300431262200157630ustar00rootroot00000000000000var common = require('./common'); var os = require('os'); var fs = require('fs'); common.register('tempdir', _tempDir, { allowGlobbing: false, wrapOutput: false, }); // 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; shelljs-0.7.5/src/test.js000066400000000000000000000036531300431262200152730ustar00rootroot00000000000000var common = require('./common'); var fs = require('fs'); common.register('test', _test, { cmdOptions: { 'b': 'block', 'c': 'character', 'd': 'directory', 'e': 'exists', 'f': 'file', 'L': 'link', 'p': 'pipe', 'S': 'socket', }, wrapOutput: false, allowGlobbing: false, }); //@ //@ ### 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'); var canInterpret = false; Object.keys(options).forEach(function (key) { if (options[key] === true) { canInterpret = true; } }); 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(); return false; // fallback } // test module.exports = _test; shelljs-0.7.5/src/to.js000066400000000000000000000016411300431262200147310ustar00rootroot00000000000000var common = require('./common'); var fs = require('fs'); var path = require('path'); common.register('to', _to, { pipeOnly: true, wrapOutput: false, }); //@ //@ ### ShellString.prototype.to(file) //@ //@ Examples: //@ //@ ```javascript //@ cat('input.txt').to('output.txt'); //@ ``` //@ //@ Analogous to the redirection operator `>` in Unix, but works with //@ ShellStrings (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.stdout || this.toString(), 'utf8'); return this; } catch (e) { common.error('could not write to file (code ' + e.code + '): ' + file, { continue: true }); } } module.exports = _to; shelljs-0.7.5/src/toEnd.js000066400000000000000000000015671300431262200153670ustar00rootroot00000000000000var common = require('./common'); var fs = require('fs'); var path = require('path'); common.register('toEnd', _toEnd, { pipeOnly: true, wrapOutput: false, }); //@ //@ ### ShellString.prototype.toEnd(file) //@ //@ Examples: //@ //@ ```javascript //@ cat('input.txt').toEnd('output.txt'); //@ ``` //@ //@ Analogous to the redirect-and-append operator `>>` in Unix, but works with //@ ShellStrings (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.stdout || this.toString(), 'utf8'); return this; } catch (e) { common.error('could not append to file (code ' + e.code + '): ' + file, { continue: true }); } } module.exports = _toEnd; shelljs-0.7.5/src/touch.js000066400000000000000000000052031300431262200154270ustar00rootroot00000000000000var common = require('./common'); var fs = require('fs'); common.register('touch', _touch, { cmdOptions: { 'a': 'atime_only', 'c': 'no_create', 'd': 'date', 'm': 'mtime_only', 'r': 'reference', }, }); //@ //@ ### touch([options,] file [, file ...]) //@ ### touch([options,] file_array) //@ 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) { if (!files) { common.error('no files given'); } else if (typeof files === 'string') { files = [].slice.call(arguments, 1); } else { common.error('file arg should be a string file path or an Array of string file paths'); } files.forEach(function (f) { touchFile(opts, f); }); return ''; } 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; } } shelljs-0.7.5/src/uniq.js000066400000000000000000000042151300431262200152630ustar00rootroot00000000000000var common = require('./common'); var fs = require('fs'); // add c spaces to the left of str function lpad(c, str) { var res = '' + str; if (res.length < c) { res = Array((c - res.length) + 1).join(' ') + res; } return res; } common.register('uniq', _uniq, { canReceivePipe: true, cmdOptions: { 'i': 'ignoreCase', 'c': 'count', 'd': 'duplicates', }, }); //@ //@ ### uniq([options,] [input, [output]]) //@ Available options: //@ //@ + `-i`: Ignore case while comparing //@ + `-c`: Prefix lines by the number of occurrences //@ + `-d`: Only print duplicate lines, one for each group of identical lines //@ //@ Examples: //@ //@ ```javascript //@ uniq('foo.txt'); //@ uniq('-i', 'foo.txt'); //@ uniq('-cd', 'foo.txt', 'bar.txt'); //@ ``` //@ //@ Filter adjacent matching lines from input function _uniq(options, input, output) { // Check if this is coming from a pipe var pipe = common.readFromPipe(); if (!input && !pipe) common.error('no input given'); var lines = (input ? fs.readFileSync(input, 'utf8') : pipe). trimRight(). split(/\r*\n/); var compare = function (a, b) { return options.ignoreCase ? a.toLocaleLowerCase().localeCompare(b.toLocaleLowerCase()) : a.localeCompare(b); }; var uniqed = lines.reduceRight(function (res, e) { // Perform uniq -c on the input if (res.length === 0) { return [{ count: 1, ln: e }]; } else if (compare(res[0].ln, e) === 0) { return [{ count: res[0].count + 1, ln: e }].concat(res.slice(1)); } else { return [{ count: 1, ln: e }].concat(res); } }, []).filter(function (obj) { // Do we want only duplicated objects? return options.duplicates ? obj.count > 1 : true; }).map(function (obj) { // Are we tracking the counts of each line? return (options.count ? (lpad(7, obj.count) + ' ') : '') + obj.ln; }).join('\n') + '\n'; if (output) { (new common.ShellString(uniqed)).to(output); // if uniq writes to output, nothing is passed to the next command in the pipeline (if any) return ''; } else { return uniqed; } } module.exports = _uniq; shelljs-0.7.5/src/which.js000066400000000000000000000052451300431262200154150ustar00rootroot00000000000000var common = require('./common'); var fs = require('fs'); var path = require('path'); common.register('which', _which, { allowGlobbing: false, }); // 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(pathName) { return fs.existsSync(pathName) && !fs.statSync(pathName).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; var pathArray = splitPath(pathEnv); var 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 where; } module.exports = _which; shelljs-0.7.5/test/000077500000000000000000000000001300431262200141375ustar00rootroot00000000000000shelljs-0.7.5/test/.gitignore000066400000000000000000000000061300431262200161230ustar00rootroot00000000000000tmp/ shelljs-0.7.5/test/cat.js000066400000000000000000000025261300431262200152510ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var fs = require('fs'); shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); // // Invalids // var result = shell.cat(); assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(result.stderr, 'cat: no paths given'); assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check result = shell.cat('/asdfasdf'); // file does not exist assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(result.stderr, 'cat: no such file or directory: /asdfasdf'); // // Valids // // simple result = shell.cat('resources/cat/file1'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result, 'test1\n'); // multiple files result = shell.cat('resources/cat/file2', 'resources/cat/file1'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result, 'test2\ntest1\n'); // multiple files, array syntax result = shell.cat(['resources/cat/file2', 'resources/cat/file1']); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result, 'test2\ntest1\n'); result = shell.cat('resources/file*.txt'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.ok(result.search('test1') > -1); // file order might be random assert.ok(result.search('test2') > -1); shell.exit(123); shelljs-0.7.5/test/cd.js000066400000000000000000000047251300431262200150730ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var path = require('path'); var fs = require('fs'); var common = require('../src/common'); shell.config.silent = true; // save current dir var cur = shell.pwd(); shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); // // Invalids // assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check var result = shell.cd('/asdfasdf'); // dir does not exist assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(result.stderr, 'cd: no such file or directory: /asdfasdf'); assert.equal(fs.existsSync('resources/file1'), true); // sanity check result = shell.cd('resources/file1'); // file, not dir assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(result.stderr, 'cd: not a directory: resources/file1'); result = shell.cd('-'); // Haven't changed yet, so there is no previous directory assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(result.stderr, 'cd: could not find previous directory'); // // Valids // result = shell.cd(cur); result = shell.cd('tmp'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(path.basename(process.cwd()), 'tmp'); result = shell.cd(cur); result = shell.cd('/'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(process.cwd(), path.resolve('/')); result = shell.cd(cur); result = shell.cd('/'); result = shell.cd('-'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(process.cwd(), path.resolve(cur.toString())); // cd + other commands result = shell.cd(cur); result = shell.rm('-f', 'tmp/*'); assert.equal(fs.existsSync('tmp/file1'), false); result = shell.cd('resources'); assert.equal(shell.error(), null); assert.equal(result.code, 0); result = shell.cp('file1', '../tmp'); assert.equal(shell.error(), null); assert.equal(result.code, 0); result = shell.cd('../tmp'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(fs.existsSync('file1'), true); // Test tilde expansion result = shell.cd('~'); assert.equal(process.cwd(), common.getUserHome()); result = shell.cd('..'); assert.notEqual(process.cwd(), common.getUserHome()); result = shell.cd('~'); // Change back to home assert.equal(process.cwd(), common.getUserHome()); // Goes to home directory if no arguments are passed result = shell.cd(cur); result = shell.cd(); assert.ok(!shell.error()); assert.equal(result.code, 0); assert.equal(process.cwd(), common.getUserHome()); shell.exit(123); shelljs-0.7.5/test/chmod.js000066400000000000000000000210551300431262200155720ustar00rootroot00000000000000var shell = require('..'); var common = require('../src/common'); var assert = require('assert'); var fs = require('fs'); shell.config.silent = true; // // Invalids // var result = shell.chmod('blah'); // missing args assert.ok(shell.error()); assert.equal(result.code, 1); result = shell.chmod('893', 'resources/chmod'); // invalid permissions - mode must be in octal assert.ok(shell.error()); assert.equal(result.code, 1); // // Valids // // On Windows, chmod acts VERY differently so skip those tests for now if (common.platform === 'win') shell.exit(123); // Test files - the bitmasking is to ignore the upper bits. result = shell.chmod('755', 'resources/chmod/file1'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('777', 8), parseInt('755', 8)); result = shell.chmod('644', 'resources/chmod/file1'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('777', 8), parseInt('644', 8)); result = shell.chmod('o+x', 'resources/chmod/file1'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('007', 8), parseInt('005', 8)); result = shell.chmod('644', 'resources/chmod/file1'); assert.equal(result.code, 0); result = shell.chmod('+x', 'resources/chmod/file1'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('777', 8), parseInt('755', 8)); result = shell.chmod('644', 'resources/chmod/file1'); assert.equal(result.code, 0); // Test setuid result = shell.chmod('u+s', 'resources/chmod/file1'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('4000', 8), parseInt('4000', 8)); result = shell.chmod('u-s', 'resources/chmod/file1'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('777', 8), parseInt('644', 8)); // according to POSIX standards at http://linux.die.net/man/1/chmod, // setuid is never cleared from a directory unless explicitly asked for. result = shell.chmod('u+s', 'resources/chmod/c'); assert.equal(result.code, 0); result = shell.chmod('755', 'resources/chmod/c'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/c').mode & parseInt('4000', 8), parseInt('4000', 8)); result = shell.chmod('u-s', 'resources/chmod/c'); assert.equal(result.code, 0); // Test setgid result = shell.chmod('g+s', 'resources/chmod/file1'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('2000', 8), parseInt('2000', 8)); result = shell.chmod('g-s', 'resources/chmod/file1'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('777', 8), parseInt('644', 8)); // Test sticky bit result = shell.chmod('+t', 'resources/chmod/file1'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('1000', 8), parseInt('1000', 8)); result = shell.chmod('-t', 'resources/chmod/file1'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('777', 8), parseInt('644', 8)); assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('1000', 8), 0); // Test directories result = shell.chmod('a-w', 'resources/chmod/b/a/b'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/b/a/b').mode & parseInt('777', 8), parseInt('555', 8)); result = shell.chmod('755', 'resources/chmod/b/a/b'); assert.equal(result.code, 0); // Test recursion result = shell.chmod('-R', 'a+w', 'resources/chmod/b'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/b/a/b').mode & parseInt('777', 8), parseInt('777', 8)); result = shell.chmod('-R', '755', 'resources/chmod/b'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/b/a/b').mode & parseInt('777', 8), parseInt('755', 8)); // Test symbolic links w/ recursion - WARNING: *nix only fs.symlinkSync('resources/chmod/b/a', 'resources/chmod/a/b/c/link', 'dir'); result = shell.chmod('-R', 'u-w', 'resources/chmod/a/b'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/a/b/c').mode & parseInt('700', 8), parseInt('500', 8)); assert.equal(fs.statSync('resources/chmod/b/a').mode & parseInt('700', 8), parseInt('700', 8)); result = shell.chmod('-R', 'u+w', 'resources/chmod/a/b'); assert.equal(result.code, 0); fs.unlinkSync('resources/chmod/a/b/c/link'); // Test combinations result = shell.chmod('a-rwx', 'resources/chmod/file1'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('000', 8), parseInt('000', 8)); result = shell.chmod('644', 'resources/chmod/file1'); assert.equal(result.code, 0); result = shell.chmod('a-rwx,u+r', 'resources/chmod/file1'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('400', 8), parseInt('400', 8)); result = shell.chmod('644', 'resources/chmod/file1'); assert.equal(result.code, 0); result = shell.chmod('a-rwx,u+rw', 'resources/chmod/file1'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('600', 8), parseInt('600', 8)); result = shell.chmod('644', 'resources/chmod/file1'); assert.equal(result.code, 0); result = shell.chmod('a-rwx,u+rwx', 'resources/chmod/file1'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('700', 8), parseInt('700', 8)); result = shell.chmod('644', 'resources/chmod/file1'); assert.equal(result.code, 0); result = shell.chmod('000', 'resources/chmod/file1'); assert.equal(result.code, 0); result = shell.chmod('u+rw', 'resources/chmod/file1'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('600', 8), parseInt('600', 8)); result = shell.chmod('644', 'resources/chmod/file1'); assert.equal(result.code, 0); result = shell.chmod('000', 'resources/chmod/file1'); assert.equal(result.code, 0); result = shell.chmod('u+wx', 'resources/chmod/file1'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('300', 8), parseInt('300', 8)); result = shell.chmod('644', 'resources/chmod/file1'); assert.equal(result.code, 0); result = shell.chmod('000', 'resources/chmod/file1'); assert.equal(result.code, 0); result = shell.chmod('u+r,g+w,o+x', 'resources/chmod/file1'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('421', 8), parseInt('421', 8)); result = shell.chmod('644', 'resources/chmod/file1'); assert.equal(result.code, 0); result = shell.chmod('000', 'resources/chmod/file1'); assert.equal(result.code, 0); result = shell.chmod('u+rw,g+wx', 'resources/chmod/file1'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('630', 8), parseInt('630', 8)); result = shell.chmod('644', 'resources/chmod/file1'); assert.equal(result.code, 0); result = shell.chmod('700', 'resources/chmod/file1'); assert.equal(result.code, 0); result = shell.chmod('u-x,g+rw', 'resources/chmod/file1'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('660', 8), parseInt('660', 8)); result = shell.chmod('644', 'resources/chmod/file1'); assert.equal(result.code, 0); result = shell.chmod('a-rwx,u+rw', 'resources/chmod/file1'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('600', 8), parseInt('600', 8)); result = shell.chmod('a-rwx,u+rw', 'resources/chmod/file1'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/file1').mode & parseInt('600', 8), parseInt('600', 8)); result = shell.chmod('644', 'resources/chmod/file1'); assert.equal(result.code, 0); // Support capital X ("entry" permission aka directory-only execute) result = shell.chmod('744', 'resources/chmod/xdir'); assert.equal(result.code, 0); result = shell.chmod('644', 'resources/chmod/xdir/file'); assert.equal(result.code, 0); result = shell.chmod('744', 'resources/chmod/xdir/deep'); assert.equal(result.code, 0); result = shell.chmod('644', 'resources/chmod/xdir/deep/file'); assert.equal(result.code, 0); result = shell.chmod('-R', 'a+X', 'resources/chmod/xdir'); assert.equal(result.code, 0); assert.equal(fs.statSync('resources/chmod/xdir').mode & parseInt('755', 8), parseInt('755', 8)); assert.equal(fs.statSync('resources/chmod/xdir/file').mode & parseInt('644', 8), parseInt('644', 8)); assert.equal(fs.statSync('resources/chmod/xdir/deep').mode & parseInt('755', 8), parseInt('755', 8)); assert.equal(fs.statSync('resources/chmod/xdir/deep/file').mode & parseInt('644', 8), parseInt('644', 8)); shell.exit(123); shelljs-0.7.5/test/common.js000066400000000000000000000065021300431262200157700ustar00rootroot00000000000000var shell = require('..'); var common = require('../src/common'); var assert = require('assert'); shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); // // Invalids // // too few args assert.throws(function () { common.expand(); }, TypeError); // should be a list assert.throws(function () { common.expand('resources'); }, TypeError); // // Valids // var result; // single file, array syntax result = common.expand(['resources/file1.txt']); assert.equal(shell.error(), null); assert.deepEqual(result, ['resources/file1.txt']); // multiple file, glob syntax, * for file name result = common.expand(['resources/file*.txt']); assert.equal(shell.error(), null); assert.deepEqual(result.sort(), ['resources/file1.txt', 'resources/file2.txt'].sort()); // multiple file, glob syntax, * for directory name result = common.expand(['*/file*.txt']); assert.equal(shell.error(), null); assert.deepEqual(result.sort(), ['resources/file1.txt', 'resources/file2.txt'].sort()); // multiple file, glob syntax, ** for directory name result = common.expand(['**/file*.js']); assert.equal(shell.error(), null); assert.deepEqual(result.sort(), ['resources/file1.js', 'resources/file2.js', 'resources/ls/file1.js', 'resources/ls/file2.js'].sort()); // broken links still expand result = common.expand(['resources/b*dlink']); assert.equal(shell.error(), null); assert.deepEqual(result, ['resources/badlink']); // common.parseOptions (normal case) result = common.parseOptions('-Rf', { 'R': 'recursive', 'f': 'force', 'r': 'reverse' }); assert.ok(result.recursive === true); assert.ok(result.force === true); assert.ok(result.reverse === false); // common.parseOptions (with mutually-negating options) result = common.parseOptions('-f', { 'n': 'no_force', 'f': '!no_force', 'R': 'recursive' }); assert.ok(result.recursive === false); assert.ok(result.no_force === false); assert.ok(result.force === undefined); // this key shouldn't exist // common.parseOptions (the last of the conflicting options should hold) var options = { 'n': 'no_force', 'f': '!no_force', 'R': 'recursive' }; result = common.parseOptions('-fn', options); assert.ok(result.recursive === false); assert.ok(result.no_force === true); assert.ok(result.force === undefined); // this key shouldn't exist result = common.parseOptions('-nf', options); assert.ok(result.recursive === false); assert.ok(result.no_force === false); assert.ok(result.force === undefined); // this key shouldn't exist // common.parseOptions using an object to hold options result = common.parseOptions({ '-v': 'some text here' }, { 'v': 'value', 'f': 'force', 'r': 'reverse' }); assert.ok(result.value === 'some text here'); assert.ok(result.force === false); assert.ok(result.reverse === false); // Some basic tests on the ShellString type result = shell.ShellString('foo'); assert.strictEqual(result.toString(), 'foo'); assert.equal(result.stdout, 'foo'); assert.ok(typeof result.stderr === 'undefined'); assert.ok(result.to); assert.ok(result.toEnd); // Commands that fail will still output error messages to stderr result = shell.exec(JSON.stringify(process.execPath) + ' -e "require(\'../global\'); ls(\'noexist\'); cd(\'noexist\');"'); assert.equal(result.stdout, ''); assert.equal(result.stderr, 'ls: no such file or directory: noexist\ncd: no such file or directory: noexist\n'); shell.exit(123); shelljs-0.7.5/test/config.js000066400000000000000000000040521300431262200157430ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var child = require('child_process'); var common = require('../src/common'); // // config.silent // assert.equal(shell.config.silent, false); // default shell.config.silent = true; assert.equal(shell.config.silent, true); shell.config.silent = false; assert.equal(shell.config.silent, false); // // config.fatal // assert.equal(shell.config.fatal, false); // default // // config.fatal = false // shell.mkdir('-p', 'tmp'); var file = 'tmp/tempscript' + Math.random() + '.js'; var script = 'require(\'../../global.js\'); config.silent=true; config.fatal=false; cp("this_file_doesnt_exist", "."); echo("got here");'; shell.ShellString(script).to(file); child.exec(JSON.stringify(process.execPath) + ' ' + file, function (err, stdout) { assert.ok(stdout.match('got here')); // // config.fatal = true // shell.mkdir('-p', 'tmp'); file = 'tmp/tempscript' + Math.random() + '.js'; script = 'require(\'../../global.js\'); config.silent=true; config.fatal=true; cp("this_file_doesnt_exist", "."); echo("got here");'; shell.ShellString(script).to(file); child.exec(JSON.stringify(process.execPath) + ' ' + file, function (err2, stdout2) { assert.ok(!stdout2.match('got here')); shell.exit(123); }); }); // // config.globOptions // // Expands to directories by default var result = common.expand(['resources/*a*']); assert.equal(result.length, 5); assert.ok(result.indexOf('resources/a.txt') > -1); assert.ok(result.indexOf('resources/badlink') > -1); assert.ok(result.indexOf('resources/cat') > -1); assert.ok(result.indexOf('resources/head') > -1); assert.ok(result.indexOf('resources/external') > -1); // Check to make sure options get passed through (nodir is an example) shell.config.globOptions = { nodir: true }; result = common.expand(['resources/*a*']); assert.equal(result.length, 2); assert.ok(result.indexOf('resources/a.txt') > -1); assert.ok(result.indexOf('resources/badlink') > -1); assert.ok(result.indexOf('resources/cat') < 0); assert.ok(result.indexOf('resources/external') < 0); shelljs-0.7.5/test/cp.js000066400000000000000000000523131300431262200151030ustar00rootroot00000000000000var shell = require('..'); var common = require('../src/common'); var assert = require('assert'); var fs = require('fs'); var numLines = require('./utils/utils').numLines; shell.config.silent = true; var isWindows = common.platform === 'win'; // On Windows, symlinks for files need admin permissions. This helper // skips certain tests if we are on Windows and got an EPERM error function skipOnWinForEPERM(action, test) { action(); var error = shell.error(); if (isWindows && error && /EPERM:/.test(error)) { console.log('Got EPERM when testing symlinks on Windows. Assuming non-admin environment and skipping test.'); } else { test(); } } shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); // // Invalids // var result = shell.cp(); assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(result.stderr, 'cp: missing and/or '); result = shell.cp('file1'); assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(result.stderr, 'cp: missing and/or '); result = shell.cp('-f'); assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(result.stderr, 'cp: missing and/or '); shell.rm('-rf', 'tmp/*'); result = shell.cp('-@', 'resources/file1', 'tmp/file1'); // option not supported, files OK assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(fs.existsSync('tmp/file1'), false); assert.equal(result.stderr, 'cp: option not recognized: @'); result = shell.cp('-Z', 'asdfasdf', 'tmp/file2'); // option not supported, files NOT OK assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(fs.existsSync('tmp/file2'), false); assert.equal(result.stderr, 'cp: option not recognized: Z'); result = shell.cp('asdfasdf', 'tmp'); // source does not exist assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(numLines(result.stderr), 1); assert.equal(fs.existsSync('tmp/asdfasdf'), false); assert.equal(result.stderr, 'cp: no such file or directory: asdfasdf'); result = shell.cp('asdfasdf1', 'asdfasdf2', 'tmp'); // sources do not exist assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(numLines(result.stderr), 2); assert.equal(fs.existsSync('tmp/asdfasdf1'), false); assert.equal(fs.existsSync('tmp/asdfasdf2'), false); assert.equal(result.stderr, 'cp: no such file or directory: asdfasdf1\ncp: no such file or directory: asdfasdf2'); result = shell.cp('asdfasdf1', 'asdfasdf2', 'resources/file1'); // too many sources (dest is file) assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(result.stderr, 'cp: dest is not a directory (too many sources)'); result = shell.cp('resources/file1', 'resources/file2', 'tmp/a_file'); // too many sources assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(fs.existsSync('tmp/a_file'), false); assert.equal(result.stderr, 'cp: dest is not a directory (too many sources)'); // // Valids // var oldContents = shell.cat('resources/file2').toString(); result = shell.cp('-n', 'resources/file1', 'resources/file2'); // dest already exists assert.ok(!shell.error()); assert.equal(result.code, 0); assert.equal(result.stderr, ''); assert.equal(shell.cat('resources/file2').toString(), oldContents); // -f by default result = shell.cp('resources/file2', 'resources/copyfile2'); result = shell.cp('resources/file1', 'resources/file2'); // dest already exists assert.ok(!shell.error()); assert.equal(result.code, 0); assert.ok(!result.stderr); assert.equal(shell.cat('resources/file1') + '', shell.cat('resources/file2') + ''); // after cp shell.mv('resources/copyfile2', 'resources/file2'); // restore assert.ok(!shell.error()); // -f (explicitly) result = shell.cp('resources/file2', 'resources/copyfile2'); result = shell.cp('-f', 'resources/file1', 'resources/file2'); // dest already exists assert.ok(!shell.error()); assert.ok(!result.stderr); assert.equal(result.code, 0); assert.equal(shell.cat('resources/file1') + '', shell.cat('resources/file2') + ''); // after cp shell.mv('resources/copyfile2', 'resources/file2'); // restore assert.ok(!shell.error()); assert.equal(result.code, 0); // simple - to dir result = shell.cp('resources/file1', 'tmp'); assert.equal(shell.error(), null); assert.ok(!result.stderr); assert.equal(result.code, 0); assert.equal(fs.existsSync('tmp/file1'), true); // simple - to file result = shell.cp('resources/file2', 'tmp/file2'); assert.equal(shell.error(), null); assert.ok(!result.stderr); assert.equal(result.code, 0); assert.equal(fs.existsSync('tmp/file2'), true); // simple - file list shell.rm('-rf', 'tmp/*'); result = shell.cp('resources/file1', 'resources/file2', 'tmp'); assert.equal(shell.error(), null); assert.ok(!result.stderr); assert.equal(result.code, 0); assert.equal(fs.existsSync('tmp/file1'), true); assert.equal(fs.existsSync('tmp/file2'), true); // simple - file list, array syntax shell.rm('-rf', 'tmp/*'); result = shell.cp(['resources/file1', 'resources/file2'], 'tmp'); assert.equal(shell.error(), null); assert.ok(!result.stderr); assert.equal(result.code, 0); assert.equal(fs.existsSync('tmp/file1'), true); assert.equal(fs.existsSync('tmp/file2'), true); result = shell.cp('resources/file2', 'tmp/file3'); assert.equal(fs.existsSync('tmp/file3'), true); result = shell.cp('-f', 'resources/file2', 'tmp/file3'); // file exists, but -f specified assert.equal(shell.error(), null); assert.ok(!result.stderr); assert.equal(result.code, 0); assert.equal(fs.existsSync('tmp/file3'), true); // glob shell.rm('-rf', 'tmp/*'); result = shell.cp('resources/file?', 'tmp'); assert.equal(shell.error(), null); assert.ok(!result.stderr); assert.equal(result.code, 0); assert.ok(fs.existsSync('tmp/file1')); assert.ok(fs.existsSync('tmp/file2')); assert.ok(!fs.existsSync('tmp/file1.js')); assert.ok(!fs.existsSync('tmp/file2.js')); assert.ok(!fs.existsSync('tmp/file1.txt')); assert.ok(!fs.existsSync('tmp/file2.txt')); // wildcard shell.rm('tmp/file1', 'tmp/file2'); result = shell.cp('resources/file*', 'tmp'); assert.equal(shell.error(), null); assert.ok(!result.stderr); assert.equal(result.code, 0); assert.ok(fs.existsSync('tmp/file1')); assert.ok(fs.existsSync('tmp/file2')); assert.ok(fs.existsSync('tmp/file1.js')); assert.ok(fs.existsSync('tmp/file2.js')); assert.ok(fs.existsSync('tmp/file1.txt')); assert.ok(fs.existsSync('tmp/file2.txt')); // recursive, with regular files shell.rm('-rf', 'tmp/*'); result = shell.cp('-R', 'resources/file1', 'resources/file2', 'tmp'); assert.equal(shell.error(), null); assert.ok(!result.stderr); assert.equal(result.code, 0); assert.ok(fs.existsSync('tmp/file1')); assert.ok(fs.existsSync('tmp/file2')); // recursive, nothing exists shell.rm('-rf', 'tmp/*'); result = shell.cp('-R', 'resources/cp', 'tmp'); assert.equal(shell.error(), null); assert.ok(!result.stderr); assert.equal(result.code, 0); assert.equal(shell.ls('-R', 'resources/cp') + '', shell.ls('-R', 'tmp/cp') + ''); // recursive, nothing exists, source ends in '/' (see Github issue #15) shell.rm('-rf', 'tmp/*'); result = shell.cp('-R', 'resources/cp/', 'tmp/'); assert.equal(shell.error(), null); assert.ok(!result.stderr); assert.equal(result.code, 0); assert.equal(shell.ls('-R', 'resources/cp') + '', shell.ls('-R', 'tmp/cp') + ''); // recursive, globbing regular files with extension (see Github issue #376) shell.rm('-rf', 'tmp/*'); result = shell.cp('-R', 'resources/file*.txt', 'tmp'); assert.equal(shell.error(), null); assert.ok(!result.stderr); assert.equal(result.code, 0); assert.ok(fs.existsSync('tmp/file1.txt')); assert.ok(fs.existsSync('tmp/file2.txt')); // recursive, copying one regular file (also related to Github issue #376) shell.rm('-rf', 'tmp/*'); result = shell.cp('-R', 'resources/file1.txt', 'tmp'); assert.equal(shell.error(), null); assert.ok(!result.stderr); assert.equal(result.code, 0); assert.ok(fs.existsSync('tmp/file1.txt')); assert.ok(!fs.statSync('tmp/file1.txt').isDirectory()); // don't let it be a dir // recursive, everything exists, no force flag shell.rm('-rf', 'tmp/*'); result = shell.cp('-R', 'resources/cp', 'tmp'); result = shell.cp('-R', 'resources/cp', 'tmp'); assert.equal(shell.error(), null); // crash test only assert.ok(!result.stderr); assert.equal(result.code, 0); if (process.platform !== 'win32') { // Recursive, everything exists, overwrite a real file with a link (if same name) // Because -R implies to not follow links! shell.rm('-rf', 'tmp/*'); shell.cp('-R', 'resources/cp/*', 'tmp'); assert.ok(fs.lstatSync('tmp/links/sym.lnk').isSymbolicLink()); // this one is a link assert.ok(!(fs.lstatSync('tmp/fakeLinks/sym.lnk').isSymbolicLink())); // this one isn't assert.notEqual(shell.cat('tmp/links/sym.lnk').toString(), shell.cat('tmp/fakeLinks/sym.lnk').toString()); result = shell.cp('-R', 'tmp/links/*', 'tmp/fakeLinks'); assert.equal(shell.error(), null); assert.ok(!result.stderr); assert.equal(result.code, 0); assert.ok(fs.lstatSync('tmp/links/sym.lnk').isSymbolicLink()); // this one is a link assert.ok(fs.lstatSync('tmp/fakeLinks/sym.lnk').isSymbolicLink()); // this one is now a link assert.equal(shell.cat('tmp/links/sym.lnk').toString(), shell.cat('tmp/fakeLinks/sym.lnk').toString()); // Recursive, everything exists, overwrite a real file *by following a link* // Because missing the -R implies -L. shell.rm('-rf', 'tmp/*'); shell.cp('-R', 'resources/cp/*', 'tmp'); assert.ok(fs.lstatSync('tmp/links/sym.lnk').isSymbolicLink()); // this one is a link assert.ok(!(fs.lstatSync('tmp/fakeLinks/sym.lnk').isSymbolicLink())); // this one isn't assert.notEqual(shell.cat('tmp/links/sym.lnk').toString(), shell.cat('tmp/fakeLinks/sym.lnk').toString()); result = shell.cp('tmp/links/*', 'tmp/fakeLinks'); // don't use -R assert.equal(shell.error(), null); assert.ok(!result.stderr); assert.equal(result.code, 0); assert.ok(fs.lstatSync('tmp/links/sym.lnk').isSymbolicLink()); // this one is a link assert.ok(!fs.lstatSync('tmp/fakeLinks/sym.lnk').isSymbolicLink()); // this one is still not a link // But it still follows the link assert.equal(shell.cat('tmp/links/sym.lnk').toString(), shell.cat('tmp/fakeLinks/sym.lnk').toString()); } // recursive, everything exists, with force flag shell.rm('-rf', 'tmp/*'); result = shell.cp('-R', 'resources/cp', 'tmp'); shell.ShellString('changing things around').to('tmp/cp/dir_a/z'); assert.notEqual(shell.cat('resources/cp/dir_a/z') + '', shell.cat('tmp/cp/dir_a/z') + ''); // before cp result = shell.cp('-Rf', 'resources/cp', 'tmp'); assert.equal(shell.error(), null); assert.ok(!result.stderr); assert.equal(result.code, 0); assert.equal(shell.cat('resources/cp/dir_a/z') + '', shell.cat('tmp/cp/dir_a/z') + ''); // after cp // recursive, creates dest dir since it's only one level deep (see Github issue #44) shell.rm('-rf', 'tmp/*'); result = shell.cp('-r', 'resources/issue44', 'tmp/dir2'); assert.equal(shell.error(), null); assert.ok(!result.stderr); assert.equal(result.code, 0); assert.equal(shell.ls('-R', 'resources/issue44') + '', shell.ls('-R', 'tmp/dir2') + ''); assert.equal(shell.cat('resources/issue44/main.js') + '', shell.cat('tmp/dir2/main.js') + ''); // recursive, does *not* create dest dir since it's too deep (see Github issue #44) shell.rm('-rf', 'tmp/*'); result = shell.cp('-r', 'resources/issue44', 'tmp/dir2/dir3'); assert.ok(shell.error()); assert.equal(result.stderr, 'cp: cannot create directory \'tmp/dir2/dir3\': No such file or directory'); assert.equal(result.code, 1); assert.equal(fs.existsSync('tmp/dir2'), false); // recursive, copies entire directory shell.rm('-rf', 'tmp/*'); result = shell.cp('-r', 'resources/cp/dir_a', 'tmp/dest'); assert.equal(shell.error(), null); assert.ok(!result.stderr); assert.equal(result.code, 0); assert.equal(fs.existsSync('tmp/dest/z'), true); // recursive, with trailing slash, does the exact same shell.rm('-rf', 'tmp/*'); result = shell.cp('-r', 'resources/cp/dir_a/', 'tmp/dest'); assert.equal(shell.error(), null); assert.equal(fs.existsSync('tmp/dest/z'), true); // On Windows, permission bits are quite different so skip those tests for now if (common.platform !== 'win') { // preserve mode bits shell.rm('-rf', 'tmp/*'); var execBit = parseInt('001', 8); assert.equal(fs.statSync('resources/cp-mode-bits/executable').mode & execBit, execBit); shell.cp('resources/cp-mode-bits/executable', 'tmp/executable'); assert.equal(fs.statSync('resources/cp-mode-bits/executable').mode, fs.statSync('tmp/executable').mode); } // Make sure hidden files are copied recursively shell.rm('-rf', 'tmp/'); result = shell.cp('-r', 'resources/ls/', 'tmp/'); assert.ok(!shell.error()); assert.ok(!result.stderr); assert.equal(result.code, 0); assert.ok(fs.existsSync('tmp/.hidden_file')); // no-recursive will copy regular files only shell.rm('-rf', 'tmp/'); shell.mkdir('tmp/'); result = shell.cp('resources/file1.txt', 'resources/ls/', 'tmp/'); assert.ok(shell.error()); assert.ok(!fs.existsSync('tmp/.hidden_file')); // doesn't copy dir contents assert.ok(!fs.existsSync('tmp/ls')); // doesn't copy dir itself assert.ok(fs.existsSync('tmp/file1.txt')); // no-recursive will copy regular files only shell.rm('-rf', 'tmp/'); shell.mkdir('tmp/'); result = shell.cp('resources/file1.txt', 'resources/file2.txt', 'resources/cp', 'resources/ls/', 'tmp/'); assert.ok(shell.error()); assert.ok(!fs.existsSync('tmp/.hidden_file')); // doesn't copy dir contents assert.ok(!fs.existsSync('tmp/ls')); // doesn't copy dir itself assert.ok(!fs.existsSync('tmp/a')); // doesn't copy dir contents assert.ok(!fs.existsSync('tmp/cp')); // doesn't copy dir itself assert.ok(fs.existsSync('tmp/file1.txt')); assert.ok(fs.existsSync('tmp/file2.txt')); if (process.platform !== 'win32') { // -R implies -P shell.rm('-rf', 'tmp/*'); shell.cp('-R', 'resources/cp/links/sym.lnk', 'tmp'); assert.ok(fs.lstatSync('tmp/sym.lnk').isSymbolicLink()); // using -P explicitly works shell.rm('-rf', 'tmp/*'); shell.cp('-P', 'resources/cp/links/sym.lnk', 'tmp'); assert.ok(fs.lstatSync('tmp/sym.lnk').isSymbolicLink()); // using -PR on a link to a folder does not follow the link shell.rm('-rf', 'tmp/*'); shell.cp('-PR', 'resources/cp/symFolder', 'tmp'); assert.ok(fs.lstatSync('tmp/symFolder').isSymbolicLink()); // -L overrides -P for copying directory shell.rm('-rf', 'tmp/*'); shell.cp('-LPR', 'resources/cp/symFolder', 'tmp'); assert.ok(!fs.lstatSync('tmp/symFolder').isSymbolicLink()); assert.ok(!fs.lstatSync('tmp/symFolder/sym.lnk').isSymbolicLink()); // Recursive, copies entire directory with no symlinks and -L option does not cause change in behavior. shell.rm('-rf', 'tmp/*'); result = shell.cp('-rL', 'resources/cp/dir_a', 'tmp/dest'); assert.equal(shell.error(), null); assert.ok(!result.stderr); assert.equal(result.code, 0); assert.equal(fs.existsSync('tmp/dest/z'), true); } // -u flag won't overwrite newer files shell.rm('-rf', 'tmp/*'); shell.touch('tmp/file1.js'); shell.cp('-u', 'resources/file1.js', 'tmp'); assert.ok(!shell.error()); assert.notEqual(shell.cat('resources/file1.js').toString(), shell.cat('tmp/file1.js').toString()); // -u flag does overwrite older files shell.rm('-rf', 'tmp/*'); shell.touch({ '-d': new Date(10) }, 'tmp/file1.js'); // really old file shell.cp('-u', 'resources/file1.js', 'tmp'); assert.ok(!shell.error()); assert.equal(shell.cat('resources/file1.js').toString(), shell.cat('tmp/file1.js').toString()); // -u flag works even if it's not overwriting a file shell.rm('-rf', 'tmp/*'); shell.cp('-u', 'resources/file1.js', 'tmp'); assert.ok(!shell.error()); assert.equal(shell.cat('resources/file1.js').toString(), shell.cat('tmp/file1.js').toString()); // -u flag works correctly recursively shell.rm('-rf', 'tmp/*'); shell.mkdir('tmp/foo'); [1, 2, 3].forEach(function (num) { new shell.ShellString('old\n').to('tmp/foo/file' + num); shell.touch({ '-d': new Date(10) }, 'tmp/foo/file' + num); }); shell.mkdir('tmp/bar'); [1, 2, 3].forEach(function (num) { new shell.ShellString('new\n').to('tmp/bar/file' + num); shell.touch({ '-d': new Date(1000) }, 'tmp/bar/file' + num); }); // put one new one in the foo directory new shell.ShellString('newest\n').to('tmp/foo/file3'); shell.touch({ '-d': new Date(10000) }, 'tmp/foo/file3'); shell.cp('-u', 'tmp/foo/*', 'tmp/bar'); assert.ok(!shell.error()); assert.equal(shell.cat('tmp/bar/*').toString(), 'new\nnew\nnewest\n'); // using -R on a link to a folder *does* follow the link shell.rm('-rf', 'tmp/*'); shell.cp('-R', 'resources/cp/symFolder', 'tmp'); assert.ok(!fs.lstatSync('tmp/symFolder').isSymbolicLink()); // Without -R, -L is implied shell.rm('-rf', 'tmp/*'); shell.cp('resources/cp/links/sym.lnk', 'tmp'); assert.ok(!fs.lstatSync('tmp/sym.lnk').isSymbolicLink()); // -L explicitly works shell.rm('-rf', 'tmp/*'); shell.cp('-L', 'resources/cp/links/sym.lnk', 'tmp'); assert.ok(!fs.lstatSync('tmp/sym.lnk').isSymbolicLink()); // using -LR does not imply -P shell.rm('-rf', 'tmp/*'); shell.cp('-LR', 'resources/cp/links/sym.lnk', 'tmp'); assert.ok(!fs.lstatSync('tmp/sym.lnk').isSymbolicLink()); // using -LR also works recursively on directories containing links shell.rm('-rf', 'tmp/*'); shell.cp('-LR', 'resources/cp/links', 'tmp'); assert.ok(!fs.lstatSync('tmp/links/sym.lnk').isSymbolicLink()); // -L always overrides a -P shell.rm('-rf', 'tmp/*'); shell.cp('-LP', 'resources/cp/links/sym.lnk', 'tmp'); assert.ok(!fs.lstatSync('tmp/sym.lnk').isSymbolicLink()); shell.rm('-rf', 'tmp/*'); shell.cp('-LPR', 'resources/cp/links/sym.lnk', 'tmp'); assert.ok(!fs.lstatSync('tmp/sym.lnk').isSymbolicLink()); // Test max depth. shell.rm('-rf', 'tmp/'); shell.mkdir('tmp/'); shell.config.maxdepth = 32; var directory = ''; var i; for (i = 1; i < 40; i++) { directory += '/' + i; } var directory32deep = ''; for (i = 1; i < 32; i++) { directory32deep += '/' + i; } shell.mkdir('-p', 'tmp/0' + directory); shell.cp('-r', 'tmp/0', 'tmp/copytestdepth'); // Check full directory exists. assert.ok(shell.test('-d', 'tmp/0/' + directory)); // Check full copy of directory does not exist. assert.ok(!shell.test('-d', 'tmp/copytestdepth' + directory)); // Check last directory to exist is bellow maxdepth. assert.ok(shell.test('-d', 'tmp/copytestdepth' + directory32deep)); assert.ok(!shell.test('-d', 'tmp/copytestdepth' + directory32deep + '/32')); // Only complete sym link checks if script has permission to do so. skipOnWinForEPERM(shell.ln.bind(shell, '-s', 'tmp/0', 'tmp/symlinktest'), function () { if (!shell.test('-L', 'tmp/symlinktest')) { return; } shell.rm('-rf', 'tmp/symlinktest'); // Create sym links to check for cycle. shell.cd('tmp/0/1/2/3/4'); shell.ln('-s', '../../../2', 'link'); shell.ln('-s', './5/6/7', 'link1'); shell.cd('../../../../../..'); assert.ok(shell.test('-d', 'tmp/')); shell.rm('-fr', 'tmp/copytestdepth'); shell.cp('-r', 'tmp/0', 'tmp/copytestdepth'); assert.ok(shell.test('-d', 'tmp/copytestdepth/1/2/3/4/link/3/4/link/3/4')); // Test copying of symlinked files cp -L. shell.rm('-fr', 'tmp'); shell.mkdir('-p', 'tmp/sub'); shell.mkdir('-p', 'tmp/new'); shell.cp('-f', 'resources/file1.txt', 'tmp/sub/file.txt'); shell.cd('tmp/sub'); shell.ln('-s', 'file.txt', 'foo.lnk'); shell.ln('-s', 'file.txt', 'sym.lnk'); shell.cd('..'); shell.cp('-L', 'sub/*', 'new/'); // Ensure copies are files. shell.cd('new'); shell.cp('-f', '../../resources/file2.txt', 'file.txt'); assert.equal(shell.cat('file.txt').toString(), 'test2\n'); // Ensure other files have not changed. assert.equal(shell.cat('foo.lnk').toString(), 'test1\n'); assert.equal(shell.cat('sym.lnk').toString(), 'test1\n'); // Ensure the links are converted to files. assert.equal(shell.test('-L', 'foo.lnk'), false); assert.equal(shell.test('-L', 'sym.lnk'), false); shell.cd('../..'); // Test with recursive option and symlinks. shell.rm('-fr', 'tmp'); shell.mkdir('-p', 'tmp/sub/sub1'); shell.cp('-f', 'resources/file1.txt', 'tmp/sub/file.txt'); shell.cp('-f', 'resources/file1.txt', 'tmp/sub/sub1/file.txt'); shell.cd('tmp/sub'); shell.ln('-s', 'file.txt', 'foo.lnk'); shell.ln('-s', 'file.txt', 'sym.lnk'); shell.cd('sub1'); shell.ln('-s', '../file.txt', 'foo.lnk'); shell.ln('-s', '../file.txt', 'sym.lnk'); // Ensure file reads from proper source. assert.equal(shell.cat('file.txt').toString(), 'test1\n'); assert.equal(shell.cat('foo.lnk').toString(), 'test1\n'); assert.equal(shell.cat('sym.lnk').toString(), 'test1\n'); assert.equal(shell.test('-L', 'foo.lnk'), true); assert.equal(shell.test('-L', 'sym.lnk'), true); shell.cd('../..'); shell.cp('-rL', 'sub/', 'new/'); shell.cd('new'); // Ensure copies of files are symlinks by updating file contents. shell.cp('-f', '../../resources/file2.txt', 'file.txt'); assert.equal(shell.cat('file.txt').toString(), 'test2\n'); // Ensure other files have not changed. assert.equal(shell.cat('foo.lnk').toString(), 'test1\n'); assert.equal(shell.cat('sym.lnk').toString(), 'test1\n'); // Ensure the links are converted to files. assert.equal(shell.test('-L', 'foo.lnk'), false); assert.equal(shell.test('-L', 'sym.lnk'), false); shell.cd('sub1'); shell.cp('-f', '../../../resources/file2.txt', 'file.txt'); assert.equal(shell.cat('file.txt').toString(), 'test2\n'); // Ensure other files have not changed. assert.equal(shell.cat('foo.lnk').toString(), 'test1\n'); assert.equal(shell.cat('sym.lnk').toString(), 'test1\n'); // Ensure the links are converted to files. assert.equal(shell.test('-L', 'foo.lnk'), false); assert.equal(shell.test('-L', 'sym.lnk'), false); }); shell.exit(123); shelljs-0.7.5/test/dirs.js000066400000000000000000000013131300431262200154340ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var path = require('path'); shell.config.silent = true; var root = path.resolve(); shell.pushd('resources/pushd'); shell.pushd('a'); var trail = [ path.resolve(root, 'resources/pushd/a'), path.resolve(root, 'resources/pushd'), root ]; assert.deepEqual(shell.dirs(), trail); // Single items assert.equal(shell.dirs('+0'), trail[0]); assert.equal(shell.dirs('+1'), trail[1]); assert.equal(shell.dirs('+2'), trail[2]); assert.equal(shell.dirs('-0'), trail[2]); assert.equal(shell.dirs('-1'), trail[1]); assert.equal(shell.dirs('-2'), trail[0]); // Clearing items assert.deepEqual(shell.dirs('-c'), []); assert(!shell.error()); shell.exit(123); shelljs-0.7.5/test/echo.js000066400000000000000000000031711300431262200154150ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var child = require('child_process'); shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); // // Valids // // From here on we use child.exec() to intercept the stdout // simple test with defaults shell.mkdir('-p', 'tmp'); var file = 'tmp/tempscript' + Math.random() + '.js'; var script = 'require(\'../../global.js\'); echo("-asdf", "111");'; // test '-' bug (see issue #20) shell.ShellString(script).to(file); child.exec(JSON.stringify(process.execPath) + ' ' + file, function (err, stdout) { assert.equal(stdout, '-asdf 111\n'); // using null as an explicit argument doesn't crash the function file = 'tmp/tempscript' + Math.random() + '.js'; script = 'require(\'../../global.js\'); echo(null);'; shell.ShellString(script).to(file); child.exec(JSON.stringify(process.execPath) + ' ' + file, function (err2, stdout2, stderr2) { assert.equal(stdout2, 'null\n'); assert.equal(stderr2, ''); // simple test with silent(true) script = 'require(\'../../global.js\'); config.silent=true; echo(555);'; shell.ShellString(script).to(file); child.exec(JSON.stringify(process.execPath) + ' ' + file, function (err3, stdout3) { assert.equal(stdout3, '555\n'); script = "require('../../global.js'); echo('-e', '\\tmessage');"; shell.ShellString(script).to(file); child.exec(JSON.stringify(process.execPath) + ' ' + file, function (err4, stdout4) { assert.equal(stdout4, '\tmessage\n'); theEnd(); }); }); // simple test with silent(true) }); }); function theEnd() { shell.exit(123); } shelljs-0.7.5/test/env.js000066400000000000000000000005031300431262200152630ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); // // Valids // assert.equal(shell.env.PATH, process.env.PATH); shell.env.SHELLJS_TEST = 'hello world'; assert.equal(shell.env.SHELLJS_TEST, process.env.SHELLJS_TEST); shell.exit(123); shelljs-0.7.5/test/exec.js000066400000000000000000000135161300431262200154270ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var util = require('util'); var path = require('path'); var os = require('os'); shell.config.silent = true; // // Invalids // shell.exec(); assert.ok(shell.error()); var result = shell.exec('asdfasdf'); // could not find command assert.ok(result.code > 0); // Test 'fatal' mode for exec, temporarily overriding process.exit var oldFatal = shell.config.fatal; shell.config.fatal = true; assert.throws(function () { shell.exec('asdfasdf'); // could not find command }, /exec: internal error/); shell.config.fatal = oldFatal; // // Valids // // // sync // // check if stdout goes to output result = shell.exec(JSON.stringify(process.execPath) + ' -e "console.log(1234);"'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.ok(result.stdout === '1234\n' || result.stdout === '1234\nundefined\n'); // 'undefined' for v0.4 // check if stderr goes to output result = shell.exec(JSON.stringify(process.execPath) + ' -e "console.error(1234);"'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.ok(result.stdout === '' || result.stdout === 'undefined\n'); // 'undefined' for v0.4 assert.ok(result.stderr === '1234\n' || result.stderr === '1234\nundefined\n'); // 'undefined' for v0.4 // check if stdout + stderr go to output result = shell.exec(JSON.stringify(process.execPath) + ' -e "console.error(1234); console.log(666);"'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.ok(result.stdout === '666\n' || result.stdout === '666\nundefined\n'); // 'undefined' for v0.4 assert.ok(result.stderr === '1234\n' || result.stderr === '1234\nundefined\n'); // 'undefined' for v0.4 // check exit code result = shell.exec(JSON.stringify(process.execPath) + ' -e "process.exit(12);"'); assert.ok(shell.error()); assert.equal(result.code, 12); // interaction with cd shell.cd('resources/external'); result = shell.exec(JSON.stringify(process.execPath) + ' node_script.js'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.stdout, 'node_script_1234\n'); shell.cd('../..'); // check quotes escaping result = shell.exec(util.format(JSON.stringify(process.execPath) + ' -e "console.log(%s);"', "\\\"\\'+\\'_\\'+\\'\\\"")); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.stdout, "'+'_'+'\n"); // set cwd var cmdString = process.platform === 'win32' ? 'cd' : 'pwd'; result = shell.exec(cmdString, { cwd: '..' }); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.stdout, path.resolve('..') + os.EOL); // set maxBuffer (very small) result = shell.exec('echo 1234567890'); // default maxBuffer is ok assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.stdout, '1234567890' + os.EOL); if (process.version >= 'v0.11') { // this option doesn't work on v0.10 shell.exec('echo 1234567890', { maxBuffer: 6 }); assert.ok(shell.error()); } // set timeout option result = shell.exec(JSON.stringify(process.execPath) + ' resources/exec/slow.js 100'); // default timeout is ok assert.ok(!shell.error()); assert.equal(result.code, 0); if (process.version >= 'v0.11') { // this option doesn't work on v0.10 result = shell.exec(JSON.stringify(process.execPath) + ' resources/exec/slow.js 100', { timeout: 10 }); // times out assert.ok(shell.error()); } // check process.env works assert.ok(!shell.env.FOO); shell.env.FOO = 'Hello world'; result = shell.exec(process.platform !== 'win32' ? 'echo $FOO' : 'echo %FOO%'); assert.ok(!shell.error()); assert.equal(result.code, 0); assert.equal(result.stdout, 'Hello world' + os.EOL); assert.equal(result.stderr, ''); // set shell option (TODO: add tests for Windows) if (process.platform !== 'win32') { result = shell.exec('echo $0'); assert.ok(!shell.error()); assert.equal(result.code, 0); assert.equal(result.stdout, '/bin/sh\n'); // sh by default var bashPath = shell.which('bash').trim(); // this option doesn't work on v0.10 if (bashPath && process.version >= 'v0.11') { result = shell.exec('echo $0', { shell: '/bin/bash' }); assert.ok(!shell.error()); assert.equal(result.code, 0); assert.equal(result.stdout, '/bin/bash\n'); } } // exec returns a ShellString result = shell.exec('echo foo'); assert.ok(typeof result === 'object'); assert.ok(result instanceof String); assert.ok(typeof result.stdout === 'string'); assert.strictEqual(result.toString(), result.stdout); // // async // // no callback var c = shell.exec(JSON.stringify(process.execPath) + ' -e "console.log(1234)"', { async: true }); assert.equal(shell.error(), null); assert.ok('stdout' in c, 'async exec returns child process object'); // // callback as 2nd argument // shell.exec(JSON.stringify(process.execPath) + ' -e "console.log(5678);"', function (code, stdout, stderr) { assert.equal(code, 0); assert.ok(stdout === '5678\n' || stdout === '5678\nundefined\n'); // 'undefined' for v0.4 assert.ok(stderr === '' || stderr === 'undefined\n'); // 'undefined' for v0.4 // // callback as 3rd argument // shell.exec(JSON.stringify(process.execPath) + ' -e "console.log(5566);"', { async: true }, function (code2, stdout2, stderr2) { assert.equal(code2, 0); assert.ok(stdout2 === '5566\n' || stdout2 === '5566\nundefined\n'); // 'undefined' for v0.4 assert.ok(stderr2 === '' || stderr2 === 'undefined\n'); // 'undefined' for v0.4 // // callback as 3rd argument (slient:true) // shell.exec(JSON.stringify(process.execPath) + ' -e "console.log(5678);"', { silent: true }, function (code3, stdout3, stderr3) { assert.equal(code3, 0); assert.ok(stdout3 === '5678\n' || stdout3 === '5678\nundefined\n'); // 'undefined' for v0.4 assert.ok(stderr3 === '' || stderr3 === 'undefined\n'); // 'undefined' for v0.4 shell.exit(123); }); }); }); assert.equal(shell.error(), null); shelljs-0.7.5/test/find.js000066400000000000000000000030451300431262200154170ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); // // Invalids // var result = shell.find(); // no paths given assert.equal(result.code, 1); assert.ok(shell.error()); // // Valids // // current path shell.cd('resources/find'); result = shell.find('.'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.indexOf('.hidden') > -1, true); assert.equal(result.indexOf('dir1/dir11/a_dir11') > -1, true); assert.equal(result.length, 11); shell.cd('../..'); // simple path result = shell.find('resources/find'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.indexOf('resources/find/.hidden') > -1, true); assert.equal(result.indexOf('resources/find/dir1/dir11/a_dir11') > -1, true); assert.equal(result.length, 11); // multiple paths - comma result = shell.find('resources/find/dir1', 'resources/find/dir2'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.indexOf('resources/find/dir1/dir11/a_dir11') > -1, true); assert.equal(result.indexOf('resources/find/dir2/a_dir1') > -1, true); assert.equal(result.length, 6); // multiple paths - array result = shell.find(['resources/find/dir1', 'resources/find/dir2']); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.indexOf('resources/find/dir1/dir11/a_dir11') > -1, true); assert.equal(result.indexOf('resources/find/dir2/a_dir1') > -1, true); assert.equal(result.length, 6); shell.exit(123); shelljs-0.7.5/test/global.js000066400000000000000000000015101300431262200157320ustar00rootroot00000000000000/* globals cat, config, cp, env, error, exit, mkdir, rm */ require('../global'); var assert = require('assert'); var fs = require('fs'); config.silent = true; rm('-rf', 'tmp'); mkdir('tmp'); // // Valids // assert.equal(process.env, env); // cat var result = cat('resources/cat/file1'); assert.equal(error(), null); assert.equal(result.code, 0); assert.equal(result, 'test1\n'); // rm cp('-f', 'resources/file1', 'tmp/file1'); assert.equal(fs.existsSync('tmp/file1'), true); result = rm('tmp/file1'); assert.equal(error(), null); assert.equal(result.code, 0); assert.equal(fs.existsSync('tmp/file1'), false); // String.prototype is modified for global require 'foo'.to('tmp/testfile.txt'); assert.equal('foo', cat('tmp/testfile.txt')); 'bar'.toEnd('tmp/testfile.txt'); assert.equal('foobar', cat('tmp/testfile.txt')); exit(123); shelljs-0.7.5/test/grep.js000066400000000000000000000067651300431262200154500ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var fs = require('fs'); shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); // // Invalids // var result; result = shell.grep(); assert.ok(shell.error()); assert.equal(result.code, 2); result = shell.grep(/asdf/g); // too few args assert.ok(shell.error()); assert.equal(result.code, 2); assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check result = shell.grep(/asdf/g, '/asdfasdf'); // no such file assert.ok(shell.error()); assert.equal(result.stderr, 'grep: no such file or directory: /asdfasdf'); assert.equal(result.code, 2); // if at least one file is missing, this should be an error shell.cp('-f', 'resources/file1', 'tmp/file1'); assert.equal(fs.existsSync('asdfasdf'), false); // sanity check assert.equal(fs.existsSync('tmp/file1'), true); // sanity check result = shell.grep(/asdf/g, 'tmp/file1', 'asdfasdf'); assert.ok(shell.error()); assert.equal(result.stderr, 'grep: no such file or directory: asdfasdf'); assert.equal(result.code, 2); // // Valids // result = shell.grep('line', 'resources/a.txt'); assert.equal(shell.error(), null); assert.equal(result.split('\n').length - 1, 4); result = shell.grep('-v', 'line', 'resources/a.txt'); assert.equal(shell.error(), null); assert.equal(result.split('\n').length - 1, 8); result = shell.grep('line one', 'resources/a.txt'); assert.equal(shell.error(), null); assert.equal(result, 'This is line one\n'); // multiple files result = shell.grep(/test/, 'resources/file1.txt', 'resources/file2.txt'); assert.equal(shell.error(), null); assert.equal(result, 'test1\ntest2\n'); // multiple files, array syntax result = shell.grep(/test/, ['resources/file1.txt', 'resources/file2.txt']); assert.equal(shell.error(), null); assert.equal(result, 'test1\ntest2\n'); // multiple files, glob syntax, * for file name result = shell.grep(/test/, 'resources/file*.txt'); assert.equal(shell.error(), null); assert.ok(result.toString() === 'test1\ntest2\n' || result.toString() === 'test2\ntest1\n'); // multiple files, glob syntax, * for directory name result = shell.grep(/test/, '*/file*.txt'); assert.equal(shell.error(), null); assert.ok(result.toString() === 'test1\ntest2\n' || result.toString() === 'test2\ntest1\n'); // multiple files, glob syntax, ** for directory name result = shell.grep(/test/, '**/file*.js'); assert.equal(shell.error(), null); assert.equal(result, 'test\ntest\ntest\ntest\n'); // one file, * in regex result = shell.grep(/alpha*beta/, 'resources/grep/file'); assert.equal(shell.error(), null); assert.equal(result, 'alphaaaaaaabeta\nalphbeta\n'); // one file, * in string-regex result = shell.grep('alpha*beta', 'resources/grep/file'); assert.equal(shell.error(), null); assert.equal(result, 'alphaaaaaaabeta\nalphbeta\n'); // one file, * in regex, make sure * is not globbed result = shell.grep(/l*\.js/, 'resources/grep/file'); assert.equal(shell.error(), null); assert.equal(result, 'this line ends in.js\nlllllllllllllllll.js\n'); // one file, * in string-regex, make sure * is not globbed result = shell.grep('l*\\.js', 'resources/grep/file'); assert.equal(shell.error(), null); assert.equal(result, 'this line ends in.js\nlllllllllllllllll.js\n'); // -l option result = shell.grep('-l', 'test1', 'resources/file1', 'resources/file2', 'resources/file1.txt'); assert.equal(shell.error(), null); assert.ok(result.match(/file1(\n|$)/)); assert.ok(result.match(/file1.txt/)); assert.ok(!result.match(/file2.txt/)); assert.equal(result.split('\n').length - 1, 2); shell.exit(123); shelljs-0.7.5/test/head.js000066400000000000000000000073041300431262200154020ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var fs = require('fs'); shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); var result; // // Invalids // result = shell.head(); assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check result = shell.head('/adsfasdf'); // file does not exist assert.ok(shell.error()); assert.equal(result.code, 1); // // Valids // var topOfFile1 = ['file1 1', 'file1 2', 'file1 3', 'file1 4', 'file1 5', 'file1 6', 'file1 7', 'file1 8', 'file1 9', 'file1 10', 'file1 11', 'file1 12', 'file1 13', 'file1 14', 'file1 15', 'file1 16', 'file1 17', 'file1 18', 'file1 19', 'file1 20']; var topOfFile2 = ['file2 1', 'file2 2', 'file2 3', 'file2 4', 'file2 5', 'file2 6', 'file2 7', 'file2 8', 'file2 9', 'file2 10', 'file2 11', 'file2 12', 'file2 13', 'file2 14', 'file2 15', 'file2 16', 'file2 17', 'file2 18', 'file2 19', 'file2 20']; // simple result = shell.head('resources/head/file1.txt'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result, topOfFile1.slice(0, 10).join('\n') + '\n'); // multiple files result = shell.head('resources/head/file2.txt', 'resources/head/file1.txt'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result, topOfFile2 .slice(0, 10) .concat(topOfFile1.slice(0, 10)) .join('\n') + '\n' ); // multiple files, array syntax result = shell.head(['resources/head/file2.txt', 'resources/head/file1.txt']); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result, topOfFile2 .slice(0, 10) .concat(topOfFile1.slice(0, 10)) .join('\n') + '\n' ); // reading more lines than are in the file (no trailing newline) result = shell.head('resources/file2', 'resources/file1'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result, 'test2\ntest1'); // these files only have one line (no \n) // reading more lines than are in the file (with trailing newline) result = shell.head('resources/head/shortfile2', 'resources/head/shortfile1'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result, 'short2\nshort1\n'); // these files only have one line (with \n) // Globbed file result = shell.head('resources/head/file?.txt'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result, topOfFile1 .slice(0, 10) .concat(topOfFile2.slice(0, 10)) .join('\n') + '\n' ); // With `'-n' ` option result = shell.head('-n', 4, 'resources/head/file2.txt', 'resources/head/file1.txt'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result, topOfFile2 .slice(0, 4) .concat(topOfFile1.slice(0, 4)) .join('\n') + '\n' ); // With `{'-n': }` option result = shell.head({ '-n': 4 }, 'resources/head/file2.txt', 'resources/head/file1.txt'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result, topOfFile2 .slice(0, 4) .concat(topOfFile1.slice(0, 4)) .join('\n') + '\n' ); // negative values (-num) are the same as (numLines - num) result = shell.head('-n', -46, 'resources/head/file1.txt'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result, 'file1 1\nfile1 2\nfile1 3\nfile1 4\n'); shell.exit(123); shelljs-0.7.5/test/ln.js000066400000000000000000000125151300431262200151120ustar00rootroot00000000000000var shell = require('..'); var common = require('../src/common'); var isWindows = common.platform === 'win'; var assert = require('assert'); var fs = require('fs'); var path = require('path'); shell.config.silent = true; // On Windows, symlinks for files need admin permissions. This helper // skips certain tests if we are on Windows and got an EPERM error function skipOnWinForEPERM(action, test) { action(); var error = shell.error(); if (isWindows && error && /EPERM:/.test(error)) { console.log('Got EPERM when testing symlinks on Windows. Assuming non-admin environment and skipping test.'); } else { test(); } } shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); // Prepare tmp/ shell.cp('resources/*', 'tmp'); // // Invalids // var result = shell.ln(); assert.ok(shell.error()); assert.equal(result.code, 1); result = shell.ln('file'); assert.ok(shell.error()); assert.equal(result.code, 1); result = shell.ln('-f'); assert.ok(shell.error()); assert.equal(result.code, 1); result = shell.ln('tmp/file1', 'tmp/file2'); assert.ok(shell.error()); assert.equal(result.code, 1); result = shell.ln('tmp/noexist', 'tmp/linkfile1'); assert.ok(shell.error()); assert.equal(result.code, 1); result = shell.ln('-sf', 'no/exist', 'tmp/badlink'); assert.ok(shell.error()); assert.equal(result.code, 1); result = shell.ln('-sf', 'noexist', 'tmp/badlink'); assert.ok(shell.error()); assert.equal(result.code, 1); result = shell.ln('-f', 'noexist', 'tmp/badlink'); assert.ok(shell.error()); assert.equal(result.code, 1); // // Valids // result = shell.ln('tmp/file1', 'tmp/linkfile1'); assert(fs.existsSync('tmp/linkfile1')); assert.equal( fs.readFileSync('tmp/file1').toString(), fs.readFileSync('tmp/linkfile1').toString() ); fs.writeFileSync('tmp/file1', 'new content 1'); assert.equal( fs.readFileSync('tmp/linkfile1').toString(), 'new content 1' ); assert.equal(result.code, 0); // With glob shell.rm('tmp/linkfile1'); result = shell.ln('tmp/fi*1', 'tmp/linkfile1'); assert(fs.existsSync('tmp/linkfile1')); assert.equal( fs.readFileSync('tmp/file1').toString(), fs.readFileSync('tmp/linkfile1').toString() ); fs.writeFileSync('tmp/file1', 'new content 1'); assert.equal( fs.readFileSync('tmp/linkfile1').toString(), 'new content 1' ); assert.equal(result.code, 0); skipOnWinForEPERM(shell.ln.bind(shell, '-s', 'file2', 'tmp/linkfile2'), function () { assert(fs.existsSync('tmp/linkfile2')); assert.equal( fs.readFileSync('tmp/file2').toString(), fs.readFileSync('tmp/linkfile2').toString() ); fs.writeFileSync('tmp/file2', 'new content 2'); assert.equal( fs.readFileSync('tmp/linkfile2').toString(), 'new content 2' ); }); // Symbolic link directory test shell.mkdir('tmp/ln'); shell.touch('tmp/ln/hello'); result = shell.ln('-s', 'ln', 'tmp/dir1'); assert(fs.existsSync('tmp/ln/hello')); assert(fs.existsSync('tmp/dir1/hello')); assert.equal(result.code, 0); // To current directory shell.cd('tmp'); result = shell.ln('-s', './', 'dest'); assert.equal(result.code, 0); shell.touch('testfile.txt'); assert(fs.existsSync('testfile.txt')); assert(fs.existsSync('dest/testfile.txt')); shell.rm('-f', 'dest'); shell.mkdir('dir1'); shell.cd('dir1'); result = shell.ln('-s', './', '../dest'); assert.equal(result.code, 0); shell.touch('insideDir.txt'); shell.cd('..'); assert(fs.existsSync('testfile.txt')); assert(fs.existsSync('dest/testfile.txt')); assert(fs.existsSync('dir1/insideDir.txt')); assert(!fs.existsSync('dest/insideDir.txt')); shell.cd('..'); result = shell.ln('-f', 'tmp/file1.js', 'tmp/file2.js'); assert.equal(result.code, 0); assert(fs.existsSync('tmp/file2.js')); assert.equal( fs.readFileSync('tmp/file1.js').toString(), fs.readFileSync('tmp/file2.js').toString() ); fs.writeFileSync('tmp/file1.js', 'new content js'); assert.equal( fs.readFileSync('tmp/file2.js').toString(), 'new content js' ); skipOnWinForEPERM(shell.ln.bind(shell, '-sf', 'file1.txt', 'tmp/file2.txt'), function () { assert(fs.existsSync('tmp/file2.txt')); assert.equal( fs.readFileSync('tmp/file1.txt').toString(), fs.readFileSync('tmp/file2.txt').toString() ); fs.writeFileSync('tmp/file1.txt', 'new content txt'); assert.equal( fs.readFileSync('tmp/file2.txt').toString(), 'new content txt' ); }); // Abspath regression skipOnWinForEPERM(shell.ln.bind(shell, '-sf', 'file1', path.resolve('tmp/abspath')), function () { assert(fs.existsSync('tmp/abspath')); assert.equal( fs.readFileSync('tmp/file1').toString(), fs.readFileSync('tmp/abspath').toString() ); fs.writeFileSync('tmp/file1', 'new content 3'); assert.equal( fs.readFileSync('tmp/abspath').toString(), 'new content 3' ); }); // Relative regression skipOnWinForEPERM(shell.ln.bind(shell, '-sf', 'file1.txt', 'tmp/file2.txt'), function () { shell.mkdir('-p', 'tmp/new'); // Move the symlink first, as the reverse confuses `mv`. shell.mv('tmp/file2.txt', 'tmp/new/file2.txt'); shell.mv('tmp/file1.txt', 'tmp/new/file1.txt'); assert(fs.existsSync('tmp/new/file2.txt')); assert.equal( fs.readFileSync('tmp/new/file1.txt').toString(), fs.readFileSync('tmp/new/file2.txt').toString() ); fs.writeFileSync('tmp/new/file1.txt', 'new content txt'); assert.equal( fs.readFileSync('tmp/new/file2.txt').toString(), 'new content txt' ); }); shell.exit(123); shelljs-0.7.5/test/ls.js000066400000000000000000000376631300431262200151320ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var fs = require('fs'); shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); var idx; var k; // // Invalids // assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check var result = shell.ls('/asdfasdf'); // no such file or dir assert.ok(shell.error()); assert.equal(result.code, 2); assert.equal(result.length, 0); // // Valids // result = shell.ls(); assert.equal(shell.error(), null); assert.equal(result.code, 0); result = shell.ls('/'); assert.equal(shell.error(), null); assert.equal(result.code, 0); // no args shell.cd('resources/ls'); result = shell.ls(); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.indexOf('file1') > -1, true); assert.equal(result.indexOf('file2') > -1, true); assert.equal(result.indexOf('file1.js') > -1, true); assert.equal(result.indexOf('file2.js') > -1, true); assert.equal(result.indexOf('filename(with)[chars$]^that.must+be-escaped') > -1, true); assert.equal(result.indexOf('a_dir') > -1, true); assert.equal(result.length, 6); shell.cd('../..'); // simple arg result = shell.ls('resources/ls'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.indexOf('file1') > -1, true); assert.equal(result.indexOf('file2') > -1, true); assert.equal(result.indexOf('file1.js') > -1, true); assert.equal(result.indexOf('file2.js') > -1, true); assert.equal(result.indexOf('filename(with)[chars$]^that.must+be-escaped') > -1, true); assert.equal(result.indexOf('a_dir') > -1, true); assert.equal(result.length, 6); // simple arg, with a trailing slash result = shell.ls('resources/ls/'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.indexOf('file1') > -1, true); assert.equal(result.indexOf('file2') > -1, true); assert.equal(result.indexOf('file1.js') > -1, true); assert.equal(result.indexOf('file2.js') > -1, true); assert.equal(result.indexOf('filename(with)[chars$]^that.must+be-escaped') > -1, true); assert.equal(result.indexOf('a_dir') > -1, true); assert.equal(result.length, 6); // no args, 'all' option shell.cd('resources/ls'); result = shell.ls('-A'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.indexOf('file1') > -1, true); assert.equal(result.indexOf('file2') > -1, true); assert.equal(result.indexOf('file1.js') > -1, true); assert.equal(result.indexOf('file2.js') > -1, true); assert.equal(result.indexOf('filename(with)[chars$]^that.must+be-escaped') > -1, true); assert.equal(result.indexOf('a_dir') > -1, true); assert.equal(result.indexOf('.hidden_file') > -1, true); assert.equal(result.indexOf('.hidden_dir') > -1, true); assert.equal(result.length, 8); shell.cd('../..'); // no args, 'all' option shell.cd('resources/ls'); result = shell.ls('-a'); // (deprecated) backwards compatibility test assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.indexOf('file1') > -1, true); assert.equal(result.indexOf('file2') > -1, true); assert.equal(result.indexOf('file1.js') > -1, true); assert.equal(result.indexOf('file2.js') > -1, true); assert.equal(result.indexOf('filename(with)[chars$]^that.must+be-escaped') > -1, true); assert.equal(result.indexOf('a_dir') > -1, true); assert.equal(result.indexOf('.hidden_file') > -1, true); assert.equal(result.indexOf('.hidden_dir') > -1, true); assert.equal(result.length, 8); shell.cd('../..'); // wildcard, very simple result = shell.ls('resources/cat/*'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.indexOf('resources/cat/file1') > -1, true); assert.equal(result.indexOf('resources/cat/file2') > -1, true); assert.equal(result.length, 2); // wildcard, simple result = shell.ls('resources/ls/*'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.indexOf('resources/ls/file1') > -1, true); assert.equal(result.indexOf('resources/ls/file2') > -1, true); assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); assert.equal(result.indexOf('resources/ls/filename(with)[chars$]^that.must+be-escaped') > -1, true); assert.ok(result.indexOf('resources/ls/a_dir') === -1); // this shouldn't be there assert.ok(result.indexOf('nada') > -1); assert.ok(result.indexOf('b_dir') > -1); assert.equal(result.length, 7); // wildcard, simple, with -d result = shell.ls('-d', 'resources/ls/*'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.indexOf('resources/ls/file1') > -1, true); assert.equal(result.indexOf('resources/ls/file2') > -1, true); assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); assert.equal(result.indexOf('resources/ls/filename(with)[chars$]^that.must+be-escaped') > -1, true); assert.ok(result.indexOf('resources/ls/a_dir') > -1); assert.equal(result.length, 6); // wildcard, hidden only result = shell.ls('-d', 'resources/ls/.*'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.indexOf('resources/ls/.hidden_file') > -1, true); assert.equal(result.indexOf('resources/ls/.hidden_dir') > -1, true); assert.equal(result.length, 2); // wildcard, mid-file result = shell.ls('resources/ls/f*le*'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.length, 5); assert.equal(result.indexOf('resources/ls/file1') > -1, true); assert.equal(result.indexOf('resources/ls/file2') > -1, true); assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); assert.equal(result.indexOf('resources/ls/filename(with)[chars$]^that.must+be-escaped') > -1, true); // wildcard, mid-file with dot (should escape dot for regex) result = shell.ls('resources/ls/f*le*.js'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.length, 2); assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); // one file that exists, one that doesn't result = shell.ls('resources/ls/file1.js', 'resources/ls/thisdoesntexist'); assert.ok(shell.error()); assert.equal(result.code, 2); assert.equal(result.length, 1); assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); // one file that exists, one that doesn't (other order) result = shell.ls('resources/ls/thisdoesntexist', 'resources/ls/file1.js'); assert.ok(shell.error()); assert.equal(result.code, 2); assert.equal(result.length, 1); assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); // wildcard, should not do partial matches result = shell.ls('resources/ls/*.j'); // shouldn't get .js assert.ok(shell.error()); assert.equal(result.code, 2); assert.equal(result.length, 0); // wildcard, all files with extension result = shell.ls('resources/ls/*.*'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.length, 3); assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); assert.equal(result.indexOf('resources/ls/filename(with)[chars$]^that.must+be-escaped') > -1, true); // wildcard, with additional path result = shell.ls('resources/ls/f*le*.js', 'resources/ls/a_dir'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.length, 4); assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); assert.equal(result.indexOf('b_dir') > -1, true); // no wildcard == no path prefix assert.equal(result.indexOf('nada') > -1, true); // no wildcard == no path prefix // wildcard for both paths result = shell.ls('resources/ls/f*le*.js', 'resources/ls/a_dir/*'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.length, 4); assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); assert.equal(result.indexOf('z') > -1, true); assert.equal(result.indexOf('resources/ls/a_dir/nada') > -1, true); // wildcard for both paths, array result = shell.ls(['resources/ls/f*le*.js', 'resources/ls/a_dir/*']); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.length, 4); assert.equal(result.indexOf('resources/ls/file1.js') > -1, true); assert.equal(result.indexOf('resources/ls/file2.js') > -1, true); assert.equal(result.indexOf('z') > -1, true); assert.equal(result.indexOf('resources/ls/a_dir/nada') > -1, true); // recursive, no path shell.cd('resources/ls'); result = shell.ls('-R'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.indexOf('a_dir') > -1, true); assert.equal(result.indexOf('a_dir/b_dir') > -1, true); assert.equal(result.indexOf('a_dir/b_dir/z') > -1, true); assert.equal(result.length, 9); shell.cd('../..'); // recusive, path given result = shell.ls('-R', 'resources/ls'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.indexOf('a_dir') > -1, true); assert.equal(result.indexOf('a_dir/b_dir') > -1, true); assert.equal(result.indexOf('a_dir/b_dir/z') > -1, true); assert.equal(result.length, 9); // recusive, path given - 'all' flag result = shell.ls('-RA', 'resources/ls'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.indexOf('a_dir') > -1, true); assert.equal(result.indexOf('a_dir/b_dir') > -1, true); assert.equal(result.indexOf('a_dir/b_dir/z') > -1, true); assert.equal(result.indexOf('a_dir/.hidden_dir/nada') > -1, true); assert.equal(result.length, 14); // recursive, wildcard result = shell.ls('-R', 'resources/ls'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.indexOf('a_dir') > -1, true); assert.equal(result.indexOf('a_dir/b_dir') > -1, true); assert.equal(result.indexOf('a_dir/b_dir/z') > -1, true); assert.equal(result.length, 9); // -Rd works like -d result = shell.ls('-Rd', 'resources/ls'); assert.equal(shell.error(), null); assert.equal(result.length, 1); // directory option, single arg result = shell.ls('-d', 'resources/ls'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.length, 1); // directory option, single arg with trailing '/' result = shell.ls('-d', 'resources/ls/'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.length, 1); // directory option, multiple args result = shell.ls('-d', 'resources/ls/a_dir', 'resources/ls/file1'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.ok(result.indexOf('resources/ls/a_dir') > -1); assert.ok(result.indexOf('resources/ls/file1') > -1); assert.equal(result.length, 2); // directory option, globbed arg result = shell.ls('-d', 'resources/ls/*'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.ok(result.indexOf('resources/ls/a_dir') > -1); assert.ok(result.indexOf('resources/ls/file1') > -1); assert.ok(result.indexOf('resources/ls/file1.js') > -1); assert.ok(result.indexOf('resources/ls/file2') > -1); assert.ok(result.indexOf('resources/ls/file2.js') > -1); assert.ok(result.indexOf('resources/ls/file2') > -1); assert.ok(result.indexOf('resources/ls/filename(with)[chars$]^that.must+be-escaped') > -1); assert.equal(result.length, 6); // long option, single file result = shell.ls('-l', 'resources/ls/file1'); assert.equal(result.length, 1); result = result[0]; assert.equal(shell.error(), null); assert.ok(result.name, 'file1'); assert.equal(result.nlink, 1); assert.equal(result.size, 5); assert.ok(result.mode); // check that these keys exist assert.ok(process.platform === 'win32' || result.uid); // only on unix assert.ok(process.platform === 'win32' || result.gid); // only on unix assert.ok(result.mtime); // check that these keys exist assert.ok(result.atime); // check that these keys exist assert.ok(result.ctime); // check that these keys exist assert.ok(result.toString().match(/^(\d+ +){5}.*$/)); // long option, glob files result = shell.ls('-l', 'resources/ls/f*le1'); assert.equal(result.length, 1); result = result[0]; assert.equal(shell.error(), null); assert.ok(result.name, 'file1'); assert.equal(result.nlink, 1); assert.equal(result.size, 5); assert.ok(result.mode); // check that these keys exist assert.ok(process.platform === 'win32' || result.uid); // only on unix assert.ok(process.platform === 'win32' || result.gid); // only on unix assert.ok(result.mtime); // check that these keys exist assert.ok(result.atime); // check that these keys exist assert.ok(result.ctime); // check that these keys exist assert.ok(result.toString().match(/^(\d+ +){5}.*$/)); // long option, directory result = shell.ls('-l', 'resources/ls'); assert.equal(shell.error(), null); assert.equal(result.code, 0); idx = -1; for (k = 0; k < result.length; k++) { if (result[k].name === 'file1') { idx = k; break; } } assert.ok(idx >= 0); assert.equal(result.length, 6); result = result[idx]; assert.equal(result.name, 'file1'); assert.equal(result.nlink, 1); assert.equal(result.size, 5); assert.ok(result.mode); // check that these keys exist assert.ok(process.platform === 'win32' || result.uid); // only on unix assert.ok(process.platform === 'win32' || result.gid); // only on unix assert.ok(result.mtime); // check that these keys exist assert.ok(result.atime); // check that these keys exist assert.ok(result.ctime); // check that these keys exist assert.ok(result.toString().match(/^(\d+ +){5}.*$/)); // long option, directory, recursive (and windows converts slashes) result = shell.ls('-lR', 'resources/ls/'); assert.equal(shell.error(), null); assert.equal(result.code, 0); idx = -1; for (k = 0; k < result.length; k++) { if (result[k].name === 'a_dir/b_dir') { idx = k; break; } } assert.equal(result.length, 9); assert.ok(idx >= 0); result = result[idx]; assert.equal(result.name, result.name); assert.ok(fs.statSync('resources/ls/a_dir/b_dir').isDirectory()); assert.ok(typeof result.nlink === 'number'); // This can vary between the local machine and travis assert.ok(typeof result.size === 'number'); // This can vary between different file systems assert.ok(result.mode); // check that these keys exist assert.ok(process.platform === 'win32' || result.uid); // only on unix assert.ok(process.platform === 'win32' || result.gid); // only on unix assert.ok(result.mtime); // check that these keys exist assert.ok(result.atime); // check that these keys exist assert.ok(result.ctime); // check that these keys exist assert.ok(result.toString().match(/^(\d+ +){5}.*$/)); // still lists broken links result = shell.ls('resources/badlink'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.indexOf('resources/badlink') > -1, true); assert.equal(result.length, 1); // Test new ShellString-like attributes result = shell.ls('resources/ls'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.stdout.indexOf('file1') > -1, true); assert.equal(result.stdout.indexOf('file2') > -1, true); assert.equal(result.stdout.indexOf('file1.js') > -1, true); assert.equal(result.stdout.indexOf('file2.js') > -1, true); assert.equal(result.stdout.indexOf('filename(with)[chars$]^that.must+be-escaped') > -1, true); assert.equal(result.stdout.indexOf('a_dir') > -1, true); assert.strictEqual(typeof result.stdout, 'string'); assert.ok(result.to); assert.ok(result.toEnd); result.to('tmp/testingToOutput.txt'); assert.equal(shell.cat('tmp/testingToOutput.txt'), result.stdout); shell.rm('tmp/testingToOutput.txt'); // No trailing newline for ls() on empty directories shell.mkdir('foo'); assert.ok(!shell.error()); result = shell.ls('foo'); assert.ok(!shell.error()); assert.equal(result.stdout, ''); shell.rm('-r', 'foo'); assert.ok(!shell.error()); // Check stderr field assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check result = shell.ls('resources/ls/file1', '/asdfasdf'); assert.ok(shell.error()); assert.equal('ls: no such file or directory: /asdfasdf', result.stderr); shell.exit(123); shelljs-0.7.5/test/make.js000066400000000000000000000012541300431262200154140ustar00rootroot00000000000000var shell = require('..'); var child = require('child_process'); var assert = require('assert'); shell.mkdir('-p', 'tmp'); var file = 'tmp/tempscript' + Math.random() + '.js'; var script = 'require(\'../../make.js\');' + 'target.all=function(){' + ' echo("first"); ' + ' cp("this_file_doesnt_exist", ".");' + ' echo("second");' + '}'; shell.ShellString(script).to(file); child.exec(JSON.stringify(process.execPath) + ' ' + file, function (err, stdout) { assert.ok(stdout.match('first')); assert.ok(!stdout.match('second')); // Make should die on errors, so this should never get echoed shell.exit(123); }); shelljs-0.7.5/test/mkdir.js000066400000000000000000000077101300431262200156100ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var fs = require('fs'); var numLines = require('./utils/utils').numLines; shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); // // Invalids // var result = shell.mkdir(); assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(result.stderr, 'mkdir: no paths given'); var mtime = fs.statSync('tmp').mtime.toString(); result = shell.mkdir('tmp'); // dir already exists assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(result.stderr, 'mkdir: path already exists: tmp'); assert.equal(fs.statSync('tmp').mtime.toString(), mtime); // didn't mess with dir // Can't overwrite a broken link mtime = fs.lstatSync('resources/badlink').mtime.toString(); result = shell.mkdir('resources/badlink'); assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(result.stderr, 'mkdir: path already exists: resources/badlink'); assert.equal(fs.lstatSync('resources/badlink').mtime.toString(), mtime); // didn't mess with file assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check result = shell.mkdir('/asdfasdf/foobar'); // root path does not exist assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(result.stderr, 'mkdir: no such file or directory: /asdfasdf'); assert.equal(fs.existsSync('/asdfasdf'), false); assert.equal(fs.existsSync('/asdfasdf/foobar'), false); // Check for invalid permissions if (process.platform !== 'win32') { // This test case only works on unix, but should work on Windows as well var dirName = 'nowritedir'; shell.mkdir(dirName); assert.ok(!shell.error()); shell.chmod('-w', dirName); result = shell.mkdir(dirName + '/foo'); assert.equal(result.code, 1); assert.equal(result.stderr, 'mkdir: cannot create directory nowritedir/foo: Permission denied'); assert.ok(shell.error()); assert.equal(fs.existsSync(dirName + '/foo'), false); shell.rm('-rf', dirName); // clean up } // // Valids // assert.equal(fs.existsSync('tmp/t1'), false); result = shell.mkdir('tmp/t1'); // simple dir assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(fs.existsSync('tmp/t1'), true); assert.equal(fs.existsSync('tmp/t2'), false); assert.equal(fs.existsSync('tmp/t3'), false); result = shell.mkdir('tmp/t2', 'tmp/t3'); // multiple dirs assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(fs.existsSync('tmp/t2'), true); assert.equal(fs.existsSync('tmp/t3'), true); assert.equal(fs.existsSync('tmp/t1'), true); assert.equal(fs.existsSync('tmp/t4'), false); result = shell.mkdir('tmp/t1', 'tmp/t4'); // one dir exists, one doesn't assert.equal(numLines(shell.error()), 1); assert.equal(fs.existsSync('tmp/t1'), true); assert.equal(fs.existsSync('tmp/t4'), true); assert.equal(fs.existsSync('tmp/a'), false); result = shell.mkdir('-p', 'tmp/a/b/c'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(fs.existsSync('tmp/a/b/c'), true); shell.rm('-Rf', 'tmp/a'); // revert // multiple dirs result = shell.mkdir('-p', 'tmp/zzza', 'tmp/zzzb', 'tmp/zzzc'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(fs.existsSync('tmp/zzza'), true); assert.equal(fs.existsSync('tmp/zzzb'), true); assert.equal(fs.existsSync('tmp/zzzc'), true); // multiple dirs, array syntax result = shell.mkdir('-p', ['tmp/yyya', 'tmp/yyyb', 'tmp/yyyc']); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(fs.existsSync('tmp/yyya'), true); assert.equal(fs.existsSync('tmp/yyyb'), true); assert.equal(fs.existsSync('tmp/yyyc'), true); // globbed dir result = shell.mkdir('-p', 'tmp/mydir'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(fs.existsSync('tmp/mydir'), true); result = shell.mkdir('-p', 'tmp/m*ir'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(fs.existsSync('tmp/mydir'), true); assert.equal(fs.existsSync('tmp/m*ir'), false); // doesn't create literal name shell.exit(123); shelljs-0.7.5/test/mv.js000066400000000000000000000132341300431262200151220ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var fs = require('fs'); var numLines = require('./utils/utils').numLines; shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); // Prepare tmp/ shell.cp('resources/*', 'tmp'); // // Invalids // var result = shell.mv(); assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(result.stderr, 'mv: missing and/or '); result = shell.mv('file1'); assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(result.stderr, 'mv: missing and/or '); result = shell.mv('-f'); assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(result.stderr, 'mv: missing and/or '); result = shell.mv('-Z', 'tmp/file1', 'tmp/file1'); // option not supported assert.ok(shell.error()); assert.equal(fs.existsSync('tmp/file1'), true); assert.equal(result.code, 1); assert.equal(result.stderr, 'mv: option not recognized: Z'); result = shell.mv('asdfasdf', 'tmp'); // source does not exist assert.ok(shell.error()); assert.equal(numLines(shell.error()), 1); assert.equal(fs.existsSync('tmp/asdfasdf'), false); assert.equal(result.code, 1); assert.equal(result.stderr, 'mv: no such file or directory: asdfasdf'); result = shell.mv('asdfasdf1', 'asdfasdf2', 'tmp'); // sources do not exist assert.ok(shell.error()); assert.equal(numLines(shell.error()), 2); assert.equal(fs.existsSync('tmp/asdfasdf1'), false); assert.equal(fs.existsSync('tmp/asdfasdf2'), false); assert.equal(result.code, 1); assert.equal(result.stderr, 'mv: no such file or directory: asdfasdf1\nmv: no such file or directory: asdfasdf2'); result = shell.mv('asdfasdf1', 'asdfasdf2', 'tmp/file1'); // too many sources (dest is file) assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(result.stderr, 'mv: dest is not a directory (too many sources)'); // -n is no-force/no-clobber result = shell.mv('-n', 'tmp/file1', 'tmp/file2'); // dest already exists assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(result.stderr, 'mv: dest file already exists: tmp/file2'); // -f is the default behavior shell.cp('tmp/file1', 'tmp/tmp_file'); result = shell.mv('tmp/tmp_file', 'tmp/file2'); // dest already exists (but that's ok) assert.ok(!shell.error()); assert.ok(!result.stderr); assert.equal(result.code, 0); // -fn is the same as -n result = shell.mv('-fn', 'tmp/file1', 'tmp/file2'); assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(result.stderr, 'mv: dest file already exists: tmp/file2'); result = shell.mv('tmp/file1', 'tmp/file2', 'tmp/a_file'); // too many sources (exist, but dest is file) assert.ok(shell.error()); assert.equal(fs.existsSync('tmp/a_file'), false); assert.equal(result.code, 1); assert.equal(result.stderr, 'mv: dest is not a directory (too many sources)'); result = shell.mv('tmp/file*', 'tmp/file1'); // can't use wildcard when dest is file assert.ok(shell.error()); assert.equal(fs.existsSync('tmp/file1'), true); assert.equal(fs.existsSync('tmp/file2'), true); assert.equal(fs.existsSync('tmp/file1.js'), true); assert.equal(fs.existsSync('tmp/file2.js'), true); assert.equal(result.code, 1); assert.equal(result.stderr, 'mv: dest is not a directory (too many sources)'); // // Valids // shell.cd('tmp'); // handles self OK shell.mkdir('tmp2'); result = shell.mv('*', 'tmp2'); // has to handle self (tmp2 --> tmp2) without throwing error assert.ok(shell.error()); // there's an error, but not fatal assert.equal(fs.existsSync('tmp2/file1'), true); // moved OK assert.equal(result.code, 1); result = shell.mv('tmp2/*', '.'); // revert assert.equal(fs.existsSync('file1'), true); // moved OK assert.equal(result.code, 0); result = shell.mv('file1', 'file3'); // one source assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(fs.existsSync('file1'), false); assert.equal(fs.existsSync('file3'), true); result = shell.mv('file3', 'file1'); // revert assert.equal(shell.error(), null); assert.equal(fs.existsSync('file1'), true); assert.equal(result.code, 0); // two sources shell.rm('-rf', 't'); shell.mkdir('-p', 't'); result = shell.mv('file1', 'file2', 't'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(fs.existsSync('file1'), false); assert.equal(fs.existsSync('file2'), false); assert.equal(fs.existsSync('t/file1'), true); assert.equal(fs.existsSync('t/file2'), true); result = shell.mv('t/*', '.'); // revert assert.equal(result.code, 0); assert.equal(fs.existsSync('file1'), true); assert.equal(fs.existsSync('file2'), true); // two sources, array style shell.rm('-rf', 't'); shell.mkdir('-p', 't'); result = shell.mv(['file1', 'file2'], 't'); // two sources assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(fs.existsSync('file1'), false); assert.equal(fs.existsSync('file2'), false); assert.equal(fs.existsSync('t/file1'), true); assert.equal(fs.existsSync('t/file2'), true); result = shell.mv('t/*', '.'); // revert assert.equal(fs.existsSync('file1'), true); assert.equal(fs.existsSync('file2'), true); result = shell.mv('file*.js', 't'); // wildcard assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(fs.existsSync('file1.js'), false); assert.equal(fs.existsSync('file2.js'), false); assert.equal(fs.existsSync('t/file1.js'), true); assert.equal(fs.existsSync('t/file2.js'), true); result = shell.mv('t/*', '.'); // revert assert.equal(fs.existsSync('file1.js'), true); assert.equal(fs.existsSync('file2.js'), true); result = shell.mv('-f', 'file1', 'file2'); // dest exists, but -f given assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(fs.existsSync('file1'), false); assert.equal(fs.existsSync('file2'), true); shell.exit(123); shelljs-0.7.5/test/pipe.js000066400000000000000000000047101300431262200154340ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); // // Invalids // // commands like `rm` can't be on the right side of pipes assert.equal(typeof shell.ls('.').rm, 'undefined'); assert.equal(typeof shell.cat('resources/file1.txt').rm, 'undefined'); // // Valids // // piping to cat() should return roughly the same thing assert.strictEqual(shell.cat('resources/file1.txt').cat().toString(), shell.cat('resources/file1.txt').toString()); // piping ls() into cat() converts to a string assert.strictEqual(shell.ls('resources/').cat().toString(), shell.ls('resources/').stdout); var result; result = shell.ls('resources/').grep('file1'); assert.equal(result + '', 'file1\nfile1.js\nfile1.txt\n'); result = shell.ls('resources/').cat().grep('file1'); assert.equal(result + '', 'file1\nfile1.js\nfile1.txt\n'); // Equivalent to a simple grep() test case result = shell.cat('resources/grep/file').grep(/alpha*beta/); assert.equal(shell.error(), null); assert.equal(result.toString(), 'alphaaaaaaabeta\nalphbeta\n'); // Equivalent to a simple sed() test case result = shell.cat('resources/grep/file').sed(/l*\.js/, ''); assert.ok(!shell.error()); assert.equal(result.toString(), 'alphaaaaaaabeta\nhowareyou\nalphbeta\nthis line ends in\n\n'); // Sort a file by frequency of each line result = shell.sort('resources/uniq/pipe').uniq('-c').sort('-n'); assert.equal(shell.error(), null); assert.equal(result.toString(), shell.cat('resources/uniq/pipeSorted').toString()); // Synchronous exec // TODO: add windows tests if (process.platform !== 'win32') { // unix-specific if (shell.which('grep').stdout) { result = shell.cat('resources/grep/file').exec("grep 'alpha*beta'"); assert.equal(shell.error(), null); assert.equal(result, 'alphaaaaaaabeta\nalphbeta\n'); } else { console.error('Warning: Cannot verify piped exec'); } } else { console.error('Warning: Cannot verify piped exec'); } // Async exec // TODO: add windows tests if (process.platform !== 'win32') { // unix-specific if (shell.which('grep').stdout) { shell.cat('resources/grep/file').exec("grep 'alpha*beta'", function (code, stdout) { assert.equal(code, 0); assert.equal(stdout, 'alphaaaaaaabeta\nalphbeta\n'); shell.exit(123); }); } else { console.error('Warning: Cannot verify piped exec'); } } else { console.error('Warning: Cannot verify piped exec'); shell.exit(123); } shelljs-0.7.5/test/plugin.js000066400000000000000000000066101300431262200157760ustar00rootroot00000000000000var plugin = require('../plugin'); var shell = require('..'); var assert = require('assert'); shell.config.silent = true; var data = 0; var ret; var fname; function fooImplementation(options, arg) { // Some sort of side effect, so we know when this is called if (arg) { fname = arg; } else { fname = plugin.readFromPipe(); } if (arg === 'exitWithCode5') { plugin.error('Exited with code 5', 5); } else if (arg === 'changePrefix') { plugin.error('prefix was changed', { prefix: 'prefix: ', }); } else if (arg === 'continue') { plugin.error('Error, but continuing', { continue: true, }); } if (options.flag) { data = 12; } else { data++; } return 'hello world'; } // All plugin utils exist assert.equal(typeof plugin.error, 'function'); assert.equal(typeof plugin.parseOptions, 'function'); assert.equal(typeof plugin.readFromPipe, 'function'); assert.equal(typeof plugin.register, 'function'); // The plugin does not exist before it's registered assert.ok(!shell.foo); // Register the plugin plugin.register('foo', fooImplementation, { cmdOptions: { 'f': 'flag', }, wrapOutput: true, canReceivePipe: true, }); // The plugin exists after registering assert.equal(typeof shell.foo, 'function'); // The command fails for invalid options ret = shell.foo('-n', 'filename'); assert.equal(ret.code, 1); assert.equal(ret.stdout, ''); assert.equal(ret.stderr, 'foo: option not recognized: n'); assert.equal(shell.error(), 'foo: option not recognized: n'); // The command succeeds for normal calls assert.equal(data, 0); shell.foo('filename'); assert.equal(data, 1); assert.equal(fname, 'filename'); shell.foo('filename2'); assert.equal(data, 2); assert.equal(fname, 'filename2'); // The command parses options shell.foo('-f', 'filename'); assert.equal(data, 12); assert.equal(fname, 'filename'); // The command supports globbing by default shell.foo('-f', 're*u?ces'); assert.equal(data, 12); assert.equal(fname, 'resources'); // Plugins are also compatible with shelljs/global require('../global'); assert.equal(typeof global.foo, 'function'); assert.equal(global.foo, shell.foo); // Plugins can be added as methods to ShellStrings ret = shell.ShellString('hello world\n'); assert.equal(ret.toString(), 'hello world\n'); assert.equal(typeof ret.grep, 'function'); // existing methods persist assert.equal(typeof ret.foo, 'function'); ret.foo(); assert.equal(fname, 'hello world\n'); // readFromPipe() works // Plugins can signal errors ret = shell.foo('exitWithCode5'); assert.equal(ret.code, 5); assert.equal(ret.stdout, ''); assert.equal(ret.stderr, 'foo: Exited with code 5'); assert.equal(shell.error(), 'foo: Exited with code 5'); // Plugins can change the prefix ret = shell.foo('changePrefix'); assert.equal(ret.code, 1); assert.equal(ret.stdout, ''); assert.equal(ret.stderr, 'prefix: prefix was changed'); assert.equal(shell.error(), 'prefix: prefix was changed'); // Plugins can continue from errors ret = shell.foo('continue'); assert.equal(ret.code, 1); assert.equal(ret.stdout, 'hello world'); assert.equal(ret.stderr, 'foo: Error, but continuing'); assert.equal(shell.error(), 'foo: Error, but continuing'); // Cannot overwrite an existing command by default var oldCat = shell.cat; assert.throws(function () { plugin.register('cat', fooImplementation); }, 'Error: unable to overwrite `cat` command'); assert.equal(shell.cat, oldCat); shell.exit(123); shelljs-0.7.5/test/popd.js000066400000000000000000000053451300431262200154460ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var path = require('path'); shell.config.silent = true; var root = path.resolve(); var trail; function reset() { shell.dirs('-c'); shell.cd(root); } // Valid shell.pushd('resources/pushd'); trail = shell.popd(); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [root]); shell.pushd('resources/pushd'); shell.pushd('a'); trail = shell.popd(); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [ path.resolve(root, 'resources/pushd'), root ]); shell.pushd('b'); trail = shell.popd(); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [ path.resolve(root, 'resources/pushd'), root ]); shell.pushd('b'); shell.pushd('c'); trail = shell.popd(); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [ path.resolve(root, 'resources/pushd/b'), path.resolve(root, 'resources/pushd'), root ]); trail = shell.popd(); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [ path.resolve(root, 'resources/pushd'), root ]); trail = shell.popd(); assert.equal(shell.error(), null); assert.equal(trail.length, 1); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [root]); // Valid by index shell.pushd('resources/pushd'); trail = shell.popd('+0'); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [root]); shell.pushd('resources/pushd'); trail = shell.popd('+1'); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [path.resolve(root, 'resources/pushd')]); reset(); shell.pushd('resources/pushd'); trail = shell.popd('-0'); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [path.resolve(root, 'resources/pushd')]); reset(); shell.pushd('resources/pushd'); trail = shell.popd('-1'); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [root]); reset(); shell.pushd('resources/pushd'); trail = shell.popd('-n'); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [path.resolve(root, 'resources/pushd')]); // Invalid trail = shell.popd(); assert.ok(shell.error('popd: directory stack empty\n')); // Test that the root dir is not stored shell.cd('resources/pushd'); shell.pushd('b'); trail = shell.popd(); assert.equal(shell.error(), null); assert.equal(trail[0], path.resolve(root, 'resources/pushd')); assert.equal(process.cwd(), trail[0]); shell.popd(); assert.ok(shell.error(), null); shell.cd(root); shell.exit(123); shelljs-0.7.5/test/pushd.js000066400000000000000000000146341300431262200156300ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var path = require('path'); shell.config.silent = true; var root = path.resolve(); var trail; function reset() { shell.dirs('-c'); shell.cd(root); } // Push valid directories trail = shell.pushd('resources/pushd'); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [ path.resolve(root, 'resources/pushd'), root ]); trail = shell.pushd('a'); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [ path.resolve(root, 'resources/pushd/a'), path.resolve(root, 'resources/pushd'), root ]); trail = shell.pushd('../b'); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [ path.resolve(root, 'resources/pushd/b'), path.resolve(root, 'resources/pushd/a'), path.resolve(root, 'resources/pushd'), root ]); trail = shell.pushd('c'); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [ path.resolve(root, 'resources/pushd/b/c'), path.resolve(root, 'resources/pushd/b'), path.resolve(root, 'resources/pushd/a'), path.resolve(root, 'resources/pushd'), root ]); // Push stuff around with positive indices trail = shell.pushd('+0'); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [ path.resolve(root, 'resources/pushd/b/c'), path.resolve(root, 'resources/pushd/b'), path.resolve(root, 'resources/pushd/a'), path.resolve(root, 'resources/pushd'), root ]); trail = shell.pushd('+1'); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [ path.resolve(root, 'resources/pushd/b'), path.resolve(root, 'resources/pushd/a'), path.resolve(root, 'resources/pushd'), root, path.resolve(root, 'resources/pushd/b/c') ]); trail = shell.pushd('+2'); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [ path.resolve(root, 'resources/pushd'), root, path.resolve(root, 'resources/pushd/b/c'), path.resolve(root, 'resources/pushd/b'), path.resolve(root, 'resources/pushd/a') ]); trail = shell.pushd('+3'); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [ path.resolve(root, 'resources/pushd/b'), path.resolve(root, 'resources/pushd/a'), path.resolve(root, 'resources/pushd'), root, path.resolve(root, 'resources/pushd/b/c') ]); trail = shell.pushd('+4'); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [ path.resolve(root, 'resources/pushd/b/c'), path.resolve(root, 'resources/pushd/b'), path.resolve(root, 'resources/pushd/a'), path.resolve(root, 'resources/pushd'), root ]); // Push stuff around with negative indices trail = shell.pushd('-0'); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [ root, path.resolve(root, 'resources/pushd/b/c'), path.resolve(root, 'resources/pushd/b'), path.resolve(root, 'resources/pushd/a'), path.resolve(root, 'resources/pushd') ]); trail = shell.pushd('-1'); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [ path.resolve(root, 'resources/pushd/a'), path.resolve(root, 'resources/pushd'), root, path.resolve(root, 'resources/pushd/b/c'), path.resolve(root, 'resources/pushd/b') ]); trail = shell.pushd('-2'); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [ root, path.resolve(root, 'resources/pushd/b/c'), path.resolve(root, 'resources/pushd/b'), path.resolve(root, 'resources/pushd/a'), path.resolve(root, 'resources/pushd') ]); trail = shell.pushd('-3'); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [ path.resolve(root, 'resources/pushd/b/c'), path.resolve(root, 'resources/pushd/b'), path.resolve(root, 'resources/pushd/a'), path.resolve(root, 'resources/pushd'), root ]); trail = shell.pushd('-4'); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [ path.resolve(root, 'resources/pushd/b/c'), path.resolve(root, 'resources/pushd/b'), path.resolve(root, 'resources/pushd/a'), path.resolve(root, 'resources/pushd'), root ]); // Push without changing directory or resolving paths reset(); trail = shell.pushd('-n', 'resources/pushd'); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [ root, 'resources/pushd' ]); trail = shell.pushd('-n', 'resources/pushd/a'); assert.equal(shell.error(), null); assert.equal(process.cwd(), trail[0]); assert.deepEqual(trail, [ root, 'resources/pushd/a', 'resources/pushd' ]); // Push invalid directory shell.pushd('does/not/exist'); assert.equal(shell.error(), 'pushd: no such file or directory: ' + path.resolve('.', 'does/not/exist')); assert.equal(process.cwd(), trail[0]); // Push without arguments should swap top two directories when stack length is 2 reset(); trail = shell.pushd('resources/pushd'); assert.equal(shell.error(), null); assert.equal(trail.length, 2); assert.equal(path.relative(root, trail[0]), path.join('resources', 'pushd')); assert.equal(trail[1], root); assert.equal(process.cwd(), trail[0]); trail = shell.pushd(); assert.equal(shell.error(), null); assert.equal(trail.length, 2); assert.equal(trail[0], root); assert.equal(path.relative(root, trail[1]), path.join('resources', 'pushd')); assert.equal(process.cwd(), trail[0]); // Push without arguments should swap top two directories when stack length is > 2 trail = shell.pushd('resources/pushd/a'); assert.equal(shell.error(), null); assert.equal(trail.length, 3); assert.equal(path.relative(root, trail[0]), path.join('resources', 'pushd', 'a')); assert.equal(trail[1], root); assert.equal(path.relative(root, trail[2]), path.join('resources', 'pushd')); assert.equal(process.cwd(), trail[0]); trail = shell.pushd(); assert.equal(shell.error(), null); assert.equal(trail.length, 3); assert.equal(trail[0], root); assert.equal(path.relative(root, trail[1]), path.join('resources', 'pushd', 'a')); assert.equal(path.relative(root, trail[2]), path.join('resources', 'pushd')); assert.equal(process.cwd(), trail[0]); // Push without arguments invalid when stack is empty reset(); shell.pushd(); assert.equal(shell.error(), 'pushd: no other directory'); shell.exit(123); shelljs-0.7.5/test/pwd.js000066400000000000000000000010201300431262200152600ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var path = require('path'); shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); // // Valids // var _pwd = shell.pwd(); assert.equal(shell.error(), null); assert.equal(_pwd.code, 0); assert.ok(!_pwd.stderr); assert.equal(_pwd, path.resolve('.')); shell.cd('tmp'); _pwd = shell.pwd(); assert.equal(_pwd.code, 0); assert.ok(!_pwd.stderr); assert.equal(shell.error(), null); assert.equal(path.basename(_pwd.toString()), 'tmp'); shell.exit(123); shelljs-0.7.5/test/resources/000077500000000000000000000000001300431262200161515ustar00rootroot00000000000000shelljs-0.7.5/test/resources/a.txt000066400000000000000000000001441300431262200171310ustar00rootroot00000000000000This is line one This is line two This is line four . . More content here . . This is line eleven shelljs-0.7.5/test/resources/badlink000077700000000000000000000000001300431262200227422not_existed_fileustar00rootroot00000000000000shelljs-0.7.5/test/resources/cat/000077500000000000000000000000001300431262200167205ustar00rootroot00000000000000shelljs-0.7.5/test/resources/cat/file1000066400000000000000000000000061300431262200176370ustar00rootroot00000000000000test1 shelljs-0.7.5/test/resources/cat/file2000066400000000000000000000000061300431262200176400ustar00rootroot00000000000000test2 shelljs-0.7.5/test/resources/chmod/000077500000000000000000000000001300431262200172435ustar00rootroot00000000000000shelljs-0.7.5/test/resources/chmod/a/000077500000000000000000000000001300431262200174635ustar00rootroot00000000000000shelljs-0.7.5/test/resources/chmod/a/b/000077500000000000000000000000001300431262200177045ustar00rootroot00000000000000shelljs-0.7.5/test/resources/chmod/a/b/c/000077500000000000000000000000001300431262200201265ustar00rootroot00000000000000shelljs-0.7.5/test/resources/chmod/a/b/c/.gitignore000066400000000000000000000000001300431262200221040ustar00rootroot00000000000000shelljs-0.7.5/test/resources/chmod/b/000077500000000000000000000000001300431262200174645ustar00rootroot00000000000000shelljs-0.7.5/test/resources/chmod/b/a/000077500000000000000000000000001300431262200177045ustar00rootroot00000000000000shelljs-0.7.5/test/resources/chmod/b/a/b/000077500000000000000000000000001300431262200201255ustar00rootroot00000000000000shelljs-0.7.5/test/resources/chmod/b/a/b/.gitignore000077500000000000000000000000001300431262200221060ustar00rootroot00000000000000shelljs-0.7.5/test/resources/chmod/c/000077500000000000000000000000001300431262200174655ustar00rootroot00000000000000shelljs-0.7.5/test/resources/chmod/c/a/000077500000000000000000000000001300431262200177055ustar00rootroot00000000000000shelljs-0.7.5/test/resources/chmod/c/a/b/000077500000000000000000000000001300431262200201265ustar00rootroot00000000000000shelljs-0.7.5/test/resources/chmod/c/a/b/.gitignore000066400000000000000000000000001300431262200221040ustar00rootroot00000000000000shelljs-0.7.5/test/resources/chmod/file1000066400000000000000000000000751300431262200201700ustar00rootroot00000000000000this is test file 1 default state should be 0644 (rw-r--r--) shelljs-0.7.5/test/resources/chmod/xdir/000077500000000000000000000000001300431262200202115ustar00rootroot00000000000000shelljs-0.7.5/test/resources/chmod/xdir/deep/000077500000000000000000000000001300431262200211265ustar00rootroot00000000000000shelljs-0.7.5/test/resources/chmod/xdir/deep/file000066400000000000000000000000071300431262200217650ustar00rootroot00000000000000a file shelljs-0.7.5/test/resources/chmod/xdir/file000066400000000000000000000000071300431262200210500ustar00rootroot00000000000000a file shelljs-0.7.5/test/resources/cp-mode-bits/000077500000000000000000000000001300431262200204345ustar00rootroot00000000000000shelljs-0.7.5/test/resources/cp-mode-bits/executable000077500000000000000000000000041300431262200224750ustar00rootroot00000000000000asdfshelljs-0.7.5/test/resources/cp/000077500000000000000000000000001300431262200165535ustar00rootroot00000000000000shelljs-0.7.5/test/resources/cp/a000066400000000000000000000000051300431262200167110ustar00rootroot00000000000000asdf shelljs-0.7.5/test/resources/cp/b000066400000000000000000000000051300431262200167120ustar00rootroot00000000000000asdf shelljs-0.7.5/test/resources/cp/dir_a/000077500000000000000000000000001300431262200176315ustar00rootroot00000000000000shelljs-0.7.5/test/resources/cp/dir_a/z000066400000000000000000000000051300431262200200200ustar00rootroot00000000000000asdf shelljs-0.7.5/test/resources/cp/dir_b/000077500000000000000000000000001300431262200176325ustar00rootroot00000000000000shelljs-0.7.5/test/resources/cp/dir_b/dir_b_a/000077500000000000000000000000001300431262200212115ustar00rootroot00000000000000shelljs-0.7.5/test/resources/cp/dir_b/dir_b_a/dir_b_a_a/000077500000000000000000000000001300431262200230705ustar00rootroot00000000000000shelljs-0.7.5/test/resources/cp/dir_b/dir_b_a/dir_b_a_a/z000066400000000000000000000000051300431262200232570ustar00rootroot00000000000000asdf shelljs-0.7.5/test/resources/cp/fakeLinks/000077500000000000000000000000001300431262200204625ustar00rootroot00000000000000shelljs-0.7.5/test/resources/cp/fakeLinks/file.txt000066400000000000000000000000171300431262200221400ustar00rootroot00000000000000This is a file shelljs-0.7.5/test/resources/cp/fakeLinks/sym.lnk000066400000000000000000000000231300431262200217730ustar00rootroot00000000000000This is not a link shelljs-0.7.5/test/resources/cp/links/000077500000000000000000000000001300431262200176735ustar00rootroot00000000000000shelljs-0.7.5/test/resources/cp/links/file.txt000066400000000000000000000000171300431262200213510ustar00rootroot00000000000000This is a file shelljs-0.7.5/test/resources/cp/links/sym.lnk000077700000000000000000000000001300431262200226642file.txtustar00rootroot00000000000000shelljs-0.7.5/test/resources/cp/symFolder000077700000000000000000000000001300431262200215572links/ustar00rootroot00000000000000shelljs-0.7.5/test/resources/exec/000077500000000000000000000000001300431262200170755ustar00rootroot00000000000000shelljs-0.7.5/test/resources/exec/slow.js000066400000000000000000000001501300431262200204130ustar00rootroot00000000000000#!/usr/bin/env node setTimeout(function() { console.log('slow'); }, parseInt(process.argv[2], 10)); shelljs-0.7.5/test/resources/external/000077500000000000000000000000001300431262200177735ustar00rootroot00000000000000shelljs-0.7.5/test/resources/external/node_script.js000077500000000000000000000000421300431262200226410ustar00rootroot00000000000000console.log('node_script_1234'); shelljs-0.7.5/test/resources/file1000066400000000000000000000000051300431262200170670ustar00rootroot00000000000000test1shelljs-0.7.5/test/resources/file1.js000066400000000000000000000000051300431262200175020ustar00rootroot00000000000000test shelljs-0.7.5/test/resources/file1.txt000066400000000000000000000000061300431262200177060ustar00rootroot00000000000000test1 shelljs-0.7.5/test/resources/file2000066400000000000000000000000051300431262200170700ustar00rootroot00000000000000test2shelljs-0.7.5/test/resources/file2.js000066400000000000000000000000051300431262200175030ustar00rootroot00000000000000test shelljs-0.7.5/test/resources/file2.txt000066400000000000000000000000061300431262200177070ustar00rootroot00000000000000test2 shelljs-0.7.5/test/resources/find/000077500000000000000000000000001300431262200170715ustar00rootroot00000000000000shelljs-0.7.5/test/resources/find/.hidden000066400000000000000000000000051300431262200203200ustar00rootroot00000000000000asdf shelljs-0.7.5/test/resources/find/a000066400000000000000000000000051300431262200172270ustar00rootroot00000000000000asdf shelljs-0.7.5/test/resources/find/b000066400000000000000000000000051300431262200172300ustar00rootroot00000000000000asdf shelljs-0.7.5/test/resources/find/broken_link000077700000000000000000000000001300431262200237442non_existentustar00rootroot00000000000000shelljs-0.7.5/test/resources/find/dir1/000077500000000000000000000000001300431262200177305ustar00rootroot00000000000000shelljs-0.7.5/test/resources/find/dir1/a_dir1000066400000000000000000000000051300431262200210050ustar00rootroot00000000000000asdf shelljs-0.7.5/test/resources/find/dir1/dir11/000077500000000000000000000000001300431262200206505ustar00rootroot00000000000000shelljs-0.7.5/test/resources/find/dir1/dir11/a_dir11000066400000000000000000000000051300431262200220060ustar00rootroot00000000000000asdf shelljs-0.7.5/test/resources/find/dir2/000077500000000000000000000000001300431262200177315ustar00rootroot00000000000000shelljs-0.7.5/test/resources/find/dir2/a_dir1000066400000000000000000000000051300431262200210060ustar00rootroot00000000000000asdf shelljs-0.7.5/test/resources/grep/000077500000000000000000000000001300431262200171065ustar00rootroot00000000000000shelljs-0.7.5/test/resources/grep/file000066400000000000000000000001151300431262200177450ustar00rootroot00000000000000alphaaaaaaabeta howareyou alphbeta this line ends in.js lllllllllllllllll.js shelljs-0.7.5/test/resources/head/000077500000000000000000000000001300431262200170525ustar00rootroot00000000000000shelljs-0.7.5/test/resources/head/file1.txt000066400000000000000000000006711300431262200206170ustar00rootroot00000000000000file1 1 file1 2 file1 3 file1 4 file1 5 file1 6 file1 7 file1 8 file1 9 file1 10 file1 11 file1 12 file1 13 file1 14 file1 15 file1 16 file1 17 file1 18 file1 19 file1 20 file1 21 file1 22 file1 23 file1 24 file1 25 file1 26 file1 27 file1 28 file1 29 file1 30 file1 31 file1 32 file1 33 file1 34 file1 35 file1 36 file1 37 file1 38 file1 39 file1 40 file1 41 file1 42 file1 43 file1 44 file1 45 file1 46 file1 47 file1 48 file1 49 file1 50 shelljs-0.7.5/test/resources/head/file2.txt000066400000000000000000000006711300431262200206200ustar00rootroot00000000000000file2 1 file2 2 file2 3 file2 4 file2 5 file2 6 file2 7 file2 8 file2 9 file2 10 file2 11 file2 12 file2 13 file2 14 file2 15 file2 16 file2 17 file2 18 file2 19 file2 20 file2 21 file2 22 file2 23 file2 24 file2 25 file2 26 file2 27 file2 28 file2 29 file2 30 file2 31 file2 32 file2 33 file2 34 file2 35 file2 36 file2 37 file2 38 file2 39 file2 40 file2 41 file2 42 file2 43 file2 44 file2 45 file2 46 file2 47 file2 48 file2 49 file2 50 shelljs-0.7.5/test/resources/head/shortfile1000066400000000000000000000000071300431262200210520ustar00rootroot00000000000000short1 shelljs-0.7.5/test/resources/head/shortfile2000066400000000000000000000000071300431262200210530ustar00rootroot00000000000000short2 shelljs-0.7.5/test/resources/issue44/000077500000000000000000000000001300431262200174515ustar00rootroot00000000000000shelljs-0.7.5/test/resources/issue44/main.js000066400000000000000000000000031300431262200207240ustar00rootroot00000000000000123shelljs-0.7.5/test/resources/link000077700000000000000000000000001300431262200177472file1ustar00rootroot00000000000000shelljs-0.7.5/test/resources/ls/000077500000000000000000000000001300431262200165675ustar00rootroot00000000000000shelljs-0.7.5/test/resources/ls/.hidden_dir/000077500000000000000000000000001300431262200207365ustar00rootroot00000000000000shelljs-0.7.5/test/resources/ls/.hidden_dir/nada000066400000000000000000000000051300431262200215570ustar00rootroot00000000000000asdf shelljs-0.7.5/test/resources/ls/.hidden_file000066400000000000000000000000051300431262200210150ustar00rootroot00000000000000asdf shelljs-0.7.5/test/resources/ls/a_dir/000077500000000000000000000000001300431262200176455ustar00rootroot00000000000000shelljs-0.7.5/test/resources/ls/a_dir/.hidden_dir/000077500000000000000000000000001300431262200220145ustar00rootroot00000000000000shelljs-0.7.5/test/resources/ls/a_dir/.hidden_dir/nada000066400000000000000000000000041300431262200226340ustar00rootroot00000000000000nadashelljs-0.7.5/test/resources/ls/a_dir/b_dir/000077500000000000000000000000001300431262200207245ustar00rootroot00000000000000shelljs-0.7.5/test/resources/ls/a_dir/b_dir/z000066400000000000000000000000051300431262200211130ustar00rootroot00000000000000asdf shelljs-0.7.5/test/resources/ls/a_dir/nada000066400000000000000000000000051300431262200204660ustar00rootroot00000000000000asdf shelljs-0.7.5/test/resources/ls/file1000066400000000000000000000000051300431262200175050ustar00rootroot00000000000000test shelljs-0.7.5/test/resources/ls/file1.js000066400000000000000000000000051300431262200201200ustar00rootroot00000000000000test shelljs-0.7.5/test/resources/ls/file2000066400000000000000000000000051300431262200175060ustar00rootroot00000000000000test shelljs-0.7.5/test/resources/ls/file2.js000066400000000000000000000000051300431262200201210ustar00rootroot00000000000000test shelljs-0.7.5/test/resources/ls/filename(with)[chars$]^that.must+be-escaped000066400000000000000000000000051300431262200266510ustar00rootroot00000000000000asdf shelljs-0.7.5/test/resources/pushd/000077500000000000000000000000001300431262200172745ustar00rootroot00000000000000shelljs-0.7.5/test/resources/pushd/a/000077500000000000000000000000001300431262200175145ustar00rootroot00000000000000shelljs-0.7.5/test/resources/pushd/a/dummy000066400000000000000000000000031300431262200205630ustar00rootroot00000000000000mehshelljs-0.7.5/test/resources/pushd/b/000077500000000000000000000000001300431262200175155ustar00rootroot00000000000000shelljs-0.7.5/test/resources/pushd/b/c/000077500000000000000000000000001300431262200177375ustar00rootroot00000000000000shelljs-0.7.5/test/resources/pushd/b/c/dummy000066400000000000000000000000031300431262200210060ustar00rootroot00000000000000mehshelljs-0.7.5/test/resources/rm/000077500000000000000000000000001300431262200165675ustar00rootroot00000000000000shelljs-0.7.5/test/resources/rm/a_dir/000077500000000000000000000000001300431262200176455ustar00rootroot00000000000000shelljs-0.7.5/test/resources/rm/a_dir/a_file000066400000000000000000000000051300431262200210020ustar00rootroot00000000000000asdf shelljs-0.7.5/test/resources/rm/fake.lnk000077700000000000000000000000001300431262200215722missingustar00rootroot00000000000000shelljs-0.7.5/test/resources/rm/link_to_a_dir000077700000000000000000000000001300431262200223032a_dirustar00rootroot00000000000000shelljs-0.7.5/test/resources/shjs/000077500000000000000000000000001300431262200171205ustar00rootroot00000000000000shelljs-0.7.5/test/resources/shjs/a-file.js000066400000000000000000000000451300431262200206120ustar00rootroot00000000000000console.log('OK!'); process.exit(0); shelljs-0.7.5/test/resources/shjs/coffeescript.coffee000066400000000000000000000000521300431262200227420ustar00rootroot00000000000000msg = 'CoffeeScript: OK!' console.log msg shelljs-0.7.5/test/resources/shjs/exit-0.js000066400000000000000000000000211300431262200205550ustar00rootroot00000000000000process.exit(0); shelljs-0.7.5/test/resources/shjs/exit-codes.js000066400000000000000000000000221300431262200215140ustar00rootroot00000000000000process.exit(42); shelljs-0.7.5/test/resources/shjs/stdout-stderr.js000066400000000000000000000000721300431262200223000ustar00rootroot00000000000000console.log('stdout: OK!'); console.error('stderr: OK!'); shelljs-0.7.5/test/resources/sort/000077500000000000000000000000001300431262200171405ustar00rootroot00000000000000shelljs-0.7.5/test/resources/sort/file1000066400000000000000000000001421300431262200200600ustar00rootroot0000000000000022 symbolic 46 integers melt admiral aardvark scanner Dynamite Witness 12345 blackwater 5 numbers shelljs-0.7.5/test/resources/sort/file2000066400000000000000000000001421300431262200200610ustar00rootroot00000000000000admiral scanner 5 numbers Witness 46 integers 12345 Dynamite blackwater aardvark 22 symbolic melt shelljs-0.7.5/test/resources/sort/sorted000066400000000000000000000001421300431262200203600ustar00rootroot0000000000000012345 22 46 integers 5 numbers aardvark admiral blackwater Dynamite melt scanner symbolic Witness shelljs-0.7.5/test/resources/sort/sortedDashN000066400000000000000000000001421300431262200212760ustar00rootroot00000000000000aardvark admiral blackwater Dynamite melt scanner symbolic Witness 5 numbers 22 46 integers 12345 shelljs-0.7.5/test/resources/uniq/000077500000000000000000000000001300431262200171255ustar00rootroot00000000000000shelljs-0.7.5/test/resources/uniq/file1000066400000000000000000000000201300431262200200400ustar00rootroot00000000000000foo bar bar baz shelljs-0.7.5/test/resources/uniq/file1c000066400000000000000000000000441300431262200202110ustar00rootroot00000000000000 1 foo 2 bar 1 baz shelljs-0.7.5/test/resources/uniq/file1d000066400000000000000000000000041300431262200202060ustar00rootroot00000000000000bar shelljs-0.7.5/test/resources/uniq/file1t000066400000000000000000000000141300431262200202270ustar00rootroot00000000000000foo bar baz shelljs-0.7.5/test/resources/uniq/file1u000066400000000000000000000000141300431262200202300ustar00rootroot00000000000000foo bar baz shelljs-0.7.5/test/resources/uniq/file2000066400000000000000000000000201300431262200200410ustar00rootroot00000000000000foo bar Bar baz shelljs-0.7.5/test/resources/uniq/file2u000066400000000000000000000000141300431262200202310ustar00rootroot00000000000000foo bar baz shelljs-0.7.5/test/resources/uniq/file3000066400000000000000000000000141300431262200200450ustar00rootroot00000000000000foo bar baz shelljs-0.7.5/test/resources/uniq/pipe000066400000000000000000000003101300431262200177770ustar00rootroot00000000000000bar foo foo baz foo foo bar foo baz baz foo baz baz baz bar baz bar bar baz bar baz foo baz foo baz foo bar baz bar bar bar foo foo foo foo baz foo baz foo foo bar foo foo bar foo foo baz foo foo foo shelljs-0.7.5/test/resources/uniq/pipeSorted000066400000000000000000000000441300431262200211640ustar00rootroot00000000000000 12 bar 15 baz 23 foo shelljs-0.7.5/test/rm.js000066400000000000000000000205701300431262200151170ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var path = require('path'); var fs = require('fs'); shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); // // Invalids // var contents; var result; result = shell.rm(); assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(result.stderr, 'rm: no paths given'); result = shell.rm('asdfasdf'); // file does not exist assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(result.stderr, 'rm: no such file or directory: asdfasdf'); result = shell.rm('-f'); // no file assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(result.stderr, 'rm: no paths given'); result = shell.rm('-@', 'resources/file1'); // invalid option assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(fs.existsSync('resources/file1'), true); assert.equal(result.stderr, 'rm: option not recognized: @'); // // Valids // // file does not exist, but -f specified result = shell.rm('-f', 'asdfasdf'); assert.equal(shell.error(), null); assert.equal(result.code, 0); // directory does not exist, but -fr specified result = shell.rm('-fr', 'fake_dir/'); assert.equal(shell.error(), null); assert.equal(result.code, 0); // directory does not exist, but *only -f* specified result = shell.rm('-f', 'fake_dir/'); assert.equal(shell.error(), null); assert.equal(result.code, 0); // file (in fake dir) does not exist, but -f specified result = shell.rm('-f', 'fake_dir/asdfasdf'); assert.equal(shell.error(), null); assert.equal(result.code, 0); // dir (in fake dir) does not exist, but -fr specified result = shell.rm('-fr', 'fake_dir/sub/'); assert.equal(shell.error(), null); assert.equal(result.code, 0); // simple rm shell.cp('-f', 'resources/file1', 'tmp/file1'); assert.equal(fs.existsSync('tmp/file1'), true); result = shell.rm('tmp/file1'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(fs.existsSync('tmp/file1'), false); // recursive dir removal - small-caps '-r' shell.mkdir('-p', 'tmp/a/b/c'); assert.equal(fs.existsSync('tmp/a/b/c'), true); result = shell.rm('-rf', 'tmp/a'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(fs.existsSync('tmp/a'), false); // recursive dir removal - capital '-R' shell.mkdir('-p', 'tmp/a/b/c'); assert.equal(fs.existsSync('tmp/a/b/c'), true); result = shell.rm('-Rf', 'tmp/a'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(fs.existsSync('tmp/a'), false); // recursive dir removal - absolute path shell.mkdir('-p', 'tmp/a/b/c'); assert.equal(fs.existsSync('tmp/a/b/c'), true); result = shell.rm('-Rf', path.resolve('./tmp/a')); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(fs.existsSync('tmp/a'), false); // wildcard shell.cp('-f', 'resources/file*', 'tmp'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(fs.existsSync('tmp/file1'), true); assert.equal(fs.existsSync('tmp/file2'), true); assert.equal(fs.existsSync('tmp/file1.js'), true); assert.equal(fs.existsSync('tmp/file2.js'), true); result = shell.rm('tmp/file*'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(fs.existsSync('tmp/file1'), false); assert.equal(fs.existsSync('tmp/file2'), false); assert.equal(fs.existsSync('tmp/file1.js'), false); assert.equal(fs.existsSync('tmp/file2.js'), false); // recursive dir removal shell.mkdir('-p', 'tmp/a/b/c'); shell.mkdir('-p', 'tmp/b'); shell.mkdir('-p', 'tmp/c'); shell.mkdir('-p', 'tmp/.hidden'); assert.equal(fs.existsSync('tmp/a/b/c'), true); assert.equal(fs.existsSync('tmp/b'), true); assert.equal(fs.existsSync('tmp/c'), true); assert.equal(fs.existsSync('tmp/.hidden'), true); result = shell.rm('-rf', 'tmp/*'); assert.equal(shell.error(), null); assert.equal(result.code, 0); contents = fs.readdirSync('tmp'); assert.equal(contents.length, 1); assert.equal(contents[0], '.hidden'); // shouldn't remove hiddden if no .* given // recursive dir removal shell.mkdir('-p', 'tmp/a/b/c'); shell.mkdir('-p', 'tmp/b'); shell.mkdir('-p', 'tmp/c'); shell.mkdir('-p', 'tmp/.hidden'); assert.equal(fs.existsSync('tmp/a/b/c'), true); assert.equal(fs.existsSync('tmp/b'), true); assert.equal(fs.existsSync('tmp/c'), true); assert.equal(fs.existsSync('tmp/.hidden'), true); result = shell.rm('-rf', 'tmp/*', 'tmp/.*'); assert.equal(shell.error(), null); assert.equal(result.code, 0); contents = fs.readdirSync('tmp'); assert.equal(contents.length, 0); // recursive dir removal - array-syntax shell.mkdir('-p', 'tmp/a/b/c'); shell.mkdir('-p', 'tmp/b'); shell.mkdir('-p', 'tmp/c'); shell.mkdir('-p', 'tmp/.hidden'); assert.equal(fs.existsSync('tmp/a/b/c'), true); assert.equal(fs.existsSync('tmp/b'), true); assert.equal(fs.existsSync('tmp/c'), true); assert.equal(fs.existsSync('tmp/.hidden'), true); result = shell.rm('-rf', ['tmp/*', 'tmp/.*']); assert.equal(shell.error(), null); assert.equal(result.code, 0); contents = fs.readdirSync('tmp'); assert.equal(contents.length, 0); // removal of a read-only file (unforced) shell.mkdir('-p', 'tmp/readonly'); shell.ShellString('asdf').to('tmp/readonly/file1'); fs.chmodSync('tmp/readonly/file1', '0444'); // -r--r--r-- result = shell.rm('tmp/readonly/file1'); assert.equal(fs.existsSync('tmp/readonly/file1'), true); // bash's rm always asks before removing read-only files // here we just assume "no" // removal of a read-only file (forced) shell.mkdir('-p', 'tmp/readonly'); shell.ShellString('asdf').to('tmp/readonly/file2'); fs.chmodSync('tmp/readonly/file2', '0444'); // -r--r--r-- result = shell.rm('-f', 'tmp/readonly/file2'); assert.equal(fs.existsSync('tmp/readonly/file2'), false); // removal of a tree containing read-only files (unforced) shell.mkdir('-p', 'tmp/tree2'); shell.ShellString('asdf').to('tmp/tree2/file1'); shell.ShellString('asdf').to('tmp/tree2/file2'); fs.chmodSync('tmp/tree2/file1', '0444'); // -r--r--r-- result = shell.rm('-r', 'tmp/tree2'); assert.equal(fs.existsSync('tmp/tree2/file1'), true); assert.equal(fs.existsSync('tmp/tree2/file2'), false); // removal of a tree containing read-only files (forced) shell.mkdir('-p', 'tmp/tree'); shell.ShellString('asdf').to('tmp/tree/file1'); shell.ShellString('asdf').to('tmp/tree/file2'); fs.chmodSync('tmp/tree/file1', '0444'); // -r--r--r-- result = shell.rm('-rf', 'tmp/tree'); assert.equal(fs.existsSync('tmp/tree'), false); // removal of a sub-tree containing read-only and hidden files - rm('dir/*') shell.mkdir('-p', 'tmp/tree3'); shell.mkdir('-p', 'tmp/tree3/subtree'); shell.mkdir('-p', 'tmp/tree3/.hidden'); shell.ShellString('asdf').to('tmp/tree3/subtree/file'); shell.ShellString('asdf').to('tmp/tree3/.hidden/file'); shell.ShellString('asdf').to('tmp/tree3/file'); fs.chmodSync('tmp/tree3/file', '0444'); // -r--r--r-- fs.chmodSync('tmp/tree3/subtree/file', '0444'); // -r--r--r-- fs.chmodSync('tmp/tree3/.hidden/file', '0444'); // -r--r--r-- result = shell.rm('-rf', 'tmp/tree3/*', 'tmp/tree3/.*'); // erase dir contents assert.equal(shell.ls('tmp/tree3').length, 0); // removal of a sub-tree containing read-only and hidden files - rm('dir') shell.mkdir('-p', 'tmp/tree4'); shell.mkdir('-p', 'tmp/tree4/subtree'); shell.mkdir('-p', 'tmp/tree4/.hidden'); shell.ShellString('asdf').to('tmp/tree4/subtree/file'); shell.ShellString('asdf').to('tmp/tree4/.hidden/file'); shell.ShellString('asdf').to('tmp/tree4/file'); fs.chmodSync('tmp/tree4/file', '0444'); // -r--r--r-- fs.chmodSync('tmp/tree4/subtree/file', '0444'); // -r--r--r-- fs.chmodSync('tmp/tree4/.hidden/file', '0444'); // -r--r--r-- result = shell.rm('-rf', 'tmp/tree4'); // erase dir contents assert.equal(fs.existsSync('tmp/tree4'), false); // remove symbolic link to a dir result = shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); shell.cp('-R', 'resources/rm', 'tmp'); result = shell.rm('-f', 'tmp/rm/link_to_a_dir'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(fs.existsSync('tmp/rm/link_to_a_dir'), false); assert.equal(fs.existsSync('tmp/rm/a_dir'), true); // remove broken symbolic link if (process.platform !== 'win32') { result = shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); shell.cp('-R', 'resources/rm', 'tmp'); assert.ok(shell.test('-L', 'tmp/rm/fake.lnk')); result = shell.rm('tmp/rm/fake.lnk'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.ok(!shell.test('-L', 'tmp/rm/fake.lnk')); assert.equal(fs.existsSync('tmp/rm/fake.lnk'), false); } shell.exit(123); shelljs-0.7.5/test/sed.js000066400000000000000000000113131300431262200152470ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var fs = require('fs'); shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); var result; // // Invalids // result = shell.sed(); assert.ok(shell.error()); assert.equal(result.code, 1); assert.ok(result.stderr); result = shell.sed(/asdf/g); // too few args assert.ok(shell.error()); assert.equal(result.code, 1); result = shell.sed(/asdf/g, 'nada'); // too few args assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(fs.existsSync('asdfasdf'), false); // sanity check result = shell.sed(/asdf/g, 'nada', 'asdfasdf'); // no such file assert.ok(shell.error()); assert.equal(result.code, 2); assert.equal(result.stderr, 'sed: no such file or directory: asdfasdf'); // if at least one file is missing, this should be an error shell.cp('-f', 'resources/file1', 'tmp/file1'); assert.equal(fs.existsSync('asdfasdf'), false); // sanity check assert.equal(fs.existsSync('tmp/file1'), true); // sanity check result = shell.sed(/asdf/g, 'nada', 'tmp/file1', 'asdfasdf'); assert.ok(shell.error()); assert.equal(result.code, 2); assert.equal(result.stderr, 'sed: no such file or directory: asdfasdf'); // // Valids // shell.cp('-f', 'resources/file1', 'tmp/file1'); result = shell.sed('test1', 'hello', 'tmp/file1'); // search string assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.toString(), 'hello'); result = shell.sed(/test1/, 'hello', 'tmp/file1'); // search regex assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.toString(), 'hello'); result = shell.sed(/test1/, 1234, 'tmp/file1'); // numeric replacement assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.toString(), '1234'); var replaceFun = function (match) { return match.toUpperCase() + match; }; result = shell.sed(/test1/, replaceFun, 'tmp/file1'); // replacement function assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.toString(), 'TEST1test1'); result = shell.sed('-i', /test1/, 'hello', 'tmp/file1'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.toString(), 'hello'); assert.equal(shell.cat('tmp/file1').toString(), 'hello'); // make sure * in regex is not globbed result = shell.sed(/alpha*beta/, 'hello', 'resources/grep/file'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.toString(), 'hello\nhowareyou\nhello\nthis line ends in.js\nlllllllllllllllll.js\n'); // make sure * in string-regex is not globbed result = shell.sed('alpha*beta', 'hello', 'resources/grep/file'); assert.ok(!shell.error()); assert.equal(result.code, 0); assert.equal(result.toString(), 'hello\nhowareyou\nhello\nthis line ends in.js\nlllllllllllllllll.js\n'); // make sure * in regex is not globbed result = shell.sed(/l*\.js/, '', 'resources/grep/file'); assert.ok(!shell.error()); assert.equal(result.code, 0); assert.equal(result.toString(), 'alphaaaaaaabeta\nhowareyou\nalphbeta\nthis line ends in\n\n'); // make sure * in string-regex is not globbed result = shell.sed('l*\\.js', '', 'resources/grep/file'); assert.ok(!shell.error()); assert.equal(result.code, 0); assert.equal(result.toString(), 'alphaaaaaaabeta\nhowareyou\nalphbeta\nthis line ends in\n\n'); shell.cp('-f', 'resources/file1', 'tmp/file1'); shell.cp('-f', 'resources/file2', 'tmp/file2'); // multiple file names result = shell.sed('test', 'hello', 'tmp/file1', 'tmp/file2'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.toString(), 'hello1\nhello2'); // array of file names (and try it out with a simple regex) result = shell.sed(/t.*st/, 'hello', ['tmp/file1', 'tmp/file2']); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.toString(), 'hello1\nhello2'); // multiple file names, with in-place-replacement result = shell.sed('-i', 'test', 'hello', ['tmp/file1', 'tmp/file2']); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.toString(), 'hello1\nhello2'); assert.equal(shell.cat('tmp/file1').toString(), 'hello1'); assert.equal(shell.cat('tmp/file2').toString(), 'hello2'); // glob file names, with in-place-replacement shell.cp('resources/file*.txt', 'tmp/'); assert.equal(shell.cat('tmp/file1.txt').toString(), 'test1\n'); assert.equal(shell.cat('tmp/file2.txt').toString(), 'test2\n'); result = shell.sed('-i', 'test', 'hello', 'tmp/file*.txt'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result.toString(), 'hello1\n\nhello2\n'); // TODO: fix sed's behavior assert.equal(shell.cat('tmp/file1.txt').toString(), 'hello1\n'); assert.equal(shell.cat('tmp/file2.txt').toString(), 'hello2\n'); shell.exit(123); shelljs-0.7.5/test/set.js000066400000000000000000000050761300431262200153000ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var oldConfigSilent = shell.config.silent; shell.config.silent = true; shell.rm('-rf', 'tmp'); // // Valids // var result; // initial values assert.strictEqual(oldConfigSilent, false); assert.strictEqual(shell.config.verbose, false); assert.strictEqual(shell.config.fatal, false); assert.strictEqual(shell.config.noglob, false); shell.cp('-R', 'resources/', 'tmp'); // default behavior result = shell.exec(JSON.stringify(process.execPath) + ' -e "require(\'../global\'); ls(\'file_doesnt_exist\'); echo(1234);"'); assert.equal(result.code, 0); assert.equal(result.stdout, '1234\n'); assert.equal(result.stderr, 'ls: no such file or directory: file_doesnt_exist\n'); // set -e result = shell.exec(JSON.stringify(process.execPath) + ' -e "require(\'../global\'); set(\'-e\'); ls(\'file_doesnt_exist\'); echo(1234);"'); var nodeVersion = process.versions.node.split('.').map(function (str) { return parseInt(str, 10); }); var uncaughtErrorExitCode = (nodeVersion[0] === 0 && nodeVersion[1] < 11) ? 8 : 1; assert.equal(result.code, uncaughtErrorExitCode); assert.equal(result.stdout, ''); assert(result.stderr.indexOf('Error: ls: no such file or directory: file_doesnt_exist') >= 0); // set -v result = shell.exec(JSON.stringify(process.execPath) + ' -e "require(\'../global\'); set(\'-v\'); ls(\'file_doesnt_exist\'); echo(1234);"'); assert.equal(result.code, 0); assert.equal(result.stdout, '1234\n'); assert.equal(result.stderr, 'ls file_doesnt_exist\nls: no such file or directory: file_doesnt_exist\necho 1234\n'); // set -ev result = shell.exec(JSON.stringify(process.execPath) + ' -e "require(\'../global\'); set(\'-ev\'); ls(\'file_doesnt_exist\'); echo(1234);"'); assert.equal(result.code, uncaughtErrorExitCode); assert.equal(result.stdout, ''); assert(result.stderr.indexOf('Error: ls: no such file or directory: file_doesnt_exist') >= 0); assert(result.stderr.indexOf('ls file_doesnt_exist\n') >= 0); assert.equal(result.stderr.indexOf('echo 1234\n'), -1); // set -e, set +e result = shell.exec(JSON.stringify(process.execPath) + ' -e "require(\'../global\'); set(\'-e\'); set(\'+e\'); ls(\'file_doesnt_exist\'); echo(1234);"'); assert.equal(result.code, 0); assert.equal(result.stdout, '1234\n'); assert.equal(result.stderr, 'ls: no such file or directory: file_doesnt_exist\n'); // set -f shell.set('-f'); // disable globbing shell.rm('tmp/*.txt'); assert.ok(shell.error()); // file '*.txt' doesn't exist, so rm() fails shell.set('+f'); shell.rm('tmp/*.txt'); assert.ok(!shell.error()); // globbing works, so rm succeeds shell.exit(123); shelljs-0.7.5/test/shjs.js000066400000000000000000000020631300431262200154450ustar00rootroot00000000000000var shell = require('..'); var path = require('path'); var assert = require('assert'); function runScript(name) { // prefix with 'node ' for Windows, don't prefix for OSX/Linux var cmd = (process.platform === 'win32' ? JSON.stringify(process.execPath) + ' ' : '') + path.resolve(__dirname, '../bin/shjs'); var script = path.resolve(__dirname, 'resources', 'shjs', name); return shell.exec(cmd + ' ' + script, { silent: true }); } // Exit Codes assert.equal(runScript('exit-codes.js').code, 42, 'exit code works'); assert.equal(runScript('exit-0.js').code, 0, 'exiting 0 works'); // Stdout/Stderr var stdioRet = runScript('stdout-stderr.js'); assert.equal(stdioRet.stdout, 'stdout: OK!\n', 'stdout works'); assert.equal(stdioRet.stderr, 'stderr: OK!\n', 'stderr works'); // CoffeeScript assert.equal(runScript('coffeescript.coffee').stdout, 'CoffeeScript: OK!\n'); // Extension detection var extDetectRet = runScript('a-file'); assert.equal(extDetectRet.code, 0, 'error code works'); assert.equal(extDetectRet.stdout, 'OK!\n', 'stdout works'); shell.exit(123); shelljs-0.7.5/test/sort.js000066400000000000000000000051451300431262200154710ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var fs = require('fs'); shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); var result; var doubleSorted = shell.cat('resources/sort/sorted') .trimRight() .split('\n') .reduce(function (prev, cur) { return prev.concat([cur, cur]); }, []) .join('\n') + '\n'; // // Invalids // result = shell.sort(); assert.ok(shell.error()); assert.ok(result.code); assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check result = shell.sort('/adsfasdf'); // file does not exist assert.ok(shell.error()); assert.ok(result.code); // // Valids // // simple result = shell.sort('resources/sort/file1'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result + '', shell.cat('resources/sort/sorted')); // simple result = shell.sort('resources/sort/file2'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result + '', shell.cat('resources/sort/sorted')); // multiple files result = shell.sort('resources/sort/file2', 'resources/sort/file1'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result + '', doubleSorted); // multiple files, array syntax result = shell.sort(['resources/sort/file2', 'resources/sort/file1']); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result + '', doubleSorted); // Globbed file result = shell.sort('resources/sort/file?'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result + '', doubleSorted); // With '-n' option result = shell.sort('-n', 'resources/sort/file2'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result + '', shell.cat('resources/sort/sortedDashN')); // With '-r' option result = shell.sort('-r', 'resources/sort/file2'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result + '', shell.cat('resources/sort/sorted') .trimRight() .split('\n') .reverse() .join('\n') + '\n'); // With '-rn' option result = shell.sort('-rn', 'resources/sort/file2'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result + '', shell.cat('resources/sort/sortedDashN') .trimRight() .split('\n') .reverse() .join('\n') + '\n'); shell.exit(123); shelljs-0.7.5/test/tail.js000066400000000000000000000075761300431262200154450ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var fs = require('fs'); shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); var result; // // Invalids // result = shell.tail(); assert.ok(shell.error()); assert.equal(result.code, 1); assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check result = shell.tail('/adsfasdf'); // file does not exist assert.ok(shell.error()); assert.equal(result.code, 1); // // Valids // var bottomOfFile1 = ['file1 50', 'file1 49', 'file1 48', 'file1 47', 'file1 46', 'file1 45', 'file1 44', 'file1 43', 'file1 42', 'file1 41', 'file1 40', 'file1 39', 'file1 38', 'file1 37', 'file1 36', 'file1 35', 'file1 34', 'file1 33', 'file1 32', 'file1 31']; var bottomOfFile2 = ['file2 50', 'file2 49', 'file2 48', 'file2 47', 'file2 46', 'file2 45', 'file2 44', 'file2 43', 'file2 42', 'file2 41', 'file2 40', 'file2 39', 'file2 38', 'file2 37', 'file2 36', 'file2 35', 'file2 34', 'file2 33', 'file2 32', 'file2 31']; // simple result = shell.tail('resources/head/file1.txt'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result, bottomOfFile1.slice(0, 10).reverse().join('\n') + '\n'); // multiple files result = shell.tail('resources/head/file2.txt', 'resources/head/file1.txt'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result, bottomOfFile2.slice(0, 10).reverse().concat( bottomOfFile1.slice(0, 10).reverse() ).join('\n') + '\n'); // multiple files, array syntax result = shell.tail(['resources/head/file2.txt', 'resources/head/file1.txt']); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result, bottomOfFile2.slice(0, 10).reverse().concat( bottomOfFile1.slice(0, 10).reverse() ).join('\n') + '\n'); // reading more lines than are in the file (no trailing newline) result = shell.tail('resources/file2', 'resources/file1'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result, 'test2\ntest1'); // these files only have one line (no \n) // reading more lines than are in the file (with trailing newline) result = shell.tail('resources/head/shortfile2', 'resources/head/shortfile1'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result, 'short2\nshort1\n'); // these files only have one line (with \n) // Globbed file result = shell.tail('resources/head/file?.txt'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result, bottomOfFile1.slice(0, 10).reverse().concat( bottomOfFile2.slice(0, 10).reverse() ).join('\n') + '\n'); // With `'-n' ` option result = shell.tail('-n', 4, 'resources/head/file2.txt', 'resources/head/file1.txt'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result, bottomOfFile2.slice(0, 4).reverse().concat( bottomOfFile1.slice(0, 4).reverse() ).join('\n') + '\n'); // With `{'-n': }` option result = shell.tail({ '-n': 4 }, 'resources/head/file2.txt', 'resources/head/file1.txt'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result, bottomOfFile2.slice(0, 4).reverse().concat( bottomOfFile1.slice(0, 4).reverse() ).join('\n') + '\n'); // negative values are the same as positive values result = shell.tail('-n', -4, 'resources/head/file2.txt', 'resources/head/file1.txt'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result, bottomOfFile2.slice(0, 4).reverse().concat( bottomOfFile1.slice(0, 4).reverse() ).join('\n') + '\n'); shell.exit(123); shelljs-0.7.5/test/tempdir.js000066400000000000000000000004501300431262200161400ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var fs = require('fs'); shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); // // Valids // var tmp = shell.tempdir(); assert.equal(shell.error(), null); assert.equal(fs.existsSync(tmp), true); shell.exit(123); shelljs-0.7.5/test/test.js000066400000000000000000000043661300431262200154650ustar00rootroot00000000000000var shell = require('..'); var common = require('../src/common'); var assert = require('assert'); shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); // // Invalids // var result; result = shell.test(); // no expression given assert.ok(shell.error()); result = shell.test('asdf'); // bad expression assert.ok(shell.error()); result = shell.test('f', 'resources/file1'); // bad expression assert.ok(shell.error()); result = shell.test('-f'); // no file assert.ok(shell.error()); // // Valids // // exists result = shell.test('-e', 'resources/file1'); assert.equal(shell.error(), null); assert.equal(result, true);// true result = shell.test('-e', 'resources/404'); assert.equal(shell.error(), null); assert.equal(result, false); // directory result = shell.test('-d', 'resources'); assert.equal(shell.error(), null); assert.equal(result, true);// true result = shell.test('-f', 'resources'); assert.equal(shell.error(), null); assert.equal(result, false); result = shell.test('-L', 'resources'); assert.equal(shell.error(), null); assert.equal(result, false); // file result = shell.test('-d', 'resources/file1'); assert.equal(shell.error(), null); assert.equal(result, false); result = shell.test('-f', 'resources/file1'); assert.equal(shell.error(), null); assert.equal(result, true);// true result = shell.test('-L', 'resources/file1'); assert.equal(shell.error(), null); assert.equal(result, false); // regression #529 result = shell.test('-f', 'resources/**/*.js'); assert.equal(shell.error(), null); assert.equal(result, false); // link // Windows is weird with links so skip these tests if (common.platform !== 'win') { result = shell.test('-d', 'resources/link'); assert.equal(shell.error(), null); assert.equal(result, false); result = shell.test('-f', 'resources/link'); assert.equal(shell.error(), null); assert.equal(result, true);// true result = shell.test('-L', 'resources/link'); assert.equal(shell.error(), null); assert.equal(result, true);// true result = shell.test('-L', 'resources/badlink'); assert.equal(shell.error(), null); assert.equal(result, true);// true result = shell.test('-L', 'resources/404'); assert.equal(shell.error(), null); assert.equal(result, false);// false } shell.exit(123); shelljs-0.7.5/test/to.js000066400000000000000000000020511300431262200151150ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var fs = require('fs'); shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); // // Invalids // // Normal strings don't have '.to()' anymore var str = 'hello world'; assert.ok(typeof str.to === 'undefined'); shell.ShellString('hello world').to(); assert.ok(shell.error()); assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check shell.ShellString('hello world').to('/asdfasdf/file'); assert.ok(shell.error()); // // Valids // var result; shell.ShellString('hello world').to('tmp/to1').to('tmp/to2'); result = shell.cat('tmp/to1'); assert.equal(shell.error(), null); assert.equal(result, 'hello world'); result = shell.cat('tmp/to2'); assert.equal(shell.error(), null); assert.equal(result, 'hello world'); // With a glob shell.ShellString('goodbye').to('tmp/t*1'); assert.equal(fs.existsSync('tmp/t*1'), false, 'globs are not interpreted literally'); result = shell.cat('tmp/to1'); assert.equal(shell.error(), null); assert.equal(result, 'goodbye'); shell.exit(123); shelljs-0.7.5/test/toEnd.js000066400000000000000000000026771300431262200155620ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var fs = require('fs'); shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); // // Invalids // // Normal strings don't have '.toEnd()' anymore var str = 'hello world'; assert.ok(typeof str.toEnd === 'undefined'); shell.ShellString('hello world').toEnd(); assert.ok(shell.error()); assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check assert.ok(shell.error()); // // Valids // var result; assert.equal(fs.existsSync('tmp/toEnd1'), false); // Check file toEnd() creates does not already exist assert.equal(fs.existsSync('tmp/toEnd2'), false); shell.ShellString('hello ').toEnd('tmp/toEnd1'); assert.equal(fs.existsSync('tmp/toEnd1'), true); // Check that file was created shell.ShellString('world').toEnd('tmp/toEnd1').toEnd('tmp/toEnd2'); // Write some more to the file result = shell.cat('tmp/toEnd1'); assert.equal(shell.error(), null); assert.equal(result, 'hello world'); // Check that the result is what we expect result = shell.cat('tmp/toEnd2'); assert.equal(shell.error(), null); assert.equal(result, 'world'); // Check that the result is what we expect // With a glob shell.ShellString('good').to('tmp/toE*1'); shell.ShellString('bye').toEnd('tmp/toE*1'); assert.equal(fs.existsSync('tmp/toE*1'), false, 'globs are not interpreted literally'); result = shell.cat('tmp/toEnd1'); assert.equal(shell.error(), null); assert.equal(result, 'goodbye'); shell.exit(123); shelljs-0.7.5/test/touch.js000066400000000000000000000100151300431262200156140ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var fs = require('fs'); var crypto = require('crypto'); shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); var oldStat; var testFile; // should handle args var result = shell.touch(); assert.ok(shell.error()); assert.equal(result.code, 1); result = shell.touch(1); assert.ok(shell.error()); assert.equal(result.code, 1); // exits without error when trying to touch a directory result = shell.touch('tmp/'); assert.ok(!shell.error()); assert.equal(result.code, 0); result = shell.touch('tmp'); assert.ok(!shell.error()); assert.equal(result.code, 0); // creates new files testFile = tmpFile(); result = shell.touch(testFile); assert(fs.existsSync(testFile)); // does not create a file if told not to testFile = tmpFile(true); result = shell.touch('-c', testFile); assert.equal(result.code, 0); assert.ok(!fs.existsSync(testFile)); // handles globs correctly result = shell.touch('tmp/file.txt'); result = shell.touch('tmp/file.js'); result = shell.touch('tmp/file*'); assert.equal(result.code, 0); var files = shell.ls('tmp/file*'); assert.ok(files.indexOf('tmp/file.txt') > -1); assert.ok(files.indexOf('tmp/file.js') > -1); assert.equal(files.length, 2); // errors if reference file is not found testFile = tmpFile(); var refFile = tmpFile(true); result = shell.touch({ '-r': refFile }, testFile); assert.equal(result.code, 1); assert.ok(shell.error()); // uses a reference file for mtime testFile = tmpFile(false); var testFile2 = tmpFile(); shell.touch(testFile2); shell.exec(JSON.stringify(process.execPath) + ' resources/exec/slow.js 3000'); result = shell.touch(testFile); assert.ok(!shell.error()); assert.equal(result.code, 0); assert.notEqual(fs.statSync(testFile).mtime.getTime(), fs.statSync(testFile2).mtime.getTime()); assert.notEqual(fs.statSync(testFile).atime.getTime(), fs.statSync(testFile2).atime.getTime()); result = shell.touch({ '-r': testFile2 }, testFile); assert.ok(!shell.error()); assert.equal(result.code, 0); assert.equal(fs.statSync(testFile).mtime.getTime(), fs.statSync(testFile2).mtime.getTime()); assert.equal(fs.statSync(testFile).atime.getTime(), fs.statSync(testFile2).atime.getTime()); // sets mtime testFile = tmpFile(); oldStat = resetUtimes(testFile); result = shell.touch(testFile); assert.equal(result.code, 0); assert(oldStat.mtime < fs.statSync(testFile).mtime); // sets atime assert(oldStat.atime < fs.statSync(testFile).atime); // does not sets mtime if told not to testFile = tmpFile(); oldStat = resetUtimes(testFile); result = shell.touch('-a', testFile); assert.equal(result.code, 0); assert.equal(oldStat.mtime.getTime(), fs.statSync(testFile).mtime.getTime()); // does not sets atime if told not to testFile = tmpFile(); oldStat = resetUtimes(testFile); result = shell.touch('-m', testFile); assert.equal(result.code, 0); assert.equal(oldStat.atime.getTime(), fs.statSync(testFile).atime.getTime()); // multiple files testFile = tmpFile(true); testFile2 = tmpFile(true); shell.rm('-f', testFile, testFile2); result = shell.touch(testFile, testFile2); assert.equal(result.code, 0); assert(fs.existsSync(testFile)); assert(fs.existsSync(testFile2)); // file array testFile = tmpFile(true); testFile2 = tmpFile(true); shell.rm('-f', testFile, testFile2); result = shell.touch([testFile, testFile2]); assert.equal(result.code, 0); assert(fs.existsSync(testFile)); assert(fs.existsSync(testFile2)); // touching broken link creates a new file if (process.platform !== 'win32') { result = shell.touch('resources/badlink'); assert.equal(result.code, 0); assert.ok(!shell.error()); assert.ok(fs.existsSync('resources/not_existed_file')); shell.rm('resources/not_existed_file'); } function resetUtimes(f) { var d = new Date(); d.setYear(2000); fs.utimesSync(f, d, d); return fs.statSync(f); } function tmpFile(noCreate) { var str = crypto.randomBytes(Math.ceil(10 / 2)).toString('hex'); var file = 'tmp/' + str; if (!noCreate) { fs.closeSync(fs.openSync(file, 'a')); } return file; } // required for the test runner shell.exit(123); shelljs-0.7.5/test/uniq.js000066400000000000000000000037031300431262200154540ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var fs = require('fs'); shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); var result; // // Invalids // result = shell.uniq(); assert.ok(shell.error()); assert.ok(result.code); assert.equal(fs.existsSync('/asdfasdf'), false); // sanity check result = shell.sort('/adsfasdf'); // file does not exist assert.ok(shell.error()); assert.ok(result.code); // // Valids // // uniq file1 result = shell.uniq('resources/uniq/file1'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result + '', shell.cat('resources/uniq/file1u').toString()); // uniq -i file2 result = shell.uniq('-i', 'resources/uniq/file2'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result + '', shell.cat('resources/uniq/file2u').toString()); // with glob character result = shell.uniq('-i', 'resources/uniq/fi?e2'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result + '', shell.cat('resources/uniq/file2u').toString()); // uniq file1 file2 shell.uniq('resources/uniq/file1', 'resources/uniq/file1t'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(shell.cat('resources/uniq/file1u').toString(), shell.cat('resources/uniq/file1t').toString()); // cat file1 |uniq result = shell.cat('resources/uniq/file1').uniq(); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result + '', shell.cat('resources/uniq/file1u').toString()); // uniq -c file1 result = shell.uniq('-c', 'resources/uniq/file1'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result + '', shell.cat('resources/uniq/file1c').toString()); // uniq -d file1 result = shell.uniq('-d', 'resources/uniq/file1'); assert.equal(shell.error(), null); assert.equal(result.code, 0); assert.equal(result + '', shell.cat('resources/uniq/file1d').toString()); shell.exit(123); shelljs-0.7.5/test/utils/000077500000000000000000000000001300431262200152775ustar00rootroot00000000000000shelljs-0.7.5/test/utils/utils.js000066400000000000000000000002071300431262200167740ustar00rootroot00000000000000function _numLines(str) { return typeof str === 'string' ? (str.match(/\n/g) || []).length + 1 : 0; } exports.numLines = _numLines; shelljs-0.7.5/test/which.js000066400000000000000000000014621300431262200156020ustar00rootroot00000000000000var shell = require('..'); var assert = require('assert'); var fs = require('fs'); shell.config.silent = true; shell.rm('-rf', 'tmp'); shell.mkdir('tmp'); // // Invalids // shell.which(); assert.ok(shell.error()); var result = shell.which('asdfasdfasdfasdfasdf'); // what are the odds... assert.ok(!shell.error()); assert.ok(!result); // // Valids // var node = shell.which('node'); assert.equal(node.code, 0); assert.ok(!node.stderr); assert.ok(!shell.error()); assert.ok(fs.existsSync(node + '')); if (process.platform === 'win32') { // This should be equivalent on Windows var nodeExe = shell.which('node.exe'); assert.ok(!shell.error()); // If the paths are equal, then this file *should* exist, since that's // already been checked. assert.equal(node + '', nodeExe + ''); } shell.exit(123);