aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBernhard Guillon <Bernhard.Guillon@begu.org>2026-07-06 22:03:47 +0200
committerBernhard Guillon <Bernhard.Guillon@begu.org>2026-07-06 22:03:47 +0200
commit990f6e2aacbbb6869259390d973fde30fac13501 (patch)
tree18d4a7f0add623c8141be64247eae46967e49fff
parent1043b58c164ac48757cdb373967ead2b34aa7388 (diff)
downloadsourcewatch-990f6e2aacbbb6869259390d973fde30fac13501.tar.gz
sourcewatch-990f6e2aacbbb6869259390d973fde30fac13501.zip
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
-rw-r--r--main.go7
-rw-r--r--sync.go38
2 files changed, 44 insertions, 1 deletions
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
}