added bower, gulp

This commit is contained in:
Bachir Soussi Chiadmi
2017-01-22 15:18:08 +01:00
parent 4c9b35f2d1
commit ac58a24f5c
12657 changed files with 1359874 additions and 579 deletions
@@ -0,0 +1,5 @@
.*.swp
node_modules/
examples/deep-copy/
examples/path/
examples/filter-copy/
@@ -0,0 +1,9 @@
language: node_js
node_js:
- "6"
- "4"
- "0.10"
- "0.12"
before_install:
- "npm config set spin false"
- "npm install -g npm/npm"
+15
View File
@@ -0,0 +1,15 @@
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+76
View File
@@ -0,0 +1,76 @@
Like FS streams, but with stat on them, and supporting directories and
symbolic links, as well as normal files. Also, you can use this to set
the stats on a file, even if you don't change its contents, or to create
a symlink, etc.
So, for example, you can "write" a directory, and it'll call `mkdir`. You
can specify a uid and gid, and it'll call `chown`. You can specify a
`mtime` and `atime`, and it'll call `utimes`. You can call it a symlink
and provide a `linkpath` and it'll call `symlink`.
Note that it won't automatically resolve symbolic links. So, if you
call `fstream.Reader('/some/symlink')` then you'll get an object
that stats and then ends immediately (since it has no data). To follow
symbolic links, do this: `fstream.Reader({path:'/some/symlink', follow:
true })`.
There are various checks to make sure that the bytes emitted are the
same as the intended size, if the size is set.
## Examples
```javascript
fstream
.Writer({ path: "path/to/file"
, mode: 0755
, size: 6
})
.write("hello\n")
.end()
```
This will create the directories if they're missing, and then write
`hello\n` into the file, chmod it to 0755, and assert that 6 bytes have
been written when it's done.
```javascript
fstream
.Writer({ path: "path/to/file"
, mode: 0755
, size: 6
, flags: "a"
})
.write("hello\n")
.end()
```
You can pass flags in, if you want to append to a file.
```javascript
fstream
.Writer({ path: "path/to/symlink"
, linkpath: "./file"
, SymbolicLink: true
, mode: "0755" // octal strings supported
})
.end()
```
If isSymbolicLink is a function, it'll be called, and if it returns
true, then it'll treat it as a symlink. If it's not a function, then
any truish value will make a symlink, or you can set `type:
'SymbolicLink'`, which does the same thing.
Note that the linkpath is relative to the symbolic link location, not
the parent dir or cwd.
```javascript
fstream
.Reader("path/to/dir")
.pipe(fstream.Writer("path/to/other/dir"))
```
This will do like `cp -Rp path/to/dir path/to/other/dir`. If the other
dir exists and isn't a directory, then it'll emit an error. It'll also
set the uid, gid, mode, etc. to be identical. In this way, it's more
like `rsync -a` than simply a copy.
@@ -0,0 +1,134 @@
var fstream = require('../fstream.js')
var path = require('path')
var r = fstream.Reader({
path: path.dirname(__dirname),
filter: function () {
return !this.basename.match(/^\./) &&
!this.basename.match(/^node_modules$/) &&
!this.basename.match(/^deep-copy$/) &&
!this.basename.match(/^filter-copy$/)
}
})
// this writer will only write directories
var w = fstream.Writer({
path: path.resolve(__dirname, 'filter-copy'),
type: 'Directory',
filter: function () {
return this.type === 'Directory'
}
})
var indent = ''
r.on('entry', appears)
r.on('ready', function () {
console.error('ready to begin!', r.path)
})
function appears (entry) {
console.error(indent + 'a %s appears!', entry.type, entry.basename, typeof entry.basename)
if (foggy) {
console.error('FOGGY!')
var p = entry
do {
console.error(p.depth, p.path, p._paused)
p = p.parent
} while (p)
throw new Error('\u001b[mshould not have entries while foggy')
}
indent += '\t'
entry.on('data', missile(entry))
entry.on('end', runaway(entry))
entry.on('entry', appears)
}
var foggy
function missile (entry) {
function liftFog (who) {
if (!foggy) return
if (who) {
console.error('%s breaks the spell!', who && who.path)
} else {
console.error('the spell expires!')
}
console.error('\u001b[mthe fog lifts!\n')
clearTimeout(foggy)
foggy = null
if (entry._paused) entry.resume()
}
if (entry.type === 'Directory') {
var ended = false
entry.once('end', function () { ended = true })
return function (c) {
// throw in some pathological pause()/resume() behavior
// just for extra fun.
process.nextTick(function () {
if (!foggy && !ended) { // && Math.random() < 0.3) {
console.error(indent + '%s casts a spell', entry.basename)
console.error('\na slowing fog comes over the battlefield...\n\u001b[32m')
entry.pause()
entry.once('resume', liftFog)
foggy = setTimeout(liftFog, 1000)
}
})
}
}
return function (c) {
var e = Math.random() < 0.5
console.error(indent + '%s %s for %d damage!',
entry.basename,
e ? 'is struck' : 'fires a chunk',
c.length)
}
}
function runaway (entry) {
return function () {
var e = Math.random() < 0.5
console.error(indent + '%s %s',
entry.basename,
e ? 'turns to flee' : 'is vanquished!')
indent = indent.slice(0, -1)
}
}
w.on('entry', attacks)
// w.on('ready', function () { attacks(w) })
function attacks (entry) {
console.error(indent + '%s %s!', entry.basename,
entry.type === 'Directory' ? 'calls for backup' : 'attacks')
entry.on('entry', attacks)
}
var ended = false
var i = 1
r.on('end', function () {
if (foggy) clearTimeout(foggy)
console.error("\u001b[mIT'S OVER!!")
console.error('A WINNAR IS YOU!')
console.log('ok ' + (i++) + ' A WINNAR IS YOU')
ended = true
// now go through and verify that everything in there is a dir.
var p = path.resolve(__dirname, 'filter-copy')
var checker = fstream.Reader({ path: p })
checker.checker = true
checker.on('child', function (e) {
var ok = e.type === 'Directory'
console.log((ok ? '' : 'not ') + 'ok ' + (i++) +
' should be a dir: ' +
e.path.substr(checker.path.length + 1))
})
})
process.on('exit', function () {
console.log((ended ? '' : 'not ') + 'ok ' + (i) + ' ended')
console.log('1..' + i)
})
r.pipe(w)
@@ -0,0 +1,118 @@
var fstream = require('../fstream.js')
var path = require('path')
var r = fstream.Reader({
path: path.dirname(__dirname),
filter: function () {
return !this.basename.match(/^\./) &&
!this.basename.match(/^node_modules$/) &&
!this.basename.match(/^deep-copy$/)
}
})
var w = fstream.Writer({
path: path.resolve(__dirname, 'deep-copy'),
type: 'Directory'
})
var indent = ''
r.on('entry', appears)
r.on('ready', function () {
console.error('ready to begin!', r.path)
})
function appears (entry) {
console.error(indent + 'a %s appears!', entry.type, entry.basename, typeof entry.basename, entry)
if (foggy) {
console.error('FOGGY!')
var p = entry
do {
console.error(p.depth, p.path, p._paused)
p = p.parent
} while (p)
throw new Error('\u001b[mshould not have entries while foggy')
}
indent += '\t'
entry.on('data', missile(entry))
entry.on('end', runaway(entry))
entry.on('entry', appears)
}
var foggy
function missile (entry) {
function liftFog (who) {
if (!foggy) return
if (who) {
console.error('%s breaks the spell!', who && who.path)
} else {
console.error('the spell expires!')
}
console.error('\u001b[mthe fog lifts!\n')
clearTimeout(foggy)
foggy = null
if (entry._paused) entry.resume()
}
if (entry.type === 'Directory') {
var ended = false
entry.once('end', function () { ended = true })
return function (c) {
// throw in some pathological pause()/resume() behavior
// just for extra fun.
process.nextTick(function () {
if (!foggy && !ended) { // && Math.random() < 0.3) {
console.error(indent + '%s casts a spell', entry.basename)
console.error('\na slowing fog comes over the battlefield...\n\u001b[32m')
entry.pause()
entry.once('resume', liftFog)
foggy = setTimeout(liftFog, 10)
}
})
}
}
return function (c) {
var e = Math.random() < 0.5
console.error(indent + '%s %s for %d damage!',
entry.basename,
e ? 'is struck' : 'fires a chunk',
c.length)
}
}
function runaway (entry) {
return function () {
var e = Math.random() < 0.5
console.error(indent + '%s %s',
entry.basename,
e ? 'turns to flee' : 'is vanquished!')
indent = indent.slice(0, -1)
}
}
w.on('entry', attacks)
// w.on('ready', function () { attacks(w) })
function attacks (entry) {
console.error(indent + '%s %s!', entry.basename,
entry.type === 'Directory' ? 'calls for backup' : 'attacks')
entry.on('entry', attacks)
}
var ended = false
r.on('end', function () {
if (foggy) clearTimeout(foggy)
console.error("\u001b[mIT'S OVER!!")
console.error('A WINNAR IS YOU!')
console.log('ok 1 A WINNAR IS YOU')
ended = true
})
process.on('exit', function () {
console.log((ended ? '' : 'not ') + 'ok 2 ended')
console.log('1..2')
})
r.pipe(w)
@@ -0,0 +1,68 @@
var fstream = require('../fstream.js')
var tap = require('tap')
var fs = require('fs')
var path = require('path')
var dir = path.dirname(__dirname)
tap.test('reader test', function (t) {
var children = -1
var gotReady = false
var ended = false
var r = fstream.Reader({
path: dir,
filter: function () {
// return this.parent === r
return this.parent === r || this === r
}
})
r.on('ready', function () {
gotReady = true
children = fs.readdirSync(dir).length
console.error('Setting expected children to ' + children)
t.equal(r.type, 'Directory', 'should be a directory')
})
r.on('entry', function (entry) {
children--
if (!gotReady) {
t.fail('children before ready!')
}
t.equal(entry.dirname, r.path, 'basename is parent dir')
})
r.on('error', function (er) {
t.fail(er)
t.end()
process.exit(1)
})
r.on('end', function () {
t.equal(children, 0, 'should have seen all children')
ended = true
})
var closed = false
r.on('close', function () {
t.ok(ended, 'saw end before close')
t.notOk(closed, 'close should only happen once')
closed = true
t.end()
})
})
tap.test('reader error test', function (t) {
// assumes non-root on a *nix system
var r = fstream.Reader({ path: '/etc/shadow' })
r.once('error', function (er) {
t.ok(true)
t.end()
})
r.on('end', function () {
t.fail('reader ended without error')
t.end()
})
})
@@ -0,0 +1,27 @@
var fstream = require('../fstream.js')
var notOpen = false
process.chdir(__dirname)
fstream
.Writer({
path: 'path/to/symlink',
linkpath: './file',
isSymbolicLink: true,
mode: '0755' // octal strings supported
})
.on('close', function () {
notOpen = true
var fs = require('fs')
var s = fs.lstatSync('path/to/symlink')
var isSym = s.isSymbolicLink()
console.log((isSym ? '' : 'not ') + 'ok 1 should be symlink')
var t = fs.readlinkSync('path/to/symlink')
var isTarget = t === './file'
console.log((isTarget ? '' : 'not ') + 'ok 2 should link to ./file')
})
.end()
process.on('exit', function () {
console.log((notOpen ? '' : 'not ') + 'ok 3 should be closed')
console.log('1..3')
})
+35
View File
@@ -0,0 +1,35 @@
exports.Abstract = require('./lib/abstract.js')
exports.Reader = require('./lib/reader.js')
exports.Writer = require('./lib/writer.js')
exports.File = {
Reader: require('./lib/file-reader.js'),
Writer: require('./lib/file-writer.js')
}
exports.Dir = {
Reader: require('./lib/dir-reader.js'),
Writer: require('./lib/dir-writer.js')
}
exports.Link = {
Reader: require('./lib/link-reader.js'),
Writer: require('./lib/link-writer.js')
}
exports.Proxy = {
Reader: require('./lib/proxy-reader.js'),
Writer: require('./lib/proxy-writer.js')
}
exports.Reader.Dir = exports.DirReader = exports.Dir.Reader
exports.Reader.File = exports.FileReader = exports.File.Reader
exports.Reader.Link = exports.LinkReader = exports.Link.Reader
exports.Reader.Proxy = exports.ProxyReader = exports.Proxy.Reader
exports.Writer.Dir = exports.DirWriter = exports.Dir.Writer
exports.Writer.File = exports.FileWriter = exports.File.Writer
exports.Writer.Link = exports.LinkWriter = exports.Link.Writer
exports.Writer.Proxy = exports.ProxyWriter = exports.Proxy.Writer
exports.collect = require('./lib/collect.js')
@@ -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
}
@@ -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)
}
@@ -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)
}
@@ -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()
}
}
@@ -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()
}
@@ -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)
}
@@ -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
}
@@ -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
}
}
@@ -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()
}
}
@@ -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
}
@@ -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)
}
@@ -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 }
}
if (!props.path) {
self.error('Must provide a path', null, true)
}
// 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)
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)
}
@@ -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
}
}
@@ -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 }
}
if (!props.path) self.error('Must provide a path', null, true)
// 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)
// 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) {
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]'
}
@@ -0,0 +1,15 @@
The ISC License
Copyright (c) Isaac Z. Schlueter, Ben Noordhuis, and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@@ -0,0 +1,133 @@
# graceful-fs
graceful-fs functions as a drop-in replacement for the fs module,
making various improvements.
The improvements are meant to normalize behavior across different
platforms and environments, and to make filesystem access more
resilient to errors.
## Improvements over [fs module](https://nodejs.org/api/fs.html)
* Queues up `open` and `readdir` calls, and retries them once
something closes if there is an EMFILE error from too many file
descriptors.
* fixes `lchmod` for Node versions prior to 0.6.2.
* implements `fs.lutimes` if possible. Otherwise it becomes a noop.
* ignores `EINVAL` and `EPERM` errors in `chown`, `fchown` or
`lchown` if the user isn't root.
* makes `lchmod` and `lchown` become noops, if not available.
* retries reading a file if `read` results in EAGAIN error.
On Windows, it retries renaming a file for up to one second if `EACCESS`
or `EPERM` error occurs, likely because antivirus software has locked
the directory.
## USAGE
```javascript
// use just like fs
var fs = require('graceful-fs')
// now go and do stuff with it...
fs.readFileSync('some-file-or-whatever')
```
## Global Patching
If you want to patch the global fs module (or any other fs-like
module) you can do this:
```javascript
// Make sure to read the caveat below.
var realFs = require('fs')
var gracefulFs = require('graceful-fs')
gracefulFs.gracefulify(realFs)
```
This should only ever be done at the top-level application layer, in
order to delay on EMFILE errors from any fs-using dependencies. You
should **not** do this in a library, because it can cause unexpected
delays in other parts of the program.
## Changes
This module is fairly stable at this point, and used by a lot of
things. That being said, because it implements a subtle behavior
change in a core part of the node API, even modest changes can be
extremely breaking, and the versioning is thus biased towards
bumping the major when in doubt.
The main change between major versions has been switching between
providing a fully-patched `fs` module vs monkey-patching the node core
builtin, and the approach by which a non-monkey-patched `fs` was
created.
The goal is to trade `EMFILE` errors for slower fs operations. So, if
you try to open a zillion files, rather than crashing, `open`
operations will be queued up and wait for something else to `close`.
There are advantages to each approach. Monkey-patching the fs means
that no `EMFILE` errors can possibly occur anywhere in your
application, because everything is using the same core `fs` module,
which is patched. However, it can also obviously cause undesirable
side-effects, especially if the module is loaded multiple times.
Implementing a separate-but-identical patched `fs` module is more
surgical (and doesn't run the risk of patching multiple times), but
also imposes the challenge of keeping in sync with the core module.
The current approach loads the `fs` module, and then creates a
lookalike object that has all the same methods, except a few that are
patched. It is safe to use in all versions of Node from 0.8 through
7.0.
### v4
* Do not monkey-patch the fs module. This module may now be used as a
drop-in dep, and users can opt into monkey-patching the fs builtin
if their app requires it.
### v3
* Monkey-patch fs, because the eval approach no longer works on recent
node.
* fixed possible type-error throw if rename fails on windows
* verify that we *never* get EMFILE errors
* Ignore ENOSYS from chmod/chown
* clarify that graceful-fs must be used as a drop-in
### v2.1.0
* Use eval rather than monkey-patching fs.
* readdir: Always sort the results
* win32: requeue a file if error has an OK status
### v2.0
* A return to monkey patching
* wrap process.cwd
### v1.1
* wrap readFile
* Wrap fs.writeFile.
* readdir protection
* Don't clobber the fs builtin
* Handle fs.read EAGAIN errors by trying again
* Expose the curOpen counter
* No-op lchown/lchmod if not implemented
* fs.rename patch only for win32
* Patch fs.rename to handle AV software on Windows
* Close #4 Chown should not fail on einval or eperm if non-root
* Fix isaacs/fstream#1 Only wrap fs one time
* Fix #3 Start at 1024 max files, then back off on EMFILE
* lutimes that doens't blow up on Linux
* A full on-rewrite using a queue instead of just swallowing the EMFILE error
* Wrap Read/Write streams as well
### 1.0
* Update engines for node 0.6
* Be lstat-graceful on Windows
* first
@@ -0,0 +1,21 @@
'use strict'
var fs = require('fs')
module.exports = clone(fs)
function clone (obj) {
if (obj === null || typeof obj !== 'object')
return obj
if (obj instanceof Object)
var copy = { __proto__: obj.__proto__ }
else
var copy = Object.create(null)
Object.getOwnPropertyNames(obj).forEach(function (key) {
Object.defineProperty(copy, key, Object.getOwnPropertyDescriptor(obj, key))
})
return copy
}
@@ -0,0 +1,262 @@
var fs = require('fs')
var polyfills = require('./polyfills.js')
var legacy = require('./legacy-streams.js')
var queue = []
var util = require('util')
function noop () {}
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)
}
if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) {
process.on('exit', function() {
debug(queue)
require('assert').equal(queue.length, 0)
})
}
module.exports = patch(require('./fs.js'))
if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH) {
module.exports = patch(fs)
}
// Always patch fs.close/closeSync, because we want 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.
module.exports.close =
fs.close = (function (fs$close) { return function (fd, cb) {
return fs$close.call(fs, fd, function (err) {
if (!err)
retry()
if (typeof cb === 'function')
cb.apply(this, arguments)
})
}})(fs.close)
module.exports.closeSync =
fs.closeSync = (function (fs$closeSync) { return function (fd) {
// Note that graceful-fs also retries when fs.closeSync() fails.
// Looks like a bug to me, although it's probably a harmless one.
var rval = fs$closeSync.apply(fs, arguments)
retry()
return rval
}})(fs.closeSync)
function patch (fs) {
// Everything that references the open() function needs to be in here
polyfills(fs)
fs.gracefulify = patch
fs.FileReadStream = ReadStream; // Legacy name.
fs.FileWriteStream = WriteStream; // Legacy name.
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
ReadStream.prototype = Object.create(fs$ReadStream.prototype)
ReadStream.prototype.open = ReadStream$open
var fs$WriteStream = fs.WriteStream
WriteStream.prototype = Object.create(fs$WriteStream.prototype)
WriteStream.prototype.open = WriteStream$open
fs.ReadStream = ReadStream
fs.WriteStream = WriteStream
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 ReadStream(path, options)
}
function createWriteStream (path, options) {
return new 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])
queue.push(elem)
}
function retry () {
var elem = queue.shift()
if (elem) {
debug('RETRY', elem[0].name, elem[1])
elem[0].apply(null, elem[1])
}
}
@@ -0,0 +1,118 @@
var Stream = require('stream').Stream
module.exports = legacy
function legacy (fs) {
return {
ReadStream: ReadStream,
WriteStream: WriteStream
}
function ReadStream (path, options) {
if (!(this instanceof ReadStream)) return new ReadStream(path, options);
Stream.call(this);
var self = this;
this.path = path;
this.fd = null;
this.readable = true;
this.paused = false;
this.flags = 'r';
this.mode = 438; /*=0666*/
this.bufferSize = 64 * 1024;
options = options || {};
// Mixin options into this
var keys = Object.keys(options);
for (var index = 0, length = keys.length; index < length; index++) {
var key = keys[index];
this[key] = options[key];
}
if (this.encoding) this.setEncoding(this.encoding);
if (this.start !== undefined) {
if ('number' !== typeof this.start) {
throw TypeError('start must be a Number');
}
if (this.end === undefined) {
this.end = Infinity;
} else if ('number' !== typeof this.end) {
throw TypeError('end must be a Number');
}
if (this.start > this.end) {
throw new Error('start must be <= end');
}
this.pos = this.start;
}
if (this.fd !== null) {
process.nextTick(function() {
self._read();
});
return;
}
fs.open(this.path, this.flags, this.mode, function (err, fd) {
if (err) {
self.emit('error', err);
self.readable = false;
return;
}
self.fd = fd;
self.emit('open', fd);
self._read();
})
}
function WriteStream (path, options) {
if (!(this instanceof WriteStream)) return new WriteStream(path, options);
Stream.call(this);
this.path = path;
this.fd = null;
this.writable = true;
this.flags = 'w';
this.encoding = 'binary';
this.mode = 438; /*=0666*/
this.bytesWritten = 0;
options = options || {};
// Mixin options into this
var keys = Object.keys(options);
for (var index = 0, length = keys.length; index < length; index++) {
var key = keys[index];
this[key] = options[key];
}
if (this.start !== undefined) {
if ('number' !== typeof this.start) {
throw TypeError('start must be a Number');
}
if (this.start < 0) {
throw new Error('start must be >= zero');
}
this.pos = this.start;
}
this.busy = false;
this._queue = [];
if (this.fd === null) {
this._open = fs.open;
this._queue.push([this._open, this.path, this.flags, this.mode, undefined]);
this.flush();
}
}
}
@@ -0,0 +1,111 @@
{
"_args": [
[
{
"raw": "graceful-fs@^4.1.2",
"scope": null,
"escapedName": "graceful-fs",
"name": "graceful-fs",
"rawSpec": "^4.1.2",
"spec": ">=4.1.2 <5.0.0",
"type": "range"
},
"/mnt/Data/bach/Sites/clameurs.org/sites/all/themes/figureslibres/inifig/node_modules/fstream"
]
],
"_from": "graceful-fs@>=4.1.2 <5.0.0",
"_id": "graceful-fs@4.1.11",
"_inCache": true,
"_location": "/fstream/graceful-fs",
"_nodeVersion": "6.5.0",
"_npmOperationalInternal": {
"host": "packages-18-east.internal.npmjs.com",
"tmp": "tmp/graceful-fs-4.1.11.tgz_1479843029430_0.2122855328489095"
},
"_npmUser": {
"name": "isaacs",
"email": "i@izs.me"
},
"_npmVersion": "3.10.9",
"_phantomChildren": {},
"_requested": {
"raw": "graceful-fs@^4.1.2",
"scope": null,
"escapedName": "graceful-fs",
"name": "graceful-fs",
"rawSpec": "^4.1.2",
"spec": ">=4.1.2 <5.0.0",
"type": "range"
},
"_requiredBy": [
"/fstream"
],
"_resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
"_shasum": "0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658",
"_shrinkwrap": null,
"_spec": "graceful-fs@^4.1.2",
"_where": "/mnt/Data/bach/Sites/clameurs.org/sites/all/themes/figureslibres/inifig/node_modules/fstream",
"bugs": {
"url": "https://github.com/isaacs/node-graceful-fs/issues"
},
"dependencies": {},
"description": "A drop-in replacement for fs, making various improvements.",
"devDependencies": {
"mkdirp": "^0.5.0",
"rimraf": "^2.2.8",
"tap": "^5.4.2"
},
"directories": {
"test": "test"
},
"dist": {
"shasum": "0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658",
"tarball": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz"
},
"engines": {
"node": ">=0.4.0"
},
"files": [
"fs.js",
"graceful-fs.js",
"legacy-streams.js",
"polyfills.js"
],
"gitHead": "65cf80d1fd3413b823c16c626c1e7c326452bee5",
"homepage": "https://github.com/isaacs/node-graceful-fs#readme",
"keywords": [
"fs",
"module",
"reading",
"retry",
"retries",
"queue",
"error",
"errors",
"handling",
"EMFILE",
"EAGAIN",
"EINVAL",
"EPERM",
"EACCESS"
],
"license": "ISC",
"main": "graceful-fs.js",
"maintainers": [
{
"name": "isaacs",
"email": "i@izs.me"
}
],
"name": "graceful-fs",
"optionalDependencies": {},
"readme": "ERROR: No README data found!",
"repository": {
"type": "git",
"url": "git+https://github.com/isaacs/node-graceful-fs.git"
},
"scripts": {
"test": "node test.js | tap -"
},
"version": "4.1.11"
}
@@ -0,0 +1,330 @@
var fs = require('./fs.js')
var constants = require('constants')
var origCwd = process.cwd
var cwd = null
var platform = process.env.GRACEFUL_FS_PLATFORM || process.platform
process.cwd = function() {
if (!cwd)
cwd = origCwd.call(process)
return cwd
}
try {
process.cwd()
} catch (er) {}
var chdir = process.chdir
process.chdir = function(d) {
cwd = null
chdir.call(process, d)
}
module.exports = patch
function patch (fs) {
// (re-)implement some things that are known busted or missing.
// lchmod, broken prior to 0.6.2
// back-port the fix here.
if (constants.hasOwnProperty('O_SYMLINK') &&
process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
patchLchmod(fs)
}
// lutimes implementation, or no-op
if (!fs.lutimes) {
patchLutimes(fs)
}
// https://github.com/isaacs/node-graceful-fs/issues/4
// Chown should not fail on einval or eperm if non-root.
// It should not fail on enosys ever, as this just indicates
// that a fs doesn't support the intended operation.
fs.chown = chownFix(fs.chown)
fs.fchown = chownFix(fs.fchown)
fs.lchown = chownFix(fs.lchown)
fs.chmod = chmodFix(fs.chmod)
fs.fchmod = chmodFix(fs.fchmod)
fs.lchmod = chmodFix(fs.lchmod)
fs.chownSync = chownFixSync(fs.chownSync)
fs.fchownSync = chownFixSync(fs.fchownSync)
fs.lchownSync = chownFixSync(fs.lchownSync)
fs.chmodSync = chmodFixSync(fs.chmodSync)
fs.fchmodSync = chmodFixSync(fs.fchmodSync)
fs.lchmodSync = chmodFixSync(fs.lchmodSync)
fs.stat = statFix(fs.stat)
fs.fstat = statFix(fs.fstat)
fs.lstat = statFix(fs.lstat)
fs.statSync = statFixSync(fs.statSync)
fs.fstatSync = statFixSync(fs.fstatSync)
fs.lstatSync = statFixSync(fs.lstatSync)
// if lchmod/lchown do not exist, then make them no-ops
if (!fs.lchmod) {
fs.lchmod = function (path, mode, cb) {
if (cb) process.nextTick(cb)
}
fs.lchmodSync = function () {}
}
if (!fs.lchown) {
fs.lchown = function (path, uid, gid, cb) {
if (cb) process.nextTick(cb)
}
fs.lchownSync = function () {}
}
// on Windows, A/V software can lock the directory, causing this
// to fail with an EACCES or EPERM if the directory contains newly
// created files. Try again on failure, for up to 60 seconds.
// Set the timeout this long because some Windows Anti-Virus, such as Parity
// bit9, may lock files for up to a minute, causing npm package install
// failures. Also, take care to yield the scheduler. Windows scheduling gives
// CPU to a busy looping process, which can cause the program causing the lock
// contention to be starved of CPU by node, so the contention doesn't resolve.
if (platform === "win32") {
fs.rename = (function (fs$rename) { return function (from, to, cb) {
var start = Date.now()
var backoff = 0;
fs$rename(from, to, function CB (er) {
if (er
&& (er.code === "EACCES" || er.code === "EPERM")
&& Date.now() - start < 60000) {
setTimeout(function() {
fs.stat(to, function (stater, st) {
if (stater && stater.code === "ENOENT")
fs$rename(from, to, CB);
else
cb(er)
})
}, backoff)
if (backoff < 100)
backoff += 10;
return;
}
if (cb) cb(er)
})
}})(fs.rename)
}
// if read() returns EAGAIN, then just try it again.
fs.read = (function (fs$read) { return function (fd, buffer, offset, length, position, callback_) {
var callback
if (callback_ && typeof callback_ === 'function') {
var eagCounter = 0
callback = function (er, _, __) {
if (er && er.code === 'EAGAIN' && eagCounter < 10) {
eagCounter ++
return fs$read.call(fs, fd, buffer, offset, length, position, callback)
}
callback_.apply(this, arguments)
}
}
return fs$read.call(fs, fd, buffer, offset, length, position, callback)
}})(fs.read)
fs.readSync = (function (fs$readSync) { return function (fd, buffer, offset, length, position) {
var eagCounter = 0
while (true) {
try {
return fs$readSync.call(fs, fd, buffer, offset, length, position)
} catch (er) {
if (er.code === 'EAGAIN' && eagCounter < 10) {
eagCounter ++
continue
}
throw er
}
}
}})(fs.readSync)
}
function patchLchmod (fs) {
fs.lchmod = function (path, mode, callback) {
fs.open( path
, constants.O_WRONLY | constants.O_SYMLINK
, mode
, function (err, fd) {
if (err) {
if (callback) callback(err)
return
}
// prefer to return the chmod error, if one occurs,
// but still try to close, and report closing errors if they occur.
fs.fchmod(fd, mode, function (err) {
fs.close(fd, function(err2) {
if (callback) callback(err || err2)
})
})
})
}
fs.lchmodSync = function (path, mode) {
var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode)
// prefer to return the chmod error, if one occurs,
// but still try to close, and report closing errors if they occur.
var threw = true
var ret
try {
ret = fs.fchmodSync(fd, mode)
threw = false
} finally {
if (threw) {
try {
fs.closeSync(fd)
} catch (er) {}
} else {
fs.closeSync(fd)
}
}
return ret
}
}
function patchLutimes (fs) {
if (constants.hasOwnProperty("O_SYMLINK")) {
fs.lutimes = function (path, at, mt, cb) {
fs.open(path, constants.O_SYMLINK, function (er, fd) {
if (er) {
if (cb) cb(er)
return
}
fs.futimes(fd, at, mt, function (er) {
fs.close(fd, function (er2) {
if (cb) cb(er || er2)
})
})
})
}
fs.lutimesSync = function (path, at, mt) {
var fd = fs.openSync(path, constants.O_SYMLINK)
var ret
var threw = true
try {
ret = fs.futimesSync(fd, at, mt)
threw = false
} finally {
if (threw) {
try {
fs.closeSync(fd)
} catch (er) {}
} else {
fs.closeSync(fd)
}
}
return ret
}
} else {
fs.lutimes = function (_a, _b, _c, cb) { if (cb) process.nextTick(cb) }
fs.lutimesSync = function () {}
}
}
function chmodFix (orig) {
if (!orig) return orig
return function (target, mode, cb) {
return orig.call(fs, target, mode, function (er) {
if (chownErOk(er)) er = null
if (cb) cb.apply(this, arguments)
})
}
}
function chmodFixSync (orig) {
if (!orig) return orig
return function (target, mode) {
try {
return orig.call(fs, target, mode)
} catch (er) {
if (!chownErOk(er)) throw er
}
}
}
function chownFix (orig) {
if (!orig) return orig
return function (target, uid, gid, cb) {
return orig.call(fs, target, uid, gid, function (er) {
if (chownErOk(er)) er = null
if (cb) cb.apply(this, arguments)
})
}
}
function chownFixSync (orig) {
if (!orig) return orig
return function (target, uid, gid) {
try {
return orig.call(fs, target, uid, gid)
} catch (er) {
if (!chownErOk(er)) throw er
}
}
}
function statFix (orig) {
if (!orig) return orig
// Older versions of Node erroneously returned signed integers for
// uid + gid.
return function (target, cb) {
return orig.call(fs, target, function (er, stats) {
if (!stats) return cb.apply(this, arguments)
if (stats.uid < 0) stats.uid += 0x100000000
if (stats.gid < 0) stats.gid += 0x100000000
if (cb) cb.apply(this, arguments)
})
}
}
function statFixSync (orig) {
if (!orig) return orig
// Older versions of Node erroneously returned signed integers for
// uid + gid.
return function (target) {
var stats = orig.call(fs, target)
if (stats.uid < 0) stats.uid += 0x100000000
if (stats.gid < 0) stats.gid += 0x100000000
return stats;
}
}
// ENOSYS means that the fs doesn't support the op. Just ignore
// that, because it doesn't matter.
//
// if there's no getuid, or if getuid() is something other
// than 0, and the error is EINVAL or EPERM, then just ignore
// it.
//
// This specific case is a silent failure in cp, install, tar,
// and most other unix tools that manage permissions.
//
// When running as root, or if other types of errors are
// encountered, then it's strict.
function chownErOk (er) {
if (!er)
return true
if (er.code === "ENOSYS")
return true
var nonroot = !process.getuid || process.getuid() !== 0
if (nonroot) {
if (er.code === "EINVAL" || er.code === "EPERM")
return true
}
return false
}
+109
View File
@@ -0,0 +1,109 @@
{
"_args": [
[
{
"raw": "fstream@^1.0.0",
"scope": null,
"escapedName": "fstream",
"name": "fstream",
"rawSpec": "^1.0.0",
"spec": ">=1.0.0 <2.0.0",
"type": "range"
},
"/mnt/Data/bach/Sites/clameurs.org/sites/all/themes/figureslibres/inifig/node_modules/node-gyp"
]
],
"_from": "fstream@>=1.0.0 <2.0.0",
"_id": "fstream@1.0.10",
"_inCache": true,
"_location": "/fstream",
"_nodeVersion": "4.4.5",
"_npmOperationalInternal": {
"host": "packages-16-east.internal.npmjs.com",
"tmp": "tmp/fstream-1.0.10.tgz_1466189553883_0.3062701092567295"
},
"_npmUser": {
"name": "othiym23",
"email": "ogd@aoaioxxysz.net"
},
"_npmVersion": "3.10.0",
"_phantomChildren": {},
"_requested": {
"raw": "fstream@^1.0.0",
"scope": null,
"escapedName": "fstream",
"name": "fstream",
"rawSpec": "^1.0.0",
"spec": ">=1.0.0 <2.0.0",
"type": "range"
},
"_requiredBy": [
"/node-gyp",
"/tar"
],
"_resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.10.tgz",
"_shasum": "604e8a92fe26ffd9f6fae30399d4984e1ab22822",
"_shrinkwrap": null,
"_spec": "fstream@^1.0.0",
"_where": "/mnt/Data/bach/Sites/clameurs.org/sites/all/themes/figureslibres/inifig/node_modules/node-gyp",
"author": {
"name": "Isaac Z. Schlueter",
"email": "i@izs.me",
"url": "http://blog.izs.me/"
},
"bugs": {
"url": "https://github.com/npm/fstream/issues"
},
"dependencies": {
"graceful-fs": "^4.1.2",
"inherits": "~2.0.0",
"mkdirp": ">=0.5 0",
"rimraf": "2"
},
"description": "Advanced file system stream things",
"devDependencies": {
"standard": "^4.0.0",
"tap": "^1.2.0"
},
"directories": {},
"dist": {
"shasum": "604e8a92fe26ffd9f6fae30399d4984e1ab22822",
"tarball": "https://registry.npmjs.org/fstream/-/fstream-1.0.10.tgz"
},
"engines": {
"node": ">=0.6"
},
"gitHead": "24fabdec32e334dd3b130d77b38c010e3119b102",
"homepage": "https://github.com/npm/fstream#readme",
"license": "ISC",
"main": "fstream.js",
"maintainers": [
{
"name": "iarna",
"email": "me@re-becca.org"
},
{
"name": "isaacs",
"email": "isaacs@npmjs.com"
},
{
"name": "othiym23",
"email": "ogd@aoaioxxysz.net"
},
{
"name": "zkat",
"email": "kat@sykosomatic.org"
}
],
"name": "fstream",
"optionalDependencies": {},
"readme": "ERROR: No README data found!",
"repository": {
"type": "git",
"url": "git+https://github.com/npm/fstream.git"
},
"scripts": {
"test": "standard && tap examples/*.js"
},
"version": "1.0.10"
}