diff options
| author | Bernhard Guillon <Bernhard.Guillon@begu.org> | 2026-07-06 21:58:06 +0200 |
|---|---|---|
| committer | Bernhard Guillon <Bernhard.Guillon@begu.org> | 2026-07-06 21:58:06 +0200 |
| commit | 1043b58c164ac48757cdb373967ead2b34aa7388 (patch) | |
| tree | bc8286a404c17a5eec6a0de9b9adb1aa6201a413 /watcher.go | |
| parent | 5a2d70be3ce8524c366f4dd303b950974f05aa7c (diff) | |
| download | sourcewatch-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.go | 40 |
1 files changed, 23 insertions, 17 deletions
@@ -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 { |
