Skip to content

feat(dotfile): add support for ignoring sections in collected files#103

Merged
AnnatarHe merged 1 commit intomainfrom
feat/issue-102-ignore-sections
Sep 17, 2025
Merged

feat(dotfile): add support for ignoring sections in collected files#103
AnnatarHe merged 1 commit intomainfrom
feat/issue-102-ignore-sections

Conversation

@AnnatarHe
Copy link
Copy Markdown
Contributor

Summary

  • Add optional boolean parameter to CollectFromPaths to skip content between ignore markers
  • Implement filterIgnoredSections function to remove lines between SHELLTIME IGNORE BEGIN and SHELLTIME IGNORE END
  • Update all dotfile app implementations to use the new parameter with default value true

Changes

  • Modified BaseApp.CollectFromPaths to accept optional skipIgnoredSections parameter (defaults to true)
  • Added filterIgnoredSections method to filter out sensitive content
  • Updated all 13 dotfile app implementations to pass true for the new parameter
  • Added comprehensive tests for the ignore functionality

Test Plan

  • Added test case for ignored sections functionality
  • Updated existing tests to pass the new parameter
  • Verified filtering works correctly with both skipIgnored=true and skipIgnored=false

Fixes #102

🤖 Generated with Claude Code

Add optional parameter to CollectFromPaths to skip content between
SHELLTIME IGNORE BEGIN and SHELLTIME IGNORE END markers. This allows
users to exclude sensitive information from dotfile collection.

Fixes #102

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Sep 17, 2025

Claude finished @AnnatarHe's task —— View job


Code Review

I've completed a thorough review of this pull request. Here's my detailed feedback:

  • Code quality and best practices
  • Potential bugs or issues
  • Performance considerations
  • Security concerns
  • Test coverage

Positive Aspects

  1. Good API Design: The optional skipIgnoredSections parameter with a sensible default of true maintains backward compatibility while providing the new functionality.

  2. Comprehensive Test Coverage: The tests cover all major scenarios including:

    • Both skipIgnored=true and skipIgnored=false cases
    • Edge cases with ignore markers
    • Integration with existing functionality
  3. Consistent Implementation: All 13 dotfile apps have been updated uniformly to use the new parameter.

  4. Clear Documentation: The filterIgnoredSections function has good inline documentation explaining its purpose.


⚠️ Issues and Concerns

1. Security/Privacy Vulnerability in filterIgnoredSections Implementation

Location: model/dotfile_apps.go:214-218

The current implementation uses strings.Contains() which is too permissive and could lead to unintended filtering:

if strings.Contains(line, "SHELLTIME IGNORE BEGIN") {
    inIgnoreBlock = true
    continue
}

Problem: This will match anywhere in the line, potentially causing false positives like:

  • echo "This is not a SHELLTIME IGNORE BEGIN comment"
  • # Some text before SHELLTIME IGNORE BEGIN and after

Impact: Could inappropriately filter legitimate content or fail to filter when markers appear in unexpected contexts.

Recommendation: Use more precise pattern matching:

trimmed := strings.TrimSpace(line)
if strings.Contains(trimmed, "SHELLTIME IGNORE BEGIN") {
    // Optionally check if it's in a comment context
    inIgnoreBlock = true
    continue
}

2. Incomplete Error Handling

Location: model/dotfile_apps.go:113-118

The nil pointer handling for skipIgnoredSections is correct, but the parameter should be bool instead of *bool to simplify the API:

Current:

func (b *BaseApp) CollectFromPaths(_ context.Context, appName string, paths []string, skipIgnoredSections *bool) 

Recommendation:

func (b *BaseApp) CollectFromPaths(_ context.Context, appName string, paths []string, skipIgnoredSections bool)

This eliminates the need for pointer checking and makes the API cleaner.

3. Missing Edge Case Handling

The implementation doesn't handle several edge cases:

  1. Unmatched markers: What happens if there's a BEGIN without an END?
  2. Nested markers: How should nested ignore blocks be handled?
  3. Multiple BEGIN markers: Should subsequent BEGIN markers reset the state?

Recommendation: Add validation and define behavior for these cases.

4. Performance Consideration

Location: model/dotfile_apps.go:207-230

The filterIgnoredSections function processes content line-by-line using strings.Split() and strings.Join(), which creates intermediate slice allocations.

Impact: For large configuration files, this could be inefficient.

Recommendation: Consider using a more efficient approach with a strings.Builder for large files or add a size threshold before applying the optimization.


🔧 Minor Issues

  1. Test Naming: In model/dotfile_apps_test.go:188, consider renaming the test case to be more descriptive: "collect with ignored sections filtering""filter ignored sections when skipIgnored is true"

  2. Code Comments: The ignore markers (SHELLTIME IGNORE BEGIN/END) should be documented in a central location (README or constants) to ensure consistency across the codebase.


📋 Recommendations for Follow-up

  1. Security: Fix the strings.Contains() pattern matching issue
  2. API Design: Consider simplifying the parameter from *bool to bool
  3. Documentation: Add examples of proper ignore marker usage
  4. Edge Cases: Define and implement behavior for unmatched/nested markers
  5. Performance: Consider optimization for large files if needed

🎯 Overall Assessment

This is a solid implementation of a useful feature. The core functionality works correctly, and the test coverage is comprehensive. The main concerns are around the security/correctness of the pattern matching and some API design considerations. With the security fix for pattern matching, this would be ready for production use.

Recommendation: ✅ Approve with minor changes - primarily fixing the strings.Contains() pattern matching issue for security reasons.


Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary of Changes

Hello @AnnatarHe, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant enhancement to how dotfiles are collected, allowing users to explicitly mark and ignore sensitive sections within their configuration files. By adding a skipIgnoredSections parameter to the CollectFromPaths function and implementing a robust filtering mechanism, the system can now prevent confidential data from being inadvertently included. This improves security and flexibility for managing dotfiles, with all existing dotfile applications updated to leverage this new capability by default.

Highlights

  • New Ignore Sections Feature: An optional boolean parameter skipIgnoredSections has been added to the CollectFromPaths function, allowing content between specific ignore markers to be skipped during collection.
  • Content Filtering Logic: A new filterIgnoredSections function has been implemented to parse file content and remove lines found between SHELLTIME IGNORE BEGIN and SHELLTIME IGNORE END markers.
  • Default Behavior Update: All existing dotfile application implementations have been updated to utilize the new skipIgnoredSections parameter, with its default value set to true to enable content filtering by default.
  • Comprehensive Testing: New and updated tests have been added to ensure the ignore functionality works correctly, covering scenarios where sections are both skipped and included.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@codecov
Copy link
Copy Markdown

codecov Bot commented Sep 17, 2025

Codecov Report

❌ Patch coverage is 54.71698% with 24 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
model/dotfile_bash.go 0.00% 2 Missing ⚠️
model/dotfile_claude.go 0.00% 2 Missing ⚠️
model/dotfile_fish.go 0.00% 2 Missing ⚠️
model/dotfile_ghostty.go 0.00% 2 Missing ⚠️
model/dotfile_git.go 0.00% 2 Missing ⚠️
model/dotfile_kitty.go 0.00% 2 Missing ⚠️
model/dotfile_kubernetes.go 0.00% 2 Missing ⚠️
model/dotfile_npm.go 0.00% 2 Missing ⚠️
model/dotfile_nvim.go 0.00% 2 Missing ⚠️
model/dotfile_ssh.go 0.00% 2 Missing ⚠️
... and 2 more
Flag Coverage Δ
unittests 23.70% <54.71%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
model/dotfile_apps.go 59.11% <100.00%> (+5.81%) ⬆️
model/dotfile_bash.go 0.00% <0.00%> (ø)
model/dotfile_claude.go 0.00% <0.00%> (ø)
model/dotfile_fish.go 0.00% <0.00%> (ø)
model/dotfile_ghostty.go 0.00% <0.00%> (ø)
model/dotfile_git.go 0.00% <0.00%> (ø)
model/dotfile_kitty.go 0.00% <0.00%> (ø)
model/dotfile_kubernetes.go 0.00% <0.00%> (ø)
model/dotfile_npm.go 0.00% <0.00%> (ø)
model/dotfile_nvim.go 0.00% <0.00%> (ø)
... and 3 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a valuable feature for ignoring specific sections within dotfiles. The implementation is generally solid and includes good test coverage. My review provides suggestions to enhance code clarity, reduce duplication, and improve the robustness of the tests. The most significant recommendation is to simplify how CollectFromPaths is called across all application-specific implementations, which will remove considerable boilerplate code. Additionally, there are opportunities to refactor duplicated logic within CollectFromPaths and refine the filterIgnoredSections function for better maintainability.

Comment thread model/dotfile_bash.go
Comment on lines +28 to +29
skipIgnored := true
return b.CollectFromPaths(ctx, b.Name(), b.GetConfigPaths(), &skipIgnored)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This implementation can be simplified. The CollectFromPaths function is designed to handle a nil value for skipIgnoredSections by defaulting to true. Therefore, you can just pass nil directly.

This simplification applies to all other CollectDotfiles methods in the other dotfile_*.go files as well, which would remove a lot of boilerplate code.

Suggested change
skipIgnored := true
return b.CollectFromPaths(ctx, b.Name(), b.GetConfigPaths(), &skipIgnored)
return b.CollectFromPaths(ctx, b.Name(), b.GetConfigPaths(), nil)

Comment thread model/dotfile_apps.go
Comment on lines +207 to +230
func (b *BaseApp) filterIgnoredSections(content string) string {
lines := strings.Split(content, "\n")
var filteredLines []string
var inIgnoreBlock bool

for _, line := range lines {
// Check for ignore markers (can be in comments)
if strings.Contains(line, "SHELLTIME IGNORE BEGIN") {
inIgnoreBlock = true
continue
}
if strings.Contains(line, "SHELLTIME IGNORE END") {
inIgnoreBlock = false
continue
}

// Only include lines that are not in an ignore block
if !inIgnoreBlock {
filteredLines = append(filteredLines, line)
}
}

return strings.Join(filteredLines, "\n")
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The implementation of filterIgnoredSections can be improved for readability and efficiency:

  1. Use constants for markers: The strings "SHELLTIME IGNORE BEGIN" and "SHELLTIME IGNORE END" are used as magic strings. Defining them as constants at the package or function level would improve readability and make them easier to manage.
  2. Pre-allocate slice capacity: You can pre-allocate the capacity for filteredLines to avoid multiple re-allocations as the slice grows. This is a good practice for performance, especially with larger files.
func (b *BaseApp) filterIgnoredSections(content string) string {
	const ignoreBeginMarker = "SHELLTIME IGNORE BEGIN"
	const ignoreEndMarker = "SHELLTIME IGNORE END"

	lines := strings.Split(content, "\n")
	filteredLines := make([]string, 0, len(lines))
	var inIgnoreBlock bool

	for _, line := range lines {
		// Check for ignore markers (can be in comments)
		if strings.Contains(line, ignoreBeginMarker) {
			inIgnoreBlock = true
			continue
		}
		if strings.Contains(line, ignoreEndMarker) {
			inIgnoreBlock = false
			continue
		}

		// Only include lines that are not in an ignore block
		if !inIgnoreBlock {
			filteredLines = append(filteredLines, line)
		}
	}

	return strings.Join(filteredLines, "\n")
}


t.Run("collect from single file", func(t *testing.T) {
dotfiles, err := app.CollectFromPaths(ctx, "testapp", []string{configFile})
skipIgnored := true
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The variable skipIgnored is repeatedly declared with := true inside each t.Run block (e.g., here, and on lines 152, 174, 182). To reduce repetition, you can declare it once before all the sub-tests.

Comment on lines +208 to +213
assert.NotContains(t, dotfiles[0].Content, "secret_key")
assert.NotContains(t, dotfiles[0].Content, "password=hidden")
assert.NotContains(t, dotfiles[0].Content, "SHELLTIME IGNORE")
assert.Contains(t, dotfiles[0].Content, "line1")
assert.Contains(t, dotfiles[0].Content, "line2")
assert.Contains(t, dotfiles[0].Content, "visible_key=value")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The assertions here check for the presence or absence of certain substrings. This is good, but it can be made more robust by asserting the exact expected content. This ensures that no extra lines or characters are present and that the line order is correct.

For the skipIgnored = true case, you could assert:

expectedContent := "line1\nline2\nvisible_key=value"
assert.Equal(t, expectedContent, dotfiles[0].Content)

Similarly, for the skipIgnored = false case, you can assert that the content is identical to the original configContentWithIgnore.

@AnnatarHe AnnatarHe merged commit a8332ee into main Sep 17, 2025
9 checks passed
@AnnatarHe AnnatarHe deleted the feat/issue-102-ignore-sections branch September 17, 2025 07:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[dotfiles push] support magic ignore comment

1 participant