Skip to content

Commit

Permalink
Add workaround for equivalent paths for watch option (#1895)
Browse files Browse the repository at this point in the history
* Add workaround for equivalent paths for watch option

* Add comment

* Simplify path watching
  • Loading branch information
joelim-work authored Jan 29, 2025
1 parent 2745c1a commit 7595e05
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 27 deletions.
18 changes: 7 additions & 11 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ func (app *app) loop() {
}
}

app.addWatchPaths()
app.watchDir(d)

app.ui.draw(app.nav)
case r := <-app.nav.regChan:
Expand Down Expand Up @@ -633,21 +633,17 @@ func (app *app) runShell(s string, args []string, prefix string) {
}
}

func (app *app) addWatchPaths() {
if !gOpts.watch || len(app.nav.dirs) == 0 {
func (app *app) watchDir(dir *dir) {
if !gOpts.watch {
return
}

paths := make(map[string]bool)
for _, dir := range app.nav.dirs {
paths[dir.path] = true
}
app.watch.add(dir.path)

for _, file := range app.nav.currDir().allFiles {
// ensure dircounts are updated for child directories
for _, file := range dir.allFiles {
if file.IsDir() {
paths[file.path] = true
app.watch.add(file.path)
}
}

app.watch.add(paths)
}
5 changes: 3 additions & 2 deletions eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,9 @@ func (e *setExpr) eval(app *app, args []string) {
if err == nil {
if gOpts.watch {
app.watch.start()
app.addWatchPaths()
for _, dir := range app.nav.dirCache {
app.watchDir(dir)
}
} else {
app.watch.stop()
}
Expand Down Expand Up @@ -582,7 +584,6 @@ func preChdir(app *app) {

func onChdir(app *app) {
app.nav.addJumpList()
app.addWatchPaths()
if cmd, ok := gOpts.cmds["on-cd"]; ok {
cmd.eval(app, nil)
}
Expand Down
61 changes: 47 additions & 14 deletions watch.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,14 @@ func (watch *watch) stop() {
watch.events = nil
}

func (watch *watch) add(paths map[string]bool) {
func (watch *watch) add(path string) {
if watch.watcher == nil {
return
}

for path := range paths {
// ignore /dev since write updates to /dev/tty causes high cpu usage
if path != "/dev" {
watch.watcher.Add(path)
}
// ignore /dev since write updates to /dev/tty causes high cpu usage
if path != "/dev" {
watch.watcher.Add(path)
}
}

Expand All @@ -82,20 +80,26 @@ func (watch *watch) loop() {
select {
case ev := <-watch.events:
if ev.Has(fsnotify.Create) {
dir := filepath.Dir(ev.Name)
watch.addLoad(dir)
watch.addUpdate(dir)
for _, path := range watch.getSameDirs(filepath.Dir(ev.Name)) {
watch.addLoad(path)
watch.addUpdate(path)
}
}

if ev.Has(fsnotify.Remove) || ev.Has(fsnotify.Rename) {
watch.delChan <- ev.Name
dir := filepath.Dir(ev.Name)
watch.addLoad(dir)
watch.addUpdate(dir)
dir, file := filepath.Split(ev.Name)
for _, path := range watch.getSameDirs(dir) {
watch.delChan <- filepath.Join(path, file)
watch.addLoad(path)
watch.addUpdate(path)
}
}

if ev.Has(fsnotify.Write) || ev.Has(fsnotify.Chmod) {
watch.addUpdate(ev.Name)
dir, file := filepath.Split(ev.Name)
for _, path := range watch.getSameDirs(dir) {
watch.addUpdate(filepath.Join(path, file))
}
}
case <-watch.loadTimer.C:
for path := range watch.loads {
Expand Down Expand Up @@ -136,3 +140,32 @@ func (watch *watch) addUpdate(path string) {
}
watch.updates[path] = true
}

// Hacky workaround since fsnotify reports changes for only one path if a
// directory is located at more than one path (e.g. bind mounts).
func (watch *watch) getSameDirs(dir string) []string {
var paths []string

dirStat, err := os.Stat(dir)
if err != nil {
return nil
}

for _, path := range watch.watcher.WatchList() {
if path == dir {
paths = append(paths, path)
continue
}

stat, err := os.Stat(path)
if err != nil {
continue
}

if os.SameFile(stat, dirStat) {
paths = append(paths, path)
}
}

return paths
}

0 comments on commit 7595e05

Please sign in to comment.