Skip to content

Commit

Permalink
Merge pull request #698 from strukturag/filewatcher-rename
Browse files Browse the repository at this point in the history
Improve detecting renames in file watcher.
  • Loading branch information
fancycode authored Apr 4, 2024
2 parents 47fc669 + d0c711b commit e1f40a0
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 5 deletions.
8 changes: 3 additions & 5 deletions file_watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,9 @@ func NewFileWatcher(filename string, callback FileWatcherCallback) (*FileWatcher
return nil, err
}

if filename != realFilename {
if err := watcher.Add(path.Dir(filename)); err != nil {
watcher.Close() // nolint
return nil, err
}
if err := watcher.Add(path.Dir(filename)); err != nil {
watcher.Close() // nolint
return nil, err
}

w := &FileWatcher{
Expand Down
95 changes: 95 additions & 0 deletions file_watcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,51 @@ func TestFileWatcher_File(t *testing.T) {
}
}

func TestFileWatcher_Rename(t *testing.T) {
tmpdir := t.TempDir()
filename := path.Join(tmpdir, "test.txt")
if err := os.WriteFile(filename, []byte("Hello world!"), 0644); err != nil {
t.Fatal(err)
}

modified := make(chan struct{})
w, err := NewFileWatcher(filename, func(filename string) {
modified <- struct{}{}
})
if err != nil {
t.Fatal(err)
}
defer w.Close()

filename2 := path.Join(tmpdir, "test.txt.tmp")
if err := os.WriteFile(filename2, []byte("Updated"), 0644); err != nil {
t.Fatal(err)
}

ctxTimeout, cancel := context.WithTimeout(context.Background(), testWatcherNoEventTimeout)
defer cancel()

select {
case <-modified:
t.Error("should not have received another event")
case <-ctxTimeout.Done():
}

if err := os.Rename(filename2, filename); err != nil {
t.Fatal(err)
}
<-modified

ctxTimeout, cancel = context.WithTimeout(context.Background(), testWatcherNoEventTimeout)
defer cancel()

select {
case <-modified:
t.Error("should not have received another event")
case <-ctxTimeout.Done():
}
}

func TestFileWatcher_Symlink(t *testing.T) {
tmpdir := t.TempDir()
sourceFilename := path.Join(tmpdir, "test1.txt")
Expand Down Expand Up @@ -211,3 +256,53 @@ func TestFileWatcher_OtherSymlink(t *testing.T) {
case <-ctxTimeout.Done():
}
}

func TestFileWatcher_RenameSymlinkTarget(t *testing.T) {
tmpdir := t.TempDir()
sourceFilename1 := path.Join(tmpdir, "test1.txt")
if err := os.WriteFile(sourceFilename1, []byte("Hello world!"), 0644); err != nil {
t.Fatal(err)
}

filename := path.Join(tmpdir, "test.txt")
if err := os.Symlink(sourceFilename1, filename); err != nil {
t.Fatal(err)
}

modified := make(chan struct{})
w, err := NewFileWatcher(filename, func(filename string) {
modified <- struct{}{}
})
if err != nil {
t.Fatal(err)
}
defer w.Close()

sourceFilename2 := path.Join(tmpdir, "test1.txt.tmp")
if err := os.WriteFile(sourceFilename2, []byte("Updated"), 0644); err != nil {
t.Fatal(err)
}

ctxTimeout, cancel := context.WithTimeout(context.Background(), testWatcherNoEventTimeout)
defer cancel()

select {
case <-modified:
t.Error("should not have received another event")
case <-ctxTimeout.Done():
}

if err := os.Rename(sourceFilename2, sourceFilename1); err != nil {
t.Fatal(err)
}
<-modified

ctxTimeout, cancel = context.WithTimeout(context.Background(), testWatcherNoEventTimeout)
defer cancel()

select {
case <-modified:
t.Error("should not have received another event")
case <-ctxTimeout.Done():
}
}

0 comments on commit e1f40a0

Please sign in to comment.