99 "os"
1010 "os/signal"
1111 "path/filepath"
12+ "slices"
1213 "syscall"
1314 "time"
1415 _ "time/tzdata"
@@ -282,7 +283,7 @@ func runServe(cfg config.Config) {
282283 )
283284 defer stopWatcher ()
284285 if len (unwatchedDirs ) > 0 {
285- go startUnwatchedPoll (engine )
286+ go startUnwatchedPoll (engine , unwatchedDirs )
286287 }
287288 }
288289
@@ -513,62 +514,7 @@ func startFileWatcher(
513514 return func () {}, []string {"all" }
514515 }
515516
516- type watchRoot struct {
517- dir string
518- root string // actual path passed to WatchRecursive
519- shallow bool // use shallow watch (root only)
520- }
521-
522- var roots []watchRoot
523- seenRoots := make (map [string ]struct {})
524- addRoot := func (r watchRoot ) {
525- if _ , ok := seenRoots [r .root ]; ok {
526- return
527- }
528- seenRoots [r .root ] = struct {}{}
529- roots = append (roots , r )
530- }
531- for _ , def := range parser .Registry {
532- if ! def .FileBased {
533- continue
534- }
535- for _ , d := range cfg .ResolveDirs (def .Type ) {
536- if def .ShallowWatchRootsFunc != nil {
537- for _ , watchDir := range def .ShallowWatchRootsFunc (d ) {
538- if _ , err := os .Stat (watchDir ); err == nil {
539- addRoot (watchRoot {d , watchDir , true })
540- }
541- }
542- }
543- if def .WatchRootsFunc != nil {
544- watchDirs := def .WatchRootsFunc (d )
545- if len (watchDirs ) == 0 {
546- unwatchedDirs = append (unwatchedDirs , d )
547- continue
548- }
549- for _ , watchDir := range watchDirs {
550- if _ , err := os .Stat (watchDir ); err == nil {
551- addRoot (watchRoot {d , watchDir , def .ShallowWatch })
552- continue
553- }
554- unwatchedDirs = append (unwatchedDirs , d )
555- }
556- continue
557- }
558- if len (def .WatchSubdirs ) == 0 {
559- if _ , err := os .Stat (d ); err == nil {
560- addRoot (watchRoot {d , d , def .ShallowWatch })
561- }
562- continue
563- }
564- for _ , sub := range def .WatchSubdirs {
565- watchDir := filepath .Join (d , sub )
566- if _ , err := os .Stat (watchDir ); err == nil {
567- addRoot (watchRoot {d , watchDir , def .ShallowWatch })
568- }
569- }
570- }
571- }
517+ roots , unwatchedDirs := collectWatchRoots (cfg )
572518
573519 var totalWatched int
574520 var shallowWatched int
@@ -579,7 +525,7 @@ func startFileWatcher(
579525 shallowWatched ++
580526 totalWatched ++
581527 } else {
582- unwatchedDirs = append (unwatchedDirs , r .dir )
528+ unwatchedDirs = append (unwatchedDirs , r .dirs ... )
583529 }
584530 continue
585531 }
@@ -588,13 +534,13 @@ func startFileWatcher(
588534 remaining -= result .Watched
589535 if result .Unwatched > 0 || result .BudgetExhausted ||
590536 result .ResourceExhausted || result .Err != nil {
591- unwatchedDirs = append (unwatchedDirs , r .dir )
537+ unwatchedDirs = append (unwatchedDirs , r .dirs ... )
592538 log .Printf (
593539 "Couldn't watch %d directories under %s, will poll every %s" ,
594- result .Unwatched , r .dir , unwatchedPollInterval ,
540+ result .Unwatched , r .root , unwatchedPollInterval ,
595541 )
596542 if result .Err != nil {
597- log .Printf ("watching %s: %v" , r .dir , result .Err )
543+ log .Printf ("watching %s: %v" , r .root , result .Err )
598544 }
599545 }
600546 }
@@ -620,6 +566,72 @@ func startFileWatcher(
620566 return watcher .Stop , unwatchedDirs
621567}
622568
569+ type watchRoot struct {
570+ dirs []string
571+ root string // actual path passed to WatchRecursive
572+ shallow bool // use shallow watch (root only)
573+ }
574+
575+ func collectWatchRoots (cfg config.Config ) (roots []watchRoot , unwatchedDirs []string ) {
576+ rootIndexes := make (map [string ]int )
577+ addRoot := func (dir , root string , shallow bool ) {
578+ if idx , ok := rootIndexes [root ]; ok {
579+ if ! slices .Contains (roots [idx ].dirs , dir ) {
580+ roots [idx ].dirs = append (roots [idx ].dirs , dir )
581+ }
582+ return
583+ }
584+ rootIndexes [root ] = len (roots )
585+ roots = append (roots , watchRoot {
586+ dirs : []string {dir },
587+ root : root ,
588+ shallow : shallow ,
589+ })
590+ }
591+ for _ , def := range parser .Registry {
592+ if ! def .FileBased {
593+ continue
594+ }
595+ for _ , d := range cfg .ResolveDirs (def .Type ) {
596+ if def .ShallowWatchRootsFunc != nil {
597+ for _ , watchDir := range def .ShallowWatchRootsFunc (d ) {
598+ if _ , err := os .Stat (watchDir ); err == nil {
599+ addRoot (d , watchDir , true )
600+ }
601+ }
602+ }
603+ if def .WatchRootsFunc != nil {
604+ watchDirs := def .WatchRootsFunc (d )
605+ if len (watchDirs ) == 0 {
606+ unwatchedDirs = append (unwatchedDirs , d )
607+ continue
608+ }
609+ for _ , watchDir := range watchDirs {
610+ if _ , err := os .Stat (watchDir ); err == nil {
611+ addRoot (d , watchDir , def .ShallowWatch )
612+ continue
613+ }
614+ unwatchedDirs = append (unwatchedDirs , d )
615+ }
616+ continue
617+ }
618+ if len (def .WatchSubdirs ) == 0 {
619+ if _ , err := os .Stat (d ); err == nil {
620+ addRoot (d , d , def .ShallowWatch )
621+ }
622+ continue
623+ }
624+ for _ , sub := range def .WatchSubdirs {
625+ watchDir := filepath .Join (d , sub )
626+ if _ , err := os .Stat (watchDir ); err == nil {
627+ addRoot (d , watchDir , def .ShallowWatch )
628+ }
629+ }
630+ }
631+ }
632+ return roots , unwatchedDirs
633+ }
634+
623635func startPeriodicSync (
624636 engine * sync.Engine , database * db.DB ,
625637) {
@@ -659,11 +671,21 @@ func recomputePendingSessions(
659671 }
660672}
661673
662- func startUnwatchedPoll (engine * sync.Engine ) {
674+ type unwatchedPollSyncer interface {
675+ SyncRootsSince (
676+ context.Context , []string , time.Time , sync.ProgressFunc ,
677+ ) sync.SyncStats
678+ }
679+
680+ func startUnwatchedPoll (engine unwatchedPollSyncer , roots []string ) {
663681 ticker := time .NewTicker (unwatchedPollInterval )
664682 defer ticker .Stop ()
665683 for range ticker .C {
666684 log .Println ("Polling unwatched directories..." )
667- engine . SyncAll ( context . Background (), nil )
685+ pollUnwatchedRootsOnce ( engine , roots )
668686 }
669687}
688+
689+ func pollUnwatchedRootsOnce (engine unwatchedPollSyncer , roots []string ) {
690+ engine .SyncRootsSince (context .Background (), roots , time.Time {}, nil )
691+ }
0 commit comments