filterGitIgnored removes gitignored files from the list using git check-ignore. Falls back gracefully (returns input unchanged) if git is unavailable or the project is not a repo.
(files []FileEntry, projectRoot string)
| 218 | // filterGitIgnored removes gitignored files from the list using git check-ignore. |
| 219 | // Falls back gracefully (returns input unchanged) if git is unavailable or the project is not a repo. |
| 220 | func filterGitIgnored(files []FileEntry, projectRoot string) []FileEntry { |
| 221 | if len(files) == 0 { |
| 222 | return files |
| 223 | } |
| 224 | |
| 225 | var paths []string |
| 226 | for _, f := range files { |
| 227 | paths = append(paths, f.Path) |
| 228 | } |
| 229 | |
| 230 | cmd := exec.Command("git", "check-ignore", "--stdin") |
| 231 | cmd.Dir = projectRoot |
| 232 | cmd.Stdin = strings.NewReader(strings.Join(paths, "\n")) |
| 233 | |
| 234 | var out bytes.Buffer |
| 235 | cmd.Stdout = &out |
| 236 | |
| 237 | if err := cmd.Run(); err != nil { |
| 238 | // exit code 1 = no paths are ignored; other errors = git unavailable |
| 239 | return files |
| 240 | } |
| 241 | |
| 242 | ignored := make(map[string]bool) |
| 243 | for _, line := range strings.Split(strings.TrimSpace(out.String()), "\n") { |
| 244 | if line != "" { |
| 245 | ignored[line] = true |
| 246 | } |
| 247 | } |
| 248 | |
| 249 | var filtered []FileEntry |
| 250 | for _, f := range files { |
| 251 | if !ignored[f.Path] { |
| 252 | filtered = append(filtered, f) |
| 253 | } |
| 254 | } |
| 255 | return filtered |
| 256 | } |
| 257 | |
| 258 | // inlineContents reads file contents and counts lines for each existing text file. |
| 259 | // Binary files and known generated files (lock files, etc.) are skipped. |