summaryrefslogtreecommitdiffstats
path: root/pkg/gui
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/gui')
-rw-r--r--pkg/gui/file_watching.go108
-rw-r--r--pkg/gui/files_panel.go2
-rw-r--r--pkg/gui/gui.go5
3 files changed, 88 insertions, 27 deletions
diff --git a/pkg/gui/file_watching.go b/pkg/gui/file_watching.go
index 90fb32639..9ad7f68c4 100644
--- a/pkg/gui/file_watching.go
+++ b/pkg/gui/file_watching.go
@@ -4,24 +4,103 @@ import (
"os"
"path/filepath"
+ "github.com/davecgh/go-spew/spew"
"github.com/fsnotify/fsnotify"
"github.com/jesseduffield/lazygit/pkg/commands"
+ "github.com/sirupsen/logrus"
)
+// macs for some bizarre reason cap the number of watchable files to 256.
+// there's no obvious platform agonstic way to check the situation of the user's
+// computer so we're just arbitrarily capping at 200. This isn't so bad because
+// file watching is only really an added bonus for faster refreshing.
+const MAX_WATCHED_FILES = 200
+
+type fileWatcher struct {
+ Watcher *fsnotify.Watcher
+ WatchedFilenames []string
+ Log *logrus.Entry
+}
+
+func NewFileWatcher(log *logrus.Entry) *fileWatcher {
+ watcher, err := fsnotify.NewWatcher()
+ if err != nil {
+ log.Error(err)
+ return nil
+ }
+
+ return &fileWatcher{
+ Watcher: watcher,
+ Log: log,
+ WatchedFilenames: make([]string, 0, MAX_WATCHED_FILES),
+ }
+}
+
+func (w *fileWatcher) watchingFilename(filename string) bool {
+ for _, watchedFilename := range w.WatchedFilenames {
+ if watchedFilename == filename {
+ return true
+ }
+ }
+ return false
+}
+
+func (w *fileWatcher) popOldestFilename() {
+ // shift the last off the array to make way for this one
+ oldestFilename := w.WatchedFilenames[0]
+ w.WatchedFilenames = w.WatchedFilenames[1:]
+ if err := w.Watcher.Remove(oldestFilename); err != nil {
+ // swallowing errors here because it doesn't really matter if we can't unwatch a file
+ w.Log.Warn(err)
+ }
+}
+
+func (w *fileWatcher) watchFilename(filename string) {
+ w.Log.Warn(filename)
+ if err := w.Watcher.Add(filename); err != nil {
+ // swallowing errors here because it doesn't really matter if we can't watch a file
+ w.Log.Warn(err)
+ }
+
+ // assume we're watching it now to be safe
+ w.WatchedFilenames = append(w.WatchedFilenames, filename)
+}
+
+func (w *fileWatcher) addFilesToFileWatcher(files []*commands.File) error {
+ // watch the files for changes
+ dirName, err := os.Getwd()
+ if err != nil {
+ return err
+ }
+
+ for _, file := range files {
+ filename := filepath.Join(dirName, file.Name)
+ if w.watchingFilename(filename) {
+ continue
+ }
+ if len(w.WatchedFilenames) > MAX_WATCHED_FILES {
+ w.popOldestFilename()
+ }
+
+ w.watchFilename(filename)
+ w.Log.Warn(spew.Sdump(w.WatchedFilenames))
+ }
+
+ return nil
+}
+
// NOTE: given that we often edit files ourselves, this may make us end up refreshing files too often
// TODO: consider watching the whole directory recursively (could be more expensive)
func (gui *Gui) watchFilesForChanges() {
- var err error
- gui.fileWatcher, err = fsnotify.NewWatcher()
- if err != nil {
- gui.Log.Error(err)
+ gui.fileWatcher = NewFileWatcher(gui.Log)
+ if gui.fileWatcher == nil {
return
}
go func() {
for {
select {
// watch for events
- case event := <-gui.fileWatcher.Events:
+ case event := <-gui.fileWatcher.Watcher.Events:
if event.Op == fsnotify.Chmod {
// for some reason we pick up chmod events when they don't actually happen
continue
@@ -37,7 +116,7 @@ func (gui *Gui) watchFilesForChanges() {
}
// watch for errors
- case err := <-gui.fileWatcher.Errors:
+ case err := <-gui.fileWatcher.Watcher.Errors:
if err != nil {
gui.Log.Warn(err)
}
@@ -45,20 +124,3 @@ func (gui *Gui) watchFilesForChanges() {
}
}()
}
-
-func (gui *Gui) addFilesToFileWatcher(files []*commands.File) error {
- // watch the files for changes
- dirName, err := os.Getwd()
- if err != nil {
- return err
- }
-
- for _, file := range files {
- if err := gui.fileWatcher.Add(filepath.Join(dirName, file.Name)); err != nil {
- // swallowing errors here because it doesn't really matter if we can't watch a file
- gui.Log.Warn(err)
- }
- }
-
- return nil
-}
diff --git a/pkg/gui/files_panel.go b/pkg/gui/files_panel.go
index aa2e8592e..82a81654c 100644
--- a/pkg/gui/files_panel.go
+++ b/pkg/gui/files_panel.go
@@ -356,7 +356,7 @@ func (gui *Gui) refreshStateFiles() error {
files := gui.GitCommand.GetStatusFiles()
gui.State.Files = gui.GitCommand.MergeStatusFiles(gui.State.Files, files)
- if err := gui.addFilesToFileWatcher(files); err != nil {
+ if err := gui.fileWatcher.addFilesToFileWatcher(files); err != nil {
return err
}
diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go
index fc24bbd6b..530c00383 100644
--- a/pkg/gui/gui.go
+++ b/pkg/gui/gui.go
@@ -15,7 +15,6 @@ import (
"strings"
"time"
- "github.com/fsnotify/fsnotify"
"github.com/go-errors/errors"
// "strings"
@@ -82,7 +81,7 @@ type Gui struct {
statusManager *statusManager
credentials credentials
waitForIntro sync.WaitGroup
- fileWatcher *fsnotify.Watcher
+ fileWatcher *fileWatcher
}
// for now the staging panel state, unlike the other panel states, is going to be
@@ -840,7 +839,7 @@ func (gui *Gui) RunWithSubprocesses() error {
}
}
- gui.fileWatcher.Close()
+ gui.fileWatcher.Watcher.Close()
break
} else if err == gui.Errors.ErrSwitchRepo {