diff --git a/lib/abstract.js b/lib/abstract.js index acfa910..2a50870 100644 --- a/lib/abstract.js +++ b/lib/abstract.js @@ -62,6 +62,9 @@ function decorate (er, code, me) { er.path = er.path || me.path er.fstream_type = me.type er.fstream_path = me.path + if (me._path !== me.path) { + er.fstream_unc_path = me._path + } er.fstream_class = me.constructor.name er.fstream_stack = new Error().stack.split(/\n/).slice(3).map(function (s) { return s.replace(/^ at /, "") diff --git a/lib/dir-reader.js b/lib/dir-reader.js index 60fdf51..8011728 100644 --- a/lib/dir-reader.js +++ b/lib/dir-reader.js @@ -34,7 +34,7 @@ function DirReader (props) { DirReader.prototype._getEntries = function () { var me = this - fs.readdir(me.path, function (er, entries) { + fs.readdir(me._path, function (er, entries) { if (er) return me.error(er) me._entries = entries me._length = entries.length @@ -58,7 +58,7 @@ DirReader.prototype._read = function () { me._index ++ if (me._index >= me._length) { - // console.error(" DR End/close", me.path) + // console.error(" DR End/close", me._path) me.emit("end") me.emit("close") return @@ -67,7 +67,7 @@ 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]) // 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) { @@ -102,7 +102,7 @@ DirReader.prototype._read = function () { }) entry.on("ready", function EMITCHILD () { - // console.error("DR emit child", entry.path) + // 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. @@ -154,10 +154,10 @@ DirReader.prototype.resume = function (who) { who = who || me me._paused = false - // console.error("DR Emit Resume", me.path) + // console.error("DR Emit Resume", me._path) me.emit("resume", who) if (me._paused) { - // console.error("DR Re-paused", me.path) + // console.error("DR Re-paused", me._path) return } diff --git a/lib/dir-writer.js b/lib/dir-writer.js index 3a8e947..1dc988c 100644 --- a/lib/dir-writer.js +++ b/lib/dir-writer.js @@ -32,7 +32,7 @@ function DirWriter (props) { DirWriter.prototype._create = function () { var me = this - mkdir(me.path, Writer.dirmode, function (er) { + mkdir(me._path, Writer.dirmode, function (er) { if (er) return me.error(er) // ready to start getting entries! me.ready = true @@ -56,7 +56,7 @@ DirWriter.prototype.end = function () { DirWriter.prototype.add = function (entry) { var me = this - // console.error("\tadd", entry.path, "->", me.path) + // console.error("\tadd", entry._path, "->", me._path) collect(entry) if (!me.ready || me._currentEntry) { me._buffer.push(entry) @@ -90,7 +90,7 @@ DirWriter.prototype._process = function () { } me._processing = true - // console.error("DW Entry", entry.path) + // console.error("DW Entry", entry._path) me.emit("entry", entry) @@ -99,8 +99,8 @@ DirWriter.prototype._process = function () { // 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) + 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() @@ -115,12 +115,12 @@ DirWriter.prototype._process = function () { , type: entry.type , depth: me.depth + 1 } - var p = entry.path || entry.props.path + var p = entry._path || entry.props._path if (entry.parent) { - p = p.substr(entry.parent.path.length + 1) + p = p.substr(entry.parent._path.length + 1) } // get rid of any ../../ shenanigans - props.path = path.join(me.path, path.join("/", p)) + 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) { @@ -132,8 +132,8 @@ DirWriter.prototype._process = function () { // 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) + // console.error("DW Child Ready", child.type, child._path) + // console.error(" resuming", entry._path) entry.pipe(child) entry.resume() }) diff --git a/lib/file-reader.js b/lib/file-reader.js index 5758bb7..659c97f 100644 --- a/lib/file-reader.js +++ b/lib/file-reader.js @@ -14,7 +14,7 @@ var fs = require("graceful-fs") inherits(FileReader, Reader) function FileReader (props) { - // console.error(" FR create", props.path, props.size, new Error().stack) + // 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.") @@ -34,7 +34,7 @@ function FileReader (props) { FileReader.prototype._getStream = function () { var me = this - , stream = me._stream = fs.createReadStream(me.path, me.props) + , stream = me._stream = fs.createReadStream(me._path, me.props) if (me.props.blksize) { stream.bufferSize = me.props.blksize @@ -55,7 +55,7 @@ FileReader.prototype._getStream = function () { stream.on("end", function () { if (me._paused || me._buffer.length) { - // console.error("FR Buffering End", me.path) + // console.error("FR Buffering End", me._path) me._buffer.push(EOF) me._read() } else { @@ -64,8 +64,6 @@ FileReader.prototype._getStream = function () { if (me._bytesEmitted !== me.props.size) { me.error("Didn't get expected byte count\n"+ - "type: " + me.type + "\n"+ - "path: " + me.path + "\n" + "expect: "+me.props.size + "\n" + "actual: "+me._bytesEmitted) } @@ -73,11 +71,11 @@ FileReader.prototype._getStream = function () { stream.on("close", function () { if (me._paused || me._buffer.length) { - // console.error("FR Buffering Close", me.path) + // console.error("FR Buffering Close", me._path) me._buffer.push(CLOSE) me._read() } else { - // console.error("FR close 1", me.path) + // console.error("FR close 1", me._path) me.emit("close") } }) @@ -87,36 +85,36 @@ FileReader.prototype._getStream = function () { FileReader.prototype._read = function () { var me = this - // console.error("FR _read", me.path) + // console.error("FR _read", me._path) if (me._paused) { - // console.error("FR _read paused", me.path) + // console.error("FR _read paused", me._path) return } if (!me._stream) { - // console.error("FR _getStream calling", me.path) + // 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) + // 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) + // 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) + // console.error("FR Read emitting buffered close", me._path) me.emit("close") } else { - // console.error("FR Read emitting buffered data", me.path) + // 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) + // console.error("FR Read Re-pausing at "+i, me._path) me._buffer = buf.slice(i) return } @@ -129,7 +127,7 @@ FileReader.prototype._read = function () { FileReader.prototype.pause = function (who) { var me = this - // console.error("FR Pause", me.path) + // console.error("FR Pause", me._path) if (me._paused) return who = who || me me._paused = true @@ -139,7 +137,7 @@ FileReader.prototype.pause = function (who) { FileReader.prototype.resume = function (who) { var me = this - // console.error("FR Resume", me.path) + // console.error("FR Resume", me._path) if (!me._paused) return who = who || me me.emit("resume", who) diff --git a/lib/file-writer.js b/lib/file-writer.js index 6bd5a26..4ed0c9c 100644 --- a/lib/file-writer.js +++ b/lib/file-writer.js @@ -33,7 +33,7 @@ FileWriter.prototype._create = function () { so.mode = Writer.filemode if (me._old && me._old.blksize) so.bufferSize = me._old.blksize - me._stream = fs.createWriteStream(me.path, so) + me._stream = fs.createWriteStream(me._path, so) me._stream.on("open", function (fd) { me.ready = true @@ -47,7 +47,7 @@ FileWriter.prototype._create = function () { me._stream.on("drain", function () { me.emit("drain") }) me._stream.on("close", function () { - // console.error("\n\nFW Stream Close", me.path, me.size) + // console.error("\n\nFW Stream Close", me._path, me.size) me._finish() }) } @@ -88,7 +88,6 @@ FileWriter.prototype._finish = function () { if (typeof me.size === "number" && me._bytesWritten != me.size) { me.error( "Did not get expected byte count.\n" + - "path: " + me.path + "\n" + "expect: " + me.size + "\n" + "actual: " + me._bytesWritten) } diff --git a/lib/link-reader.js b/lib/link-reader.js index 4a01137..7e7ab6c 100644 --- a/lib/link-reader.js +++ b/lib/link-reader.js @@ -33,7 +33,7 @@ function LinkReader (props) { // override the _stat method. LinkReader.prototype._stat = function (currentStat) { var me = this - fs.readlink(me.path, function (er, linkpath) { + fs.readlink(me._path, function (er, linkpath) { if (er) return me.error(er) me.linkpath = me.props.linkpath = linkpath me.emit("linkpath", linkpath) diff --git a/lib/link-writer.js b/lib/link-writer.js index f6a1b74..57684af 100644 --- a/lib/link-writer.js +++ b/lib/link-writer.js @@ -39,7 +39,7 @@ LinkWriter.prototype._create = function () { // 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) { + 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) @@ -47,14 +47,14 @@ LinkWriter.prototype._create = function () { } function clobber (me, lp, link) { - rimraf(me.path, function (er) { + 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) { + fs[link](lp, me._path, function (er) { if (er) return me.error(er) finish(me) }) diff --git a/lib/reader.js b/lib/reader.js index 41688cf..d741ac3 100644 --- a/lib/reader.js +++ b/lib/reader.js @@ -24,7 +24,7 @@ function Reader (props, currentStat) { props = { path: props } } - if (!props.path) { + if (!props._path) { me.error("Must provide a path", null, true) } @@ -93,14 +93,20 @@ function Reader (props, currentStat) { me.depth = props.depth = props.depth || 0 me.parent = props.parent || null me.root = props.root || (props.parent && props.parent.root) || me - me.path = path.resolve(props.path) + + me._path = me.path = path.resolve(props.path) + if (process.platform === "win32" && me._path.length > 200) { + // how DOES one create files on the moon? + 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) + // 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 @@ -108,7 +114,7 @@ function Reader (props, currentStat) { // 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) + // console.error("calling stat", props._path, currentStat) me._stat(currentStat) } @@ -125,13 +131,13 @@ Reader.prototype._stat = function (currentStat) { , props = me.props , stat = props.follow ? "stat" : "lstat" - // console.error("Reader._stat", me.path, currentStat) + // console.error("Reader._stat", me._path, currentStat) if (currentStat) process.nextTick(statCb.bind(null, null, currentStat)) - else fs[stat](me.path, statCb) + else fs[stat](me._path, statCb) function statCb (er, props_) { - // console.error("Reader._stat, statCb", me.path, props_, props_.nlink) + // console.error("Reader._stat, statCb", me._path, props_, props_.nlink) if (er) return me.error(er) Object.keys(props_).forEach(function (k) { @@ -148,14 +154,14 @@ Reader.prototype._stat = function (currentStat) { // 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 + // 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) + // 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 diff --git a/lib/writer.js b/lib/writer.js index 2aac7bf..b141693 100644 --- a/lib/writer.js +++ b/lib/writer.js @@ -69,7 +69,13 @@ function Writer (props, current) { 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 = props.path + + me._path = me.path = path.resolve(props.path) + if (process.platform === "win32" && me._path.length > 200) { + // how DOES one create files on the moon? + me._path = "\\\\?\\" + me.path.replace(/\//g, "\\") + } + me.basename = path.basename(props.path) me.dirname = path.dirname(props.path) me.linkpath = props.linkpath || null @@ -100,9 +106,9 @@ function Writer (props, current) { // 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) { + fs[me.props.follow ? "stat" : "lstat"](me._path, function (er, current) { if (er) { - return me.warn("Cannot create " + me.path + "\n" + + return me.warn("Cannot create " + me._path + "\n" + "Unsupported type: "+me.type, "ENOTSUP") } me._finish() @@ -115,7 +121,7 @@ Writer.prototype._stat = function (current) { , stat = props.follow ? "stat" : "lstat" if (current) statCb(null, current) - else fs[stat](props.path, statCb) + else fs[stat](me._path, statCb) function statCb (er, current) { // if it's not there, great. We'll just create it. @@ -130,7 +136,7 @@ Writer.prototype._stat = function (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) { + return rimraf(me._path, function (er) { if (er) return me.error(er) me._old = null create(me) @@ -146,7 +152,7 @@ Writer.prototype._stat = function (current) { 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) { if (er) return me.error(er) me._create() }) @@ -155,7 +161,7 @@ function create (me) { Writer.prototype._finish = function () { var me = this - // console.error(" W Finish", me.path, me.size) + // 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, @@ -169,13 +175,13 @@ Writer.prototype._finish = function () { // 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) + // 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) + // 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) return me.error(er) setProps(me._old = current) }) @@ -184,7 +190,7 @@ Writer.prototype._finish = function () { return function setProps (current) { - // console.error(" W setprops", me.path) + // console.error(" W setprops", me._path) // mode var wantMode = me.props.mode , chmod = me.props.follow || me.type === "Directory" @@ -194,7 +200,7 @@ Writer.prototype._finish = function () { wantMode = wantMode & 0777 todo ++ // console.error(" W chmod", wantMode.toString(8), me.basename) - fs[chmod](me.path, wantMode, next(chmod)) + fs[chmod](me._path, wantMode, next(chmod)) } // uid, gid @@ -210,12 +216,13 @@ Writer.prototype._finish = function () { 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")) + fs.chown(me._path, me.props.uid, me.props.gid, next("chown")) } } // atime, mtime. - if (fs.utimes) { + if (fs.utimes && + !(process.platform === "win32" && me.type === "Directory")) { var utimes = (me.props.follow || me.type !== "SymbolicLink") ? "utimes" : "lutimes" @@ -248,7 +255,7 @@ Writer.prototype._finish = function () { meM.getTime() !== curM.getTime()) { todo ++ // console.error(" W utimes", meA, meM, me.basename) - fs[utimes](me.path, meA, meM, next("utimes")) + fs[utimes](me._path, meA, meM, next("utimes")) } } @@ -263,7 +270,6 @@ Writer.prototype._finish = function () { // console.error(" W Finish", what, todo) if (errState) return if (er) { - er.fstream_path = me.path er.fstream_finish_call = what return me.error(errState = er) }