Expose posix realpath on windows as well
This commit is contained in:
parent
60b45dcbb6
commit
6332a4cf00
346
lib/fs.js
346
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.
|
||||
// Regexp that finds the next partion of a (partial) path
|
||||
// result is [base_with_slash, base], e.g. ['somedir/', 'somedir']
|
||||
var nextPartRe = /(.*?)(?:[\/]+|$)/g;
|
||||
|
||||
// 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;
|
||||
};
|
||||
fs.realpathSync = function realpathSync(p, cache) {
|
||||
// make p is absolute
|
||||
p = pathModule.resolve(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);
|
||||
});
|
||||
};
|
||||
if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
|
||||
return cache[p];
|
||||
}
|
||||
|
||||
var original = p,
|
||||
seenLinks = {},
|
||||
knownHard = {};
|
||||
|
||||
} else /* posix */ {
|
||||
// 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 = '';
|
||||
|
||||
// Regexp that finds the next partion of a (partial) path
|
||||
// result is [base_with_slash, base], e.g. ['somedir/', 'somedir']
|
||||
var nextPartRe = /(.*?)(?:[\/]+|$)/g;
|
||||
// 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;
|
||||
|
||||
// posix version
|
||||
fs.realpathSync = function realpathSync(p, cache) {
|
||||
// make p is absolute
|
||||
p = pathModule.resolve(p);
|
||||
|
||||
if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
|
||||
return cache[p];
|
||||
// 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)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// resolve the link, then start over
|
||||
p = pathModule.resolve(resolvedLink, p.slice(pos));
|
||||
pos = 0;
|
||||
previous = base = current = '';
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
|
||||
return cb(null, cache[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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
|
||||
// known symbolic link. no need to stat again.
|
||||
return gotResolvedLink(cache[base]);
|
||||
}
|
||||
|
||||
return fs.lstat(base, gotStat);
|
||||
}
|
||||
|
||||
function gotStat(err, stat) {
|
||||
if (err) return cb(err);
|
||||
|
||||
// if not a symlink, skip to the next path part
|
||||
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;
|
||||
return process.nextTick(LOOP);
|
||||
continue;
|
||||
}
|
||||
|
||||
// stat & read the link if not read before
|
||||
// call gotTarget as soon as the link target is known
|
||||
// read the link if it wasn't read before
|
||||
var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
|
||||
if (seenLinks[id]) {
|
||||
return gotTarget(null, seenLinks[id], base);
|
||||
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;
|
||||
}
|
||||
fs.stat(base, function(err) {
|
||||
if (err) return cb(err);
|
||||
|
||||
fs.readlink(base, function(err, target) {
|
||||
gotTarget(err, seenLinks[id] = target);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
if (cache) cache[original] = p;
|
||||
|
||||
return p;
|
||||
};
|
||||
|
||||
|
||||
fs.realpath = function realpath(p, cache, cb) {
|
||||
if (typeof cb !== 'function') {
|
||||
cb = cache;
|
||||
cache = null;
|
||||
}
|
||||
|
||||
// make p is absolute
|
||||
p = pathModule.resolve(p);
|
||||
|
||||
if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
|
||||
return cb(null, cache[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);
|
||||
}
|
||||
|
||||
function gotResolvedLink(resolvedLink) {
|
||||
|
||||
// resolve the link, then start over
|
||||
p = pathModule.resolve(resolvedLink, p.slice(pos));
|
||||
pos = 0;
|
||||
previous = base = current = '';
|
||||
// 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);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
|
||||
// known symbolic link. no need to stat again.
|
||||
return gotResolvedLink(cache[base]);
|
||||
}
|
||||
|
||||
return fs.lstat(base, gotStat);
|
||||
}
|
||||
|
||||
function gotStat(err, stat) {
|
||||
if (err) return cb(err);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
fs.readlink(base, function(err, target) {
|
||||
gotTarget(err, seenLinks[id] = target);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function gotTarget(err, target, base) {
|
||||
if (err) return cb(err);
|
||||
|
||||
var resolvedLink = pathModule.resolve(previous, target);
|
||||
if (cache) cache[base] = resolvedLink;
|
||||
gotResolvedLink(resolvedLink);
|
||||
}
|
||||
|
||||
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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user