"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/fs-write-stream-atomic/index.js" (8 Mar 2017, 3758 Bytes) of archive /windows/misc/atom-windows.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Javascript source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 var fs = require('graceful-fs')
    2 var Writable = require('readable-stream').Writable
    3 var util = require('util')
    4 var MurmurHash3 = require('imurmurhash')
    5 var iferr = require('iferr')
    6 
    7 function murmurhex () {
    8   var hash = MurmurHash3('')
    9   for (var ii = 0; ii < arguments.length; ++ii) {
   10     hash.hash(hash + arguments[ii])
   11   }
   12   return hash.result()
   13 }
   14 
   15 var invocations = 0
   16 function getTmpname (filename) {
   17   return filename + '.' + murmurhex(__filename, process.pid, ++invocations)
   18 }
   19 
   20 var setImmediate = global.setImmediate || setTimeout
   21 
   22 module.exports = WriteStreamAtomic
   23 
   24 // Requirements:
   25 //   1. Write everything written to the stream to a temp file.
   26 //   2. If there are no errors:
   27 //      a. moves the temp file into its final destination
   28 //      b. emits `finish` & `closed` ONLY after the file is
   29 //         fully flushed and renamed.
   30 //   3. If there's an error, removes the temp file.
   31 
   32 util.inherits(WriteStreamAtomic, Writable)
   33 function WriteStreamAtomic (path, options) {
   34   if (!(this instanceof WriteStreamAtomic)) {
   35     return new WriteStreamAtomic(path, options)
   36   }
   37   Writable.call(this, options)
   38 
   39   this.__atomicTarget = path
   40   this.__atomicTmp = getTmpname(path)
   41 
   42   this.__atomicChown = options && options.chown
   43 
   44   this.__atomicClosed = false
   45 
   46   this.__atomicStream = fs.WriteStream(this.__atomicTmp, options)
   47 
   48   this.__atomicStream.once('open', handleOpen(this))
   49   this.__atomicStream.once('close', handleClose(this))
   50   this.__atomicStream.once('error', handleError(this))
   51 }
   52 
   53 // We have to suppress default finish emitting, because ordinarily it
   54 // would happen as soon as `end` is called on us and all of the
   55 // data has been written to our target stream. So we suppress
   56 // finish from being emitted here, and only emit it after our
   57 // target stream is closed and we've moved everything around.
   58 WriteStreamAtomic.prototype.emit = function (event) {
   59   if (event === 'finish') return this.__atomicStream.end()
   60   return Writable.prototype.emit.apply(this, arguments)
   61 }
   62 
   63 WriteStreamAtomic.prototype._write = function (buffer, encoding, cb) {
   64   var flushed = this.__atomicStream.write(buffer, encoding)
   65   if (flushed) return cb()
   66   this.__atomicStream.once('drain', cb)
   67 }
   68 
   69 function handleOpen (writeStream) {
   70   return function (fd) {
   71     writeStream.emit('open', fd)
   72   }
   73 }
   74 
   75 function handleClose (writeStream) {
   76   return function () {
   77     if (writeStream.__atomicClosed) return
   78     writeStream.__atomicClosed = true
   79     if (writeStream.__atomicChown) {
   80       var uid = writeStream.__atomicChown.uid
   81       var gid = writeStream.__atomicChown.gid
   82       return fs.chown(writeStream.__atomicTmp, uid, gid, iferr(cleanup, moveIntoPlace))
   83     } else {
   84       moveIntoPlace()
   85     }
   86   }
   87   function cleanup (err) {
   88     fs.unlink(writeStream.__atomicTmp, function () {
   89       writeStream.emit('error', err)
   90       writeStream.emit('close')
   91     })
   92   }
   93   function moveIntoPlace () {
   94     fs.rename(writeStream.__atomicTmp, writeStream.__atomicTarget, iferr(cleanup, end))
   95   }
   96   function end () {
   97     // We have to use our parent class directly because we suppress `finish`
   98     // events fired via our own emit method.
   99     Writable.prototype.emit.call(writeStream, 'finish')
  100 
  101     // Delay the close to provide the same temporal separation a physical
  102     // file operation would have– that is, the close event is emitted only
  103     // after the async close operation completes.
  104     setImmediate(function () {
  105       writeStream.emit('close')
  106     })
  107   }
  108 }
  109 
  110 function handleError (writeStream) {
  111   return function (er) {
  112     cleanupSync()
  113     writeStream.emit('error', er)
  114     writeStream.__atomicClosed = true
  115     writeStream.emit('close')
  116   }
  117   function cleanupSync () {
  118     try {
  119       fs.unlinkSync(writeStream.__atomicTmp)
  120     } finally {
  121       return
  122     }
  123   }
  124 }