summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorisaacs <i@izs.me>2012-06-08 16:49:03 -0700
committerisaacs <i@izs.me>2012-06-09 09:43:46 -0700
commit424bca15c8e227a9170cfe00f9ba7d9daae6fb03 (patch)
tree2c8022533153ae884c9c2bfbeed39f4e3f757bd2
parent6332a4cf00425c63ae476d89f6705881eb06a3e1 (diff)
downloadnode-424bca15c8e227a9170cfe00f9ba7d9daae6fb03.tar.gz
Fix fs.realpath to work on Windows
1. Make the isRoot check valid 2. Don't cache results based on dev/ino, since those are alwasy 0 on windows.
-rw-r--r--lib/fs.js55
1 files changed, 44 insertions, 11 deletions
diff --git a/lib/fs.js b/lib/fs.js
index 56ca131d2..f0cd903cb 100644
--- a/lib/fs.js
+++ b/lib/fs.js
@@ -897,6 +897,11 @@ var normalize = pathModule.normalize;
// result is [base_with_slash, base], e.g. ['somedir/', 'somedir']
var nextPartRe = /(.*?)(?:[\/]+|$)/g;
+// Regex to split a windows path into three parts: [*, device, slash,
+// tail] windows-only
+var splitDeviceRe =
+ /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?([\\\/])?([\s\S]*?)$/;
+
fs.realpathSync = function realpathSync(p, cache) {
// make p is absolute
p = pathModule.resolve(p);
@@ -931,7 +936,15 @@ fs.realpathSync = function realpathSync(p, cache) {
pos = nextPartRe.lastIndex;
// continue if not a symlink, or if root
- if (!base || knownHard[base] || (cache && cache[base] === base)) {
+ var isRoot = !base;
+ if (isWindows) {
+ // if it doens't have a tail, then it's the root.
+ var split = base.match(splitDeviceRe);
+ if (split) {
+ isRoot = !split[2];
+ }
+ }
+ if (isRoot || knownHard[base] || (cache && cache[base] === base)) {
continue;
}
@@ -948,13 +961,21 @@ fs.realpathSync = function realpathSync(p, cache) {
}
// read the link if it wasn't read before
- var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
- if (!seenLinks[id]) {
+ // dev/ino always return 0 on windows, so skip the check.
+ var linkTarget;
+ if (!isWindows) {
+ var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
+ if (seenLinks[id]) {
+ linkTarget = seenLinks[id];
+ }
+ }
+ if (!linkTarget) {
fs.statSync(base);
- seenLinks[id] = fs.readlinkSync(base);
- resolvedLink = pathModule.resolve(previous, seenLinks[id]);
+ linkTarget = fs.readlinkSync(base);
+ resolvedLink = pathModule.resolve(previous, linkTarget);
// track this, if given a cache.
if (cache) cache[base] = resolvedLink;
+ if (!isWindows) seenLinks[id] = linkTarget;
}
}
@@ -1014,8 +1035,16 @@ fs.realpath = function realpath(p, cache, cb) {
base = previous + result[1];
pos = nextPartRe.lastIndex;
- // continue if known to be hard or if root or in cache already.
- if (!base || knownHard[base] || (cache && cache[base] === base)) {
+ // continue if not a symlink, or if root
+ var isRoot = !base;
+ if (isWindows) {
+ // if it doens't have a tail, then it's the root.
+ var split = base.match(splitDeviceRe);
+ if (split) {
+ isRoot = !split[2];
+ }
+ }
+ if (isRoot || knownHard[base] || (cache && cache[base] === base)) {
return process.nextTick(LOOP);
}
@@ -1039,15 +1068,19 @@ fs.realpath = function realpath(p, cache, cb) {
// stat & read the link if not read before
// call gotTarget as soon as the link target is known
- var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
- if (seenLinks[id]) {
- return gotTarget(null, seenLinks[id], base);
+ // dev/ino always return 0 on windows, so skip the check.
+ if (!isWindows) {
+ var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
+ if (seenLinks[id]) {
+ return gotTarget(null, seenLinks[id], base);
+ }
}
fs.stat(base, function(err) {
if (err) return cb(err);
fs.readlink(base, function(err, target) {
- gotTarget(err, seenLinks[id] = target);
+ if (!isWindows) seenLinks[id] = target;
+ gotTarget(err, target);
});
});
}