1
0
Fork 0
pull/11962/head
Jordi Boggiano 2024-05-03 16:20:34 +02:00
parent 6cb3070203
commit 0d856c0a65
No known key found for this signature in database
GPG Key ID: 7BBD42C429EC80BC
1 changed files with 23 additions and 8 deletions

View File

@ -41,6 +41,8 @@ use Composer\Package\Locker;
*/ */
class AutoloadGenerator class AutoloadGenerator
{ {
private const EXCLUDE_FROM_CLASSMAP_SUFFIX_PATTERN = '($|/)';
/** /**
* @var EventDispatcher * @var EventDispatcher
*/ */
@ -325,7 +327,8 @@ EOF;
} }
foreach ($autoloads['classmap'] as $dir) { foreach ($autoloads['classmap'] as $dir) {
$classMapGenerator->scanPaths($dir, $this->buildExclusionRegex($dir, $excluded)); $excludeRules = $this->buildExclusionRegex($dir, $excluded);
$classMapGenerator->scanPaths($dir, $excludeRules['pattern'], 'classmap', null, $excludeRules['paths']);
} }
if ($scanPsrPackages) { if ($scanPsrPackages) {
@ -348,7 +351,8 @@ EOF;
continue; continue;
} }
$classMapGenerator->scanPaths($dir, $this->buildExclusionRegex($dir, $excluded), $group['type'], $namespace); $excludeRules = $this->buildExclusionRegex($dir, $excluded);
$classMapGenerator->scanPaths($dir, $excludeRules['pattern'], $group['type'], $namespace, $excludeRules['paths']);
} }
} }
} }
@ -463,12 +467,14 @@ EOF;
* @param array<string>|null $excluded * @param array<string>|null $excluded
* @return non-empty-string|null * @return non-empty-string|null
*/ */
private function buildExclusionRegex(string $dir, ?array $excluded): ?string private function buildExclusionRegex(string $dir, ?array $excluded): array
{ {
if (null === $excluded) { if (null === $excluded) {
return null; return ['pattern' => null, 'paths' => []];
} }
$excludedPaths = [];
// filter excluded patterns here to only use those matching $dir // filter excluded patterns here to only use those matching $dir
// exclude-from-classmap patterns are all realpath'd so we can only filter them if $dir exists so that realpath($dir) will work // exclude-from-classmap patterns are all realpath'd so we can only filter them if $dir exists so that realpath($dir) will work
// if $dir does not exist, it should anyway not find anything there so no trouble // if $dir does not exist, it should anyway not find anything there so no trouble
@ -478,14 +484,22 @@ EOF;
foreach ($excluded as $index => $pattern) { foreach ($excluded as $index => $pattern) {
// extract the constant string prefix of the pattern here, until we reach a non-escaped regex special character // extract the constant string prefix of the pattern here, until we reach a non-escaped regex special character
$pattern = Preg::replace('{^(([^.+*?\[^\]$(){}=!<>|:\\\\#-]+|\\\\[.+*?\[^\]$(){}=!<>|:#-])*).*}', '$1', $pattern); $pattern = Preg::replace('{^(([^.+*?\[^\]$(){}=!<>|:\\\\#-]+|\\\\[.+*?\[^\]$(){}=!<>|:#-])*).*}', '$1', $pattern);
// if the pattern is not a subset or superset of $dir, it is unrelated and we skip it // if the pattern is not a subset or superset of $dir, it is unrelated and we skip it
if (0 !== strpos($pattern, $dirMatch) && 0 !== strpos($dirMatch, $pattern)) { if (!Preg::isMatch('{^'.preg_quote($pattern).'($|/)}', $dirMatch) && !Preg::isMatch('{^'.preg_quote($dirMatch).'($|/)}', $pattern)) {
unset($excluded[$index]); unset($excluded[$index]);
continue;
}
if ($pattern.self::EXCLUDE_FROM_CLASSMAP_SUFFIX_PATTERN === $excluded[$index]) {
$excludedPaths[] = substr($pattern, strlen($dirMatch) + 1);
// TODO maybe this shuold have a /prefix to make sure it does not exclude "Tests" for example from any sub-path
} }
} }
} }
return \count($excluded) > 0 ? '{(' . implode('|', $excluded) . ')}' : null; return ['pattern' => \count($excluded) > 0 ? '{^(' . implode('|', $excluded) . ')}' : null, 'paths' => $excludedPaths];
} }
/** /**
@ -612,7 +626,8 @@ EOF;
foreach ($autoloads['classmap'] as $dir) { foreach ($autoloads['classmap'] as $dir) {
try { try {
$classMapGenerator->scanPaths($dir, $this->buildExclusionRegex($dir, $excluded)); $excludeRules = $this->buildExclusionRegex($dir, $excluded);
$classMapGenerator->scanPaths($dir, $excludeRules['pattern'], 'classmap', null, $excludeRules['paths']);
} catch (\RuntimeException $e) { } catch (\RuntimeException $e) {
$this->io->writeError('<warning>'.$e->getMessage().'</warning>'); $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
} }
@ -1272,7 +1287,7 @@ INITIALIZER;
if (false === $resolvedPath) { if (false === $resolvedPath) {
continue; continue;
} }
$autoloads[] = preg_quote(strtr($resolvedPath, '\\', '/')) . '/' . $path . '($|/)'; $autoloads[] = preg_quote(strtr($resolvedPath, '\\', '/')) . '/' . $path . self::EXCLUDE_FROM_CLASSMAP_SUFFIX_PATTERN;
continue; continue;
} }