Add 'fstream' as a dependency.

This commit is contained in:
Nathan Rajlich 2012-02-27 13:00:27 -08:00
parent 301f8b82ec
commit 72fa76e585
88 changed files with 156 additions and 708 deletions

3
node_modules/fstream/examples/deep-copy/.npmignore generated vendored Normal file
View file

@ -0,0 +1,3 @@
.*.swp
examples/deep-copy
node_modules/

3
node_modules/fstream/examples/deep-copy/.travis.yml generated vendored Normal file
View file

@ -0,0 +1,3 @@
language: node_js
node_js:
- 0.6

76
node_modules/fstream/examples/deep-copy/README.md generated vendored Normal file
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.

View file

@ -0,0 +1 @@
file

View file

@ -0,0 +1,115 @@
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 = ""
var escape = {}
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)
} while (p = p.parent)
throw new Error("\033[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) {
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\033[32m")
entry.pause()
entry.once("resume", liftFog)
foggy = setTimeout(liftFog, 10)
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("\033[mthe fog lifts!\n")
clearTimeout(foggy)
foggy = null
if (entry._paused) entry.resume()
}
}
})
}
}
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)
}
ended = false
r.on("end", function () {
if (foggy) clearTimeout(foggy)
console.error("\033[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")
})
r.pipe(w)

View file

@ -0,0 +1,54 @@
var fstream = require("../fstream.js")
var tap = require("tap")
var fs = require("fs")
var path = require("path")
var children = -1
var dir = path.dirname(__dirname)
var gotReady = false
var ended = false
tap.test("reader test", function (t) {
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()
})
})

View file

@ -0,0 +1,24 @@
var fstream = require("../fstream.js")
, closed = false
fstream
.Writer({ path: "path/to/symlink"
, linkpath: "./file"
, isSymbolicLink: true
, mode: "0755" // octal strings supported
})
.on("close", function () {
closed = 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((closed?"":"not ")+"ok 3 should be closed")
})

31
node_modules/fstream/examples/deep-copy/fstream.js generated vendored Normal file
View file

@ -0,0 +1,31 @@
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")

View file

@ -0,0 +1,82 @@
// the parent class for all fstreams.
module.exports = Abstract
var Stream = require("stream").Stream
, 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.destroy = function () {}
Abstract.prototype.warn = function (msg, code) {
var me = this
, er = decorate(msg, code, me)
if (!me.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 {
me.emit("warn", er)
}
}
Abstract.prototype.info = function (msg, code) {
var me = this
if (!me.listeners("info")) return
me.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, me) {
if (!(er instanceof Error)) er = new Error(er)
er.code = er.code || code
er.path = er.path || me.path
er.fstream_type = er.fstream_type || me.type
er.fstream_path = er.fstream_path || me.path
if (me._path !== me.path) {
er.fstream_unc_path = er.fstream_unc_path || me._path
}
if (me.linkpath) {
er.fstream_linkpath = er.fstream_linkpath || me.linkpath
}
er.fstream_class = er.fstream_class || me.constructor.name
er.fstream_stack = er.fstream_stack ||
new Error().stack.split(/\n/).slice(3).map(function (s) {
return s.replace(/^ at /, "")
})
return er
}

67
node_modules/fstream/examples/deep-copy/lib/collect.js generated vendored Normal file
View file

@ -0,0 +1,67 @@
module.exports = collect
function collect (stream) {
if (stream._collected) return
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)
}

View file

@ -0,0 +1,192 @@
// 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")
, fstream = require("../fstream.js")
, Reader = fstream.Reader
, inherits = require("inherits")
, mkdir = require("mkdirp")
, path = require("path")
, Reader = require("./reader.js")
inherits(DirReader, Reader)
function DirReader (props) {
var me = this
if (!(me 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)
}
me._entries = null
me._index = -1
me._paused = false
me._length = -1
Reader.call(this, props)
}
DirReader.prototype._getEntries = function () {
var me = this
fs.readdir(me._path, function (er, entries) {
if (er) return me.error(er)
me._entries = entries
me._length = entries.length
// console.error("DR %s sort =", me.path, me.props.sort)
if (typeof me.props.sort === "function") {
me._entries.sort(me.props.sort)
}
me._read()
})
}
// start walking the dir, and emit an "entry" event for each one.
DirReader.prototype._read = function () {
var me = this
if (!me._entries) return me._getEntries()
if (me._paused || me._currentEntry || me._aborted) {
// console.error("DR paused=%j, current=%j, aborted=%j", me._paused, !!me._currentEntry, me._aborted)
return
}
me._index ++
if (me._index >= me._length) {
if (!me._ended) {
me._ended = true
me.emit("end")
me.emit("close")
}
return
}
// ok, handle this one, then.
// save creating a proxy, by stat'ing the thing now.
var p = path.resolve(me._path, me._entries[me._index])
// set this to prevent trying to _read() again in the stat time.
me._currentEntry = p
fs[ me.props.follow ? "stat" : "lstat" ](p, function (er, stat) {
if (er) return me.error(er)
var entry = Reader({ path: p
, depth: me.depth + 1
, root: me.root || me._proxy || me
, parent: me._proxy || me
, follow: me.follow
, filter: me.filter
, sort: me.props.sort
}, stat)
// console.error("DR Entry", p, stat.size)
me._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 (!me._paused) {
me.pause(who)
}
})
entry.on("resume", function (who) {
if (me._paused) {
me.resume(who)
}
})
entry.on("ready", function EMITCHILD () {
// console.error("DR emit child", entry._path)
if (me._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(me)
return me.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") {
me.emit("socket", entry)
} else {
me.emit("entry", entry)
me.emit("child", entry)
}
})
var ended = false
entry.on("close", onend)
function onend () {
if (ended) return
ended = true
me.emit("childEnd", entry)
me.emit("entryEnd", entry)
me._currentEntry = null
me._read()
}
// XXX Make this work in node.
// Long filenames should not break stuff.
entry.on("error", function (er) {
if (entry._swallowErrors) {
me.warn(er)
entry.emit("end")
entry.emit("close")
} else {
me.emit("error", er)
}
})
// proxy up some events.
; [ "child"
, "childEnd"
, "warn"
].forEach(function (ev) {
entry.on(ev, me.emit.bind(me, ev))
})
})
}
DirReader.prototype.pause = function (who) {
var me = this
if (me._paused) return
who = who || me
me._paused = true
if (me._currentEntry && me._currentEntry.pause) {
me._currentEntry.pause(who)
}
me.emit("pause", who)
}
DirReader.prototype.resume = function (who) {
var me = this
if (!me._paused) return
who = who || me
me._paused = false
// console.error("DR Emit Resume", me._path)
me.emit("resume", who)
if (me._paused) {
// console.error("DR Re-paused", me._path)
return
}
if (me._currentEntry) {
if (me._currentEntry.resume) {
me._currentEntry.resume(who)
}
} else me._read()
}

View file

@ -0,0 +1,165 @@
// 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 fs = require("graceful-fs")
, fstream = require("../fstream.js")
, Writer = require("./writer.js")
, inherits = require("inherits")
, mkdir = require("mkdirp")
, path = require("path")
, collect = require("./collect.js")
inherits(DirWriter, Writer)
function DirWriter (props) {
var me = this
if (!(me instanceof DirWriter)) me.error(
"DirWriter must be called as constructor.", null, true)
// should already be established as a Directory type
if (props.type !== "Directory" || !props.Directory) {
me.error("Non-directory type "+ props.type + " " +
JSON.stringify(props), null, true)
}
Writer.call(this, props)
}
DirWriter.prototype._create = function () {
var me = this
mkdir(me._path, Writer.dirmode, function (er) {
if (er) return me.error(er)
// ready to start getting entries!
me.ready = true
me.emit("ready")
})
}
// 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 me = this
// console.error("\tadd", entry._path, "->", me._path)
collect(entry)
if (!me.ready || me._currentEntry) {
me._buffer.push(entry)
return false
}
// create a new writer, and pipe the incoming entry into it.
if (me._ended) {
return me.error("add after end")
}
me._buffer.push(entry)
me._process()
return 0 === this._buffer.length
}
DirWriter.prototype._process = function () {
var me = this
// console.error("DW Process p=%j", me._processing, me.basename)
if (me._processing) return
var entry = me._buffer.shift()
if (!entry) {
// console.error("DW Drain")
me.emit("drain")
if (me._ended) me._finish()
return
}
me._processing = true
// console.error("DW Entry", entry._path)
me.emit("entry", entry)
// ok, add this entry
//
// don't allow recursive copying
var p = entry
do {
if (p._path === me.root._path || p._path === me._path) {
// console.error("DW Exit (recursive)", entry.basename, me._path)
me._processing = false
if (entry._collected) entry.pipe()
return me._process()
}
} while (p = p.parent)
// console.error("DW not recursive")
// chop off the entry's root dir, replace with ours
var props = { parent: me
, root: me.root || me
, type: entry.type
, depth: me.depth + 1 }
var p = entry._path || entry.path || entry.props.path
if (entry.parent) {
p = p.substr(entry.parent._path.length + 1)
}
// get rid of any ../../ shenanigans
props.path = path.join(me.path, path.join("/", p))
// 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 = me._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) {
me.warn(er)
child.emit("end")
child.emit("close")
} else {
me.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)
me._currentChild = null
me._processing = false
me._process()
}
}

View file

@ -0,0 +1,147 @@
// Basically just a wrapper around an fs.ReadStream
module.exports = FileReader
var fs = require("graceful-fs")
, fstream = require("../fstream.js")
, Reader = fstream.Reader
, inherits = require("inherits")
, mkdir = require("mkdirp")
, Reader = require("./reader.js")
, EOF = {EOF: true}
, CLOSE = {CLOSE: true}
inherits(FileReader, Reader)
function FileReader (props) {
// console.error(" FR create", props.path, props.size, new Error().stack)
var me = this
if (!(me 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)
}
me._buffer = []
me._bytesEmitted = 0
Reader.call(me, props)
}
FileReader.prototype._getStream = function () {
var me = this
, stream = me._stream = fs.createReadStream(me._path, me.props)
if (me.props.blksize) {
stream.bufferSize = me.props.blksize
}
stream.on("open", me.emit.bind(me, "open"))
stream.on("data", function (c) {
// console.error("\t\t%d %s", c.length, me.basename)
me._bytesEmitted += c.length
// no point saving empty chunks
if (!c.length) return
else if (me._paused || me._buffer.length) {
me._buffer.push(c)
me._read()
} else me.emit("data", c)
})
stream.on("end", function () {
if (me._paused || me._buffer.length) {
// console.error("FR Buffering End", me._path)
me._buffer.push(EOF)
me._read()
} else {
me.emit("end")
}
if (me._bytesEmitted !== me.props.size) {
me.error("Didn't get expected byte count\n"+
"expect: "+me.props.size + "\n" +
"actual: "+me._bytesEmitted)
}
})
stream.on("close", function () {
if (me._paused || me._buffer.length) {
// console.error("FR Buffering Close", me._path)
me._buffer.push(CLOSE)
me._read()
} else {
// console.error("FR close 1", me._path)
me.emit("close")
}
})
me._read()
}
FileReader.prototype._read = function () {
var me = this
// console.error("FR _read", me._path)
if (me._paused) {
// console.error("FR _read paused", me._path)
return
}
if (!me._stream) {
// console.error("FR _getStream calling", me._path)
return me._getStream()
}
// clear out the buffer, if there is one.
if (me._buffer.length) {
// console.error("FR _read has buffer", me._buffer.length, me._path)
var buf = me._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", me._path)
me.emit("end")
} else if (c === CLOSE) {
// console.error("FR Read emitting buffered close", me._path)
me.emit("close")
} else {
// console.error("FR Read emitting buffered data", me._path)
me.emit("data", c)
}
if (me._paused) {
// console.error("FR Read Re-pausing at "+i, me._path)
me._buffer = buf.slice(i)
return
}
}
me._buffer.length = 0
}
// console.error("FR _read done")
// that's about all there is to it.
}
FileReader.prototype.pause = function (who) {
var me = this
// console.error("FR Pause", me._path)
if (me._paused) return
who = who || me
me._paused = true
if (me._stream) me._stream.pause()
me.emit("pause", who)
}
FileReader.prototype.resume = function (who) {
var me = this
// console.error("FR Resume", me._path)
if (!me._paused) return
who = who || me
me.emit("resume", who)
me._paused = false
if (me._stream) me._stream.resume()
me._read()
}

View file

@ -0,0 +1,95 @@
module.exports = FileWriter
var fs = require("graceful-fs")
, mkdir = require("mkdirp")
, Writer = require("./writer.js")
, inherits = require("inherits")
, EOF = {}
inherits(FileWriter, Writer)
function FileWriter (props) {
var me = this
if (!(me 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)
}
me._buffer = []
me._bytesWritten = 0
Writer.call(this, props)
}
FileWriter.prototype._create = function () {
var me = this
if (me._stream) return
var so = {}
if (me.props.flags) so.flags = me.props.flags
so.mode = Writer.filemode
if (me._old && me._old.blksize) so.bufferSize = me._old.blksize
me._stream = fs.createWriteStream(me._path, so)
me._stream.on("open", function (fd) {
me.ready = true
me._buffer.forEach(function (c) {
if (c === EOF) me._stream.end()
else me._stream.write(c)
})
me.emit("ready")
})
me._stream.on("drain", function () { me.emit("drain") })
me._stream.on("close", function () {
// console.error("\n\nFW Stream Close", me._path, me.size)
me._finish()
})
}
FileWriter.prototype.write = function (c) {
var me = this
me._bytesWritten += c.length
if (!me.ready) {
me._buffer.push(c)
return false
}
var ret = me._stream.write(c)
// console.error("\t-- fw wrote, _stream says", ret, me._stream._queue.length)
// allow 2 buffered writes, because otherwise there's just too
// much stop and go bs.
return ret || (me._stream._queue && me._stream._queue.length <= 2)
}
FileWriter.prototype.end = function (c) {
var me = this
if (c) me.write(c)
if (!me.ready) {
me._buffer.push(EOF)
return false
}
return me._stream.end()
}
FileWriter.prototype._finish = function () {
var me = this
if (typeof me.size === "number" && me._bytesWritten != me.size) {
me.error(
"Did not get expected byte count.\n" +
"expect: " + me.size + "\n" +
"actual: " + me._bytesWritten)
}
Writer.prototype._finish.call(me)
}

View file

@ -0,0 +1,32 @@
module.exports = getType
function getType (st) {
var types =
[ "Directory"
, "File"
, "SymbolicLink"
, "Link" // special for hardlinks from tarballs
, "BlockDevice"
, "CharacterDevice"
, "FIFO"
, "Socket" ]
, type
if (st.type && -1 !== types.indexOf(st.type)) {
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
}

View file

@ -0,0 +1,54 @@
// 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")
, fstream = require("../fstream.js")
, inherits = require("inherits")
, mkdir = require("mkdirp")
, Reader = require("./reader.js")
inherits(LinkReader, Reader)
function LinkReader (props) {
var me = this
if (!(me 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(me, 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 me = this
fs.readlink(me._path, function (er, linkpath) {
if (er) return me.error(er)
me.linkpath = me.props.linkpath = linkpath
me.emit("linkpath", linkpath)
Reader.prototype._stat.call(me, currentStat)
})
}
LinkReader.prototype._read = function () {
var me = this
if (me._paused) return
// basically just a no-op, since we got all the info we need
// from the _stat method
if (!me._ended) {
me.emit("end")
me.emit("close")
me._ended = true
}
}

View file

@ -0,0 +1,96 @@
module.exports = LinkWriter
var fs = require("graceful-fs")
, Writer = require("./writer.js")
, inherits = require("inherits")
, collect = require("./collect.js")
, path = require("path")
, rimraf = require("rimraf")
inherits(LinkWriter, Writer)
function LinkWriter (props) {
var me = this
if (!(me 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) {
me.error("Need linkpath property to create " + props.type)
}
Writer.call(this, props)
}
LinkWriter.prototype._create = function () {
// console.error(" LW _create")
var me = this
, hard = me.type === "Link" || process.platform === "win32"
, link = hard ? "link" : "symlink"
, lp = hard ? path.resolve(me.dirname, me.linkpath) : me.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(me, lp, link)
fs.readlink(me._path, function (er, p) {
// only skip creation if it's exactly the same link
if (p && p === lp) return finish(me)
clobber(me, lp, link)
})
}
function clobber (me, lp, link) {
rimraf(me._path, function (er) {
if (er) return me.error(er)
create(me, lp, link)
})
}
function create (me, lp, link) {
fs[link](lp, me._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") {
me.ready = true
me.emit("ready")
me.emit("end")
me.emit("close")
me.end = me._finish = function () {}
} else return me.error(er)
}
finish(me)
})
}
function finish (me) {
me.ready = true
me.emit("ready")
if (me._ended && !me._finished) me._finish()
}
LinkWriter.prototype.end = function () {
// console.error("LW finish in end")
this._ended = true
if (this.ready) {
this._finished = true
this._finish()
}
}

View file

@ -0,0 +1,89 @@
// A reader for when we don't yet know what kind of thing
// the thing is.
module.exports = ProxyReader
var Reader = require("./reader.js")
, getType = require("./get-type.js")
, inherits = require("inherits")
, fs = require("graceful-fs")
inherits(ProxyReader, Reader)
function ProxyReader (props) {
var me = this
if (!(me instanceof ProxyReader)) throw new Error(
"ProxyReader must be called as constructor.")
me.props = props
me._buffer = []
me.ready = false
Reader.call(me, props)
}
ProxyReader.prototype._stat = function () {
var me = this
, props = me.props
// stat the thing to see what the proxy should be.
, 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 = me.type = type
me._old = current
me._addProxy(Reader(props, current))
})
}
ProxyReader.prototype._addProxy = function (proxy) {
var me = this
if (me._proxyTarget) {
return me.error("proxy already set")
}
me._proxyTarget = proxy
proxy._proxy = me
; [ "error"
, "data"
, "end"
, "close"
, "linkpath"
, "entry"
, "warn"
].forEach(function (ev) {
// console.error("~~ proxy event", ev, me.path)
proxy.on(ev, me.emit.bind(me, ev))
})
me.emit("proxy", proxy)
proxy.on("ready", function () {
// console.error("~~ proxy is ready!", me.path)
me.ready = true
me.emit("ready")
})
var calls = me._buffer
me._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
}

View file

@ -0,0 +1,109 @@
// 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")
, getType = require("./get-type.js")
, inherits = require("inherits")
, collect = require("./collect.js")
, fs = require("fs")
inherits(ProxyWriter, Writer)
function ProxyWriter (props) {
var me = this
if (!(me instanceof ProxyWriter)) throw new Error(
"ProxyWriter must be called as constructor.")
me.props = props
me._needDrain = false
Writer.call(me, props)
}
ProxyWriter.prototype._stat = function () {
var me = this
, props = me.props
// stat the thing to see what the proxy should be.
, 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 = me.type = type
me._old = current
me._addProxy(Writer(props, current))
})
}
ProxyWriter.prototype._addProxy = function (proxy) {
// console.error("~~ set proxy", this.path)
var me = this
if (me._proxy) {
return me.error("proxy already set")
}
me._proxy = proxy
; [ "ready"
, "error"
, "close"
, "pipe"
, "drain"
, "warn"
].forEach(function (ev) {
proxy.on(ev, me.emit.bind(me, ev))
})
me.emit("proxy", proxy)
var calls = me._buffer
calls.forEach(function (c) {
// console.error("~~ ~~ proxy buffered call", c[0], c[1])
proxy[c[0]].call(proxy, c[1])
})
me._buffer.length = 0
if (me._needsDrain) me.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)
}

240
node_modules/fstream/examples/deep-copy/lib/reader.js generated vendored Normal file
View file

@ -0,0 +1,240 @@
module.exports = Reader
var fs = require("graceful-fs")
, Stream = require("stream").Stream
, inherits = require("inherits")
, path = require("path")
, getType = require("./get-type.js")
, hardLinks = Reader.hardLinks = {}
, Abstract = require("./abstract.js")
// Must do this *before* loading the child classes
inherits(Reader, Abstract)
var DirReader = require("./dir-reader.js")
, FileReader = require("./file-reader.js")
, LinkReader = require("./link-reader.js")
, SocketReader = require("./socket-reader.js")
, ProxyReader = require("./proxy-reader.js")
function Reader (props, currentStat) {
var me = this
if (!(me instanceof Reader)) return new Reader(props, currentStat)
if (typeof props === "string") {
props = { path: props }
}
if (!props.path) {
me.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
, 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 = DirReader
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 = FileReader
break
case "SymbolicLink":
ClassType = LinkReader
break
case "Socket":
ClassType = SocketReader
break
case null:
ClassType = ProxyReader
break
}
if (!(me instanceof ClassType)) {
return new ClassType(props)
}
Abstract.call(me)
me.readable = true
me.writable = false
me.type = type
me.props = props
me.depth = props.depth = props.depth || 0
me.parent = props.parent || null
me.root = props.root || (props.parent && props.parent.root) || me
me._path = me.path = path.resolve(props.path)
if (process.platform === "win32") {
me.path = me._path = me.path.replace(/\?/g, "_")
if (me._path.length >= 260) {
// how DOES one create files on the moon?
// if the path has spaces in it, then UNC will fail.
me._swallowErrors = true
//if (me._path.indexOf(" ") === -1) {
me._path = "\\\\?\\" + me.path.replace(/\//g, "\\")
//}
}
}
me.basename = props.basename = path.basename(me.path)
me.dirname = props.dirname = path.dirname(me.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)
me.size = props.size
me.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 me._read()
// to start reading whatever it is.
// console.error("calling stat", props.path, currentStat)
me._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 me = this
, props = me.props
, stat = props.follow ? "stat" : "lstat"
// console.error("Reader._stat", me._path, currentStat)
if (currentStat) process.nextTick(statCb.bind(null, null, currentStat))
else fs[stat](me._path, statCb)
function statCb (er, props_) {
// console.error("Reader._stat, statCb", me._path, props_, props_.nlink)
if (er) return me.error(er)
Object.keys(props_).forEach(function (k) {
props[k] = props_[k]
})
// if it's not the expected size, then abort here.
if (undefined !== me.size && props.size !== me.size) {
return me.error("incorrect size")
}
me.size = props.size
var type = getType(props)
// special little thing for handling hardlinks.
if (type !== "Directory" && props.nlink && props.nlink > 1) {
var k = props.dev + ":" + props.ino
// console.error("Reader has nlink", me._path, k)
if (hardLinks[k] === me._path || !hardLinks[k]) hardLinks[k] = me._path
else {
// switch into hardlink mode.
type = me.type = me.props.type = "Link"
me.Link = me.props.Link = true
me.linkpath = me.props.linkpath = hardLinks[k]
// console.error("Hardlink detected, switching mode", me._path, me.linkpath)
// Setting __proto__ would arguably be the "correct"
// approach here, but that just seems too wrong.
me._stat = me._read = LinkReader.prototype._read
}
}
if (me.type && me.type !== type) {
me.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 (me.filter) {
// special handling for ProxyReaders
if (!me.filter.call(me._proxy || me)) {
me._aborted = true
me.emit("end")
me.emit("close")
return
}
}
me.emit("ready", props)
// if it's a directory, then we'll be emitting "entry" events.
me._read()
}
}
Reader.prototype.pipe = function (dest, opts) {
var me = this
if (typeof dest.add === "function") {
// piping to a multi-compatible, and we've got directory entries.
me.on("entry", function (entry) {
var ret = dest.add(entry)
if (false === ret) {
me.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)
}

View file

@ -0,0 +1,38 @@
// 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 fs = require("graceful-fs")
, fstream = require("../fstream.js")
, inherits = require("inherits")
, mkdir = require("mkdirp")
, Reader = require("./reader.js")
inherits(SocketReader, Reader)
function SocketReader (props) {
var me = this
if (!(me 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(me, props)
}
SocketReader.prototype._read = function () {
var me = this
if (me._paused) return
// basically just a no-op, since we got all the info we have
// from the _stat method
if (!me._ended) {
me.emit("end")
me.emit("close")
me._ended = true
}
}

316
node_modules/fstream/examples/deep-copy/lib/writer.js generated vendored Normal file
View file

@ -0,0 +1,316 @@
module.exports = Writer
var fs = require("graceful-fs")
, inherits = require("inherits")
, rimraf = require("rimraf")
, mkdir = require("mkdirp")
, path = require("path")
, umask = process.platform === "win32" ? 0 : process.umask()
, getType = require("./get-type.js")
, Abstract = require("./abstract.js")
// Must do this *before* loading the child classes
inherits(Writer, Abstract)
Writer.dirmode = 0777 & (~umask)
Writer.filemode = 0666 & (~umask)
var DirWriter = require("./dir-writer.js")
, LinkWriter = require("./link-writer.js")
, FileWriter = require("./file-writer.js")
, 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 me = this
if (typeof props === "string") {
props = { path: props }
}
if (!props.path) me.error("Must provide a path", null, true)
// polymorphism.
// call fstream.Writer(dir) to get a DirWriter object, etc.
var type = getType(props)
, ClassType = Writer
switch (type) {
case "Directory":
ClassType = DirWriter
break
case "File":
ClassType = FileWriter
break
case "Link":
case "SymbolicLink":
ClassType = LinkWriter
break
case null:
// Don't know yet what type to create, so we wrap in a proxy.
ClassType = ProxyWriter
break
}
if (!(me instanceof ClassType)) return new ClassType(props)
// now get down to business.
Abstract.call(me)
// props is what we want to set.
// set some convenience properties as well.
me.type = props.type
me.props = props
me.depth = props.depth || 0
me.clobber = false === props.clobber ? props.clobber : true
me.parent = props.parent || null
me.root = props.root || (props.parent && props.parent.root) || me
me._path = me.path = path.resolve(props.path)
if (process.platform === "win32") {
me.path = me._path = me.path.replace(/\?/g, "_")
if (me._path.length >= 260) {
me._swallowErrors = true
me._path = "\\\\?\\" + me.path.replace(/\//g, "\\")
}
}
me.basename = path.basename(props.path)
me.dirname = path.dirname(props.path)
me.linkpath = props.linkpath || null
props.parent = props.root = null
// console.error("\n\n\n%s setting size to", props.path, props.size)
me.size = props.size
if (typeof props.mode === "string") {
props.mode = parseInt(props.mode, 8)
}
me.readable = false
me.writable = true
// buffer until ready, or while handling another entry
me._buffer = []
me.ready = false
// start the ball rolling.
// this checks what's there already, and then calls
// me._create() to call the impl-specific creation stuff.
me._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 me = this
fs[me.props.follow ? "stat" : "lstat"](me._path, function (er, current) {
if (er) {
return me.warn("Cannot create " + me._path + "\n" +
"Unsupported type: "+me.type, "ENOTSUP")
}
me._finish()
})
}
Writer.prototype._stat = function (current) {
var me = this
, props = me.props
, stat = props.follow ? "stat" : "lstat"
if (current) statCb(null, current)
else fs[stat](me._path, statCb)
function statCb (er, current) {
// 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(me)
}
me._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 !== me.type) {
return rimraf(me._path, function (er) {
if (er) return me.error(er)
me._old = null
create(me)
})
}
// otherwise, just handle in the app-specific way
// this creates a fs.WriteStream, or mkdir's, or whatever
create(me)
}
}
function create (me) {
// console.error("W create", me._path, Writer.dirmode)
// XXX Need to clobber non-dirs that are in the way,
// unless { clobber: false } in the props.
mkdir(path.dirname(me._path), Writer.dirmode, function (er) {
// console.error("W created", path.dirname(me._path), er)
if (er) return me.error(er)
me._create()
})
}
Writer.prototype._finish = function () {
var me = this
// console.error(" W Finish", me._path, me.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 (me._old) {
// the times will almost *certainly* have changed.
// adds the utimes syscall, but remove another stat.
me._old.atime = new Date(0)
me._old.mtime = new Date(0)
// console.error(" W Finish Stale Stat", me._path, me.size)
setProps(me._old)
} else {
var stat = me.props.follow ? "stat" : "lstat"
// console.error(" W Finish Stating", me._path, me.size)
fs[stat](me._path, function (er, current) {
// console.error(" W Finish Stated", me._path, me.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" &&
(me.type === "Link" || me.type === "SymbolicLink") &&
process.platform === "win32") {
me.ready = true
me.emit("ready")
me.emit("end")
me.emit("close")
me.end = me._finish = function () {}
return
} else return me.error(er)
}
setProps(me._old = current)
})
}
return
function setProps (current) {
// console.error(" W setprops", me._path)
// mode
var wantMode = me.props.mode
, chmod = me.props.follow || me.type !== "SymbolicLink"
? "chmod" : "lchmod"
if (fs[chmod] && typeof wantMode === "number") {
wantMode = wantMode & 0777
todo ++
// console.error(" W chmod", wantMode.toString(8), me.basename, "\r")
fs[chmod](me._path, wantMode, next(chmod))
}
// uid, gid
// Don't even try it unless root. Too easy to EPERM.
if (process.platform !== "win32" &&
process.getuid && process.getuid() === 0 &&
( typeof me.props.uid === "number" ||
typeof me.props.gid === "number" )) {
var chown = (me.props.follow || me.type !== "SymbolicLink")
? "chown" : "lchown"
if (fs[chown]) {
if (typeof me.props.uid !== "number") me.props.uid = current.uid
if (typeof me.props.gid !== "number") me.props.gid = current.gid
if (me.props.uid !== current.uid || me.props.gid !== current.gid) {
todo ++
// console.error(" W chown", me.props.uid, me.props.gid, me.basename)
fs[chown](me._path, me.props.uid, me.props.gid, next("chown"))
}
}
}
// atime, mtime.
if (fs.utimes && process.platform !== "win32") {
var utimes = (me.props.follow || me.type !== "SymbolicLink")
? "utimes" : "lutimes"
if (utimes === "lutimes" && !fs[utimes]) {
utimes = "utimes"
}
var curA = current.atime
, curM = current.mtime
, meA = me.props.atime
, meM = me.props.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()) {
todo ++
// console.error(" W utimes", meA, meM, me.basename)
fs[utimes](me._path, meA, meM, next("utimes"))
}
}
// finally, handle the case if there was nothing to do.
if (todo === 0) {
// console.error(" W nothing to do", me.basename)
next("nothing to do")()
}
}
function next (what) { return function (er) {
// console.error(" W Finish", what, todo)
if (errState) return
if (er) {
er.fstream_finish_call = what
return me.error(errState = er)
}
if (--todo > 0) return
if (done) return
done = true
// all the props have been set, so we're completely done.
me.emit("end")
me.emit("close")
}}
}
Writer.prototype.pipe = function () {
this.error("Can't pipe from writable stream")
}
Writer.prototype.add = function () {
this.error("Cannot 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]';
}

26
node_modules/fstream/examples/deep-copy/package.json generated vendored Normal file
View file

@ -0,0 +1,26 @@
{
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
"name": "fstream",
"description": "Advanced file system stream things",
"version": "0.1.11",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/fstream.git"
},
"main": "fstream.js",
"engines": {
"node": "0.5 || 0.6 || 0.7"
},
"dependencies": {
"rimraf": "2",
"mkdirp": "0.3",
"graceful-fs": "~1.1.2",
"inherits": "~1.0.0"
},
"devDependencies": {
"tap": "0.1"
},
"scripts": {
"test": "tap examples/*.js"
}
}

1
node_modules/fstream/examples/path/to/symlink generated vendored Symbolic link
View file

@ -0,0 +1 @@
file

115
node_modules/fstream/examples/pipe.js generated vendored Normal file
View file

@ -0,0 +1,115 @@
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 = ""
var escape = {}
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)
} while (p = p.parent)
throw new Error("\033[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) {
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\033[32m")
entry.pause()
entry.once("resume", liftFog)
foggy = setTimeout(liftFog, 10)
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("\033[mthe fog lifts!\n")
clearTimeout(foggy)
foggy = null
if (entry._paused) entry.resume()
}
}
})
}
}
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)
}
ended = false
r.on("end", function () {
if (foggy) clearTimeout(foggy)
console.error("\033[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")
})
r.pipe(w)

54
node_modules/fstream/examples/reader.js generated vendored Normal file
View file

@ -0,0 +1,54 @@
var fstream = require("../fstream.js")
var tap = require("tap")
var fs = require("fs")
var path = require("path")
var children = -1
var dir = path.dirname(__dirname)
var gotReady = false
var ended = false
tap.test("reader test", function (t) {
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()
})
})

24
node_modules/fstream/examples/symlink-write.js generated vendored Normal file
View file

@ -0,0 +1,24 @@
var fstream = require("../fstream.js")
, closed = false
fstream
.Writer({ path: "path/to/symlink"
, linkpath: "./file"
, isSymbolicLink: true
, mode: "0755" // octal strings supported
})
.on("close", function () {
closed = 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((closed?"":"not ")+"ok 3 should be closed")
})