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

Breadcrumb

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

function Installer::run

Run installation (or update)

@phpstan-return self::ERROR_*

Return value

int 0 on success or a positive error code on failure

Throws

\Exception

File

vendor/composer/composer/src/Composer/Installer.php, line 244

Class

Installer
@author Jordi Boggiano <j.boggiano@seld.be> @author Beau Simensen <beau@dflydev.com> @author Konstantin Kudryashov <ever.zet@gmail.com> @author Nils Adermann <naderman@naderman.de>

Namespace

Composer

Code

public function run() : int {
    // Disable GC to save CPU cycles, as the dependency solver can create hundreds of thousands
    // of PHP objects, the GC can spend quite some time walking the tree of references looking
    // for stuff to collect while there is nothing to collect. This slows things down dramatically
    // and turning it off results in much better performance. Do not try this at home however.
    gc_collect_cycles();
    gc_disable();
    if ($this->updateAllowList !== null && $this->updateMirrors) {
        throw new \RuntimeException("The installer options updateMirrors and updateAllowList are mutually exclusive.");
    }
    $isFreshInstall = $this->repositoryManager
        ->getLocalRepository()
        ->isFresh();
    // Force update if there is no lock file present
    if (!$this->update && !$this->locker
        ->isLocked()) {
        $this->io
            ->writeError('<warning>No composer.lock file present. Updating dependencies to latest instead of installing from lock file. See https://getcomposer.org/install for more information.</warning>');
        $this->update = true;
    }
    if ($this->dryRun) {
        $this->verbose = true;
        $this->runScripts = false;
        $this->executeOperations = false;
        $this->writeLock = false;
        $this->dumpAutoloader = false;
        $this->mockLocalRepositories($this->repositoryManager);
    }
    if ($this->downloadOnly) {
        $this->dumpAutoloader = false;
    }
    if ($this->update && !$this->install) {
        $this->dumpAutoloader = false;
    }
    if ($this->runScripts) {
        Platform::putEnv('COMPOSER_DEV_MODE', $this->devMode ? '1' : '0');
        // dispatch pre event
        // should we treat this more strictly as running an update and then running an install, triggering events multiple times?
        $eventName = $this->update ? ScriptEvents::PRE_UPDATE_CMD : ScriptEvents::PRE_INSTALL_CMD;
        $this->eventDispatcher
            ->dispatchScript($eventName, $this->devMode);
    }
    $this->downloadManager
        ->setPreferSource($this->preferSource);
    $this->downloadManager
        ->setPreferDist($this->preferDist);
    $localRepo = $this->repositoryManager
        ->getLocalRepository();
    try {
        if ($this->update) {
            $res = $this->doUpdate($localRepo, $this->install);
        }
        else {
            $res = $this->doInstall($localRepo);
        }
        if ($res !== 0) {
            return $res;
        }
    } catch (\Exception $e) {
        if ($this->executeOperations && $this->install && $this->config
            ->get('notify-on-install')) {
            $this->installationManager
                ->notifyInstalls($this->io);
        }
        throw $e;
    }
    if ($this->executeOperations && $this->install && $this->config
        ->get('notify-on-install')) {
        $this->installationManager
            ->notifyInstalls($this->io);
    }
    if ($this->update) {
        $installedRepo = new InstalledRepository([
            $this->locker
                ->getLockedRepository($this->devMode),
            $this->createPlatformRepo(false),
            new RootPackageRepository(clone $this->package),
        ]);
        if ($isFreshInstall) {
            $this->suggestedPackagesReporter
                ->addSuggestionsFromPackage($this->package);
        }
        $this->suggestedPackagesReporter
            ->outputMinimalistic($installedRepo);
    }
    // Find abandoned packages and warn user
    $lockedRepository = $this->locker
        ->getLockedRepository(true);
    foreach ($lockedRepository->getPackages() as $package) {
        if (!$package instanceof CompletePackage || !$package->isAbandoned()) {
            continue;
        }
        $replacement = is_string($package->getReplacementPackage()) ? 'Use ' . $package->getReplacementPackage() . ' instead' : 'No replacement was suggested';
        $this->io
            ->writeError(sprintf("<warning>Package %s is abandoned, you should avoid using it. %s.</warning>", $package->getPrettyName(), $replacement));
    }
    if ($this->dumpAutoloader) {
        // write autoloader
        if ($this->optimizeAutoloader) {
            $this->io
                ->writeError('<info>Generating optimized autoload files</info>');
        }
        else {
            $this->io
                ->writeError('<info>Generating autoload files</info>');
        }
        $this->autoloadGenerator
            ->setClassMapAuthoritative($this->classMapAuthoritative);
        $this->autoloadGenerator
            ->setApcu($this->apcuAutoloader, $this->apcuAutoloaderPrefix);
        $this->autoloadGenerator
            ->setRunScripts($this->runScripts);
        $this->autoloadGenerator
            ->setPlatformRequirementFilter($this->platformRequirementFilter);
        $this->autoloadGenerator
            ->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader, null, $this->locker);
    }
    if ($this->install && $this->executeOperations) {
        // force binaries re-generation in case they are missing
        foreach ($localRepo->getPackages() as $package) {
            $this->installationManager
                ->ensureBinariesPresence($package);
        }
    }
    $fundEnv = Platform::getEnv('COMPOSER_FUND');
    $showFunding = true;
    if (is_numeric($fundEnv)) {
        $showFunding = intval($fundEnv) !== 0;
    }
    if ($showFunding) {
        $fundingCount = 0;
        foreach ($localRepo->getPackages() as $package) {
            if ($package instanceof CompletePackageInterface && !$package instanceof AliasPackage && $package->getFunding()) {
                $fundingCount++;
            }
        }
        if ($fundingCount > 0) {
            $this->io
                ->writeError([
                sprintf("<info>%d package%s you are using %s looking for funding.</info>", $fundingCount, 1 === $fundingCount ? '' : 's', 1 === $fundingCount ? 'is' : 'are'),
                '<info>Use the `composer fund` command to find out more!</info>',
            ]);
        }
    }
    if ($this->runScripts) {
        // dispatch post event
        $eventName = $this->update ? ScriptEvents::POST_UPDATE_CMD : ScriptEvents::POST_INSTALL_CMD;
        $this->eventDispatcher
            ->dispatchScript($eventName, $this->devMode);
    }
    // re-enable GC except on HHVM which triggers a warning here
    if (!defined('HHVM_VERSION')) {
        gc_enable();
    }
    if ($this->audit) {
        if ($this->update && !$this->install) {
            $packages = $lockedRepository->getCanonicalPackages();
            $target = 'locked';
        }
        else {
            $packages = $localRepo->getCanonicalPackages();
            $target = 'installed';
        }
        if (count($packages) > 0) {
            try {
                $auditor = new Auditor();
                $repoSet = new RepositorySet();
                foreach ($this->repositoryManager
                    ->getRepositories() as $repo) {
                    $repoSet->addRepository($repo);
                }
                $auditConfig = $this->config
                    ->get('audit');
                return $auditor->audit($this->io, $repoSet, $packages, $this->auditFormat, true, $auditConfig['ignore'] ?? [], $auditConfig['abandoned'] ?? Auditor::ABANDONED_FAIL) > 0 && $this->errorOnAudit ? self::ERROR_AUDIT_FAILED : 0;
            } catch (TransportException $e) {
                $this->io
                    ->error('Failed to audit ' . $target . ' packages.');
                if ($this->io
                    ->isVerbose()) {
                    $this->io
                        ->error('[' . get_class($e) . '] ' . $e->getMessage());
                }
            }
        }
        else {
            $this->io
                ->writeError('No ' . $target . ' packages - skipping audit.');
        }
    }
    return 0;
}

API Navigation

  • Drupal Core 11.1.x
  • Topics
  • Classes
  • Functions
  • Constants
  • Globals
  • Files
  • Namespaces
  • Deprecated
  • Services
RSS feed
Powered by Drupal