esync

Directory watching and remote syncing
Log | Files | Refs | README | LICENSE

commit a7b4d498c9a35333022ff0565bf206530b76ffea
parent ba0ab002d58858ac177c73a1692dcf293cc9fc50
Author: Erik Loualiche <eloualic@umn.edu>
Date:   Sun,  8 Mar 2026 15:02:48 -0400

feat: add Include field to Settings config

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Diffstat:
Minternal/config/config.go | 4++++
Minternal/config/config_test.go | 51++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/internal/config/config.go b/internal/config/config.go @@ -54,6 +54,7 @@ type LogSettings struct { type Settings struct { WatcherDebounce int `mapstructure:"watcher_debounce"` InitialSync bool `mapstructure:"initial_sync"` + Include []string `mapstructure:"include"` Ignore []string `mapstructure:"ignore"` Rsync RsyncSettings `mapstructure:"rsync"` Log LogSettings `mapstructure:"log"` @@ -198,6 +199,9 @@ interval = 1 [settings] watcher_debounce = 500 initial_sync = false +# include: path prefixes to sync (relative to local). Empty means everything. +# Keep include simple and explicit; use ignore for fine-grained filtering. +include = [] ignore = [".git", "node_modules", ".DS_Store"] [settings.rsync] diff --git a/internal/config/config_test.go b/internal/config/config_test.go @@ -341,7 +341,56 @@ func TestAllIgnorePatternsEmpty(t *testing.T) { } // ----------------------------------------------------------------------- -// 8. TestDefaultTOML — returns a non-empty template +// 8. TestLoadConfigWithInclude — include field parsed correctly +// ----------------------------------------------------------------------- +func TestLoadConfigWithInclude(t *testing.T) { + toml := ` +[sync] +local = "/src" +remote = "/dst" + +[settings] +include = ["src", "docs/api"] +ignore = [".git"] +` + path := writeTempTOML(t, toml) + cfg, err := Load(path) + if err != nil { + t.Fatalf("Load returned error: %v", err) + } + + if len(cfg.Settings.Include) != 2 { + t.Fatalf("Settings.Include length = %d, want 2", len(cfg.Settings.Include)) + } + if cfg.Settings.Include[0] != "src" || cfg.Settings.Include[1] != "docs/api" { + t.Errorf("Settings.Include = %v, want [src docs/api]", cfg.Settings.Include) + } +} + +// ----------------------------------------------------------------------- +// 9. TestLoadConfigIncludeDefaultsToEmpty — omitted include is nil/empty +// ----------------------------------------------------------------------- +func TestLoadConfigIncludeDefaultsToEmpty(t *testing.T) { + toml := ` +[sync] +local = "/src" +remote = "/dst" +` + path := writeTempTOML(t, toml) + cfg, err := Load(path) + if err != nil { + t.Fatalf("Load returned error: %v", err) + } + + if cfg.Settings.Include == nil { + // nil is fine — treated as "include everything" + } else if len(cfg.Settings.Include) != 0 { + t.Errorf("Settings.Include = %v, want empty", cfg.Settings.Include) + } +} + +// ----------------------------------------------------------------------- +// 10. TestDefaultTOML — returns a non-empty template // ----------------------------------------------------------------------- func TestDefaultTOML(t *testing.T) { toml := DefaultTOML()