update fstream to v0.1.18

This commit is contained in:
Nathan Rajlich 2012-06-06 14:31:56 -07:00
parent a07f082717
commit aa8bc9d7cf
9 changed files with 275 additions and 124 deletions

View file

@ -20,6 +20,11 @@ Abstract.prototype.on = function (ev, fn) {
return this
}
Abstract.prototype.abort = function () {
this._aborted = true
this.emit("abort")
}
Abstract.prototype.destroy = function () {}
Abstract.prototype.warn = function (msg, code) {

View file

@ -11,6 +11,7 @@ var fs = require("graceful-fs")
, mkdir = require("mkdirp")
, path = require("path")
, Reader = require("./reader.js")
, assert = require("assert").ok
inherits(DirReader, Reader)
@ -24,25 +25,42 @@ function DirReader (props) {
throw new Error("Non-directory type "+ props.type)
}
me._entries = null
me.entries = null
me._index = -1
me._paused = false
me._length = -1
if (props.sort) {
this.sort = props.sort
}
Reader.call(this, props)
}
DirReader.prototype._getEntries = function () {
var me = this
// race condition. might pause() before calling _getEntries,
// and then resume, and try to get them a second time.
if (me._gotEntries) return
me._gotEntries = true
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.entries = entries
me.emit("entries", entries)
if (me._paused) me.once("resume", processEntries)
else processEntries()
function processEntries () {
me._length = me.entries.length
if (typeof me.sort === "function") {
me.entries = me.entries.sort(me.sort.bind(me))
}
me._read()
}
me._read()
})
}
@ -50,7 +68,7 @@ DirReader.prototype._getEntries = function () {
DirReader.prototype._read = function () {
var me = this
if (!me._entries) return me._getEntries()
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)
@ -58,7 +76,7 @@ DirReader.prototype._read = function () {
}
me._index ++
if (me._index >= me._length) {
if (me._index >= me.entries.length) {
if (!me._ended) {
me._ended = true
me.emit("end")
@ -70,20 +88,26 @@ DirReader.prototype._read = function () {
// 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])
var p = path.resolve(me._path, me.entries[me._index])
assert(p !== me._path)
assert(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)
var who = me._proxy || me
stat.path = p
stat.basename = path.basename(p)
stat.dirname = path.dirname(p)
var childProps = me.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)
@ -94,17 +118,25 @@ DirReader.prototype._read = function () {
// This nomenclature is not completely final.
entry.on("pause", function (who) {
if (!me._paused) {
if (!me._paused && !entry._disowned) {
me.pause(who)
}
})
entry.on("resume", function (who) {
if (me._paused) {
if (me._paused && !entry._disowned) {
me.resume(who)
}
})
entry.on("stat", function (props) {
me.emit("_entryStat", entry, props)
if (entry._aborted) return
if (entry._paused) entry.once("resume", function () {
me.emit("entryStat", entry, props)
})
})
entry.on("ready", function EMITCHILD () {
// console.error("DR emit child", entry._path)
if (me._paused) {
@ -122,23 +154,25 @@ DirReader.prototype._read = function () {
if (entry.type === "Socket") {
me.emit("socket", entry)
} else {
me.emit("entry", entry)
me.emit("child", entry)
me.emitEntry(entry)
}
})
var ended = false
entry.on("close", onend)
entry.on("disown", onend)
function onend () {
if (ended) return
ended = true
me.emit("childEnd", entry)
me.emit("entryEnd", entry)
me._currentEntry = null
me._read()
if (!me._paused) {
me._read()
}
}
// XXX Make this work in node.
// 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) {
@ -160,6 +194,26 @@ DirReader.prototype._read = function () {
})
}
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 (stat) {
return { depth: this.depth + 1
, root: this.root || this
, parent: this
, follow: this.follow
, filter: this.filter
, sort: this.props.sort
}
}
DirReader.prototype.pause = function (who) {
var me = this
if (me._paused) return
@ -185,8 +239,11 @@ DirReader.prototype.resume = function (who) {
}
if (me._currentEntry) {
if (me._currentEntry.resume) {
me._currentEntry.resume(who)
}
if (me._currentEntry.resume) me._currentEntry.resume(who)
} else me._read()
}
DirReader.prototype.emitEntry = function (entry) {
this.emit("entry", entry)
this.emit("child", entry)
}

View file

@ -100,7 +100,9 @@ DirWriter.prototype._process = function () {
// don't allow recursive copying
var p = entry
do {
if (p._path === me.root._path || p._path === me._path) {
var pp = p._path || p.path
if (pp === me.root._path || pp === me._path ||
(pp && pp.indexOf(me._path) === 0)) {
// console.error("DW Exit (recursive)", entry.basename, me._path)
me._processing = false
if (entry._collected) entry.pipe()

View file

@ -4,7 +4,6 @@ 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")

View file

@ -63,6 +63,7 @@ ProxyReader.prototype._addProxy = function (proxy) {
, "child"
, "childEnd"
, "warn"
, "stat"
].forEach(function (ev) {
// console.error("~~ proxy event", ev, me.path)
proxy.on(ev, me.emit.bind(me, ev))

33
node_modules/fstream/lib/reader.js generated vendored
View file

@ -187,19 +187,38 @@ Reader.prototype._stat = function (currentStat) {
// 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) {
var who = me._proxy || me
// special handling for ProxyReaders
if (!me.filter.call(me._proxy || me)) {
me._aborted = true
me.emit("end")
me.emit("close")
if (!me.filter.call(who, who, props)) {
if (!me._disowned) {
me.abort()
me.emit("end")
me.emit("close")
}
return
}
}
me.emit("ready", props)
// last chance to abort or disown before the flow starts!
var events = ["_stat", "stat", "ready"]
var e = 0
;(function go () {
if (me._aborted) {
me.emit("end")
me.emit("close")
return
}
// if it's a directory, then we'll be emitting "entry" events.
me._read()
if (me._paused) {
me.once("resume", go)
return
}
var ev = events[e ++]
if (!ev) return me._read()
me.emit(ev, props)
go()
})()
}
}

229
node_modules/fstream/lib/writer.js generated vendored
View file

@ -123,12 +123,13 @@ Writer.prototype._stat = function (current) {
var me = this
, props = me.props
, stat = props.follow ? "stat" : "lstat"
, who = me._proxy || me
if (current) statCb(null, current)
else fs[stat](me._path, statCb)
function statCb (er, current) {
if (me.filter && !me.filter.call(me._proxy || me, current)) {
if (me.filter && !me.filter.call(who, who, current)) {
me._aborted = true
me.emit("end")
me.emit("close")
@ -165,13 +166,83 @@ function create (me) {
// 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) {
mkdir(path.dirname(me._path), Writer.dirmode, function (er, made) {
// console.error("W created", path.dirname(me._path), er)
if (er) return me.error(er)
me._create()
// later on, we have to set the mode and owner for these
me._madeDir = made
return me._create()
})
}
function endChmod (me, want, current, path, cb) {
var wantMode = want.mode
, chmod = want.follow || me.type !== "SymbolicLink"
? "chmod" : "lchmod"
if (!fs[chmod]) return cb()
if (typeof wantMode !== "number") return cb()
var curMode = current.mode & 0777
wantMode = wantMode & 0777
if (wantMode === curMode) return cb()
fs[chmod](path, wantMode, cb)
}
function endChown (me, 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 = (me.props.follow || me.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 (me, want, current, path, cb) {
if (!fs.utimes || process.platform === "win32") return cb()
var utimes = (want.follow || me.type !== "SymbolicLink")
? "utimes" : "lutimes"
if (utimes === "lutimes" && !fs[utimes]) {
utimes = "utimes"
}
if (!fs[utimes]) return cb()
var curA = current.atime
, curM = current.mtime
, meA = want.atime
, 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 me = this
@ -219,88 +290,82 @@ Writer.prototype._finish = function () {
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")()
}
endChmod(me, me.props, current, me._path, next("chmod"))
endChown(me, me.props, current, me._path, next("chown"))
endUtimes(me, me.props, current, me._path, next("chown"))
}
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
function next (what) {
todo ++
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")
}}
// we may still need to set the mode/etc. on some parent dirs
// that were created previously. delay end/close until then.
if (!me._madeDir) return end()
else endMadeDir(me, me._path, end)
function end (er) {
if (er) {
er.fstream_finish_call = "setupMadeDir"
return me.error(er)
}
// all the props have been set, so we're completely done.
me.emit("end")
me.emit("close")
}
}
}
}
function endMadeDir (me, p, cb) {
var made = me._madeDir
// everything *between* made and path.dirname(me._path)
// needs to be set up. Note that this may just be one dir.
var d = path.dirname(p)
endMadeDir_(me, d, function (er) {
if (er) return cb(er)
if (d === made) {
return cb()
}
endMadeDir(me, d, cb)
})
}
function endMadeDir_ (me, p, cb) {
var dirProps = {}
Object.keys(me.props).forEach(function (k) {
dirProps[k] = me.props[k]
// only make non-readable dirs if explicitly requested.
if (k === "mode" && me.type !== "Directory") {
dirProps[k] = dirProps[k] | 0111
}
})
var todo = 3
, errState = null
fs.stat(p, function (er, current) {
if (er) return cb(errState = er)
endChmod(me, dirProps, current, p, next)
endChown(me, dirProps, current, p, next)
endUtimes(me, 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 () {

View file

@ -31,8 +31,8 @@
"node": "*"
},
"_engineSupported": true,
"_npmVersion": "1.1.10",
"_nodeVersion": "v0.6.13",
"_npmVersion": "1.1.18",
"_nodeVersion": "v0.6.18",
"_defaultsLoaded": true,
"_from": "inherits@~1.0.0"
}

11
node_modules/fstream/package.json generated vendored
View file

@ -6,7 +6,7 @@
},
"name": "fstream",
"description": "Advanced file system stream things",
"version": "0.1.14",
"version": "0.1.18",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/fstream.git"
@ -32,11 +32,14 @@
"name": "tootallnate",
"email": "nathan@tootallnate.net"
},
"_id": "fstream@0.1.14",
"_id": "fstream@0.1.18",
"optionalDependencies": {},
"_engineSupported": true,
"_npmVersion": "1.1.10",
"_nodeVersion": "v0.6.13",
"_npmVersion": "1.1.18",
"_nodeVersion": "v0.6.18",
"_defaultsLoaded": true,
"dist": {
"shasum": "eb42721022505a2197b1f6dadf517189a5f63522"
},
"_from": "fstream@~0.1.13"
}