diff --git a/src/Symfony/Component/Finder/Gitignore.php b/src/Symfony/Component/Finder/Gitignore.php index 5ffe585f8a..9e7ba4d7b3 100644 --- a/src/Symfony/Component/Finder/Gitignore.php +++ b/src/Symfony/Component/Finder/Gitignore.php @@ -27,42 +27,56 @@ class Gitignore { $gitignoreFileContent = preg_replace('/^[^\\\r\n]*#.*/m', '', $gitignoreFileContent); $gitignoreLines = preg_split('/\r\n|\r|\n/', $gitignoreFileContent); - $gitignoreLines = array_map('trim', $gitignoreLines); - $gitignoreLines = array_filter($gitignoreLines); - $ignoreLinesPositive = array_filter($gitignoreLines, function (string $line) { - return !preg_match('/^!/', $line); - }); + $positives = []; + $negatives = []; + foreach ($gitignoreLines as $i => $line) { + $line = trim($line); + if ('' === $line) { + continue; + } - $ignoreLinesNegative = array_filter($gitignoreLines, function (string $line) { - return preg_match('/^!/', $line); - }); + if (1 === preg_match('/^!/', $line)) { + $positives[$i] = null; + $negatives[$i] = self::getRegexFromGitignore(preg_replace('/^!(.*)/', '${1}', $line), true); - $ignoreLinesNegative = array_map(function (string $line) { - return preg_replace('/^!(.*)/', '${1}', $line); - }, $ignoreLinesNegative); - $ignoreLinesNegative = array_map([__CLASS__, 'getRegexFromGitignore'], $ignoreLinesNegative); - - $ignoreLinesPositive = array_map([__CLASS__, 'getRegexFromGitignore'], $ignoreLinesPositive); - if (empty($ignoreLinesPositive)) { - return '/^$/'; + continue; + } + $negatives[$i] = null; + $positives[$i] = self::getRegexFromGitignore($line); } - if (empty($ignoreLinesNegative)) { - return sprintf('/%s/', implode('|', $ignoreLinesPositive)); + $index = 0; + $patterns = []; + foreach ($positives as $pattern) { + if (null === $pattern) { + continue; + } + + $negativesAfter = array_filter(\array_slice($negatives, ++$index)); + if ($negativesAfter !== []) { + $pattern .= sprintf('(?'.$regex.'($|\/.*))'; } } diff --git a/src/Symfony/Component/Finder/Tests/GitignoreTest.php b/src/Symfony/Component/Finder/Tests/GitignoreTest.php index 9f9ed738ca..ae1cfb9900 100644 --- a/src/Symfony/Component/Finder/Tests/GitignoreTest.php +++ b/src/Symfony/Component/Finder/Tests/GitignoreTest.php @@ -47,6 +47,7 @@ class GitignoreTest extends TestCase [ ' * + !/bin !/bin/bash ', ['bin/cat', 'abc/bin/cat'], @@ -99,8 +100,8 @@ class GitignoreTest extends TestCase ], [ 'app/cache/', - ['app/cache/file.txt', 'app/cache/dir1/dir2/file.txt', 'a/app/cache/file.txt'], - [], + ['app/cache/file.txt', 'app/cache/dir1/dir2/file.txt'], + ['a/app/cache/file.txt'], ], [ ' @@ -133,6 +134,15 @@ class GitignoreTest extends TestCase ['app/cache/file.txt', 'app/cache/subdir/ile.txt', '#file.txt', 'another_file.txt'], ['a/app/cache/file.txt', 'IamComment', '#IamComment'], ], + [ + ' + /app/** + !/app/bin + !/app/bin/test + ', + ['app/test/file', 'app/bin/file'], + ['app/bin/test'], + ], ]; } }