Skip .git, .gitignore and .gitattributes export-ignore files when enumerating#297
Conversation
…merating FileEnumerator now mimics `git archive` / Composer dist behaviour by skipping files that would not be part of a package's distributed archive: the `.git` directory, files matched by the package's `.gitignore` (via inmarelibero/gitignore-checker), and files marked `export-ignore` in the package's `.gitattributes` (via a new BrianHenryIE\Strauss\Helpers\GitAttributes parser). Filtering is per package root and gated behind the new `exclude_git_files` config option, which defaults to true. Fixes #254 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Generated: Sat, Jun 27, 2026, 3:33:39 UTC.
|
There was a problem hiding this comment.
Code Review
This pull request introduces a feature to exclude Git-related files (such as the .git directory, .gitignore-matched files, and .gitattributes export-ignore files) during file enumeration, controlled by the new exclude_git_files configuration option. Feedback on the changes highlights two critical issues in FileEnumerator.php related to cross-platform compatibility: prepending a slash to the base path breaks path resolution on Windows and with stream wrappers, and a lack of directory separator normalization on $relativePath prevents proper exclusion of .git and parent directories on Windows environments.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| /** | ||
| * TODO: use {@see FileSystem::prefixPath()} when #278 is merged. | ||
| */ | ||
| $gitIgnoreChecker = new GitIgnoreChecker('/' . $normalizedBasePath); |
There was a problem hiding this comment.
Prepending '/' to $normalizedBasePath breaks path resolution on Windows (e.g., /C:/path) and prevents the GitIgnoreChecker from working with registered stream wrappers like mem:// (which becomes /mem://...). This causes .gitignore detection to be silently skipped during dry-runs and in-memory unit tests. Pass $normalizedBasePath directly instead.
$gitIgnoreChecker = new GitIgnoreChecker($normalizedBasePath);| protected function isGitExcluded(string $sourceAbsolutePath, array $repositories): bool | ||
| { | ||
| foreach ($repositories as $basePath => $checkers) { | ||
| $relativePath = $this->filesystem->getRelativePath($basePath, $sourceAbsolutePath); |
There was a problem hiding this comment.
On Windows, $relativePath may contain backslashes (e.g., ..\\ or .git\\). This will cause the checks for ../ and .git/ to fail, meaning files outside the repository or inside the .git directory won't be correctly identified and excluded. Normalize the directory separators of $relativePath immediately after retrieving it.
$relativePath = FileSystem::normalizeDirSeparator($this->filesystem->getRelativePath($basePath, $sourceAbsolutePath));|
strauss.phar.zip @ 151bbf8 \n |
Fixes #254
Summary
When a package is installed from source (a git clone) rather than a dist zip,
FileEnumeratorpreviously copied every file in the package directory — including.git/internals, build/test artifacts listed in.gitignore, and files the package author markedexport-ignorein.gitattributes(whichgit archive/ Composer dist would have stripped).This change makes
FileEnumeratormimicgit archive/ dist behaviour, per package root:.gitdirectory;.gitignore, usinginmarelibero/gitignore-checker;export-ignorein the package's.gitattributes, via a newBrianHenryIE\Strauss\Helpers\GitAttributesparser (parse()+isExportIgnored()).Filtering is gated behind a new
exclude_git_filesconfig option which defaults totrue; set it tofalseto restore the previous copy-everything behaviour.Changes
composer.json— addedinmarelibero/gitignore-checker.src/Helpers/GitAttributes.php(new) — minimal.gitattributesparser + gitignore-style path matching (anchored vs unanchored, directory-prefix matching,*wildcards, last-match-wins so-export-ignorecan re-include).src/Config/FileEnumeratorConfig.php+src/Composer/Extra/StraussConfig.php— newgetExcludeGitFiles()/exclude_git_filesoption (defaulttrue).src/Pipeline/FileEnumerator.php— builds the gitignore/gitattributes checkers once per base path and filters discovered files; degrades gracefully (try/catch) when the gitignore library cannot read a path.README.md— documented the new option.Tests
GitAttributesTest— parsing and export-ignore matching against the in-memory filesystem.StraussConfigTest—exclude_git_filesdefault-trueandfalsemapping.GitFilesFeatureTest— builds a real package dir with.git/,.gitignoreand.gitattributesand asserts the right files are kept/skipped, plus a flag-off case proving backward compatibility.Verification
phpcs(PSR-2): clean on all new/changed code.phpstan(level 7): no errors on all newsrccode.FileEnumeratorIntegrationTestpass.🤖 Generated with Claude Code