Skip to content

Commit

Permalink
watch: add watch function that traverses up directory structure recur…
Browse files Browse the repository at this point in the history
…sively (docker#1013)
  • Loading branch information
Dan Miller authored and ndeloof committed Jan 30, 2023
1 parent 1375661 commit d9a5dbe
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 4 deletions.
24 changes: 24 additions & 0 deletions pkg/watch/notify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"runtime"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -309,6 +310,29 @@ func TestWatchBothDirAndFile(t *testing.T) {
f.assertEvents(fileB)
}

func TestWatchNonexistentDirectory(t *testing.T) {
f := newNotifyFixture(t)
defer f.tearDown()

root := f.JoinPath("root")
err := os.Mkdir(root, 0777)
if err != nil {
t.Fatal(err)
}
parent := f.JoinPath("root", "parent")
file := f.JoinPath("root", "parent", "a")

f.watch(file)
f.fsync()
f.events = nil
f.WriteFile(file, "hello")
if runtime.GOOS == "darwin" {
f.assertEvents(file)
} else {
f.assertEvents(parent, file)
}
}

type notifyFixture struct {
*tempdir.TempDirFixture
notify Notify
Expand Down
26 changes: 22 additions & 4 deletions pkg/watch/watcher_naive.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package watch

import (
"fmt"
"log"
"os"
"path/filepath"
Expand Down Expand Up @@ -31,12 +32,11 @@ func (d *naiveNotify) Add(name string) error {

// if it's a file that doesn't exist, watch its parent
if os.IsNotExist(err) {
parent := filepath.Join(name, "..")
err = d.watcher.Add(parent)
err, fileWatched := d.watchUpRecursively(name)
if err != nil {
return errors.Wrapf(err, "notify.Add(%q)", name)
return errors.Wrapf(err, "watchUpRecursively(%q)", name)
}
d.watchList[parent] = true
d.watchList[fileWatched] = true
} else if fi.IsDir() {
err = d.watchRecursively(name)
if err != nil {
Expand Down Expand Up @@ -71,6 +71,24 @@ func (d *naiveNotify) watchRecursively(dir string) error {
})
}

func (d *naiveNotify) watchUpRecursively(path string) (error, string) {
if path == string(filepath.Separator) {
return fmt.Errorf("cannot watch root directory"), ""
}

_, err := os.Stat(path)
if err != nil && !os.IsNotExist(err) {
return errors.Wrapf(err, "os.Stat(%q)", path), ""
}

if os.IsNotExist(err) {
parent := filepath.Dir(path)
return d.watchUpRecursively(parent)
}

return d.watcher.Add(path), path
}

func (d *naiveNotify) Close() error {
return d.watcher.Close()
}
Expand Down

0 comments on commit d9a5dbe

Please sign in to comment.