Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorisaacs <i@izs.me>2014-09-20 03:23:02 +0400
committerisaacs <i@izs.me>2014-09-20 03:23:02 +0400
commit42c872b32cadc0e555638fc78eab3a38a04401d8 (patch)
tree00c64ac3f1867aab1effd4bc5cb6af7ebe718412 /node_modules/fs-write-stream-atomic
parent4ab5a79c68dbbfb8a468d89d27aea877e0fae3b6 (diff)
Add fs-write-stream-atomic dep
Diffstat (limited to 'node_modules/fs-write-stream-atomic')
-rw-r--r--node_modules/fs-write-stream-atomic/LICENSE15
-rw-r--r--node_modules/fs-write-stream-atomic/README.md35
-rw-r--r--node_modules/fs-write-stream-atomic/index.js68
-rw-r--r--node_modules/fs-write-stream-atomic/package.json38
-rw-r--r--node_modules/fs-write-stream-atomic/test/basic.js78
5 files changed, 234 insertions, 0 deletions
diff --git a/node_modules/fs-write-stream-atomic/LICENSE b/node_modules/fs-write-stream-atomic/LICENSE
new file mode 100644
index 000000000..19129e315
--- /dev/null
+++ b/node_modules/fs-write-stream-atomic/LICENSE
@@ -0,0 +1,15 @@
+The ISC License
+
+Copyright (c) Isaac Z. Schlueter and Contributors
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/node_modules/fs-write-stream-atomic/README.md b/node_modules/fs-write-stream-atomic/README.md
new file mode 100644
index 000000000..0554d6861
--- /dev/null
+++ b/node_modules/fs-write-stream-atomic/README.md
@@ -0,0 +1,35 @@
+# fs-write-stream-atomic
+
+Like `fs.createWriteStream(...)`, but atomic.
+
+Writes to a tmp file and does an atomic `fs.rename` to move it into
+place when it's done.
+
+First rule of debugging: **It's always a write condition.**
+
+## USAGE
+
+```javascript
+var fsWriteStreamAtomic = require('fs-write-stream-atomic')
+// options are optional.
+var write = fsWriteStreamAtomic('output.txt', options)
+var read = fs.createReadStream('input.txt')
+read.pipe(write)
+
+// When the write stream emits a 'finish' or 'close' event,
+// you can be sure that it is moved into place, and contains
+// all the bytes that were written to it, even if something else
+// was writing to `output.txt` at the same time.
+```
+
+### `fsWriteStreamAtomic(filename, [options])`
+
+* `filename` {String} The file we want to write to
+* `options` {Object}
+ * `chown` {Object} User and group to set ownership after write
+ * `uid` {Number}
+ * `gid` {Number}
+ * `encoding` {String} default = 'utf8'
+ * `mode` {Number} default = `0666`
+ * `flags` {String} default = `'w'`
+
diff --git a/node_modules/fs-write-stream-atomic/index.js b/node_modules/fs-write-stream-atomic/index.js
new file mode 100644
index 000000000..cb9b99aa7
--- /dev/null
+++ b/node_modules/fs-write-stream-atomic/index.js
@@ -0,0 +1,68 @@
+var fs = require('graceful-fs')
+var util = require('util')
+var crypto = require('crypto')
+
+function md5hex () {
+ var hash = crypto.createHash('md5')
+ for (var ii=0; ii<arguments.length; ++ii) {
+ hash.update(''+arguments[ii])
+ }
+ return hash.digest('hex')
+}
+
+var invocations = 0;
+function getTmpname (filename) {
+ return filename + "." + md5hex(__filename, process.pid, ++invocations)
+}
+
+module.exports = WriteStream
+
+util.inherits(WriteStream, fs.WriteStream)
+function WriteStream (path, options) {
+ if (!options)
+ options = {}
+
+ if (!(this instanceof WriteStream))
+ return new WriteStream(path, options)
+
+ this.__atomicTarget = path
+ this.__atomicChown = options.chown
+ this.__atomicDidStuff = false
+ this.__atomicTmp = getTmpname(path)
+
+ fs.WriteStream.call(this, this.__atomicTmp, options)
+}
+
+// When we *would* emit 'close' or 'finish', instead do our stuff
+WriteStream.prototype.emit = function (ev) {
+ if (this.__atomicDidStuff || (ev !== 'close' && ev !== 'finish'))
+ return fs.WriteStream.prototype.emit.apply(this, arguments)
+
+ atomicDoStuff.call(this, function (er) {
+ if (er)
+ this.emit('error', er)
+ else
+ this.emit(ev)
+ }.bind(this))
+}
+
+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)
+ }
+}
+
+function moveIntoPlace (cb) {
+ fs.rename(this.__atomicTmp, this.__atomicTarget, cb)
+}
diff --git a/node_modules/fs-write-stream-atomic/package.json b/node_modules/fs-write-stream-atomic/package.json
new file mode 100644
index 000000000..9c3babd5c
--- /dev/null
+++ b/node_modules/fs-write-stream-atomic/package.json
@@ -0,0 +1,38 @@
+{
+ "name": "fs-write-stream-atomic",
+ "version": "1.0.0",
+ "description": "Like `fs.createWriteStream(...)`, but atomic.",
+ "main": "index.js",
+ "directories": {
+ "test": "test"
+ },
+ "dependencies": {
+ "graceful-fs": "^3.0.2"
+ },
+ "devDependencies": {
+ "tap": "^0.4.12"
+ },
+ "scripts": {
+ "test": "tap test/*.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/npm/fs-write-stream-atomic"
+ },
+ "author": {
+ "name": "Isaac Z. Schlueter",
+ "email": "i@izs.me",
+ "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",
+ "readme": "# fs-write-stream-atomic\n\nLike `fs.createWriteStream(...)`, but atomic.\n\nWrites to a tmp file and does an atomic `fs.rename` to move it into\nplace when it's done.\n\nFirst rule of debugging: **It's always a write condition.**\n\n## USAGE\n\n```javascript\nvar fsWriteStreamAtomic = require('fs-write-stream-atomic')\n// options are optional.\nvar write = fsWriteStreamAtomic('output.txt', options)\nvar read = fs.createReadStream('input.txt')\nread.pipe(write)\n\n// When the write stream emits a 'finish' or 'close' event,\n// you can be sure that it is moved into place, and contains\n// all the bytes that were written to it, even if something else\n// was writing to `output.txt` at the same time.\n```\n\n### `fsWriteStreamAtomic(filename, [options])`\n\n* `filename` {String} The file we want to write to\n* `options` {Object}\n * `chown` {Object} User and group to set ownership after write\n * `uid` {Number}\n * `gid` {Number}\n * `encoding` {String} default = 'utf8'\n * `mode` {Number} default = `0666`\n * `flags` {String} default = `'w'`\n\n",
+ "readmeFilename": "README.md",
+ "gitHead": "81a7c1e0f9dbcfc6e7a2e004389f362c7997566c",
+ "_id": "fs-write-stream-atomic@1.0.0",
+ "_shasum": "df22968876ac5163dce116790792cb3592d16930",
+ "_from": "fs-write-stream-atomic@*"
+}
diff --git a/node_modules/fs-write-stream-atomic/test/basic.js b/node_modules/fs-write-stream-atomic/test/basic.js
new file mode 100644
index 000000000..c68c7315a
--- /dev/null
+++ b/node_modules/fs-write-stream-atomic/test/basic.js
@@ -0,0 +1,78 @@
+var test = require('tap').test
+var writeStream = require('../index.js')
+var fs = require('fs')
+var path = require('path')
+
+test('basic', function (t) {
+ // open 10 write streams to the same file.
+ // then write to each of them, and to the target
+ // and verify at the end that each of them does their thing
+ var target = path.resolve(__dirname, 'test.txt')
+ var n = 10
+
+ var streams = []
+ for (var i = 0; i < n; i++) {
+ var s = writeStream(target)
+ s.on('finish', verifier)
+ streams.push(s)
+ }
+
+ var verifierCalled = 0
+ function verifier () {
+ if (++verifierCalled < n) return
+ // 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)
+ })
+
+ var resExpr = /^first write \d+\nsecond write \d+\nthird write \d+\nfinal write \d+\n$/
+ t.similar(res, resExpr)
+ t.end()
+ }
+
+ // now write something to each stream.
+ streams.forEach(function (stream, i) {
+ stream.write('first write ' + i + '\n')
+ })
+
+ // wait a sec for those writes to go out.
+ setTimeout(function () {
+ // write something else to the target.
+ fs.writeFileSync(target, 'brutality!\n')
+
+ // write some more stuff.
+ streams.forEach(function (stream, i) {
+ stream.write('second write ' + i + '\n')
+ })
+
+ setTimeout(function () {
+ // Oops! Deleted the file!
+ fs.unlinkSync(target)
+
+ // write some more stuff.
+ streams.forEach(function (stream, i) {
+ stream.write('third write ' + i + '\n')
+ })
+
+ setTimeout(function () {
+ fs.writeFileSync(target, 'brutality TWO!\n')
+ streams.forEach(function (stream, i) {
+ stream.end('final write ' + i + '\n')
+ })
+ }, 50)
+ }, 50)
+ }, 50)
+})
+
+test('cleanup', function (t) {
+ fs.readdirSync(__dirname).filter(function (f) {
+ return f.match(/^test.txt/)
+ }).forEach(function (file) {
+ fs.unlinkSync(path.resolve(__dirname, file))
+ })
+ t.end()
+})