Expose posix realpath on windows as well
authorisaacs <i@izs.me>
Fri, 8 Jun 2012 22:26:04 +0000 (15:26 -0700)
committerisaacs <i@izs.me>
Sat, 9 Jun 2012 16:43:46 +0000 (09:43 -0700)
lib/fs.js

index cbc1087..56ca131 100644 (file)
--- a/lib/fs.js
+++ b/lib/fs.js
@@ -893,222 +893,184 @@ fs.unwatchFile = function(filename) {
 
 var normalize = pathModule.normalize;
 
-if (isWindows) {
-  // Node doesn't support symlinks / lstat on windows. Hence realpath is just
-  // the same as path.resolve that fails if the path doesn't exists.
-
-  // windows version
-  fs.realpathSync = function realpathSync(p, cache) {
-    p = pathModule.resolve(p);
-    if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
-      return cache[p];
-    }
-    fs.statSync(p);
-    if (cache) cache[p] = p;
-    return p;
-  };
-
-  // windows version
-  fs.realpath = function(p, cache, cb) {
-    if (typeof cb !== 'function') {
-      cb = cache;
-      cache = null;
-    }
-    p = pathModule.resolve(p);
-    if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
-      return cb(null, cache[p]);
-    }
-    fs.stat(p, function(err) {
-      if (err) return cb(err);
-      if (cache) cache[p] = p;
-      cb(null, p);
-    });
-  };
+// Regexp that finds the next partion of a (partial) path
+// result is [base_with_slash, base], e.g. ['somedir/', 'somedir']
+var nextPartRe = /(.*?)(?:[\/]+|$)/g;
 
+fs.realpathSync = function realpathSync(p, cache) {
+  // make p is absolute
+  p = pathModule.resolve(p);
 
-} else /* posix */ {
-
-  // Regexp that finds the next partion of a (partial) path
-  // result is [base_with_slash, base], e.g. ['somedir/', 'somedir']
-  var nextPartRe = /(.*?)(?:[\/]+|$)/g;
+  if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
+    return cache[p];
+  }
 
-  // posix version
-  fs.realpathSync = function realpathSync(p, cache) {
-    // make p is absolute
-    p = pathModule.resolve(p);
+  var original = p,
+      seenLinks = {},
+      knownHard = {};
 
-    if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
-      return cache[p];
+  // current character position in p
+  var pos = 0;
+  // the partial path so far, including a trailing slash if any
+  var current = '';
+  // the partial path without a trailing slash
+  var base = '';
+  // the partial path scanned in the previous round, with slash
+  var previous = '';
+
+  // walk down the path, swapping out linked pathparts for their real
+  // values
+  // NB: p.length changes.
+  while (pos < p.length) {
+    // find the next part
+    nextPartRe.lastIndex = pos;
+    var result = nextPartRe.exec(p);
+    previous = current;
+    current += result[0];
+    base = previous + result[1];
+    pos = nextPartRe.lastIndex;
+
+    // continue if not a symlink, or if root
+    if (!base || knownHard[base] || (cache && cache[base] === base)) {
+      continue;
     }
 
-    var original = p,
-        seenLinks = {},
-        knownHard = {};
-
-    // current character position in p
-    var pos = 0;
-    // the partial path so far, including a trailing slash if any
-    var current = '';
-    // the partial path without a trailing slash
-    var base = '';
-    // the partial path scanned in the previous round, with slash
-    var previous = '';
-
-    // walk down the path, swapping out linked pathparts for their real
-    // values
-    // NB: p.length changes.
-    while (pos < p.length) {
-      // find the next part
-      nextPartRe.lastIndex = pos;
-      var result = nextPartRe.exec(p);
-      previous = current;
-      current += result[0];
-      base = previous + result[1];
-      pos = nextPartRe.lastIndex;
-
-      // continue if not a symlink, or if root
-      if (!base || knownHard[base] || (cache && cache[base] === base)) {
+    var resolvedLink;
+    if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
+      // some known symbolic link.  no need to stat again.
+      resolvedLink = cache[base];
+    } else {
+      var stat = fs.lstatSync(base);
+      if (!stat.isSymbolicLink()) {
+        knownHard[base] = true;
+        if (cache) cache[base] = base;
         continue;
       }
 
-      var resolvedLink;
-      if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
-        // some known symbolic link.  no need to stat again.
-        resolvedLink = cache[base];
-      } else {
-        var stat = fs.lstatSync(base);
-        if (!stat.isSymbolicLink()) {
-          knownHard[base] = true;
-          if (cache) cache[base] = base;
-          continue;
-        }
-
-        // read the link if it wasn't read before
-        var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
-        if (!seenLinks[id]) {
-          fs.statSync(base);
-          seenLinks[id] = fs.readlinkSync(base);
-          resolvedLink = pathModule.resolve(previous, seenLinks[id]);
-          // track this, if given a cache.
-          if (cache) cache[base] = resolvedLink;
-        }
+      // read the link if it wasn't read before
+      var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
+      if (!seenLinks[id]) {
+        fs.statSync(base);
+        seenLinks[id] = fs.readlinkSync(base);
+        resolvedLink = pathModule.resolve(previous, seenLinks[id]);
+        // track this, if given a cache.
+        if (cache) cache[base] = resolvedLink;
       }
-
-      // resolve the link, then start over
-      p = pathModule.resolve(resolvedLink, p.slice(pos));
-      pos = 0;
-      previous = base = current = '';
     }
 
-    if (cache) cache[original] = p;
+    // resolve the link, then start over
+    p = pathModule.resolve(resolvedLink, p.slice(pos));
+    pos = 0;
+    previous = base = current = '';
+  }
 
-    return p;
-  };
+  if (cache) cache[original] = p;
 
+  return p;
+};
 
-  // posix version
-  fs.realpath = function realpath(p, cache, cb) {
-    if (typeof cb !== 'function') {
-      cb = cache;
-      cache = null;
-    }
 
-    // make p is absolute
-    p = pathModule.resolve(p);
+fs.realpath = function realpath(p, cache, cb) {
+  if (typeof cb !== 'function') {
+    cb = cache;
+    cache = null;
+  }
 
-    if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
-      return cb(null, cache[p]);
-    }
+  // make p is absolute
+  p = pathModule.resolve(p);
 
-    var original = p,
-        seenLinks = {},
-        knownHard = {};
-
-    // current character position in p
-    var pos = 0;
-    // the partial path so far, including a trailing slash if any
-    var current = '';
-    // the partial path without a trailing slash
-    var base = '';
-    // the partial path scanned in the previous round, with slash
-    var previous = '';
-
-    // walk down the path, swapping out linked pathparts for their real
-    // values
-    LOOP();
-    function LOOP() {
-      // stop if scanned past end of path
-      if (pos >= p.length) {
-        if (cache) cache[original] = p;
-        return cb(null, p);
-      }
+  if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
+    return cb(null, cache[p]);
+  }
 
-      // find the next part
-      nextPartRe.lastIndex = pos;
-      var result = nextPartRe.exec(p);
-      previous = current;
-      current += result[0];
-      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)) {
-        return process.nextTick(LOOP);
-      }
+  var original = p,
+      seenLinks = {},
+      knownHard = {};
 
-      if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
-        // known symbolic link.  no need to stat again.
-        return gotResolvedLink(cache[base]);
-      }
+  // current character position in p
+  var pos = 0;
+  // the partial path so far, including a trailing slash if any
+  var current = '';
+  // the partial path without a trailing slash
+  var base = '';
+  // the partial path scanned in the previous round, with slash
+  var previous = '';
+
+  // walk down the path, swapping out linked pathparts for their real
+  // values
+  LOOP();
+  function LOOP() {
+    // stop if scanned past end of path
+    if (pos >= p.length) {
+      if (cache) cache[original] = p;
+      return cb(null, p);
+    }
+
+    // find the next part
+    nextPartRe.lastIndex = pos;
+    var result = nextPartRe.exec(p);
+    previous = current;
+    current += result[0];
+    base = previous + result[1];
+    pos = nextPartRe.lastIndex;
 
-      return fs.lstat(base, gotStat);
+    // continue if known to be hard or if root or in cache already.
+    if (!base || knownHard[base] || (cache && cache[base] === base)) {
+      return process.nextTick(LOOP);
     }
 
-    function gotStat(err, stat) {
-      if (err) return cb(err);
+    if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
+      // known symbolic link.  no need to stat again.
+      return gotResolvedLink(cache[base]);
+    }
 
-      // if not a symlink, skip to the next path part
-      if (!stat.isSymbolicLink()) {
-        knownHard[base] = true;
-        if (cache) cache[base] = base;
-        return process.nextTick(LOOP);
-      }
+    return fs.lstat(base, gotStat);
+  }
 
-      // 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);
-      }
-      fs.stat(base, function(err) {
-        if (err) return cb(err);
+  function gotStat(err, stat) {
+    if (err) return cb(err);
 
-        fs.readlink(base, function(err, target) {
-          gotTarget(err, seenLinks[id] = target);
-        });
-      });
+    // if not a symlink, skip to the next path part
+    if (!stat.isSymbolicLink()) {
+      knownHard[base] = true;
+      if (cache) cache[base] = base;
+      return process.nextTick(LOOP);
     }
 
-    function gotTarget(err, target, base) {
+    // 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);
+    }
+    fs.stat(base, function(err) {
       if (err) return cb(err);
 
-      var resolvedLink = pathModule.resolve(previous, target);
-      if (cache) cache[base] = resolvedLink;
-      gotResolvedLink(resolvedLink);
-    }
+      fs.readlink(base, function(err, target) {
+        gotTarget(err, seenLinks[id] = target);
+      });
+    });
+  }
 
-    function gotResolvedLink(resolvedLink) {
+  function gotTarget(err, target, base) {
+    if (err) return cb(err);
 
-      // resolve the link, then start over
-      p = pathModule.resolve(resolvedLink, p.slice(pos));
-      pos = 0;
-      previous = base = current = '';
+    var resolvedLink = pathModule.resolve(previous, target);
+    if (cache) cache[base] = resolvedLink;
+    gotResolvedLink(resolvedLink);
+  }
 
-      return process.nextTick(LOOP);
-    }
-  };
+  function gotResolvedLink(resolvedLink) {
+
+    // resolve the link, then start over
+    p = pathModule.resolve(resolvedLink, p.slice(pos));
+    pos = 0;
+    previous = base = current = '';
+
+    return process.nextTick(LOOP);
+  }
+};
 
-}
 
 
 var pool;