From 6332a4cf00425c63ae476d89f6705881eb06a3e1 Mon Sep 17 00:00:00 2001 From: isaacs Date: Fri, 8 Jun 2012 15:26:04 -0700 Subject: [PATCH] Expose posix realpath on windows as well --- lib/fs.js | 326 +++++++++++++++++++++++++++----------------------------------- 1 file changed, 144 insertions(+), 182 deletions(-) diff --git a/lib/fs.js b/lib/fs.js index cbc1087..56ca131 100644 --- 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; -- 2.7.4