"Fossies" - the Fresh Open Source Software Archive

Member "Atom/resources/app/apm/node_modules/fstream/lib/dir-reader.js" (11 Apr 2017, 6501 Bytes) of package /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 // A thing that emits "entry" events with Reader objects
    2 // Pausing it causes it to stop emitting entry events, and also
    3 // pauses the current entry if there is one.
    4 
    5 module.exports = DirReader
    6 
    7 var fs = require('graceful-fs')
    8 var inherits = require('inherits')
    9 var path = require('path')
   10 var Reader = require('./reader.js')
   11 var assert = require('assert').ok
   12 
   13 inherits(DirReader, Reader)
   14 
   15 function DirReader (props) {
   16   var self = this
   17   if (!(self instanceof DirReader)) {
   18     throw new Error('DirReader must be called as constructor.')
   19   }
   20 
   21   // should already be established as a Directory type
   22   if (props.type !== 'Directory' || !props.Directory) {
   23     throw new Error('Non-directory type ' + props.type)
   24   }
   25 
   26   self.entries = null
   27   self._index = -1
   28   self._paused = false
   29   self._length = -1
   30 
   31   if (props.sort) {
   32     this.sort = props.sort
   33   }
   34 
   35   Reader.call(this, props)
   36 }
   37 
   38 DirReader.prototype._getEntries = function () {
   39   var self = this
   40 
   41   // race condition.  might pause() before calling _getEntries,
   42   // and then resume, and try to get them a second time.
   43   if (self._gotEntries) return
   44   self._gotEntries = true
   45 
   46   fs.readdir(self._path, function (er, entries) {
   47     if (er) return self.error(er)
   48 
   49     self.entries = entries
   50 
   51     self.emit('entries', entries)
   52     if (self._paused) self.once('resume', processEntries)
   53     else processEntries()
   54 
   55     function processEntries () {
   56       self._length = self.entries.length
   57       if (typeof self.sort === 'function') {
   58         self.entries = self.entries.sort(self.sort.bind(self))
   59       }
   60       self._read()
   61     }
   62   })
   63 }
   64 
   65 // start walking the dir, and emit an "entry" event for each one.
   66 DirReader.prototype._read = function () {
   67   var self = this
   68 
   69   if (!self.entries) return self._getEntries()
   70 
   71   if (self._paused || self._currentEntry || self._aborted) {
   72     // console.error('DR paused=%j, current=%j, aborted=%j', self._paused, !!self._currentEntry, self._aborted)
   73     return
   74   }
   75 
   76   self._index++
   77   if (self._index >= self.entries.length) {
   78     if (!self._ended) {
   79       self._ended = true
   80       self.emit('end')
   81       self.emit('close')
   82     }
   83     return
   84   }
   85 
   86   // ok, handle this one, then.
   87 
   88   // save creating a proxy, by stat'ing the thing now.
   89   var p = path.resolve(self._path, self.entries[self._index])
   90   assert(p !== self._path)
   91   assert(self.entries[self._index])
   92 
   93   // set this to prevent trying to _read() again in the stat time.
   94   self._currentEntry = p
   95   fs[ self.props.follow ? 'stat' : 'lstat' ](p, function (er, stat) {
   96     if (er) return self.error(er)
   97 
   98     var who = self._proxy || self
   99 
  100     stat.path = p
  101     stat.basename = path.basename(p)
  102     stat.dirname = path.dirname(p)
  103     var childProps = self.getChildProps.call(who, stat)
  104     childProps.path = p
  105     childProps.basename = path.basename(p)
  106     childProps.dirname = path.dirname(p)
  107 
  108     var entry = Reader(childProps, stat)
  109 
  110     // console.error("DR Entry", p, stat.size)
  111 
  112     self._currentEntry = entry
  113 
  114     // "entry" events are for direct entries in a specific dir.
  115     // "child" events are for any and all children at all levels.
  116     // This nomenclature is not completely final.
  117 
  118     entry.on('pause', function (who) {
  119       if (!self._paused && !entry._disowned) {
  120         self.pause(who)
  121       }
  122     })
  123 
  124     entry.on('resume', function (who) {
  125       if (self._paused && !entry._disowned) {
  126         self.resume(who)
  127       }
  128     })
  129 
  130     entry.on('stat', function (props) {
  131       self.emit('_entryStat', entry, props)
  132       if (entry._aborted) return
  133       if (entry._paused) {
  134         entry.once('resume', function () {
  135           self.emit('entryStat', entry, props)
  136         })
  137       } else self.emit('entryStat', entry, props)
  138     })
  139 
  140     entry.on('ready', function EMITCHILD () {
  141       // console.error("DR emit child", entry._path)
  142       if (self._paused) {
  143         // console.error("  DR emit child - try again later")
  144         // pause the child, and emit the "entry" event once we drain.
  145         // console.error("DR pausing child entry")
  146         entry.pause(self)
  147         return self.once('resume', EMITCHILD)
  148       }
  149 
  150       // skip over sockets.  they can't be piped around properly,
  151       // so there's really no sense even acknowledging them.
  152       // if someone really wants to see them, they can listen to
  153       // the "socket" events.
  154       if (entry.type === 'Socket') {
  155         self.emit('socket', entry)
  156       } else {
  157         self.emitEntry(entry)
  158       }
  159     })
  160 
  161     var ended = false
  162     entry.on('close', onend)
  163     entry.on('disown', onend)
  164     function onend () {
  165       if (ended) return
  166       ended = true
  167       self.emit('childEnd', entry)
  168       self.emit('entryEnd', entry)
  169       self._currentEntry = null
  170       if (!self._paused) {
  171         self._read()
  172       }
  173     }
  174 
  175     // XXX Remove this.  Works in node as of 0.6.2 or so.
  176     // Long filenames should not break stuff.
  177     entry.on('error', function (er) {
  178       if (entry._swallowErrors) {
  179         self.warn(er)
  180         entry.emit('end')
  181         entry.emit('close')
  182       } else {
  183         self.emit('error', er)
  184       }
  185     })
  186 
  187     // proxy up some events.
  188     ;[
  189       'child',
  190       'childEnd',
  191       'warn'
  192     ].forEach(function (ev) {
  193       entry.on(ev, self.emit.bind(self, ev))
  194     })
  195   })
  196 }
  197 
  198 DirReader.prototype.disown = function (entry) {
  199   entry.emit('beforeDisown')
  200   entry._disowned = true
  201   entry.parent = entry.root = null
  202   if (entry === this._currentEntry) {
  203     this._currentEntry = null
  204   }
  205   entry.emit('disown')
  206 }
  207 
  208 DirReader.prototype.getChildProps = function () {
  209   return {
  210     depth: this.depth + 1,
  211     root: this.root || this,
  212     parent: this,
  213     follow: this.follow,
  214     filter: this.filter,
  215     sort: this.props.sort,
  216     hardlinks: this.props.hardlinks
  217   }
  218 }
  219 
  220 DirReader.prototype.pause = function (who) {
  221   var self = this
  222   if (self._paused) return
  223   who = who || self
  224   self._paused = true
  225   if (self._currentEntry && self._currentEntry.pause) {
  226     self._currentEntry.pause(who)
  227   }
  228   self.emit('pause', who)
  229 }
  230 
  231 DirReader.prototype.resume = function (who) {
  232   var self = this
  233   if (!self._paused) return
  234   who = who || self
  235 
  236   self._paused = false
  237   // console.error('DR Emit Resume', self._path)
  238   self.emit('resume', who)
  239   if (self._paused) {
  240     // console.error('DR Re-paused', self._path)
  241     return
  242   }
  243 
  244   if (self._currentEntry) {
  245     if (self._currentEntry.resume) self._currentEntry.resume(who)
  246   } else self._read()
  247 }
  248 
  249 DirReader.prototype.emitEntry = function (entry) {
  250   this.emit('entry', entry)
  251   this.emit('child', entry)
  252 }