@@ -514,15 +514,27 @@ if (isWindows) {
514
514
// windows version
515
515
fs . realpathSync = function realpathSync ( p ) {
516
516
var p = path . resolve ( p ) ;
517
+ if ( cache && Object . prototype . hasOwnProperty . call ( cache , p ) ) {
518
+ return cache [ p ] ;
519
+ }
517
520
fs . statSync ( p ) ;
521
+ if ( cache ) cache [ p ] = p ;
518
522
return p ;
519
523
} ;
520
524
521
525
// windows version
522
- fs . realpath = function ( p , cb ) {
526
+ fs . realpath = function ( p , cache , cb ) {
527
+ if ( typeof cb !== 'function' ) {
528
+ cb = cache ;
529
+ cache = null ;
530
+ }
523
531
var p = path . resolve ( p ) ;
532
+ if ( cache && Object . prototype . hasOwnProperty . call ( cache , p ) ) {
533
+ return cb ( null , cache [ p ] ) ;
534
+ }
524
535
fs . stat ( p , function ( err ) {
525
536
if ( err ) cb ( err ) ;
537
+ if ( cache ) cache [ p ] = p ;
526
538
cb ( null , p ) ;
527
539
} ) ;
528
540
} ;
@@ -535,11 +547,16 @@ if (isWindows) {
535
547
var nextPartRe = / ( .* ?) (?: [ \/ ] + | $ ) / g;
536
548
537
549
// posix version
538
- fs . realpathSync = function realpathSync ( p ) {
550
+ fs . realpathSync = function realpathSync ( p , cache ) {
539
551
// make p is absolute
540
552
p = path . resolve ( p ) ;
541
553
542
- var seenLinks = { } ,
554
+ if ( cache && Object . prototype . hasOwnProperty . call ( cache , p ) ) {
555
+ return cache [ p ] ;
556
+ }
557
+
558
+ var original = p ,
559
+ seenLinks = { } ,
543
560
knownHard = { } ;
544
561
545
562
// current character position in p
@@ -564,38 +581,61 @@ if (isWindows) {
564
581
pos = nextPartRe . lastIndex ;
565
582
566
583
// continue if not a symlink, or if root
567
- if ( ! base || knownHard [ base ] ) {
568
- continue ;
569
- }
570
- var stat = fs . lstatSync ( base ) ;
571
- if ( ! stat . isSymbolicLink ( ) ) {
572
- knownHard [ base ] = true ;
584
+ if ( ! base || knownHard [ base ] || ( cache && cache [ base ] === base ) ) {
573
585
continue ;
574
586
}
575
587
576
- // read the link if it wasn't read before
577
- var id = stat . dev . toString ( 32 ) + ':' + stat . ino . toString ( 32 ) ;
578
- if ( ! seenLinks [ id ] ) {
579
- fs . statSync ( base ) ;
580
- seenLinks [ id ] = fs . readlinkSync ( base ) ;
588
+ var resolvedLink ;
589
+ if ( cache && Object . prototype . hasOwnProperty . call ( cache , base ) ) {
590
+ // some known symbolic link. no need to stat again.
591
+ resolvedLink = cache [ base ] ;
592
+ } else {
593
+ var stat = fs . lstatSync ( base ) ;
594
+ if ( ! stat . isSymbolicLink ( ) ) {
595
+ knownHard [ base ] = true ;
596
+ if ( cache ) cache [ base ] = base ;
597
+ continue ;
598
+ }
599
+
600
+ // read the link if it wasn't read before
601
+ var id = stat . dev . toString ( 32 ) + ':' + stat . ino . toString ( 32 ) ;
602
+ if ( ! seenLinks [ id ] ) {
603
+ fs . statSync ( base ) ;
604
+ seenLinks [ id ] = fs . readlinkSync ( base ) ;
605
+ resolvedLink = path . resolve ( previous , seenLinks [ id ] ) ;
606
+ // track this, if given a cache.
607
+ if ( cache ) cache [ base ] = resolvedLink ;
608
+ }
581
609
}
582
610
583
611
// resolve the link, then start over
584
- p = path . resolve ( previous , seenLinks [ id ] , p . slice ( pos ) ) ;
612
+ p = path . resolve ( resolvedLink , p . slice ( pos ) ) ;
585
613
pos = 0 ;
586
614
previous = base = current = '' ;
587
615
}
588
616
617
+ if ( cache ) cache [ original ] = p ;
618
+
589
619
return p ;
590
620
} ;
591
621
592
622
593
623
// posix version
594
- fs . realpath = function realpath ( p , cb ) {
624
+ fs . realpath = function realpath ( p , cache , cb ) {
625
+ if ( typeof cb !== 'function' ) {
626
+ cb = cache ;
627
+ cache = null ;
628
+ }
629
+
595
630
// make p is absolute
596
631
p = path . resolve ( p ) ;
597
632
598
- var seenLinks = { } ,
633
+ if ( cache && Object . prototype . hasOwnProperty . call ( cache , p ) ) {
634
+ return cb ( null , cache [ p ] ) ;
635
+ }
636
+
637
+ var original = p ,
638
+ seenLinks = { } ,
599
639
knownHard = { } ;
600
640
601
641
// current character position in p
@@ -613,6 +653,7 @@ if (isWindows) {
613
653
function LOOP ( ) {
614
654
// stop if scanned past end of path
615
655
if ( pos >= p . length ) {
656
+ if ( cache ) cache [ original ] = p ;
616
657
return cb ( null , p ) ;
617
658
}
618
659
@@ -624,11 +665,16 @@ if (isWindows) {
624
665
base = previous + result [ 1 ] ;
625
666
pos = nextPartRe . lastIndex ;
626
667
627
- // continue if known to be hard or if root
628
- if ( ! base || knownHard [ base ] ) {
668
+ // continue if known to be hard or if root or in cache already.
669
+ if ( ! base || knownHard [ base ] || ( cache && cache [ base ] === base ) ) {
629
670
return process . nextTick ( LOOP ) ;
630
671
}
631
672
673
+ if ( cache && Object . prototype . hasOwnProperty . call ( cache , base ) ) {
674
+ // known symbolic link. no need to stat again.
675
+ return gotResolvedLink ( cache [ base ] ) ;
676
+ }
677
+
632
678
return fs . lstat ( base , gotStat ) ;
633
679
}
634
680
@@ -638,14 +684,15 @@ if (isWindows) {
638
684
// if not a symlink, skip to the next path part
639
685
if ( ! stat . isSymbolicLink ( ) ) {
640
686
knownHard [ base ] = true ;
687
+ if ( cache ) cache [ base ] = base ;
641
688
return process . nextTick ( LOOP ) ;
642
689
}
643
690
644
691
// stat & read the link if not read before
645
692
// call gotTarget as soon as the link target is known
646
693
var id = stat . dev . toString ( 32 ) + ':' + stat . ino . toString ( 32 ) ;
647
694
if ( seenLinks [ id ] ) {
648
- return gotTarget ( null , seenLinks [ id ] ) ;
695
+ return gotTarget ( null , seenLinks [ id ] , base ) ;
649
696
}
650
697
fs . stat ( base , function ( err ) {
651
698
if ( err ) return cb ( err ) ;
@@ -656,11 +703,18 @@ if (isWindows) {
656
703
} ) ;
657
704
}
658
705
659
- function gotTarget ( err , target ) {
706
+ function gotTarget ( err , target , base ) {
660
707
if ( err ) return cb ( err ) ;
661
708
709
+ var resolvedLink = path . resolve ( previous , target ) ;
710
+ if ( cache ) cache [ base ] = resolvedLink ;
711
+ gotResolvedLink ( resolvedLink ) ;
712
+ }
713
+
714
+ function gotResolvedLink ( resolvedLink ) {
715
+
662
716
// resolve the link, then start over
663
- p = path . resolve ( previous , target , p . slice ( pos ) ) ;
717
+ p = path . resolve ( resolvedLink , p . slice ( pos ) ) ;
664
718
pos = 0 ;
665
719
previous = base = current = '' ;
666
720
0 commit comments