Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #3198 from adobe/dangoor/testing-domain

Enable installation tests
  • Loading branch information...
commit 5a0fbcdeb84dfdd310e2d48270fb7264b3482683 2 parents 7d357f2 + 876f618
@njx njx authored
Showing with 3,451 additions and 10 deletions.
  1. +2 −1  Gruntfile.js
  2. +57 −0 test/SpecRunner.js
  3. +54 −0 test/node/TestingDomain.js
  4. +1 −0  test/node/node_modules/fs-extra/.npmignore
  5. +5 −0 test/node/node_modules/fs-extra/.travis.yml
  6. +67 −0 test/node/node_modules/fs-extra/CHANGELOG.md
  7. +16 −0 test/node/node_modules/fs-extra/LICENSE
  8. +281 −0 test/node/node_modules/fs-extra/README.md
  9. +42 −0 test/node/node_modules/fs-extra/lib/copy.js
  10. +53 −0 test/node/node_modules/fs-extra/lib/create.js
  11. +102 −0 test/node/node_modules/fs-extra/lib/index.js
  12. +6 −0 test/node/node_modules/fs-extra/lib/mkdir.js
  13. +35 −0 test/node/node_modules/fs-extra/lib/output.js
  14. +17 −0 test/node/node_modules/fs-extra/lib/remove.js
  15. +1 −0  test/node/node_modules/fs-extra/node_modules/.bin/ncp
  16. +1 −0  test/node/node_modules/fs-extra/node_modules/jsonfile/.npmignore
  17. +4 −0 test/node/node_modules/fs-extra/node_modules/jsonfile/.travis.yml
  18. +3 −0  test/node/node_modules/fs-extra/node_modules/jsonfile/CHANGELOG.md
  19. +15 −0 test/node/node_modules/fs-extra/node_modules/jsonfile/LICENSE
  20. +116 −0 test/node/node_modules/fs-extra/node_modules/jsonfile/README.md
  21. +44 −0 test/node/node_modules/fs-extra/node_modules/jsonfile/lib/jsonfile.js
  22. +37 −0 test/node/node_modules/fs-extra/node_modules/jsonfile/package.json
  23. +66 −0 test/node/node_modules/fs-extra/node_modules/jsonfile/test/jsonfile.test.js
  24. +3 −0  test/node/node_modules/fs-extra/node_modules/jsonfile/test/mocha.opts
  25. 0  test/node/node_modules/fs-extra/node_modules/jsonfile/test/resources/.gitkeep
  26. +2 −0  test/node/node_modules/fs-extra/node_modules/mkdirp/.npmignore
  27. +5 −0 test/node/node_modules/fs-extra/node_modules/mkdirp/.travis.yml
  28. +21 −0 test/node/node_modules/fs-extra/node_modules/mkdirp/LICENSE
  29. +6 −0 test/node/node_modules/fs-extra/node_modules/mkdirp/examples/pow.js
  30. +82 −0 test/node/node_modules/fs-extra/node_modules/mkdirp/index.js
  31. +30 −0 test/node/node_modules/fs-extra/node_modules/mkdirp/package.json
  32. +63 −0 test/node/node_modules/fs-extra/node_modules/mkdirp/readme.markdown
  33. +38 −0 test/node/node_modules/fs-extra/node_modules/mkdirp/test/chmod.js
  34. +37 −0 test/node/node_modules/fs-extra/node_modules/mkdirp/test/clobber.js
  35. +28 −0 test/node/node_modules/fs-extra/node_modules/mkdirp/test/mkdirp.js
  36. +32 −0 test/node/node_modules/fs-extra/node_modules/mkdirp/test/perm.js
  37. +39 −0 test/node/node_modules/fs-extra/node_modules/mkdirp/test/perm_sync.js
  38. +41 −0 test/node/node_modules/fs-extra/node_modules/mkdirp/test/race.js
  39. +32 −0 test/node/node_modules/fs-extra/node_modules/mkdirp/test/rel.js
  40. +25 −0 test/node/node_modules/fs-extra/node_modules/mkdirp/test/return.js
  41. +24 −0 test/node/node_modules/fs-extra/node_modules/mkdirp/test/return_sync.js
  42. +18 −0 test/node/node_modules/fs-extra/node_modules/mkdirp/test/root.js
  43. +32 −0 test/node/node_modules/fs-extra/node_modules/mkdirp/test/sync.js
  44. +28 −0 test/node/node_modules/fs-extra/node_modules/mkdirp/test/umask.js
  45. +32 −0 test/node/node_modules/fs-extra/node_modules/mkdirp/test/umask_sync.js
  46. +4 −0 test/node/node_modules/fs-extra/node_modules/ncp/.npmignore
  47. +6 −0 test/node/node_modules/fs-extra/node_modules/ncp/.travis.yml
  48. +21 −0 test/node/node_modules/fs-extra/node_modules/ncp/LICENSE.md
  49. +46 −0 test/node/node_modules/fs-extra/node_modules/ncp/README.md
  50. +48 −0 test/node/node_modules/fs-extra/node_modules/ncp/bin/ncp
  51. +216 −0 test/node/node_modules/fs-extra/node_modules/ncp/lib/ncp.js
  52. +37 −0 test/node/node_modules/fs-extra/node_modules/ncp/package.json
  53. +1 −0  test/node/node_modules/fs-extra/node_modules/ncp/test/fixtures/src/a
  54. +1 −0  test/node/node_modules/fs-extra/node_modules/ncp/test/fixtures/src/b
  55. 0  test/node/node_modules/fs-extra/node_modules/ncp/test/fixtures/src/c
  56. 0  test/node/node_modules/fs-extra/node_modules/ncp/test/fixtures/src/d
  57. 0  test/node/node_modules/fs-extra/node_modules/ncp/test/fixtures/src/e
  58. 0  test/node/node_modules/fs-extra/node_modules/ncp/test/fixtures/src/f
  59. +1 −0  test/node/node_modules/fs-extra/node_modules/ncp/test/fixtures/src/sub/a
  60. 0  test/node/node_modules/fs-extra/node_modules/ncp/test/fixtures/src/sub/b
  61. +74 −0 test/node/node_modules/fs-extra/node_modules/ncp/test/ncp-test.js
  62. +6 −0 test/node/node_modules/fs-extra/node_modules/rimraf/AUTHORS
  63. +23 −0 test/node/node_modules/fs-extra/node_modules/rimraf/LICENSE
  64. +21 −0 test/node/node_modules/fs-extra/node_modules/rimraf/README.md
  65. +1 −0  test/node/node_modules/fs-extra/node_modules/rimraf/node_modules/graceful-fs/.npmignore
  66. +23 −0 test/node/node_modules/fs-extra/node_modules/rimraf/node_modules/graceful-fs/LICENSE
  67. +5 −0 test/node/node_modules/fs-extra/node_modules/rimraf/node_modules/graceful-fs/README.md
  68. +316 −0 test/node/node_modules/fs-extra/node_modules/rimraf/node_modules/graceful-fs/graceful-fs.js
  69. +36 −0 test/node/node_modules/fs-extra/node_modules/rimraf/node_modules/graceful-fs/package.json
  70. +46 −0 test/node/node_modules/fs-extra/node_modules/rimraf/node_modules/graceful-fs/test/open.js
  71. +55 −0 test/node/node_modules/fs-extra/node_modules/rimraf/package.json
  72. +132 −0 test/node/node_modules/fs-extra/node_modules/rimraf/rimraf.js
  73. +10 −0 test/node/node_modules/fs-extra/node_modules/rimraf/test/run.sh
  74. +47 −0 test/node/node_modules/fs-extra/node_modules/rimraf/test/setup.sh
  75. +5 −0 test/node/node_modules/fs-extra/node_modules/rimraf/test/test-async.js
  76. +3 −0  test/node/node_modules/fs-extra/node_modules/rimraf/test/test-sync.js
  77. +63 −0 test/node/node_modules/fs-extra/package.json
  78. +85 −0 test/node/node_modules/fs-extra/test/copy.test.js
  79. +60 −0 test/node/node_modules/fs-extra/test/create.test.js
  80. +66 −0 test/node/node_modules/fs-extra/test/mkdir.test.js
  81. +4 −0 test/node/node_modules/fs-extra/test/mocha.opts
  82. +62 −0 test/node/node_modules/fs-extra/test/output.test.js
  83. +68 −0 test/node/node_modules/fs-extra/test/read.test.js
  84. +127 −0 test/node/node_modules/fs-extra/test/remove.test.js
  85. +7 −0 test/node/package.json
  86. +52 −9 test/spec/ExtensionInstallation-test.js
  87. +30 −0 test/spec/SpecRunnerUtils.js
View
3  Gruntfile.js
@@ -48,7 +48,8 @@ module.exports = function (grunt) {
'!test/spec/*-files/**/*.js',
'!test/smokes/**',
'!test/temp/**',
- '!test/thirdparty/**'
+ '!test/thirdparty/**',
+ '!test/**/node_modules/**/*.js'
],
grunt: [
'Gruntfile.js',
View
57 test/SpecRunner.js
@@ -50,6 +50,7 @@ define(function (require, exports, module) {
NativeFileSystem = require("file/NativeFileSystem").NativeFileSystem,
UrlParams = require("utils/UrlParams").UrlParams,
UnitTestReporter = require("test/UnitTestReporter").UnitTestReporter,
+ NodeConnection = require("utils/NodeConnection"),
BootstrapReporterView = require("test/BootstrapReporterView").BootstrapReporterView;
// Load modules that self-register and just need to get included in the main project
@@ -67,8 +68,17 @@ define(function (require, exports, module) {
var suite,
params = new UrlParams(),
reporter,
+ _nodeConnectionDeferred = new $.Deferred(),
reporterView;
+ /**
+ * @const
+ * Amount of time to wait before automatically rejecting the connection
+ * deferred. If we hit this timeout, we'll never have a node connection
+ * for the installer in this run of Brackets.
+ */
+ var NODE_CONNECTION_TIMEOUT = 30000; // 30 seconds - TODO: share with StaticServer?
+
params.parse();
function _loadExtensionTests(suite) {
@@ -157,6 +167,39 @@ define(function (require, exports, module) {
}
function init() {
+ // Start up the node connection, which is held in the
+ // _nodeConnectionDeferred module variable. (Use
+ // _nodeConnectionDeferred.done() to access it.
+
+ // This is in SpecRunner rather than SpecRunnerUtils because the hope
+ // is to hook up jasmine-node tests in this test runner.
+
+ // TODO: duplicates code from StaticServer
+ // TODO: can this be done lazily?
+
+ var connectionTimeout = setTimeout(function () {
+ console.error("[SpecRunner] Timed out while trying to connect to node");
+ _nodeConnectionDeferred.reject();
+ }, NODE_CONNECTION_TIMEOUT);
+
+ var _nodeConnection = new NodeConnection();
+ _nodeConnection.connect(true).then(function () {
+ var domainPath = FileUtils.getNativeBracketsDirectoryPath() + "/" + FileUtils.getNativeModuleDirectoryPath(module) + "/../test/node/TestingDomain";
+
+ _nodeConnection.loadDomains(domainPath, true)
+ .then(
+ function () {
+ clearTimeout(connectionTimeout);
+ _nodeConnectionDeferred.resolve(_nodeConnection);
+ },
+ function () { // Failed to connect
+ console.error("[SpecRunner] Failed to connect to node", arguments);
+ clearTimeout(connectionTimeout);
+ _nodeConnectionDeferred.reject();
+ }
+ );
+ });
+
suite = params.get("suite") || localStorage.getItem("SpecRunner.suite") || "UnitTestSuite";
// Create a top-level filter to show/hide performance and extensions tests
@@ -260,5 +303,19 @@ define(function (require, exports, module) {
});
}
+ /**
+ * Allows access to the deferred that manages the node connection for tests.
+ *
+ * @return {jQuery.Deferred} The deferred that manages the node connection
+ */
+ function getNodeConnectionDeferred() {
+ return _nodeConnectionDeferred;
+ }
+
+ // this is used by SpecRunnerUtils
+ brackets.testing = {
+ getNodeConnectionDeferred: getNodeConnectionDeferred
+ };
+
init();
});
View
54 test/node/TestingDomain.js
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+
+/*jslint vars: true, plusplus: true, devel: true, node: true, nomen: true,
+indent: 4, maxerr: 50 */
+
+"use strict";
+
+var fs = require("fs-extra");
+
+/**
+ * Initialize the "testing" domain.
+ * The testing domain provides utilities for tests.
+ */
+function init(domainManager) {
+ if (!domainManager.hasDomain("testing")) {
+ domainManager.registerDomain("testing", {major: 0, minor: 1});
+ }
+ domainManager.registerCommand(
+ "testing",
+ "remove",
+ fs.remove,
+ true,
+ "Remove the directory at the path",
+ [{
+ name: "path",
+ type: "string",
+ description: "path to the directory to remove"
+ }]
+ );
+}
+
+exports.init = init;
View
1  test/node/node_modules/fs-extra/.npmignore
@@ -0,0 +1 @@
+node_modules/
View
5 test/node/node_modules/fs-extra/.travis.yml
@@ -0,0 +1,5 @@
+language: node_js
+node_js:
+ - 0.6
+ - 0.8
+ - 0.9
View
67 test/node/node_modules/fs-extra/CHANGELOG.md
@@ -0,0 +1,67 @@
+0.5.0 / 2013-02-03
+------------------
+* Removed `readTextFile`.
+* Renamed `readJSONFile` to `readJSON` and `readJson`, same with write.
+* Restructured documentation a bit. Added roadmap.
+
+0.4.0 / 2013-01-28
+------------------
+* Set default spaces in `jsonfile` from 4 to 2.
+* Updated `testutil` deps for tests.
+* Renamed `touch()` to `createFile()`
+* Added `outputFile()` and `outputFileSync()`
+* Changed creation of testing diretories so the /tmp dir is not littered.
+* Added `readTextFile()` and `readTextFileSync()`.
+
+0.3.2 / 2012-11-01
+------------------
+* Added `touch()` and `touchSync()` methods.
+
+0.3.1 / 2012-10-11
+------------------
+* Fixed some stray globals.
+
+0.3.0 / 2012-10-09
+------------------
+* Removed all CoffeeScript from tests.
+* Renamed `mkdir` to `mkdirs`/`mkdirp`.
+
+0.2.1 / 2012-09-11
+------------------
+* Updated `rimraf` dep.
+
+0.2.0 / 2012-09-10
+------------------
+* Rewrote module into JavaScript. (Must still rewrite tests into JavaScript)
+* Added all methods of [jsonfile][https://github.com/jprichardson/node-jsonfile]
+* Added Travis-CI.
+
+0.1.3 / 2012-08-13
+------------------
+* Added method `readJSONFile`.
+
+0.1.2 / 2012-06-15
+------------------
+* Bug fix: `deleteSync()` didn't exist.
+* Verified Node v0.8 compatibility.
+
+0.1.1 / 2012-06-15
+------------------
+* Fixed bug in `remove()`/`delete()` that wouldn't execute the function if a callback wasn't passed.
+
+0.1.0 / 2012-05-31
+------------------
+* Renamed `copyFile()` to `copy()`. `copy()` can now copy directories (recursively) too.
+* Renamed `rmrf()` to `remove()`.
+* `remove()` aliased with `delete()`.
+* Added `mkdirp` capabilities. Named: `mkdir()`. Hides Node.js native `mkdir()`.
+* Instead of exporting the native `fs` module with new functions, I now copy over the native methods to a new object and export that instead.
+
+0.0.4 / 2012-03-14
+------------------
+* Removed CoffeeScript dependency
+
+0.0.3 / 2012-01-11
+------------------
+* Added methods rmrf and rmrfSync
+* Moved tests from Jasmine to Mocha
View
16 test/node/node_modules/fs-extra/LICENSE
@@ -0,0 +1,16 @@
+
+(The MIT License)
+
+Copyright (c) 2011 JP Richardson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
+(the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
281 test/node/node_modules/fs-extra/README.md
@@ -0,0 +1,281 @@
+[![build status](https://secure.travis-ci.org/jprichardson/node-fs-extra.png)](http://travis-ci.org/jprichardson/node-fs-extra)
+
+Node.js: fs-extra
+=================
+
+This module adds a few extra file system methods that aren't included in the native `fs` module. It is a drop in replacement for `fs`.
+
+
+
+Why?
+----
+
+I got tired of including `mkdirp`, `rimraf`, and `cp -r` in most of my projects.
+
+
+
+
+Installation
+------------
+
+ npm install fs-extra
+
+
+
+Usage
+-----
+
+```javascript
+var fs = require('fs-extra');
+```
+
+
+
+Methods
+-------
+
+**NOTE:** You can still use the native Node.js methods. They are copied over to `fs-extra`.
+
+
+### copy(src, dest, callback)
+
+Copy a file or directory. The directory can have contents. Like `cp -r`. There isn't a synchronous version implemented yet.
+
+Sync: (none)
+
+
+Examples:
+
+```javascript
+var fs = require('fs-extra');
+
+fs.copy('/tmp/myfile', '/tmp/mynewfile', function(err){
+ if (err) {
+ console.error(err);
+ }
+ else {
+ console.log("success!")
+ }
+}); //copies file
+
+fs.copy('/tmp/mydir', '/tmp/mynewdir', function(err){
+ if (err) {
+ console.error(err);
+ }
+ else {
+ console.log("success!")
+ }
+}); //copies directory, even if it has subdirectories or files
+```
+
+
+### createFile(file, callback)
+
+Creates a file. If the file that is requested to be created is in directories that do not exist, these directories are created. If the file already exists, it is **NOT MODIFIED**.
+
+Sync: `createFileSync()`
+
+
+Example:
+
+```javascript
+var fs = require('fs-extra')
+ , file = '/tmp/this/path/does/not/exist/file.txt'
+
+fs.createFile(file, function(err) {
+ console.log(err); //null
+
+ //file has now been created, including the directory it is to be placed in
+})
+```
+
+
+### exists() / existsSync()
+
+These methods are actually from `path` in v0.6. But in Node v0.8 they are moved from `path` to `fs`. So you can use this module to help make your modules v0.6 and v0.8 compatible.
+
+
+
+### mkdirs(dir, callback)
+
+Creates a directory. If the parent hierarchy doesn't exist, it's created. Like `mkdir -p`.
+
+Alias: `mkdirp()`
+
+Sync: `mkdirsSync()` / `mkdirpSync()`
+
+
+Examples:
+
+```javascript
+var fs = require('fs-extra');
+
+fs.mkdirs('/tmp/some/long/path/that/prob/doesnt/exist', function(err){
+ if (err) {
+ console.error(err);
+ }
+ else {
+ console.log("success!")
+ }
+});
+
+fs.mkdirsSync('/tmp/another/path');
+```
+
+
+### outputFile(file, data, callback)
+
+Almost the same as `writeFile`, except that if the directory does not exist, it's created.
+
+Sync: `outputFileSync()`
+
+
+Example:
+
+```javascript
+var fs = require('fs-extra')
+ , file = '/tmp/this/path/does/not/exist/file.txt'
+
+fs.outputFile(file, 'hello!' function(err) {
+ console.log(err); //null
+
+ fs.readFile(file, 'utf8', function(err, data) {
+ console.log(data); //hello!
+ })
+})
+```
+
+
+### readJson(file, callback)
+
+Reads a JSON file and then parses it into an object.
+
+Alias: `readJSON()`
+
+Sync: `readJsonSync()`, `readJSONSync()`
+
+
+Example:
+
+```javascript
+var fs = require('fs-extra');
+
+fs.readJson('./package.json', function(err, packageObj) {
+ console.log(packageObj.version); //0.1.3
+});
+```
+
+
+### remove(dir, callback)
+
+Removes a file or directory. The directory can have contents. Like `rm -rf`.
+
+Alias: `delete()`
+
+Sync: `removeSync()` / `deleteSync()`
+
+
+Examples:
+
+```javascript
+var fs = require('fs-extra');
+
+fs.remove('/tmp/myfile', function(err){
+ if (err) {
+ console.error(err);
+ }
+ else {
+ console.log("success!")
+ }
+});
+
+fs.removeSync('/home/jprichardson'); //I just deleted my entire HOME directory.
+```
+
+
+
+### writeJson(file, object, callback)
+
+Writes an object to a JSON file.
+
+Alias: `writeJSON()`
+
+Sync: `writeJsonSync()`, `writeJSONSync()`
+
+Example:
+
+```javascript
+var fs = require('fs-extra');
+fs.writeJson('./package.json', {name: 'fs-extra'}, function(err){
+ console.log(err);
+});
+```
+
+
+
+Roadmap
+-------
+
+This contains items that I'm considering doing. I'd love community feedback.
+
+* File system walker. I really like this one: https://github.com/daaku/nodejs-walker
+* File/directory tree watcher. There are quite a few.
+* Method to move files.
+* Copy sync.
+* Thinking about moving `rimraf`, `ncp`, and `mkdirps` code into this library. I'd like fs-extra to be a stable library that module authors
+can depend upon. A bunch of other dependencies kinda sucks for modules/libraries.
+* Change documentation to use the `fse` prefix instead of `fs`. This may encourage people to start using `fse` as a prefix and hence make their code clearer that they're not using the native `fs`. I'm very undecided on this one since `fs-extra` is a drop in replacement for the native `fs`.
+
+
+
+Naming
+------
+
+I put a lot of thought into the naming of these function. Inspired by @coolaj86's request. So he deserves much of the credit for raising the issue. See discussion(s) here:
+
+* https://github.com/jprichardson/node-fs-extra/issues/2
+* https://github.com/flatiron/utile/issues/11
+* https://github.com/ryanmcgrath/wrench-js/issues/29
+* https://github.com/substack/node-mkdirp/issues/17
+
+First, I believe that in as many cases as possible, the [Node.js naming schemes](http://nodejs.org/api/fs.html) should be chosen. However, there are problems with the Node.js own naming schemes.
+
+For example, `fs.readFile()` and `fs.readdir()`: the **F** is capitalized in *File* and the **d** is not capitalized in *dir*. Perhaps a bit pedantic, but they should still be consistent. Also, Node.js has chosen a lot of POSIX naming schemes, which I believe is great. See: `fs.mkdir()`, `fs.rmdir()`, `fs.chown()`, etc.
+
+We have a dilemma though. How do you consistently name methods that perform the following POSIX commands: `cp`, `cp -r`, `mkdir -p`, and `rm -rf`?
+
+My perspective: when in doubt, err on the side of simplicity. Consider that for a moment. A directory is just a hierarchical grouping of directories and files. So when you want to copy it or remove it, in most cases you'll want to copy or remove all of its contents. When you want to create a directory, if the directory that it's suppose to be contained in does not exist, then in most cases you'll want to create that too.
+
+So, if you want to remove a file or a directory regardless of whether it has contents, just call `fs.remove(path)` or its alias `fs.delete(path)`. If you want to copy a file or a directory whether it has contents, just call `fs.copy(source, destination)`. If you want to create a directory regardless of whether its parent directories exist, just call `fs.mkdirs(path)` or `fs.mkdirp(path)`.
+
+
+
+Author
+------
+
+`node-fs-extra` was written by [JP Richardson][aboutjp]. You should follow him on Twitter [@jprichardson][twitter]. Also read his coding blog [Procbits][procbits]. If you write software with others, you should checkout [Gitpilot][gitpilot] to make collaboration with Git simple.
+
+
+
+
+License
+-------
+
+
+Licensed under MIT
+
+Copyright (c) 2011-2013 JP Richardson
+
+[1]: http://nodejs.org/docs/latest/api/fs.html
+
+
+[jsonfile]: https://github.com/jprichardson/node-jsonfile
+
+
+[aboutjp]: http://about.me/jprichardson
+[twitter]: http://twitter.com/jprichardson
+[procbits]: http://procbits.com
+[gitpilot]: http://gitpilot.com
+
+
+
View
42 test/node/node_modules/fs-extra/lib/copy.js
@@ -0,0 +1,42 @@
+var fs = require('fs')
+ , ncp = require('ncp').ncp;
+
+var BUF_LENGTH = 64 * 1024;
+var _buff = new Buffer(BUF_LENGTH);
+
+var copyFileSync = function(srcFile, destFile) {
+ var bytesRead, fdr, fdw, pos;
+ fdr = fs.openSync(srcFile, 'r');
+ fdw = fs.openSync(destFile, 'w');
+ bytesRead = 1;
+ pos = 0;
+ while (bytesRead > 0) {
+ bytesRead = fs.readSync(fdr, _buff, 0, BUF_LENGTH, pos);
+ fs.writeSync(fdw, _buff, 0, bytesRead);
+ pos += bytesRead;
+ }
+ fs.closeSync(fdr);
+ return fs.closeSync(fdw);
+};
+
+var copyFile = function(srcFile, destFile, cb) {
+ var fdr, fdw;
+ fdr = fs.createReadStream(srcFile);
+ fdw = fs.createWriteStream(destFile);
+ fdr.on('end', function() {
+ return cb(null);
+ });
+ return fdr.pipe(fdw);
+};
+
+function copy(source, dest, callback) {
+ if (callback)
+ ncp(source, dest, callback);
+ else
+ ncp(source, dest, function(){});
+};
+
+
+module.exports.copyFileSync = copyFileSync;
+module.exports.copyFile = copyFile;
+module.exports.copy = copy;
View
53 test/node/node_modules/fs-extra/lib/create.js
@@ -0,0 +1,53 @@
+var mkdir = require('./mkdir')
+ , path = require('path')
+ , fs = require('fs')
+ , exists = fs.exists || path.exists
+ , existsSync = fs.existsSync || path.existsSync
+
+function createFile (file, callback) {
+ exists(file, function(fileExists) {
+ if (fileExists)
+ return callback(null);
+ else {
+ var dir = path.dirname(file);
+
+ function makeFile() {
+ fs.writeFile(file, '', function(err) {
+ if (err)
+ callback(err)
+ else
+ callback(null);
+ })
+ }
+
+ exists(dir, function(dirExists) {
+ if (!dirExists) {
+ mkdir.mkdirs(dir, function(err) {
+ if (err)
+ callback(err)
+ else
+ makeFile();
+ })
+ } else {
+ makeFile();
+ }
+ })
+ }
+ })
+}
+
+
+function createFileSync (file) {
+ if (existsSync(file))
+ return;
+
+ var dir = path.dirname(file);
+ if (!existsSync(dir))
+ mkdir.mkdirsSync(dir);
+
+ fs.writeFileSync(file, '');
+}
+
+
+module.exports.createFile = createFile;
+module.exports.createFileSync = createFileSync;
View
102 test/node/node_modules/fs-extra/lib/index.js
@@ -0,0 +1,102 @@
+var fs = require('fs')
+ , path = require('path')
+ , jsonFile = require('jsonfile')
+ , fse = {};
+
+for (var funcName in fs) {
+ var func = fs[funcName];
+ if (fs.hasOwnProperty(funcName)) {
+ if (typeof func == 'function')
+ fse[funcName] = func;
+ }
+}
+
+fs = fse;
+
+// copy
+
+fs.copy = require('./copy').copy;
+
+// remove
+
+var remove = require('./remove');
+fs.remove = remove.remove;
+fs.removeSync = remove.removeSync;
+fs['delete'] = fs.remove
+fs.deleteSync = fs.removeSync
+
+// mkdir
+
+var mkdir = require('./mkdir')
+fs.mkdirs = mkdir.mkdirs
+fs.mkdirsSync = mkdir.mkdirsSync
+fs.mkdirp = mkdir.mkdirs
+fs.mkdirpSync = mkdir.mkdirsSync
+
+// create
+
+var create = require('./create')
+fs.createFile = create.createFile;
+fs.createFileSync = create.createFileSync;
+
+//deprecated
+fs.touch = function touch() {
+ console.log('fs.touch() is deprecated. Please use fs.createFile().')
+ fs.createFile.apply(null, arguments)
+}
+
+fs.touchSync = function touchSync() {
+ console.log('fs.touchSync() is deprecated. Please use fs.createFileSync().')
+ fs.createFileSync.apply(null, arguments)
+}
+
+// output
+
+var output = require('./output');
+fs.outputFile = output.outputFile;
+fs.outputFileSync = output.outputFileSync;
+
+// read
+
+/*fs.readTextFile = function(file, callback) {
+ return fs.readFile(file, 'utf8', callback)
+}
+
+fs.readTextFileSync = function(file, callback) {
+ return fs.readFileSync(file, 'utf8')
+}*/
+
+// json files
+
+fs.readJsonFile = jsonFile.readFile;
+fs.readJSONFile = jsonFile.readFile;
+fs.readJsonFileSync = jsonFile.readFileSync;
+fs.readJSONFileSync = jsonFile.readFileSync;
+
+fs.readJson = jsonFile.readFile;
+fs.readJSON = jsonFile.readFile;
+fs.readJsonSync = jsonFile.readFileSync;
+fs.readJSONSync = jsonFile.readFileSync;
+
+fs.writeJsonFile = jsonFile.writeFile;
+fs.writeJSONFile = jsonFile.writeFile;
+fs.writeJsonFileSync = jsonFile.writeFileSync;
+fs.writeJSONFileSync = jsonFile.writeFileSync;
+
+fs.writeJson = jsonFile.writeFile;
+fs.writeJSON = jsonFile.writeFile;
+fs.writeJsonSync = jsonFile.writeFileSync;
+fs.writeJSONSync = jsonFile.writeFileSync;
+
+
+//make compatible for Node v0.8
+if (typeof fs.exists == 'undefined')
+ fs.exists = path.exists
+if (typeof fs.existsSync == 'undefined')
+ fs.existsSync = path.existsSync
+
+module.exports = fs
+
+jsonFile.spaces = 2; //set to 2
+module.exports.jsonfile = jsonFile; //so users of fs-extra can modify jsonFile.spaces;
+
View
6 test/node/node_modules/fs-extra/lib/mkdir.js
@@ -0,0 +1,6 @@
+var mkdirp = require('mkdirp');
+
+module.exports.mkdirs = mkdirp;
+module.exports.mkdirsSync = mkdirp.sync;
+
+
View
35 test/node/node_modules/fs-extra/lib/output.js
@@ -0,0 +1,35 @@
+var mkdir = require('./mkdir')
+ , path = require('path')
+ , fs = require('fs')
+ , exists = fs.exists || path.exists
+ , existsSync = fs.existsSync || path.existsSync
+
+function outputFile (file, data, encoding, callback) {
+ if (typeof encoding === 'function') {
+ callback = encoding
+ encoding = 'utf8'
+ }
+
+ var dir = path.dirname(file)
+ exists(dir, function(itDoes) {
+ if (itDoes) return fs.writeFile(file, data, encoding, callback)
+
+ mkdir.mkdirs(dir, function(err) {
+ if (err) return callback(err)
+
+ fs.writeFile(file, data, encoding, callback)
+ })
+ })
+}
+
+
+function outputFileSync (file, data, encoding) {
+ var dir = path.dirname(file)
+ if (existsSync(dir)) return fs.writeFileSync.apply(fs, arguments)
+ mkdir.mkdirsSync(dir)
+ fs.writeFileSync.apply(fs, arguments)
+}
+
+
+module.exports.outputFile = outputFile;
+module.exports.outputFileSync = outputFileSync;
View
17 test/node/node_modules/fs-extra/lib/remove.js
@@ -0,0 +1,17 @@
+var rimraf = require('rimraf')
+ , fs = require('fs');
+
+function rmrfSync(dir) {
+ return rimraf.sync(dir);
+}
+
+function rmrf(dir, cb) {
+ if (cb != null) {
+ return rimraf(dir, cb);
+ } else {
+ return rimraf(dir, (function() {}));
+ }
+}
+
+module.exports.remove = rmrf;
+module.exports.removeSync = rmrfSync;
View
1  test/node/node_modules/fs-extra/node_modules/.bin/ncp
View
1  test/node/node_modules/fs-extra/node_modules/jsonfile/.npmignore
@@ -0,0 +1 @@
+node_modules/
View
4 test/node/node_modules/fs-extra/node_modules/jsonfile/.travis.yml
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+ - 0.6
+ - 0.8
View
3  test/node/node_modules/fs-extra/node_modules/jsonfile/CHANGELOG.md
@@ -0,0 +1,3 @@
+0.0.1 / 2012-09-10
+------------------
+* Initial release.
View
15 test/node/node_modules/fs-extra/node_modules/jsonfile/LICENSE
@@ -0,0 +1,15 @@
+(The MIT License)
+
+Copyright (c) 2012, JP Richardson <jprichardson@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
+(the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
116 test/node/node_modules/fs-extra/node_modules/jsonfile/README.md
@@ -0,0 +1,116 @@
+[![build status](https://secure.travis-ci.org/jprichardson/node-jsonfile.png)](http://travis-ci.org/jprichardson/node-jsonfile)
+
+Node.js - jsonfile
+================
+
+Easily read/write JSON files.
+
+
+Why?
+----
+
+Writing `JSON.stringify()` and then `fs.writeFile()` and `JSON.parse()` with `fs.readFile()` enclosed in `try/catch` blocks became annoying.
+
+
+
+Installation
+------------
+
+ npm install jsonfile
+
+
+
+API
+---
+
+### readFile()
+
+```javascript
+var jf = require('jsonfile')
+ , util = require('util');
+
+var file = '/tmp/data.json';
+js.readFile(file, function(err, obj) {
+ console.log(util.inspect(obj));
+});
+```
+
+
+### readFileSync()
+
+```javascript
+var jf = require('jsonfile')
+ , util = require('util');
+
+var file = '/tmp/data.json';
+
+console.log(util.inspect(jf.readFileSync(file)));
+```
+
+
+### writeFile()
+
+```javascript
+var jf = require('jsonfile')
+
+var file = '/tmp/data.json';
+var obj = {name: 'JP'};
+
+jf.writeFile(file, obj, function(err) {
+ console.log(err);
+})
+```
+
+### writeFileSync()
+
+```javascript
+var jf = require('jsonfile')
+
+var file = '/tmp/data.json';
+var obj = {name: 'JP'};
+
+jf.writeFileSync(file, obj);
+```
+
+
+### spaces
+
+Number of spaces to indent JSON files.
+
+**default:** 4
+
+```
+var jf = require('jsonfile');
+
+jf.spaces = 2;
+
+var file = '/tmp/data.json';
+var obj = {name: 'JP'};
+
+jf.writeFile(file, obj, function(err) { //json file has two space indenting now
+ console.log(err);
+});
+```
+
+
+Author
+------
+
+`node-jsonfile` was written by [JP Richardson][aboutjp]. You should follow him on Twitter [@jprichardson][twitter]. Also read his coding blog [Procbits][procbits]. If you write software with others, you should checkout [Gitpilot][gitpilot] to make collaboration with Git simple.
+
+
+
+License
+-------
+
+(MIT License)
+
+Copyright 2012, JP Richardson <jprichardson@gmail.com>
+
+
+[aboutjp]: http://about.me/jprichardson
+[twitter]: http://twitter.com/jprichardson
+[procbits]: http://procbits.com
+[gitpilot]: http://gitpilot.com
+
+
View
44 test/node/node_modules/fs-extra/node_modules/jsonfile/lib/jsonfile.js
@@ -0,0 +1,44 @@
+var fs = require('fs');
+
+module.exports.spaces = 4;
+
+function readFile(file, callback) {
+ fs.readFile(file, 'utf8', function(err, data) {
+ if (err) {
+ callback(err, null);
+ } else {
+ try {
+ var obj = JSON.parse(data);
+ callback(null, obj);
+ } catch (err2) {
+ callback(err2, null);
+ }
+ }
+ })
+}
+
+function readFileSync(file) {
+ var data = fs.readFileSync(file, 'utf8');
+ return JSON.parse(data);
+}
+
+function writeFile(file, obj, callback) {
+ var str = '';
+ try {
+ str = JSON.stringify(obj, null, module.exports.spaces);
+ } catch (err) {
+ callback(err, null);
+ }
+ fs.writeFile(file, str, callback);
+}
+
+function writeFileSync(file, obj) {
+ var str = JSON.stringify(obj, null, module.exports.spaces);
+ return fs.writeFileSync(file, str); //not sure if fs.writeFileSync returns anything, but just in case
+}
+
+
+module.exports.readFile = readFile;
+module.exports.readFileSync = readFileSync;
+module.exports.writeFile = writeFile;
+module.exports.writeFileSync = writeFileSync;
View
37 test/node/node_modules/fs-extra/node_modules/jsonfile/package.json
@@ -0,0 +1,37 @@
+{
+ "name": "jsonfile",
+ "version": "0.0.1",
+ "description": "Easily read/write JSON files.",
+ "homepage": [
+ ""
+ ],
+ "repository": {
+ "type": "git",
+ "url": "git@github.com:jprichardson/node-jsonfile.git"
+ },
+ "keywords": [],
+ "author": {
+ "name": "JP Richardson",
+ "email": "jprichardson@gmail.com"
+ },
+ "licenses": [
+ {
+ "type": "MIT",
+ "url": ""
+ }
+ ],
+ "dependencies": {},
+ "devDependencies": {
+ "mkdirp": "~0.3.4",
+ "testutil": "~0.2.2",
+ "mocha": "~1.4.2"
+ },
+ "main": "./lib/jsonfile.js",
+ "scripts": {
+ "test": "mocha test"
+ },
+ "readme": "[![build status](https://secure.travis-ci.org/jprichardson/node-jsonfile.png)](http://travis-ci.org/jprichardson/node-jsonfile)\n\nNode.js - jsonfile\n================\n\nEasily read/write JSON files. \n\n\nWhy?\n----\n\nWriting `JSON.stringify()` and then `fs.writeFile()` and `JSON.parse()` with `fs.readFile()` enclosed in `try/catch` blocks became annoying.\n\n\n\nInstallation\n------------\n\n npm install jsonfile\n\n\n\nAPI\n---\n\n### readFile()\n\n```javascript\nvar jf = require('jsonfile')\n , util = require('util');\n\nvar file = '/tmp/data.json';\njs.readFile(file, function(err, obj) {\n console.log(util.inspect(obj)); \n});\n```\n\n\n### readFileSync()\n\n```javascript\nvar jf = require('jsonfile')\n , util = require('util');\n\nvar file = '/tmp/data.json';\n\nconsole.log(util.inspect(jf.readFileSync(file)));\n```\n\n\n### writeFile()\n\n```javascript\nvar jf = require('jsonfile')\n\nvar file = '/tmp/data.json';\nvar obj = {name: 'JP'};\n\njf.writeFile(file, obj, function(err) {\n console.log(err);\n})\n```\n\n### writeFileSync()\n\n```javascript\nvar jf = require('jsonfile')\n\nvar file = '/tmp/data.json';\nvar obj = {name: 'JP'};\n\njf.writeFileSync(file, obj);\n```\n\n\n### spaces\n\nNumber of spaces to indent JSON files. \n\n**default:** 4\n\n```\nvar jf = require('jsonfile');\n\njf.spaces = 2;\n\nvar file = '/tmp/data.json';\nvar obj = {name: 'JP'};\n\njf.writeFile(file, obj, function(err) { //json file has two space indenting now\n console.log(err);\n});\n```\n\n\nAuthor\n------\n\n`node-jsonfile` was written by [JP Richardson][aboutjp]. You should follow him on Twitter [@jprichardson][twitter]. Also read his coding blog [Procbits][procbits]. If you write software with others, you should checkout [Gitpilot][gitpilot] to make collaboration with Git simple.\n\n\n\nLicense\n-------\n\n(MIT License)\n\nCopyright 2012, JP Richardson <jprichardson@gmail.com>\n\n\n[aboutjp]: http://about.me/jprichardson\n[twitter]: http://twitter.com/jprichardson\n[procbits]: http://procbits.com\n[gitpilot]: http://gitpilot.com\n\n\n",
+ "readmeFilename": "README.md",
+ "_id": "jsonfile@0.0.1",
+ "_from": "jsonfile@0.0.x"
+}
View
66 test/node/node_modules/fs-extra/node_modules/jsonfile/test/jsonfile.test.js
@@ -0,0 +1,66 @@
+var testutil = require('testutil')
+ , mkdirp = require('mkdirp')
+ , jf = require('../lib/jsonfile')
+ , fs = require('fs')
+ , path = require('path');
+
+TEST_DIR = ''
+
+beforeEach(function(done) {
+ TEST_DIR = testutil.generateTestPath('test-jsonfile');
+ mkdirp(TEST_DIR, done);
+})
+
+suite('jsonfile');
+
+test('- readFile()', function(done) {
+ var file = path.join(TEST_DIR, 'somefile.json');
+ var obj = {name: 'JP'}
+ fs.writeFileSync(file, JSON.stringify(obj));
+
+ jf.readFile(file, function(err, obj2) {
+ F (err)
+ T (obj2.name === obj.name)
+ done();
+ });
+})
+
+test('- writeFile()', function(done) {
+ var file = path.join(TEST_DIR, 'somefile2.json');
+ var obj = {name: 'JP'};
+
+ jf.writeFile(file, obj, function(err) {
+ F (err)
+ fs.readFile(file, 'utf8', function(err,data) {
+ var obj2 = JSON.parse(data);
+ T (obj2.name === obj.name)
+ done();
+ });
+ })
+})
+
+test('- readFileSync()', function(done) {
+ var file = path.join(TEST_DIR, 'somefile3.json');
+ var obj = {name: 'JP'}
+ fs.writeFileSync(file, JSON.stringify(obj));
+
+ try {
+ var obj2 = jf.readFileSync(file);
+ T (obj2.name === obj.name);
+ done();
+ } catch (err) {
+ done(err);
+ }
+})
+
+test('- writeFileSync()', function(done) {
+ var file = path.join(TEST_DIR, 'somefile4.json');
+ var obj = {name: 'JP'};
+
+ jf.writeFileSync(file, obj);
+
+ var obj2 = JSON.parse(fs.readFileSync(file, 'utf8'));
+ T (obj2.name === obj.name);
+ done();
+})
+
View
3  test/node/node_modules/fs-extra/node_modules/jsonfile/test/mocha.opts
@@ -0,0 +1,3 @@
+--reporter spec
+--ui qunit
+--timeout 2000
View
0  test/node/node_modules/fs-extra/node_modules/jsonfile/test/resources/.gitkeep
No changes.
View
2  test/node/node_modules/fs-extra/node_modules/mkdirp/.npmignore
@@ -0,0 +1,2 @@
+node_modules/
+npm-debug.log
View
5 test/node/node_modules/fs-extra/node_modules/mkdirp/.travis.yml
@@ -0,0 +1,5 @@
+language: node_js
+node_js:
+ - 0.6
+ - 0.8
+ - 0.9
View
21 test/node/node_modules/fs-extra/node_modules/mkdirp/LICENSE
@@ -0,0 +1,21 @@
+Copyright 2010 James Halliday (mail@substack.net)
+
+This project is free software released under the MIT/X11 license:
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
View
6 test/node/node_modules/fs-extra/node_modules/mkdirp/examples/pow.js
@@ -0,0 +1,6 @@
+var mkdirp = require('mkdirp');
+
+mkdirp('/tmp/foo/bar/baz', function (err) {
+ if (err) console.error(err)
+ else console.log('pow!')
+});
View
82 test/node/node_modules/fs-extra/node_modules/mkdirp/index.js
@@ -0,0 +1,82 @@
+var path = require('path');
+var fs = require('fs');
+
+module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP;
+
+function mkdirP (p, mode, f, made) {
+ if (typeof mode === 'function' || mode === undefined) {
+ f = mode;
+ mode = 0777 & (~process.umask());
+ }
+ if (!made) made = null;
+
+ var cb = f || function () {};
+ if (typeof mode === 'string') mode = parseInt(mode, 8);
+ p = path.resolve(p);
+
+ fs.mkdir(p, mode, function (er) {
+ if (!er) {
+ made = made || p;
+ return cb(null, made);
+ }
+ switch (er.code) {
+ case 'ENOENT':
+ mkdirP(path.dirname(p), mode, function (er, made) {
+ if (er) cb(er, made);
+ else mkdirP(p, mode, cb, made);
+ });
+ break;
+
+ // In the case of any other error, just see if there's a dir
+ // there already. If so, then hooray! If not, then something
+ // is borked.
+ default:
+ fs.stat(p, function (er2, stat) {
+ // if the stat fails, then that's super weird.
+ // let the original error be the failure reason.
+ if (er2 || !stat.isDirectory()) cb(er, made)
+ else cb(null, made);
+ });
+ break;
+ }
+ });
+}
+
+mkdirP.sync = function sync (p, mode, made) {
+ if (mode === undefined) {
+ mode = 0777 & (~process.umask());
+ }
+ if (!made) made = null;
+
+ if (typeof mode === 'string') mode = parseInt(mode, 8);
+ p = path.resolve(p);
+
+ try {
+ fs.mkdirSync(p, mode);
+ made = made || p;
+ }
+ catch (err0) {
+ switch (err0.code) {
+ case 'ENOENT' :
+ made = sync(path.dirname(p), mode, made);
+ sync(p, mode, made);
+ break;
+
+ // In the case of any other error, just see if there's a dir
+ // there already. If so, then hooray! If not, then something
+ // is borked.
+ default:
+ var stat;
+ try {
+ stat = fs.statSync(p);
+ }
+ catch (err1) {
+ throw err0;
+ }
+ if (!stat.isDirectory()) throw err0;
+ break;
+ }
+ }
+
+ return made;
+};
View
30 test/node/node_modules/fs-extra/node_modules/mkdirp/package.json
@@ -0,0 +1,30 @@
+{
+ "name": "mkdirp",
+ "description": "Recursively mkdir, like `mkdir -p`",
+ "version": "0.3.5",
+ "author": {
+ "name": "James Halliday",
+ "email": "mail@substack.net",
+ "url": "http://substack.net"
+ },
+ "main": "./index",
+ "keywords": [
+ "mkdir",
+ "directory"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "http://github.com/substack/node-mkdirp.git"
+ },
+ "scripts": {
+ "test": "tap test/*.js"
+ },
+ "devDependencies": {
+ "tap": "~0.4.0"
+ },
+ "license": "MIT",
+ "readme": "# mkdirp\n\nLike `mkdir -p`, but in node.js!\n\n[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)\n\n# example\n\n## pow.js\n\n```js\nvar mkdirp = require('mkdirp');\n \nmkdirp('/tmp/foo/bar/baz', function (err) {\n if (err) console.error(err)\n else console.log('pow!')\n});\n```\n\nOutput\n\n```\npow!\n```\n\nAnd now /tmp/foo/bar/baz exists, huzzah!\n\n# methods\n\n```js\nvar mkdirp = require('mkdirp');\n```\n\n## mkdirp(dir, mode, cb)\n\nCreate a new directory and any necessary subdirectories at `dir` with octal\npermission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\n`cb(err, made)` fires with the error or the first directory `made`\nthat had to be created, if any.\n\n## mkdirp.sync(dir, mode)\n\nSynchronously create a new directory and any necessary subdirectories at `dir`\nwith octal permission string `mode`.\n\nIf `mode` isn't specified, it defaults to `0777 & (~process.umask())`.\n\nReturns the first directory that had to be created, if any.\n\n# install\n\nWith [npm](http://npmjs.org) do:\n\n```\nnpm install mkdirp\n```\n\n# license\n\nMIT\n",
+ "readmeFilename": "readme.markdown",
+ "_id": "mkdirp@0.3.5",
+ "_from": "mkdirp@0.3.x"
+}
View
63 test/node/node_modules/fs-extra/node_modules/mkdirp/readme.markdown
@@ -0,0 +1,63 @@
+# mkdirp
+
+Like `mkdir -p`, but in node.js!
+
+[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)
+
+# example
+
+## pow.js
+
+```js
+var mkdirp = require('mkdirp');
+
+mkdirp('/tmp/foo/bar/baz', function (err) {
+ if (err) console.error(err)
+ else console.log('pow!')
+});
+```
+
+Output
+
+```
+pow!
+```
+
+And now /tmp/foo/bar/baz exists, huzzah!
+
+# methods
+
+```js
+var mkdirp = require('mkdirp');
+```
+
+## mkdirp(dir, mode, cb)
+
+Create a new directory and any necessary subdirectories at `dir` with octal
+permission string `mode`.
+
+If `mode` isn't specified, it defaults to `0777 & (~process.umask())`.
+
+`cb(err, made)` fires with the error or the first directory `made`
+that had to be created, if any.
+
+## mkdirp.sync(dir, mode)
+
+Synchronously create a new directory and any necessary subdirectories at `dir`
+with octal permission string `mode`.
+
+If `mode` isn't specified, it defaults to `0777 & (~process.umask())`.
+
+Returns the first directory that had to be created, if any.
+
+# install
+
+With [npm](http://npmjs.org) do:
+
+```
+npm install mkdirp
+```
+
+# license
+
+MIT
View
38 test/node/node_modules/fs-extra/node_modules/mkdirp/test/chmod.js
@@ -0,0 +1,38 @@
+var mkdirp = require('../').mkdirp;
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+var ps = [ '', 'tmp' ];
+
+for (var i = 0; i < 25; i++) {
+ var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ ps.push(dir);
+}
+
+var file = ps.join('/');
+
+test('chmod-pre', function (t) {
+ var mode = 0744
+ mkdirp(file, mode, function (er) {
+ t.ifError(er, 'should not error');
+ fs.stat(file, function (er, stat) {
+ t.ifError(er, 'should exist');
+ t.ok(stat && stat.isDirectory(), 'should be directory');
+ t.equal(stat && stat.mode & 0777, mode, 'should be 0744');
+ t.end();
+ });
+ });
+});
+
+test('chmod', function (t) {
+ var mode = 0755
+ mkdirp(file, mode, function (er) {
+ t.ifError(er, 'should not error');
+ fs.stat(file, function (er, stat) {
+ t.ifError(er, 'should exist');
+ t.ok(stat && stat.isDirectory(), 'should be directory');
+ t.end();
+ });
+ });
+});
View
37 test/node/node_modules/fs-extra/node_modules/mkdirp/test/clobber.js
@@ -0,0 +1,37 @@
+var mkdirp = require('../').mkdirp;
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+var ps = [ '', 'tmp' ];
+
+for (var i = 0; i < 25; i++) {
+ var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ ps.push(dir);
+}
+
+var file = ps.join('/');
+
+// a file in the way
+var itw = ps.slice(0, 3).join('/');
+
+
+test('clobber-pre', function (t) {
+ console.error("about to write to "+itw)
+ fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.');
+
+ fs.stat(itw, function (er, stat) {
+ t.ifError(er)
+ t.ok(stat && stat.isFile(), 'should be file')
+ t.end()
+ })
+})
+
+test('clobber', function (t) {
+ t.plan(2);
+ mkdirp(file, 0755, function (err) {
+ t.ok(err);
+ t.equal(err.code, 'ENOTDIR');
+ t.end();
+ });
+});
View
28 test/node/node_modules/fs-extra/node_modules/mkdirp/test/mkdirp.js
@@ -0,0 +1,28 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('woo', function (t) {
+ t.plan(2);
+ var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+
+ var file = '/tmp/' + [x,y,z].join('/');
+
+ mkdirp(file, 0755, function (err) {
+ if (err) t.fail(err);
+ else path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.equal(stat.mode & 0777, 0755);
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ })
+ })
+ });
+});
View
32 test/node/node_modules/fs-extra/node_modules/mkdirp/test/perm.js
@@ -0,0 +1,32 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('async perm', function (t) {
+ t.plan(2);
+ var file = '/tmp/' + (Math.random() * (1<<30)).toString(16);
+
+ mkdirp(file, 0755, function (err) {
+ if (err) t.fail(err);
+ else path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.equal(stat.mode & 0777, 0755);
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ })
+ })
+ });
+});
+
+test('async root perm', function (t) {
+ mkdirp('/tmp', 0755, function (err) {
+ if (err) t.fail(err);
+ t.end();
+ });
+ t.end();
+});
View
39 test/node/node_modules/fs-extra/node_modules/mkdirp/test/perm_sync.js
@@ -0,0 +1,39 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('sync perm', function (t) {
+ t.plan(2);
+ var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json';
+
+ mkdirp.sync(file, 0755);
+ path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.equal(stat.mode & 0777, 0755);
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ })
+ });
+});
+
+test('sync root perm', function (t) {
+ t.plan(1);
+
+ var file = '/tmp';
+ mkdirp.sync(file, 0755);
+ path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ })
+ });
+});
View
41 test/node/node_modules/fs-extra/node_modules/mkdirp/test/race.js
@@ -0,0 +1,41 @@
+var mkdirp = require('../').mkdirp;
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('race', function (t) {
+ t.plan(4);
+ var ps = [ '', 'tmp' ];
+
+ for (var i = 0; i < 25; i++) {
+ var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ ps.push(dir);
+ }
+ var file = ps.join('/');
+
+ var res = 2;
+ mk(file, function () {
+ if (--res === 0) t.end();
+ });
+
+ mk(file, function () {
+ if (--res === 0) t.end();
+ });
+
+ function mk (file, cb) {
+ mkdirp(file, 0755, function (err) {
+ if (err) t.fail(err);
+ else path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.equal(stat.mode & 0777, 0755);
+ t.ok(stat.isDirectory(), 'target not a directory');
+ if (cb) cb();
+ }
+ })
+ })
+ });
+ }
+});
View
32 test/node/node_modules/fs-extra/node_modules/mkdirp/test/rel.js
@@ -0,0 +1,32 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('rel', function (t) {
+ t.plan(2);
+ var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+
+ var cwd = process.cwd();
+ process.chdir('/tmp');
+
+ var file = [x,y,z].join('/');
+
+ mkdirp(file, 0755, function (err) {
+ if (err) t.fail(err);
+ else path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ process.chdir(cwd);
+ t.equal(stat.mode & 0777, 0755);
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ })
+ })
+ });
+});
View
25 test/node/node_modules/fs-extra/node_modules/mkdirp/test/return.js
@@ -0,0 +1,25 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('return value', function (t) {
+ t.plan(4);
+ var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+
+ var file = '/tmp/' + [x,y,z].join('/');
+
+ // should return the first dir created.
+ // By this point, it would be profoundly surprising if /tmp didn't
+ // already exist, since every other test makes things in there.
+ mkdirp(file, function (err, made) {
+ t.ifError(err);
+ t.equal(made, '/tmp/' + x);
+ mkdirp(file, function (err, made) {
+ t.ifError(err);
+ t.equal(made, null);
+ });
+ });
+});
View
24 test/node/node_modules/fs-extra/node_modules/mkdirp/test/return_sync.js
@@ -0,0 +1,24 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('return value', function (t) {
+ t.plan(2);
+ var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+
+ var file = '/tmp/' + [x,y,z].join('/');
+
+ // should return the first dir created.
+ // By this point, it would be profoundly surprising if /tmp didn't
+ // already exist, since every other test makes things in there.
+ // Note that this will throw on failure, which will fail the test.
+ var made = mkdirp.sync(file);
+ t.equal(made, '/tmp/' + x);
+
+ // making the same file again should have no effect.
+ made = mkdirp.sync(file);
+ t.equal(made, null);
+});
View
18 test/node/node_modules/fs-extra/node_modules/mkdirp/test/root.js
@@ -0,0 +1,18 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('root', function (t) {
+ // '/' on unix, 'c:/' on windows.
+ var file = path.resolve('/');
+
+ mkdirp(file, 0755, function (err) {
+ if (err) throw err
+ fs.stat(file, function (er, stat) {
+ if (er) throw er
+ t.ok(stat.isDirectory(), 'target is a directory');
+ t.end();
+ })
+ });
+});
View
32 test/node/node_modules/fs-extra/node_modules/mkdirp/test/sync.js
@@ -0,0 +1,32 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('sync', function (t) {
+ t.plan(2);
+ var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+
+ var file = '/tmp/' + [x,y,z].join('/');
+
+ try {
+ mkdirp.sync(file, 0755);
+ } catch (err) {
+ t.fail(err);
+ return t.end();
+ }
+
+ path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.equal(stat.mode & 0777, 0755);
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ });
+ });
+});
View
28 test/node/node_modules/fs-extra/node_modules/mkdirp/test/umask.js
@@ -0,0 +1,28 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('implicit mode from umask', function (t) {
+ t.plan(2);
+ var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+
+ var file = '/tmp/' + [x,y,z].join('/');
+
+ mkdirp(file, function (err) {
+ if (err) t.fail(err);
+ else path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.equal(stat.mode & 0777, 0777 & (~process.umask()));
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ })
+ })
+ });
+});
View
32 test/node/node_modules/fs-extra/node_modules/mkdirp/test/umask_sync.js
@@ -0,0 +1,32 @@
+var mkdirp = require('../');
+var path = require('path');
+var fs = require('fs');
+var test = require('tap').test;
+
+test('umask sync modes', function (t) {
+ t.plan(2);
+ var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+ var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
+
+ var file = '/tmp/' + [x,y,z].join('/');
+
+ try {
+ mkdirp.sync(file);
+ } catch (err) {
+ t.fail(err);
+ return t.end();
+ }
+
+ path.exists(file, function (ex) {
+ if (!ex) t.fail('file not created')
+ else fs.stat(file, function (err, stat) {
+ if (err) t.fail(err)
+ else {
+ t.equal(stat.mode & 0777, (0777 & (~process.umask())));
+ t.ok(stat.isDirectory(), 'target not a directory');
+ t.end();
+ }
+ });
+ });
+});
View
4 test/node/node_modules/fs-extra/node_modules/ncp/.npmignore
@@ -0,0 +1,4 @@
+node_modules
+.*.sw[op]
+.DS_Store
+test/fixtures/out
View
6 test/node/node_modules/fs-extra/node_modules/ncp/.travis.yml
@@ -0,0 +1,6 @@
+language: node_js
+
+node_js:
+ - 0.4
+ - 0.6
+ - 0.7
View
21 test/node/node_modules/fs-extra/node_modules/ncp/LICENSE.md
@@ -0,0 +1,21 @@
+# MIT License
+
+###Copyright (C) 2011 by Charlie McConnell
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
View
46 test/node/node_modules/fs-extra/node_modules/ncp/README.md
@@ -0,0 +1,46 @@
+# ncp - Asynchronous recursive file & directory copying
+
+[![Build Status](https://secure.travis-ci.org/AvianFlu/ncp.png)](http://travis-ci.org/AvianFlu/ncp)
+
+Think `cp -r`, but pure node, and asynchronous. `ncp` can be used both as a CLI tool and programmatically.
+
+## Command Line usage
+
+Usage is simple: `ncp [source] [dest] [--limit=concurrency limit]
+[--filter=filter] --stopOnErr`
+
+The 'filter' is a Regular Expression - matched files will be copied.
+
+The 'concurrency limit' is an integer that represents how many pending file system requests `ncp` has at a time.
+
+'stopOnErr' is a boolean flag that will tell `ncp` to stop immediately if any
+errors arise, rather than attempting to continue while logging errors.
+
+If there are no errors, `ncp` will output `done.` when complete. If there are errors, the error messages will be logged to `stdout` and to `./ncp-debug.log`, and the copy operation will attempt to continue.
+
+## Programmatic usage
+
+Programmatic usage of `ncp` is just as simple. The only argument to the completion callback is a possible error.
+
+```javascript
+var ncp = require('ncp').ncp;
+
+ncp.limit = 16;
+
+ncp(source, destination, function (err) {
+ if (err) {
+ return console.error(err);
+ }
+ console.log('done!');
+});
+```
+
+You can also call ncp like `ncp(source, destination, options, callback)`.
+`options` should be a dictionary. Currently, such options are available:
+
+ * `options.filter` - a `RegExp` instance, against which each file name is
+ tested to determine whether to copy it or not, or a function taking single
+ parameter: copied file name, returning `true` or `false`, determining
+ whether to copy file or not.
+
+Please open an issue if any bugs arise. As always, I accept (working) pull requests, and refunds are available at `/dev/null`.
View
48 test/node/node_modules/fs-extra/node_modules/ncp/bin/ncp
@@ -0,0 +1,48 @@
+#!/usr/bin/env node
+
+
+
+
+var ncp = require('../lib/ncp'),
+ args = process.argv.slice(2),
+ source, dest;
+
+if (args.length < 2) {
+ console.error('Usage: ncp [source] [destination] [--filter=filter] [--limit=concurrency limit]');
+ process.exit(1);
+}
+
+// parse arguments the hard way
+function startsWith(str, prefix) {
+ return str.substr(0, prefix.length) == prefix;
+}
+
+var options = {};
+args.forEach(function (arg) {
+ if (startsWith(arg, "--limit=")) {
+ options.limit = parseInt(arg.split('=', 2)[1], 10);
+ }
+ if (startsWith(arg, "--filter=")) {
+ options.filter = new RegExp(arg.split('=', 2)[1]);
+ }
+ if (startsWith(arg, "--stoponerr")) {
+ options.stopOnErr = true;
+ }
+});
+
+ncp.ncp(args[0], args[1], options, function (err) {
+ if (Array.isArray(err)) {
+ console.error('There were errors during the copy.');
+ err.forEach(function (err) {
+ console.error(err.stack || err.message);
+ });
+ process.exit(1);
+ }
+ else if (err) {
+ console.error('An error has occurred.');
+ console.error(err.stack || err.message);
+ process.exit(1);
+ }
+});
+
+
View
216 test/node/node_modules/fs-extra/node_modules/ncp/lib/ncp.js
@@ -0,0 +1,216 @@
+var fs = require('fs'),
+ path = require('path');
+
+var ncp = exports;
+
+ncp.ncp = function (source, dest, options, callback) {
+ if (!callback) {
+ callback = options;
+ options = {};
+ }
+
+ var basePath = process.cwd(),
+ currentPath = path.resolve(basePath, source),
+ targetPath = path.resolve(basePath, dest),
+ filter = options.filter,
+ errs = null,
+ started = 0,
+ finished = 0,
+ running = 0,
+ limit = options.limit || ncp.limit || 16;
+
+ limit = (limit < 1) ? 1 : (limit > 512) ? 512 : limit;
+
+ startCopy(currentPath);
+
+ function startCopy(source) {
+ started++;
+ if (filter) {
+ if (filter instanceof RegExp) {
+ if (!filter.test(source)) {
+ return cb(true);
+ }
+ }
+ else if (typeof filter === 'function') {
+ if (!filter(source)) {
+ return cb(true);
+ }
+ }
+ }
+ return getStats(source);
+ }
+
+ function defer(fn) {
+ if (typeof(setImmediate) === 'function')
+ return setImmediate(fn);
+ return process.nextTick(fn);
+ }
+
+ function getStats(source) {
+ if (running >= limit) {
+ return defer(function () {
+ getStats(source);
+ });
+ }
+ running++;
+ fs.lstat(source, function (err, stats) {
+ var item = {};
+ if (err) {
+ return onError(err);
+ }
+
+ // We need to get the mode from the stats object and preserve it.
+ item.name = source;
+ item.mode = stats.mode;
+
+ if (stats.isDirectory()) {
+ return onDir(item);
+ }
+ else if (stats.isFile()) {
+ return onFile(item);
+ }
+ else if (stats.isSymbolicLink()) {
+ // Symlinks don't really need to know about the mode.
+ return onLink(source);
+ }
+ });
+ }
+
+ function onFile(file) {
+ var target = file.name.replace(currentPath, targetPath);
+ isWritable(target, function (writable) {
+ if (writable) {
+ return copyFile(file, target);
+ }
+ rmFile(target, function () {
+ copyFile(file, target);
+ });
+ });
+ }
+
+ function copyFile(file, target) {
+ var readStream = fs.createReadStream(file.name),
+ writeStream = fs.createWriteStream(target, { mode: file.mode });
+ readStream.pipe(writeStream);
+ readStream.once('end', cb);
+ }
+
+ function rmFile(file, done) {
+ fs.unlink(file, function (err) {
+ if (err) {
+ return onError(err);
+ }
+ return done();
+ });
+ }
+
+ function onDir(dir) {
+ var target = dir.name.replace(currentPath, targetPath);
+ isWritable(target, function (writable) {
+ if (writable) {
+ return mkDir(dir, target);
+ }
+ copyDir(dir.name);
+ });
+ }
+
+ function mkDir(dir, target) {
+ fs.mkdir(target, dir.mode, function (err) {
+ if (err) {
+ return onError(err);
+ }
+ copyDir(dir.name);
+ });
+ }
+
+ function copyDir(dir) {
+ fs.readdir(dir, function (err, items) {
+ if (err) {
+ return onError(err);
+ }
+ items.forEach(function (item) {
+ startCopy(dir + '/' + item);
+ });
+ return cb();
+ });
+ }
+
+ function onLink(link) {
+ var target = link.replace(currentPath, targetPath);
+ fs.readlink(link, function (err, resolvedPath) {
+ if (err) {
+ return onError(err);
+ }
+ checkLink(resolvedPath, target);
+ });
+ }
+
+ function checkLink(resolvedPath, target) {
+ isWritable(target, function (writable) {
+ if (writable) {
+ return makeLink(resolvedPath, target);
+ }
+ fs.readlink(target, function (err, targetDest) {
+ if (err) {
+ return onError(err);
+ }
+ if (targetDest === resolvedPath) {
+ return cb();
+ }
+ return rmFile(target, function () {
+ makeLink(resolvedPath, target);
+ });
+ });
+ });
+ }
+
+ function makeLink(linkPath, target) {
+ fs.symlink(linkPath, target, function (err) {
+ if (err) {
+ return onError(err);
+ }
+ return cb();
+ });
+ }
+
+ function isWritable(path, done) {
+ fs.lstat(path, function (err, stats) {
+ if (err) {
+ if (err.code === 'ENOENT') return done(true);
+ return done(false);
+ }
+ return done(false);
+ });
+ }
+
+ function onError(err) {
+ if (options.stopOnError) {
+ return callback(err);
+ }
+ else if (!errs && options.errs) {
+ errs = fs.createWriteStream(options.errs);
+ }
+ else if (!errs) {
+ errs = [];
+ }
+ else if (options.errs) {
+ if (typeof errs.write === 'undefined') {
+ errs.push(err);
+ }
+ else {
+ errs.write(err.stack + '\n\n');
+ }
+ }
+ return cb();
+ }
+
+ function cb(skipped) {
+ if (!skipped) running--;
+ finished++;
+ if ((started === finished) && (running === 0)) {
+ return errs ? callback(errs) : callback(null);
+ }
+ }
+};
+
+
View
37 test/node/node_modules/fs-extra/node_modules/ncp/package.json
@@ -0,0 +1,37 @@
+{
+ "name": "ncp",
+ "version": "0.2.7",
+ "author": {
+ "name": "AvianFlu",
+ "email": "charlie@charlieistheman.com"
+ },
+ "description": "Asynchronous recursive file copy utility.",
+ "bin": {
+ "ncp": "./bin/ncp"
+ },
+ "devDependencies": {