Source code of filesite.io.
https://filesite.io
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
3.0 KiB
93 lines
3.0 KiB
<?php |
|
|
|
/* |
|
* This file is part of the Symfony package. |
|
* |
|
* (c) Fabien Potencier <[email protected]> |
|
* |
|
* For the full copyright and license information, please view the LICENSE |
|
* file that was distributed with this source code. |
|
*/ |
|
|
|
namespace Symfony\Component\Finder; |
|
|
|
/** |
|
* Gitignore matches against text. |
|
* |
|
* @author Michael Voříšek <[email protected]> |
|
* @author Ahmed Abdou <[email protected]> |
|
*/ |
|
class Gitignore |
|
{ |
|
/** |
|
* Returns a regexp which is the equivalent of the gitignore pattern. |
|
* |
|
* Format specification: https://git-scm.com/docs/gitignore#_pattern_format |
|
*/ |
|
public static function toRegex(string $gitignoreFileContent): string |
|
{ |
|
return self::buildRegex($gitignoreFileContent, false); |
|
} |
|
|
|
public static function toRegexMatchingNegatedPatterns(string $gitignoreFileContent): string |
|
{ |
|
return self::buildRegex($gitignoreFileContent, true); |
|
} |
|
|
|
private static function buildRegex(string $gitignoreFileContent, bool $inverted): string |
|
{ |
|
$gitignoreFileContent = preg_replace('~(?<!\\\\)#[^\n\r]*~', '', $gitignoreFileContent); |
|
$gitignoreLines = preg_split('~\r\n?|\n~', $gitignoreFileContent); |
|
|
|
$res = self::lineToRegex(''); |
|
foreach ($gitignoreLines as $line) { |
|
$line = preg_replace('~(?<!\\\\)[ \t]+$~', '', $line); |
|
|
|
if ('!' === substr($line, 0, 1)) { |
|
$line = substr($line, 1); |
|
$isNegative = true; |
|
} else { |
|
$isNegative = false; |
|
} |
|
|
|
if ('' !== $line) { |
|
if ($isNegative xor $inverted) { |
|
$res = '(?!'.self::lineToRegex($line).'$)'.$res; |
|
} else { |
|
$res = '(?:'.$res.'|'.self::lineToRegex($line).')'; |
|
} |
|
} |
|
} |
|
|
|
return '~^(?:'.$res.')~s'; |
|
} |
|
|
|
private static function lineToRegex(string $gitignoreLine): string |
|
{ |
|
if ('' === $gitignoreLine) { |
|
return '$f'; // always false |
|
} |
|
|
|
$slashPos = strpos($gitignoreLine, '/'); |
|
if (false !== $slashPos && \strlen($gitignoreLine) - 1 !== $slashPos) { |
|
if (0 === $slashPos) { |
|
$gitignoreLine = substr($gitignoreLine, 1); |
|
} |
|
$isAbsolute = true; |
|
} else { |
|
$isAbsolute = false; |
|
} |
|
|
|
$regex = preg_quote(str_replace('\\', '', $gitignoreLine), '~'); |
|
$regex = preg_replace_callback('~\\\\\[((?:\\\\!)?)([^\[\]]*)\\\\\]~', function (array $matches): string { |
|
return '['.('' !== $matches[1] ? '^' : '').str_replace('\\-', '-', $matches[2]).']'; |
|
}, $regex); |
|
$regex = preg_replace('~(?:(?:\\\\\*){2,}(/?))+~', '(?:(?:(?!//).(?<!//))+$1)?', $regex); |
|
$regex = preg_replace('~\\\\\*~', '[^/]*', $regex); |
|
$regex = preg_replace('~\\\\\?~', '[^/]', $regex); |
|
|
|
return ($isAbsolute ? '' : '(?:[^/]+/)*') |
|
.$regex |
|
.(!str_ends_with($gitignoreLine, '/') ? '(?:$|/)' : ''); |
|
} |
|
}
|
|
|