diff --git a/internal/server/indexer/indexer_test.go b/internal/server/indexer/indexer_test.go index 2815bfa..b9c8c3e 100644 --- a/internal/server/indexer/indexer_test.go +++ b/internal/server/indexer/indexer_test.go @@ -515,25 +515,14 @@ func TestShouldIndexFile_WithGitIgnoreFilter(t *testing.T) { _, teardown := setupTestEnv(t) defer teardown() - wsDir := t.TempDir() - ws, err := workspace.Create(wsDir) + ws, err := workspace.Create(t.TempDir()) if err != nil { t.Fatalf("workspace.Create: %v", err) } - // Initialize a real git repo for gitignore to work - origDir, _ := os.Getwd() - os.Chdir(wsDir) - defer os.Chdir(origDir) - - // Use git init to create a proper repo - gitCmd := filepath.Join("/usr", "bin", "git") - if _, err := os.Stat(gitCmd); err != nil { - t.Skip("git not available, skipping gitignore test") - } - - // Create .gitignore that excludes .log files - if err := os.WriteFile(filepath.Join(wsDir, ".gitignore"), []byte("*.log\n"), 0644); err != nil { + // Create a .gitignore that ignores the build/ directory and *.log files. + // NewGitIgnore reads .gitignore directly — it needs no .git dir or git binary. + if err := os.WriteFile(filepath.Join(ws.Path, ".gitignore"), []byte("build/\n*.log\n"), 0644); err != nil { t.Fatalf("write .gitignore: %v", err) } @@ -546,12 +535,18 @@ func TestShouldIndexFile_WithGitIgnoreFilter(t *testing.T) { } ws.Save() - // The GitIgnoreFilter should exercise the code path even if the actual - // gitignore behavior is partial — we at least cover the code branch. - _ = ShouldIndexFile(ws, "debug.log") - _ = ShouldIndexFile(ws, "main.go") - // Just exercising the code path — no assertions on gitignore behavior - // since it depends on git repo structure + // main.go is not ignored → should be kept (indexed). + if !ShouldIndexFile(ws, "main.go") { + t.Errorf("ShouldIndexFile(main.go) = false, want true (not ignored, should be kept)") + } + // app.log matches *.log → should be excluded. + if ShouldIndexFile(ws, "app.log") { + t.Errorf("ShouldIndexFile(app.log) = true, want false (ignored by *.log)") + } + // build/out.go is under build/ → should be excluded. + if ShouldIndexFile(ws, "build/out.go") { + t.Errorf("ShouldIndexFile(build/out.go) = true, want false (ignored by build/)") + } } // --------------------------------------------------------------------------- diff --git a/internal/server/indexer/scanner.go b/internal/server/indexer/scanner.go index f4269e5..1920341 100644 --- a/internal/server/indexer/scanner.go +++ b/internal/server/indexer/scanner.go @@ -10,10 +10,19 @@ import ( gitutils "github.com/codetrek/haystack/core/utils/git" "github.com/codetrek/haystack/internal/core/workspace" "github.com/codetrek/haystack/internal/shared/running" + "github.com/codetrek/haystack/internal/shared/types" "github.com/codetrek/haystack/internal/utils" fsutils "github.com/codetrek/haystack/internal/utils/fs" ) +// buildExcludeFilter returns a keep-filter: Match==true => keep, Match==false => exclude. +func buildExcludeFilter(baseDir string, exclude types.Exclude) fsutils.ListFileFilter { + if exclude.UseGitIgnore { + return &GitIgnoreFilter{ignore: gitutils.NewGitIgnore(baseDir, true)} + } + return utils.NewSimpleFilterExclude(exclude.Customized) +} + type GitIgnoreFilter struct { ignore *gitutils.GitIgnore } @@ -102,16 +111,8 @@ func ShouldIndexFile(w *workspace.Workspace, relPath string) bool { baseDir := w.Path filters := w.GetFilters() - var exclude fsutils.ListFileFilter - if filters.Exclude.UseGitIgnore { - exclude = &GitIgnoreFilter{ - ignore: gitutils.NewGitIgnore(baseDir, true), - } - } else { - exclude = utils.NewSimpleFilter(filters.Exclude.Customized) - } - - if exclude.Match(relPath, false) { + exclude := buildExcludeFilter(baseDir, filters.Exclude) + if !exclude.Match(relPath, false) { return false } @@ -133,14 +134,7 @@ func (s *Scanner) processWorkspace(w *workspace.Workspace, forceRefresh bool) er baseDir := w.Path filters := w.GetFilters() - var exclude fsutils.ListFileFilter - if filters.Exclude.UseGitIgnore { - exclude = &GitIgnoreFilter{ - ignore: gitutils.NewGitIgnore(baseDir, true), - } - } else { - exclude = utils.NewSimpleFilterExclude(filters.Exclude.Customized) - } + exclude := buildExcludeFilter(baseDir, filters.Exclude) include := utils.NewSimpleFilter(filters.Include) startTime := time.Now()