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:
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()