@@ -8,9 +8,11 @@ package file
88import (
99 "context"
1010 "errors"
11+ "io/fs"
1112 "log/slog"
1213 "os"
1314 "path/filepath"
15+ "regexp"
1416 "strings"
1517 "sync"
1618 "sync/atomic"
@@ -110,20 +112,33 @@ func (fws *FileWatcherService) watchDirectories(ctx context.Context) {
110112
111113 slog .DebugContext (ctx , "Creating file watchers" , "directory" , dir )
112114
113- err := filepath .Walk (dir , func (path string , info os.FileInfo , fileWalkErr error ) error {
114- if fileWalkErr != nil {
115- return fileWalkErr
116- }
117- fws .addWatcher (ctx , path , info )
118-
119- return nil
120- })
115+ err := fws .walkDir (ctx , dir )
121116 if err != nil {
122117 slog .ErrorContext (ctx , "Failed to create file watchers" , "directory" , dir , "error" , err )
123118 }
124119 }
125120}
126121
122+ func (fws * FileWatcherService ) walkDir (ctx context.Context , dir string ) error {
123+ return filepath .WalkDir (dir , func (path string , d fs.DirEntry , fileWalkErr error ) error {
124+ if fileWalkErr != nil {
125+ return fileWalkErr
126+ }
127+
128+ info , infoErr := d .Info ()
129+ if infoErr != nil {
130+ slog .ErrorContext (ctx , "Error getting info for file" , "error" , infoErr )
131+ return infoErr
132+ }
133+
134+ if d .IsDir () {
135+ fws .addWatcher (ctx , path , info )
136+ }
137+
138+ return nil
139+ })
140+ }
141+
127142func (fws * FileWatcherService ) addWatcher (ctx context.Context , path string , info os.FileInfo ) {
128143 if info .IsDir () && ! fws .isWatching (path ) {
129144 if err := fws .watcher .Add (path ); err != nil {
@@ -164,7 +179,7 @@ func (fws *FileWatcherService) isWatching(name string) bool {
164179
165180func (fws * FileWatcherService ) handleEvent (ctx context.Context , event fsnotify.Event ) {
166181 if fws .enabled .Load () {
167- if isEventSkippable (event ) {
182+ if fws . isEventSkippable (event ) {
168183 slog .DebugContext (ctx , "Skipping FSNotify event" , "event" , event )
169184 return
170185 }
@@ -204,10 +219,29 @@ func (fws *FileWatcherService) checkForUpdates(ctx context.Context, ch chan<- Fi
204219 }
205220}
206221
207- func isEventSkippable (event fsnotify.Event ) bool {
222+ func ( fws * FileWatcherService ) isEventSkippable (event fsnotify.Event ) bool {
208223 return event == emptyEvent ||
209- event .Name == "" ||
210- strings .HasSuffix (event .Name , ".swp" ) ||
211- strings .HasSuffix (event .Name , ".swx" ) ||
212- strings .HasSuffix (event .Name , "~" )
224+ event .Name == "" || isExcludedFile (event .Name , fws .agentConfig .Watchers .FileWatcher .ExcludeFiles )
225+ }
226+
227+ func isExcludedFile (path string , excludeFiles []string ) bool {
228+ path = strings .ToLower (path )
229+ for _ , pattern := range excludeFiles {
230+ _ , compileErr := regexp .Compile (pattern )
231+ if compileErr != nil {
232+ slog .Error ("Invalid path for excluding file" , "file_path" , pattern )
233+ continue
234+ }
235+
236+ ok , err := regexp .MatchString (pattern , path )
237+ if err != nil {
238+ slog .Error ("Invalid path for excluding file" , "file_path" , pattern )
239+ continue
240+ } else if ok {
241+ slog .Debug ("Excluding file from watcher as specified in config" , "file_path" , path )
242+ return true
243+ }
244+ }
245+
246+ return false
213247}
0 commit comments