@ -514,15 +514,27 @@ if (isWindows) {
// windows version
// windows version
fs . realpathSync = function realpathSync ( p ) {
fs . realpathSync = function realpathSync ( p ) {
var p = path . resolve ( p ) ;
var p = path . resolve ( p ) ;
if ( cache && Object . prototype . hasOwnProperty . call ( cache , p ) ) {
return cache [ p ] ;
}
fs . statSync ( p ) ;
fs . statSync ( p ) ;
if ( cache ) cache [ p ] = p ;
return p ;
return p ;
} ;
} ;
// windows version
// windows version
fs . realpath = function ( p , cb ) {
fs . realpath = function ( p , cache , cb ) {
if ( typeof cb !== 'function' ) {
cb = cache ;
cache = null ;
}
var p = path . resolve ( p ) ;
var p = path . resolve ( p ) ;
if ( cache && Object . prototype . hasOwnProperty . call ( cache , p ) ) {
return cb ( null , cache [ p ] ) ;
}
fs . stat ( p , function ( err ) {
fs . stat ( p , function ( err ) {
if ( err ) cb ( err ) ;
if ( err ) cb ( err ) ;
if ( cache ) cache [ p ] = p ;
cb ( null , p ) ;
cb ( null , p ) ;
} ) ;
} ) ;
} ;
} ;
@ -535,11 +547,16 @@ if (isWindows) {
var nextPartRe = /(.*?)(?:[\/]+|$)/g ;
var nextPartRe = /(.*?)(?:[\/]+|$)/g ;
// posix version
// posix version
fs . realpathSync = function realpathSync ( p ) {
fs . realpathSync = function realpathSync ( p , cache ) {
// make p is absolute
// make p is absolute
p = path . resolve ( p ) ;
p = path . resolve ( p ) ;
var seenLinks = { } ,
if ( cache && Object . prototype . hasOwnProperty . call ( cache , p ) ) {
return cache [ p ] ;
}
var original = p ,
seenLinks = { } ,
knownHard = { } ;
knownHard = { } ;
// current character position in p
// current character position in p
@ -564,38 +581,61 @@ if (isWindows) {
pos = nextPartRe . lastIndex ;
pos = nextPartRe . lastIndex ;
// continue if not a symlink, or if root
// continue if not a symlink, or if root
if ( ! base || knownHard [ base ] ) {
if ( ! base || knownHard [ base ] || ( cache && cache [ base ] === base ) ) {
continue ;
}
var stat = fs . lstatSync ( base ) ;
if ( ! stat . isSymbolicLink ( ) ) {
knownHard [ base ] = true ;
continue ;
continue ;
}
}
// read the link if it wasn't read before
var resolvedLink ;
var id = stat . dev . toString ( 32 ) + ':' + stat . ino . toString ( 32 ) ;
if ( cache && Object . prototype . hasOwnProperty . call ( cache , base ) ) {
if ( ! seenLinks [ id ] ) {
// some known symbolic link. no need to stat again.
fs . statSync ( base ) ;
resolvedLink = cache [ base ] ;
seenLinks [ id ] = fs . readlinkSync ( 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 = path . resolve ( previous , seenLinks [ id ] ) ;
// track this, if given a cache.
if ( cache ) cache [ base ] = resolvedLink ;
}
}
}
// resolve the link, then start over
// resolve the link, then start over
p = path . resolve ( previous , seenLinks [ id ] , p . slice ( pos ) ) ;
p = path . resolve ( resolvedLink , p . slice ( pos ) ) ;
pos = 0 ;
pos = 0 ;
previous = base = current = '' ;
previous = base = current = '' ;
}
}
if ( cache ) cache [ original ] = p ;
return p ;
return p ;
} ;
} ;
// posix version
// posix version
fs . realpath = function realpath ( p , cb ) {
fs . realpath = function realpath ( p , cache , cb ) {
if ( typeof cb !== 'function' ) {
cb = cache ;
cache = null ;
}
// make p is absolute
// make p is absolute
p = path . resolve ( p ) ;
p = path . resolve ( p ) ;
var seenLinks = { } ,
if ( cache && Object . prototype . hasOwnProperty . call ( cache , p ) ) {
return cb ( null , cache [ p ] ) ;
}
var original = p ,
seenLinks = { } ,
knownHard = { } ;
knownHard = { } ;
// current character position in p
// current character position in p
@ -613,6 +653,7 @@ if (isWindows) {
function LOOP ( ) {
function LOOP ( ) {
// stop if scanned past end of path
// stop if scanned past end of path
if ( pos >= p . length ) {
if ( pos >= p . length ) {
if ( cache ) cache [ original ] = p ;
return cb ( null , p ) ;
return cb ( null , p ) ;
}
}
@ -624,11 +665,16 @@ if (isWindows) {
base = previous + result [ 1 ] ;
base = previous + result [ 1 ] ;
pos = nextPartRe . lastIndex ;
pos = nextPartRe . lastIndex ;
// continue if known to be hard or if root
// continue if known to be hard or if root or in cache already.
if ( ! base || knownHard [ base ] ) {
if ( ! base || knownHard [ base ] || ( cache && cache [ base ] === base ) ) {
return process . nextTick ( LOOP ) ;
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 ) ;
return fs . lstat ( base , gotStat ) ;
}
}
@ -638,6 +684,7 @@ if (isWindows) {
// if not a symlink, skip to the next path part
// if not a symlink, skip to the next path part
if ( ! stat . isSymbolicLink ( ) ) {
if ( ! stat . isSymbolicLink ( ) ) {
knownHard [ base ] = true ;
knownHard [ base ] = true ;
if ( cache ) cache [ base ] = base ;
return process . nextTick ( LOOP ) ;
return process . nextTick ( LOOP ) ;
}
}
@ -645,7 +692,7 @@ if (isWindows) {
// call gotTarget as soon as the link target is known
// call gotTarget as soon as the link target is known
var id = stat . dev . toString ( 32 ) + ':' + stat . ino . toString ( 32 ) ;
var id = stat . dev . toString ( 32 ) + ':' + stat . ino . toString ( 32 ) ;
if ( seenLinks [ id ] ) {
if ( seenLinks [ id ] ) {
return gotTarget ( null , seenLinks [ id ] ) ;
return gotTarget ( null , seenLinks [ id ] , base ) ;
}
}
fs . stat ( base , function ( err ) {
fs . stat ( base , function ( err ) {
if ( err ) return cb ( err ) ;
if ( err ) return cb ( err ) ;
@ -656,11 +703,18 @@ if (isWindows) {
} ) ;
} ) ;
}
}
function gotTarget ( err , target ) {
function gotTarget ( err , target , base ) {
if ( err ) return cb ( err ) ;
if ( err ) return cb ( err ) ;
var resolvedLink = path . resolve ( previous , target ) ;
if ( cache ) cache [ base ] = resolvedLink ;
gotResolvedLink ( resolvedLink ) ;
}
function gotResolvedLink ( resolvedLink ) {
// resolve the link, then start over
// resolve the link, then start over
p = path . resolve ( previous , target , p . slice ( pos ) ) ;
p = path . resolve ( resolvedLink , p . slice ( pos ) ) ;
pos = 0 ;
pos = 0 ;
previous = base = current = '' ;
previous = base = current = '' ;