1- /*
1+ /*
22 MIT License http://www.opensource.org/licenses/mit-license.php
33 Author Tobias Koppers @sokra
44*/
@@ -61,6 +61,7 @@ class DirectoryWatcher extends EventEmitter {
6161 this . watcherManager = watcherManager ;
6262 this . options = options ;
6363 this . path = directoryPath ;
64+ this . watchingSymlink = false ;
6465 // safeTime is the point in time after which reading is safe to be unchanged
6566 // timestamp is a value that should be compared with another timestamp (mtime)
6667 /** @type {Map<string, { safeTime: number, timestamp: number } } */
@@ -111,8 +112,8 @@ class DirectoryWatcher extends EventEmitter {
111112 this . watchInParentDirectory ( ) ;
112113 }
113114 this . watcher = watchEventSource . watch ( this . path ) ;
114- this . watcher . on ( "change" , this . onWatchEvent . bind ( this ) ) ;
115115 this . watcher . on ( "error" , this . onWatcherError . bind ( this ) ) ;
116+ this . watcher . on ( "change" , this . onWatchEvent . bind ( this ) ) ;
116117 }
117118 } catch ( err ) {
118119 this . onWatcherError ( err ) ;
@@ -550,11 +551,6 @@ class DirectoryWatcher extends EventEmitter {
550551 fs . readdir ( this . path , ( err , items ) => {
551552 if ( this . closed ) return ;
552553 if ( err ) {
553- if ( err . code === "ENOENT" || err . code === "EPERM" ) {
554- this . onDirectoryRemoved ( "scan readdir failed" ) ;
555- } else {
556- this . onScanError ( err ) ;
557- }
558554 this . initialScan = false ;
559555 this . initialScanFinished = Date . now ( ) ;
560556 if ( initial ) {
@@ -627,22 +623,7 @@ class DirectoryWatcher extends EventEmitter {
627623 }
628624 } ) ;
629625 for ( const itemPath of itemPaths ) {
630- const handleStats = ( err2 , stats ) => {
631- if ( this . closed ) return ;
632- if ( err2 ) {
633- if (
634- err2 . code === "ENOENT" ||
635- err2 . code === "EPERM" ||
636- err2 . code === "EACCES" ||
637- err2 . code === "EBUSY"
638- ) {
639- this . setMissing ( itemPath , initial , "scan (" + err2 . code + ")" ) ;
640- } else {
641- this . onScanError ( err2 ) ;
642- }
643- itemFinished ( ) ;
644- return ;
645- }
626+ const handleStats = ( stats , symlinkStats ) => {
646627 if ( stats . isFile ( ) || stats . isSymbolicLink ( ) ) {
647628 if ( stats . mtime ) {
648629 ensureFsAccuracy ( stats . mtime ) ;
@@ -654,7 +635,11 @@ class DirectoryWatcher extends EventEmitter {
654635 true ,
655636 "scan (file)"
656637 ) ;
657- } else if ( stats . isDirectory ( ) ) {
638+ }
639+ if (
640+ stats . isDirectory ( ) ||
641+ ( symlinkStats && symlinkStats . isDirectory ( ) )
642+ ) {
658643 if ( ! initial || ! this . directories . has ( itemPath ) )
659644 this . setDirectory (
660645 itemPath ,
@@ -665,11 +650,42 @@ class DirectoryWatcher extends EventEmitter {
665650 }
666651 itemFinished ( ) ;
667652 } ;
668- if ( this . watcherManager . options . followSymlinks ) {
669- fs . stat ( itemPath , handleStats ) ;
670- } else {
671- fs . lstat ( itemPath , handleStats ) ;
672- }
653+ fs . lstat ( itemPath , ( err2 , stats ) => {
654+ if ( this . closed ) return ;
655+ if ( err2 ) {
656+ if (
657+ err2 . code === "ENOENT" ||
658+ err2 . code === "EPERM" ||
659+ err2 . code === "EACCES" ||
660+ err2 . code === "EBUSY"
661+ ) {
662+ this . setMissing ( itemPath , initial , "scan (" + err2 . code + ")" ) ;
663+ } else {
664+ this . onScanError ( err2 ) ;
665+ }
666+ itemFinished ( ) ;
667+ return ;
668+ }
669+ if (
670+ stats . isSymbolicLink ( ) &&
671+ this . watcherManager . options . followSymlinks
672+ ) {
673+ fs . stat ( itemPath , ( err3 , symlinkStats ) => {
674+ if ( this . closed ) return ;
675+ // something is wrong with the symlink, but not with the file itself
676+ if ( err3 ) {
677+ handleStats ( stats ) ;
678+ this . watchingSymlink = false ;
679+ return ;
680+ }
681+ this . watchingSymlink = true ;
682+ handleStats ( stats , symlinkStats ) ;
683+ } ) ;
684+ } else {
685+ this . watchingSymlink = false ;
686+ handleStats ( stats ) ;
687+ }
688+ } ) ;
673689 }
674690 itemFinished ( ) ;
675691 } ) ;
0 commit comments