Skip to content

Commit 0482f92

Browse files
Dan Millerndeloof
authored andcommitted
watch: add watch function that traverses up directory structure recursively (docker#1013)
1 parent e8a34c8 commit 0482f92

File tree

2 files changed

+46
-4
lines changed

2 files changed

+46
-4
lines changed

pkg/watch/notify_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"io/ioutil"
66
"os"
77
"path/filepath"
8+
"runtime"
89
"strings"
910
"testing"
1011
"time"
@@ -309,6 +310,29 @@ func TestWatchBothDirAndFile(t *testing.T) {
309310
f.assertEvents(fileB)
310311
}
311312

313+
func TestWatchNonexistentDirectory(t *testing.T) {
314+
f := newNotifyFixture(t)
315+
defer f.tearDown()
316+
317+
root := f.JoinPath("root")
318+
err := os.Mkdir(root, 0777)
319+
if err != nil {
320+
t.Fatal(err)
321+
}
322+
parent := f.JoinPath("root", "parent")
323+
file := f.JoinPath("root", "parent", "a")
324+
325+
f.watch(file)
326+
f.fsync()
327+
f.events = nil
328+
f.WriteFile(file, "hello")
329+
if runtime.GOOS == "darwin" {
330+
f.assertEvents(file)
331+
} else {
332+
f.assertEvents(parent, file)
333+
}
334+
}
335+
312336
type notifyFixture struct {
313337
*tempdir.TempDirFixture
314338
notify Notify

pkg/watch/watcher_naive.go

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
package watch
44

55
import (
6+
"fmt"
67
"log"
78
"os"
89
"path/filepath"
@@ -31,12 +32,11 @@ func (d *naiveNotify) Add(name string) error {
3132

3233
// if it's a file that doesn't exist, watch its parent
3334
if os.IsNotExist(err) {
34-
parent := filepath.Join(name, "..")
35-
err = d.watcher.Add(parent)
35+
err, fileWatched := d.watchUpRecursively(name)
3636
if err != nil {
37-
return errors.Wrapf(err, "notify.Add(%q)", name)
37+
return errors.Wrapf(err, "watchUpRecursively(%q)", name)
3838
}
39-
d.watchList[parent] = true
39+
d.watchList[fileWatched] = true
4040
} else if fi.IsDir() {
4141
err = d.watchRecursively(name)
4242
if err != nil {
@@ -71,6 +71,24 @@ func (d *naiveNotify) watchRecursively(dir string) error {
7171
})
7272
}
7373

74+
func (d *naiveNotify) watchUpRecursively(path string) (error, string) {
75+
if path == string(filepath.Separator) {
76+
return fmt.Errorf("cannot watch root directory"), ""
77+
}
78+
79+
_, err := os.Stat(path)
80+
if err != nil && !os.IsNotExist(err) {
81+
return errors.Wrapf(err, "os.Stat(%q)", path), ""
82+
}
83+
84+
if os.IsNotExist(err) {
85+
parent := filepath.Dir(path)
86+
return d.watchUpRecursively(parent)
87+
}
88+
89+
return d.watcher.Add(path), path
90+
}
91+
7492
func (d *naiveNotify) Close() error {
7593
return d.watcher.Close()
7694
}

0 commit comments

Comments
 (0)