|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var pathModule = require('path'); |
|
var isWindows = process.platform === 'win32'; |
|
var fs = require('fs'); |
|
|
|
|
|
|
|
var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG); |
|
|
|
function rethrow() { |
|
|
|
|
|
var callback; |
|
if (DEBUG) { |
|
var backtrace = new Error; |
|
callback = debugCallback; |
|
} else |
|
callback = missingCallback; |
|
|
|
return callback; |
|
|
|
function debugCallback(err) { |
|
if (err) { |
|
backtrace.message = err.message; |
|
err = backtrace; |
|
missingCallback(err); |
|
} |
|
} |
|
|
|
function missingCallback(err) { |
|
if (err) { |
|
if (process.throwDeprecation) |
|
throw err; |
|
else if (!process.noDeprecation) { |
|
var msg = 'fs: missing callback ' + (err.stack || err.message); |
|
if (process.traceDeprecation) |
|
console.trace(msg); |
|
else |
|
console.error(msg); |
|
} |
|
} |
|
} |
|
} |
|
|
|
function maybeCallback(cb) { |
|
return typeof cb === 'function' ? cb : rethrow(); |
|
} |
|
|
|
var normalize = pathModule.normalize; |
|
|
|
|
|
|
|
if (isWindows) { |
|
var nextPartRe = /(.*?)(?:[\/\\]+|$)/g; |
|
} else { |
|
var nextPartRe = /(.*?)(?:[\/]+|$)/g; |
|
} |
|
|
|
|
|
if (isWindows) { |
|
var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/; |
|
} else { |
|
var splitRootRe = /^[\/]*/; |
|
} |
|
|
|
exports.realpathSync = function realpathSync(p, cache) { |
|
|
|
p = pathModule.resolve(p); |
|
|
|
if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { |
|
return cache[p]; |
|
} |
|
|
|
var original = p, |
|
seenLinks = {}, |
|
knownHard = {}; |
|
|
|
|
|
var pos; |
|
|
|
var current; |
|
|
|
var base; |
|
|
|
var previous; |
|
|
|
start(); |
|
|
|
function start() { |
|
|
|
var m = splitRootRe.exec(p); |
|
pos = m[0].length; |
|
current = m[0]; |
|
base = m[0]; |
|
previous = ''; |
|
|
|
|
|
if (isWindows && !knownHard[base]) { |
|
fs.lstatSync(base); |
|
knownHard[base] = true; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
while (pos < p.length) { |
|
|
|
nextPartRe.lastIndex = pos; |
|
var result = nextPartRe.exec(p); |
|
previous = current; |
|
current += result[0]; |
|
base = previous + result[1]; |
|
pos = nextPartRe.lastIndex; |
|
|
|
|
|
if (knownHard[base] || (cache && cache[base] === base)) { |
|
continue; |
|
} |
|
|
|
var resolvedLink; |
|
if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { |
|
|
|
resolvedLink = cache[base]; |
|
} else { |
|
var stat = fs.lstatSync(base); |
|
if (!stat.isSymbolicLink()) { |
|
knownHard[base] = true; |
|
if (cache) cache[base] = base; |
|
continue; |
|
} |
|
|
|
|
|
|
|
var linkTarget = null; |
|
if (!isWindows) { |
|
var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); |
|
if (seenLinks.hasOwnProperty(id)) { |
|
linkTarget = seenLinks[id]; |
|
} |
|
} |
|
if (linkTarget === null) { |
|
fs.statSync(base); |
|
linkTarget = fs.readlinkSync(base); |
|
} |
|
resolvedLink = pathModule.resolve(previous, linkTarget); |
|
|
|
if (cache) cache[base] = resolvedLink; |
|
if (!isWindows) seenLinks[id] = linkTarget; |
|
} |
|
|
|
|
|
p = pathModule.resolve(resolvedLink, p.slice(pos)); |
|
start(); |
|
} |
|
|
|
if (cache) cache[original] = p; |
|
|
|
return p; |
|
}; |
|
|
|
|
|
exports.realpath = function realpath(p, cache, cb) { |
|
if (typeof cb !== 'function') { |
|
cb = maybeCallback(cache); |
|
cache = null; |
|
} |
|
|
|
|
|
p = pathModule.resolve(p); |
|
|
|
if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { |
|
return process.nextTick(cb.bind(null, null, cache[p])); |
|
} |
|
|
|
var original = p, |
|
seenLinks = {}, |
|
knownHard = {}; |
|
|
|
|
|
var pos; |
|
|
|
var current; |
|
|
|
var base; |
|
|
|
var previous; |
|
|
|
start(); |
|
|
|
function start() { |
|
|
|
var m = splitRootRe.exec(p); |
|
pos = m[0].length; |
|
current = m[0]; |
|
base = m[0]; |
|
previous = ''; |
|
|
|
|
|
if (isWindows && !knownHard[base]) { |
|
fs.lstat(base, function(err) { |
|
if (err) return cb(err); |
|
knownHard[base] = true; |
|
LOOP(); |
|
}); |
|
} else { |
|
process.nextTick(LOOP); |
|
} |
|
} |
|
|
|
|
|
|
|
function LOOP() { |
|
|
|
if (pos >= p.length) { |
|
if (cache) cache[original] = p; |
|
return cb(null, p); |
|
} |
|
|
|
|
|
nextPartRe.lastIndex = pos; |
|
var result = nextPartRe.exec(p); |
|
previous = current; |
|
current += result[0]; |
|
base = previous + result[1]; |
|
pos = nextPartRe.lastIndex; |
|
|
|
|
|
if (knownHard[base] || (cache && cache[base] === base)) { |
|
return process.nextTick(LOOP); |
|
} |
|
|
|
if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { |
|
|
|
return gotResolvedLink(cache[base]); |
|
} |
|
|
|
return fs.lstat(base, gotStat); |
|
} |
|
|
|
function gotStat(err, stat) { |
|
if (err) return cb(err); |
|
|
|
|
|
if (!stat.isSymbolicLink()) { |
|
knownHard[base] = true; |
|
if (cache) cache[base] = base; |
|
return process.nextTick(LOOP); |
|
} |
|
|
|
|
|
|
|
|
|
if (!isWindows) { |
|
var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); |
|
if (seenLinks.hasOwnProperty(id)) { |
|
return gotTarget(null, seenLinks[id], base); |
|
} |
|
} |
|
fs.stat(base, function(err) { |
|
if (err) return cb(err); |
|
|
|
fs.readlink(base, function(err, target) { |
|
if (!isWindows) seenLinks[id] = target; |
|
gotTarget(err, 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) { |
|
|
|
p = pathModule.resolve(resolvedLink, p.slice(pos)); |
|
start(); |
|
} |
|
}; |
|
|