fs-write-stream-atomic
Advanced tools
Comparing version 1.0.9 to 1.0.10
62
index.js
@@ -6,2 +6,3 @@ var fs = require('graceful-fs') | ||
var iferr = require('iferr') | ||
var crypto = require('crypto') | ||
@@ -40,2 +41,4 @@ function murmurhex () { | ||
this.__isWin = options && options.hasOwnProperty('isWin') ? options.isWin : process.platform === 'win32' | ||
this.__atomicTarget = path | ||
@@ -89,11 +92,60 @@ this.__atomicTmp = getTmpname(path) | ||
} | ||
function moveIntoPlace () { | ||
fs.rename(writeStream.__atomicTmp, writeStream.__atomicTarget, iferr(trapWindowsEPERM, end)) | ||
} | ||
function trapWindowsEPERM (err) { | ||
if (writeStream.__isWin && | ||
err.syscall && err.syscall === 'rename' && | ||
err.code && err.code === 'EPERM' | ||
) { | ||
checkFileHashes(err) | ||
} else { | ||
cleanup(err) | ||
} | ||
} | ||
function checkFileHashes (eperm) { | ||
var inprocess = 2 | ||
var tmpFileHash = crypto.createHash('sha512') | ||
var targetFileHash = crypto.createHash('sha512') | ||
fs.createReadStream(writeStream.__atomicTmp) | ||
.on('data', function (data, enc) { tmpFileHash.update(data, enc) }) | ||
.on('error', fileHashError) | ||
.on('end', fileHashComplete) | ||
fs.createReadStream(writeStream.__atomicTarget) | ||
.on('data', function (data, enc) { targetFileHash.update(data, enc) }) | ||
.on('error', fileHashError) | ||
.on('end', fileHashComplete) | ||
function fileHashError () { | ||
if (inprocess === 0) return | ||
inprocess = 0 | ||
cleanup(eperm) | ||
} | ||
function fileHashComplete () { | ||
if (inprocess === 0) return | ||
if (--inprocess) return | ||
if (tmpFileHash.digest('hex') === targetFileHash.digest('hex')) { | ||
return cleanup() | ||
} else { | ||
return cleanup(eperm) | ||
} | ||
} | ||
} | ||
function cleanup (err) { | ||
fs.unlink(writeStream.__atomicTmp, function () { | ||
writeStream.emit('error', err) | ||
writeStream.emit('close') | ||
if (err) { | ||
writeStream.emit('error', err) | ||
writeStream.emit('close') | ||
} else { | ||
end() | ||
} | ||
}) | ||
} | ||
function moveIntoPlace () { | ||
fs.rename(writeStream.__atomicTmp, writeStream.__atomicTarget, iferr(cleanup, end)) | ||
} | ||
function end () { | ||
@@ -100,0 +152,0 @@ // We have to use our parent class directly because we suppress `finish` |
{ | ||
"name": "fs-write-stream-atomic", | ||
"version": "1.0.9", | ||
"version": "1.0.10", | ||
"description": "Like `fs.createWriteStream(...)`, but atomic.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
18683
12
502