watch: add watch function that traverses up directory structure recursively (#1013)

This commit is contained in:
Dan Miller 2019-01-16 14:57:50 -05:00 committed by Nicolas De loof
parent e8a34c8d1e
commit 0482f9276a
2 changed files with 46 additions and 4 deletions

View File

@ -5,6 +5,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"runtime"
"strings"
"testing"
"time"
@ -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

View File

@ -3,6 +3,7 @@
package watch
import (
"fmt"
"log"
"os"
"path/filepath"
@ -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 {
@ -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()
}