Multiple appends without pre-allocation; use make() with capacity when size is known
out = append(out, gitignore.ParsePattern(line, domain))
1// SPDX-License-Identifier: MIT23package processor45import (6 "bufio"7 "io"8 "path"9 "strings"1011 "github.com/go-git/go-git/v5"12 "github.com/go-git/go-git/v5/plumbing"13 "github.com/go-git/go-git/v5/plumbing/filemode"14 "github.com/go-git/go-git/v5/plumbing/format/gitignore"15 "github.com/go-git/go-git/v5/plumbing/object"16)1718// historyIgnore wraps a gitignore.Matcher built from .ignore / .sccignore19// files found in the HEAD tree. .gitignore is already applied by git itself,20// so files it excludes never appear in the tree — only the scc/ripgrep21// conventions need extra handling.22type historyIgnore struct {23 matcher gitignore.Matcher24}2526func (h *historyIgnore) Match(p string, isDir bool) bool {27 if h == nil || h.matcher == nil {28 return false29 }30 parts := strings.Split(p, "/")31 return h.matcher.Match(parts, isDir)32}3334// buildHistoryIgnore scans the HEAD tree for .ignore and .sccignore blobs,35// parses them, and produces a matcher. Respects the existing --no-ignore36// (Ignore) and --no-scc-ignore (SccIgnore) flag globals.37func buildHistoryIgnore(repo *git.Repository, head plumbing.Hash) (*historyIgnore, error) {38 commit, err := repo.CommitObject(head)39 if err != nil {40 return nil, err41 }42 tree, err := commit.Tree()43 if err != nil {44 return nil, err45 }4647 var patterns []gitignore.Pattern48 err = tree.Files().ForEach(func(f *object.File) error {49 if f.Mode == filemode.Dir || f.Mode == filemode.Submodule || f.Mode == filemode.Symlink {50 return nil51 }5253 base := path.Base(f.Name)54 switch {55 case base == ".ignore" && !Ignore:56 case base == ".sccignore" && !SccIgnore:57 default:58 return nil59 }6061 reader, err := f.Reader()62 if err != nil {63 return nil64 }65 defer reader.Close()6667 domain := splitDomain(path.Dir(f.Name))68 patterns = append(patterns, parseIgnoreFile(reader, domain)...)69 return nil70 })71 if err != nil {72 return nil, err73 }7475 if len(patterns) == 0 {76 return &historyIgnore{}, nil77 }78 return &historyIgnore{matcher: gitignore.NewMatcher(patterns)}, nil79}8081func splitDomain(dir string) []string {82 if dir == "" || dir == "." {83 return nil84 }85 return strings.Split(dir, "/")86}8788func parseIgnoreFile(r io.Reader, domain []string) []gitignore.Pattern {89 var out []gitignore.Pattern90 scan := bufio.NewScanner(r)91 for scan.Scan() {92 line := strings.TrimRight(scan.Text(), "\r")93 trimmed := strings.TrimSpace(line)94 if trimmed == "" || strings.HasPrefix(trimmed, "#") {95 continue96 }97 out = append(out, gitignore.ParsePattern(line, domain))98 }99 return out100}
Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.