From 6a0b826d4fb1dd872d902e3f413050162f95ce1e Mon Sep 17 00:00:00 2001
From: Volker Schukai <volker.schukai@schukai.com>
Date: Mon, 11 Sep 2023 08:39:23 +0200
Subject: [PATCH] feat: implement #1

---
 lighthouse.go      | 67 +++++++++++++++++++++++++++++++++++++++
 lighthouse_test.go | 79 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 146 insertions(+)

diff --git a/lighthouse.go b/lighthouse.go
index bbbe346..40580fd 100644
--- a/lighthouse.go
+++ b/lighthouse.go
@@ -1,6 +1,7 @@
 package watch
 
 import (
+	"fmt"
 	"github.com/fsnotify/fsnotify"
 	"path/filepath"
 	"sync"
@@ -57,6 +58,11 @@ type Lighthouse interface {
 
 	SetOnError(callback EventErrorCallback)
 	SetDebounce(duration time.Duration)
+
+	WatchList() []string
+	Sync() error
+
+	IsInSync() bool
 }
 
 // NewLighthouse creates a new lighthouse instance.
@@ -102,6 +108,67 @@ func (l *lighthouse) checkAndInit() {
 
 }
 
+// WatchList returns a list of all watched paths.
+func (l *lighthouse) WatchList() []string {
+	l.mutex.Lock()
+	defer l.mutex.Unlock()
+	var list []string
+	for k := range l.watchers {
+		list = append(list, k)
+	}
+	return list
+
+}
+
+// IsInSync returns true if all paths are watched by fsnotify.
+func (l *lighthouse) IsInSync() bool {
+	l.mutex.Lock()
+	defer l.mutex.Unlock()
+
+	wl := l.fsnotify.WatchList()
+
+	if len(wl) != len(l.watchers) {
+		return false
+	}
+
+	for _, w := range wl {
+		if _, ok := l.watchers[w]; !ok {
+			return false
+		}
+	}
+
+	return true
+
+}
+
+// Sync Lighthouse and fsnotify. Remove all watchers from fsnotify and add them again.
+func (l *lighthouse) Sync() error {
+	l.mutex.Lock()
+	defer l.mutex.Unlock()
+
+	// remove all watchers from fsnotify
+	wl := l.fsnotify.WatchList()
+	for _, w := range wl {
+		_ = l.fsnotify.Remove(w)
+	}
+
+	// add all watchers to fsnotify
+	var errReturn error
+
+	for k := range l.watchers {
+		err := l.fsnotify.Add(k)
+		if err != nil {
+			if errReturn == nil {
+				errReturn = err
+			} else {
+				errReturn = fmt.Errorf("%w, %v", errReturn, err)
+			}
+		}
+	}
+
+	return errReturn
+}
+
 // IsRunning returns true if the watcher is active, false otherwise.
 func (l *lighthouse) IsRunning() bool {
 	l.mutex.Lock()
diff --git a/lighthouse_test.go b/lighthouse_test.go
index 218ea09..e36aa6c 100644
--- a/lighthouse_test.go
+++ b/lighthouse_test.go
@@ -84,3 +84,82 @@ func TestIsActiveWatched(t *testing.T) {
 	assert.True(t, l.IsActiveWatched(tempDir))
 	assert.False(t, l.IsActiveWatched("path/not/watched"))
 }
+
+func TestWatchList(t *testing.T) {
+	tempDir, err := os.MkdirTemp("", "watchtest")
+	assert.Nil(t, err)
+	defer func() {
+		_ = os.RemoveAll(tempDir) // Cleanup
+	}()
+
+	l := NewLighthouse()
+
+	w := &Watch{Path: tempDir}
+	err = l.Add(w)
+	assert.Nil(t, err)
+
+	assert.Equal(t, 1, len(l.WatchList()))
+	assert.Equal(t, tempDir, l.WatchList()[0])
+}
+
+// test isinsync
+func TestIsInSync(t *testing.T) {
+	tempDir, err := os.MkdirTemp("", "watchtest")
+	assert.Nil(t, err)
+
+	tempFile, err := os.CreateTemp(tempDir, "test")
+	assert.Nil(t, err)
+
+	defer func() {
+		_ = os.RemoveAll(tempDir)         // Cleanup
+		_ = os.RemoveAll(tempFile.Name()) // Cleanup
+	}()
+
+	l := NewLighthouse()
+
+	w := &Watch{Path: tempDir}
+	err = l.Add(w)
+	assert.Nil(t, err)
+
+	w2 := &Watch{Path: tempFile.Name()}
+	err = l.Add(w2)
+	assert.Nil(t, err)
+
+	err = l.Sync()
+	assert.Nil(t, err)
+
+	assert.True(t, l.IsInSync())
+
+	internal := l.(*lighthouse)
+	internal.fsnotify.Remove(tempFile.Name())
+
+	assert.False(t, l.IsInSync())
+
+}
+
+// test Sync
+func TestSync(t *testing.T) {
+	tempDir, err := os.MkdirTemp("", "watchtest")
+	assert.Nil(t, err)
+
+	tempFile, err := os.CreateTemp(tempDir, "test")
+	assert.Nil(t, err)
+
+	defer func() {
+		_ = os.RemoveAll(tempDir)         // Cleanup
+		_ = os.RemoveAll(tempFile.Name()) // Cleanup
+	}()
+
+	l := NewLighthouse()
+
+	w := &Watch{Path: tempDir}
+	err = l.Add(w)
+	assert.Nil(t, err)
+
+	w2 := &Watch{Path: tempFile.Name()}
+	err = l.Add(w2)
+	assert.Nil(t, err)
+
+	err = l.Sync()
+	assert.Nil(t, err)
+}
-- 
GitLab