pax_global_header00006660000000000000000000000064135134133360014514gustar00rootroot0000000000000052 comment=ce6e0dc4363447985aed327efe259c2db7714403 node-cpr-3.0.1/000077500000000000000000000000001351341333600132245ustar00rootroot00000000000000node-cpr-3.0.1/.dockerignore000066400000000000000000000000311351341333600156720ustar00rootroot00000000000000node_modules ./tests/out node-cpr-3.0.1/.gitignore000066400000000000000000000002621351341333600152140ustar00rootroot00000000000000**/node_modules/ **/npm-debug.log node_modules/ coverage/ artifacts/ tmp/ CVS/ .DS_Store .*.swp .svn *~ .com.apple.timemachine.supported tests/out/ .nyc_output package-lock.json node-cpr-3.0.1/.travis.yml000066400000000000000000000000471351341333600153360ustar00rootroot00000000000000language: node_js node_js: - '6' - '8' node-cpr-3.0.1/CHANGELOG.md000066400000000000000000000373221351341333600150440ustar00rootroot00000000000000## Change Log ### v3.0.0 (2017/10/31 13:08 +00:00) - [e3cd84b](https://github.com/davglass/cpr/commit/e3cd84b7f27a61e8c86cd14379905781e0970806) 3.0.0 (@davglass) - [17b0494](https://github.com/davglass/cpr/commit/17b0494af1b173a30e82e0d8c69297f4376d6cbb) Manually porting #43 (@davglass) - [a5a8ee4](https://github.com/davglass/cpr/commit/a5a8ee4e5ff0a5696320b5f828f39c1cd94d13dc) Fixing a race condition that can occur when a file has been read but the write buffer has not been flushed when copying a file. (#57) (@PlutoMatt) - [e08f362](https://github.com/davglass/cpr/commit/e08f362a89f474002f930afdbe492bf88bd529e1) Amend filtering info for more clarity. (#52) (@jrpool) - [b0e8f40](https://github.com/davglass/cpr/commit/b0e8f40b303d9b4fbbd2f20e2853d0617ae48b19) added node.js specific build info (@davglass) - [01efad1](https://github.com/davglass/cpr/commit/01efad136c554008fc529ff4f120fb863dfd1b8a) added node.js specific build info (@davglass) - [e2395ba](https://github.com/davglass/cpr/commit/e2395ba3846fea420e02ed043cde014a52cd614a) added appveyor build config (@davglass) - [4cb7ceb](https://github.com/davglass/cpr/commit/4cb7cebe41efc9e5854caf013f8c670b05cb008b) various changes (#50) (@stevenvachon) ### v2.2.0 (2017/06/26 12:15 +00:00) - [4520872](https://github.com/davglass/cpr/commit/4520872c30bbed3bac9930ad633f4dd4e5545225) 2.2.0 (@davglass) - [0686492](https://github.com/davglass/cpr/commit/0686492dab8f1563172996dc1e1be5e39d0adac7) changelog (@davglass) - [cdbc530](https://github.com/davglass/cpr/commit/cdbc53008427bd291476cd547e6f8a3e73cea632) Various changes (#48) (@stevenvachon) - [724900c](https://github.com/davglass/cpr/commit/724900c9ae5307cba2ba250fba5d1dfb74cb9af3) changelog (@davglass) ### v2.1.0 (2017/05/29 12:56 +00:00) - [57e7c2e](https://github.com/davglass/cpr/commit/57e7c2ecd17842e490003ab4eabe07368de24ad5) 2.1.0 (@davglass) - [8d3c003](https://github.com/davglass/cpr/commit/8d3c003e4658cb8c71d0f40167f96b0cc9f23f70) [fixes #44] - don't error when no callback given (@davglass) - [#40](https://github.com/davglass/cpr/pull/40) Merge pull request #40 from oferh/cpr-typings (@oferh) - [55dc201](https://github.com/davglass/cpr/commit/55dc2013cd00ae9ee5d97ae34d6a2f60382a306d) typings for cpr (@oferh) - [#37](https://github.com/davglass/cpr/pull/37) Merge pull request #37 from davglass/tests (@davglass) - [b4f8c00](https://github.com/davglass/cpr/commit/b4f8c003f2bd7f92e69e40c766846966ac34c484) fixing travis build (@davglass) - [0f2c8b5](https://github.com/davglass/cpr/commit/0f2c8b51a33610d53f7f9604e55bea8fe6360966) changelog (@davglass) ### v2.0.2 (2016/12/21 18:14 +00:00) - [3fa3af0](https://github.com/davglass/cpr/commit/3fa3af02572fe5a42fdf35ed879e3040fd209409) 2.0.2 (@davglass) - [#36](https://github.com/davglass/cpr/pull/36) Merge pull request #36 from benelliott/master (@benelliott) - [0443d51](https://github.com/davglass/cpr/commit/0443d511e92ee19a7d389e19d8f684f0ccb60c32) Include CLI documentation in README.md, update usage.txt to reflect CLI filter option (@benelliott) - [14233bf](https://github.com/davglass/cpr/commit/14233bf74563aa90f7c1b5fe8094717aededaf72) Added changelog [skip ci] (@davglass) ### v2.0.1 (2016/12/19 15:47 +00:00) - [4225fc6](https://github.com/davglass/cpr/commit/4225fc6ce0a62b8301ee881b9b2ff677246e8096) 2.0.1 (@davglass) - [f05f162](https://github.com/davglass/cpr/commit/f05f16298eb7467eb3b741c1f62af95e3519f779) added contrib (@davglass) - [#35](https://github.com/davglass/cpr/pull/35) Merge pull request #35 from benelliott/master (@benelliott) - [42e6e57](https://github.com/davglass/cpr/commit/42e6e573ebecbb950dd033ad96c7790d6a798962) Add simplified version of `filter` functionality to CLI (@benelliott) - [6ad0023](https://github.com/davglass/cpr/commit/6ad00236c6c5a888ea012c825d1422afa39e51fd) [Fixes #31] Added changelog [skip ci] (@davglass) ### v2.0.0 (2016/08/15 19:08 +00:00) - [#30](https://github.com/davglass/cpr/pull/30) Merge pull request #30 from stevenvachon/master (@stevenvachon) - [e7c4db1](https://github.com/davglass/cpr/commit/e7c4db18e36a10abb00d7eacdff08bced8fa9312) 2.0.0 (@stevenvachon) - [82dcffb](https://github.com/davglass/cpr/commit/82dcffb40a5841c663a5e66e76876470ae8a3518) added cli options (@stevenvachon) - [bf5d1ce](https://github.com/davglass/cpr/commit/bf5d1cec0a12c2a1841de58d501d29bcb45fbd58) adding new collaborator to package.json (@davglass) ### v1.1.2 (2016/06/09 14:26 +00:00) - [0584e7c](https://github.com/davglass/cpr/commit/0584e7cf7135d13b79a1fbb8ccd9c68ef4614262) 1.1.2 (@davglass) - [#29](https://github.com/davglass/cpr/pull/29) Merge pull request #29 from happinov/single-file-copy (@happinov) - [a79261d](https://github.com/davglass/cpr/commit/a79261d39d1e832d76aa9f7d4e00b372b02f6314) Fixed behavior in case to has trailing path separator. (@ldanet) - [128570a](https://github.com/davglass/cpr/commit/128570adfe3e3d2efd1de1b58147c4fb71bc32a3) Single files are now copied without creating a directory first. (@ldanet) ### v1.1.1 (2016/04/06 13:51 +00:00) - [e691cb3](https://github.com/davglass/cpr/commit/e691cb365ca7db3113a5ef3487ad12df1a4088ea) 1.1.1 (@davglass) - [e4bddfd](https://github.com/davglass/cpr/commit/e4bddfdad43d1d89ab4b7adbb43916411ef07c91) updating tests again (@davglass) - [bf0f79a](https://github.com/davglass/cpr/commit/bf0f79a8c80f67c071107e09dbddaaa83c5221ab) fix tests based on npm 3.x file tree (@davglass) - [f9c413e](https://github.com/davglass/cpr/commit/f9c413e8fc8b96847cb711871a56b6559bbb3c83) removed the .x from the node version in travis.yml (@davglass) - [eb41753](https://github.com/davglass/cpr/commit/eb41753dddd00c7d6abe86096c72e11ae37b39f4) adding more node.js testing support (@davglass) - [de5cf9a](https://github.com/davglass/cpr/commit/de5cf9ae7df184f0180b2d8a5ab8f090c14fcfa3) more test tweaks (@davglass) - [ac6cccf](https://github.com/davglass/cpr/commit/ac6cccf1ab6e8033baa8ab4f4764d430c9b9e0f3) Fixes #25 - Catching errors on copy properly (@davglass) - [a4153f7](https://github.com/davglass/cpr/commit/a4153f70587e8c8de9afb7cf1a34ccddf9ce512b) converting tests from vows to mocha (@davglass) ### v1.1.0 (2016/04/05 13:35 +00:00) - [5435bd2](https://github.com/davglass/cpr/commit/5435bd23be4c4d793de6c1d8077af9215b3f8edd) 1.1.0 (@davglass) - [bb2912d](https://github.com/davglass/cpr/commit/bb2912d7f500088b00c74bd83acab32430ca67cb) added contributor (@davglass) - [1173261](https://github.com/davglass/cpr/commit/1173261f75537853f7ee0e982a2d8c52d3e82cae) fixed formatting and added -v/--version (@davglass) - [135216e](https://github.com/davglass/cpr/commit/135216e0232496bde32eb8a564ed4cd86f3346f0) Add basic CLI support (@jonnyreeves) ### v1.0.0 (2015/11/12 19:58 +00:00) - [2d04135](https://github.com/davglass/cpr/commit/2d0413543ffe38001526feacf07eea9ffdea20fd) 1.0.0 (@davglass) - [1390d0a](https://github.com/davglass/cpr/commit/1390d0abf81fbe10a36112e2d03dc0fee3af6c96) updated travis with iojs (@davglass) - [2cd5e30](https://github.com/davglass/cpr/commit/2cd5e30a9d3341a70074bc6d996d8e8d527fdf5b) Fixes #18 - Fixed overwrite deleting existing directories (@davglass) ### v0.4.3 (2015/10/11 21:01 +00:00) - [845fb91](https://github.com/davglass/cpr/commit/845fb91422335679379878ebdb8a228bf5abda9f) 0.4.3 (@davglass) - [f005cd2](https://github.com/davglass/cpr/commit/f005cd246c06b54cb8776f1f543a4342dfb6c13f) added contributors (@davglass) - [#17](https://github.com/davglass/cpr/pull/17) Merge pull request #17 from soyuka/fix-overwrite-singlefile (@soyuka) - [3adcb91](https://github.com/davglass/cpr/commit/3adcb911846c85257ae846037507b786d801fc82) Fix single file copy override (@soyuka) - [#16](https://github.com/davglass/cpr/pull/16) Merge pull request #16 from fresheneesz/patch-2 (@fresheneesz) - [fa3cd1d](https://github.com/davglass/cpr/commit/fa3cd1d3e522fc2fac64053f7fffe95bb52de46c) Clarifications for issue #s 14 and 15 (@fresheneesz) ### v0.4.2 (2015/09/12 14:43 +00:00) - [8ccb044](https://github.com/davglass/cpr/commit/8ccb044a8c439af86d3065d6ca1cc1086d95fac2) 0.4.2 (@davglass) - [#13](https://github.com/davglass/cpr/pull/13) Merge pull request #13 from silverwind/deps (@silverwind) - [ff55b98](https://github.com/davglass/cpr/commit/ff55b98878d3a5ced88678dc3bb6a936b885e883) graceful-fs@4.1.2, rimraf@2.4.3 (@silverwind) ### v0.4.1 (2015/05/26 15:48 +00:00) - [28ffe61](https://github.com/davglass/cpr/commit/28ffe618ddd8e55a9bcae05613eb232f02286962) 0.4.1 (@davglass) - [#12](https://github.com/davglass/cpr/pull/12) Merge pull request #12 from pdehaan/patch-1 (@pdehaan) - [6ddd41f](https://github.com/davglass/cpr/commit/6ddd41f2a7ed4df1b91c1be99601f40870874081) Update license attribute (@pdehaan) ### v0.4.0 (2015/02/15 14:15 +00:00) - [98acf24](https://github.com/davglass/cpr/commit/98acf2409cb49aaefefc71378f195d596b18bc89) 0.4.0 (@davglass) - [294c282](https://github.com/davglass/cpr/commit/294c282d68518c51df8286ae1a48240295b0d4fc) fixed #11 - empty directory handling (@davglass) ### v0.3.3 (2015/02/10 14:58 +00:00) - [76b0f84](https://github.com/davglass/cpr/commit/76b0f840419e19bf829fb55ca91a0103a26175a8) 0.3.3 (@davglass) - [892dff3](https://github.com/davglass/cpr/commit/892dff31dfaaaccb824971e8921d00ce7df411cc) updated deps (@davglass) - [20ab662](https://github.com/davglass/cpr/commit/20ab662ceb101dd0d0e615eb0993a4a6e7c744b1) updated dev deps (@davglass) - [bbdfb84](https://github.com/davglass/cpr/commit/bbdfb842425e6bbbff86517c3e7bc4fd332aed47) adding image [fixes #10] (@davglass) ### v0.3.2 (2014/07/02 20:53 +00:00) - [c805cc8](https://github.com/davglass/cpr/commit/c805cc83cedf0d451d16b7bf4129297c0c77753d) 0.3.2 (@davglass) - [4a2621f](https://github.com/davglass/cpr/commit/4a2621f6d8faffb5c3b9225dc869e34c5b15c93b) Forgot to put the err in the callback.. (@davglass) ### v0.3.1 (2014/07/02 01:10 +00:00) - [1daff3c](https://github.com/davglass/cpr/commit/1daff3c92a14bc394d444bf0f601fa5b6aa290cf) 0.3.1 (@davglass) - [74dff64](https://github.com/davglass/cpr/commit/74dff64823ea7f3bebc5dd598750446acced3394) confirm: fixed missing files return when confirm is set and filter is not. Fixes #8 (@davglass) ### v0.3.0 (2014/06/30 14:12 +00:00) - [888ccb4](https://github.com/davglass/cpr/commit/888ccb448445c8113c8c27c1d32908014fa95505) 0.3.0 (@davglass) - [5d139cb](https://github.com/davglass/cpr/commit/5d139cb08fddc15228ac71cc371724148a699edc) Added support for single file copy and more tests. (@davglass) ### v0.2.0 (2014/05/13 13:33 +00:00) - [aceebf3](https://github.com/davglass/cpr/commit/aceebf3cabed52f84046471aefb31a83395048e0) 0.2.0 (@davglass) - [810d399](https://github.com/davglass/cpr/commit/810d3997e5c96abdcd4454b41c266684d094ead9) Updated deps and travis config (@davglass) - [c48d130](https://github.com/davglass/cpr/commit/c48d130952ee12c633cd11e186c55c960ac85980) Standardise errors to be more node-like. (@satazor) - [#4](https://github.com/davglass/cpr/pull/4) Merge pull request #4 from brianloveswords/readme-readability (@brianloveswords) - [540ba2d](https://github.com/davglass/cpr/commit/540ba2dd09b2aed59833ced567bb8ec47068a48b) Update readme with syntax highlighting. (@brianloveswords) - [09e943d](https://github.com/davglass/cpr/commit/09e943d24205f857f5d1c705f7e7b4287509c81f) Updated Travis Config (@davglass) - [cec7c7b](https://github.com/davglass/cpr/commit/cec7c7b89421acff331c0ab3029788a2ec114683) Updated Travis Config (@davglass) - [b586aa2](https://github.com/davglass/cpr/commit/b586aa2bf2b5e1b99c7ca7882009b82a3031bbb1) Version Bump and added @tmpvar credits (@davglass) - [4068056](https://github.com/davglass/cpr/commit/4068056a860e25fc9cccf5543f9e54b78977529e) Updated README (@davglass) - [6deea9a](https://github.com/davglass/cpr/commit/6deea9a0551dd2048166561c8ee27056cb4ed8a7) Adding in back compat support (@davglass) - [3a902c8](https://github.com/davglass/cpr/commit/3a902c80b90d5128dcdead64e83f9bee52f4663f) export a single function (@tmpvar) - [e5a81af](https://github.com/davglass/cpr/commit/e5a81afbd2f6891a9479a9f2d781f5f758adc644) Version Bump (@davglass) - [4c1ff62](https://github.com/davglass/cpr/commit/4c1ff62c3e3ec451b38a5749e690ecc70e0d34df) Updated test logic (@davglass) - [263d3d5](https://github.com/davglass/cpr/commit/263d3d51f4edabb0180caba8aae167b6cd706194) Fixed issue with empty dirs (@davglass) - [b1f824c](https://github.com/davglass/cpr/commit/b1f824c010b6331e3fac5da6f52579630aa6bc4d) Fixed issue with Node 9 (@davglass) - [7959698](https://github.com/davglass/cpr/commit/79596981b33680f53bcd2a6259df8fc3ff680402) Updated dep (@davglass) - [fc0cd12](https://github.com/davglass/cpr/commit/fc0cd1226fa92149d6a1519ffa1131256cb7eb61) Forgot license requirements (@davglass) - [1f99e6f](https://github.com/davglass/cpr/commit/1f99e6fb5785a7d6247ceffcac8ffb56c14221b6) Version Bump (@davglass) - [915ded3](https://github.com/davglass/cpr/commit/915ded3abcd1b35c0edf0840a963cfac15199feb) And added a test for it (@davglass) - [2cbeb0e](https://github.com/davglass/cpr/commit/2cbeb0e622003520008da2acb9f78f5c37fd8615) Fixed issue with cpr is given a file instead of a dir (@davglass) - [f3d6302](https://github.com/davglass/cpr/commit/f3d63023ebcd8f6a72839644fcb4a6d25f1f71a9) Added windows-test script to test on windows without istanbul (@davglass) - [f80e3c6](https://github.com/davglass/cpr/commit/f80e3c6d8b8889bc6ea4dd84d52d39325417c3cf) Added missing toHash entries for dirs, mkdirp must handle this under the hood better on unix than windows (@davglass) - [e7b5ddb](https://github.com/davglass/cpr/commit/e7b5ddb8dab1c4de6ce9e1c56f0488d7bba79e71) Version Bump (@davglass) - [f3e5ea4](https://github.com/davglass/cpr/commit/f3e5ea45481d612959eac7e42b9ae72c16f36067) Removed unusable error throw (@davglass) - [c400722](https://github.com/davglass/cpr/commit/c400722bd2aba1e69c01296ba05524edcc1da484) New Istanbul for coverage (@davglass) - [8a603cd](https://github.com/davglass/cpr/commit/8a603cdf8773d6c133e732e98cf75697c7d1c0ce) MOAR TEST COVERAGE (@davglass) - [dfd4cc1](https://github.com/davglass/cpr/commit/dfd4cc1ec5c04f2ff73ca6db8ca92924a8473c87) Fixed a few issues that appeared with more tests (@davglass) - [5ceed85](https://github.com/davglass/cpr/commit/5ceed850547dda0b81ff07852cd60f9eafccffba) Version Bump (@davglass) - [3380124](https://github.com/davglass/cpr/commit/3380124917309efecf0dde4474b974f669ce1eff) Added istanbul code coverage reporting (@davglass) - [861fece](https://github.com/davglass/cpr/commit/861fecebbabb443a2aa45ea8bea7276ca466d331) Added coverage report to gitignore (@davglass) - [9e6c416](https://github.com/davglass/cpr/commit/9e6c4167b5f2bec1827bfd25ab6ab31ffb0a8237) Break reference with options object for multi processing (@davglass) - [d225a74](https://github.com/davglass/cpr/commit/d225a74e228f610b4f5d171867a4f78d98a6f65d) Version Bump (@davglass) - [aa4d814](https://github.com/davglass/cpr/commit/aa4d814129f616eaddc7fe7c6416dc478f0e6529) Added check for string before stat (@davglass) - [1c91806](https://github.com/davglass/cpr/commit/1c918069cb90fa31c43c43160ac79b05a7e151a8) Added Travis Build Button (@davglass) - [f4b748b](https://github.com/davglass/cpr/commit/f4b748b42ce726fa916ad9b9a9aea3f07057bf96) Version Bump (@davglass) - [2dd7815](https://github.com/davglass/cpr/commit/2dd7815e3160bce9c126b14170baec83b001cdd0) Added jshint to devDeps for Travis (@davglass) - [2504edd](https://github.com/davglass/cpr/commit/2504eddfed33e7c4afb4a3d7ce26c6c37f155f67) MOAR TESTS (@davglass) - [b960127](https://github.com/davglass/cpr/commit/b9601270de82e8315f8155a7b46fd6d1a2075b2e) Trap EMFILE on both read and write streams (@davglass) - [0d2bc35](https://github.com/davglass/cpr/commit/0d2bc35dc82dde4024ab2abd62c6644ba7b2513e) Added test suite (@davglass) - [5758825](https://github.com/davglass/cpr/commit/5758825870e1c7e0b5dbd0ad721307ed21add575) Fixed some callback issues (@davglass) - [4e186f7](https://github.com/davglass/cpr/commit/4e186f70162f2c1abf9c2c7cf4f3bf2ed7a3e4f6) Added test dirs to ignore (@davglass) - [6c709f1](https://github.com/davglass/cpr/commit/6c709f1fbf0fb62c1ab317c0feab21d00b8f7098) Initial Commit (@davglass)node-cpr-3.0.1/Dockerfile000066400000000000000000000002411351341333600152130ustar00rootroot00000000000000FROM node:8 ENV NODE_ENV dev RUN mkdir /cpr COPY ./ /cpr/ RUN rm -rRf /cpr/node_modules RUN cd /cpr && npm install WORKDIR /cpr ENTRYPOINT cd /cpr && npm test node-cpr-3.0.1/LICENSE000066400000000000000000000027141351341333600142350ustar00rootroot00000000000000Copyright 2012 Yahoo! Inc. All rights reserved. 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 the Yahoo! Inc. nor the names of its 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 YAHOO! INC. 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. node-cpr-3.0.1/README.md000066400000000000000000000052471351341333600145130ustar00rootroot00000000000000CPR (cp -R) =========== There are other modules out there that attempt this, but none did it the way I needed it to be done or they had issues and the author failed to fix them in a timely manner. Install ------- npm install cpr Build Status ------------ [![Build Status](https://secure.travis-ci.org/davglass/cpr.png)](http://travis-ci.org/davglass/cpr) Usage ----- ```js var cpr = require('cpr'); //or var cpr = require('cpr').cpr; //Back compat cpr('/path/from', '/path/to', { deleteFirst: true, //Delete "to" before overwrite: true, //If the file exists, overwrite it confirm: true //After the copy, stat all the copied files to make sure they are there }, function(err, files) { //err - The error if any (err.list might be available with an array of errors for more detailed information) //files - List of files that we copied }); cpr('/path/from', '/path/to', function(err, files) { //err - The error if any (err.list might be available with an array of errors for more detailed information) // In the case of an error, cpr continues to copy files but returns this error object with all of the files that it failed to copy. //files - List of files that we copied }); ``` Options ------- All options default to `false`. * `deleteFirst`: Delete the to directory with `rimraf` * `overwrite`: If the destination exists, overwrite it * `confirm`: After the copy operation, stat all the files and report errors if any are missing * `filter`: `RegExp` or `function` to test each file against before copying Filtering --------- If you give it a `RegExp`, it will use that to `test` the full absolute pathnames of the files and directories as they are being gathered. If any of them passes, it will not be copied. If you give it a `function`, it will use that with `Array.filter` on the list of full absolute pathnames of files and directories. CLI --- `cpr` can also be used from the command line which is useful for cross platform support. Usage: ``` cpr [options] ``` Copies files from `source` to `destination`. Options: * `-d`, `--delete-first`: Delete the destination directory before copying. * `-f `, `--filter `: Filter out any items that match ``, a case-insensitive regex pattern. * `-h`, `--help`: Display this usage info. * `-o`, `--overwrite`: Overwrite the destination exists if it exists. * `-v`, `--version`: Display the cpr version. Note that the CLI's `filter` option is simpler than the original NodeJS API, only accepting case-insensitive regular expression patterns and not functions. ![cpr](../master/cpr.jpg?raw=true) node-cpr-3.0.1/appveyor.yml000066400000000000000000000007641351341333600156230ustar00rootroot00000000000000version: 1.0.{build} pull_requests: do_not_increment_build_number: true skip_tags: true environment: nodejs_version: "6" # Install scripts. (runs after repo cloning) install: # Get the latest stable version of Node.js or io.js - ps: Install-Product node $env:nodejs_version # install modules - npm install # Post-install test scripts. test_script: # Output useful info for debugging. - node --version - npm --version # run tests - npm test # Don't actually build. build: off node-cpr-3.0.1/bin/000077500000000000000000000000001351341333600137745ustar00rootroot00000000000000node-cpr-3.0.1/bin/cpr000077500000000000000000000013031351341333600145030ustar00rootroot00000000000000#!/usr/bin/env node var cpr = require('../lib'); var fs = require('fs'); var minimist = require('minimist'); var argv = minimist(process.argv.slice(2), { alias: { d:'delete-first', f:'filter', h:'help', o:'overwrite', v:'version' } }); if (argv.v) { console.log(require('../package.json').version); return; } if (argv.h) { fs.createReadStream(__dirname + '/usage.txt').pipe(process.stdout); return; } var filter; if (argv.f) { filter = new RegExp(argv.f, 'i'); } cpr(argv._[0], argv._[1], { deleteFirst: argv.d, filter: filter, overwrite: argv.o }, function (err) { if (err) { console.error('Error: ' + err.message); process.exit(1); } }); node-cpr-3.0.1/bin/usage.txt000077500000000000000000000007621351341333600156510ustar00rootroot00000000000000Usage: cpr [options] Copies files from one directory to another. Options: -d, --delete-first Delete the destination directory before copying. -f , --filter Filter out any items that match ``, a case-insensitive regex pattern. -h, --help Display this usage info. -o, --overwrite Overwrite the destination exists if it exists. -v, --version Display the cpr version. node-cpr-3.0.1/cpr.d.ts000066400000000000000000000006161351341333600146050ustar00rootroot00000000000000/** * Nodejs cp -R */ declare module "cpr" { function cpr (from: string, to: string, options?: cpr.CprOptions, callback?: (err: any, files: string[]) => void): void; namespace cpr { interface CprOptions { deleteFirst?: boolean; overwrite?: boolean; confirm?: boolean; filter?: RegExp | Function; } } export = cpr; } node-cpr-3.0.1/cpr.jpg000066400000000000000000000352001351341333600145120ustar00rootroot00000000000000JFIFHHC    #%$""!&+7/&)4)!"0A149;>>>%.DIC; X"R  !1AQaq"2BV#SUCRTbt$36r57s%D4c?.!aTo4֧#{Ne+ A%sbO28Q=%Oqb\q5r3mkRF.nN9VJus=}i'sO5ߦO̖yܸRcu5+ ;RȞ Ozle+r瑔5\&]z7.g }i )5DenqS5dOr{fV8r5];TÀH>,N O52ԼDb4 U5 f2F.htҴCga~ [&+Rx3F&{8׬Օ8\us>yrIx6ߕVn*#.;rv9>)++C[MCYI3fv#㑻O@{ZRڰӱ\ܼMNu\7Yqc58s'Sa-{>-Ui\HսIӵ+-_P'D]\Ѩ "pO-5Ds",OG"-uqdDkZ9=Fl.HTۿv9vbxYT;"D0ML?dmDHMW|Z^c Ib5-8ie2\cw @>j ,)R5SOKr [H-]@o_z-Mm_6[k"8kF*>JxOVx4E]f paX,*,y]nOq!ؒa+_i^_TɿB.y mǢḤƋ׍~ի KpS*b*S`M'9crr;@®DW~ &Ipw76Ttq/5=eOrs!VⵏEHr\ǘ @x[&'E~LMUߗN4m9' gJjrj/JfHCjڸiiY&lMrH(nQ-Or'USBӮ:. +5lr8n;%]^jd;Wg"Id)jaV G.hT;p_K:JWkkQچ.Y^R0[XE@45=vnszU GYK]v{jBc&hM҅Z0*s뙫,<=NNeM4[Нպ+b3e;~?6s]UL4THءۚLJ{\]=V&ͅWӱ}HNՠ˪IHZ+ssTTRbif}mC8bznW\5&m IW%LֆGqy:Ӑt`R޸j91*vλ7;W῕XmfMA_N*avzmESwUxVEJ> *|ɱd_g?*t: FGw5OLAn%"ۘEB:7kWmEڼDǣAedlNrMW@)Xt?k4ZXS=UE^ff}E,Lɢ{$nG5\QQK!] v᭣ũ?(8Lbᷥ2+"j=SS5g2ovEvbԭlRk|~ 9 l-2GIGs`_6Ykyjr==.Dx#d5cQ>CK*bcvmb嬜mbrCʹ݁H|z'j鰷ruXLuU;j뛥{=@i!'#$nVʊUQVU5S͎_YN#- ͍4jj[A_7=mC@hm~ *G_b'Ky(pC%MDpBI$F1LU:OcZV6/ RTrs!B`~pS_!hus_DܭEޗ.Ό <5FDb!J;ˉk"\fI97ܩҼӣ֕ \_j|_K%q͂ZdNELkکEE*jhdwRSҍwu5RН0%zէ6>eMPߴvy7jde~!QdX]*V,cz1W9˒"&jYZ,x9MTG*loM9=nTsd=5'"z.TUutUqSF/rS B+s*sPiN|b9OmzzO!Z2\zp:ĩ8J8ʫi-kv Ȑ˽^J/n5JHv/Jkk@I:<=MSoNDr}tQGzV'S'ncV;KR/@ՙ쑾WPV%Mt؍cI#wKΛK4PbNY$޿I:WeusŻ8h=EؘEEJI2~K߼:5 jqRdD_7im \S*=} >%A=\i, XbS%*mZN>nlk FE0K<Kz2dʲѪޜ輤wt]ULHhdTD~ ̪Uj9誣XEF/rT:ۘMɏRa4+r&jZh0kd,VAcSjvn:VeTlՉ8c[`&Y ۛf-5"iR$kխUTL A:?߸U?Vɨ_69d]ԼDOMrAPˢ,2u^˔,;KF炿5ZgK֍WoZlT-rEWL#s%V׵Sb󢢕IVWDB̨jxvΌDgiuERe5W"no])m~O4blv:W$*%_QbUoמGI#UW3>Z+5U:MbZV>ըrxJzR.ܜikNYoRK55]r}"1ѮLULz,7PF,>/O)䤫[Dd/:s)bmFYIORŎF"s9U.~ظ*л_EҟwНrOMצW/_r!iK֚&"*=&w!X7$\r۟!fki%kEѣkx˹e6tFm~PţeΞu5Wc]ȿE`Ƅ_rVG4VR&[]_zF+R]F#XJzhG2q'?T,rǪZʉ5Ln92Bh[q"&Ls4w쵞rʪe+ԸZlVX$k78v!MWʒ1$Ɗh:cSZ j$;ܝ):CjjvSSHDc̩uhLvqNU|;Ίis 4wp5jI""eȫUrEj[X]+R/")2)Uj*%w{޻\}X`85URTmjljqy3^E.atLՂ*:j$G $+^_5KX]1z=%i&[q:`UQw% ~-Rb_Unr/׽9&"9JV'j\Zx0TMu* 0 Ewڸ߉V˫9UrKXTsQɒN2ir.Uuv>oYz#'} Y'n"ʦȹ~9Mi{v| >m2bUUȲOQ#\MуpdsUaUyT`V~'OpO--DuH=E:E`ݱ]5qSՑ~\=GjGw[3dԪgR}Y6&|zy<2SO$1c7+okrT^mz8upS&UݨirN HwKmNj\K4uMr53_qW=9\\UsU8%k>))ON(vJD-$1G,&##ֵv/&M"&d7Νb4 <`1MNZx*cV=8ӑS%NXUa5HkS%1tMiuGQ;hplfgЊKZVڵ_<ڕ,PjַR.]*lqkPaʒ;=I78ס9K ѥ+nFSʮ|9}g{ ,Z0Ol'~? {0|Vũ*<E4/:/2hZk*lVrdUcrlsWtg&;Gux{>u6T|68ڮ{DUW6iSֲDo_Tڙ56u&ݗUE[$9JZ.\׭ \vR]W %4k$=#UZ6نԶptMyOH ̈k[]EM&~"<%^b cf"%""|!]?HREjd)/_+΄l}Y*UXQScwR.]+M5<MW֢fEX.n۞Ur@R$ֻUyJ{W U#Ǔʀa Of2QfEBEȲ)緒Tv#@^t2ZBYw2FH秪^#kvU$&DL_orá75sUb*7R/z):+{l*;TW/2&E6RtmT4csU^u\׬tw%vOɯPvD>yH vw /C"*HJVirFtBḅ.+A_G*KOP|oN4_״#2.Jwq+ڋRqOtݩ:nNfu[8<~#{'k7g7$]ʋm7vrJw$h[D*k=Z\Jpvsm,YIU'ǞO]hᤦQ152F$D"4VcuSN]Q5TS=r-ר<=;KS<=;KSt#zL*ju;S#GH֮X0C#LcQ2fmW=kZrϏ`ԪQ¨ʏcW.]x}[;|}[;<}[;|}[;CnlGծLR~' NVʏ\ktdzU6%U&;oBT?Ωnő=ZƜ{jij(OS j^tS#dl陞%BSZdVF}.̰eAf GIHꊇ&N߂'qt9Fi3NQ/=1g!f3NPr.{Xsj&j"3OmF/ҷT:<֦݉i&$rj sVMW^~zZ4_E?_{iUWXsrN3 -L9],Hޯrgr>)$nV=k**nTRtޗ ģ lت޹2ng.滟r.QDTTTS]aeay"xxZzP^+asYLTϟ#&;޵w5)T|SwJGix +I:UwmaK׼]"724&^ozn U\j{>xJp*ޝCۺGqHuj&5r?^\s?yE%:$qI^{{;W|S؏?;|S؏?;ȹEE]wr#ُbHh7'yHw Tm^.ߙK/\a$L)ӝI<4)5t*^_EɿPv6NwS~N3gthdډjh>~ en%KVf NކC3p3Ac1i|g9ssڽHEs@n娬LzWqdsLR-mXӡ| 82<;t/T4Nf4Ngf1a*zΧvkvGUN/ T˖YMʦ_f&zU rdܓ#_sʪ8Q$26H=\QzMo=VJV?%Po_SsBro,Z6b'dgʜπ\GnY\ʫGm!kY۳8WV$_SBtrԹEMEDܨők:I%Ve|?v&GE) s53`vRdIG\޲êjn0j6f\:Eח$BeU TU0?ђ'hz@jL6Jژ3|"N2b!VⵏEHr\ǘ8q:TBEN4^4,vRx HEԞl']輆f3irpkYwVdDTbҪ}R]7=v䮫s)ue$Ky3OYy3[e+ϼ@5lO S"|,js7~%wo\b؄ڰWG8yokHdï/UAFVvH:nidGW5XٚOݥ kz5wiy Ϗӹ]7ƪ*w,hN'xw,hN'y v@;~C/L((=nlW&ժq#?(Y5L櫑ЮIt3^ dhѵLNSH;ov raؓW/c2} Q$z3;K74yi{9f /g0ٚ<{3Nk6٢hF@sU7*)ߍ[=șPEVUV4?5W~1<ٞx~t{h@k-E\\ /g0ٚwCg[4VoE\7]TܪT<@aZ{ ]#L~m 7 J7-PILkj#G.+n|Ch2w8k~'xZ>̝ㆻh2w8k~'xZ>̝ㆻh2w8k~'xZ>̝ㆻh2w8k~'xZ>̝ㆻh2w8k~'xZ>̝ㆻh2w8k~'xZ>̝ㆻh2w8k~'xZ>̝ㆻh2w8k~'xZ>̝ㆻh2w8k~'xZ>̝ㆻh2w8k~'xZ>̝m6.e֙ kVQP,0a\xv#NulE*"^elWXCk"bgOR;jW"PJD2~h$&ƢqIUTm&&ZMKPr'_sc0>tTקlVvmN a1TG#۵U$%ƯY\XpZ.6)ʞ&M*-ty.~}CNW"3+ `/V'27/uW्-^ r"Jen֯ʥUZj=X92V%E:,?&VOPZCViMn^c:sU5M>⊑8KWc&|k~ߢLrɹDʙ#4Nd*fCcNjoDO7HXV4v낭)Xd&;p]~jqRdW;z1\1Q3ؙ;q ) yv#9y:2JbG+vb/Ykʦ|\񐞑E%3-$.Ut,MƜiӋfQQrT@HZ>euQ!C%.v5FREK-,,6&Mj&D;eC&/@c5"=sS<*/*}nܮ)Uw"H׵=WhdU\?c*|Zvo DUJ̾WȆG}*oW*7<8"l.f%6)Ւal{w=>8?軸|S8?軸|S8?軸fb>,ͥz%.'p^w%.'p^w%.'p^w%.'p^w%.'p^wqZ7$ԏĜw v7W!.f>%'_<}+oxepoB]}KټOy v7W!.f>-'_zSFד-֢ͩ~#[s{~ o/g^857pky{?Wox~_[s{~h=Lt~ϽoOP/_?Q?ECk'pM|D "5D_8&~h;z9pȘ꺦<}5z_jp5z_jh>eu6iRN734:YZ9#EMdr.JdI6Z1}KUS.NL"s"!K4]]JbW5zw;b?kY$e-'sOrdIsZSj䉵xqj |0;qSl˕3ڽHhhoef**۵s2ʍ_IyH興r e2tF]#.d2 C!d2 C!d2 C$' 9I2NAr d$' 9H2 C!d29˷ q 6g/k6:hZOz-R?j8!ԕ&Wjn UKMRKO=ep<"f¨]ɯ;z!o)node-cpr-3.0.1/lib/000077500000000000000000000000001351341333600137725ustar00rootroot00000000000000node-cpr-3.0.1/lib/index.js000066400000000000000000000255631351341333600154520ustar00rootroot00000000000000/* Copyright (c) 2012, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://yuilibrary.com/license/ */ var fs = require('graceful-fs'); var Stack = require('./stack').Stack; var path = require('path'); var rimraf = require('rimraf'); var mkdirp = require('mkdirp'); var getTree = function(from, options, callback) { var stack = new Stack(), errors = [], results = {}; options.stats = options.stats || {}; options.toHash = options.toHash || {}; fs.readdir(from, stack.add(function(err, dirs) { if (!dirs.length) { results[from] = true; fs.stat(from, stack.add(function(err, stat) { /*istanbul ignore next*/ if (err) { return errors.push(err); } options.stats[from] = stat; options.toHash[from] = path.join(options.to, path.relative(options.from, from)); })); } dirs.forEach(function (dir) { var base = path.join(from, dir); fs.stat(base, stack.add(function(err, stat) { options.stats[base] = stat; options.toHash[base] = path.join(options.to, path.relative(options.from, base)); /*istanbul ignore next*/ if (err) { return errors.push(err); } if (stat.isDirectory()) { getTree(base, options, stack.add(function(errs, tree) { /*istanbul ignore next*/ if (errs && errs.length) { errs.forEach(function(item) { errors.push(item); }); } //tree is always an Array tree.forEach(function(item) { results[item] = true; }); })); } else { results[base] = true; } })); }); })); stack.done(function() { callback(errors, Object.keys(results).sort()); }); }; var filterTree = function (tree, options, callback) { var t = tree; if (options.filter) { if (typeof options.filter === 'function') { t = tree.filter(options.filter); } else if (options.filter instanceof RegExp) { t = tree.filter(function(item) { return !options.filter.test(item); }); } } callback(null, t); }; var splitTree = function (tree, options, callback) { var files = {}, dirs = {}; tree.forEach(function(item) { var to = options.toHash[item]; if (options.stats[item] && options.stats[item].isDirectory()) { dirs[item] = true; } else { dirs[path.dirname(item)] = true; options.stats[path.dirname(item)] = fs.statSync(path.dirname(item)); options.toHash[path.dirname(item)] = path.dirname(to); } }); tree.forEach(function(item) { if (!dirs[item]) { files[item] = true; } }); callback(Object.keys(dirs).sort(), Object.keys(files).sort()); }; var createDirs = function(dirs, to, options, callback) { var stack = new Stack(); dirs.forEach(function(dir) { var stat = options.stats[dir], to = options.toHash[dir]; /*istanbul ignore else*/ if (to && typeof to === 'string') { fs.stat(to, stack.add(function(err, s) { if (s && !s.isDirectory()) { /*istanbul ignore next*/ err = new Error(to + ' exists and is not a directory, can not create'); /*istanbul ignore next*/ err.code = 'ENOTDIR'; /*istanbul ignore next*/ err.errno = 27; options.errors.push(err); } else { mkdirp(to, stat.mode, stack.add(function(err) { /*istanbul ignore next*/ if (err) { options.errors.push(err); } })); } })); } }); stack.done(function() { callback(); }); }; var copyFile = function(from, to, options, callback) { var dir = path.dirname(to); mkdirp(dir, function() { fs.stat(to, function(statError) { var err; if(!statError && options.overwrite !== true) { /*istanbul ignore next*/ err = new Error('File '+to+' exists'); /*istanbul ignore next*/ err.code = 'EEXIST'; /*istanbul ignore next*/ err.errno = 47; return callback(err); } var fromFile = fs.createReadStream(from), toFile = fs.createWriteStream(to, { mode: options.stats[from].mode }), called = false, cb = function(e) { /*istanbul ignore next - This catches a hard to trap race condition */ if (!called) { callback(e); called = true; } }, /*istanbul ignore next*/ onError = function (e) { err = e; cb(e); }; fromFile.on('error', onError); toFile.on('error', onError); toFile.once('finish', function() { cb(err); }); fromFile.pipe(toFile); }); }); }; var createFiles = function(files, to, options, callback) { var next = process.nextTick, complete = 0, count = files.length, check = function() { /*istanbul ignore else - Shouldn't need this if graceful-fs does it's job*/ if (count === complete) { callback(); } }, copy = function() { var from = files.pop(), to = options.toHash[from], bail; if (!from) { return check(); } copyFile(from, to, options, function(err) { /*istanbul ignore next*/ //This shouldn't happen with graceful-fs, but just in case if (/EMFILE/.test(err)) { bail = true; files.push(from); } else if (err) { options.errors.push(err); } /*istanbul ignore next*/ if (!bail) { complete++; } next(copy); }); }; copy(); }; var confirm = function(files, options, callback) { var stack = new Stack(), errors = [], f = [], filtered = files; if (options.filter) { if (typeof options.filter === 'function') { filtered = files.filter(options.filter); } else if (options.filter instanceof RegExp) { filtered = files.filter(function(item) { return !options.filter.test(item); }); } } /*istanbul ignore else - filtered should be an array, but just in case*/ if (filtered.length) { filtered.forEach(function(file) { fs.stat(file, stack.add(function(err, stat) { /*istanbul ignore next*/ if (err) { errors.push(err); } else { if (stat && (stat.isFile() || stat.isDirectory())) { f.push(file); } } })); }); } stack.done(function() { /*istanbul ignore next */ callback(((errors.length) ? errors : null), f.sort()); }); }; var cpr = function(from, to, opts, callback) { if (typeof opts === 'function') { callback = opts; opts = {}; } var options = {}, proc; /*istanbul ignore next - in case a callback isn't provided*/ callback = callback || function () {}; Object.keys(opts).forEach(function(key) { options[key] = opts[key]; }); options.from = from; options.to = to; options.errors = []; proc = function() { getTree(options.from, options, function(err, tree) { filterTree(tree, options, function(err, t) { splitTree(t, options, function(dirs, files) { if (!dirs.length && !files.length) { return callback(new Error('No files to copy')); } createDirs(dirs, to, options, function() { createFiles(files, to, options, function() { var out = [], err; Object.keys(options.toHash).forEach(function(k) { out.push(options.toHash[k]); }); if (options.confirm) { confirm(out, options, callback); } else if (!options.errors.length) { callback(null, out.sort()); } else { /*istanbul ignore next*/ err = new Error('Unable to copy directory' + (out.length ? ' entirely' : '')); /*istanbul ignore next*/ err.list = options.errors; /*istanbul ignore next*/ callback(err, out.sort()); } }); }); }); }); }); }; fs.stat(options.from, function(err, stat) { if (err) { return callback(new Error('From should be a file or directory')); } if (stat && stat.isDirectory()) { if (options.deleteFirst) { rimraf(to, function() { proc(); }); } else { proc(); } } else { if (stat.isFile()) { var dirRegex = new RegExp(path.sep + '$'); if (dirRegex.test(to)) { // Create directory if has trailing separator to = path.join(to, path.basename(options.from)); } // ensure copyFile() can access cached stat options.stats = options.stats || {}; options.stats[from] = stat; return copyFile(options.from, to, options, callback); } callback(new Error('From should be a file or directory')); } }); }; //Preserve backward compatibility cpr.cpr = cpr; //Export a function module.exports = cpr; node-cpr-3.0.1/lib/stack.js000066400000000000000000000017311351341333600154370ustar00rootroot00000000000000/* Copyright (c) 2012, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://yuilibrary.com/license/ */ var Stack = function () { this.errors = []; this.finished = 0; this.results = []; this.total = 0; }; Stack.prototype = { add: function (fn) { var self = this, index = self.total; self.total += 1; return function (err) { if (err) { self.errors[index] = err; } self.finished += 1; self.results[index] = fn.apply(null, arguments); self.test(); }; }, test: function () { if (this.finished >= this.total && this.callback) { this.callback.call(null, this.errors.length ? this.errors : null, this.results, this.data); } }, done: function (callback, data) { this.callback = callback; this.data = data; this.test(); } }; exports.Stack = Stack; node-cpr-3.0.1/package.json000066400000000000000000000031651351341333600155170ustar00rootroot00000000000000{ "name": "cpr", "description": "cp -R", "author": "Dav Glass ", "version": "3.0.1", "dependencies": { "graceful-fs": "^4.1.5", "minimist": "^1.2.0", "mkdirp": "~0.5.1", "rimraf": "^2.5.4" }, "main": "./lib/index.js", "typings": "./cpr.d.ts", "bin": "./bin/cpr", "devDependencies": { "github-changes": "^1.0.4", "jenkins-mocha": "^4.0.0", "jshint": "^2.9.2", "nyc": "^11.0.2", "yui-lint": "~0.2.0" }, "contributors": [ "soyuka ", "fresheneesz ", "silverwind ", "Peter deHaan ", "André Cruz ", "Brian J Brennan ", "Elijah Insua ", "Jonny Reeves ", "Lydie Danet ", "Ben Elliott " ], "keywords": [ "copy", "recursive", "cp -r", "cp" ], "scripts": { "pretest": "jshint --config ./node_modules/yui-lint/jshint.json ./lib/", "windows-test": "jenkins-mocha ./tests/full.js", "test": "jenkins-mocha ./tests/full.js", "posttest": "nyc report", "changes": "github-changes -o davglass -r cpr" }, "nyc": { "lines": 100, "statements": 100, "functions": 100, "branches": 90, "check-coverage": true, "reporter": [ "text", "text-summary" ] }, "bugs": { "url": "http://github.com/davglass/cpr/issues" }, "license": "BSD-3-Clause", "repository": { "type": "git", "url": "http://github.com/davglass/cpr.git" } } node-cpr-3.0.1/tests/000077500000000000000000000000001351341333600143665ustar00rootroot00000000000000node-cpr-3.0.1/tests/full.js000066400000000000000000000353661351341333600157030ustar00rootroot00000000000000var assert = require('assert'), path = require('path'), fs = require('fs'), rimraf = require('rimraf'), mkdirp = require('mkdirp'), cpr = require('../lib'), exec = require('child_process').exec, to = path.join(__dirname, './out/'), from = path.join(__dirname, '../node_modules'); describe('cpr test suite', function() { this.timeout(55000); describe('loading', function() { before(function() { rimraf.sync(to); }); it('should export raw method', function () { assert.equal(typeof cpr, 'function'); }); it('should export cpr method too', function () { assert.equal(typeof cpr.cpr, 'function'); }); }); describe('should copy node_modules', function() { var out = path.join(to, '0'); var data = {}; var beforeStat = fs.statSync(path.join(from, '.bin/mocha')); before(function(done) { cpr(from, out, function(err, status) { data = { from: fs.readdirSync(from).sort(), to: fs.readdirSync(out).sort() }; done(); }); }); it('has ./out/0', function() { var stat = fs.statSync(out); assert.ok(stat.isDirectory()); }); it('dirs are equal', function() { assert.deepEqual(data.to, data.from); }); it('from directory has graceful-fs dir', function() { var fromHasGFS = data.from.some(function(item) { return (item === 'graceful-fs'); }); assert.equal(true, fromHasGFS); }); it('to directory has graceful-fs dir', function() { var toHasGFS = data.to.some(function(item) { return (item === 'graceful-fs'); }); assert.equal(true, toHasGFS); }); it('preserves file mode of copied files', function () { var stat = fs.statSync(path.join(out, '.bin/mocha')); assert.equal(beforeStat.mode, stat.mode); }); }); describe('should NOT copy node_modules', function() { var out = path.join(to, '1'), data; before(function(done) { cpr(from, out, { filter: /node_modules/ }, function(err) { fs.stat(out, function(e, stat) { data = { err: err, stat: e }; done(); }); }); }); it('does not have ./out/1', function() { assert.ok(data.stat); // Should be an error }); it('threw an error', function() { assert(data.err instanceof Error); // Should be an error assert.equal(data.err.message, 'No files to copy'); }); }); describe('should not copy yui-lint from regex', function() { var out = path.join(to, '2'), data; before(function(done) { cpr(from, out, { confirm: true, overwrite: true, filter: /yui-lint/ }, function(err, status) { data = { status: status, dirs: { from: fs.readdirSync(from).sort(), to: fs.readdirSync(out).sort() } }; done(); }); }); it('returns files array with confirm', function() { assert.ok(Array.isArray(data.status)); assert.ok(data.status.length > 0); }); it('has ./out/2', function() { var stat = fs.statSync(out); assert.ok(stat.isDirectory()); }); it('dirs are not equal', function() { assert.notDeepEqual(data.dirs.to, data.dirs.from); }); it('from directory has yui-lint dir', function() { var fromHasLint = data.dirs.from.some(function(item) { return (item === 'yui-lint'); }); assert.equal(true, fromHasLint); }); it('to directory does not have yui-lint dir', function() { var toHasLint = data.dirs.to.some(function(item) { return (item === 'yui-lint'); }); assert.equal(false, toHasLint); }); }); describe('should not copy directory from function', function() { var out = path.join(to, '3'), data; before(function(done) { cpr(from, out, { confirm: true, deleteFirst: true, filter: function (item) { return !(/data/.test(item)); } }, function(err, status) { data = { status: status, dirs: { from: fs.readdirSync(path.join(from, 'jshint/')).sort(), to: fs.readdirSync(path.join(out, 'jshint/')).sort() } }; done(); }); }); it('has ./out/3', function() { var stat = fs.statSync(out); assert.ok(stat.isDirectory()); }); it('dirs are not equal', function() { assert.notDeepEqual(data.dirs.to, data.dirs.from); }); it('from directory has data dir', function() { var fromHas = data.dirs.from.some(function(item) { return (item === 'data'); }); assert.equal(true, fromHas); }); it('to directory does not have data dir', function() { var toHas = data.dirs.to.some(function(item) { return (item === 'data'); }); assert.equal(false, toHas); }); }); describe('should copy shelljs from bad filter', function() { var out = path.join(to, '4'), data; before(function(done) { cpr(from, out, { confirm: true, deleteFirst: true, filter: 'bs content' }, function(err, status) { data = { status: status, dirs: { from: fs.readdirSync(path.join(from, 'jshint/node_modules')).sort(), to: fs.readdirSync(path.join(out, 'jshint/node_modules')).sort() } }; done(); }); }); it('has ./out/4', function() { var stat = fs.statSync(out); assert.ok(stat.isDirectory()); }); it('dirs are not equal', function() { assert.deepEqual(data.dirs.to, data.dirs.from); }); it('from directory has shelljs dir', function() { var fromHas = data.dirs.from.some(function(item) { return (item === 'shelljs'); }); assert.equal(true, fromHas); }); it('to directory does have shelljs dir', function() { var toHas = data.dirs.to.some(function(item) { return (item === 'shelljs'); }); assert.equal(true, toHas); }); }); describe('should copy node_modules with overwrite flag', function() { var out = path.join(to, '4'), data; before(function(done) { cpr(from, out, function() { cpr(from, out, { overwrite: true, confirm: true }, function(err, status) { data = { status: status, dirs: { from: fs.readdirSync(from).sort(), to: fs.readdirSync(out).sort() } }; done(); }); }); }); it('should return files array', function() { assert.ok(Array.isArray(data.status)); assert.ok(data.status.length > 0); }); it('has ./out/0', function() { var stat = fs.statSync(out); assert.ok(stat.isDirectory()); }); it('dirs are equal', function() { assert.deepEqual(data.dirs.to, data.dirs.from); }); it('from directory has graceful-fs dir', function() { var fromHasGFS = data.dirs.from.some(function(item) { return (item === 'graceful-fs'); }); assert.equal(true, fromHasGFS); }); it('to directory has graceful-fs dir', function() { var toHasGFS = data.dirs.to.some(function(item) { return (item === 'graceful-fs'); }); assert.equal(true, toHasGFS); }); }); describe('error handling', function() { it('should fail on non-existant from dir', function(done) { cpr('./does/not/exist', path.join(to, 'does/not/matter'), function(err, status) { assert.equal(undefined, status); assert(err instanceof Error); assert.equal('From should be a file or directory', err.message); done(); }); }); it('should fail on non-file', function(done) { cpr('/dev/null', path.join(to, 'does/not/matter'), function(err, status) { assert.equal(undefined, status); assert(err instanceof Error); assert.equal('From should be a file or directory', err.message); done(); }); }); it('should return an error if a directory is to write over an existing file with the same name', function(done) { mkdirp.sync(path.join(to, 'empty-src2', 'a')); mkdirp.sync(path.join(to, 'empty-dest2')); fs.writeFileSync(path.join(to, 'empty-dest2', 'a'), 'FILE'); cpr(path.join(to, 'empty-src2'), path.join(to, 'empty-dest2'), { overwrite: true }, function(errs) { var stat = fs.statSync(path.join(to, 'empty-dest2')); assert.ok(stat.isDirectory()); assert.ok(errs); assert.ok(errs.list); assert.ok(errs.list[0]); assert.ok(errs.list[0].message.match(/exists and is not a directory, can not create/)); assert.equal(errs.list[0].code, 'ENOTDIR'); assert.equal(errs.list[0].errno, 27); done(); }); }); it('should fail without write permissions', function(done) { /*istanbul ignore next - This is for docker perms*/ (function() { if (process.getuid && process.getuid() === 0) { console.log('Skipping this test as root has all access..'); return done(); } var baddir = path.join(to, 'readonly'); mkdirp.sync(baddir); fs.chmodSync(baddir, '555'); cpr(path.join(from, '.bin'), baddir, function(errs, status) { assert.ok(errs); assert.ok(errs.list); assert.ok(errs.list[0]); assert.ok(errs.message.match(/Unable to copy directory entirely/)); done(); }); })(); }); }); describe('validations', function() { it('should copy empty directory', function(done) { mkdirp.sync(path.join(to, 'empty-src')); cpr(path.join(to, 'empty-src'), path.join(to, 'empty-dest'), function() { var stat = fs.statSync(path.join(to, 'empty-dest')); assert.ok(stat.isDirectory()); done(); }); }); it('should not delete existing folders in out dir', function(done) { mkdirp.sync(path.join(to, 'empty-src', 'a')); mkdirp.sync(path.join(to, 'empty-dest', 'b')); cpr(path.join(to, 'empty-src'), path.join(to, 'empty-dest'), { overwrite: true }, function() { var stat = fs.statSync(path.join(to, 'empty-dest')); assert.ok(stat.isDirectory()); var dirs = fs.readdirSync(path.join(to, 'empty-dest')); assert.equal(dirs[0], 'a'); assert.equal(dirs[1], 'b'); done(); }); }); it('should copy one file', function(done) { cpr(__filename, path.join(to, 'one-file-test.js'), { overwrite: true }, function(err) { assert.equal(undefined, err); var stat = fs.statSync(path.join(to, 'one-file-test.js')); assert.ok(stat.isFile()); done(); }); }); it('should copy one file in dir if to has trailing sep', function(done) { cpr(__filename, path.join(to, 'one-file-dir'+path.sep), { overwrite: true }, function(err) { assert.equal(undefined, err); var stat = fs.statSync(path.join(to, 'one-file-dir','full.js')); assert.ok(stat.isFile()); done(); }); }); it('should not copy because file exists', function(done) { cpr(__filename, path.join(to, 'one-file-test.js'), function(err, status) { assert.equal(undefined, status); assert(err instanceof Error); assert.ok(/^File .* exists$/.test(err.message)); assert.equal(err.code, 'EEXIST'); assert.equal(err.errno, 47); done(); }); }); }); describe('should work as a standalone bin', function() { var out = path.join(to, '4'), data; before(function(done) { exec('node ./bin/cpr ' + from + ' ' + out, function(err) { data = { dirs: { from: fs.readdirSync(from).sort(), to: fs.readdirSync(out).sort() } }; done(); }); }); it('has ./out/4', function() { var stat = fs.statSync(out); assert.ok(stat.isDirectory()); }); it('dirs are equal', function() { assert.deepEqual(data.dirs.to, data.dirs.from); }); it('from directory has graceful-fs dir', function() { var fromHasGFS = data.dirs.from.some(function(item) { return (item === 'graceful-fs'); }); assert.equal(true, fromHasGFS); }); it('to directory has graceful-fs dir', function() { var toHasGFS = data.dirs.to.some(function(item) { return (item === 'graceful-fs'); }); assert.equal(true, toHasGFS); }); }); });