From 990f6e2aacbbb6869259390d973fde30fac13501 Mon Sep 17 00:00:00 2001 From: Bernhard Guillon Date: Mon, 6 Jul 2026 22:03:47 +0200 Subject: Add progress logging for initial sync - Log start of sync with source directory - Print progress every 1000 files during sync - Log completion with stats (files, dirs, skipped, errors) and elapsed time - Print 'watcher: ready' when monitoring begins - Exit cleanly on dry-run --- main.go | 7 +++++++ sync.go | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/main.go b/main.go index 24135f5..077aec2 100644 --- a/main.go +++ b/main.go @@ -32,6 +32,13 @@ func main() { log.Fatalf("initial sync failed: %v", err) } + if *dryRun { + log.Println("dry-run complete, exiting") + return + } + + log.Println("watcher: ready, monitoring for changes ...") + ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer cancel() diff --git a/sync.go b/sync.go index 42066a3..2cead22 100644 --- a/sync.go +++ b/sync.go @@ -1,7 +1,9 @@ package main import ( + "fmt" "io" + "log" "os" "path/filepath" "time" @@ -18,12 +20,25 @@ type Manifest struct { Files map[string]FileMeta } +type syncStats struct { + files int + dirs int + skipped int + errors int +} + func initialSync(hostDir, dataDir string, stack *GitignoreStack, dryRun bool) (*Manifest, error) { manifest := &Manifest{Files: make(map[string]FileMeta)} + stats := &syncStats{} + start := time.Now() + + log.Printf("initial sync: scanning %s ...", hostDir) err := filepath.Walk(hostDir, func(path string, info os.FileInfo, err error) error { if err != nil { - return err + stats.errors++ + logError("walk", path, err) + return nil } relPath, err := filepath.Rel(hostDir, path) @@ -47,18 +62,30 @@ func initialSync(hostDir, dataDir string, stack *GitignoreStack, dryRun bool) (* } if stack.IsIgnored(relPath) { + stats.skipped++ if info.IsDir() { return filepath.SkipDir } return nil } + if info.IsDir() { + stats.dirs++ + } else { + stats.files++ + } + + if stats.files%1000 == 0 && stats.files > 0 { + fmt.Fprintf(os.Stderr, "\r synced %d files, %d dirs ...", stats.files, stats.dirs) + } + destPath := filepath.Join(dataDir, relPath) linkTarget := "" if info.Mode()&os.ModeSymlink != 0 { linkTarget, err = os.Readlink(path) if err != nil { + stats.errors++ logError("readlink", relPath, err) return nil } @@ -78,29 +105,38 @@ func initialSync(hostDir, dataDir string, stack *GitignoreStack, dryRun bool) (* if info.IsDir() { if err := os.MkdirAll(destPath, info.Mode()); err != nil { + stats.errors++ logError("mkdir", relPath, err) } return nil } if err := os.MkdirAll(filepath.Dir(destPath), 0755); err != nil { + stats.errors++ logError("mkdir", filepath.Dir(relPath), err) return nil } if linkTarget != "" { if err := os.Symlink(linkTarget, destPath); err != nil { + stats.errors++ logError("symlink", relPath, err) } return nil } if err := copyFileWithRetry(path, destPath, info.Mode()); err != nil { + stats.errors++ logError("copy", relPath, err) } return nil }) + elapsed := time.Since(start) + fmt.Fprintf(os.Stderr, "\r") + log.Printf("initial sync: done in %s — %d files, %d dirs, %d skipped, %d errors", + elapsed.Round(time.Millisecond), stats.files, stats.dirs, stats.skipped, stats.errors) + return manifest, err } -- cgit v1.2.3