PHP 8 Compatibility
This commit is contained in:
150
vendor/symfony/finder/Gitignore.php
vendored
150
vendor/symfony/finder/Gitignore.php
vendored
@@ -14,6 +14,7 @@ namespace Symfony\Component\Finder;
|
||||
/**
|
||||
* Gitignore matches against text.
|
||||
*
|
||||
* @author Michael Voříšek <vorismi3@fel.cvut.cz>
|
||||
* @author Ahmed Abdou <mail@ahmd.io>
|
||||
*/
|
||||
class Gitignore
|
||||
@@ -21,113 +22,72 @@ class Gitignore
|
||||
/**
|
||||
* Returns a regexp which is the equivalent of the gitignore pattern.
|
||||
*
|
||||
* @return string The regexp
|
||||
* Format specification: https://git-scm.com/docs/gitignore#_pattern_format
|
||||
*/
|
||||
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));
|
||||
return self::buildRegex($gitignoreFileContent, false);
|
||||
}
|
||||
|
||||
private static function getRegexFromGitignore(string $gitignorePattern, bool $negative = false): string
|
||||
public static function toRegexMatchingNegatedPatterns(string $gitignoreFileContent): string
|
||||
{
|
||||
$regex = '';
|
||||
$isRelativePath = false;
|
||||
// If there is a separator at the beginning or middle (or both) of the pattern, then the pattern is relative to the directory level of the particular .gitignore file itself
|
||||
$slashPosition = strpos($gitignorePattern, '/');
|
||||
if (false !== $slashPosition && \strlen($gitignorePattern) - 1 !== $slashPosition) {
|
||||
if (0 === $slashPosition) {
|
||||
$gitignorePattern = substr($gitignorePattern, 1);
|
||||
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;
|
||||
}
|
||||
|
||||
$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 ('' !== $line) {
|
||||
if ($isNegative xor $inverted) {
|
||||
$res = '(?!'.self::lineToRegex($line).'$)'.$res;
|
||||
} else {
|
||||
$res = '(?:'.$res.'|'.self::lineToRegex($line).')';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($negative) {
|
||||
// a lookbehind assertion has to be a fixed width (it can not have nested '|' statements)
|
||||
return sprintf('%s$|%s\/$', $regex, $regex);
|
||||
return '~^(?:'.$res.')~s';
|
||||
}
|
||||
|
||||
private static function lineToRegex(string $gitignoreLine): string
|
||||
{
|
||||
if ('' === $gitignoreLine) {
|
||||
return '$f'; // always false
|
||||
}
|
||||
|
||||
return '(?>'.$regex.'($|\/.*))';
|
||||
$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, '/') ? '(?:$|/)' : '');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user