summaryrefslogtreecommitdiff
path: root/deps/npm/node_modules/fs-write-stream-atomic
diff options
context:
space:
mode:
authorRebecca Turner <me@re-becca.org>2016-01-28 18:11:35 -0800
committerJeremiah Senkpiel <fishrock123@rocketmail.com>2016-02-01 10:43:34 -0500
commit76cb81b354de8447898427619c66c86c59b22b3d (patch)
tree0c0826bed77086fb38cda8dc680d4fb10d2cff25 /deps/npm/node_modules/fs-write-stream-atomic
parentd5d301f3032a0723f5a29cfbe0d95ac4ad205d42 (diff)
downloadandroid-node-v8-76cb81b354de8447898427619c66c86c59b22b3d.tar.gz
android-node-v8-76cb81b354de8447898427619c66c86c59b22b3d.tar.bz2
android-node-v8-76cb81b354de8447898427619c66c86c59b22b3d.zip
deps: upgrade npm to 3.6.0
PR-URL: https://github.com/nodejs/node/pull/4958 Reviewed-By: Myles Borins <mborins@us.ibm.com> Reviewed-By: Kat Marchán <kzm@sykosomatic.org> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Diffstat (limited to 'deps/npm/node_modules/fs-write-stream-atomic')
-rw-r--r--deps/npm/node_modules/fs-write-stream-atomic/.npmignore3
-rw-r--r--deps/npm/node_modules/fs-write-stream-atomic/.travis.yml11
-rw-r--r--deps/npm/node_modules/fs-write-stream-atomic/index.js162
-rw-r--r--deps/npm/node_modules/fs-write-stream-atomic/package.json102
-rw-r--r--deps/npm/node_modules/fs-write-stream-atomic/test/basic.js62
-rw-r--r--deps/npm/node_modules/fs-write-stream-atomic/test/chown.js44
-rw-r--r--deps/npm/node_modules/fs-write-stream-atomic/test/rename-fail.js30
-rw-r--r--deps/npm/node_modules/fs-write-stream-atomic/test/slow-close.js40
-rw-r--r--deps/npm/node_modules/fs-write-stream-atomic/test/toolong.js9
9 files changed, 331 insertions, 132 deletions
diff --git a/deps/npm/node_modules/fs-write-stream-atomic/.npmignore b/deps/npm/node_modules/fs-write-stream-atomic/.npmignore
new file mode 100644
index 0000000000..2f24c57c38
--- /dev/null
+++ b/deps/npm/node_modules/fs-write-stream-atomic/.npmignore
@@ -0,0 +1,3 @@
+node_modules/
+coverage/
+.nyc_output/
diff --git a/deps/npm/node_modules/fs-write-stream-atomic/.travis.yml b/deps/npm/node_modules/fs-write-stream-atomic/.travis.yml
new file mode 100644
index 0000000000..6894662527
--- /dev/null
+++ b/deps/npm/node_modules/fs-write-stream-atomic/.travis.yml
@@ -0,0 +1,11 @@
+language: node_js
+sudo: false
+before_install:
+ - "npm -g install npm"
+node_js:
+ - "0.8"
+ - "0.10"
+ - "0.12"
+ - "iojs"
+ - "4"
+ - "5"
diff --git a/deps/npm/node_modules/fs-write-stream-atomic/index.js b/deps/npm/node_modules/fs-write-stream-atomic/index.js
index d86b8c673f..59b50db6d7 100644
--- a/deps/npm/node_modules/fs-write-stream-atomic/index.js
+++ b/deps/npm/node_modules/fs-write-stream-atomic/index.js
@@ -1,96 +1,124 @@
var fs = require('graceful-fs')
+var Writable = require('readable-stream').Writable
var util = require('util')
-var crypto = require('crypto')
+var MurmurHash3 = require('imurmurhash')
+var iferr = require('iferr')
-function md5hex () {
- var hash = crypto.createHash('md5')
- for (var ii=0; ii<arguments.length; ++ii) {
- hash.update(''+arguments[ii])
+function murmurhex () {
+ var hash = MurmurHash3('')
+ for (var ii = 0; ii < arguments.length; ++ii) {
+ hash.hash(hash + arguments[ii])
}
- return hash.digest('hex')
+ return hash.result()
}
-var invocations = 0;
+var invocations = 0
function getTmpname (filename) {
- return filename + "." + md5hex(__filename, process.pid, ++invocations)
+ return filename + '.' + murmurhex(__filename, process.pid, ++invocations)
}
-module.exports = WriteStream
+var setImmediate = global.setImmediate || setTimeout
-util.inherits(WriteStream, fs.WriteStream)
-function WriteStream (path, options) {
- if (!options)
- options = {}
+module.exports = WriteStreamAtomic
- if (!(this instanceof WriteStream))
- return new WriteStream(path, options)
+// Requirements:
+// 1. Write everything written to the stream to a temp file.
+// 2. If there are no errors:
+// a. moves the temp file into its final destination
+// b. emits `finish` & `closed` ONLY after the file is
+// fully flushed and renamed.
+// 3. If there's an error, removes the temp file.
+
+util.inherits(WriteStreamAtomic, Writable)
+function WriteStreamAtomic (path, options) {
+ if (!(this instanceof WriteStreamAtomic)) {
+ return new WriteStreamAtomic(path, options)
+ }
+ Writable.call(this, options)
this.__atomicTarget = path
- this.__atomicChown = options.chown
- this.__atomicDidStuff = false
this.__atomicTmp = getTmpname(path)
- fs.WriteStream.call(this, this.__atomicTmp, options)
+ this.__atomicChown = options && options.chown
+
+ this.__atomicClosed = false
+
+ this.__atomicStream = fs.WriteStream(this.__atomicTmp, options)
+
+ this.__atomicStream.once('open', handleOpen(this))
+ this.__atomicStream.once('close', handleClose(this))
+ this.__atomicStream.once('error', handleError(this))
+}
+
+// We have to suppress default finish emitting, because ordinarily it
+// would happen as soon as `end` is called on us and all of the
+// data has been written to our target stream. So we suppress
+// finish from being emitted here, and only emit it after our
+// target stream is closed and we've moved everything around.
+WriteStreamAtomic.prototype.emit = function (event) {
+ if (event === 'finish') return this.__atomicStream.end()
+ return Writable.prototype.emit.apply(this, arguments)
}
-function cleanup (er) {
- fs.unlink(this.__atomicTmp, function () {
- fs.WriteStream.prototype.emit.call(this, 'error', er)
- }.bind(this))
+WriteStreamAtomic.prototype._write = function (buffer, encoding, cb) {
+ var flushed = this.__atomicStream.write(buffer, encoding)
+ if (flushed) return cb()
+ this.__atomicStream.once('drain', cb)
}
-function cleanupSync () {
- try {
- fs.unlinkSync(this.__atomicTmp)
- } finally {
- return
+function handleOpen (writeStream) {
+ return function (fd) {
+ writeStream.emit('open', fd)
}
}
-// When we *would* emit 'close' or 'finish', instead do our stuff
-WriteStream.prototype.emit = function (ev) {
- if (ev === 'error')
- cleanupSync.call(this)
-
- if (ev !== 'close' && ev !== 'finish')
- return fs.WriteStream.prototype.emit.apply(this, arguments)
-
- // We handle emitting finish and close after the rename.
- if (ev === 'close' || ev === 'finish') {
- if (!this.__atomicDidStuff) {
- atomicDoStuff.call(this, function (er) {
- if (er)
- cleanup.call(this, er)
- }.bind(this))
+function handleClose (writeStream) {
+ return function () {
+ if (writeStream.__atomicClosed) return
+ writeStream.__atomicClosed = true
+ if (writeStream.__atomicChown) {
+ var uid = writeStream.__atomicChown.uid
+ var gid = writeStream.__atomicChown.gid
+ return fs.chown(writeStream.__atomicTmp, uid, gid, iferr(cleanup, moveIntoPlace))
+ } else {
+ moveIntoPlace()
}
}
-}
+ function cleanup (err) {
+ fs.unlink(writeStream.__atomicTmp, function () {
+ writeStream.emit('error', err)
+ writeStream.emit('close')
+ })
+ }
+ function moveIntoPlace () {
+ fs.rename(writeStream.__atomicTmp, writeStream.__atomicTarget, iferr(cleanup, end))
+ }
+ function end () {
+ // We have to use our parent class directly because we suppress `finish`
+ // events fired via our own emit method.
+ Writable.prototype.emit.call(writeStream, 'finish')
-function atomicDoStuff(cb) {
- if (this.__atomicDidStuff)
- throw new Error('Already did atomic move-into-place')
-
- this.__atomicDidStuff = true
- if (this.__atomicChown) {
- var uid = this.__atomicChown.uid
- var gid = this.__atomicChown.gid
- return fs.chown(this.__atomicTmp, uid, gid, function (er) {
- if (er) return cb(er)
- moveIntoPlace.call(this, cb)
- }.bind(this))
- } else {
- moveIntoPlace.call(this, cb)
+ // Delay the close to provide the same temporal separation a physical
+ // file operation would have– that is, the close event is emitted only
+ // after the async close operation completes.
+ setImmediate(function () {
+ writeStream.emit('close')
+ })
}
}
-function moveIntoPlace (cb) {
- fs.rename(this.__atomicTmp, this.__atomicTarget, function (er) {
- cb(er)
- // emit finish, and then close on the next tick
- // This makes finish/close consistent across Node versions also.
- fs.WriteStream.prototype.emit.call(this, 'finish')
- process.nextTick(function() {
- fs.WriteStream.prototype.emit.call(this, 'close')
- }.bind(this))
- }.bind(this))
+function handleError (writeStream) {
+ return function (er) {
+ cleanupSync()
+ writeStream.emit('error', er)
+ writeStream.__atomicClosed = true
+ writeStream.emit('close')
+ }
+ function cleanupSync () {
+ try {
+ fs.unlinkSync(writeStream.__atomicTmp)
+ } finally {
+ return
+ }
+ }
}
diff --git a/deps/npm/node_modules/fs-write-stream-atomic/package.json b/deps/npm/node_modules/fs-write-stream-atomic/package.json
index a226dbe48d..e65fa32c0e 100644
--- a/deps/npm/node_modules/fs-write-stream-atomic/package.json
+++ b/deps/npm/node_modules/fs-write-stream-atomic/package.json
@@ -1,48 +1,68 @@
{
- "name": "fs-write-stream-atomic",
- "version": "1.0.4",
- "description": "Like `fs.createWriteStream(...)`, but atomic.",
- "main": "index.js",
- "directories": {
- "test": "test"
- },
- "dependencies": {
- "graceful-fs": "^4.1.2"
- },
- "devDependencies": {
- "tap": "^1.2.0"
- },
- "scripts": {
- "test": "tap test/*.js"
+ "_args": [
+ [
+ "fs-write-stream-atomic@1.0.8",
+ "/Users/rebecca/code/npm"
+ ]
+ ],
+ "_from": "fs-write-stream-atomic@1.0.8",
+ "_id": "fs-write-stream-atomic@1.0.8",
+ "_inCache": true,
+ "_installable": true,
+ "_location": "/fs-write-stream-atomic",
+ "_nodeVersion": "4.2.2",
+ "_npmUser": {
+ "email": "me@re-becca.org",
+ "name": "iarna"
},
- "repository": {
- "type": "git",
- "url": "git+https://github.com/npm/fs-write-stream-atomic.git"
+ "_npmVersion": "3.5.2",
+ "_phantomChildren": {},
+ "_requested": {
+ "name": "fs-write-stream-atomic",
+ "raw": "fs-write-stream-atomic@1.0.8",
+ "rawSpec": "1.0.8",
+ "scope": null,
+ "spec": "1.0.8",
+ "type": "version"
},
+ "_requiredBy": [
+ "/"
+ ],
+ "_shasum": "e49aaddf288f87d46ff9e882f216a13abc40778b",
+ "_shrinkwrap": null,
+ "_spec": "fs-write-stream-atomic@1.0.8",
+ "_where": "/Users/rebecca/code/npm",
"author": {
- "name": "Isaac Z. Schlueter",
"email": "i@izs.me",
+ "name": "Isaac Z. Schlueter",
"url": "http://blog.izs.me/"
},
- "license": "ISC",
"bugs": {
"url": "https://github.com/npm/fs-write-stream-atomic/issues"
},
- "homepage": "https://github.com/npm/fs-write-stream-atomic",
- "gitHead": "6ca2651b913149543c5390c6c4f7d370bdca42b5",
- "_id": "fs-write-stream-atomic@1.0.4",
- "_shasum": "c1ea55889f036ceebdead7d1055edbad998fe5e9",
- "_from": "fs-write-stream-atomic@>=1.0.4 <1.1.0",
- "_npmVersion": "2.14.3",
- "_nodeVersion": "2.2.2",
- "_npmUser": {
- "name": "zkat",
- "email": "kat@sykosomatic.org"
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "iferr": "^0.1.5",
+ "imurmurhash": "^0.1.4",
+ "readable-stream": "1 || 2"
+ },
+ "description": "Like `fs.createWriteStream(...)`, but atomic.",
+ "devDependencies": {
+ "rimraf": "^2.4.4",
+ "standard": "^5.4.1",
+ "tap": "^2.3.1"
+ },
+ "directories": {
+ "test": "test"
},
"dist": {
- "shasum": "c1ea55889f036ceebdead7d1055edbad998fe5e9",
- "tarball": "http://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.4.tgz"
+ "shasum": "e49aaddf288f87d46ff9e882f216a13abc40778b",
+ "tarball": "http://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.8.tgz"
},
+ "gitHead": "b55824ee4de7f1ca23784929d68b1b8f5edbf4a4",
+ "homepage": "https://github.com/npm/fs-write-stream-atomic",
+ "license": "ISC",
+ "main": "index.js",
"maintainers": [
{
"name": "iarna",
@@ -50,12 +70,26 @@
},
{
"name": "isaacs",
- "email": "isaacs@npmjs.com"
+ "email": "i@izs.me"
+ },
+ {
+ "name": "othiym23",
+ "email": "ogd@aoaioxxysz.net"
},
{
"name": "zkat",
"email": "kat@sykosomatic.org"
}
],
- "_resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.4.tgz"
+ "name": "fs-write-stream-atomic",
+ "optionalDependencies": {},
+ "readme": "ERROR: No README data found!",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/npm/fs-write-stream-atomic.git"
+ },
+ "scripts": {
+ "test": "standard && tap --coverage test/*.js"
+ },
+ "version": "1.0.8"
}
diff --git a/deps/npm/node_modules/fs-write-stream-atomic/test/basic.js b/deps/npm/node_modules/fs-write-stream-atomic/test/basic.js
index 159c596ab0..d0205e15f4 100644
--- a/deps/npm/node_modules/fs-write-stream-atomic/test/basic.js
+++ b/deps/npm/node_modules/fs-write-stream-atomic/test/basic.js
@@ -1,7 +1,14 @@
+var fs = require('graceful-fs')
var test = require('tap').test
-var writeStream = require('../index.js')
-var fs = require('fs')
var path = require('path')
+var writeStream = require('../index.js')
+
+var rename = fs.rename
+fs.rename = function (from, to, cb) {
+ setTimeout(function () {
+ rename(from, to, cb)
+ }, 100)
+}
test('basic', function (t) {
// open 10 write streams to the same file.
@@ -10,40 +17,41 @@ test('basic', function (t) {
var target = path.resolve(__dirname, 'test.txt')
var n = 10
+ // We run all of our assertions twice:
+ // once for finish, once for close
+ // There are 6 assertions, two fixed, plus 4 lines in the file.
+ t.plan(n * 2 * 6)
+
var streams = []
for (var i = 0; i < n; i++) {
var s = writeStream(target)
- s.on('finish', verifier('finish'))
- s.on('close', verifier('close'))
+ s.on('finish', verifier('finish', i))
+ s.on('close', verifier('close', i))
streams.push(s)
}
- var verifierCalled = 0
- function verifier (ev) { return function () {
- if (ev === 'close')
- t.equal(this.__emittedFinish, true)
- else {
- this.__emittedFinish = true
- t.equal(ev, 'finish')
- }
-
- // make sure that one of the atomic streams won.
- var res = fs.readFileSync(target, 'utf8')
- var lines = res.trim().split(/\n/)
- lines.forEach(function (line) {
- var first = lines[0].match(/\d+$/)[0]
- var cur = line.match(/\d+$/)[0]
- t.equal(cur, first)
- })
+ function verifier (ev, num) {
+ return function () {
+ if (ev === 'close') {
+ t.equal(this.__emittedFinish, true, num + '. closed only after finish')
+ } else {
+ this.__emittedFinish = true
+ t.equal(ev, 'finish', num + '. finished')
+ }
- var resExpr = /^first write \d+\nsecond write \d+\nthird write \d+\nfinal write \d+\n$/
- t.similar(res, resExpr)
+ // make sure that one of the atomic streams won.
+ var res = fs.readFileSync(target, 'utf8')
+ var lines = res.trim().split(/\n/)
+ lines.forEach(function (line, lineno) {
+ var first = lines[0].match(/\d+$/)[0]
+ var cur = line.match(/\d+$/)[0]
+ t.equal(cur, first, num + '. line ' + lineno + ' matches')
+ })
- // should be called once for each close, and each finish
- if (++verifierCalled === n * 2) {
- t.end()
+ var resExpr = /^first write \d+\nsecond write \d+\nthird write \d+\nfinal write \d+\n$/
+ t.similar(res, resExpr, num + '. content matches')
}
- }}
+ }
// now write something to each stream.
streams.forEach(function (stream, i) {
diff --git a/deps/npm/node_modules/fs-write-stream-atomic/test/chown.js b/deps/npm/node_modules/fs-write-stream-atomic/test/chown.js
new file mode 100644
index 0000000000..1733cf27ec
--- /dev/null
+++ b/deps/npm/node_modules/fs-write-stream-atomic/test/chown.js
@@ -0,0 +1,44 @@
+'use strict'
+var fs = require('graceful-fs')
+var path = require('path')
+var test = require('tap').test
+var rimraf = require('rimraf')
+var writeStream = require('../index.js')
+
+var target = path.resolve(__dirname, 'test-chown')
+
+test('chown works', function (t) {
+ t.plan(1)
+ var stream = writeStream(target, {chown: {uid: process.getuid(), gid: process.getgid()}})
+ var hadError = false
+ stream.on('error', function (er) {
+ hadError = true
+ console.log('#', er)
+ })
+ stream.on('close', function () {
+ t.is(hadError, false, 'no errors before close')
+ })
+ stream.end()
+})
+
+test('chown fails', function (t) {
+ t.plan(1)
+ fs.chown = function (file, uid, gid, cb) {
+ cb(new Error('TEST BREAK'))
+ }
+ var stream = writeStream(target, {chown: {uid: process.getuid(), gid: process.getgid()}})
+ var hadError = false
+ stream.on('error', function (er) {
+ hadError = true
+ console.log('#', er)
+ })
+ stream.on('close', function () {
+ t.is(hadError, true, 'error before close')
+ })
+ stream.end()
+})
+
+test('cleanup', function (t) {
+ rimraf.sync(target)
+ t.end()
+})
diff --git a/deps/npm/node_modules/fs-write-stream-atomic/test/rename-fail.js b/deps/npm/node_modules/fs-write-stream-atomic/test/rename-fail.js
new file mode 100644
index 0000000000..7e27f0bfb0
--- /dev/null
+++ b/deps/npm/node_modules/fs-write-stream-atomic/test/rename-fail.js
@@ -0,0 +1,30 @@
+'use strict'
+var fs = require('graceful-fs')
+var path = require('path')
+var test = require('tap').test
+var rimraf = require('rimraf')
+var writeStream = require('../index.js')
+
+var target = path.resolve(__dirname, 'test-rename')
+
+test('rename fails', function (t) {
+ t.plan(1)
+ fs.rename = function (src, dest, cb) {
+ cb(new Error('TEST BREAK'))
+ }
+ var stream = writeStream(target)
+ var hadError = false
+ stream.on('error', function (er) {
+ hadError = true
+ console.log('#', er)
+ })
+ stream.on('close', function () {
+ t.is(hadError, true, 'error before close')
+ })
+ stream.end()
+})
+
+test('cleanup', function (t) {
+ rimraf.sync(target)
+ t.end()
+})
diff --git a/deps/npm/node_modules/fs-write-stream-atomic/test/slow-close.js b/deps/npm/node_modules/fs-write-stream-atomic/test/slow-close.js
new file mode 100644
index 0000000000..9840a6ef03
--- /dev/null
+++ b/deps/npm/node_modules/fs-write-stream-atomic/test/slow-close.js
@@ -0,0 +1,40 @@
+'use strict'
+var fs = require('graceful-fs')
+var path = require('path')
+var test = require('tap').test
+var rimraf = require('rimraf')
+var writeStream = require('../index.js')
+
+var target = path.resolve(__dirname, 'test-chown')
+
+test('slow close', function (t) {
+ t.plan(2)
+ // The goal here is to simulate the "file close" step happening so slowly
+ // that the whole close/rename process could finish before the file is
+ // actually closed (and thus buffers truely flushed to the OS). In
+ // previous versions of this module, this would result in the module
+ // emitting finish & close before the file was fully written and in
+ // turn, could break other layers that tried to read the new file.
+ var realEmit = fs.WriteStream.prototype.emit
+ var reallyClosed = false
+ fs.WriteStream.prototype.emit = function (event) {
+ if (event !== 'close') return realEmit.apply(this, arguments)
+ setTimeout(function () {
+ reallyClosed = true
+ realEmit.call(this, 'close')
+ }.bind(this), 200)
+ }
+ var stream = writeStream(target)
+ stream.on('finish', function () {
+ t.is(reallyClosed, true, "didn't finish before target was closed")
+ })
+ stream.on('close', function () {
+ t.is(reallyClosed, true, "didn't close before target was closed")
+ })
+ stream.end()
+})
+
+test('cleanup', function (t) {
+ rimraf.sync(target)
+ t.end()
+})
diff --git a/deps/npm/node_modules/fs-write-stream-atomic/test/toolong.js b/deps/npm/node_modules/fs-write-stream-atomic/test/toolong.js
index a1e5b714a6..f146cc55b1 100644
--- a/deps/npm/node_modules/fs-write-stream-atomic/test/toolong.js
+++ b/deps/npm/node_modules/fs-write-stream-atomic/test/toolong.js
@@ -2,7 +2,7 @@ var path = require('path')
var test = require('tap').test
var writeStream = require('../index.js')
-function repeat(times, string) {
+function repeat (times, string) {
var output = ''
for (var ii = 0; ii < times; ++ii) {
output += string
@@ -10,19 +10,20 @@ function repeat(times, string) {
return output
}
-var target = path.resolve(__dirname, repeat(1000,'test'))
+var target = path.resolve(__dirname, repeat(1000, 'test'))
test('name too long', function (t) {
+ t.plan(2)
var stream = writeStream(target)
var hadError = false
stream.on('error', function (er) {
if (!hadError) {
- t.is(er.code, 'ENAMETOOLONG', target.length + " character name results in ENAMETOOLONG")
+ t.is(er.code, 'ENAMETOOLONG', target.length + ' character name results in ENAMETOOLONG')
hadError = true
}
})
stream.on('close', function () {
- t.end()
+ t.ok(hadError, 'got error before close')
})
stream.end()
})