mirror of
https://github.com/biobulkbende/biobulkbende.org.git
synced 2025-10-11 15:14:59 +00:00
structure, layout and automation
This commit is contained in:
85
node_modules/fstream/lib/abstract.js
generated
vendored
Normal file
85
node_modules/fstream/lib/abstract.js
generated
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
// the parent class for all fstreams.
|
||||
|
||||
module.exports = Abstract
|
||||
|
||||
var Stream = require('stream').Stream
|
||||
var inherits = require('inherits')
|
||||
|
||||
function Abstract () {
|
||||
Stream.call(this)
|
||||
}
|
||||
|
||||
inherits(Abstract, Stream)
|
||||
|
||||
Abstract.prototype.on = function (ev, fn) {
|
||||
if (ev === 'ready' && this.ready) {
|
||||
process.nextTick(fn.bind(this))
|
||||
} else {
|
||||
Stream.prototype.on.call(this, ev, fn)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
Abstract.prototype.abort = function () {
|
||||
this._aborted = true
|
||||
this.emit('abort')
|
||||
}
|
||||
|
||||
Abstract.prototype.destroy = function () {}
|
||||
|
||||
Abstract.prototype.warn = function (msg, code) {
|
||||
var self = this
|
||||
var er = decorate(msg, code, self)
|
||||
if (!self.listeners('warn')) {
|
||||
console.error('%s %s\n' +
|
||||
'path = %s\n' +
|
||||
'syscall = %s\n' +
|
||||
'fstream_type = %s\n' +
|
||||
'fstream_path = %s\n' +
|
||||
'fstream_unc_path = %s\n' +
|
||||
'fstream_class = %s\n' +
|
||||
'fstream_stack =\n%s\n',
|
||||
code || 'UNKNOWN',
|
||||
er.stack,
|
||||
er.path,
|
||||
er.syscall,
|
||||
er.fstream_type,
|
||||
er.fstream_path,
|
||||
er.fstream_unc_path,
|
||||
er.fstream_class,
|
||||
er.fstream_stack.join('\n'))
|
||||
} else {
|
||||
self.emit('warn', er)
|
||||
}
|
||||
}
|
||||
|
||||
Abstract.prototype.info = function (msg, code) {
|
||||
this.emit('info', msg, code)
|
||||
}
|
||||
|
||||
Abstract.prototype.error = function (msg, code, th) {
|
||||
var er = decorate(msg, code, this)
|
||||
if (th) throw er
|
||||
else this.emit('error', er)
|
||||
}
|
||||
|
||||
function decorate (er, code, self) {
|
||||
if (!(er instanceof Error)) er = new Error(er)
|
||||
er.code = er.code || code
|
||||
er.path = er.path || self.path
|
||||
er.fstream_type = er.fstream_type || self.type
|
||||
er.fstream_path = er.fstream_path || self.path
|
||||
if (self._path !== self.path) {
|
||||
er.fstream_unc_path = er.fstream_unc_path || self._path
|
||||
}
|
||||
if (self.linkpath) {
|
||||
er.fstream_linkpath = er.fstream_linkpath || self.linkpath
|
||||
}
|
||||
er.fstream_class = er.fstream_class || self.constructor.name
|
||||
er.fstream_stack = er.fstream_stack ||
|
||||
new Error().stack.split(/\n/).slice(3).map(function (s) {
|
||||
return s.replace(/^ {4}at /, '')
|
||||
})
|
||||
|
||||
return er
|
||||
}
|
70
node_modules/fstream/lib/collect.js
generated
vendored
Normal file
70
node_modules/fstream/lib/collect.js
generated
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
module.exports = collect
|
||||
|
||||
function collect (stream) {
|
||||
if (stream._collected) return
|
||||
|
||||
if (stream._paused) return stream.on('resume', collect.bind(null, stream))
|
||||
|
||||
stream._collected = true
|
||||
stream.pause()
|
||||
|
||||
stream.on('data', save)
|
||||
stream.on('end', save)
|
||||
var buf = []
|
||||
function save (b) {
|
||||
if (typeof b === 'string') b = new Buffer(b)
|
||||
if (Buffer.isBuffer(b) && !b.length) return
|
||||
buf.push(b)
|
||||
}
|
||||
|
||||
stream.on('entry', saveEntry)
|
||||
var entryBuffer = []
|
||||
function saveEntry (e) {
|
||||
collect(e)
|
||||
entryBuffer.push(e)
|
||||
}
|
||||
|
||||
stream.on('proxy', proxyPause)
|
||||
function proxyPause (p) {
|
||||
p.pause()
|
||||
}
|
||||
|
||||
// replace the pipe method with a new version that will
|
||||
// unlock the buffered stuff. if you just call .pipe()
|
||||
// without a destination, then it'll re-play the events.
|
||||
stream.pipe = (function (orig) {
|
||||
return function (dest) {
|
||||
// console.error(' === open the pipes', dest && dest.path)
|
||||
|
||||
// let the entries flow through one at a time.
|
||||
// Once they're all done, then we can resume completely.
|
||||
var e = 0
|
||||
;(function unblockEntry () {
|
||||
var entry = entryBuffer[e++]
|
||||
// console.error(" ==== unblock entry", entry && entry.path)
|
||||
if (!entry) return resume()
|
||||
entry.on('end', unblockEntry)
|
||||
if (dest) dest.add(entry)
|
||||
else stream.emit('entry', entry)
|
||||
})()
|
||||
|
||||
function resume () {
|
||||
stream.removeListener('entry', saveEntry)
|
||||
stream.removeListener('data', save)
|
||||
stream.removeListener('end', save)
|
||||
|
||||
stream.pipe = orig
|
||||
if (dest) stream.pipe(dest)
|
||||
|
||||
buf.forEach(function (b) {
|
||||
if (b) stream.emit('data', b)
|
||||
else stream.emit('end')
|
||||
})
|
||||
|
||||
stream.resume()
|
||||
}
|
||||
|
||||
return dest
|
||||
}
|
||||
})(stream.pipe)
|
||||
}
|
252
node_modules/fstream/lib/dir-reader.js
generated
vendored
Normal file
252
node_modules/fstream/lib/dir-reader.js
generated
vendored
Normal file
@ -0,0 +1,252 @@
|
||||
// A thing that emits "entry" events with Reader objects
|
||||
// Pausing it causes it to stop emitting entry events, and also
|
||||
// pauses the current entry if there is one.
|
||||
|
||||
module.exports = DirReader
|
||||
|
||||
var fs = require('graceful-fs')
|
||||
var inherits = require('inherits')
|
||||
var path = require('path')
|
||||
var Reader = require('./reader.js')
|
||||
var assert = require('assert').ok
|
||||
|
||||
inherits(DirReader, Reader)
|
||||
|
||||
function DirReader (props) {
|
||||
var self = this
|
||||
if (!(self instanceof DirReader)) {
|
||||
throw new Error('DirReader must be called as constructor.')
|
||||
}
|
||||
|
||||
// should already be established as a Directory type
|
||||
if (props.type !== 'Directory' || !props.Directory) {
|
||||
throw new Error('Non-directory type ' + props.type)
|
||||
}
|
||||
|
||||
self.entries = null
|
||||
self._index = -1
|
||||
self._paused = false
|
||||
self._length = -1
|
||||
|
||||
if (props.sort) {
|
||||
this.sort = props.sort
|
||||
}
|
||||
|
||||
Reader.call(this, props)
|
||||
}
|
||||
|
||||
DirReader.prototype._getEntries = function () {
|
||||
var self = this
|
||||
|
||||
// race condition. might pause() before calling _getEntries,
|
||||
// and then resume, and try to get them a second time.
|
||||
if (self._gotEntries) return
|
||||
self._gotEntries = true
|
||||
|
||||
fs.readdir(self._path, function (er, entries) {
|
||||
if (er) return self.error(er)
|
||||
|
||||
self.entries = entries
|
||||
|
||||
self.emit('entries', entries)
|
||||
if (self._paused) self.once('resume', processEntries)
|
||||
else processEntries()
|
||||
|
||||
function processEntries () {
|
||||
self._length = self.entries.length
|
||||
if (typeof self.sort === 'function') {
|
||||
self.entries = self.entries.sort(self.sort.bind(self))
|
||||
}
|
||||
self._read()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// start walking the dir, and emit an "entry" event for each one.
|
||||
DirReader.prototype._read = function () {
|
||||
var self = this
|
||||
|
||||
if (!self.entries) return self._getEntries()
|
||||
|
||||
if (self._paused || self._currentEntry || self._aborted) {
|
||||
// console.error('DR paused=%j, current=%j, aborted=%j', self._paused, !!self._currentEntry, self._aborted)
|
||||
return
|
||||
}
|
||||
|
||||
self._index++
|
||||
if (self._index >= self.entries.length) {
|
||||
if (!self._ended) {
|
||||
self._ended = true
|
||||
self.emit('end')
|
||||
self.emit('close')
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ok, handle this one, then.
|
||||
|
||||
// save creating a proxy, by stat'ing the thing now.
|
||||
var p = path.resolve(self._path, self.entries[self._index])
|
||||
assert(p !== self._path)
|
||||
assert(self.entries[self._index])
|
||||
|
||||
// set this to prevent trying to _read() again in the stat time.
|
||||
self._currentEntry = p
|
||||
fs[ self.props.follow ? 'stat' : 'lstat' ](p, function (er, stat) {
|
||||
if (er) return self.error(er)
|
||||
|
||||
var who = self._proxy || self
|
||||
|
||||
stat.path = p
|
||||
stat.basename = path.basename(p)
|
||||
stat.dirname = path.dirname(p)
|
||||
var childProps = self.getChildProps.call(who, stat)
|
||||
childProps.path = p
|
||||
childProps.basename = path.basename(p)
|
||||
childProps.dirname = path.dirname(p)
|
||||
|
||||
var entry = Reader(childProps, stat)
|
||||
|
||||
// console.error("DR Entry", p, stat.size)
|
||||
|
||||
self._currentEntry = entry
|
||||
|
||||
// "entry" events are for direct entries in a specific dir.
|
||||
// "child" events are for any and all children at all levels.
|
||||
// This nomenclature is not completely final.
|
||||
|
||||
entry.on('pause', function (who) {
|
||||
if (!self._paused && !entry._disowned) {
|
||||
self.pause(who)
|
||||
}
|
||||
})
|
||||
|
||||
entry.on('resume', function (who) {
|
||||
if (self._paused && !entry._disowned) {
|
||||
self.resume(who)
|
||||
}
|
||||
})
|
||||
|
||||
entry.on('stat', function (props) {
|
||||
self.emit('_entryStat', entry, props)
|
||||
if (entry._aborted) return
|
||||
if (entry._paused) {
|
||||
entry.once('resume', function () {
|
||||
self.emit('entryStat', entry, props)
|
||||
})
|
||||
} else self.emit('entryStat', entry, props)
|
||||
})
|
||||
|
||||
entry.on('ready', function EMITCHILD () {
|
||||
// console.error("DR emit child", entry._path)
|
||||
if (self._paused) {
|
||||
// console.error(" DR emit child - try again later")
|
||||
// pause the child, and emit the "entry" event once we drain.
|
||||
// console.error("DR pausing child entry")
|
||||
entry.pause(self)
|
||||
return self.once('resume', EMITCHILD)
|
||||
}
|
||||
|
||||
// skip over sockets. they can't be piped around properly,
|
||||
// so there's really no sense even acknowledging them.
|
||||
// if someone really wants to see them, they can listen to
|
||||
// the "socket" events.
|
||||
if (entry.type === 'Socket') {
|
||||
self.emit('socket', entry)
|
||||
} else {
|
||||
self.emitEntry(entry)
|
||||
}
|
||||
})
|
||||
|
||||
var ended = false
|
||||
entry.on('close', onend)
|
||||
entry.on('disown', onend)
|
||||
function onend () {
|
||||
if (ended) return
|
||||
ended = true
|
||||
self.emit('childEnd', entry)
|
||||
self.emit('entryEnd', entry)
|
||||
self._currentEntry = null
|
||||
if (!self._paused) {
|
||||
self._read()
|
||||
}
|
||||
}
|
||||
|
||||
// XXX Remove this. Works in node as of 0.6.2 or so.
|
||||
// Long filenames should not break stuff.
|
||||
entry.on('error', function (er) {
|
||||
if (entry._swallowErrors) {
|
||||
self.warn(er)
|
||||
entry.emit('end')
|
||||
entry.emit('close')
|
||||
} else {
|
||||
self.emit('error', er)
|
||||
}
|
||||
})
|
||||
|
||||
// proxy up some events.
|
||||
;[
|
||||
'child',
|
||||
'childEnd',
|
||||
'warn'
|
||||
].forEach(function (ev) {
|
||||
entry.on(ev, self.emit.bind(self, ev))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
DirReader.prototype.disown = function (entry) {
|
||||
entry.emit('beforeDisown')
|
||||
entry._disowned = true
|
||||
entry.parent = entry.root = null
|
||||
if (entry === this._currentEntry) {
|
||||
this._currentEntry = null
|
||||
}
|
||||
entry.emit('disown')
|
||||
}
|
||||
|
||||
DirReader.prototype.getChildProps = function () {
|
||||
return {
|
||||
depth: this.depth + 1,
|
||||
root: this.root || this,
|
||||
parent: this,
|
||||
follow: this.follow,
|
||||
filter: this.filter,
|
||||
sort: this.props.sort,
|
||||
hardlinks: this.props.hardlinks
|
||||
}
|
||||
}
|
||||
|
||||
DirReader.prototype.pause = function (who) {
|
||||
var self = this
|
||||
if (self._paused) return
|
||||
who = who || self
|
||||
self._paused = true
|
||||
if (self._currentEntry && self._currentEntry.pause) {
|
||||
self._currentEntry.pause(who)
|
||||
}
|
||||
self.emit('pause', who)
|
||||
}
|
||||
|
||||
DirReader.prototype.resume = function (who) {
|
||||
var self = this
|
||||
if (!self._paused) return
|
||||
who = who || self
|
||||
|
||||
self._paused = false
|
||||
// console.error('DR Emit Resume', self._path)
|
||||
self.emit('resume', who)
|
||||
if (self._paused) {
|
||||
// console.error('DR Re-paused', self._path)
|
||||
return
|
||||
}
|
||||
|
||||
if (self._currentEntry) {
|
||||
if (self._currentEntry.resume) self._currentEntry.resume(who)
|
||||
} else self._read()
|
||||
}
|
||||
|
||||
DirReader.prototype.emitEntry = function (entry) {
|
||||
this.emit('entry', entry)
|
||||
this.emit('child', entry)
|
||||
}
|
174
node_modules/fstream/lib/dir-writer.js
generated
vendored
Normal file
174
node_modules/fstream/lib/dir-writer.js
generated
vendored
Normal file
@ -0,0 +1,174 @@
|
||||
// It is expected that, when .add() returns false, the consumer
|
||||
// of the DirWriter will pause until a "drain" event occurs. Note
|
||||
// that this is *almost always going to be the case*, unless the
|
||||
// thing being written is some sort of unsupported type, and thus
|
||||
// skipped over.
|
||||
|
||||
module.exports = DirWriter
|
||||
|
||||
var Writer = require('./writer.js')
|
||||
var inherits = require('inherits')
|
||||
var mkdir = require('mkdirp')
|
||||
var path = require('path')
|
||||
var collect = require('./collect.js')
|
||||
|
||||
inherits(DirWriter, Writer)
|
||||
|
||||
function DirWriter (props) {
|
||||
var self = this
|
||||
if (!(self instanceof DirWriter)) {
|
||||
self.error('DirWriter must be called as constructor.', null, true)
|
||||
}
|
||||
|
||||
// should already be established as a Directory type
|
||||
if (props.type !== 'Directory' || !props.Directory) {
|
||||
self.error('Non-directory type ' + props.type + ' ' +
|
||||
JSON.stringify(props), null, true)
|
||||
}
|
||||
|
||||
Writer.call(this, props)
|
||||
}
|
||||
|
||||
DirWriter.prototype._create = function () {
|
||||
var self = this
|
||||
mkdir(self._path, Writer.dirmode, function (er) {
|
||||
if (er) return self.error(er)
|
||||
// ready to start getting entries!
|
||||
self.ready = true
|
||||
self.emit('ready')
|
||||
self._process()
|
||||
})
|
||||
}
|
||||
|
||||
// a DirWriter has an add(entry) method, but its .write() doesn't
|
||||
// do anything. Why a no-op rather than a throw? Because this
|
||||
// leaves open the door for writing directory metadata for
|
||||
// gnu/solaris style dumpdirs.
|
||||
DirWriter.prototype.write = function () {
|
||||
return true
|
||||
}
|
||||
|
||||
DirWriter.prototype.end = function () {
|
||||
this._ended = true
|
||||
this._process()
|
||||
}
|
||||
|
||||
DirWriter.prototype.add = function (entry) {
|
||||
var self = this
|
||||
|
||||
// console.error('\tadd', entry._path, '->', self._path)
|
||||
collect(entry)
|
||||
if (!self.ready || self._currentEntry) {
|
||||
self._buffer.push(entry)
|
||||
return false
|
||||
}
|
||||
|
||||
// create a new writer, and pipe the incoming entry into it.
|
||||
if (self._ended) {
|
||||
return self.error('add after end')
|
||||
}
|
||||
|
||||
self._buffer.push(entry)
|
||||
self._process()
|
||||
|
||||
return this._buffer.length === 0
|
||||
}
|
||||
|
||||
DirWriter.prototype._process = function () {
|
||||
var self = this
|
||||
|
||||
// console.error('DW Process p=%j', self._processing, self.basename)
|
||||
|
||||
if (self._processing) return
|
||||
|
||||
var entry = self._buffer.shift()
|
||||
if (!entry) {
|
||||
// console.error("DW Drain")
|
||||
self.emit('drain')
|
||||
if (self._ended) self._finish()
|
||||
return
|
||||
}
|
||||
|
||||
self._processing = true
|
||||
// console.error("DW Entry", entry._path)
|
||||
|
||||
self.emit('entry', entry)
|
||||
|
||||
// ok, add this entry
|
||||
//
|
||||
// don't allow recursive copying
|
||||
var p = entry
|
||||
var pp
|
||||
do {
|
||||
pp = p._path || p.path
|
||||
if (pp === self.root._path || pp === self._path ||
|
||||
(pp && pp.indexOf(self._path) === 0)) {
|
||||
// console.error('DW Exit (recursive)', entry.basename, self._path)
|
||||
self._processing = false
|
||||
if (entry._collected) entry.pipe()
|
||||
return self._process()
|
||||
}
|
||||
p = p.parent
|
||||
} while (p)
|
||||
|
||||
// console.error("DW not recursive")
|
||||
|
||||
// chop off the entry's root dir, replace with ours
|
||||
var props = {
|
||||
parent: self,
|
||||
root: self.root || self,
|
||||
type: entry.type,
|
||||
depth: self.depth + 1
|
||||
}
|
||||
|
||||
pp = entry._path || entry.path || entry.props.path
|
||||
if (entry.parent) {
|
||||
pp = pp.substr(entry.parent._path.length + 1)
|
||||
}
|
||||
// get rid of any ../../ shenanigans
|
||||
props.path = path.join(self.path, path.join('/', pp))
|
||||
|
||||
// if i have a filter, the child should inherit it.
|
||||
props.filter = self.filter
|
||||
|
||||
// all the rest of the stuff, copy over from the source.
|
||||
Object.keys(entry.props).forEach(function (k) {
|
||||
if (!props.hasOwnProperty(k)) {
|
||||
props[k] = entry.props[k]
|
||||
}
|
||||
})
|
||||
|
||||
// not sure at this point what kind of writer this is.
|
||||
var child = self._currentChild = new Writer(props)
|
||||
child.on('ready', function () {
|
||||
// console.error("DW Child Ready", child.type, child._path)
|
||||
// console.error(" resuming", entry._path)
|
||||
entry.pipe(child)
|
||||
entry.resume()
|
||||
})
|
||||
|
||||
// XXX Make this work in node.
|
||||
// Long filenames should not break stuff.
|
||||
child.on('error', function (er) {
|
||||
if (child._swallowErrors) {
|
||||
self.warn(er)
|
||||
child.emit('end')
|
||||
child.emit('close')
|
||||
} else {
|
||||
self.emit('error', er)
|
||||
}
|
||||
})
|
||||
|
||||
// we fire _end internally *after* end, so that we don't move on
|
||||
// until any "end" listeners have had their chance to do stuff.
|
||||
child.on('close', onend)
|
||||
var ended = false
|
||||
function onend () {
|
||||
if (ended) return
|
||||
ended = true
|
||||
// console.error("* DW Child end", child.basename)
|
||||
self._currentChild = null
|
||||
self._processing = false
|
||||
self._process()
|
||||
}
|
||||
}
|
150
node_modules/fstream/lib/file-reader.js
generated
vendored
Normal file
150
node_modules/fstream/lib/file-reader.js
generated
vendored
Normal file
@ -0,0 +1,150 @@
|
||||
// Basically just a wrapper around an fs.ReadStream
|
||||
|
||||
module.exports = FileReader
|
||||
|
||||
var fs = require('graceful-fs')
|
||||
var inherits = require('inherits')
|
||||
var Reader = require('./reader.js')
|
||||
var EOF = {EOF: true}
|
||||
var CLOSE = {CLOSE: true}
|
||||
|
||||
inherits(FileReader, Reader)
|
||||
|
||||
function FileReader (props) {
|
||||
// console.error(" FR create", props.path, props.size, new Error().stack)
|
||||
var self = this
|
||||
if (!(self instanceof FileReader)) {
|
||||
throw new Error('FileReader must be called as constructor.')
|
||||
}
|
||||
|
||||
// should already be established as a File type
|
||||
// XXX Todo: preserve hardlinks by tracking dev+inode+nlink,
|
||||
// with a HardLinkReader class.
|
||||
if (!((props.type === 'Link' && props.Link) ||
|
||||
(props.type === 'File' && props.File))) {
|
||||
throw new Error('Non-file type ' + props.type)
|
||||
}
|
||||
|
||||
self._buffer = []
|
||||
self._bytesEmitted = 0
|
||||
Reader.call(self, props)
|
||||
}
|
||||
|
||||
FileReader.prototype._getStream = function () {
|
||||
var self = this
|
||||
var stream = self._stream = fs.createReadStream(self._path, self.props)
|
||||
|
||||
if (self.props.blksize) {
|
||||
stream.bufferSize = self.props.blksize
|
||||
}
|
||||
|
||||
stream.on('open', self.emit.bind(self, 'open'))
|
||||
|
||||
stream.on('data', function (c) {
|
||||
// console.error('\t\t%d %s', c.length, self.basename)
|
||||
self._bytesEmitted += c.length
|
||||
// no point saving empty chunks
|
||||
if (!c.length) {
|
||||
return
|
||||
} else if (self._paused || self._buffer.length) {
|
||||
self._buffer.push(c)
|
||||
self._read()
|
||||
} else self.emit('data', c)
|
||||
})
|
||||
|
||||
stream.on('end', function () {
|
||||
if (self._paused || self._buffer.length) {
|
||||
// console.error('FR Buffering End', self._path)
|
||||
self._buffer.push(EOF)
|
||||
self._read()
|
||||
} else {
|
||||
self.emit('end')
|
||||
}
|
||||
|
||||
if (self._bytesEmitted !== self.props.size) {
|
||||
self.error("Didn't get expected byte count\n" +
|
||||
'expect: ' + self.props.size + '\n' +
|
||||
'actual: ' + self._bytesEmitted)
|
||||
}
|
||||
})
|
||||
|
||||
stream.on('close', function () {
|
||||
if (self._paused || self._buffer.length) {
|
||||
// console.error('FR Buffering Close', self._path)
|
||||
self._buffer.push(CLOSE)
|
||||
self._read()
|
||||
} else {
|
||||
// console.error('FR close 1', self._path)
|
||||
self.emit('close')
|
||||
}
|
||||
})
|
||||
|
||||
stream.on('error', function (e) {
|
||||
self.emit('error', e)
|
||||
})
|
||||
|
||||
self._read()
|
||||
}
|
||||
|
||||
FileReader.prototype._read = function () {
|
||||
var self = this
|
||||
// console.error('FR _read', self._path)
|
||||
if (self._paused) {
|
||||
// console.error('FR _read paused', self._path)
|
||||
return
|
||||
}
|
||||
|
||||
if (!self._stream) {
|
||||
// console.error('FR _getStream calling', self._path)
|
||||
return self._getStream()
|
||||
}
|
||||
|
||||
// clear out the buffer, if there is one.
|
||||
if (self._buffer.length) {
|
||||
// console.error('FR _read has buffer', self._buffer.length, self._path)
|
||||
var buf = self._buffer
|
||||
for (var i = 0, l = buf.length; i < l; i++) {
|
||||
var c = buf[i]
|
||||
if (c === EOF) {
|
||||
// console.error('FR Read emitting buffered end', self._path)
|
||||
self.emit('end')
|
||||
} else if (c === CLOSE) {
|
||||
// console.error('FR Read emitting buffered close', self._path)
|
||||
self.emit('close')
|
||||
} else {
|
||||
// console.error('FR Read emitting buffered data', self._path)
|
||||
self.emit('data', c)
|
||||
}
|
||||
|
||||
if (self._paused) {
|
||||
// console.error('FR Read Re-pausing at '+i, self._path)
|
||||
self._buffer = buf.slice(i)
|
||||
return
|
||||
}
|
||||
}
|
||||
self._buffer.length = 0
|
||||
}
|
||||
// console.error("FR _read done")
|
||||
// that's about all there is to it.
|
||||
}
|
||||
|
||||
FileReader.prototype.pause = function (who) {
|
||||
var self = this
|
||||
// console.error('FR Pause', self._path)
|
||||
if (self._paused) return
|
||||
who = who || self
|
||||
self._paused = true
|
||||
if (self._stream) self._stream.pause()
|
||||
self.emit('pause', who)
|
||||
}
|
||||
|
||||
FileReader.prototype.resume = function (who) {
|
||||
var self = this
|
||||
// console.error('FR Resume', self._path)
|
||||
if (!self._paused) return
|
||||
who = who || self
|
||||
self.emit('resume', who)
|
||||
self._paused = false
|
||||
if (self._stream) self._stream.resume()
|
||||
self._read()
|
||||
}
|
107
node_modules/fstream/lib/file-writer.js
generated
vendored
Normal file
107
node_modules/fstream/lib/file-writer.js
generated
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
module.exports = FileWriter
|
||||
|
||||
var fs = require('graceful-fs')
|
||||
var Writer = require('./writer.js')
|
||||
var inherits = require('inherits')
|
||||
var EOF = {}
|
||||
|
||||
inherits(FileWriter, Writer)
|
||||
|
||||
function FileWriter (props) {
|
||||
var self = this
|
||||
if (!(self instanceof FileWriter)) {
|
||||
throw new Error('FileWriter must be called as constructor.')
|
||||
}
|
||||
|
||||
// should already be established as a File type
|
||||
if (props.type !== 'File' || !props.File) {
|
||||
throw new Error('Non-file type ' + props.type)
|
||||
}
|
||||
|
||||
self._buffer = []
|
||||
self._bytesWritten = 0
|
||||
|
||||
Writer.call(this, props)
|
||||
}
|
||||
|
||||
FileWriter.prototype._create = function () {
|
||||
var self = this
|
||||
if (self._stream) return
|
||||
|
||||
var so = {}
|
||||
if (self.props.flags) so.flags = self.props.flags
|
||||
so.mode = Writer.filemode
|
||||
if (self._old && self._old.blksize) so.bufferSize = self._old.blksize
|
||||
|
||||
self._stream = fs.createWriteStream(self._path, so)
|
||||
|
||||
self._stream.on('open', function () {
|
||||
// console.error("FW open", self._buffer, self._path)
|
||||
self.ready = true
|
||||
self._buffer.forEach(function (c) {
|
||||
if (c === EOF) self._stream.end()
|
||||
else self._stream.write(c)
|
||||
})
|
||||
self.emit('ready')
|
||||
// give this a kick just in case it needs it.
|
||||
self.emit('drain')
|
||||
})
|
||||
|
||||
self._stream.on('error', function (er) { self.emit('error', er) })
|
||||
|
||||
self._stream.on('drain', function () { self.emit('drain') })
|
||||
|
||||
self._stream.on('close', function () {
|
||||
// console.error('\n\nFW Stream Close', self._path, self.size)
|
||||
self._finish()
|
||||
})
|
||||
}
|
||||
|
||||
FileWriter.prototype.write = function (c) {
|
||||
var self = this
|
||||
|
||||
self._bytesWritten += c.length
|
||||
|
||||
if (!self.ready) {
|
||||
if (!Buffer.isBuffer(c) && typeof c !== 'string') {
|
||||
throw new Error('invalid write data')
|
||||
}
|
||||
self._buffer.push(c)
|
||||
return false
|
||||
}
|
||||
|
||||
var ret = self._stream.write(c)
|
||||
// console.error('\t-- fw wrote, _stream says', ret, self._stream._queue.length)
|
||||
|
||||
// allow 2 buffered writes, because otherwise there's just too
|
||||
// much stop and go bs.
|
||||
if (ret === false && self._stream._queue) {
|
||||
return self._stream._queue.length <= 2
|
||||
} else {
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
FileWriter.prototype.end = function (c) {
|
||||
var self = this
|
||||
|
||||
if (c) self.write(c)
|
||||
|
||||
if (!self.ready) {
|
||||
self._buffer.push(EOF)
|
||||
return false
|
||||
}
|
||||
|
||||
return self._stream.end()
|
||||
}
|
||||
|
||||
FileWriter.prototype._finish = function () {
|
||||
var self = this
|
||||
if (typeof self.size === 'number' && self._bytesWritten !== self.size) {
|
||||
self.error(
|
||||
'Did not get expected byte count.\n' +
|
||||
'expect: ' + self.size + '\n' +
|
||||
'actual: ' + self._bytesWritten)
|
||||
}
|
||||
Writer.prototype._finish.call(self)
|
||||
}
|
33
node_modules/fstream/lib/get-type.js
generated
vendored
Normal file
33
node_modules/fstream/lib/get-type.js
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
module.exports = getType
|
||||
|
||||
function getType (st) {
|
||||
var types = [
|
||||
'Directory',
|
||||
'File',
|
||||
'SymbolicLink',
|
||||
'Link', // special for hardlinks from tarballs
|
||||
'BlockDevice',
|
||||
'CharacterDevice',
|
||||
'FIFO',
|
||||
'Socket'
|
||||
]
|
||||
var type
|
||||
|
||||
if (st.type && types.indexOf(st.type) !== -1) {
|
||||
st[st.type] = true
|
||||
return st.type
|
||||
}
|
||||
|
||||
for (var i = 0, l = types.length; i < l; i++) {
|
||||
type = types[i]
|
||||
var is = st[type] || st['is' + type]
|
||||
if (typeof is === 'function') is = is.call(st)
|
||||
if (is) {
|
||||
st[type] = true
|
||||
st.type = type
|
||||
return type
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
53
node_modules/fstream/lib/link-reader.js
generated
vendored
Normal file
53
node_modules/fstream/lib/link-reader.js
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
// Basically just a wrapper around an fs.readlink
|
||||
//
|
||||
// XXX: Enhance this to support the Link type, by keeping
|
||||
// a lookup table of {<dev+inode>:<path>}, so that hardlinks
|
||||
// can be preserved in tarballs.
|
||||
|
||||
module.exports = LinkReader
|
||||
|
||||
var fs = require('graceful-fs')
|
||||
var inherits = require('inherits')
|
||||
var Reader = require('./reader.js')
|
||||
|
||||
inherits(LinkReader, Reader)
|
||||
|
||||
function LinkReader (props) {
|
||||
var self = this
|
||||
if (!(self instanceof LinkReader)) {
|
||||
throw new Error('LinkReader must be called as constructor.')
|
||||
}
|
||||
|
||||
if (!((props.type === 'Link' && props.Link) ||
|
||||
(props.type === 'SymbolicLink' && props.SymbolicLink))) {
|
||||
throw new Error('Non-link type ' + props.type)
|
||||
}
|
||||
|
||||
Reader.call(self, props)
|
||||
}
|
||||
|
||||
// When piping a LinkReader into a LinkWriter, we have to
|
||||
// already have the linkpath property set, so that has to
|
||||
// happen *before* the "ready" event, which means we need to
|
||||
// override the _stat method.
|
||||
LinkReader.prototype._stat = function (currentStat) {
|
||||
var self = this
|
||||
fs.readlink(self._path, function (er, linkpath) {
|
||||
if (er) return self.error(er)
|
||||
self.linkpath = self.props.linkpath = linkpath
|
||||
self.emit('linkpath', linkpath)
|
||||
Reader.prototype._stat.call(self, currentStat)
|
||||
})
|
||||
}
|
||||
|
||||
LinkReader.prototype._read = function () {
|
||||
var self = this
|
||||
if (self._paused) return
|
||||
// basically just a no-op, since we got all the info we need
|
||||
// from the _stat method
|
||||
if (!self._ended) {
|
||||
self.emit('end')
|
||||
self.emit('close')
|
||||
self._ended = true
|
||||
}
|
||||
}
|
95
node_modules/fstream/lib/link-writer.js
generated
vendored
Normal file
95
node_modules/fstream/lib/link-writer.js
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
module.exports = LinkWriter
|
||||
|
||||
var fs = require('graceful-fs')
|
||||
var Writer = require('./writer.js')
|
||||
var inherits = require('inherits')
|
||||
var path = require('path')
|
||||
var rimraf = require('rimraf')
|
||||
|
||||
inherits(LinkWriter, Writer)
|
||||
|
||||
function LinkWriter (props) {
|
||||
var self = this
|
||||
if (!(self instanceof LinkWriter)) {
|
||||
throw new Error('LinkWriter must be called as constructor.')
|
||||
}
|
||||
|
||||
// should already be established as a Link type
|
||||
if (!((props.type === 'Link' && props.Link) ||
|
||||
(props.type === 'SymbolicLink' && props.SymbolicLink))) {
|
||||
throw new Error('Non-link type ' + props.type)
|
||||
}
|
||||
|
||||
if (props.linkpath === '') props.linkpath = '.'
|
||||
if (!props.linkpath) {
|
||||
self.error('Need linkpath property to create ' + props.type)
|
||||
}
|
||||
|
||||
Writer.call(this, props)
|
||||
}
|
||||
|
||||
LinkWriter.prototype._create = function () {
|
||||
// console.error(" LW _create")
|
||||
var self = this
|
||||
var hard = self.type === 'Link' || process.platform === 'win32'
|
||||
var link = hard ? 'link' : 'symlink'
|
||||
var lp = hard ? path.resolve(self.dirname, self.linkpath) : self.linkpath
|
||||
|
||||
// can only change the link path by clobbering
|
||||
// For hard links, let's just assume that's always the case, since
|
||||
// there's no good way to read them if we don't already know.
|
||||
if (hard) return clobber(self, lp, link)
|
||||
|
||||
fs.readlink(self._path, function (er, p) {
|
||||
// only skip creation if it's exactly the same link
|
||||
if (p && p === lp) return finish(self)
|
||||
clobber(self, lp, link)
|
||||
})
|
||||
}
|
||||
|
||||
function clobber (self, lp, link) {
|
||||
rimraf(self._path, function (er) {
|
||||
if (er) return self.error(er)
|
||||
create(self, lp, link)
|
||||
})
|
||||
}
|
||||
|
||||
function create (self, lp, link) {
|
||||
fs[link](lp, self._path, function (er) {
|
||||
// if this is a hard link, and we're in the process of writing out a
|
||||
// directory, it's very possible that the thing we're linking to
|
||||
// doesn't exist yet (especially if it was intended as a symlink),
|
||||
// so swallow ENOENT errors here and just soldier in.
|
||||
// Additionally, an EPERM or EACCES can happen on win32 if it's trying
|
||||
// to make a link to a directory. Again, just skip it.
|
||||
// A better solution would be to have fs.symlink be supported on
|
||||
// windows in some nice fashion.
|
||||
if (er) {
|
||||
if ((er.code === 'ENOENT' ||
|
||||
er.code === 'EACCES' ||
|
||||
er.code === 'EPERM') && process.platform === 'win32') {
|
||||
self.ready = true
|
||||
self.emit('ready')
|
||||
self.emit('end')
|
||||
self.emit('close')
|
||||
self.end = self._finish = function () {}
|
||||
} else return self.error(er)
|
||||
}
|
||||
finish(self)
|
||||
})
|
||||
}
|
||||
|
||||
function finish (self) {
|
||||
self.ready = true
|
||||
self.emit('ready')
|
||||
if (self._ended && !self._finished) self._finish()
|
||||
}
|
||||
|
||||
LinkWriter.prototype.end = function () {
|
||||
// console.error("LW finish in end")
|
||||
this._ended = true
|
||||
if (this.ready) {
|
||||
this._finished = true
|
||||
this._finish()
|
||||
}
|
||||
}
|
95
node_modules/fstream/lib/proxy-reader.js
generated
vendored
Normal file
95
node_modules/fstream/lib/proxy-reader.js
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
// A reader for when we don't yet know what kind of thing
|
||||
// the thing is.
|
||||
|
||||
module.exports = ProxyReader
|
||||
|
||||
var Reader = require('./reader.js')
|
||||
var getType = require('./get-type.js')
|
||||
var inherits = require('inherits')
|
||||
var fs = require('graceful-fs')
|
||||
|
||||
inherits(ProxyReader, Reader)
|
||||
|
||||
function ProxyReader (props) {
|
||||
var self = this
|
||||
if (!(self instanceof ProxyReader)) {
|
||||
throw new Error('ProxyReader must be called as constructor.')
|
||||
}
|
||||
|
||||
self.props = props
|
||||
self._buffer = []
|
||||
self.ready = false
|
||||
|
||||
Reader.call(self, props)
|
||||
}
|
||||
|
||||
ProxyReader.prototype._stat = function () {
|
||||
var self = this
|
||||
var props = self.props
|
||||
// stat the thing to see what the proxy should be.
|
||||
var stat = props.follow ? 'stat' : 'lstat'
|
||||
|
||||
fs[stat](props.path, function (er, current) {
|
||||
var type
|
||||
if (er || !current) {
|
||||
type = 'File'
|
||||
} else {
|
||||
type = getType(current)
|
||||
}
|
||||
|
||||
props[type] = true
|
||||
props.type = self.type = type
|
||||
|
||||
self._old = current
|
||||
self._addProxy(Reader(props, current))
|
||||
})
|
||||
}
|
||||
|
||||
ProxyReader.prototype._addProxy = function (proxy) {
|
||||
var self = this
|
||||
if (self._proxyTarget) {
|
||||
return self.error('proxy already set')
|
||||
}
|
||||
|
||||
self._proxyTarget = proxy
|
||||
proxy._proxy = self
|
||||
|
||||
;[
|
||||
'error',
|
||||
'data',
|
||||
'end',
|
||||
'close',
|
||||
'linkpath',
|
||||
'entry',
|
||||
'entryEnd',
|
||||
'child',
|
||||
'childEnd',
|
||||
'warn',
|
||||
'stat'
|
||||
].forEach(function (ev) {
|
||||
// console.error('~~ proxy event', ev, self.path)
|
||||
proxy.on(ev, self.emit.bind(self, ev))
|
||||
})
|
||||
|
||||
self.emit('proxy', proxy)
|
||||
|
||||
proxy.on('ready', function () {
|
||||
// console.error("~~ proxy is ready!", self.path)
|
||||
self.ready = true
|
||||
self.emit('ready')
|
||||
})
|
||||
|
||||
var calls = self._buffer
|
||||
self._buffer.length = 0
|
||||
calls.forEach(function (c) {
|
||||
proxy[c[0]].apply(proxy, c[1])
|
||||
})
|
||||
}
|
||||
|
||||
ProxyReader.prototype.pause = function () {
|
||||
return this._proxyTarget ? this._proxyTarget.pause() : false
|
||||
}
|
||||
|
||||
ProxyReader.prototype.resume = function () {
|
||||
return this._proxyTarget ? this._proxyTarget.resume() : false
|
||||
}
|
111
node_modules/fstream/lib/proxy-writer.js
generated
vendored
Normal file
111
node_modules/fstream/lib/proxy-writer.js
generated
vendored
Normal file
@ -0,0 +1,111 @@
|
||||
// A writer for when we don't know what kind of thing
|
||||
// the thing is. That is, it's not explicitly set,
|
||||
// so we're going to make it whatever the thing already
|
||||
// is, or "File"
|
||||
//
|
||||
// Until then, collect all events.
|
||||
|
||||
module.exports = ProxyWriter
|
||||
|
||||
var Writer = require('./writer.js')
|
||||
var getType = require('./get-type.js')
|
||||
var inherits = require('inherits')
|
||||
var collect = require('./collect.js')
|
||||
var fs = require('fs')
|
||||
|
||||
inherits(ProxyWriter, Writer)
|
||||
|
||||
function ProxyWriter (props) {
|
||||
var self = this
|
||||
if (!(self instanceof ProxyWriter)) {
|
||||
throw new Error('ProxyWriter must be called as constructor.')
|
||||
}
|
||||
|
||||
self.props = props
|
||||
self._needDrain = false
|
||||
|
||||
Writer.call(self, props)
|
||||
}
|
||||
|
||||
ProxyWriter.prototype._stat = function () {
|
||||
var self = this
|
||||
var props = self.props
|
||||
// stat the thing to see what the proxy should be.
|
||||
var stat = props.follow ? 'stat' : 'lstat'
|
||||
|
||||
fs[stat](props.path, function (er, current) {
|
||||
var type
|
||||
if (er || !current) {
|
||||
type = 'File'
|
||||
} else {
|
||||
type = getType(current)
|
||||
}
|
||||
|
||||
props[type] = true
|
||||
props.type = self.type = type
|
||||
|
||||
self._old = current
|
||||
self._addProxy(Writer(props, current))
|
||||
})
|
||||
}
|
||||
|
||||
ProxyWriter.prototype._addProxy = function (proxy) {
|
||||
// console.error("~~ set proxy", this.path)
|
||||
var self = this
|
||||
if (self._proxy) {
|
||||
return self.error('proxy already set')
|
||||
}
|
||||
|
||||
self._proxy = proxy
|
||||
;[
|
||||
'ready',
|
||||
'error',
|
||||
'close',
|
||||
'pipe',
|
||||
'drain',
|
||||
'warn'
|
||||
].forEach(function (ev) {
|
||||
proxy.on(ev, self.emit.bind(self, ev))
|
||||
})
|
||||
|
||||
self.emit('proxy', proxy)
|
||||
|
||||
var calls = self._buffer
|
||||
calls.forEach(function (c) {
|
||||
// console.error("~~ ~~ proxy buffered call", c[0], c[1])
|
||||
proxy[c[0]].apply(proxy, c[1])
|
||||
})
|
||||
self._buffer.length = 0
|
||||
if (self._needsDrain) self.emit('drain')
|
||||
}
|
||||
|
||||
ProxyWriter.prototype.add = function (entry) {
|
||||
// console.error("~~ proxy add")
|
||||
collect(entry)
|
||||
|
||||
if (!this._proxy) {
|
||||
this._buffer.push(['add', [entry]])
|
||||
this._needDrain = true
|
||||
return false
|
||||
}
|
||||
return this._proxy.add(entry)
|
||||
}
|
||||
|
||||
ProxyWriter.prototype.write = function (c) {
|
||||
// console.error('~~ proxy write')
|
||||
if (!this._proxy) {
|
||||
this._buffer.push(['write', [c]])
|
||||
this._needDrain = true
|
||||
return false
|
||||
}
|
||||
return this._proxy.write(c)
|
||||
}
|
||||
|
||||
ProxyWriter.prototype.end = function (c) {
|
||||
// console.error('~~ proxy end')
|
||||
if (!this._proxy) {
|
||||
this._buffer.push(['end', [c]])
|
||||
return false
|
||||
}
|
||||
return this._proxy.end(c)
|
||||
}
|
255
node_modules/fstream/lib/reader.js
generated
vendored
Normal file
255
node_modules/fstream/lib/reader.js
generated
vendored
Normal file
@ -0,0 +1,255 @@
|
||||
module.exports = Reader
|
||||
|
||||
var fs = require('graceful-fs')
|
||||
var Stream = require('stream').Stream
|
||||
var inherits = require('inherits')
|
||||
var path = require('path')
|
||||
var getType = require('./get-type.js')
|
||||
var hardLinks = Reader.hardLinks = {}
|
||||
var Abstract = require('./abstract.js')
|
||||
|
||||
// Must do this *before* loading the child classes
|
||||
inherits(Reader, Abstract)
|
||||
|
||||
var LinkReader = require('./link-reader.js')
|
||||
|
||||
function Reader (props, currentStat) {
|
||||
var self = this
|
||||
if (!(self instanceof Reader)) return new Reader(props, currentStat)
|
||||
|
||||
if (typeof props === 'string') {
|
||||
props = { path: props }
|
||||
}
|
||||
|
||||
// polymorphism.
|
||||
// call fstream.Reader(dir) to get a DirReader object, etc.
|
||||
// Note that, unlike in the Writer case, ProxyReader is going
|
||||
// to be the *normal* state of affairs, since we rarely know
|
||||
// the type of a file prior to reading it.
|
||||
|
||||
var type
|
||||
var ClassType
|
||||
|
||||
if (props.type && typeof props.type === 'function') {
|
||||
type = props.type
|
||||
ClassType = type
|
||||
} else {
|
||||
type = getType(props)
|
||||
ClassType = Reader
|
||||
}
|
||||
|
||||
if (currentStat && !type) {
|
||||
type = getType(currentStat)
|
||||
props[type] = true
|
||||
props.type = type
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 'Directory':
|
||||
ClassType = require('./dir-reader.js')
|
||||
break
|
||||
|
||||
case 'Link':
|
||||
// XXX hard links are just files.
|
||||
// However, it would be good to keep track of files' dev+inode
|
||||
// and nlink values, and create a HardLinkReader that emits
|
||||
// a linkpath value of the original copy, so that the tar
|
||||
// writer can preserve them.
|
||||
// ClassType = HardLinkReader
|
||||
// break
|
||||
|
||||
case 'File':
|
||||
ClassType = require('./file-reader.js')
|
||||
break
|
||||
|
||||
case 'SymbolicLink':
|
||||
ClassType = LinkReader
|
||||
break
|
||||
|
||||
case 'Socket':
|
||||
ClassType = require('./socket-reader.js')
|
||||
break
|
||||
|
||||
case null:
|
||||
ClassType = require('./proxy-reader.js')
|
||||
break
|
||||
}
|
||||
|
||||
if (!(self instanceof ClassType)) {
|
||||
return new ClassType(props)
|
||||
}
|
||||
|
||||
Abstract.call(self)
|
||||
|
||||
if (!props.path) {
|
||||
self.error('Must provide a path', null, true)
|
||||
}
|
||||
|
||||
self.readable = true
|
||||
self.writable = false
|
||||
|
||||
self.type = type
|
||||
self.props = props
|
||||
self.depth = props.depth = props.depth || 0
|
||||
self.parent = props.parent || null
|
||||
self.root = props.root || (props.parent && props.parent.root) || self
|
||||
|
||||
self._path = self.path = path.resolve(props.path)
|
||||
if (process.platform === 'win32') {
|
||||
self.path = self._path = self.path.replace(/\?/g, '_')
|
||||
if (self._path.length >= 260) {
|
||||
// how DOES one create files on the moon?
|
||||
// if the path has spaces in it, then UNC will fail.
|
||||
self._swallowErrors = true
|
||||
// if (self._path.indexOf(" ") === -1) {
|
||||
self._path = '\\\\?\\' + self.path.replace(/\//g, '\\')
|
||||
// }
|
||||
}
|
||||
}
|
||||
self.basename = props.basename = path.basename(self.path)
|
||||
self.dirname = props.dirname = path.dirname(self.path)
|
||||
|
||||
// these have served their purpose, and are now just noisy clutter
|
||||
props.parent = props.root = null
|
||||
|
||||
// console.error("\n\n\n%s setting size to", props.path, props.size)
|
||||
self.size = props.size
|
||||
self.filter = typeof props.filter === 'function' ? props.filter : null
|
||||
if (props.sort === 'alpha') props.sort = alphasort
|
||||
|
||||
// start the ball rolling.
|
||||
// this will stat the thing, and then call self._read()
|
||||
// to start reading whatever it is.
|
||||
// console.error("calling stat", props.path, currentStat)
|
||||
self._stat(currentStat)
|
||||
}
|
||||
|
||||
function alphasort (a, b) {
|
||||
return a === b ? 0
|
||||
: a.toLowerCase() > b.toLowerCase() ? 1
|
||||
: a.toLowerCase() < b.toLowerCase() ? -1
|
||||
: a > b ? 1
|
||||
: -1
|
||||
}
|
||||
|
||||
Reader.prototype._stat = function (currentStat) {
|
||||
var self = this
|
||||
var props = self.props
|
||||
var stat = props.follow ? 'stat' : 'lstat'
|
||||
// console.error("Reader._stat", self._path, currentStat)
|
||||
if (currentStat) process.nextTick(statCb.bind(null, null, currentStat))
|
||||
else fs[stat](self._path, statCb)
|
||||
|
||||
function statCb (er, props_) {
|
||||
// console.error("Reader._stat, statCb", self._path, props_, props_.nlink)
|
||||
if (er) return self.error(er)
|
||||
|
||||
Object.keys(props_).forEach(function (k) {
|
||||
props[k] = props_[k]
|
||||
})
|
||||
|
||||
// if it's not the expected size, then abort here.
|
||||
if (undefined !== self.size && props.size !== self.size) {
|
||||
return self.error('incorrect size')
|
||||
}
|
||||
self.size = props.size
|
||||
|
||||
var type = getType(props)
|
||||
var handleHardlinks = props.hardlinks !== false
|
||||
|
||||
// special little thing for handling hardlinks.
|
||||
if (handleHardlinks && type !== 'Directory' && props.nlink && props.nlink > 1) {
|
||||
var k = props.dev + ':' + props.ino
|
||||
// console.error("Reader has nlink", self._path, k)
|
||||
if (hardLinks[k] === self._path || !hardLinks[k]) {
|
||||
hardLinks[k] = self._path
|
||||
} else {
|
||||
// switch into hardlink mode.
|
||||
type = self.type = self.props.type = 'Link'
|
||||
self.Link = self.props.Link = true
|
||||
self.linkpath = self.props.linkpath = hardLinks[k]
|
||||
// console.error("Hardlink detected, switching mode", self._path, self.linkpath)
|
||||
// Setting __proto__ would arguably be the "correct"
|
||||
// approach here, but that just seems too wrong.
|
||||
self._stat = self._read = LinkReader.prototype._read
|
||||
}
|
||||
}
|
||||
|
||||
if (self.type && self.type !== type) {
|
||||
self.error('Unexpected type: ' + type)
|
||||
}
|
||||
|
||||
// if the filter doesn't pass, then just skip over this one.
|
||||
// still have to emit end so that dir-walking can move on.
|
||||
if (self.filter) {
|
||||
var who = self._proxy || self
|
||||
// special handling for ProxyReaders
|
||||
if (!self.filter.call(who, who, props)) {
|
||||
if (!self._disowned) {
|
||||
self.abort()
|
||||
self.emit('end')
|
||||
self.emit('close')
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// last chance to abort or disown before the flow starts!
|
||||
var events = ['_stat', 'stat', 'ready']
|
||||
var e = 0
|
||||
;(function go () {
|
||||
if (self._aborted) {
|
||||
self.emit('end')
|
||||
self.emit('close')
|
||||
return
|
||||
}
|
||||
|
||||
if (self._paused && self.type !== 'Directory') {
|
||||
self.once('resume', go)
|
||||
return
|
||||
}
|
||||
|
||||
var ev = events[e++]
|
||||
if (!ev) {
|
||||
return self._read()
|
||||
}
|
||||
self.emit(ev, props)
|
||||
go()
|
||||
})()
|
||||
}
|
||||
}
|
||||
|
||||
Reader.prototype.pipe = function (dest) {
|
||||
var self = this
|
||||
if (typeof dest.add === 'function') {
|
||||
// piping to a multi-compatible, and we've got directory entries.
|
||||
self.on('entry', function (entry) {
|
||||
var ret = dest.add(entry)
|
||||
if (ret === false) {
|
||||
self.pause()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// console.error("R Pipe apply Stream Pipe")
|
||||
return Stream.prototype.pipe.apply(this, arguments)
|
||||
}
|
||||
|
||||
Reader.prototype.pause = function (who) {
|
||||
this._paused = true
|
||||
who = who || this
|
||||
this.emit('pause', who)
|
||||
if (this._stream) this._stream.pause(who)
|
||||
}
|
||||
|
||||
Reader.prototype.resume = function (who) {
|
||||
this._paused = false
|
||||
who = who || this
|
||||
this.emit('resume', who)
|
||||
if (this._stream) this._stream.resume(who)
|
||||
this._read()
|
||||
}
|
||||
|
||||
Reader.prototype._read = function () {
|
||||
this.error('Cannot read unknown type: ' + this.type)
|
||||
}
|
36
node_modules/fstream/lib/socket-reader.js
generated
vendored
Normal file
36
node_modules/fstream/lib/socket-reader.js
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
// Just get the stats, and then don't do anything.
|
||||
// You can't really "read" from a socket. You "connect" to it.
|
||||
// Mostly, this is here so that reading a dir with a socket in it
|
||||
// doesn't blow up.
|
||||
|
||||
module.exports = SocketReader
|
||||
|
||||
var inherits = require('inherits')
|
||||
var Reader = require('./reader.js')
|
||||
|
||||
inherits(SocketReader, Reader)
|
||||
|
||||
function SocketReader (props) {
|
||||
var self = this
|
||||
if (!(self instanceof SocketReader)) {
|
||||
throw new Error('SocketReader must be called as constructor.')
|
||||
}
|
||||
|
||||
if (!(props.type === 'Socket' && props.Socket)) {
|
||||
throw new Error('Non-socket type ' + props.type)
|
||||
}
|
||||
|
||||
Reader.call(self, props)
|
||||
}
|
||||
|
||||
SocketReader.prototype._read = function () {
|
||||
var self = this
|
||||
if (self._paused) return
|
||||
// basically just a no-op, since we got all the info we have
|
||||
// from the _stat method
|
||||
if (!self._ended) {
|
||||
self.emit('end')
|
||||
self.emit('close')
|
||||
self._ended = true
|
||||
}
|
||||
}
|
390
node_modules/fstream/lib/writer.js
generated
vendored
Normal file
390
node_modules/fstream/lib/writer.js
generated
vendored
Normal file
@ -0,0 +1,390 @@
|
||||
module.exports = Writer
|
||||
|
||||
var fs = require('graceful-fs')
|
||||
var inherits = require('inherits')
|
||||
var rimraf = require('rimraf')
|
||||
var mkdir = require('mkdirp')
|
||||
var path = require('path')
|
||||
var umask = process.platform === 'win32' ? 0 : process.umask()
|
||||
var getType = require('./get-type.js')
|
||||
var Abstract = require('./abstract.js')
|
||||
|
||||
// Must do this *before* loading the child classes
|
||||
inherits(Writer, Abstract)
|
||||
|
||||
Writer.dirmode = parseInt('0777', 8) & (~umask)
|
||||
Writer.filemode = parseInt('0666', 8) & (~umask)
|
||||
|
||||
var DirWriter = require('./dir-writer.js')
|
||||
var LinkWriter = require('./link-writer.js')
|
||||
var FileWriter = require('./file-writer.js')
|
||||
var ProxyWriter = require('./proxy-writer.js')
|
||||
|
||||
// props is the desired state. current is optionally the current stat,
|
||||
// provided here so that subclasses can avoid statting the target
|
||||
// more than necessary.
|
||||
function Writer (props, current) {
|
||||
var self = this
|
||||
|
||||
if (typeof props === 'string') {
|
||||
props = { path: props }
|
||||
}
|
||||
|
||||
// polymorphism.
|
||||
// call fstream.Writer(dir) to get a DirWriter object, etc.
|
||||
var type = getType(props)
|
||||
var ClassType = Writer
|
||||
|
||||
switch (type) {
|
||||
case 'Directory':
|
||||
ClassType = DirWriter
|
||||
break
|
||||
case 'File':
|
||||
ClassType = FileWriter
|
||||
break
|
||||
case 'Link':
|
||||
case 'SymbolicLink':
|
||||
ClassType = LinkWriter
|
||||
break
|
||||
case null:
|
||||
default:
|
||||
// Don't know yet what type to create, so we wrap in a proxy.
|
||||
ClassType = ProxyWriter
|
||||
break
|
||||
}
|
||||
|
||||
if (!(self instanceof ClassType)) return new ClassType(props)
|
||||
|
||||
// now get down to business.
|
||||
|
||||
Abstract.call(self)
|
||||
|
||||
if (!props.path) self.error('Must provide a path', null, true)
|
||||
|
||||
// props is what we want to set.
|
||||
// set some convenience properties as well.
|
||||
self.type = props.type
|
||||
self.props = props
|
||||
self.depth = props.depth || 0
|
||||
self.clobber = props.clobber === false ? props.clobber : true
|
||||
self.parent = props.parent || null
|
||||
self.root = props.root || (props.parent && props.parent.root) || self
|
||||
|
||||
self._path = self.path = path.resolve(props.path)
|
||||
if (process.platform === 'win32') {
|
||||
self.path = self._path = self.path.replace(/\?/g, '_')
|
||||
if (self._path.length >= 260) {
|
||||
self._swallowErrors = true
|
||||
self._path = '\\\\?\\' + self.path.replace(/\//g, '\\')
|
||||
}
|
||||
}
|
||||
self.basename = path.basename(props.path)
|
||||
self.dirname = path.dirname(props.path)
|
||||
self.linkpath = props.linkpath || null
|
||||
|
||||
props.parent = props.root = null
|
||||
|
||||
// console.error("\n\n\n%s setting size to", props.path, props.size)
|
||||
self.size = props.size
|
||||
|
||||
if (typeof props.mode === 'string') {
|
||||
props.mode = parseInt(props.mode, 8)
|
||||
}
|
||||
|
||||
self.readable = false
|
||||
self.writable = true
|
||||
|
||||
// buffer until ready, or while handling another entry
|
||||
self._buffer = []
|
||||
self.ready = false
|
||||
|
||||
self.filter = typeof props.filter === 'function' ? props.filter : null
|
||||
|
||||
// start the ball rolling.
|
||||
// this checks what's there already, and then calls
|
||||
// self._create() to call the impl-specific creation stuff.
|
||||
self._stat(current)
|
||||
}
|
||||
|
||||
// Calling this means that it's something we can't create.
|
||||
// Just assert that it's already there, otherwise raise a warning.
|
||||
Writer.prototype._create = function () {
|
||||
var self = this
|
||||
fs[self.props.follow ? 'stat' : 'lstat'](self._path, function (er) {
|
||||
if (er) {
|
||||
return self.warn('Cannot create ' + self._path + '\n' +
|
||||
'Unsupported type: ' + self.type, 'ENOTSUP')
|
||||
}
|
||||
self._finish()
|
||||
})
|
||||
}
|
||||
|
||||
Writer.prototype._stat = function (current) {
|
||||
var self = this
|
||||
var props = self.props
|
||||
var stat = props.follow ? 'stat' : 'lstat'
|
||||
var who = self._proxy || self
|
||||
|
||||
if (current) statCb(null, current)
|
||||
else fs[stat](self._path, statCb)
|
||||
|
||||
function statCb (er, current) {
|
||||
if (self.filter && !self.filter.call(who, who, current)) {
|
||||
self._aborted = true
|
||||
self.emit('end')
|
||||
self.emit('close')
|
||||
return
|
||||
}
|
||||
|
||||
// if it's not there, great. We'll just create it.
|
||||
// if it is there, then we'll need to change whatever differs
|
||||
if (er || !current) {
|
||||
return create(self)
|
||||
}
|
||||
|
||||
self._old = current
|
||||
var currentType = getType(current)
|
||||
|
||||
// if it's a type change, then we need to clobber or error.
|
||||
// if it's not a type change, then let the impl take care of it.
|
||||
if (currentType !== self.type || self.type === 'File' && current.nlink > 1) {
|
||||
return rimraf(self._path, function (er) {
|
||||
if (er) return self.error(er)
|
||||
self._old = null
|
||||
create(self)
|
||||
})
|
||||
}
|
||||
|
||||
// otherwise, just handle in the app-specific way
|
||||
// this creates a fs.WriteStream, or mkdir's, or whatever
|
||||
create(self)
|
||||
}
|
||||
}
|
||||
|
||||
function create (self) {
|
||||
// console.error("W create", self._path, Writer.dirmode)
|
||||
|
||||
// XXX Need to clobber non-dirs that are in the way,
|
||||
// unless { clobber: false } in the props.
|
||||
mkdir(path.dirname(self._path), Writer.dirmode, function (er, made) {
|
||||
// console.error("W created", path.dirname(self._path), er)
|
||||
if (er) return self.error(er)
|
||||
|
||||
// later on, we have to set the mode and owner for these
|
||||
self._madeDir = made
|
||||
return self._create()
|
||||
})
|
||||
}
|
||||
|
||||
function endChmod (self, want, current, path, cb) {
|
||||
var wantMode = want.mode
|
||||
var chmod = want.follow || self.type !== 'SymbolicLink'
|
||||
? 'chmod' : 'lchmod'
|
||||
|
||||
if (!fs[chmod]) return cb()
|
||||
if (typeof wantMode !== 'number') return cb()
|
||||
|
||||
var curMode = current.mode & parseInt('0777', 8)
|
||||
wantMode = wantMode & parseInt('0777', 8)
|
||||
if (wantMode === curMode) return cb()
|
||||
|
||||
fs[chmod](path, wantMode, cb)
|
||||
}
|
||||
|
||||
function endChown (self, want, current, path, cb) {
|
||||
// Don't even try it unless root. Too easy to EPERM.
|
||||
if (process.platform === 'win32') return cb()
|
||||
if (!process.getuid || process.getuid() !== 0) return cb()
|
||||
if (typeof want.uid !== 'number' &&
|
||||
typeof want.gid !== 'number') return cb()
|
||||
|
||||
if (current.uid === want.uid &&
|
||||
current.gid === want.gid) return cb()
|
||||
|
||||
var chown = (self.props.follow || self.type !== 'SymbolicLink')
|
||||
? 'chown' : 'lchown'
|
||||
if (!fs[chown]) return cb()
|
||||
|
||||
if (typeof want.uid !== 'number') want.uid = current.uid
|
||||
if (typeof want.gid !== 'number') want.gid = current.gid
|
||||
|
||||
fs[chown](path, want.uid, want.gid, cb)
|
||||
}
|
||||
|
||||
function endUtimes (self, want, current, path, cb) {
|
||||
if (!fs.utimes || process.platform === 'win32') return cb()
|
||||
|
||||
var utimes = (want.follow || self.type !== 'SymbolicLink')
|
||||
? 'utimes' : 'lutimes'
|
||||
|
||||
if (utimes === 'lutimes' && !fs[utimes]) {
|
||||
utimes = 'utimes'
|
||||
}
|
||||
|
||||
if (!fs[utimes]) return cb()
|
||||
|
||||
var curA = current.atime
|
||||
var curM = current.mtime
|
||||
var meA = want.atime
|
||||
var meM = want.mtime
|
||||
|
||||
if (meA === undefined) meA = curA
|
||||
if (meM === undefined) meM = curM
|
||||
|
||||
if (!isDate(meA)) meA = new Date(meA)
|
||||
if (!isDate(meM)) meA = new Date(meM)
|
||||
|
||||
if (meA.getTime() === curA.getTime() &&
|
||||
meM.getTime() === curM.getTime()) return cb()
|
||||
|
||||
fs[utimes](path, meA, meM, cb)
|
||||
}
|
||||
|
||||
// XXX This function is beastly. Break it up!
|
||||
Writer.prototype._finish = function () {
|
||||
var self = this
|
||||
|
||||
if (self._finishing) return
|
||||
self._finishing = true
|
||||
|
||||
// console.error(" W Finish", self._path, self.size)
|
||||
|
||||
// set up all the things.
|
||||
// At this point, we're already done writing whatever we've gotta write,
|
||||
// adding files to the dir, etc.
|
||||
var todo = 0
|
||||
var errState = null
|
||||
var done = false
|
||||
|
||||
if (self._old) {
|
||||
// the times will almost *certainly* have changed.
|
||||
// adds the utimes syscall, but remove another stat.
|
||||
self._old.atime = new Date(0)
|
||||
self._old.mtime = new Date(0)
|
||||
// console.error(" W Finish Stale Stat", self._path, self.size)
|
||||
setProps(self._old)
|
||||
} else {
|
||||
var stat = self.props.follow ? 'stat' : 'lstat'
|
||||
// console.error(" W Finish Stating", self._path, self.size)
|
||||
fs[stat](self._path, function (er, current) {
|
||||
// console.error(" W Finish Stated", self._path, self.size, current)
|
||||
if (er) {
|
||||
// if we're in the process of writing out a
|
||||
// directory, it's very possible that the thing we're linking to
|
||||
// doesn't exist yet (especially if it was intended as a symlink),
|
||||
// so swallow ENOENT errors here and just soldier on.
|
||||
if (er.code === 'ENOENT' &&
|
||||
(self.type === 'Link' || self.type === 'SymbolicLink') &&
|
||||
process.platform === 'win32') {
|
||||
self.ready = true
|
||||
self.emit('ready')
|
||||
self.emit('end')
|
||||
self.emit('close')
|
||||
self.end = self._finish = function () {}
|
||||
return
|
||||
} else return self.error(er)
|
||||
}
|
||||
setProps(self._old = current)
|
||||
})
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
function setProps (current) {
|
||||
todo += 3
|
||||
endChmod(self, self.props, current, self._path, next('chmod'))
|
||||
endChown(self, self.props, current, self._path, next('chown'))
|
||||
endUtimes(self, self.props, current, self._path, next('utimes'))
|
||||
}
|
||||
|
||||
function next (what) {
|
||||
return function (er) {
|
||||
// console.error(" W Finish", what, todo)
|
||||
if (errState) return
|
||||
if (er) {
|
||||
er.fstream_finish_call = what
|
||||
return self.error(errState = er)
|
||||
}
|
||||
if (--todo > 0) return
|
||||
if (done) return
|
||||
done = true
|
||||
|
||||
// we may still need to set the mode/etc. on some parent dirs
|
||||
// that were created previously. delay end/close until then.
|
||||
if (!self._madeDir) return end()
|
||||
else endMadeDir(self, self._path, end)
|
||||
|
||||
function end (er) {
|
||||
if (er) {
|
||||
er.fstream_finish_call = 'setupMadeDir'
|
||||
return self.error(er)
|
||||
}
|
||||
// all the props have been set, so we're completely done.
|
||||
self.emit('end')
|
||||
self.emit('close')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function endMadeDir (self, p, cb) {
|
||||
var made = self._madeDir
|
||||
// everything *between* made and path.dirname(self._path)
|
||||
// needs to be set up. Note that this may just be one dir.
|
||||
var d = path.dirname(p)
|
||||
|
||||
endMadeDir_(self, d, function (er) {
|
||||
if (er) return cb(er)
|
||||
if (d === made) {
|
||||
return cb()
|
||||
}
|
||||
endMadeDir(self, d, cb)
|
||||
})
|
||||
}
|
||||
|
||||
function endMadeDir_ (self, p, cb) {
|
||||
var dirProps = {}
|
||||
Object.keys(self.props).forEach(function (k) {
|
||||
dirProps[k] = self.props[k]
|
||||
|
||||
// only make non-readable dirs if explicitly requested.
|
||||
if (k === 'mode' && self.type !== 'Directory') {
|
||||
dirProps[k] = dirProps[k] | parseInt('0111', 8)
|
||||
}
|
||||
})
|
||||
|
||||
var todo = 3
|
||||
var errState = null
|
||||
fs.stat(p, function (er, current) {
|
||||
if (er) return cb(errState = er)
|
||||
endChmod(self, dirProps, current, p, next)
|
||||
endChown(self, dirProps, current, p, next)
|
||||
endUtimes(self, dirProps, current, p, next)
|
||||
})
|
||||
|
||||
function next (er) {
|
||||
if (errState) return
|
||||
if (er) return cb(errState = er)
|
||||
if (--todo === 0) return cb()
|
||||
}
|
||||
}
|
||||
|
||||
Writer.prototype.pipe = function () {
|
||||
this.error("Can't pipe from writable stream")
|
||||
}
|
||||
|
||||
Writer.prototype.add = function () {
|
||||
this.error("Can't add to non-Directory type")
|
||||
}
|
||||
|
||||
Writer.prototype.write = function () {
|
||||
return true
|
||||
}
|
||||
|
||||
function objectToString (d) {
|
||||
return Object.prototype.toString.call(d)
|
||||
}
|
||||
|
||||
function isDate (d) {
|
||||
return typeof d === 'object' && objectToString(d) === '[object Date]'
|
||||
}
|
Reference in New Issue
Block a user