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 --- sync.go | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'sync.go') diff --git a/sync.go b/sync.go index 6bdd651..42066a3 100644 --- a/sync.go +++ b/sync.go @@ -2,7 +2,6 @@ package main import ( "io" - "log" "os" "path/filepath" "time" @@ -60,7 +59,8 @@ func initialSync(hostDir, dataDir string, stack *GitignoreStack, dryRun bool) (* if info.Mode()&os.ModeSymlink != 0 { linkTarget, err = os.Readlink(path) if err != nil { - return err + logError("readlink", relPath, err) + return nil } } @@ -73,23 +73,32 @@ func initialSync(hostDir, dataDir string, stack *GitignoreStack, dryRun bool) (* manifest.Files[relPath] = meta if dryRun { - log.Printf("[dry-run] would sync: %s", relPath) return nil } if info.IsDir() { - return os.MkdirAll(destPath, info.Mode()) + if err := os.MkdirAll(destPath, info.Mode()); err != nil { + logError("mkdir", relPath, err) + } + return nil } if err := os.MkdirAll(filepath.Dir(destPath), 0755); err != nil { - return err + logError("mkdir", filepath.Dir(relPath), err) + return nil } if linkTarget != "" { - return os.Symlink(linkTarget, destPath) + if err := os.Symlink(linkTarget, destPath); err != nil { + logError("symlink", relPath, err) + } + return nil } - return copyFile(path, destPath, info.Mode()) + if err := copyFileWithRetry(path, destPath, info.Mode()); err != nil { + logError("copy", relPath, err) + } + return nil }) return manifest, err -- cgit v1.2.3