aboutsummaryrefslogtreecommitdiffstats
path: root/watcher.go
diff options
context:
space:
mode:
authorBernhard Guillon <Bernhard.Guillon@begu.org>2026-07-06 21:58:06 +0200
committerBernhard Guillon <Bernhard.Guillon@begu.org>2026-07-06 21:58:06 +0200
commit1043b58c164ac48757cdb373967ead2b34aa7388 (patch)
treebc8286a404c17a5eec6a0de9b9adb1aa6201a413 /watcher.go
parent5a2d70be3ce8524c366f4dd303b950974f05aa7c (diff)
downloadsourcewatch-1043b58c164ac48757cdb373967ead2b34aa7388.tar.gz
sourcewatch-1043b58c164ac48757cdb373967ead2b34aa7388.zip
Add structured error handling with retry logic
- errors.go: retry wrapper for transient errors (ENOENT), structured error logging (disk full, permission denied, symlink loops) - sync.go: continue on individual file errors, log clearly, skip broken symlinks instead of failing entire sync - watcher.go: log all errors with context, handle readlink failures - Added 11 tests for error handling scenarios - 50 tests passing
Diffstat (limited to 'watcher.go')
-rw-r--r--watcher.go40
1 files changed, 23 insertions, 17 deletions
diff --git a/watcher.go b/watcher.go
index d2a98e9..7df290d 100644
--- a/watcher.go
+++ b/watcher.go
@@ -98,7 +98,7 @@ func syncCreate(srcPath, destPath, relPath string, manifest *Manifest, stack *Gi
if os.IsNotExist(err) {
return
}
- log.Printf("error stat %s: %v", relPath, err)
+ logError("stat", relPath, err)
return
}
@@ -107,21 +107,24 @@ func syncCreate(srcPath, destPath, relPath string, manifest *Manifest, stack *Gi
stack.Push(srcPath)
}
if err := watcher.Add(srcPath); err != nil {
- log.Printf("error adding watcher for %s: %v", relPath, err)
+ logError("watch", relPath, err)
}
if dryRun {
- log.Printf("[dry-run] would create dir: %s", relPath)
return
}
if err := os.MkdirAll(destPath, info.Mode()); err != nil {
- log.Printf("error creating dir %s: %v", relPath, err)
+ logError("mkdir", relPath, err)
}
return
}
linkTarget := ""
if info.Mode()&os.ModeSymlink != 0 {
- linkTarget, _ = os.Readlink(srcPath)
+ linkTarget, err = os.Readlink(srcPath)
+ if err != nil {
+ logError("readlink", relPath, err)
+ return
+ }
}
meta := FileMeta{
@@ -133,7 +136,6 @@ func syncCreate(srcPath, destPath, relPath string, manifest *Manifest, stack *Gi
manifest.Files[relPath] = meta
if dryRun {
- log.Printf("[dry-run] would sync: %s", relPath)
return
}
@@ -142,13 +144,13 @@ func syncCreate(srcPath, destPath, relPath string, manifest *Manifest, stack *Gi
if linkTarget != "" {
if err := os.Symlink(linkTarget, destPath); err != nil {
- log.Printf("error creating symlink %s: %v", relPath, err)
+ logError("symlink", relPath, err)
}
return
}
- if err := copyFile(srcPath, destPath, info.Mode()); err != nil {
- log.Printf("error copying %s: %v", relPath, err)
+ if err := copyFileWithRetry(srcPath, destPath, info.Mode()); err != nil {
+ logError("copy", relPath, err)
}
}
@@ -158,7 +160,7 @@ func syncWrite(srcPath, destPath, relPath string, manifest *Manifest, dryRun, ve
if os.IsNotExist(err) {
return
}
- log.Printf("error stat %s: %v", relPath, err)
+ logError("stat", relPath, err)
return
}
@@ -169,7 +171,11 @@ func syncWrite(srcPath, destPath, relPath string, manifest *Manifest, dryRun, ve
linkTarget := ""
if info.Mode()&os.ModeSymlink != 0 {
- linkTarget, _ = os.Readlink(srcPath)
+ linkTarget, err = os.Readlink(srcPath)
+ if err != nil {
+ logError("readlink", relPath, err)
+ return
+ }
}
manifest.Files[relPath] = FileMeta{
@@ -180,7 +186,6 @@ func syncWrite(srcPath, destPath, relPath string, manifest *Manifest, dryRun, ve
}
if dryRun {
- log.Printf("[dry-run] would update: %s", relPath)
return
}
@@ -188,13 +193,13 @@ func syncWrite(srcPath, destPath, relPath string, manifest *Manifest, dryRun, ve
if linkTarget != "" {
if err := os.Symlink(linkTarget, destPath); err != nil {
- log.Printf("error creating symlink %s: %v", relPath, err)
+ logError("symlink", relPath, err)
}
return
}
- if err := copyFile(srcPath, destPath, info.Mode()); err != nil {
- log.Printf("error copying %s: %v", relPath, err)
+ if err := copyFileWithRetry(srcPath, destPath, info.Mode()); err != nil {
+ logError("copy", relPath, err)
}
}
@@ -202,11 +207,12 @@ func syncRemove(destPath, relPath string, manifest *Manifest, dryRun, verbose bo
delete(manifest.Files, relPath)
if dryRun {
- log.Printf("[dry-run] would remove: %s", relPath)
return
}
- os.Remove(destPath)
+ if err := os.Remove(destPath); err != nil && !os.IsNotExist(err) {
+ logError("remove", relPath, err)
+ }
}
func addWatchersRecursively(watcher *fsnotify.Watcher, root string, stack *GitignoreStack) error {