Avoid scanning files twice when generating optimized autoloaders, fixes #8683
parent
12b32707fa
commit
86677ad172
|
@ -101,15 +101,15 @@ class AutoloadGenerator
|
|||
$this->runScripts = (bool) $runScripts;
|
||||
}
|
||||
|
||||
public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsr0Packages = false, $suffix = '')
|
||||
public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsrPackages = false, $suffix = '')
|
||||
{
|
||||
if ($this->classMapAuthoritative) {
|
||||
// Force scanPsr0Packages when classmap is authoritative
|
||||
$scanPsr0Packages = true;
|
||||
// Force scanPsrPackages when classmap is authoritative
|
||||
$scanPsrPackages = true;
|
||||
}
|
||||
if ($this->runScripts) {
|
||||
$this->eventDispatcher->dispatchScript(ScriptEvents::PRE_AUTOLOAD_DUMP, $this->devMode, array(), array(
|
||||
'optimize' => (bool) $scanPsr0Packages,
|
||||
'optimize' => (bool) $scanPsrPackages,
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -234,14 +234,18 @@ EOF;
|
|||
$blacklist = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
|
||||
}
|
||||
|
||||
// flatten array
|
||||
$classMap = array();
|
||||
$ambiguousClasses = array();
|
||||
if ($scanPsr0Packages) {
|
||||
$scannedFiles = array();
|
||||
foreach ($autoloads['classmap'] as $dir) {
|
||||
$classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, null, null, $classMap, $ambiguousClasses, $scannedFiles);
|
||||
}
|
||||
|
||||
if ($scanPsrPackages) {
|
||||
$namespacesToScan = array();
|
||||
|
||||
// Scan the PSR-0/4 directories for class files, and add them to the class map
|
||||
foreach (array('psr-0', 'psr-4') as $psrType) {
|
||||
foreach (array('psr-4', 'psr-0') as $psrType) {
|
||||
foreach ($autoloads[$psrType] as $namespace => $paths) {
|
||||
$namespacesToScan[$namespace][] = array('paths' => $paths, 'type' => $psrType);
|
||||
}
|
||||
|
@ -257,16 +261,12 @@ EOF;
|
|||
continue;
|
||||
}
|
||||
|
||||
$classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, $namespace, $group['type'], $classMap, $ambiguousClasses);
|
||||
$classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, $namespace, $group['type'], $classMap, $ambiguousClasses, $scannedFiles);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($autoloads['classmap'] as $dir) {
|
||||
$classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, null, null, $classMap, $ambiguousClasses);
|
||||
}
|
||||
|
||||
foreach ($ambiguousClasses as $className => $ambigiousPaths) {
|
||||
$cleanPath = str_replace(array('$vendorDir . \'', '$baseDir . \'', "',\n"), array($vendorPath, $basePath, ''), $classMap[$className]);
|
||||
|
||||
|
@ -319,7 +319,7 @@ EOF;
|
|||
|
||||
if ($this->runScripts) {
|
||||
$this->eventDispatcher->dispatchScript(ScriptEvents::POST_AUTOLOAD_DUMP, $this->devMode, array(), array(
|
||||
'optimize' => (bool) $scanPsr0Packages,
|
||||
'optimize' => (bool) $scanPsrPackages,
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -336,9 +336,9 @@ EOF;
|
|||
return 0;
|
||||
}
|
||||
|
||||
private function addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, $namespaceFilter, $autoloadType, array $classMap, array &$ambiguousClasses)
|
||||
private function addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, $namespaceFilter, $autoloadType, array $classMap, array &$ambiguousClasses, array &$scannedFiles)
|
||||
{
|
||||
foreach ($this->generateClassMap($dir, $blacklist, $namespaceFilter, $autoloadType) as $class => $path) {
|
||||
foreach ($this->generateClassMap($dir, $blacklist, $namespaceFilter, $autoloadType, true, $scannedFiles) as $class => $path) {
|
||||
$pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path).",\n";
|
||||
if (!isset($classMap[$class])) {
|
||||
$classMap[$class] = $pathCode;
|
||||
|
@ -350,9 +350,9 @@ EOF;
|
|||
return $classMap;
|
||||
}
|
||||
|
||||
private function generateClassMap($dir, $blacklist = null, $namespaceFilter = null, $autoloadType = null, $showAmbiguousWarning = true)
|
||||
private function generateClassMap($dir, $blacklist, $namespaceFilter, $autoloadType, $showAmbiguousWarning, array &$scannedFiles)
|
||||
{
|
||||
return ClassMapGenerator::createMap($dir, $blacklist, $showAmbiguousWarning ? $this->io : null, $namespaceFilter, $autoloadType);
|
||||
return ClassMapGenerator::createMap($dir, $blacklist, $showAmbiguousWarning ? $this->io : null, $namespaceFilter, $autoloadType, $scannedFiles);
|
||||
}
|
||||
|
||||
public function buildPackageMap(InstallationManager $installationManager, PackageInterface $mainPackage, array $packages)
|
||||
|
@ -461,9 +461,10 @@ EOF;
|
|||
$blacklist = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
|
||||
}
|
||||
|
||||
$scannedFiles = array();
|
||||
foreach ($autoloads['classmap'] as $dir) {
|
||||
try {
|
||||
$loader->addClassMap($this->generateClassMap($dir, $blacklist, null, null, false));
|
||||
$loader->addClassMap($this->generateClassMap($dir, $blacklist, null, null, false, $scannedFiles));
|
||||
} catch (\RuntimeException $e) {
|
||||
$this->io->writeError('<warning>'.$e->getMessage().'</warning>');
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ class ClassMapGenerator
|
|||
* @throws \RuntimeException When the path is neither an existing file nor directory
|
||||
* @return array A class map array
|
||||
*/
|
||||
public static function createMap($path, $blacklist = null, IOInterface $io = null, $namespace = null, $autoloadType = null)
|
||||
public static function createMap($path, $blacklist = null, IOInterface $io = null, $namespace = null, $autoloadType = null, &$scannedFiles = array())
|
||||
{
|
||||
if (is_string($path)) {
|
||||
$basePath = $path;
|
||||
|
@ -94,8 +94,16 @@ class ClassMapGenerator
|
|||
$filePath = preg_replace('{[\\\\/]{2,}}', '/', $filePath);
|
||||
}
|
||||
|
||||
$realPath = realpath($filePath);
|
||||
|
||||
// if a list of scanned files is given, avoid scanning twice the same file to save cycles and avoid generating warnings
|
||||
// in case a PSR-0/4 declaration follows another more specific one, or a classmap declaration, which covered this file already
|
||||
if (isset($scannedFiles[$realPath])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check the realpath of the file against the blacklist as the path might be a symlink and the blacklist is realpath'd so symlink are resolved
|
||||
if ($blacklist && preg_match($blacklist, strtr(realpath($filePath), '\\', '/'))) {
|
||||
if ($blacklist && preg_match($blacklist, strtr($realPath, '\\', '/'))) {
|
||||
continue;
|
||||
}
|
||||
// check non-realpath of file for directories symlink in project dir
|
||||
|
@ -105,7 +113,15 @@ class ClassMapGenerator
|
|||
|
||||
$classes = self::findClasses($filePath);
|
||||
if (null !== $autoloadType) {
|
||||
$classes = self::filterByNamespace($classes, $filePath, $namespace, $autoloadType, $basePath, $io);
|
||||
list($classes, $validClasses) = self::filterByNamespace($classes, $filePath, $namespace, $autoloadType, $basePath, $io);
|
||||
|
||||
// if no valid class was found in the file then we do not mark it as scanned as it might still be matched by another rule later
|
||||
if ($validClasses) {
|
||||
$scannedFiles[$realPath] = true;
|
||||
}
|
||||
} else {
|
||||
// classmap autoload rules always collect all classes so for these we definitely do not want to scan again
|
||||
$scannedFiles[$realPath] = true;
|
||||
}
|
||||
|
||||
foreach ($classes as $class) {
|
||||
|
@ -192,7 +208,7 @@ class ClassMapGenerator
|
|||
|
||||
// TODO enable in Composer 2.0 & unskip test in AutoloadGeneratorTest::testPSRToClassMapIgnoresNonPSRClasses
|
||||
//return $validClasses;
|
||||
return $classes;
|
||||
return array($classes, $validClasses);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -82,7 +82,7 @@ EOT
|
|||
} elseif ($optimize) {
|
||||
$this->getIO()->write('<info>Generated optimized autoload files containing '. $numberOfClasses .' classes</info>');
|
||||
} else {
|
||||
$this->getIO()->write('<info>Generated autoload files containing '. $numberOfClasses .' classes</info>');
|
||||
$this->getIO()->write('<info>Generated autoload files</info>');
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue