Skip to content

Commit a8332ee

Browse files
authored
Merge pull request #103 from shelltime/feat/issue-102-ignore-sections
feat(dotfile): add support for ignoring sections in collected files
2 parents d8e79e7 + 2d7b9af commit a8332ee

14 files changed

Lines changed: 115 additions & 18 deletions

model/dotfile_apps.go

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,12 @@ func (b *BaseApp) readFileContent(path string) (string, *time.Time, error) {
110110
return string(content), &modTime, nil
111111
}
112112

113-
func (b *BaseApp) CollectFromPaths(_ context.Context, appName string, paths []string) ([]DotfileItem, error) {
113+
func (b *BaseApp) CollectFromPaths(_ context.Context, appName string, paths []string, skipIgnoredSections *bool) ([]DotfileItem, error) {
114+
// Default to true if not specified
115+
shouldSkipIgnored := true
116+
if skipIgnoredSections != nil {
117+
shouldSkipIgnored = *skipIgnoredSections
118+
}
114119
hostname, _ := os.Hostname()
115120
var dotfiles []DotfileItem
116121

@@ -143,6 +148,11 @@ func (b *BaseApp) CollectFromPaths(_ context.Context, appName string, paths []st
143148
continue
144149
}
145150

151+
// Filter ignored sections if requested
152+
if shouldSkipIgnored {
153+
content = b.filterIgnoredSections(content)
154+
}
155+
146156
dotfiles = append(dotfiles, DotfileItem{
147157
App: appName,
148158
Path: file,
@@ -160,6 +170,11 @@ func (b *BaseApp) CollectFromPaths(_ context.Context, appName string, paths []st
160170
continue
161171
}
162172

173+
// Filter ignored sections if requested
174+
if shouldSkipIgnored {
175+
content = b.filterIgnoredSections(content)
176+
}
177+
163178
dotfiles = append(dotfiles, DotfileItem{
164179
App: appName,
165180
Path: expandedPath,
@@ -188,6 +203,32 @@ func (b *BaseApp) collectFromDirectory(dir string) ([]string, error) {
188203
return files, err
189204
}
190205

206+
// filterIgnoredSections removes content between SHELLTIME IGNORE BEGIN and SHELLTIME IGNORE END markers
207+
func (b *BaseApp) filterIgnoredSections(content string) string {
208+
lines := strings.Split(content, "\n")
209+
var filteredLines []string
210+
var inIgnoreBlock bool
211+
212+
for _, line := range lines {
213+
// Check for ignore markers (can be in comments)
214+
if strings.Contains(line, "SHELLTIME IGNORE BEGIN") {
215+
inIgnoreBlock = true
216+
continue
217+
}
218+
if strings.Contains(line, "SHELLTIME IGNORE END") {
219+
inIgnoreBlock = false
220+
continue
221+
}
222+
223+
// Only include lines that are not in an ignore block
224+
if !inIgnoreBlock {
225+
filteredLines = append(filteredLines, line)
226+
}
227+
}
228+
229+
return strings.Join(filteredLines, "\n")
230+
}
231+
191232
// IsEqual checks if the provided files match the local files by comparing SHA256 hashes
192233
func (b *BaseApp) IsEqual(_ context.Context, files map[string]string) (map[string]bool, error) {
193234
result := make(map[string]bool)

model/dotfile_apps_test.go

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ func TestBaseApp_CollectFromPaths(t *testing.T) {
134134
require.NoError(t, err)
135135

136136
t.Run("collect from single file", func(t *testing.T) {
137-
dotfiles, err := app.CollectFromPaths(ctx, "testapp", []string{configFile})
137+
skipIgnored := true
138+
dotfiles, err := app.CollectFromPaths(ctx, "testapp", []string{configFile}, &skipIgnored)
138139
require.NoError(t, err)
139140
assert.Len(t, dotfiles, 1)
140141

@@ -148,7 +149,8 @@ func TestBaseApp_CollectFromPaths(t *testing.T) {
148149
})
149150

150151
t.Run("collect from directory", func(t *testing.T) {
151-
dotfiles, err := app.CollectFromPaths(ctx, "testapp", []string{subDir})
152+
skipIgnored := true
153+
dotfiles, err := app.CollectFromPaths(ctx, "testapp", []string{subDir}, &skipIgnored)
152154
require.NoError(t, err)
153155

154156
// Should find 2 files (hidden files are ignored)
@@ -169,17 +171,58 @@ func TestBaseApp_CollectFromPaths(t *testing.T) {
169171
})
170172

171173
t.Run("collect from mixed paths", func(t *testing.T) {
172-
dotfiles, err := app.CollectFromPaths(ctx, "testapp", []string{configFile, subDir})
174+
skipIgnored := true
175+
dotfiles, err := app.CollectFromPaths(ctx, "testapp", []string{configFile, subDir}, &skipIgnored)
173176
require.NoError(t, err)
174177
assert.Len(t, dotfiles, 3) // 1 file + 2 files from directory
175178
})
176179

177180
t.Run("collect from non-existent path", func(t *testing.T) {
178181
nonExistentPath := filepath.Join(tmpDir, "does-not-exist")
179-
dotfiles, err := app.CollectFromPaths(ctx, "testapp", []string{nonExistentPath})
182+
skipIgnored := true
183+
dotfiles, err := app.CollectFromPaths(ctx, "testapp", []string{nonExistentPath}, &skipIgnored)
180184
require.NoError(t, err)
181185
assert.Empty(t, dotfiles) // Should skip non-existent paths
182186
})
187+
188+
t.Run("collect with ignored sections", func(t *testing.T) {
189+
// Create a file with ignored sections
190+
configWithIgnore := filepath.Join(tmpDir, "config_with_ignore.conf")
191+
configContentWithIgnore := `line1
192+
# SHELLTIME IGNORE BEGIN
193+
secret_key=123456
194+
password=hidden
195+
# SHELLTIME IGNORE END
196+
line2
197+
visible_key=value`
198+
err = os.WriteFile(configWithIgnore, []byte(configContentWithIgnore), 0644)
199+
require.NoError(t, err)
200+
201+
// Test with skipIgnored = true (default behavior)
202+
skipIgnored := true
203+
dotfiles, err := app.CollectFromPaths(ctx, "testapp", []string{configWithIgnore}, &skipIgnored)
204+
require.NoError(t, err)
205+
require.Len(t, dotfiles, 1)
206+
207+
// Should not contain ignored sections
208+
assert.NotContains(t, dotfiles[0].Content, "secret_key")
209+
assert.NotContains(t, dotfiles[0].Content, "password=hidden")
210+
assert.NotContains(t, dotfiles[0].Content, "SHELLTIME IGNORE")
211+
assert.Contains(t, dotfiles[0].Content, "line1")
212+
assert.Contains(t, dotfiles[0].Content, "line2")
213+
assert.Contains(t, dotfiles[0].Content, "visible_key=value")
214+
215+
// Test with skipIgnored = false
216+
skipIgnored = false
217+
dotfiles, err = app.CollectFromPaths(ctx, "testapp", []string{configWithIgnore}, &skipIgnored)
218+
require.NoError(t, err)
219+
require.Len(t, dotfiles, 1)
220+
221+
// Should contain all content including ignored sections
222+
assert.Contains(t, dotfiles[0].Content, "secret_key")
223+
assert.Contains(t, dotfiles[0].Content, "password=hidden")
224+
assert.Contains(t, dotfiles[0].Content, "SHELLTIME IGNORE")
225+
})
183226
}
184227

185228
func TestBaseApp_collectFromDirectory(t *testing.T) {
@@ -524,7 +567,8 @@ func TestBaseApp_Integration(t *testing.T) {
524567

525568
t.Run("full workflow", func(t *testing.T) {
526569
// 1. Collect dotfiles
527-
dotfiles, err := app.CollectFromPaths(ctx, "testapp", []string{configFile, subDir})
570+
skipIgnored := true
571+
dotfiles, err := app.CollectFromPaths(ctx, "testapp", []string{configFile, subDir}, &skipIgnored)
528572
require.NoError(t, err)
529573
assert.Len(t, dotfiles, 2)
530574

model/dotfile_bash.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@ func (b *BashApp) GetConfigPaths() []string {
2525
}
2626

2727
func (b *BashApp) CollectDotfiles(ctx context.Context) ([]DotfileItem, error) {
28-
return b.CollectFromPaths(ctx, b.Name(), b.GetConfigPaths())
28+
skipIgnored := true
29+
return b.CollectFromPaths(ctx, b.Name(), b.GetConfigPaths(), &skipIgnored)
2930
}

model/dotfile_claude.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,6 @@ func (c *ClaudeApp) GetConfigPaths() []string {
2323
}
2424

2525
func (c *ClaudeApp) CollectDotfiles(ctx context.Context) ([]DotfileItem, error) {
26-
return c.CollectFromPaths(ctx, c.Name(), c.GetConfigPaths())
26+
skipIgnored := true
27+
return c.CollectFromPaths(ctx, c.Name(), c.GetConfigPaths(), &skipIgnored)
2728
}

model/dotfile_fish.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ func (f *FishApp) GetConfigPaths() []string {
2424
}
2525

2626
func (f *FishApp) CollectDotfiles(ctx context.Context) ([]DotfileItem, error) {
27-
return f.CollectFromPaths(ctx, f.Name(), f.GetConfigPaths())
27+
skipIgnored := true
28+
return f.CollectFromPaths(ctx, f.Name(), f.GetConfigPaths(), &skipIgnored)
2829
}

model/dotfile_ghostty.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,6 @@ func (g *GhosttyApp) GetConfigPaths() []string {
2323
}
2424

2525
func (g *GhosttyApp) CollectDotfiles(ctx context.Context) ([]DotfileItem, error) {
26-
return g.CollectFromPaths(ctx, g.Name(), g.GetConfigPaths())
26+
skipIgnored := true
27+
return g.CollectFromPaths(ctx, g.Name(), g.GetConfigPaths(), &skipIgnored)
2728
}

model/dotfile_git.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@ func (g *GitApp) GetConfigPaths() []string {
2525
}
2626

2727
func (g *GitApp) CollectDotfiles(ctx context.Context) ([]DotfileItem, error) {
28-
return g.CollectFromPaths(ctx, g.Name(), g.GetConfigPaths())
28+
skipIgnored := true
29+
return g.CollectFromPaths(ctx, g.Name(), g.GetConfigPaths(), &skipIgnored)
2930
}

model/dotfile_kitty.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,6 @@ func (k *KittyApp) GetConfigPaths() []string {
2222
}
2323

2424
func (k *KittyApp) CollectDotfiles(ctx context.Context) ([]DotfileItem, error) {
25-
return k.CollectFromPaths(ctx, k.Name(), k.GetConfigPaths())
25+
skipIgnored := true
26+
return k.CollectFromPaths(ctx, k.Name(), k.GetConfigPaths(), &skipIgnored)
2627
}

model/dotfile_kubernetes.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,6 @@ func (k *KubernetesApp) GetConfigPaths() []string {
2222
}
2323

2424
func (k *KubernetesApp) CollectDotfiles(ctx context.Context) ([]DotfileItem, error) {
25-
return k.CollectFromPaths(ctx, k.Name(), k.GetConfigPaths())
25+
skipIgnored := true
26+
return k.CollectFromPaths(ctx, k.Name(), k.GetConfigPaths(), &skipIgnored)
2627
}

model/dotfile_npm.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,6 @@ func (n *NpmApp) GetConfigPaths() []string {
2222
}
2323

2424
func (n *NpmApp) CollectDotfiles(ctx context.Context) ([]DotfileItem, error) {
25-
return n.CollectFromPaths(ctx, n.Name(), n.GetConfigPaths())
25+
skipIgnored := true
26+
return n.CollectFromPaths(ctx, n.Name(), n.GetConfigPaths(), &skipIgnored)
2627
}

0 commit comments

Comments
 (0)