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:
authorFilip Weiss <me@fiws.net>2014-09-12 14:43:19 +0400
committerForrest L Norvell <forrest@npmjs.com>2014-09-19 09:42:28 +0400
commit17c941a2d583210fe97ed47e2968d94ce9f774ba (patch)
treeb4ec50ca5d84cf93f688d0c10a9cfdeba14ffe1c /node_modules/write-file-atomic
parentf2d2190aa365d22378d03afab0da13f95614a583 (diff)
use writeFileAtomic instead of fs.writeFile fixes #6163
Diffstat (limited to 'node_modules/write-file-atomic')
-rw-r--r--node_modules/write-file-atomic/.npmignore4
-rw-r--r--node_modules/write-file-atomic/README.md44
-rw-r--r--node_modules/write-file-atomic/index.js45
-rw-r--r--node_modules/write-file-atomic/package.json55
-rw-r--r--node_modules/write-file-atomic/test/basic.js97
5 files changed, 245 insertions, 0 deletions
diff --git a/node_modules/write-file-atomic/.npmignore b/node_modules/write-file-atomic/.npmignore
new file mode 100644
index 000000000..454382637
--- /dev/null
+++ b/node_modules/write-file-atomic/.npmignore
@@ -0,0 +1,4 @@
+*~
+DEADJOE
+.#*
+node_modules \ No newline at end of file
diff --git a/node_modules/write-file-atomic/README.md b/node_modules/write-file-atomic/README.md
new file mode 100644
index 000000000..26e434d19
--- /dev/null
+++ b/node_modules/write-file-atomic/README.md
@@ -0,0 +1,44 @@
+write-file-atomic
+-----------------
+
+This is an extension for node's `fs.writeFile` that makes its operation
+atomic and allows you set ownership (uid/gid of the file).
+
+### var writeFileAtomic = require('write-file-atomic')<br>writeFileAtomic(filename, data, [options], callback)
+
+* filename **String**
+* data **String** | **Buffer**
+* options **Object**
+ * chown **Object**
+ * uid **Number**
+ * gid **Number**
+ * encoding **String** | **Null** default = 'utf8'
+ * mode **Number** default = 438 (aka 0666 in Octal)
+callback **Function**
+
+Atomically and asynchronously writes data to a file, replacing the file if it already
+exists. data can be a string or a buffer.
+
+The file is initially named `filename + "." + md5hex(__filename, process.pid, ++invocations)`.
+If writeFile completes successfully then, if passed the **chown** option it will change
+the ownership of the file. Finally it renames the file back to the filename you specified. If
+it encounters errors at any of these steps it will attempt to unlink the temporary file and then
+pass the error back to the caller.
+
+If provided, the **chown** option requires both **uid** and **gid** properties or else
+you'll get an error.
+
+The **encoding** option is ignored if **data** is a buffer. It defaults to 'utf8'.
+
+Example:
+
+```javascript
+writeFileAtomic('message.txt', 'Hello Node', {chown:{uid:100,gid:50}}, function (err) {
+ if (err) throw err;
+ console.log('It\'s saved!');
+});
+```
+
+### var writeFileAtomicSync = require('write-file-atomic').sync<br>writeFileAtomicSync(filename, data, [options])
+
+The synchronous version of **writeFileAtomic**.
diff --git a/node_modules/write-file-atomic/index.js b/node_modules/write-file-atomic/index.js
new file mode 100644
index 000000000..5f103a382
--- /dev/null
+++ b/node_modules/write-file-atomic/index.js
@@ -0,0 +1,45 @@
+'use strict'
+var fs = require('fs');
+var chain = require('slide').chain;
+var crypto = require('crypto');
+
+var md5hex = function () {
+ var hash = crypto.createHash('md5');
+ for (var ii=0; ii<arguments.length; ++ii) hash.update(''+arguments[ii])
+ return hash.digest('hex')
+}
+var invocations = 0;
+var getTmpname = function (filename) {
+ return filename + "." + md5hex(__filename, process.pid, ++invocations)
+}
+
+module.exports = function writeFile(filename, data, options, callback) {
+ if (options instanceof Function) {
+ callback = options;
+ options = null;
+ }
+ if (!options) options = {};
+ var tmpfile = getTmpname(filename);
+ chain([
+ [fs, fs.writeFile, tmpfile, data, options],
+ options.chown && [fs, fs.chown, tmpfile, options.chown.uid, options.chown.gid],
+ [fs, fs.rename, tmpfile, filename]
+ ], function (err) {
+ err ? fs.unlink(tmpfile, function () { callback(err) })
+ : callback()
+ })
+}
+
+module.exports.sync = function writeFileSync(filename, data, options) {
+ if (!options) options = {};
+ var tmpfile = getTmpname(filename);
+ try {
+ fs.writeFileSync(tmpfile, data, options);
+ if (options.chown) fs.chownSync(tmpfile, options.chown.uid, options.chown.gid);
+ fs.renameSync(tmpfile, filename);
+ }
+ catch (err) {
+ try { fs.unlinkSync(tmpfile) } catch(e) {}
+ throw err;
+ }
+} \ No newline at end of file
diff --git a/node_modules/write-file-atomic/package.json b/node_modules/write-file-atomic/package.json
new file mode 100644
index 000000000..a41a63d58
--- /dev/null
+++ b/node_modules/write-file-atomic/package.json
@@ -0,0 +1,55 @@
+{
+ "name": "write-file-atomic",
+ "version": "1.0.3",
+ "description": "Write files in an atomic fashion w/configurable ownership",
+ "main": "index.js",
+ "scripts": {
+ "test": "tap test/*.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git@github.com:iarna/write-file-atomic.git"
+ },
+ "keywords": [
+ "writeFile",
+ "atomic"
+ ],
+ "author": {
+ "name": "Rebecca Turner",
+ "email": "me@re-becca.org",
+ "url": "http://re-becca.org"
+ },
+ "license": "ISC",
+ "bugs": {
+ "url": "https://github.com/iarna/write-file-atomic/issues"
+ },
+ "homepage": "https://github.com/iarna/write-file-atomic",
+ "dependencies": {
+ "slide": "^1.1.5"
+ },
+ "devDependencies": {
+ "require-inject": "^1.1.0",
+ "tap": "^0.4.12"
+ },
+ "gitHead": "5e85cfc7b38e4f0659b15b1c1d979e6a4a7bf6d5",
+ "_id": "write-file-atomic@1.0.3",
+ "_shasum": "597fcb824a0d1ad337db90b7028d2772e9e8e7af",
+ "_from": "write-file-atomic@>=1.0.3 <1.1.0",
+ "_npmVersion": "2.0.0",
+ "_npmUser": {
+ "name": "iarna",
+ "email": "me@re-becca.org"
+ },
+ "maintainers": [
+ {
+ "name": "iarna",
+ "email": "me@re-becca.org"
+ }
+ ],
+ "dist": {
+ "shasum": "597fcb824a0d1ad337db90b7028d2772e9e8e7af",
+ "tarball": "http://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.0.3.tgz"
+ },
+ "directories": {},
+ "_resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.0.3.tgz"
+}
diff --git a/node_modules/write-file-atomic/test/basic.js b/node_modules/write-file-atomic/test/basic.js
new file mode 100644
index 000000000..3e0316dc4
--- /dev/null
+++ b/node_modules/write-file-atomic/test/basic.js
@@ -0,0 +1,97 @@
+"use strict";
+var test = require('tap').test;
+var requireInject = require('require-inject');
+var writeFileAtomic = requireInject('../index', {
+ fs: {
+ writeFile: function (tmpfile, data, options, cb) {
+ if (/nowrite/.test(tmpfile)) return cb('ENOWRITE');
+ cb();
+ },
+ chown: function (tmpfile, uid, gid, cb) {
+ if (/nochown/.test(tmpfile)) return cb('ENOCHOWN');
+ cb();
+ },
+ rename: function (tmpfile, filename, cb) {
+ if (/norename/.test(tmpfile)) return cb('ENORENAME');
+ cb();
+ },
+ unlink: function (tmpfile, cb) {
+ if (/nounlink/.test(tmpfile)) return cb('ENOUNLINK');
+ cb();
+ },
+ writeFileSync: function (tmpfile, data, options) {
+ if (/nowrite/.test(tmpfile)) throw 'ENOWRITE';
+ },
+ chownSync: function (tmpfile, uid, gid) {
+ if (/nochown/.test(tmpfile)) throw 'ENOCHOWN';
+ },
+ renameSync: function (tmpfile, filename) {
+ if (/norename/.test(tmpfile)) throw 'ENORENAME';
+ },
+ unlinkSync: function (tmpfile) {
+ if (/nounlink/.test(tmpfile)) throw 'ENOUNLINK';
+ },
+ }
+});
+var writeFileAtomicSync = writeFileAtomic.sync;
+
+test('async tests', function (t) {
+ t.plan(7);
+ writeFileAtomic('good', 'test', {mode: '0777'}, function (err) {
+ t.notOk(err, 'No errors occur when passing in options');
+ });
+ writeFileAtomic('good', 'test', function (err) {
+ t.notOk(err, 'No errors occur when NOT passing in options');
+ });
+ writeFileAtomic('nowrite', 'test', function (err) {
+ t.is(err, 'ENOWRITE', 'writeFile failures propagate');
+ });
+ writeFileAtomic('nochown', 'test', {chown: {uid:100,gid:100}}, function (err) {
+ t.is(err, 'ENOCHOWN', 'Chown failures propagate');
+ });
+ writeFileAtomic('nochown', 'test', function (err) {
+ t.notOk(err, 'No attempt to chown when no uid/gid passed in');
+ });
+ writeFileAtomic('norename', 'test', function (err) {
+ t.is(err, 'ENORENAME', 'Rename errors propagate');
+ });
+ writeFileAtomic('norename nounlink', 'test', function (err) {
+ t.is(err, 'ENORENAME', 'Failure to unlink the temp file does not clobber the original error');
+ });
+});
+
+test('sync tests', function (t) {
+ t.plan(7);
+ var throws = function (shouldthrow, msg, todo) {
+ var err;
+ try { todo() } catch (e) { err = e }
+ t.is(shouldthrow,err,msg);
+ }
+ var noexception = function (msg, todo) {
+ var err;
+ try { todo() } catch (e) { err = e }
+ t.notOk(err,msg);
+ }
+
+ noexception('No errors occur when passing in options',function (){
+ writeFileAtomicSync('good', 'test', {mode: '0777'});
+ })
+ noexception('No errors occur when NOT passing in options',function (){
+ writeFileAtomicSync('good', 'test');
+ });
+ throws('ENOWRITE', 'writeFile failures propagate', function () {
+ writeFileAtomicSync('nowrite', 'test');
+ });
+ throws('ENOCHOWN', 'Chown failures propagate', function () {
+ writeFileAtomicSync('nochown', 'test', {chown: {uid:100,gid:100}});
+ });
+ noexception('No attempt to chown when no uid/gid passed in', function (){
+ writeFileAtomicSync('nochown', 'test');
+ });
+ throws('ENORENAME', 'Rename errors propagate', function (){
+ writeFileAtomicSync('norename', 'test');
+ });
+ throws('ENORENAME', 'Failure to unlink the temp file does not clobber the original error', function (){
+ writeFileAtomicSync('norename nounlink', 'test');
+ });
+});