From 1043b58c164ac48757cdb373967ead2b34aa7388 Mon Sep 17 00:00:00 2001 From: Bernhard Guillon Date: Mon, 6 Jul 2026 21:58:06 +0200 Subject: 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 --- watcher.go | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) (limited to 'watcher.go') 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 { -- cgit v1.2.3