diff --git a/internal/cli/commands/sync/config.go b/internal/cli/commands/sync/config.go index 0ed2d47..a799f87 100644 --- a/internal/cli/commands/sync/config.go +++ b/internal/cli/commands/sync/config.go @@ -6,6 +6,7 @@ type config struct { Source string Dest string Excludes []string + DryRun bool } func (c config) validate() error { @@ -25,11 +26,13 @@ func parseConfig(cmd *cli.Command) (config, error) { Source: "", Dest: "", Excludes: nil, + DryRun: false, } cfg.Source = cmd.StringArg("source") cfg.Dest = cmd.String("dest") cfg.Excludes = cmd.StringSlice("exclude") + cfg.DryRun = cmd.Bool("dry-run") return cfg, cfg.validate() } diff --git a/internal/cli/commands/sync/sync.go b/internal/cli/commands/sync/sync.go index 3c8dd45..187b69d 100644 --- a/internal/cli/commands/sync/sync.go +++ b/internal/cli/commands/sync/sync.go @@ -36,6 +36,10 @@ func Command() *cli.Command { Name: "exclude", Usage: "paths or glob patterns to exclude (supports *, **, ?)", }, + &cli.BoolFlag{ + Name: "dry-run", + Usage: "perform a dry run without actually syncing files", + }, }, ArgsUsage: "[source]", Before: Before, @@ -103,7 +107,9 @@ func Action(ctx context.Context, cmd *cli.Command) error { return } log.Debug(ctx, "Event received", logger.Fields{"event": event}) - if syncErr := syncer.Sync(ctx, event.AbsPath); syncErr != nil { + if cfg.DryRun { + dryRunLog(ctx, event) + } else if syncErr := syncer.Sync(ctx, event.AbsPath); syncErr != nil { log.Error(ctx, "Failed to sync", syncErr) } case <-ctx.Done(): @@ -119,3 +125,21 @@ func Action(ctx context.Context, cmd *cli.Command) error { log.Info(ctx, "Sync command completed") return nil } + +func dryRunLog(ctx context.Context, event watcher.Event) { + log := logger.GetLogger(ctx) + + var action string + switch event.Type { + case watcher.EventCreated: + action = "create" + case watcher.EventModified: + action = "modify" + case watcher.EventRemoved: + action = "remove" + default: + return + } + + log.Info(ctx, "Would "+action, logger.Fields{"path": event.RelPath}) +} diff --git a/internal/syncer/syncer.go b/internal/syncer/syncer.go index 2a49d7e..99d7fb8 100644 --- a/internal/syncer/syncer.go +++ b/internal/syncer/syncer.go @@ -12,6 +12,10 @@ import ( logger "github.com/go-core-fx/cli-logger" ) +const ( + fieldPath = "path" +) + type Syncer struct { rootPath string client client.Client @@ -43,8 +47,8 @@ func (s *Syncer) Sync(ctx context.Context, absPath string) error { if matched, rule := s.isExcluded(absPath); matched { s.logger.Debug(ctx, "Excluded path skipped", logger.Fields{ - "path": relPath, - "rule": rule, + fieldPath: relPath, + "rule": rule, }) return nil } @@ -60,7 +64,7 @@ func (s *Syncer) Sync(ctx context.Context, absPath string) error { } s.logger.Info(ctx, "Removed", logger.Fields{ - "path": relPath, + fieldPath: relPath, }) return nil @@ -78,9 +82,13 @@ func (s *Syncer) syncFile(ctx context.Context, absPath, relPath string) error { return fmt.Errorf("c.UploadFile: %w", err) } - s.logger.Info(ctx, "Uploaded", logger.Fields{ - "path": relPath, - }) + fields := logger.Fields{ + fieldPath: relPath, + } + if info, err := os.Stat(absPath); err == nil { + fields["size"] = info.Size() + } + s.logger.Info(ctx, "Uploaded", fields) return nil } @@ -90,7 +98,7 @@ func (s *Syncer) syncDir(ctx context.Context, absPath, relPath string) error { return fmt.Errorf("c.MakeDir: %w", err) } s.logger.Info(ctx, "Created", logger.Fields{ - "path": relPath, + fieldPath: relPath, }) files, err := os.ReadDir(absPath) @@ -109,8 +117,8 @@ func (s *Syncer) syncDir(ctx context.Context, absPath, relPath string) error { childRelPath := filepath.Join(relPath, file.Name()) if matched, rule := s.isExcluded(childAbsPath); matched { s.logger.Debug(ctx, "Excluded path skipped", logger.Fields{ - "path": childRelPath, - "rule": rule, + fieldPath: childRelPath, + "rule": rule, }) continue } diff --git a/main.go b/main.go index f1749e2..79744b8 100644 --- a/main.go +++ b/main.go @@ -82,6 +82,10 @@ func main() { Name: "exclude", Usage: "paths or glob patterns to exclude (supports *, **, ?)", }, + &cli.BoolFlag{ + Name: "dry-run", + Usage: "perform a dry run without actually syncing files", + }, }, Before: func(ctx context.Context, cmd *cli.Command) (context.Context, error) { if cmd.Bool("debug") {