Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. Compiler.php

function Compiler::compile

Same name in this branch
  1. 11.1.x vendor/twig/twig/src/Compiler.php \Twig\Compiler::compile()
  2. 11.1.x vendor/symfony/dependency-injection/Compiler/Compiler.php \Symfony\Component\DependencyInjection\Compiler\Compiler::compile()

Compiles composer into a single phar file

Parameters

string $pharFile The full path to the file to create:

Throws

\RuntimeException

File

vendor/composer/composer/src/Composer/Compiler.php, line 46

Class

Compiler
The Compiler class compiles composer into a phar

Namespace

Composer

Code

public function compile(string $pharFile = 'composer.phar') : void {
    if (file_exists($pharFile)) {
        unlink($pharFile);
    }
    $process = new ProcessExecutor();
    if (0 !== $process->execute([
        'git',
        'log',
        '--pretty=%H',
        '-n1',
        'HEAD',
    ], $output, dirname(dirname(__DIR__)))) {
        throw new \RuntimeException('Can\'t run git log. You must ensure to run compile from composer git repository clone and that git binary is available.');
    }
    $this->version = trim($output);
    if (0 !== $process->execute([
        'git',
        'log',
        '-n1',
        '--pretty=%ci',
        'HEAD',
    ], $output, dirname(dirname(__DIR__)))) {
        throw new \RuntimeException('Can\'t run git log. You must ensure to run compile from composer git repository clone and that git binary is available.');
    }
    $this->versionDate = new \DateTime(trim($output));
    $this->versionDate
        ->setTimezone(new \DateTimeZone('UTC'));
    if (0 === $process->execute([
        'git',
        'describe',
        '--tags',
        '--exact-match',
        'HEAD',
    ], $output, dirname(dirname(__DIR__)))) {
        $this->version = trim($output);
    }
    else {
        // get branch-alias defined in composer.json for dev-main (if any)
        $localConfig = __DIR__ . '/../../composer.json';
        $file = new JsonFile($localConfig);
        $localConfig = $file->read();
        if (isset($localConfig['extra']['branch-alias']['dev-main'])) {
            $this->branchAliasVersion = $localConfig['extra']['branch-alias']['dev-main'];
        }
    }
    if ('' === $this->version) {
        throw new \UnexpectedValueException('Version detection failed');
    }
    $phar = new \Phar($pharFile, 0, 'composer.phar');
    $phar->setSignatureAlgorithm(\Phar::SHA512);
    $phar->startBuffering();
    $finderSort = static function ($a, $b) : int {
        return strcmp(strtr($a->getRealPath(), '\\', '/'), strtr($b->getRealPath(), '\\', '/'));
    };
    // Add Composer sources
    $finder = new Finder();
    $finder->files()
        ->ignoreVCS(true)
        ->name('*.php')
        ->notName('Compiler.php')
        ->notName('ClassLoader.php')
        ->notName('InstalledVersions.php')
        ->in(__DIR__ . '/..')
        ->sort($finderSort);
    foreach ($finder as $file) {
        $this->addFile($phar, $file);
    }
    // Add runtime utilities separately to make sure they retains the docblocks as these will get copied into projects
    $this->addFile($phar, new \SplFileInfo(__DIR__ . '/Autoload/ClassLoader.php'), false);
    $this->addFile($phar, new \SplFileInfo(__DIR__ . '/InstalledVersions.php'), false);
    // Add Composer resources
    $finder = new Finder();
    $finder->files()
        ->in(__DIR__ . '/../../res')
        ->sort($finderSort);
    foreach ($finder as $file) {
        $this->addFile($phar, $file, false);
    }
    // Add vendor files
    $finder = new Finder();
    $finder->files()
        ->ignoreVCS(true)
        ->notPath('/\\/(composer\\.(json|lock)|[A-Z]+\\.md(?:own)?|\\.gitignore|appveyor.yml|phpunit\\.xml\\.dist|phpstan\\.neon\\.dist|phpstan-config\\.neon|phpstan-baseline\\.neon)$/')
        ->notPath('/bin\\/(jsonlint|validate-json|simple-phpunit|phpstan|phpstan\\.phar)(\\.bat)?$/')
        ->notPath('justinrainbow/json-schema/demo/')
        ->notPath('justinrainbow/json-schema/dist/')
        ->notPath('composer/pcre/extension.neon')
        ->notPath('composer/LICENSE')
        ->exclude('Tests')
        ->exclude('tests')
        ->exclude('docs')
        ->in(__DIR__ . '/../../vendor/')
        ->sort($finderSort);
    $extraFiles = [];
    foreach ([
        __DIR__ . '/../../vendor/composer/installed.json',
        __DIR__ . '/../../vendor/composer/spdx-licenses/res/spdx-exceptions.json',
        __DIR__ . '/../../vendor/composer/spdx-licenses/res/spdx-licenses.json',
        CaBundle::getBundledCaBundlePath(),
        __DIR__ . '/../../vendor/symfony/console/Resources/bin/hiddeninput.exe',
        __DIR__ . '/../../vendor/symfony/console/Resources/completion.bash',
    ] as $file) {
        $extraFiles[$file] = realpath($file);
        if (!file_exists($file)) {
            throw new \RuntimeException('Extra file listed is missing from the filesystem: ' . $file);
        }
    }
    $unexpectedFiles = [];
    foreach ($finder as $file) {
        if (false !== ($index = array_search($file->getRealPath(), $extraFiles, true))) {
            unset($extraFiles[$index]);
        }
        elseif (!Preg::isMatch('{(^LICENSE$|\\.php$)}', $file->getFilename())) {
            $unexpectedFiles[] = (string) $file;
        }
        if (Preg::isMatch('{\\.php[\\d.]*$}', $file->getFilename())) {
            $this->addFile($phar, $file);
        }
        else {
            $this->addFile($phar, $file, false);
        }
    }
    if (count($extraFiles) > 0) {
        throw new \RuntimeException('These files were expected but not added to the phar, they might be excluded or gone from the source package:' . PHP_EOL . var_export($extraFiles, true));
    }
    if (count($unexpectedFiles) > 0) {
        throw new \RuntimeException('These files were unexpectedly added to the phar, make sure they are excluded or listed in $extraFiles:' . PHP_EOL . var_export($unexpectedFiles, true));
    }
    // Add bin/composer
    $this->addComposerBin($phar);
    // Stubs
    $phar->setStub($this->getStub());
    $phar->stopBuffering();
    // disabled for interoperability with systems without gzip ext
    // $phar->compressFiles(\Phar::GZ);
    $this->addFile($phar, new \SplFileInfo(__DIR__ . '/../../LICENSE'), false);
    unset($phar);
    // re-sign the phar with reproducible timestamp / signature
    $util = new Timestamps($pharFile);
    $util->updateTimestamps($this->versionDate);
    $util->save($pharFile, \Phar::SHA512);
    Linter::lint($pharFile, [
        'vendor/symfony/console/Attribute/AsCommand.php',
        'vendor/symfony/polyfill-intl-grapheme/bootstrap80.php',
        'vendor/symfony/polyfill-intl-normalizer/bootstrap80.php',
        'vendor/symfony/polyfill-mbstring/bootstrap80.php',
        'vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php',
        'vendor/symfony/service-contracts/Attribute/SubscribedService.php',
    ]);
}
RSS feed
Powered by Drupal