[Pkg-javascript-commits] [node-fs-extra] 02/10: New upstream version 3.0.1

Julien Puydt julien.puydt at laposte.net
Mon Jul 24 09:18:38 UTC 2017


This is an automated email from the git hooks/post-receive script.

jpuydt-guest pushed a commit to branch master
in repository node-fs-extra.

commit 531b53d586bbc9ac22585323e381f0865f686ce0
Author: Julien Puydt <julien.puydt at laposte.net>
Date:   Wed Jun 28 07:35:39 2017 +0200

    New upstream version 3.0.1
---
 CHANGELOG.md                                       | 68 +++++++++++++++-------
 README.md                                          | 41 +++++--------
 docs/copy.md                                       | 11 +++-
 docs/emptyDir.md                                   |  9 +++
 docs/ensureDir.md                                  | 11 +++-
 docs/ensureFile.md                                 | 11 +++-
 docs/ensureLink.md                                 | 11 +++-
 docs/ensureSymlink.md                              | 11 +++-
 docs/move.md                                       | 10 +++-
 docs/outputFile.md                                 | 13 ++++-
 docs/outputJson.md                                 | 13 ++++-
 docs/pathExists-sync.md                            |  3 +
 docs/pathExists.md                                 | 22 +++++++
 docs/readJson.md                                   | 22 ++++++-
 docs/remove.md                                     | 11 +++-
 docs/writeJson.md                                  | 11 +++-
 lib/__tests__/promise.test.js                      | 27 +++++++++
 lib/copy-sync/copy-file-sync.js                    |  2 +-
 lib/copy/copy.js                                   |  4 +-
 lib/copy/index.js                                  |  3 +-
 lib/empty/index.js                                 |  5 +-
 lib/ensure/__tests__/link.test.js                  | 24 ++++++++
 lib/ensure/__tests__/symlink.test.js               | 23 ++++++++
 lib/ensure/file.js                                 | 15 ++---
 lib/ensure/link.js                                 | 15 ++---
 lib/ensure/symlink-paths.js                        |  4 +-
 lib/ensure/symlink.js                              | 16 ++---
 lib/{ => fs}/__tests__/fs-integration.test.js      |  2 +-
 lib/fs/__tests__/mz.test.js                        | 50 ++++++++++++++++
 lib/fs/index.js                                    | 61 +++++++++++++++++++
 lib/index.js                                       | 25 ++------
 lib/json/__tests__/jsonfile-integration.test.js    |  7 +--
 lib/json/__tests__/output-json.test.js             |  8 +++
 lib/json/__tests__/spaces.test.js                  | 34 -----------
 lib/json/index.js                                  | 11 +++-
 lib/json/jsonfile.js                               | 12 ++--
 lib/json/output-json.js                            |  5 +-
 lib/mkdirs/__tests__/mkdirp.test.js                |  3 +-
 lib/mkdirs/__tests__/perm.test.js                  |  3 +-
 lib/mkdirs/__tests__/perm_sync.test.js             |  6 +-
 lib/mkdirs/__tests__/race.test.js                  |  3 +-
 lib/mkdirs/__tests__/rel.test.js                   |  3 +-
 lib/mkdirs/__tests__/sync.test.js                  |  3 +-
 lib/mkdirs/__tests__/umask.test.js                 |  6 +-
 lib/mkdirs/index.js                                | 17 ++++--
 lib/move-sync/__tests__/move-sync.test.js          | 13 +++--
 lib/move-sync/index.js                             |  5 +-
 lib/move/__tests__/move.test.js                    | 16 +++--
 lib/move/index.js                                  |  5 +-
 lib/output/__tests__/output.test.js                |  5 ++
 lib/output/index.js                                |  7 ++-
 lib/path-exists/__tests__/path-exists-sync.test.js | 28 +++++++++
 lib/path-exists/__tests__/path-exists.test.js      | 40 +++++++++++++
 lib/path-exists/index.js                           | 12 ++++
 lib/remove/__tests__/remove.test.js                |  3 +-
 lib/remove/index.js                                | 14 +----
 lib/remove/rimraf.js                               |  6 +-
 lib/util/buffer.js                                 | 11 ++++
 package.json                                       | 10 ++--
 59 files changed, 640 insertions(+), 210 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 99b4bd8..ff2a6dc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,31 @@
+3.0.1 / 2017-05-04
+------------------
+
+- Fix bug in `move()` & `moveSync()` when source and destination are the same, and source does not exist. [#415](https://github.com/jprichardson/node-fs-extra/pull/415)
+
+3.0.0 / 2017-04-27
+------------------
+
+### Added
+
+- **BREAKING:** Added Promise support. All asynchronous native fs methods and fs-extra methods now return a promise if the callback is not passed. [#403](https://github.com/jprichardson/node-fs-extra/pull/403)
+- `pathExists()`, a replacement for the deprecated `fs.exists`. `pathExists` has a normal error-first callback signature. Also added `pathExistsSync`, an alias to `fs.existsSync`, for completeness. [#406](https://github.com/jprichardson/node-fs-extra/pull/406)
+
+### Removed
+
+- **BREAKING:** Removed support for setting the default spaces for `writeJson()`, `writeJsonSync()`, `outputJson()`, & `outputJsonSync()`. This was undocumented. [#402](https://github.com/jprichardson/node-fs-extra/pull/402)
+
+### Changed
+
+- Upgraded jsonfile dependency to v3.0.0:
+  - **BREAKING:** Changed behavior of `throws` option for `readJsonSync()`; now does not throw filesystem errors when `throws` is `false`.
+- **BREAKING:** `writeJson()`, `writeJsonSync()`, `outputJson()`, & `outputJsonSync()` now output minified JSON by default for consistency with `JSON.stringify()`; set the `spaces` option to `2` to override this new behavior. [#402](https://github.com/jprichardson/node-fs-extra/pull/402)
+- Use `Buffer.allocUnsafe()` instead of `new Buffer()` in environments that support it. [#394](https://github.com/jprichardson/node-fs-extra/pull/394)
+
+### Fixed
+
+- `removeSync()` silently failed on Windows in some cases. Now throws an `EBUSY` error. [#408](https://github.com/jprichardson/node-fs-extra/pull/408)
+
 2.1.2 / 2017-03-16
 ------------------
 
@@ -218,10 +246,10 @@ this package had both `fs.readJsonFile` and `fs.readJson` that were aliases to e
 
 0.16.0 / 2015-01-28
 -------------------
-- bugfix `fs.move()` into itself. Closes #104
-- bugfix `fs.move()` moving directory across device. Closes #108
+- bugfix `fs.move()` into itself. Closes [#104]
+- bugfix `fs.move()` moving directory across device. Closes [#108]
 - added coveralls support
-- bugfix: nasty multiple callback `fs.copy()` bug. Closes #98
+- bugfix: nasty multiple callback `fs.copy()` bug. Closes [#98]
 - misc fs.copy code cleanups
 
 0.15.0 / 2015-01-21
@@ -258,7 +286,7 @@ see https://github.com/jprichardson/node-jsonfile#readfilesyncfilename-options f
 0.10.0 / 2014-06-29
 ------------------
 * bugfix: upgaded `"jsonfile": "~1.1.0"` to `"jsonfile": "^1.2.0"`, bumped minor because of `jsonfile` dep change
-from `~` to `^`. #67
+from `~` to `^`. [#67]
 
 0.9.1 / 2014-05-22
 ------------------
@@ -266,31 +294,31 @@ from `~` to `^`. #67
 
 0.9.0 / 2014-05-22
 ------------------
-* upgraded `ncp` from `~0.4.2` to `^0.5.1`, #58
+* upgraded `ncp` from `~0.4.2` to `^0.5.1`, [#58]
 * upgraded `rimraf` from `~2.2.6` to `^2.2.8`
 * upgraded `mkdirp` from `0.3.x` to `^0.5.0`
 * added methods `ensureFile()`, `ensureFileSync()`
-* added methods `ensureDir()`, `ensureDirSync()` #31
+* added methods `ensureDir()`, `ensureDirSync()` [#31]
 * added `move()` method. From: https://github.com/andrewrk/node-mv
 
 
 0.8.1 / 2013-10-24
 ------------------
-* copy failed to return an error to the callback if a file doesn't exist (ulikoehler #38, #39)
+* copy failed to return an error to the callback if a file doesn't exist (ulikoehler [#38], [#39])
 
 0.8.0 / 2013-10-14
 ------------------
-* `filter` implemented on `copy()` and `copySync()`. (Srirangan / #36)
+* `filter` implemented on `copy()` and `copySync()`. (Srirangan / [#36])
 
 0.7.1 / 2013-10-12
 ------------------
-* `copySync()` implemented (Srirangan / #33)
-* updated to the latest `jsonfile` version `1.1.0` which gives `options` params for the JSON methods. Closes #32
+* `copySync()` implemented (Srirangan / [#33])
+* updated to the latest `jsonfile` version `1.1.0` which gives `options` params for the JSON methods. Closes [#32]
 
 0.7.0 / 2013-10-07
 ------------------
 * update readme conventions
-* `copy()` now works if destination directory does not exist. Closes #29
+* `copy()` now works if destination directory does not exist. Closes [#29]
 
 0.6.4 / 2013-09-05
 ------------------
@@ -304,19 +332,19 @@ from `~` to `^`. #67
 
 0.6.2 / 2013-06-28
 ------------------
-* added .npmignore, #25
+* added .npmignore, [#25]
 
 0.6.1 / 2013-05-14
 ------------------
-* modified for `strict` mode, closes #24
-* added `outputJson()/outputJsonSync()`, closes #23
+* modified for `strict` mode, closes [#24]
+* added `outputJson()/outputJsonSync()`, closes [#23]
 
 0.6.0 / 2013-03-18
 ------------------
 * removed node 0.6 support
 * added node 0.10 support
 * upgraded to latest `ncp` and `rimraf`.
-* optional `graceful-fs` support. Closes #17
+* optional `graceful-fs` support. Closes [#17]
 
 
 0.5.0 / 2013-02-03
@@ -354,7 +382,7 @@ from `~` to `^`. #67
 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 all methods of [jsonfile](https://github.com/jprichardson/node-jsonfile)
 * Added Travis-CI.
 
 0.1.3 / 2012-08-13
@@ -451,7 +479,7 @@ from `~` to `^`. #67
 [#284]: https://github.com/jprichardson/node-fs-extra/issues/284    "outputFile method is missing a check to determine if existing item is a folder or not"
 [#283]: https://github.com/jprichardson/node-fs-extra/pull/283      "Apply filter also on directories and symlinks for copySync()"
 [#282]: https://github.com/jprichardson/node-fs-extra/pull/282      "Apply filter also on directories and symlinks for copySync()"
-[#281]: https://github.com/jprichardson/node-fs-extra/issues/281    "remove function executes "successfully" but doesn't do anything?"
+[#281]: https://github.com/jprichardson/node-fs-extra/issues/281    "remove function executes 'successfully' but doesn't do anything?"
 [#280]: https://github.com/jprichardson/node-fs-extra/pull/280      "Disable rimraf globbing"
 [#279]: https://github.com/jprichardson/node-fs-extra/issues/279    "Some code is vendored instead of included [awaiting-reply]"
 [#278]: https://github.com/jprichardson/node-fs-extra/issues/278    "copy() does not preserve file/directory ownership"
@@ -673,7 +701,7 @@ from `~` to `^`. #67
 [#62]: https://github.com/jprichardson/node-fs-extra/issues/62      "npm install fs-extra doesn't work"
 [#61]: https://github.com/jprichardson/node-fs-extra/issues/61      "No longer supports node 0.8 due to use of `^` in package.json dependencies"
 [#60]: https://github.com/jprichardson/node-fs-extra/issues/60      "chmod & chown for mkdirs"
-[#59]: https://github.com/jprichardson/node-fs-extra/issues/59      "Consider including mkdirp and making fs-extra "--use_strict" safe [question]"
+[#59]: https://github.com/jprichardson/node-fs-extra/issues/59      "Consider including mkdirp and making fs-extra '--use_strict' safe [question]"
 [#58]: https://github.com/jprichardson/node-fs-extra/issues/58      "Stack trace not included in fs.copy error"
 [#57]: https://github.com/jprichardson/node-fs-extra/issues/57      "Possible to include wildcards in delete?"
 [#56]: https://github.com/jprichardson/node-fs-extra/issues/56      "Crash when have no access to write to destination file in copy "
@@ -685,7 +713,7 @@ from `~` to `^`. #67
 [#50]: https://github.com/jprichardson/node-fs-extra/issues/50      "Replace mechanism in createFile"
 [#49]: https://github.com/jprichardson/node-fs-extra/pull/49        "update rimraf to v2.2.6"
 [#48]: https://github.com/jprichardson/node-fs-extra/issues/48      "fs.copy issue [bug]"
-[#47]: https://github.com/jprichardson/node-fs-extra/issues/47      "Bug in copy - callback called on readStream "close" - Fixed in ncp 0.5.0"
+[#47]: https://github.com/jprichardson/node-fs-extra/issues/47      "Bug in copy - callback called on readStream 'close' - Fixed in ncp 0.5.0"
 [#46]: https://github.com/jprichardson/node-fs-extra/pull/46        "update copyright year"
 [#45]: https://github.com/jprichardson/node-fs-extra/pull/45        "Added note about fse.outputFile() being the one that overwrites"
 [#44]: https://github.com/jprichardson/node-fs-extra/pull/44        "Proposal: Stream support"
@@ -715,7 +743,7 @@ from `~` to `^`. #67
 [#20]: https://github.com/jprichardson/node-fs-extra/issues/20      "fs.remove yields callback before directory is really deleted"
 [#19]: https://github.com/jprichardson/node-fs-extra/issues/19      "fs.copy err is empty array"
 [#18]: https://github.com/jprichardson/node-fs-extra/pull/18        "Exposed copyFile Function"
-[#17]: https://github.com/jprichardson/node-fs-extra/issues/17      "Use `require("graceful-fs")` if found instead of `require("fs")`"
+[#17]: https://github.com/jprichardson/node-fs-extra/issues/17      "Use `require('graceful-fs')` if found instead of `require('fs')`"
 [#16]: https://github.com/jprichardson/node-fs-extra/pull/16        "Update README.md"
 [#15]: https://github.com/jprichardson/node-fs-extra/issues/15      "Implement cp -r but sync aka copySync. [enhancement]"
 [#14]: https://github.com/jprichardson/node-fs-extra/issues/14      "fs.mkdirSync is broken in 0.3.1"
diff --git a/README.md b/README.md
index cee4399..bb9422d 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 Node.js: fs-extra
 =================
 
-`fs-extra` adds file system methods that aren't included in the native `fs` module. It is a drop in replacement for `fs`.
+`fs-extra` adds file system methods that aren't included in the native `fs` module and adds promise support to the `fs` methods. It should be a drop in replacement for `fs`.
 
 [![npm Package](https://img.shields.io/npm/v/fs-extra.svg?style=flat-square)](https://www.npmjs.org/package/fs-extra)
 [![build status](https://api.travis-ci.org/jprichardson/node-fs-extra.svg)](http://travis-ci.org/jprichardson/node-fs-extra)
@@ -30,7 +30,7 @@ Installation
 Usage
 -----
 
-`fs-extra` is a drop in replacement for native `fs`. All methods in `fs` are unmodified and attached to `fs-extra`.
+`fs-extra` is a drop in replacement for native `fs`. All methods in `fs` are attached to `fs-extra`. All `fs` methods return promises if the callback isn't passed.
 
 You don't ever need to include the original `fs` module again:
 
@@ -60,7 +60,7 @@ const fse = require('fs-extra')
 
 Sync vs Async
 -------------
-Most methods are async by default (they take a callback with an `Error` as first argument).
+Most methods are async by default. All async methods will return a promise if the callback isn't passed.
 
 Sync methods on the other hand will throw if an error occurs.
 
@@ -69,14 +69,21 @@ Example:
 ```js
 const fs = require('fs-extra')
 
+// Async with promises:
+fs.copy('/tmp/myfile', '/tmp/mynewfile')
+  .then(() => console.log('success!'))
+  .catch(err => console.error(err))
+
+// Async with callbacks:
 fs.copy('/tmp/myfile', '/tmp/mynewfile', err => {
   if (err) return console.error(err)
-  console.log("success!")
-});
+  console.log('success!')
+})
 
+// Sync:
 try {
   fs.copySync('/tmp/myfile', '/tmp/mynewfile')
-  console.log("success!")
+  console.log('success!')
 } catch (err) {
   console.error(err)
 }
@@ -98,6 +105,7 @@ Methods
 - [move](docs/move.md)
 - [outputFile](docs/outputFile.md)
 - [outputJson](docs/outputJson.md)
+- [pathExists](docs/pathExists.md)
 - [readJson](docs/readJson.md)
 - [remove](docs/remove.md)
 - [writeJson](docs/writeJson.md)
@@ -114,12 +122,13 @@ Methods
 - [moveSync](docs/move-sync.md)
 - [outputFileSync](docs/outputFile-sync.md)
 - [outputJsonSync](docs/outputJson-sync.md)
+- [pathExistsSync](docs/pathExists-sync.md)
 - [readJsonSync](docs/readJson-sync.md)
 - [removeSync](docs/remove-sync.md)
 - [writeJsonSync](docs/writeJson-sync.md)
 
 
-**NOTE:** You can still use the native Node.js methods. They are copied over to `fs-extra`.
+**NOTE:** You can still use the native Node.js methods. They are promisified and copied over to `fs-extra`.
 
 ### What happened to `walk()` and `walkSync()`?
 
@@ -129,24 +138,6 @@ They were removed from `fs-extra` in v2.0.0. If you need the functionality, `wal
 Third Party
 -----------
 
-### Promises
-
-Use [Bluebird](https://github.com/petkaantonov/bluebird). See https://github.com/petkaantonov/bluebird/blob/master/API.md#promisification. `fs-extra` is
-explicitly listed as supported.
-
-```js
-const Promise = require('bluebird')
-const fs = Promise.promisifyAll(require('fs-extra'))
-```
-
-Or you can use a dedicated package:
-
-- [`fs-extra-promise`](https://github.com/overlookmotel/fs-extra-promise) uses Bluebird.
-- [`fs-promise`](https://github.com/kevinbeaty/fs-promise) uses
-  [Any Promise](https://github.com/kevinbeaty/any-promise) and also covers
-  [`mz/fs`](https://github.com/normalize/mz/blob/master/fs.js).
-- [`fs-p`](https://github.com/grammarly/fs-p) - TypeScript-friendly promises implementation
-
 
 ### TypeScript
 
diff --git a/docs/copy.md b/docs/copy.md
index a4f75e9..ff0811f 100644
--- a/docs/copy.md
+++ b/docs/copy.md
@@ -1,4 +1,4 @@
-# copy(src, dest, [options], callback)
+# copy(src, dest, [options, callback])
 
 Copy a file or directory. The directory can have contents. Like `cp -r`.
 
@@ -28,6 +28,15 @@ fs.copy('/tmp/mydir', '/tmp/mynewdir', err => {
 
   console.log('success!')
 }) // copies directory, even if it has subdirectories or files
+
+// Promise usage:
+fs.copy('/tmp/myfile', '/tmp/mynewfile')
+.then(() => {
+  console.log('success!')
+})
+.catch(err => {
+  console.error(err)
+})
 ```
 
 **Using filter function**
diff --git a/docs/emptyDir.md b/docs/emptyDir.md
index 43292e3..6553e9a 100644
--- a/docs/emptyDir.md
+++ b/docs/emptyDir.md
@@ -18,4 +18,13 @@ fs.emptyDir('/tmp/some/dir', err => {
 
   console.log('success!')
 })
+
+// With promises
+fs.emptyDir('/tmp/some/dir')
+.then(() => {
+  console.log('success!')
+})
+.catch(err => {
+  console.error(err)
+})
 ```
diff --git a/docs/ensureDir.md b/docs/ensureDir.md
index 1f8acfb..d030d86 100644
--- a/docs/ensureDir.md
+++ b/docs/ensureDir.md
@@ -1,4 +1,4 @@
-# ensureDir(dir, callback)
+# ensureDir(dir, [callback])
 
 Ensures that the directory exists. If the directory structure does not exist, it is created. Like `mkdir -p`.
 
@@ -17,4 +17,13 @@ fs.ensureDir(dir, err => {
   console.log(err) // => null
   // dir has now been created, including the directory it is to be placed in
 })
+
+// With Promises:
+fs.ensureDir(dir)
+.then(() => {
+  console.log('success!')
+})
+.catch(err => {
+  console.error(err)
+})
 ```
diff --git a/docs/ensureFile.md b/docs/ensureFile.md
index 1567e60..987be63 100644
--- a/docs/ensureFile.md
+++ b/docs/ensureFile.md
@@ -1,4 +1,4 @@
-# ensureFile(file, callback)
+# ensureFile(file, [callback])
 
 Ensures that the file exists. 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**.
 
@@ -17,4 +17,13 @@ fs.ensureFile(file, err => {
   console.log(err) // => null
   // file has now been created, including the directory it is to be placed in
 })
+
+// With Promises:
+fs.ensureFile(file)
+.then(() => {
+  console.log('success!')
+})
+.catch(err => {
+  console.error(err)
+})
 ```
diff --git a/docs/ensureLink.md b/docs/ensureLink.md
index 3cf38c5..90d2a5d 100644
--- a/docs/ensureLink.md
+++ b/docs/ensureLink.md
@@ -1,4 +1,4 @@
-# ensureLink(srcpath, dstpath, callback)
+# ensureLink(srcpath, dstpath, [callback])
 
 Ensures that the link exists. If the directory structure does not exist, it is created.
 
@@ -17,4 +17,13 @@ fs.ensureLink(srcpath, dstpath, err => {
   console.log(err) // => null
   // link has now been created, including the directory it is to be placed in
 })
+
+// With Promises:
+fs.ensureLink(srcpath, dstpath)
+.then(() => {
+  console.log('success!')
+})
+.catch(err => {
+  console.error(err)
+})
 ```
diff --git a/docs/ensureSymlink.md b/docs/ensureSymlink.md
index b6c9695..45524f1 100644
--- a/docs/ensureSymlink.md
+++ b/docs/ensureSymlink.md
@@ -1,4 +1,4 @@
-# ensureSymlink(srcpath, dstpath, [type], callback)
+# ensureSymlink(srcpath, dstpath, [type, callback])
 
 Ensures that the symlink exists. If the directory structure does not exist, it is created.
 
@@ -18,4 +18,13 @@ fs.ensureSymlink(srcpath, dstpath, err => {
   console.log(err) // => null
   // symlink has now been created, including the directory it is to be placed in
 })
+
+// With Promises:
+fs.ensureSymlink(srcpath, dstpath)
+.then(() => {
+  console.log('success!')
+})
+.catch(err => {
+  console.error(err)
+})
 ```
diff --git a/docs/move.md b/docs/move.md
index 547af7c..0dd210c 100644
--- a/docs/move.md
+++ b/docs/move.md
@@ -1,4 +1,4 @@
-# move(src, dest, [options], callback)
+# move(src, dest, [options, callback])
 
 Moves a file or directory, even across devices.
 
@@ -18,6 +18,14 @@ fs.move('/tmp/somefile', '/tmp/does/not/exist/yet/somefile', err => {
 
   console.log('success!')
 })
+
+fs.move('/tmp/somefile', '/tmp/does/not/exist/yet/somefile')
+.then(() => {
+  console.log('success!')
+})
+.catch(err => {
+  console.error(err)
+})
 ```
 
 **Using `overwrite` option**
diff --git a/docs/outputFile.md b/docs/outputFile.md
index 494cba3..766787d 100644
--- a/docs/outputFile.md
+++ b/docs/outputFile.md
@@ -1,4 +1,4 @@
-# outputFile(file, data, [options], callback)
+# outputFile(file, data, [options, callback])
 
 Almost the same as `writeFile` (i.e. it [overwrites](http://pages.citebite.com/v2o5n8l2f5reb)), except that if the parent directory does not exist, it's created. `file` must be a file path (a buffer or a file descriptor is not allowed). `options` are what you'd pass to [`fs.writeFile()`](https://nodejs.org/api/fs.html#fs_fs_writefile_file_data_options_callback).
 
@@ -17,7 +17,18 @@ fs.outputFile(file, 'hello!', err => {
   console.log(err) // => null
 
   fs.readFile(file, 'utf8', (err, data) => {
+    if (err) return console.error(err)
     console.log(data) // => hello!
   })
 })
+
+// With Promises:
+fs.outputFile(file, 'hello!')
+.then(() => fs.readFile(file, 'utf8'))
+.then(data => {
+  console.log(data) // => hello!
+})
+.catch(err => {
+  console.error(err)
+})
 ```
diff --git a/docs/outputJson.md b/docs/outputJson.md
index 58917b8..fc6f2fe 100644
--- a/docs/outputJson.md
+++ b/docs/outputJson.md
@@ -1,4 +1,4 @@
-# outputJson(file, object, [options], callback)
+# outputJson(file, object, [options, callback])
 
 Almost the same as [`writeJson`](writeJson.md), except that if the directory does not exist, it's created.
 `options` are what you'd pass to [`jsonFile.writeFile()`](https://github.com/jprichardson/node-jsonfile#writefilefilename-options-callback).
@@ -20,7 +20,18 @@ fs.outputJson(file, {name: 'JP'}, err => {
   console.log(err) // => null
 
   fs.readJson(file, (err, data) => {
+    if (err) return console.error(err)
     console.log(data.name) // => JP
   })
 })
+
+// With Promises:
+fs.outputJson(file, {name: 'JP'})
+.then(() => fs.readJson(file))
+.then(data => {
+  console.log(data.name) // => JP
+})
+.catch(err => {
+  console.error(err)
+})
 ```
diff --git a/docs/pathExists-sync.md b/docs/pathExists-sync.md
new file mode 100644
index 0000000..3ef973c
--- /dev/null
+++ b/docs/pathExists-sync.md
@@ -0,0 +1,3 @@
+# pathExistsSync(file)
+
+An alias for [`fs.existsSync()`](https://nodejs.org/api/fs.html#fs_fs_existssync_path), created for consistency with [`pathExists()`](pathExists.md).
diff --git a/docs/pathExists.md b/docs/pathExists.md
new file mode 100644
index 0000000..0302b09
--- /dev/null
+++ b/docs/pathExists.md
@@ -0,0 +1,22 @@
+# pathExists(file[, callback])
+
+Test whether or not the given path exists by checking with the file system. Like [`fs.exists`](https://nodejs.org/api/fs.html#fs_fs_exists_path_callback), but with a normal callback signature (err, exists). Uses `fs.access` under the hood.
+
+- `file` `<String>`
+- `callback` `<Function>`
+
+## Example:
+
+```js
+const fs = require('fs-extra')
+
+const file = '/tmp/this/path/does/not/exist/file.txt'
+// Promise usage:
+fs.pathExists(file)
+  .then(exists => console.log(exists)) // => false
+// Callback usage:
+fs.pathExists(file, (err, exists) => {
+  console.log(err) // => null
+  console.log(exists) // => false
+})
+```
diff --git a/docs/readJson.md b/docs/readJson.md
index acaf19c..6edc329 100644
--- a/docs/readJson.md
+++ b/docs/readJson.md
@@ -1,4 +1,4 @@
-# readJson(file, [options], callback)
+# readJson(file, [options, callback])
 
 Reads a JSON file and then parses it into an object. `options` are the same
 that you'd pass to [`jsonFile.readFile`](https://github.com/jprichardson/node-jsonfile#readfilefilename-options-callback).
@@ -16,9 +16,18 @@ const fs = require('fs-extra')
 
 fs.readJson('./package.json', (err, packageObj) => {
   if (err) console.error(err)
-  
+
   console.log(packageObj.version) // => 0.1.3
 })
+
+// Promise Usage
+fs.readJson('./package.json')
+.then(packageObj => {
+  console.log(packageObj.version) // => 0.1.3
+})
+.catch(err => {
+  console.error(err)
+})
 ```
 
 ---
@@ -37,4 +46,13 @@ fs.readJson(file, { throws: false }, (err, obj) => {
 
   console.log(obj) // => null
 })
+
+// Promise Usage
+fs.readJson(file, { throws: false })
+.then(obj => {
+  console.log(obj) // => null
+})
+.catch(err => {
+  console.error(err) // Not called
+})
 ```
diff --git a/docs/remove.md b/docs/remove.md
index 68f9162..3640293 100644
--- a/docs/remove.md
+++ b/docs/remove.md
@@ -1,4 +1,4 @@
-# remove(path, callback)
+# remove(path, [callback])
 
 Removes a file or directory. The directory can have contents. Like `rm -rf`.
 
@@ -22,4 +22,13 @@ fs.remove('/home/jprichardson', err => {
 
   console.log('success!') // I just deleted my entire HOME directory.
 })
+
+// Promise Usage
+fs.remove('/tmp/myfile')
+.then(() => {
+  console.log('success!')
+})
+.catch(err => {
+  console.error(err)
+})
 ```
diff --git a/docs/writeJson.md b/docs/writeJson.md
index 3f8f042..0e9c393 100644
--- a/docs/writeJson.md
+++ b/docs/writeJson.md
@@ -1,4 +1,4 @@
-# writeJson(file, object, [options], callback)
+# writeJson(file, object, [options, callback])
 
 Writes an object to a JSON file. `options` are the same that
 you'd pass to [`jsonFile.writeFile()`](https://github.com/jprichardson/node-jsonfile#writefilefilename-options-callback).
@@ -20,6 +20,15 @@ fs.writeJson('./package.json', {name: 'fs-extra'}, err => {
 
   console.log('success!')
 })
+
+// With Promises
+fs.writeJson('./package.json', {name: 'fs-extra'})
+.then(() => {
+  console.log('success!')
+})
+.catch(err => {
+  console.error(err)
+})
 ```
 
 ---
diff --git a/lib/__tests__/promise.test.js b/lib/__tests__/promise.test.js
new file mode 100644
index 0000000..80aeca5
--- /dev/null
+++ b/lib/__tests__/promise.test.js
@@ -0,0 +1,27 @@
+'use strict'
+
+/* eslint-env mocha */
+
+const fse = require('..')
+
+const methods = [
+  'copy',
+  'emptyDir',
+  'ensureFile',
+  'ensureDir',
+  'mkdirs',
+  'move',
+  'readJson',
+  'readJSON',
+  'remove',
+  'writeJson',
+  'writeJSON'
+]
+
+describe('promise support', () => {
+  methods.forEach(method => {
+    it(method, done => {
+      fse[method]().catch(() => done())
+    })
+  })
+})
diff --git a/lib/copy-sync/copy-file-sync.js b/lib/copy-sync/copy-file-sync.js
index 4e4cd3f..102a6be 100644
--- a/lib/copy-sync/copy-file-sync.js
+++ b/lib/copy-sync/copy-file-sync.js
@@ -3,7 +3,7 @@
 const fs = require('graceful-fs')
 
 const BUF_LENGTH = 64 * 1024
-const _buff = new Buffer(BUF_LENGTH)
+const _buff = require('../util/buffer')(BUF_LENGTH)
 
 function copyFileSync (srcFile, destFile, options) {
   const overwrite = options.overwrite
diff --git a/lib/copy/copy.js b/lib/copy/copy.js
index d66c898..309a93d 100644
--- a/lib/copy/copy.js
+++ b/lib/copy/copy.js
@@ -4,6 +4,7 @@ const fs = require('graceful-fs')
 const path = require('path')
 const ncp = require('./ncp')
 const mkdir = require('../mkdirs')
+const pathExists = require('../path-exists').pathExists
 
 function copy (src, dest, options, callback) {
   if (typeof options === 'function' && !callback) {
@@ -39,7 +40,8 @@ function copy (src, dest, options, callback) {
       dir = path.dirname(dest)
     }
 
-    fs.exists(dir, dirExists => {
+    pathExists(dir, (err, dirExists) => {
+      if (err) return callback(err)
       if (dirExists) return ncp(src, dest, options, callback)
       mkdir.mkdirs(dir, err => {
         if (err) return callback(err)
diff --git a/lib/copy/index.js b/lib/copy/index.js
index 3e09016..a6a51da 100644
--- a/lib/copy/index.js
+++ b/lib/copy/index.js
@@ -1,3 +1,4 @@
+const u = require('universalify').fromCallback
 module.exports = {
-  copy: require('./copy')
+  copy: u(require('./copy'))
 }
diff --git a/lib/empty/index.js b/lib/empty/index.js
index 180c3f7..db05c17 100644
--- a/lib/empty/index.js
+++ b/lib/empty/index.js
@@ -1,11 +1,12 @@
 'use strict'
 
+const u = require('universalify').fromCallback
 const fs = require('fs')
 const path = require('path')
 const mkdir = require('../mkdirs')
 const remove = require('../remove')
 
-function emptyDir (dir, callback) {
+const emptyDir = u(function emptyDir (dir, callback) {
   callback = callback || function () {}
   fs.readdir(dir, (err, items) => {
     if (err) return mkdir.mkdirs(dir, callback)
@@ -23,7 +24,7 @@ function emptyDir (dir, callback) {
       })
     }
   })
-}
+})
 
 function emptyDirSync (dir) {
   let items
diff --git a/lib/ensure/__tests__/link.test.js b/lib/ensure/__tests__/link.test.js
index 8e27b6f..ebd1c85 100644
--- a/lib/ensure/__tests__/link.test.js
+++ b/lib/ensure/__tests__/link.test.js
@@ -197,6 +197,30 @@ describe('fse-ensure-link', () => {
     })
   })
 
+  describe('ensureLink() promise support', () => {
+    tests.filter(test => test[2] === 'file-success').forEach(test => {
+      const args = test[0].slice(0)
+      const srcpath = args[0]
+      const dstpath = args[1]
+
+      it(`should create link file using src ${srcpath} and dst ${dstpath}`, () => {
+        return ensureLink(srcpath, dstpath)
+          .then(() => {
+            const srcContent = fs.readFileSync(srcpath, 'utf8')
+            const dstDir = path.dirname(dstpath)
+            const dstBasename = path.basename(dstpath)
+            const isSymlink = fs.lstatSync(dstpath).isFile()
+            const dstContent = fs.readFileSync(dstpath, 'utf8')
+            const dstDirContents = fs.readdirSync(dstDir)
+
+            assert.equal(isSymlink, true)
+            assert.equal(srcContent, dstContent)
+            assert(dstDirContents.indexOf(dstBasename) >= 0)
+          })
+      })
+    })
+  })
+
   describe('fs.linkSync()', () => {
     const fn = fs.linkSync
     tests.forEach(test => {
diff --git a/lib/ensure/__tests__/symlink.test.js b/lib/ensure/__tests__/symlink.test.js
index 6f93958..64fdcbb 100644
--- a/lib/ensure/__tests__/symlink.test.js
+++ b/lib/ensure/__tests__/symlink.test.js
@@ -387,6 +387,29 @@ describe('fse-ensure-symlink', () => {
     })
   })
 
+  describe('ensureSymlink() promise support', () => {
+    tests.filter(test => test[2] === 'file-success').forEach(test => {
+      const args = test[0]
+      const srcpath = args[0]
+      const dstpath = args[1]
+      it(`should create symlink file using src ${srcpath} and dst ${dstpath}`, () => {
+        return ensureSymlink(srcpath, dstpath)
+          .then(() => {
+            const relative = symlinkPathsSync(srcpath, dstpath)
+            const srcContent = fs.readFileSync(relative.toCwd, 'utf8')
+            const dstDir = path.dirname(dstpath)
+            const dstBasename = path.basename(dstpath)
+            const isSymlink = fs.lstatSync(dstpath).isSymbolicLink()
+            const dstContent = fs.readFileSync(dstpath, 'utf8')
+            const dstDirContents = fs.readdirSync(dstDir)
+            assert.equal(isSymlink, true)
+            assert.equal(srcContent, dstContent)
+            assert(dstDirContents.indexOf(dstBasename) >= 0)
+          })
+      })
+    })
+  })
+
   describe('fs.symlinkSync()', () => {
     const fn = fs.symlinkSync
     tests.forEach(test => {
diff --git a/lib/ensure/file.js b/lib/ensure/file.js
index 031d130..962c21c 100644
--- a/lib/ensure/file.js
+++ b/lib/ensure/file.js
@@ -1,8 +1,10 @@
 'use strict'
 
+const u = require('universalify').fromCallback
 const path = require('path')
 const fs = require('graceful-fs')
 const mkdir = require('../mkdirs')
+const pathExists = require('../path-exists').pathExists
 
 function createFile (file, callback) {
   function makeFile () {
@@ -12,10 +14,12 @@ function createFile (file, callback) {
     })
   }
 
-  fs.exists(file, fileExists => {
+  pathExists(file, (err, fileExists) => {
+    if (err) return callback(err)
     if (fileExists) return callback()
     const dir = path.dirname(file)
-    fs.exists(dir, dirExists => {
+    pathExists(dir, (err, dirExists) => {
+      if (err) return callback(err)
       if (dirExists) return makeFile()
       mkdir.mkdirs(dir, err => {
         if (err) return callback(err)
@@ -37,9 +41,6 @@ function createFileSync (file) {
 }
 
 module.exports = {
-  createFile,
-  createFileSync,
-  // alias
-  ensureFile: createFile,
-  ensureFileSync: createFileSync
+  createFile: u(createFile),
+  createFileSync
 }
diff --git a/lib/ensure/link.js b/lib/ensure/link.js
index 8284fae..49fe379 100644
--- a/lib/ensure/link.js
+++ b/lib/ensure/link.js
@@ -1,8 +1,10 @@
 'use strict'
 
+const u = require('universalify').fromCallback
 const path = require('path')
 const fs = require('graceful-fs')
 const mkdir = require('../mkdirs')
+const pathExists = require('../path-exists').pathExists
 
 function createLink (srcpath, dstpath, callback) {
   function makeLink (srcpath, dstpath) {
@@ -12,7 +14,8 @@ function createLink (srcpath, dstpath, callback) {
     })
   }
 
-  fs.exists(dstpath, destinationExists => {
+  pathExists(dstpath, (err, destinationExists) => {
+    if (err) return callback(err)
     if (destinationExists) return callback(null)
     fs.lstat(srcpath, (err, stat) => {
       if (err) {
@@ -21,7 +24,8 @@ function createLink (srcpath, dstpath, callback) {
       }
 
       const dir = path.dirname(dstpath)
-      fs.exists(dir, dirExists => {
+      pathExists(dir, (err, dirExists) => {
+        if (err) return callback(err)
         if (dirExists) return makeLink(srcpath, dstpath)
         mkdir.mkdirs(dir, err => {
           if (err) return callback(err)
@@ -52,9 +56,6 @@ function createLinkSync (srcpath, dstpath, callback) {
 }
 
 module.exports = {
-  createLink,
-  createLinkSync,
-  // alias
-  ensureLink: createLink,
-  ensureLinkSync: createLinkSync
+  createLink: u(createLink),
+  createLinkSync
 }
diff --git a/lib/ensure/symlink-paths.js b/lib/ensure/symlink-paths.js
index e52d039..4a6b78a 100644
--- a/lib/ensure/symlink-paths.js
+++ b/lib/ensure/symlink-paths.js
@@ -2,6 +2,7 @@
 
 const path = require('path')
 const fs = require('graceful-fs')
+const pathExists = require('../path-exists').pathExists
 
 /**
  * Function that returns two types of paths, one relative to symlink, and one
@@ -40,7 +41,8 @@ function symlinkPaths (srcpath, dstpath, callback) {
   } else {
     const dstdir = path.dirname(dstpath)
     const relativeToDst = path.join(dstdir, srcpath)
-    return fs.exists(relativeToDst, exists => {
+    return pathExists(relativeToDst, (err, exists) => {
+      if (err) return callback(err)
       if (exists) {
         return callback(null, {
           'toCwd': relativeToDst,
diff --git a/lib/ensure/symlink.js b/lib/ensure/symlink.js
index 2ea9e06..847c1b9 100644
--- a/lib/ensure/symlink.js
+++ b/lib/ensure/symlink.js
@@ -1,5 +1,6 @@
 'use strict'
 
+const u = require('universalify').fromCallback
 const path = require('path')
 const fs = require('graceful-fs')
 const _mkdirs = require('../mkdirs')
@@ -14,11 +15,14 @@ const _symlinkType = require('./symlink-type')
 const symlinkType = _symlinkType.symlinkType
 const symlinkTypeSync = _symlinkType.symlinkTypeSync
 
+const pathExists = require('../path-exists').pathExists
+
 function createSymlink (srcpath, dstpath, type, callback) {
   callback = (typeof type === 'function') ? type : callback
   type = (typeof type === 'function') ? false : type
 
-  fs.exists(dstpath, destinationExists => {
+  pathExists(dstpath, (err, destinationExists) => {
+    if (err) return callback(err)
     if (destinationExists) return callback(null)
     symlinkPaths(srcpath, dstpath, (err, relative) => {
       if (err) return callback(err)
@@ -26,7 +30,8 @@ function createSymlink (srcpath, dstpath, type, callback) {
       symlinkType(relative.toCwd, type, (err, type) => {
         if (err) return callback(err)
         const dir = path.dirname(dstpath)
-        fs.exists(dir, dirExists => {
+        pathExists(dir, (err, dirExists) => {
+          if (err) return callback(err)
           if (dirExists) return fs.symlink(srcpath, dstpath, type, callback)
           mkdirs(dir, err => {
             if (err) return callback(err)
@@ -56,9 +61,6 @@ function createSymlinkSync (srcpath, dstpath, type, callback) {
 }
 
 module.exports = {
-  createSymlink,
-  createSymlinkSync,
-  // alias
-  ensureSymlink: createSymlink,
-  ensureSymlinkSync: createSymlinkSync
+  createSymlink: u(createSymlink),
+  createSymlinkSync
 }
diff --git a/lib/__tests__/fs-integration.test.js b/lib/fs/__tests__/fs-integration.test.js
similarity index 96%
rename from lib/__tests__/fs-integration.test.js
rename to lib/fs/__tests__/fs-integration.test.js
index 4ff52c5..ea19c1f 100644
--- a/lib/__tests__/fs-integration.test.js
+++ b/lib/fs/__tests__/fs-integration.test.js
@@ -2,7 +2,7 @@
 
 const os = require('os')
 const fs = require('fs')
-const fse = require('../')
+const fse = require('../..')
 const path = require('path')
 const assert = require('assert')
 
diff --git a/lib/fs/__tests__/mz.test.js b/lib/fs/__tests__/mz.test.js
new file mode 100644
index 0000000..5c61f33
--- /dev/null
+++ b/lib/fs/__tests__/mz.test.js
@@ -0,0 +1,50 @@
+// This is adapted from https://github.com/normalize/mz
+// Copyright (c) 2014-2016 Jonathan Ong me at jongleberry.com and Contributors
+
+/* eslint-env mocha */
+const assert = require('assert')
+const fs = require('../..')
+
+describe('fs', () => {
+  it('.stat()', done => {
+    fs.stat(__filename).then(function (stats) {
+      assert.equal(typeof stats.size, 'number')
+      done()
+    }).catch(done)
+  })
+
+  it('.statSync()', () => {
+    const stats = fs.statSync(__filename)
+    assert.equal(typeof stats.size, 'number')
+  })
+
+  it('.exists()', done => {
+    fs.exists(__filename).then(function (exists) {
+      assert(exists)
+      done()
+    }).catch(done)
+  })
+
+  it('.existsSync()', () => {
+    const exists = fs.existsSync(__filename)
+    assert(exists)
+  })
+
+  describe('callback support', () => {
+    it('.stat()', done => {
+      fs.stat(__filename, function (err, stats) {
+        assert(!err)
+        assert.equal(typeof stats.size, 'number')
+        done()
+      })
+    })
+
+    // This test is different from mz/fs, since we are a drop-in replacement for native fs
+    it('.exists()', done => {
+      fs.exists(__filename, function (exists) {
+        assert(exists)
+        done()
+      })
+    })
+  })
+})
diff --git a/lib/fs/index.js b/lib/fs/index.js
new file mode 100644
index 0000000..e20ae76
--- /dev/null
+++ b/lib/fs/index.js
@@ -0,0 +1,61 @@
+// This is adapted from https://github.com/normalize/mz
+// Copyright (c) 2014-2016 Jonathan Ong me at jongleberry.com and Contributors
+const u = require('universalify').fromCallback
+const fs = require('graceful-fs')
+
+const api = [
+  'access',
+  'appendFile',
+  'chmod',
+  'chown',
+  'close',
+  'fchmod',
+  'fchown',
+  'fdatasync',
+  'fstat',
+  'fsync',
+  'ftruncate',
+  'futimes',
+  'lchown',
+  'link',
+  'lstat',
+  'mkdir',
+  'open',
+  'read',
+  'readFile',
+  'readdir',
+  'readlink',
+  'realpath',
+  'rename',
+  'rmdir',
+  'stat',
+  'symlink',
+  'truncate',
+  'unlink',
+  'utimes',
+  'write',
+  'writeFile'
+]
+// fs.mkdtemp() was added in Node.js v5.10.0, so check if it exists
+typeof fs.mkdtemp === 'function' && api.push('mkdtemp')
+
+// Export all keys:
+Object.keys(fs).forEach(key => {
+  exports[key] = fs[key]
+})
+
+// Universalify async methods:
+api.forEach(method => {
+  exports[method] = u(fs[method])
+})
+
+// We differ from mz/fs in that we still ship the old, broken, fs.exists()
+// since we are a drop-in replacement for the native module
+exports.exists = function (filename, callback) {
+  if (typeof callback === 'function') {
+    return fs.exists(filename, callback)
+  }
+  return new Promise(resolve => {
+    return fs.exists(filename, resolve)
+  })
+}
diff --git a/lib/index.js b/lib/index.js
index d25fd54..cb7dd9e 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -2,16 +2,11 @@
 
 const assign = require('./util/assign')
 
-const fse = {}
-const gfs = require('graceful-fs')
-
-// attach fs methods to fse
-Object.keys(gfs).forEach(key => {
-  fse[key] = gfs[key]
-})
-
-const fs = fse
+const fs = {}
 
+// Export graceful-fs:
+assign(fs, require('./fs'))
+// Export extra methods:
 assign(fs, require('./copy'))
 assign(fs, require('./copy-sync'))
 assign(fs, require('./mkdirs'))
@@ -22,16 +17,6 @@ assign(fs, require('./move-sync'))
 assign(fs, require('./empty'))
 assign(fs, require('./ensure'))
 assign(fs, require('./output'))
+assign(fs, require('./path-exists'))
 
 module.exports = fs
-
-// maintain backwards compatibility for awhile
-const jsonfile = {}
-Object.defineProperty(jsonfile, 'spaces', {
-  get: () => fs.spaces, // found in ./json
-  set: val => {
-    fs.spaces = val
-  }
-})
-
-module.exports.jsonfile = jsonfile // so users of fs-extra can modify jsonFile.spaces
diff --git a/lib/json/__tests__/jsonfile-integration.test.js b/lib/json/__tests__/jsonfile-integration.test.js
index 27f7665..64177de 100644
--- a/lib/json/__tests__/jsonfile-integration.test.js
+++ b/lib/json/__tests__/jsonfile-integration.test.js
@@ -25,15 +25,10 @@ describe('jsonfile-integration', () => {
         lastName: 'Richardson'
       }
 
-      const oldSpaces = fse.jsonfile.spaces
-      fse.jsonfile.spaces = 4
-
       const file = path.join(TEST_DIR, 'file.json')
       fse.writeJsonSync(file, obj1)
       const data = fs.readFileSync(file, 'utf8')
-      assert.strictEqual(data, JSON.stringify(obj1, null, 4) + '\n')
-
-      fse.jsonfile.spaces = oldSpaces
+      assert.strictEqual(data, JSON.stringify(obj1) + '\n')
     })
   })
 })
diff --git a/lib/json/__tests__/output-json.test.js b/lib/json/__tests__/output-json.test.js
index 03b4714..192084f 100644
--- a/lib/json/__tests__/output-json.test.js
+++ b/lib/json/__tests__/output-json.test.js
@@ -34,6 +34,14 @@ describe('json', () => {
       })
     })
 
+    it('should support Promises', () => {
+      const file = path.join(TEST_DIR, 'this-dir', 'prob-does-not', 'exist', 'file.json')
+      assert(!fs.existsSync(file))
+
+      const data = {name: 'JP'}
+      return outputJson(file, data)
+    })
+
     describe('> when an option is passed, like JSON replacer', () => {
       it('should pass the option along to jsonfile module', done => {
         const file = path.join(TEST_DIR, 'this-dir', 'does-not', 'exist', 'really', 'file.json')
diff --git a/lib/json/__tests__/spaces.test.js b/lib/json/__tests__/spaces.test.js
deleted file mode 100644
index ab428c8..0000000
--- a/lib/json/__tests__/spaces.test.js
+++ /dev/null
@@ -1,34 +0,0 @@
-'use strict'
-
-const fs = require('fs')
-const os = require('os')
-const fse = require('../../')
-const path = require('path')
-const assert = require('assert')
-
-/* global afterEach, beforeEach, describe, it */
-// trinity: mocha
-
-describe('json spaces', () => {
-  let TEST_DIR
-
-  beforeEach(done => {
-    TEST_DIR = path.join(os.tmpdir(), 'fs-extra', 'json-spaces')
-    fse.emptyDir(TEST_DIR, done)
-  })
-
-  afterEach(done => fse.remove(TEST_DIR, done))
-
-  it('should write out the file with appropriate spacing (2)', () => {
-    fse.spaces = 2 // for legacy compatibility
-    assert.strictEqual(fse.spaces, 2)
-
-    const tempFile = path.join(TEST_DIR, 'temp.json')
-
-    const data = { first: 'JP', last: 'Richardson' }
-    fse.outputJsonSync(tempFile, data)
-
-    const dataRead = fs.readFileSync(tempFile, 'utf8')
-    assert.strictEqual(dataRead, JSON.stringify(data, null, 2) + '\n')
-  })
-})
diff --git a/lib/json/index.js b/lib/json/index.js
index 4229311..717d48f 100644
--- a/lib/json/index.js
+++ b/lib/json/index.js
@@ -1,11 +1,16 @@
 'use strict'
 
+const u = require('universalify').fromCallback
 const jsonFile = require('./jsonfile')
 
 jsonFile.outputJsonSync = require('./output-json-sync')
-jsonFile.outputJson = require('./output-json')
+jsonFile.outputJson = u(require('./output-json'))
 // aliases
-jsonFile.outputJSONSync = require('./output-json-sync')
-jsonFile.outputJSON = require('./output-json')
+jsonFile.outputJSONSync = jsonFile.outputJSONSync
+jsonFile.outputJSON = jsonFile.outputJson
+jsonFile.writeJSON = jsonFile.writeJson
+jsonFile.writeJSONSync = jsonFile.writeJsonSync
+jsonFile.readJSON = jsonFile.readJson
+jsonFile.readJSONSync = jsonFile.readJsonSync
 
 module.exports = jsonFile
diff --git a/lib/json/jsonfile.js b/lib/json/jsonfile.js
index e3630ee..59cdb3e 100644
--- a/lib/json/jsonfile.js
+++ b/lib/json/jsonfile.js
@@ -1,16 +1,12 @@
 'use strict'
 
+const u = require('universalify').fromCallback
 const jsonFile = require('jsonfile')
 
 module.exports = {
   // jsonfile exports
-  readJson: jsonFile.readFile,
-  readJSON: jsonFile.readFile,
+  readJson: u(jsonFile.readFile),
   readJsonSync: jsonFile.readFileSync,
-  readJSONSync: jsonFile.readFileSync,
-  writeJson: jsonFile.writeFile,
-  writeJSON: jsonFile.writeFile,
-  writeJsonSync: jsonFile.writeFileSync,
-  writeJSONSync: jsonFile.writeFileSync,
-  spaces: 2 // default in fs-extra
+  writeJson: u(jsonFile.writeFile),
+  writeJsonSync: jsonFile.writeFileSync
 }
diff --git a/lib/json/output-json.js b/lib/json/output-json.js
index 2f928c5..d45edb8 100644
--- a/lib/json/output-json.js
+++ b/lib/json/output-json.js
@@ -1,8 +1,8 @@
 'use strict'
 
-const fs = require('graceful-fs')
 const path = require('path')
 const mkdir = require('../mkdirs')
+const pathExists = require('../path-exists').pathExists
 const jsonFile = require('./jsonfile')
 
 function outputJson (file, data, options, callback) {
@@ -13,7 +13,8 @@ function outputJson (file, data, options, callback) {
 
   const dir = path.dirname(file)
 
-  fs.exists(dir, itDoes => {
+  pathExists(dir, (err, itDoes) => {
+    if (err) return callback(err)
     if (itDoes) return jsonFile.writeJson(file, data, options, callback)
 
     mkdir.mkdirs(dir, err => {
diff --git a/lib/mkdirs/__tests__/mkdirp.test.js b/lib/mkdirs/__tests__/mkdirp.test.js
index 7ad3868..dc52e1f 100644
--- a/lib/mkdirs/__tests__/mkdirp.test.js
+++ b/lib/mkdirs/__tests__/mkdirp.test.js
@@ -31,7 +31,8 @@ describe('mkdirp / mkdirp', () => {
 
     fse.mkdirp(file, o755, err => {
       assert.ifError(err)
-      fs.exists(file, ex => {
+      fse.pathExists(file, (err, ex) => {
+        assert.ifError(err)
         assert.ok(ex, 'file created')
         fs.stat(file, (err, stat) => {
           assert.ifError(err)
diff --git a/lib/mkdirs/__tests__/perm.test.js b/lib/mkdirs/__tests__/perm.test.js
index 873ed6a..77c6d19 100644
--- a/lib/mkdirs/__tests__/perm.test.js
+++ b/lib/mkdirs/__tests__/perm.test.js
@@ -27,7 +27,8 @@ describe('mkdirp / perm', () => {
 
     fse.mkdirp(file, o755, err => {
       assert.ifError(err)
-      fs.exists(file, ex => {
+      fse.pathExists(file, (err, ex) => {
+        assert.ifError(err)
         assert.ok(ex, 'file created')
         fs.stat(file, (err, stat) => {
           assert.ifError(err)
diff --git a/lib/mkdirs/__tests__/perm_sync.test.js b/lib/mkdirs/__tests__/perm_sync.test.js
index cfd53be..4352171 100644
--- a/lib/mkdirs/__tests__/perm_sync.test.js
+++ b/lib/mkdirs/__tests__/perm_sync.test.js
@@ -26,7 +26,8 @@ describe('mkdirp / perm_sync', () => {
     const file = path.join(TEST_DIR, (Math.random() * (1 << 30)).toString(16) + '.json')
 
     fse.mkdirpSync(file, o755)
-    fs.exists(file, ex => {
+    fse.pathExists(file, (err, ex) => {
+      assert.ifError(err)
       assert.ok(ex, 'file created')
       fs.stat(file, (err, stat) => {
         assert.ifError(err)
@@ -46,7 +47,8 @@ describe('mkdirp / perm_sync', () => {
   it('sync root perm', done => {
     const file = TEST_DIR
     fse.mkdirpSync(file, o755)
-    fs.exists(file, ex => {
+    fse.pathExists(file, (err, ex) => {
+      assert.ifError(err)
       assert.ok(ex, 'file created')
       fs.stat(file, (err, stat) => {
         assert.ifError(err)
diff --git a/lib/mkdirs/__tests__/race.test.js b/lib/mkdirs/__tests__/race.test.js
index 982b713..afec9f4 100644
--- a/lib/mkdirs/__tests__/race.test.js
+++ b/lib/mkdirs/__tests__/race.test.js
@@ -44,7 +44,8 @@ describe('mkdirp / race', () => {
     function mk (file, callback) {
       fse.mkdirp(file, o755, err => {
         assert.ifError(err)
-        fs.exists(file, ex => {
+        fse.pathExists(file, (err, ex) => {
+          assert.ifError(err)
           assert.ok(ex, 'file created')
           fs.stat(file, (err, stat) => {
             assert.ifError(err)
diff --git a/lib/mkdirs/__tests__/rel.test.js b/lib/mkdirs/__tests__/rel.test.js
index 4971d0e..29a940a 100644
--- a/lib/mkdirs/__tests__/rel.test.js
+++ b/lib/mkdirs/__tests__/rel.test.js
@@ -41,7 +41,8 @@ describe('mkdirp / relative', () => {
 
     fse.mkdirp(file, o755, err => {
       assert.ifError(err)
-      fs.exists(file, ex => {
+      fse.pathExists(file, (err, ex) => {
+        assert.ifError(err)
         assert.ok(ex, 'file created')
         fs.stat(file, (err, stat) => {
           assert.ifError(err)
diff --git a/lib/mkdirs/__tests__/sync.test.js b/lib/mkdirs/__tests__/sync.test.js
index a7033fe..b745478 100644
--- a/lib/mkdirs/__tests__/sync.test.js
+++ b/lib/mkdirs/__tests__/sync.test.js
@@ -40,7 +40,8 @@ describe('mkdirp / sync', () => {
       assert.fail(err)
     }
 
-    fs.exists(file, ex => {
+    fse.pathExists(file, (err, ex) => {
+      assert.ifError(err)
       assert.ok(ex, 'file created')
       fs.stat(file, (err, stat) => {
         assert.ifError(err)
diff --git a/lib/mkdirs/__tests__/umask.test.js b/lib/mkdirs/__tests__/umask.test.js
index a3d06e7..7195806 100644
--- a/lib/mkdirs/__tests__/umask.test.js
+++ b/lib/mkdirs/__tests__/umask.test.js
@@ -42,7 +42,8 @@ describe('mkdirp', () => {
 
         fse.mkdirp(_rndDir, err => {
           assert.ifError(err)
-          fs.exists(_rndDir, ex => {
+          fse.pathExists(_rndDir, (err, ex) => {
+            assert.ifError(err)
             assert.ok(ex, 'file created')
             fs.stat(_rndDir, (err, stat) => {
               assert.ifError(err)
@@ -65,7 +66,8 @@ describe('mkdirp', () => {
           return done(err)
         }
 
-        fs.exists(_rndDir, ex => {
+        fse.pathExists(_rndDir, (err, ex) => {
+          assert.ifError(err)
           assert.ok(ex, 'file created')
           fs.stat(_rndDir, (err, stat) => {
             assert.ifError(err)
diff --git a/lib/mkdirs/index.js b/lib/mkdirs/index.js
index 2611217..29975c5 100644
--- a/lib/mkdirs/index.js
+++ b/lib/mkdirs/index.js
@@ -1,9 +1,14 @@
+'use strict'
+const u = require('universalify').fromCallback
+const mkdirs = u(require('./mkdirs'))
+const mkdirsSync = require('./mkdirs-sync')
+
 module.exports = {
-  mkdirs: require('./mkdirs'),
-  mkdirsSync: require('./mkdirs-sync'),
+  mkdirs: mkdirs,
+  mkdirsSync: mkdirsSync,
   // alias
-  mkdirp: require('./mkdirs'),
-  mkdirpSync: require('./mkdirs-sync'),
-  ensureDir: require('./mkdirs'),
-  ensureDirSync: require('./mkdirs-sync')
+  mkdirp: mkdirs,
+  mkdirpSync: mkdirsSync,
+  ensureDir: mkdirs,
+  ensureDirSync: mkdirsSync
 }
diff --git a/lib/move-sync/__tests__/move-sync.test.js b/lib/move-sync/__tests__/move-sync.test.js
index 58361a9..48da8f1 100644
--- a/lib/move-sync/__tests__/move-sync.test.js
+++ b/lib/move-sync/__tests__/move-sync.test.js
@@ -61,6 +61,13 @@ describe('moveSync()', () => {
     assert.ok(contents.match(expected), `${contents} match ${expected}`)
   })
 
+  it('should error if src and dest are the same and src does not exist', () => {
+    const src = `${TEST_DIR}/non-existent`
+    const dest = src
+
+    assert.throws(() => fse.moveSync(src, dest))
+  })
+
   it('should rename a file on the same device', () => {
     const src = `${TEST_DIR}/a-file`
     const dest = `${TEST_DIR}/a-file-dest`
@@ -115,12 +122,6 @@ describe('moveSync()', () => {
   })
 
   it('should overwrite the destination directory if overwrite = true', function (done) {
-    // Tests fail on appveyor/Windows due to
-    // https://github.com/isaacs/node-graceful-fs/issues/98.
-    // Workaround by increasing the timeout by a minute (because
-    // graceful times out after a minute).
-    this.timeout(90000)
-
     // Create src
     const src = path.join(TEST_DIR, 'src')
     fse.ensureDirSync(src)
diff --git a/lib/move-sync/index.js b/lib/move-sync/index.js
index 3c2aa93..a5e9114 100644
--- a/lib/move-sync/index.js
+++ b/lib/move-sync/index.js
@@ -5,6 +5,7 @@ const path = require('path')
 const copySync = require('../copy-sync').copySync
 const removeSync = require('../remove').removeSync
 const mkdirpSync = require('../mkdirs').mkdirsSync
+const buffer = require('../util/buffer')
 
 function moveSync (src, dest, options) {
   options = options || {}
@@ -13,7 +14,7 @@ function moveSync (src, dest, options) {
   src = path.resolve(src)
   dest = path.resolve(dest)
 
-  if (src === dest) return
+  if (src === dest) return fs.accessSync(src)
 
   if (isSrcSubdir(src, dest)) throw new Error(`Cannot move '${src}' into itself '${dest}'.`)
 
@@ -60,7 +61,7 @@ function moveSyncAcrossDevice (src, dest, overwrite) {
 
 function moveFileSyncAcrossDevice (src, dest, overwrite) {
   const BUF_LENGTH = 64 * 1024
-  const _buff = new Buffer(BUF_LENGTH)
+  const _buff = buffer(BUF_LENGTH)
 
   const flags = overwrite ? 'w' : 'wx'
 
diff --git a/lib/move/__tests__/move.test.js b/lib/move/__tests__/move.test.js
index 31469cd..988a75c 100644
--- a/lib/move/__tests__/move.test.js
+++ b/lib/move/__tests__/move.test.js
@@ -79,6 +79,16 @@ describe('move', () => {
     })
   })
 
+  it('should error if source and destination are the same and source does not exist', done => {
+    const src = `${TEST_DIR}/non-existent`
+    const dest = src
+
+    fse.move(src, dest, err => {
+      assert(err)
+      done()
+    })
+  })
+
   it('should not move a directory if source and destination are the same', done => {
     const src = `${TEST_DIR}/a-folder`
     const dest = src
@@ -134,12 +144,6 @@ describe('move', () => {
   })
 
   it('should overwrite the destination directory if overwrite = true', function (done) {
-    // Tests fail on appveyor/Windows due to
-    // https://github.com/isaacs/node-graceful-fs/issues/98.
-    // Workaround by increasing the timeout by a minute (because
-    // graceful times out after a minute).
-    this.timeout(90000)
-
     // Create src
     const src = path.join(TEST_DIR, 'src')
     fse.ensureDirSync(src)
diff --git a/lib/move/index.js b/lib/move/index.js
index 6bbdaf4..e5eb2c1 100644
--- a/lib/move/index.js
+++ b/lib/move/index.js
@@ -6,6 +6,7 @@
 
 // this needs a cleanup
 
+const u = require('universalify').fromCallback
 const fs = require('graceful-fs')
 const ncp = require('../copy/ncp')
 const path = require('path')
@@ -36,7 +37,7 @@ function move (source, dest, options, callback) {
 
   function doRename () {
     if (path.resolve(source) === path.resolve(dest)) {
-      setImmediate(callback)
+      fs.access(source, callback)
     } else if (overwrite) {
       fs.rename(source, dest, err => {
         if (!err) return callback()
@@ -157,5 +158,5 @@ function moveDirAcrossDevice (source, dest, overwrite, callback) {
 }
 
 module.exports = {
-  move
+  move: u(move)
 }
diff --git a/lib/output/__tests__/output.test.js b/lib/output/__tests__/output.test.js
index 59ff05f..103737c 100644
--- a/lib/output/__tests__/output.test.js
+++ b/lib/output/__tests__/output.test.js
@@ -30,6 +30,11 @@ describe('output', () => {
           done()
         })
       })
+      it('should support promises', () => {
+        const file = path.join(TEST_DIR, Math.random() + 't-ne', Math.random() + '.txt')
+        assert(!fs.existsSync(file))
+        return fse.outputFile(file, 'hi jp')
+      })
     })
 
     describe('> when the file does exist', () => {
diff --git a/lib/output/index.js b/lib/output/index.js
index f4eb9bb..53d5905 100644
--- a/lib/output/index.js
+++ b/lib/output/index.js
@@ -1,8 +1,10 @@
 'use strict'
 
+const u = require('universalify').fromCallback
 const fs = require('graceful-fs')
 const path = require('path')
 const mkdir = require('../mkdirs')
+const pathExists = require('../path-exists').pathExists
 
 function outputFile (file, data, encoding, callback) {
   if (typeof encoding === 'function') {
@@ -11,7 +13,8 @@ function outputFile (file, data, encoding, callback) {
   }
 
   const dir = path.dirname(file)
-  fs.exists(dir, itDoes => {
+  pathExists(dir, (err, itDoes) => {
+    if (err) return callback(err)
     if (itDoes) return fs.writeFile(file, data, encoding, callback)
 
     mkdir.mkdirs(dir, err => {
@@ -32,6 +35,6 @@ function outputFileSync (file, data, encoding) {
 }
 
 module.exports = {
-  outputFile,
+  outputFile: u(outputFile),
   outputFileSync
 }
diff --git a/lib/path-exists/__tests__/path-exists-sync.test.js b/lib/path-exists/__tests__/path-exists-sync.test.js
new file mode 100644
index 0000000..dbde2b4
--- /dev/null
+++ b/lib/path-exists/__tests__/path-exists-sync.test.js
@@ -0,0 +1,28 @@
+'use strict'
+/* eslint-env mocha */
+
+const fs = require(process.cwd())
+const path = require('path')
+const os = require('os')
+const assert = require('assert')
+
+describe('pathExists()', () => {
+  let TEST_DIR
+
+  beforeEach(done => {
+    TEST_DIR = path.join(os.tmpdir(), 'fs-extra', 'path-exists')
+    fs.emptyDir(TEST_DIR, done)
+  })
+
+  afterEach(done => fs.remove(TEST_DIR, done))
+
+  it('should return false if file does not exist', () => {
+    assert(!fs.pathExistsSync(path.join(TEST_DIR, 'somefile')))
+  })
+
+  it('should return true if file does exist', () => {
+    const file = path.join(TEST_DIR, 'exists')
+    fs.ensureFileSync(file)
+    assert(fs.pathExistsSync(file))
+  })
+})
diff --git a/lib/path-exists/__tests__/path-exists.test.js b/lib/path-exists/__tests__/path-exists.test.js
new file mode 100644
index 0000000..abc1e63
--- /dev/null
+++ b/lib/path-exists/__tests__/path-exists.test.js
@@ -0,0 +1,40 @@
+'use strict'
+/* eslint-env mocha */
+
+const fs = require(process.cwd())
+const path = require('path')
+const os = require('os')
+const assert = require('assert')
+
+describe('pathExists()', () => {
+  let TEST_DIR
+
+  beforeEach(done => {
+    TEST_DIR = path.join(os.tmpdir(), 'fs-extra', 'path-exists')
+    fs.emptyDir(TEST_DIR, done)
+  })
+
+  afterEach(done => fs.remove(TEST_DIR, done))
+
+  it('should return false if file does not exist', () => {
+    return fs.pathExists(path.join(TEST_DIR, 'somefile'))
+      .then(exists => assert(!exists))
+  })
+
+  it('should return true if file does exist', () => {
+    const file = path.join(TEST_DIR, 'exists')
+    fs.ensureFileSync(file)
+    return fs.pathExists(file)
+      .then(exists => assert(exists))
+  })
+
+  it('should pass an empty error parameter to the callback', done => {
+    const file = path.join(TEST_DIR, 'exists')
+    fs.ensureFileSync(file)
+    fs.pathExists(file, (err, exists) => {
+      assert.ifError(err)
+      assert(exists)
+      done()
+    })
+  })
+})
diff --git a/lib/path-exists/index.js b/lib/path-exists/index.js
new file mode 100644
index 0000000..ddd9bc7
--- /dev/null
+++ b/lib/path-exists/index.js
@@ -0,0 +1,12 @@
+'use strict'
+const u = require('universalify').fromPromise
+const fs = require('../fs')
+
+function pathExists (path) {
+  return fs.access(path).then(() => true).catch(() => false)
+}
+
+module.exports = {
+  pathExists: u(pathExists),
+  pathExistsSync: fs.existsSync
+}
diff --git a/lib/remove/__tests__/remove.test.js b/lib/remove/__tests__/remove.test.js
index d7c2fbd..92979d5 100644
--- a/lib/remove/__tests__/remove.test.js
+++ b/lib/remove/__tests__/remove.test.js
@@ -71,7 +71,8 @@ describe('remove', () => {
 
       assert(fs.existsSync(file))
       const existsChecker = setInterval(() => {
-        fs.exists(file, (itDoes) => {
+        fse.pathExists(file, (err, itDoes) => {
+          assert.ifError(err)
           if (!itDoes) {
             clearInterval(existsChecker)
             done()
diff --git a/lib/remove/index.js b/lib/remove/index.js
index 0e3b5dd..cee5340 100644
--- a/lib/remove/index.js
+++ b/lib/remove/index.js
@@ -1,17 +1,9 @@
 'use strict'
 
+const u = require('universalify').fromCallback
 const rimraf = require('./rimraf')
 
-function removeSync (dir) {
-  return rimraf.sync(dir, {disableGlob: true})
-}
-
-function remove (dir, callback) {
-  const options = {disableGlob: true}
-  return callback ? rimraf(dir, options, callback) : rimraf(dir, options, function () {})
-}
-
 module.exports = {
-  remove,
-  removeSync
+  remove: u(rimraf),
+  removeSync: rimraf.sync
 }
diff --git a/lib/remove/rimraf.js b/lib/remove/rimraf.js
index 141a82d..28d4aeb 100644
--- a/lib/remove/rimraf.js
+++ b/lib/remove/rimraf.js
@@ -275,12 +275,12 @@ function rmdirSync (p, options, originalEr) {
   try {
     options.rmdirSync(p)
   } catch (er) {
-    if (er.code === 'ENOENT') {
-      return
-    } else if (er.code === 'ENOTDIR') {
+    if (er.code === 'ENOTDIR') {
       throw originalEr
     } else if (er.code === 'ENOTEMPTY' || er.code === 'EEXIST' || er.code === 'EPERM') {
       rmkidsSync(p, options)
+    } else if (er.code !== 'ENOENT') {
+      throw er
     }
   }
 }
diff --git a/lib/util/buffer.js b/lib/util/buffer.js
new file mode 100644
index 0000000..93af51b
--- /dev/null
+++ b/lib/util/buffer.js
@@ -0,0 +1,11 @@
+/* eslint-disable node/no-deprecated-api */
+module.exports = function (size) {
+  if (typeof Buffer.allocUnsafe === 'function') {
+    try {
+      return Buffer.allocUnsafe(size)
+    } catch (e) {
+      return new Buffer(size)
+    }
+  }
+  return new Buffer(size)
+}
diff --git a/package.json b/package.json
index d489494..e539c95 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "fs-extra",
-  "version": "2.1.2",
+  "version": "3.0.1",
   "description": "fs-extra contains methods that aren't included in the vanilla Node.js fs package. Such as mkdir -p, cp -r, and rm -rf.",
   "homepage": "https://github.com/jprichardson/node-fs-extra",
   "repository": {
@@ -34,7 +34,8 @@
   "license": "MIT",
   "dependencies": {
     "graceful-fs": "^4.1.2",
-    "jsonfile": "^2.1.0"
+    "jsonfile": "^3.0.0",
+    "universalify": "^0.1.0"
   },
   "devDependencies": {
     "coveralls": "^2.11.2",
@@ -47,13 +48,14 @@
     "read-dir-files": "^0.1.1",
     "rimraf": "^2.2.8",
     "secure-random": "^1.1.1",
-    "standard": "^8.5.0"
+    "standard": "^10.0.2",
+    "standard-markdown": "^2.3.0"
   },
   "main": "./lib/index",
   "scripts": {
     "coverage": "istanbul cover -i 'lib/**' -x '**/__tests__/**' test.js",
     "coveralls": "npm run coverage && coveralls < coverage/lcov.info",
-    "lint": "standard",
+    "lint": "standard && standard-markdown",
     "test-find": "find ./lib/**/__tests__ -name *.test.js | xargs mocha",
     "test": "npm run lint && npm run unit",
     "unit": "node test.js"

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-fs-extra.git



More information about the Pkg-javascript-commits mailing list