| // Copyright Joyent, Inc. and other Node contributors. | 
| // | 
| // Permission is hereby granted, free of charge, to any person obtaining a | 
| // copy of this software and associated documentation files (the | 
| // "Software"), to deal in the Software without restriction, including | 
| // without limitation the rights to use, copy, modify, merge, publish, | 
| // distribute, sublicense, and/or sell copies of the Software, and to permit | 
| // persons to whom the Software is furnished to do so, subject to the | 
| // following conditions: | 
| // | 
| // The above copyright notice and this permission notice shall be included | 
| // in all copies or substantial portions of the Software. | 
| // | 
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | 
| // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | 
| // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN | 
| // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | 
| // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | 
| // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | 
| // USE OR OTHER DEALINGS IN THE SOFTWARE. | 
|   | 
| var pathModule = require('path'); | 
| var isWindows = process.platform === 'win32'; | 
| var fs = require('fs'); | 
|   | 
| // JavaScript implementation of realpath, ported from node pre-v6 | 
|   | 
| var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG); | 
|   | 
| function rethrow() { | 
|   // Only enable in debug mode. A backtrace uses ~1000 bytes of heap space and | 
|   // is fairly slow to generate. | 
|   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;  // Forgot a callback but don't know where? Use NODE_DEBUG=fs | 
|       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; | 
|   | 
| // Regexp that finds the next partion of a (partial) path | 
| // result is [base_with_slash, base], e.g. ['somedir/', 'somedir'] | 
| if (isWindows) { | 
|   var nextPartRe = /(.*?)(?:[\/\\]+|$)/g; | 
| } else { | 
|   var nextPartRe = /(.*?)(?:[\/]+|$)/g; | 
| } | 
|   | 
| // Regex to find the device root, including trailing slash. E.g. 'c:\\'. | 
| if (isWindows) { | 
|   var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/; | 
| } else { | 
|   var splitRootRe = /^[\/]*/; | 
| } | 
|   | 
| exports.realpathSync = function realpathSync(p, cache) { | 
|   // make p is absolute | 
|   p = pathModule.resolve(p); | 
|   | 
|   if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { | 
|     return cache[p]; | 
|   } | 
|   | 
|   var original = p, | 
|       seenLinks = {}, | 
|       knownHard = {}; | 
|   | 
|   // current character position in p | 
|   var pos; | 
|   // the partial path so far, including a trailing slash if any | 
|   var current; | 
|   // the partial path without a trailing slash (except when pointing at a root) | 
|   var base; | 
|   // the partial path scanned in the previous round, with slash | 
|   var previous; | 
|   | 
|   start(); | 
|   | 
|   function start() { | 
|     // Skip over roots | 
|     var m = splitRootRe.exec(p); | 
|     pos = m[0].length; | 
|     current = m[0]; | 
|     base = m[0]; | 
|     previous = ''; | 
|   | 
|     // On windows, check that the root exists. On unix there is no need. | 
|     if (isWindows && !knownHard[base]) { | 
|       fs.lstatSync(base); | 
|       knownHard[base] = true; | 
|     } | 
|   } | 
|   | 
|   // 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 | 
|     if (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 | 
|       // dev/ino always return 0 on windows, so skip the check. | 
|       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); | 
|       // track this, if given a cache. | 
|       if (cache) cache[base] = resolvedLink; | 
|       if (!isWindows) seenLinks[id] = linkTarget; | 
|     } | 
|   | 
|     // resolve the link, then start over | 
|     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; | 
|   } | 
|   | 
|   // make p is absolute | 
|   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 = {}; | 
|   | 
|   // current character position in p | 
|   var pos; | 
|   // the partial path so far, including a trailing slash if any | 
|   var current; | 
|   // the partial path without a trailing slash (except when pointing at a root) | 
|   var base; | 
|   // the partial path scanned in the previous round, with slash | 
|   var previous; | 
|   | 
|   start(); | 
|   | 
|   function start() { | 
|     // Skip over roots | 
|     var m = splitRootRe.exec(p); | 
|     pos = m[0].length; | 
|     current = m[0]; | 
|     base = m[0]; | 
|     previous = ''; | 
|   | 
|     // On windows, check that the root exists. On unix there is no need. | 
|     if (isWindows && !knownHard[base]) { | 
|       fs.lstat(base, function(err) { | 
|         if (err) return cb(err); | 
|         knownHard[base] = true; | 
|         LOOP(); | 
|       }); | 
|     } else { | 
|       process.nextTick(LOOP); | 
|     } | 
|   } | 
|   | 
|   // walk down the path, swapping out linked pathparts for their real | 
|   // values | 
|   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 not a symlink | 
|     if (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 | 
|     // 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.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) { | 
|     // resolve the link, then start over | 
|     p = pathModule.resolve(resolvedLink, p.slice(pos)); | 
|     start(); | 
|   } | 
| }; |