/** * Apply plugin modifications to composer * * @param \Composer\Composer $composer * @param \Composer\IO\IOInterface $io * @return void */ public function activate(Composer $composer, IOInterface $io) { $this->io = $io; $this->composer = $composer; $this->factory = $this->getFactory(); $this->manager = $this->getInstallationManager($composer); // The connection factory is used to create the actual connection instances on // the database. We will inject the factory into the manager so that it may // make the connections while they are actually needed and not of before. $installers = $this->factory->getInstallers(); foreach ($installers as $name) { $this->manager->addInstaller($this->factory->make($name, $composer, $io)); } }
/** * Run installation (or update) */ public function run() { if ($this->dryRun) { $this->verbose = true; $this->runScripts = false; $this->installationManager->addInstaller(new NoopInstaller()); } if ($this->preferSource) { $this->downloadManager->setPreferSource(true); } // create installed repo, this contains all local packages + platform packages (php & extensions) $installedRootPackage = clone $this->package; $installedRootPackage->setRequires(array()); $installedRootPackage->setDevRequires(array()); $repos = array_merge($this->repositoryManager->getLocalRepositories(), array(new InstalledArrayRepository(array($installedRootPackage)), new PlatformRepository())); $installedRepo = new CompositeRepository($repos); if ($this->additionalInstalledRepository) { $installedRepo->addRepository($this->additionalInstalledRepository); } $aliases = $this->aliasPackages(); if ($this->runScripts) { // dispatch pre event $eventName = $this->update ? ScriptEvents::PRE_UPDATE_CMD : ScriptEvents::PRE_INSTALL_CMD; $this->eventDispatcher->dispatchCommandEvent($eventName); } $this->suggestedPackages = array(); if (!$this->doInstall($this->repositoryManager->getLocalRepository(), $installedRepo, $aliases)) { return false; } if ($this->devMode) { if (!$this->doInstall($this->repositoryManager->getLocalDevRepository(), $installedRepo, $aliases, true)) { return false; } } // output suggestions foreach ($this->suggestedPackages as $suggestion) { if (!$installedRepo->findPackages($suggestion['target'])) { $this->io->write($suggestion['source'] . ' suggests installing ' . $suggestion['target'] . ' (' . $suggestion['reason'] . ')'); } } if (!$this->dryRun) { // write lock if ($this->update || !$this->locker->isLocked()) { $updatedLock = $this->locker->setLockData($this->repositoryManager->getLocalRepository()->getPackages(), $this->devMode ? $this->repositoryManager->getLocalDevRepository()->getPackages() : null, $aliases, $this->package->getMinimumStability(), $this->package->getStabilityFlags()); if ($updatedLock) { $this->io->write('<info>Writing lock file</info>'); } } // write autoloader $this->io->write('<info>Generating autoload files</info>'); $localRepos = new CompositeRepository($this->repositoryManager->getLocalRepositories()); $this->autoloadGenerator->dump($localRepos, $this->package, $this->installationManager, $this->installationManager->getVendorPath() . '/composer', true); if ($this->runScripts) { // dispatch post event $eventName = $this->update ? ScriptEvents::POST_UPDATE_CMD : ScriptEvents::POST_INSTALL_CMD; $this->eventDispatcher->dispatchCommandEvent($eventName); } } return true; }
public function build($rootDirectory, $optimize = false, $noDevMode = false) { $packages = $this->loadPackages($rootDirectory); $evm = new EventDispatcher(new Composer(), $this->io); $generator = new AutoloadGenerator($evm, $this->io); $generator->setDevMode(!$noDevMode); $installationManager = new InstallationManager(); $installationManager->addInstaller(new FiddlerInstaller()); $this->io->write('Building fiddler.json projects.'); foreach ($packages as $packageName => $config) { if (strpos($packageName, 'vendor') === 0) { continue; } $this->io->write(' [Build] <info>' . $packageName . '</info>'); $mainPackage = new Package($packageName, "@stable", "@stable"); $mainPackage->setType('fiddler'); $mainPackage->setAutoload($config['autoload']); $mainPackage->setDevAutoload($config['autoload-dev']); $localRepo = new FiddlerInstalledRepository(); $this->resolvePackageDependencies($localRepo, $packages, $packageName); $composerConfig = new Config(true, $rootDirectory); $composerConfig->merge(array('config' => array('vendor-dir' => $config['path'] . '/vendor'))); $generator->dump($composerConfig, $localRepo, $mainPackage, $installationManager, 'composer', $optimize); } }
public function setUp() { $this->filesystem = new Filesystem(); $this->composer = new Composer(); $this->config = new Config(); $this->io = new NullIO(); $this->componentDir = realpath(sys_get_temp_dir()) . DIRECTORY_SEPARATOR . 'component-installer-componentDir'; $this->vendorDir = realpath(sys_get_temp_dir()) . DIRECTORY_SEPARATOR . 'component-installer-vendorDir'; $this->binDir = realpath(sys_get_temp_dir()) . DIRECTORY_SEPARATOR . 'component-installer-binDir'; foreach (array($this->componentDir, $this->vendorDir, $this->binDir) as $dir) { if (is_dir($dir)) { $this->filesystem->removeDirectory($dir); } $this->filesystem->ensureDirectoryExists($dir); } $this->config->merge(array('config' => array('vendor-dir' => $this->vendorDir, 'component-dir' => $this->componentDir, 'bin-dir' => $this->binDir))); $this->composer->setConfig($this->config); // Set up the Installation Manager. $this->installationManager = new InstallationManager(); $this->installationManager->addInstaller(new LibraryInstaller($this->io, $this->composer)); $this->installationManager->addInstaller(new Installer($this->io, $this->composer)); $this->composer->setInstallationManager($this->installationManager); }
public function build($rootDirectory, $optimize = false, $noDevMode = false) { $this->io->write(sprintf('<info>Generating autoload files for monorepo sub-packages %s dev-dependencies.</info>', $noDevMode ? 'without' : 'with')); $start = microtime(true); $packages = $this->loadPackages($rootDirectory); $evm = new EventDispatcher(new Composer(), $this->io); $generator = new AutoloadGenerator($evm, $this->io); $generator->setDevMode(!$noDevMode); $installationManager = new InstallationManager(); $installationManager->addInstaller(new MonorepoInstaller()); foreach ($packages as $packageName => $config) { if (strpos($packageName, 'vendor') === 0) { continue; } $this->io->write(sprintf(' [Subpackage] <comment>%s</comment>', $packageName)); $mainPackage = new Package($packageName, "@stable", "@stable"); $mainPackage->setType('monorepo'); $mainPackage->setAutoload($config['autoload']); $mainPackage->setDevAutoload($config['autoload-dev']); $localRepo = new MonorepoInstalledRepository(); $this->resolvePackageDependencies($localRepo, $packages, $packageName); $composerConfig = new Config(true, $rootDirectory); $composerConfig->merge(array('config' => array('vendor-dir' => $config['path'] . '/vendor'))); $generator->dump($composerConfig, $localRepo, $mainPackage, $installationManager, 'composer', $optimize); $binDir = $config['path'] . '/vendor/bin'; // remove old symlinks array_map('unlink', glob($binDir . '/*')); foreach ($localRepo->getPackages() as $package) { foreach ($package->getBinaries() as $binary) { if (!is_dir($binDir)) { mkdir($binDir, 0755, true); } $binFile = $binDir . '/' . basename($binary); symlink($rootDirectory . '/' . $binary, $binFile); } } } $duration = microtime(true) - $start; $this->io->write(sprintf('Monorepo subpackage autoloads generated in <comment>%0.2f</comment> seconds.', $duration)); }
public function build($rootDirectory, $optimize = false, $noDevMode = false) { $packages = $this->loadPackages($rootDirectory); $evm = new EventDispatcher(new Composer(), $this->io); $generator = new AutoloadGenerator($evm, $this->io); $generator->setDevMode(!$noDevMode); $installationManager = new InstallationManager(); $installationManager->addInstaller(new FiddlerInstaller()); $this->io->write('Building fiddler.json projects.'); foreach ($packages as $packageName => $config) { if (strpos($packageName, 'vendor') === 0) { continue; } $this->io->write(' [Build] <info>' . $packageName . '</info>'); $mainPackage = new Package($packageName, "@stable", "@stable"); $mainPackage->setType('fiddler'); $mainPackage->setAutoload($config['autoload']); $mainPackage->setDevAutoload($config['autoload-dev']); $localRepo = new FiddlerInstalledRepository(); $this->resolvePackageDependencies($localRepo, $packages, $packageName); $composerConfig = new Config(true, $rootDirectory); $composerConfig->merge(array('config' => array('vendor-dir' => $config['path'] . '/vendor'))); $generator->dump($composerConfig, $localRepo, $mainPackage, $installationManager, 'composer', $optimize); $binDir = $config['path'] . '/vendor/bin'; // remove old symlinks array_map('unlink', glob($binDir . '/*')); foreach ($localRepo->getPackages() as $package) { foreach ($package->getBinaries() as $binary) { if (!is_dir($binDir)) { mkdir($binDir, 0755, true); } $binFile = $binDir . '/' . basename($binary); symlink($rootDirectory . '/' . $binary, $binFile); } } } }
/** * Run installation (or update) * * @return int 0 on success or a positive error code on failure * * @throws \Exception */ public function run() { gc_collect_cycles(); gc_disable(); if ($this->dryRun) { $this->verbose = true; $this->runScripts = false; $this->installationManager->addInstaller(new NoopInstaller()); $this->mockLocalRepositories($this->repositoryManager); } // TODO remove this BC feature at some point // purge old require-dev packages to avoid conflicts with the new way of handling dev requirements $devRepo = new InstalledFilesystemRepository(new JsonFile($this->config->get('vendor-dir') . '/composer/installed_dev.json')); if ($devRepo->getPackages()) { $this->io->writeError('<warning>BC Notice: Removing old dev packages to migrate to the new require-dev handling.</warning>'); foreach ($devRepo->getPackages() as $package) { if ($this->installationManager->isPackageInstalled($devRepo, $package)) { $this->installationManager->uninstall($devRepo, new UninstallOperation($package)); } } unlink($this->config->get('vendor-dir') . '/composer/installed_dev.json'); } unset($devRepo, $package); // end BC if ($this->runScripts) { // dispatch pre event $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); // clone root package to have one in the installed repo that does not require anything // we don't want it to be uninstallable, but its requirements should not conflict // with the lock file for example $installedRootPackage = clone $this->package; $installedRootPackage->setRequires(array()); $installedRootPackage->setDevRequires(array()); // create installed repo, this contains all local packages + platform packages (php & extensions) $localRepo = $this->repositoryManager->getLocalRepository(); $platformRepo = new PlatformRepository(); $repos = array($localRepo, new InstalledArrayRepository(array($installedRootPackage)), $platformRepo); $installedRepo = new CompositeRepository($repos); if ($this->additionalInstalledRepository) { $installedRepo->addRepository($this->additionalInstalledRepository); } $aliases = $this->getRootAliases(); $this->aliasPlatformPackages($platformRepo, $aliases); try { $this->suggestedPackages = array(); $res = $this->doInstall($localRepo, $installedRepo, $platformRepo, $aliases, $this->devMode); if ($res !== 0) { return $res; } } catch (\Exception $e) { $this->installationManager->notifyInstalls(); throw $e; } $this->installationManager->notifyInstalls(); // output suggestions if we're in dev mode if ($this->devMode) { foreach ($this->suggestedPackages as $suggestion) { $target = $suggestion['target']; foreach ($installedRepo->getPackages() as $package) { if (in_array($target, $package->getNames())) { continue 2; } } $this->io->writeError($suggestion['source'] . ' suggests installing ' . $suggestion['target'] . ' (' . $suggestion['reason'] . ')'); } } # Find abandoned packages and warn user foreach ($localRepo->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("<error>Package %s is abandoned, you should avoid using it. %s.</error>", $package->getPrettyName(), $replacement)); } if (!$this->dryRun) { // write lock if ($this->update || !$this->locker->isLocked()) { $localRepo->reload(); // if this is not run in dev mode and the root has dev requires, the lock must // contain null to prevent dev installs from a non-dev lock $devPackages = $this->devMode || !$this->package->getDevRequires() ? array() : null; // split dev and non-dev requirements by checking what would be removed if we update without the dev requirements if ($this->devMode && $this->package->getDevRequires()) { $policy = $this->createPolicy(); $pool = $this->createPool(true); $pool->addRepository($installedRepo, $aliases); // creating requirements request $request = $this->createRequest($pool, $this->package, $platformRepo); $request->updateAll(); foreach ($this->package->getRequires() as $link) { $request->install($link->getTarget(), $link->getConstraint()); } $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request); $solver = new Solver($policy, $pool, $installedRepo); $ops = $solver->solve($request, $this->ignorePlatformReqs); $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request, $ops); foreach ($ops as $op) { if ($op->getJobType() === 'uninstall') { $devPackages[] = $op->getPackage(); } } } $platformReqs = $this->extractPlatformRequirements($this->package->getRequires()); $platformDevReqs = $this->devMode ? $this->extractPlatformRequirements($this->package->getDevRequires()) : array(); $updatedLock = $this->locker->setLockData(array_diff($localRepo->getCanonicalPackages(), (array) $devPackages), $devPackages, $platformReqs, $platformDevReqs, $aliases, $this->package->getMinimumStability(), $this->package->getStabilityFlags(), $this->preferStable || $this->package->getPreferStable(), $this->preferLowest); if ($updatedLock) { $this->io->writeError('<info>Writing lock file</info>'); } } 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->setDevMode($this->devMode); $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader); } if ($this->runScripts) { // dispatch post event $eventName = $this->update ? ScriptEvents::POST_UPDATE_CMD : ScriptEvents::POST_INSTALL_CMD; $this->eventDispatcher->dispatchScript($eventName, $this->devMode); } $vendorDir = $this->config->get('vendor-dir'); if (is_dir($vendorDir)) { touch($vendorDir); } } return 0; }
/** * @param Installer\InstallationManager $im * @param Composer $composer * @param IO\IOInterface $io */ protected function createDefaultInstallers(Installer\InstallationManager $im, Composer $composer, IOInterface $io) { $im->addInstaller(new Installer\LibraryInstaller($io, $composer, null)); $im->addInstaller(new Installer\PearInstaller($io, $composer, 'pear-library')); $im->addInstaller(new Installer\PluginInstaller($io, $composer)); $im->addInstaller(new Installer\MetapackageInstaller($io)); }
/** * Run installation (or update) */ public function run() { if ($this->dryRun) { $this->verbose = true; $this->runScripts = false; $this->installationManager->addInstaller(new NoopInstaller()); $this->mockLocalRepositories($this->repositoryManager); } // TODO remove this BC feature at some point // purge old require-dev packages to avoid conflicts with the new way of handling dev requirements $devRepo = new InstalledFilesystemRepository(new JsonFile($this->config->get('vendor-dir') . '/composer/installed_dev.json')); if ($devRepo->getPackages()) { $this->io->write('<warning>BC Notice: Removing old dev packages to migrate to the new require-dev handling.</warning>'); foreach ($devRepo->getPackages() as $package) { if ($this->installationManager->isPackageInstalled($devRepo, $package)) { $this->installationManager->uninstall($devRepo, new UninstallOperation($package)); } } unlink($this->config->get('vendor-dir') . '/composer/installed_dev.json'); } unset($devRepo, $package); // end BC if ($this->preferSource) { $this->downloadManager->setPreferSource(true); } if ($this->preferDist) { $this->downloadManager->setPreferDist(true); } // create installed repo, this contains all local packages + platform packages (php & extensions) $installedRootPackage = clone $this->package; $installedRootPackage->setRequires(array()); $installedRootPackage->setDevRequires(array()); $localRepo = $this->repositoryManager->getLocalRepository(); $platformRepo = new PlatformRepository(); $repos = array($localRepo, new InstalledArrayRepository(array($installedRootPackage)), $platformRepo); $installedRepo = new CompositeRepository($repos); if ($this->additionalInstalledRepository) { $installedRepo->addRepository($this->additionalInstalledRepository); } $aliases = $this->getRootAliases(); $this->aliasPlatformPackages($platformRepo, $aliases); if ($this->runScripts) { // dispatch pre event $eventName = $this->update ? ScriptEvents::PRE_UPDATE_CMD : ScriptEvents::PRE_INSTALL_CMD; $this->eventDispatcher->dispatchCommandEvent($eventName, $this->devMode); } try { $this->suggestedPackages = array(); if (!$this->doInstall($localRepo, $installedRepo, $platformRepo, $aliases, $this->devMode)) { return false; } } catch (\Exception $e) { $this->installationManager->notifyInstalls(); throw $e; } $this->installationManager->notifyInstalls(); // output suggestions foreach ($this->suggestedPackages as $suggestion) { $target = $suggestion['target']; foreach ($installedRepo->getPackages() as $package) { if (in_array($target, $package->getNames())) { continue 2; } } $this->io->write($suggestion['source'] . ' suggests installing ' . $suggestion['target'] . ' (' . $suggestion['reason'] . ')'); } if (!$this->dryRun) { // write lock if ($this->update || !$this->locker->isLocked()) { $localRepo->reload(); // if this is not run in dev mode and the root has dev requires, the lock must // contain null to prevent dev installs from a non-dev lock $devPackages = $this->devMode || !$this->package->getDevRequires() ? array() : null; // split dev and non-dev requirements by checking what would be removed if we update without the dev requirements if ($this->devMode && $this->package->getDevRequires()) { $policy = $this->createPolicy(); $pool = $this->createPool(); $pool->addRepository($installedRepo, $aliases); // creating requirements request $request = $this->createRequest($pool, $this->package, $platformRepo); $request->updateAll(); foreach ($this->package->getRequires() as $link) { $request->install($link->getTarget(), $link->getConstraint()); } $solver = new Solver($policy, $pool, $installedRepo); $ops = $solver->solve($request); foreach ($ops as $op) { if ($op->getJobType() === 'uninstall') { $devPackages[] = $op->getPackage(); } } } $platformReqs = $this->extractPlatformRequirements($this->package->getRequires()); $platformDevReqs = $this->devMode ? $this->extractPlatformRequirements($this->package->getDevRequires()) : array(); $updatedLock = $this->locker->setLockData(array_diff($localRepo->getPackages(), (array) $devPackages), $devPackages, $platformReqs, $platformDevReqs, $aliases, $this->package->getMinimumStability(), $this->package->getStabilityFlags()); if ($updatedLock) { $this->io->write('<info>Writing lock file</info>'); } } // write autoloader $this->io->write('<info>Generating autoload files</info>'); $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader); if ($this->runScripts) { // dispatch post event $eventName = $this->update ? ScriptEvents::POST_UPDATE_CMD : ScriptEvents::POST_INSTALL_CMD; $this->eventDispatcher->dispatchCommandEvent($eventName, $this->devMode); } } return true; }
/** * Run installation (or update) * * @throws \Exception * @return int 0 on success or a positive error code on failure */ public function run() { // 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(); // Force update if there is no lock file present if (!$this->update && !$this->locker->isLocked()) { $this->update = true; } if ($this->dryRun) { $this->verbose = true; $this->runScripts = false; $this->installationManager->addInstaller(new NoopInstaller()); $this->mockLocalRepositories($this->repositoryManager); } if ($this->runScripts) { // dispatch pre event $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); // create installed repo, this contains all local packages + platform packages (php & extensions) $localRepo = $this->repositoryManager->getLocalRepository(); if ($this->update) { $platformOverrides = $this->config->get('platform') ?: array(); } else { $platformOverrides = $this->locker->getPlatformOverrides(); } $platformRepo = new PlatformRepository(array(), $platformOverrides); $installedRepo = $this->createInstalledRepo($localRepo, $platformRepo); $aliases = $this->getRootAliases(); $this->aliasPlatformPackages($platformRepo, $aliases); if (!$this->suggestedPackagesReporter) { $this->suggestedPackagesReporter = new SuggestedPackagesReporter($this->io); } try { list($res, $devPackages) = $this->doInstall($localRepo, $installedRepo, $platformRepo, $aliases); if ($res !== 0) { return $res; } } catch (\Exception $e) { if (!$this->dryRun) { $this->installationManager->notifyInstalls($this->io); } throw $e; } if (!$this->dryRun) { $this->installationManager->notifyInstalls($this->io); } // output suggestions if we're in dev mode if ($this->devMode && !$this->skipSuggest) { $this->suggestedPackagesReporter->output($installedRepo); } # Find abandoned packages and warn user foreach ($localRepo->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->dryRun) { // write lock if ($this->update) { $localRepo->reload(); $platformReqs = $this->extractPlatformRequirements($this->package->getRequires()); $platformDevReqs = $this->extractPlatformRequirements($this->package->getDevRequires()); $updatedLock = $this->locker->setLockData(array_diff($localRepo->getCanonicalPackages(), $devPackages), $devPackages, $platformReqs, $platformDevReqs, $aliases, $this->package->getMinimumStability(), $this->package->getStabilityFlags(), $this->preferStable || $this->package->getPreferStable(), $this->preferLowest, $this->config->get('platform') ?: array()); if ($updatedLock) { $this->io->writeError('<info>Writing lock file</info>'); } } 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->setDevMode($this->devMode); $this->autoloadGenerator->setClassMapAuthoritative($this->classMapAuthoritative); $this->autoloadGenerator->setRunScripts($this->runScripts); $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader); } if ($this->runScripts) { $devMode = (int) $this->devMode; putenv("COMPOSER_DEV_MODE={$devMode}"); // dispatch post event $eventName = $this->update ? ScriptEvents::POST_UPDATE_CMD : ScriptEvents::POST_INSTALL_CMD; $this->eventDispatcher->dispatchScript($eventName, $this->devMode); } // force binaries re-generation in case they are missing foreach ($localRepo->getPackages() as $package) { $this->installationManager->ensureBinariesPresence($package); } $vendorDir = $this->config->get('vendor-dir'); if (is_dir($vendorDir)) { // suppress errors as this fails sometimes on OSX for no apparent reason // see https://github.com/composer/composer/issues/4070#issuecomment-129792748 @touch($vendorDir); } } // re-enable GC except on HHVM which triggers a warning here if (!defined('HHVM_VERSION')) { gc_enable(); } return 0; }
/** * Run installation (or update) * * @throws \Exception * @return int 0 on success or a positive error code on failure */ public function run() { // 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->dryRun) { $this->verbose = true; $this->runScripts = false; $this->installationManager->addInstaller(new NoopInstaller()); $this->mockLocalRepositories($this->repositoryManager); } if ($this->runScripts) { // dispatch pre event $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); // clone root package to have one in the installed repo that does not require anything // we don't want it to be uninstallable, but its requirements should not conflict // with the lock file for example $installedRootPackage = clone $this->package; $installedRootPackage->setRequires(array()); $installedRootPackage->setDevRequires(array()); // create installed repo, this contains all local packages + platform packages (php & extensions) $localRepo = $this->repositoryManager->getLocalRepository(); if (!$this->update && $this->locker->isLocked()) { $platformOverrides = $this->locker->getPlatformOverrides(); } else { $platformOverrides = $this->config->get('platform') ?: array(); } $platformRepo = new PlatformRepository(array(), $platformOverrides); $repos = array($localRepo, new InstalledArrayRepository(array($installedRootPackage)), $platformRepo); $installedRepo = new CompositeRepository($repos); if ($this->additionalInstalledRepository) { $installedRepo->addRepository($this->additionalInstalledRepository); } $aliases = $this->getRootAliases(); $this->aliasPlatformPackages($platformRepo, $aliases); try { $this->suggestedPackages = array(); $res = $this->doInstall($localRepo, $installedRepo, $platformRepo, $aliases, $this->devMode); if ($res !== 0) { return $res; } } catch (\Exception $e) { if (!$this->dryRun) { $this->installationManager->notifyInstalls($this->io); } throw $e; } if (!$this->dryRun) { $this->installationManager->notifyInstalls($this->io); } // output suggestions if we're in dev mode if ($this->devMode) { foreach ($this->suggestedPackages as $suggestion) { $target = $suggestion['target']; foreach ($installedRepo->getPackages() as $package) { if (in_array($target, $package->getNames())) { continue 2; } } $this->io->writeError($suggestion['source'] . ' suggests installing ' . $suggestion['target'] . ' (' . $suggestion['reason'] . ')'); } } # Find abandoned packages and warn user foreach ($localRepo->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->dryRun) { // write lock if ($this->update || !$this->locker->isLocked()) { $localRepo->reload(); // if this is not run in dev mode and the root has dev requires, the lock must // contain null to prevent dev installs from a non-dev lock $devPackages = $this->devMode || !$this->package->getDevRequires() ? array() : null; // split dev and non-dev requirements by checking what would be removed if we update without the dev requirements if ($this->devMode && $this->package->getDevRequires()) { $policy = $this->createPolicy(); $pool = $this->createPool(true); $pool->addRepository($installedRepo, $aliases); // creating requirements request $request = $this->createRequest($this->package, $platformRepo); $request->updateAll(); foreach ($this->package->getRequires() as $link) { $request->install($link->getTarget(), $link->getConstraint()); } $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request); $solver = new Solver($policy, $pool, $installedRepo); $ops = $solver->solve($request, $this->ignorePlatformReqs); $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request, $ops); foreach ($ops as $op) { if ($op->getJobType() === 'uninstall') { $devPackages[] = $op->getPackage(); } } } $platformReqs = $this->extractPlatformRequirements($this->package->getRequires()); $platformDevReqs = $this->devMode ? $this->extractPlatformRequirements($this->package->getDevRequires()) : array(); $updatedLock = $this->locker->setLockData(array_diff($localRepo->getCanonicalPackages(), (array) $devPackages), $devPackages, $platformReqs, $platformDevReqs, $aliases, $this->package->getMinimumStability(), $this->package->getStabilityFlags(), $this->preferStable || $this->package->getPreferStable(), $this->preferLowest, $this->config->get('platform') ?: array()); if ($updatedLock) { $this->io->writeError('<info>Writing lock file</info>'); } } 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->setDevMode($this->devMode); $this->autoloadGenerator->setClassMapAuthoritative($this->classMapAuthoritative); $this->autoloadGenerator->setRunScripts($this->runScripts); $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader); } if ($this->runScripts) { // dispatch post event $eventName = $this->update ? ScriptEvents::POST_UPDATE_CMD : ScriptEvents::POST_INSTALL_CMD; $this->eventDispatcher->dispatchScript($eventName, $this->devMode); } $vendorDir = $this->config->get('vendor-dir'); if (is_dir($vendorDir)) { // suppress errors as this fails sometimes on OSX for no apparent reason // see https://github.com/composer/composer/issues/4070#issuecomment-129792748 @touch($vendorDir); } } // re-enable GC except on HHVM which triggers a warning here if (!defined('HHVM_VERSION')) { gc_enable(); } return 0; }
protected function createInstallationManager(Repository\RepositoryManager $rm, Downloader\DownloadManager $dm, $vendorDir, $binDir, IOInterface $io) { $im = new Installer\InstallationManager($vendorDir); $im->addInstaller(new Installer\LibraryInstaller($vendorDir, $binDir, $dm, $rm->getLocalRepository(), $io, null)); $im->addInstaller(new Installer\InstallerInstaller($vendorDir, $binDir, $dm, $rm->getLocalRepository(), $io, $im)); return $im; }
/** * @test * * @depends testInstallerCreationShouldNotCreateVendorDirectory * @depends testInstallerCreationShouldNotCreateBinDirectory */ public function updateDevelopmentToStable() { $initial = $this->createDevelopmentPackageMock(); $target = $this->createStablePackageMock(); $installer = new SharedPackageInstaller($this->io, $this->composer, $this->fs, $this->dataManager); $defaultInstaller = $this->getMockBuilder('Composer\\Installer\\LibraryInstaller')->disableOriginalConstructor()->getMock(); $defaultInstaller->expects($this->once())->method('install'); $im = new InstallationManager(); $im->addInstaller(new SharedPackageInstallerSolver($installer, $defaultInstaller)); $this->composer->setInstallationManager($im); $initial->expects($this->any())->method('getPrettyName')->will($this->returnValue('initial-package')); $initial->expects($this->once())->method('getType')->willReturn('shared-package'); $target->expects($this->once())->method('getType')->willReturn('shared-package'); $target->expects($this->any())->method('getPrettyName')->will($this->returnValue('package1')); $target->expects($this->any())->method('getTargetDir')->will($this->returnValue('newtarget')); $this->repository->expects($this->exactly(1))->method('hasPackage')->will($this->onConsecutiveCalls(true, true, false, false)); $installer->update($this->repository, $initial, $target); $this->assertFileExists($this->vendorDir, 'Vendor dir should be created'); $this->assertFileExists($this->binDir, 'Bin dir should be created'); $this->assertFileExists($this->dependenciesDir, 'Dependencies dir should be created'); $this->assertFileNotExists($this->symlinkDir, 'Symlink dir should be created'); $this->assertFalse(is_link($this->symlinkDir . '/letudiant/foo-bar')); }
public function testInstallBinary() { $installer = $this->getMockBuilder('Composer\\Installer\\LibraryInstaller')->disableOriginalConstructor()->getMock(); $manager = new InstallationManager(); $manager->addInstaller($installer); $package = $this->createPackageMock(); $package->expects($this->once())->method('getType')->will($this->returnValue('library')); $installer->expects($this->once())->method('supports')->with('library')->will($this->returnValue(true)); $installer->expects($this->once())->method('ensureBinariesPresence')->with($package); $manager->ensureBinariesPresence($package); }
public function testUninstall() { $installer = $this->createInstallerMock(); $manager = new InstallationManager('vendor'); $manager->addInstaller($installer); $package = $this->createPackageMock(); $operation = new UninstallOperation($package, 'test'); $package->expects($this->once())->method('getType')->will($this->returnValue('library')); $installer->expects($this->once())->method('uninstall')->with($this->repository, $package); $installer->expects($this->once())->method('supports')->with('library')->will($this->returnValue(true)); $manager->uninstall($this->repository, $operation); }