Skip to content
Snippets Groups Projects
Select Git revision
  • 8c00c9ceafc544132ac95ee595e72eba0ed3b43f
  • main default
2 results

main.py

Blame
  • graceful-fs.js 8.75 KiB
    var fs = require('fs')
    var polyfills = require('./polyfills.js')
    var legacy = require('./legacy-streams.js')
    var clone = require('./clone.js')
    
    var util = require('util')
    
    /* istanbul ignore next - node 0.x polyfill */
    var gracefulQueue
    var previousSymbol
    
    /* istanbul ignore else - node 0.x polyfill */
    if (typeof Symbol === 'function' && typeof Symbol.for === 'function') {
      gracefulQueue = Symbol.for('graceful-fs.queue')
      // This is used in testing by future versions
      previousSymbol = Symbol.for('graceful-fs.previous')
    } else {
      gracefulQueue = '___graceful-fs.queue'
      previousSymbol = '___graceful-fs.previous'
    }
    
    function noop () {}
    
    function publishQueue(context, queue) {
      Object.defineProperty(context, gracefulQueue, {
        get: function() {
          return queue
        }
      })
    }
    
    var debug = noop
    if (util.debuglog)
      debug = util.debuglog('gfs4')
    else if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || ''))
      debug = function() {
        var m = util.format.apply(util, arguments)
        m = 'GFS4: ' + m.split(/\n/).join('\nGFS4: ')
        console.error(m)
      }
    
    // Once time initialization
    if (!fs[gracefulQueue]) {
      // This queue can be shared by multiple loaded instances
      var queue = global[gracefulQueue] || []
      publishQueue(fs, queue)
    
      // Patch fs.close/closeSync to shared queue version, because we need
      // to retry() whenever a close happens *anywhere* in the program.
      // This is essential when multiple graceful-fs instances are
      // in play at the same time.
      fs.close = (function (fs$close) {
        function close (fd, cb) {
          return fs$close.call(fs, fd, function (err) {
            // This function uses the graceful-fs shared queue
            if (!err) {
              retry()
            }
    
            if (typeof cb === 'function')
              cb.apply(this, arguments)
          })
        }
    
        Object.defineProperty(close, previousSymbol, {
          value: fs$close
        })
        return close
      })(fs.close)
    
      fs.closeSync = (function (fs$closeSync) {
        function closeSync (fd) {
          // This function uses the graceful-fs shared queue
          fs$closeSync.apply(fs, arguments)
          retry()
        }
    
        Object.defineProperty(closeSync, previousSymbol, {
          value: fs$closeSync
        })
        return closeSync
      })(fs.closeSync)
    
      if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) {
        process.on('exit', function() {
          debug(fs[gracefulQueue])
          require('assert').equal(fs[gracefulQueue].length, 0)
        })
      }
    }
    
    if (!global[gracefulQueue]) {
      publishQueue(global, fs[gracefulQueue]);
    }
    
    module.exports = patch(clone(fs))
    if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs.__patched) {
        module.exports = patch(fs)
        fs.__patched = true;
    }
    
    function patch (fs) {
      // Everything that references the open() function needs to be in here
      polyfills(fs)
      fs.gracefulify = patch
    
      fs.createReadStream = createReadStream
      fs.createWriteStream = createWriteStream
      var fs$readFile = fs.readFile
      fs.readFile = readFile
      function readFile (path, options, cb) {
        if (typeof options === 'function')
          cb = options, options = null
    
        return go$readFile(path, options, cb)
    
        function go$readFile (path, options, cb) {
          return fs$readFile(path, options, function (err) {
            if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
              enqueue([go$readFile, [path, options, cb]])
            else {
              if (typeof cb === 'function')
                cb.apply(this, arguments)
              retry()
            }
          })
        }
      }
    
      var fs$writeFile = fs.writeFile
      fs.writeFile = writeFile
      function writeFile (path, data, options, cb) {
        if (typeof options === 'function')
          cb = options, options = null
    
        return go$writeFile(path, data, options, cb)
    
        function go$writeFile (path, data, options, cb) {
          return fs$writeFile(path, data, options, function (err) {
            if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
              enqueue([go$writeFile, [path, data, options, cb]])
            else {
              if (typeof cb === 'function')
                cb.apply(this, arguments)
              retry()
            }
          })
        }
      }
    
      var fs$appendFile = fs.appendFile
      if (fs$appendFile)
        fs.appendFile = appendFile
      function appendFile (path, data, options, cb) {
        if (typeof options === 'function')
          cb = options, options = null
    
        return go$appendFile(path, data, options, cb)
    
        function go$appendFile (path, data, options, cb) {
          return fs$appendFile(path, data, options, function (err) {
            if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
              enqueue([go$appendFile, [path, data, options, cb]])
            else {
              if (typeof cb === 'function')
                cb.apply(this, arguments)
              retry()
            }
          })
        }
      }
    
      var fs$readdir = fs.readdir
      fs.readdir = readdir
      function readdir (path, options, cb) {
        var args = [path]
        if (typeof options !== 'function') {
          args.push(options)
        } else {
          cb = options
        }
        args.push(go$readdir$cb)
    
        return go$readdir(args)
    
        function go$readdir$cb (err, files) {
          if (files && files.sort)
            files.sort()
    
          if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
            enqueue([go$readdir, [args]])
    
          else {
            if (typeof cb === 'function')
              cb.apply(this, arguments)
            retry()
          }
        }
      }
    
      function go$readdir (args) {
        return fs$readdir.apply(fs, args)
      }
    
      if (process.version.substr(0, 4) === 'v0.8') {
        var legStreams = legacy(fs)
        ReadStream = legStreams.ReadStream
        WriteStream = legStreams.WriteStream
      }
    
      var fs$ReadStream = fs.ReadStream
      if (fs$ReadStream) {
        ReadStream.prototype = Object.create(fs$ReadStream.prototype)
        ReadStream.prototype.open = ReadStream$open
      }
    
      var fs$WriteStream = fs.WriteStream
      if (fs$WriteStream) {
        WriteStream.prototype = Object.create(fs$WriteStream.prototype)
        WriteStream.prototype.open = WriteStream$open
      }
    
      Object.defineProperty(fs, 'ReadStream', {
        get: function () {
          return ReadStream
        },
        set: function (val) {
          ReadStream = val
        },
        enumerable: true,
        configurable: true
      })
      Object.defineProperty(fs, 'WriteStream', {
        get: function () {
          return WriteStream
        },
        set: function (val) {
          WriteStream = val
        },
        enumerable: true,
        configurable: true
      })
    
      // legacy names
      var FileReadStream = ReadStream
      Object.defineProperty(fs, 'FileReadStream', {
        get: function () {
          return FileReadStream
        },
        set: function (val) {
          FileReadStream = val
        },
        enumerable: true,
        configurable: true
      })
      var FileWriteStream = WriteStream
      Object.defineProperty(fs, 'FileWriteStream', {
        get: function () {
          return FileWriteStream
        },
        set: function (val) {
          FileWriteStream = val
        },
        enumerable: true,
        configurable: true
      })
    
      function ReadStream (path, options) {
        if (this instanceof ReadStream)
          return fs$ReadStream.apply(this, arguments), this
        else
          return ReadStream.apply(Object.create(ReadStream.prototype), arguments)
      }
    
      function ReadStream$open () {
        var that = this
        open(that.path, that.flags, that.mode, function (err, fd) {
          if (err) {
            if (that.autoClose)
              that.destroy()
    
            that.emit('error', err)
          } else {
            that.fd = fd
            that.emit('open', fd)
            that.read()
          }
        })
      }
    
      function WriteStream (path, options) {
        if (this instanceof WriteStream)
          return fs$WriteStream.apply(this, arguments), this
        else
          return WriteStream.apply(Object.create(WriteStream.prototype), arguments)
      }
    
      function WriteStream$open () {
        var that = this
        open(that.path, that.flags, that.mode, function (err, fd) {
          if (err) {
            that.destroy()
            that.emit('error', err)
          } else {
            that.fd = fd
            that.emit('open', fd)
          }
        })
      }
    
      function createReadStream (path, options) {
        return new fs.ReadStream(path, options)
      }
    
      function createWriteStream (path, options) {
        return new fs.WriteStream(path, options)
      }
    
      var fs$open = fs.open
      fs.open = open
      function open (path, flags, mode, cb) {
        if (typeof mode === 'function')
          cb = mode, mode = null
    
        return go$open(path, flags, mode, cb)
    
        function go$open (path, flags, mode, cb) {
          return fs$open(path, flags, mode, function (err, fd) {
            if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
              enqueue([go$open, [path, flags, mode, cb]])
            else {
              if (typeof cb === 'function')
                cb.apply(this, arguments)
              retry()
            }
          })
        }
      }
    
      return fs
    }
    
    function enqueue (elem) {
      debug('ENQUEUE', elem[0].name, elem[1])
      fs[gracefulQueue].push(elem)
    }
    
    function retry () {
      var elem = fs[gracefulQueue].shift()
      if (elem) {
        debug('RETRY', elem[0].name, elem[1])
        elem[0].apply(null, elem[1])
      }
    }