123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- <?php
- namespace Symfony\Component\Finder;
- class Gitignore
- {
-
- public static function toRegex(string $gitignoreFileContent): string
- {
- $gitignoreFileContent = preg_replace('/^[^\\\r\n]*#.*/m', '', $gitignoreFileContent);
- $gitignoreLines = preg_split('/\r\n|\r|\n/', $gitignoreFileContent);
- $positives = [];
- $negatives = [];
- foreach ($gitignoreLines as $i => $line) {
- $line = trim($line);
- if ('' === $line) {
- continue;
- }
- if (1 === preg_match('/^!/', $line)) {
- $positives[$i] = null;
- $negatives[$i] = self::getRegexFromGitignore(preg_replace('/^!(.*)/', '${1}', $line), true);
- continue;
- }
- $negatives[$i] = null;
- $positives[$i] = self::getRegexFromGitignore($line);
- }
- $index = 0;
- $patterns = [];
- foreach ($positives as $pattern) {
- if (null === $pattern) {
- continue;
- }
- $negativesAfter = array_filter(\array_slice($negatives, ++$index));
- if ([] !== $negativesAfter) {
- $pattern .= sprintf('(?<!%s)', implode('|', $negativesAfter));
- }
- $patterns[] = $pattern;
- }
- return sprintf('/^((%s))$/', implode(')|(', $patterns));
- }
- private static function getRegexFromGitignore(string $gitignorePattern, bool $negative = false): string
- {
- $regex = '';
- $isRelativePath = false;
-
- $slashPosition = strpos($gitignorePattern, '/');
- if (false !== $slashPosition && \strlen($gitignorePattern) - 1 !== $slashPosition) {
- if (0 === $slashPosition) {
- $gitignorePattern = substr($gitignorePattern, 1);
- }
- $isRelativePath = true;
- $regex .= '^';
- }
- if ('/' === $gitignorePattern[\strlen($gitignorePattern) - 1]) {
- $gitignorePattern = substr($gitignorePattern, 0, -1);
- }
- $iMax = \strlen($gitignorePattern);
- for ($i = 0; $i < $iMax; ++$i) {
- $tripleChars = substr($gitignorePattern, $i, 3);
- if ('**/' === $tripleChars || '/**' === $tripleChars) {
- $regex .= '.*';
- $i += 2;
- continue;
- }
- $doubleChars = substr($gitignorePattern, $i, 2);
- if ('**' === $doubleChars) {
- $regex .= '.*';
- ++$i;
- continue;
- }
- if ('*/' === $doubleChars) {
- $regex .= '[^\/]*\/?[^\/]*';
- ++$i;
- continue;
- }
- $c = $gitignorePattern[$i];
- switch ($c) {
- case '*':
- $regex .= $isRelativePath ? '[^\/]*' : '[^\/]*\/?[^\/]*';
- break;
- case '/':
- case '.':
- case ':':
- case '(':
- case ')':
- case '{':
- case '}':
- $regex .= '\\'.$c;
- break;
- default:
- $regex .= $c;
- }
- }
- if ($negative) {
-
- return sprintf('%s$|%s\/$', $regex, $regex);
- }
- return '(?>'.$regex.'($|\/.*))';
- }
- }
|