Permalink
Browse files

Try using UNC paths to work around windows weirdness

  • Loading branch information...
1 parent bcec334 commit 3e5d171494fd2ddfc8ce7694c188c99c2a1d680d @isaacs isaacs committed Nov 18, 2011
Showing with 79 additions and 67 deletions.
  1. +3 −0 lib/abstract.js
  2. +6 −6 lib/dir-reader.js
  3. +10 −10 lib/dir-writer.js
  4. +15 −17 lib/file-reader.js
  5. +2 −3 lib/file-writer.js
  6. +1 −1 lib/link-reader.js
  7. +3 −3 lib/link-writer.js
  8. +16 −10 lib/reader.js
  9. +23 −17 lib/writer.js
View
3 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 /, "")
View
12 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
}
View
20 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()
})
View
32 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,20 +64,18 @@ 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)
}
})
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)
View
5 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)
}
View
2 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)
View
6 lib/link-writer.js
@@ -39,22 +39,22 @@ 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)
})
}
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)
})
View
26 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,22 +93,28 @@ 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
// 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
View
40 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)
}

0 comments on commit 3e5d171

Please sign in to comment.