/** * 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; }
/** * @test */ public function uninstallKeepSources() { $this->io->expects($this->once())->method('askConfirmation')->willReturn(false); /** @var SymlinkFilesystem|\PHPUnit_Framework_MockObject_MockObject $filesystem */ $filesystem = $this->getMock('\\LEtudiant\\Composer\\Util\\SymlinkFilesystem'); $filesystem->expects($this->once())->method('removeSymlink')->willReturn(true); $installer = $this->createInstaller($this->config, $filesystem); $package = $this->createPackageMock(); $this->repository->expects($this->once())->method('removePackage')->with($package); $this->dm->expects($this->never())->method('remove'); $this->dataManager->expects($this->once())->method('removePackageUsage')->with($package); $installer->uninstall($this->repository, $package); }
/** * @test */ public function uninstallDevelopment() { $this->io->expects($this->once())->method('askConfirmation')->willReturn(true); /** @var SymlinkFilesystem|\PHPUnit_Framework_MockObject_MockObject $filesystem */ $filesystem = $this->getMock('\\LEtudiant\\Composer\\Util\\SymlinkFilesystem'); $filesystem->expects($this->once())->method('removeSymlink')->willReturn(true); $library = new SharedPackageInstaller($this->io, $this->composer, $filesystem, $this->dataManager); $package = $this->createDevelopmentPackageMock(); $this->repository->expects($this->exactly(1))->method('hasPackage')->with($package)->will($this->onConsecutiveCalls(true, true)); $this->repository->expects($this->once())->method('removePackage')->with($package); $this->dm->expects($this->once())->method('remove')->with($package, $this->dependenciesDir . '/letudiant/foo-bar/dev-develop'); $this->dataManager->expects($this->once())->method('removePackageUsage')->with($package); $library->uninstall($this->repository, $package); }
/** * 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; }
/** * @param IO\IOInterface $io * @param Config $config * @return Downloader\DownloadManager */ public function createDownloadManager(IOInterface $io, Config $config) { $cache = null; if ($config->get('cache-files-ttl') > 0) { $cache = new Cache($io, $config->get('cache-files-dir'), 'a-z0-9_./'); } $dm = new Downloader\DownloadManager(); $dm->setDownloader('git', new Downloader\GitDownloader($io, $config)); $dm->setDownloader('svn', new Downloader\SvnDownloader($io, $config)); $dm->setDownloader('hg', new Downloader\HgDownloader($io, $config)); $dm->setDownloader('zip', new Downloader\ZipDownloader($io, $config, $cache)); $dm->setDownloader('tar', new Downloader\TarDownloader($io, $config, $cache)); $dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $cache)); $dm->setDownloader('file', new Downloader\FileDownloader($io, $config, $cache)); return $dm; }
/** * Download or update a package. * * @param Composer $composer * @param PackageInterface $package * @param OutputInterface $output * @param string $targetDir * @param PackageInterface $initialPackage */ protected function fetchPackage(DownloadManager $manager, PackageInterface $package, $targetDir, PackageInterface $initialPackage = null) { // Better to download the sources $manager->setPreferSource(true); if (null !== $initialPackage) { $manager->update($initialPackage, $package, $targetDir); } else { $manager->download($package, $targetDir); } }
/** * @param \Composer\Package\PackageInterface $package */ protected function removeCode(\Composer\Package\PackageInterface $package) { $downloadPath = $this->getInstallPath($package); $this->downloadManager->remove($package, $downloadPath); }
/** * @param PackageInterface $package */ protected function removeCode(PackageInterface $package) { $this->downloadManager->remove($package, $this->getInstallPath($package)); }
public function testBadPackageDownloadWithSourcePreferred() { $package = $this->createPackageMock(); $package->expects($this->once())->method('getSourceType')->will($this->returnValue(null)); $package->expects($this->once())->method('getDistType')->will($this->returnValue(null)); $manager = new DownloadManager(false, $this->filesystem); $manager->setPreferSource(true); $this->setExpectedException('InvalidArgumentException'); $manager->download($package, 'target_dir'); }
/** * Run installation (or update) * * @param Boolean $preferSource * @param Boolean $dryRun * @param Boolean $verbose * @param Boolean $noInstallRecommends * @param Boolean $installSuggests * @param Boolean $update * @param RepositoryInterface $additionalInstalledRepository */ public function run($preferSource = false, $dryRun = false, $verbose = false, $noInstallRecommends = false, $installSuggests = false, $update = false, RepositoryInterface $additionalInstalledRepository = null) { if ($dryRun) { $verbose = true; } if ($preferSource) { $this->downloadManager->setPreferSource(true); } $this->repositoryManager = $this->repositoryManager; // create local repo, this contains all packages that are installed in the local project $localRepo = $this->repositoryManager->getLocalRepository(); // create installed repo, this contains all local packages + platform packages (php & extensions) $installedRepo = new CompositeRepository(array($localRepo, new PlatformRepository())); if ($additionalInstalledRepository) { $installedRepo->addRepository($additionalInstalledRepository); } // prepare aliased packages if (!$update && $this->locker->isLocked()) { $aliases = $this->locker->getAliases(); } else { $aliases = $this->package->getAliases(); } foreach ($aliases as $alias) { foreach ($this->repositoryManager->findPackages($alias['package'], $alias['version']) as $package) { $package->getRepository()->addPackage(new AliasPackage($package, $alias['alias_normalized'], $alias['alias'])); } foreach ($this->repositoryManager->getLocalRepository()->findPackages($alias['package'], $alias['version']) as $package) { $this->repositoryManager->getLocalRepository()->addPackage(new AliasPackage($package, $alias['alias_normalized'], $alias['alias'])); $this->repositoryManager->getLocalRepository()->removePackage($package); } } // creating repository pool $pool = new Pool(); $pool->addRepository($installedRepo); foreach ($this->repositoryManager->getRepositories() as $repository) { $pool->addRepository($repository); } // dispatch pre event if (!$dryRun) { $eventName = $update ? ScriptEvents::PRE_UPDATE_CMD : ScriptEvents::PRE_INSTALL_CMD; $this->eventDispatcher->dispatchCommandEvent($eventName); } // creating requirements request $installFromLock = false; $request = new Request($pool); if ($update) { $this->io->write('<info>Updating dependencies</info>'); $request->updateAll(); $links = $this->collectLinks($noInstallRecommends, $installSuggests); foreach ($links as $link) { $request->install($link->getTarget(), $link->getConstraint()); } } elseif ($this->locker->isLocked()) { $installFromLock = true; $this->io->write('<info>Installing from lock file</info>'); if (!$this->locker->isFresh()) { $this->io->write('<warning>Your lock file is out of sync with your composer.json, run "composer.phar update" to update dependencies</warning>'); } foreach ($this->locker->getLockedPackages() as $package) { $version = $package->getVersion(); foreach ($aliases as $alias) { if ($alias['package'] === $package->getName() && $alias['version'] === $package->getVersion()) { $version = $alias['alias']; break; } } $constraint = new VersionConstraint('=', $version); $request->install($package->getName(), $constraint); } } else { $this->io->write('<info>Installing dependencies</info>'); $links = $this->collectLinks($noInstallRecommends, $installSuggests); foreach ($links as $link) { $request->install($link->getTarget(), $link->getConstraint()); } } // prepare solver $policy = new DefaultPolicy(); $solver = new Solver($policy, $pool, $installedRepo); // solve dependencies $operations = $solver->solve($request); // force dev packages to be updated to latest reference on update if ($update) { foreach ($localRepo->getPackages() as $package) { if ($package instanceof AliasPackage) { $package = $package->getAliasOf(); } // skip non-dev packages if (!$package->isDev()) { continue; } // skip packages that will be updated/uninstalled foreach ($operations as $operation) { if ('update' === $operation->getJobType() && $package === $operation->getInitialPackage() || 'uninstall' === $operation->getJobType() && $package === $operation->getPackage()) { continue 2; } } // force update $newPackage = $this->repositoryManager->findPackage($package->getName(), $package->getVersion()); if ($newPackage && $newPackage->getSourceReference() !== $package->getSourceReference()) { $operations[] = new UpdateOperation($package, $newPackage); } } } // anti-alias local repository to allow updates to work fine foreach ($this->repositoryManager->getLocalRepository()->getPackages() as $package) { if ($package instanceof AliasPackage) { $this->repositoryManager->getLocalRepository()->addPackage(clone $package->getAliasOf()); $this->repositoryManager->getLocalRepository()->removePackage($package); } } // execute operations if (!$operations) { $this->io->write('<info>Nothing to install/update</info>'); } foreach ($operations as $operation) { if ($verbose) { $this->io->write((string) $operation); } if (!$dryRun) { $this->eventDispatcher->dispatchPackageEvent(constant('Composer\\Script\\ScriptEvents::PRE_PACKAGE_' . strtoupper($operation->getJobType())), $operation); // if installing from lock, restore dev packages' references to their locked state if ($installFromLock) { $package = null; if ('update' === $operation->getJobType()) { $package = $operation->getTargetPackage(); } elseif ('install' === $operation->getJobType()) { $package = $operation->getPackage(); } if ($package && $package->isDev()) { $lockData = $this->locker->getLockData(); foreach ($lockData['packages'] as $lockedPackage) { if (!empty($lockedPackage['source-reference']) && strtolower($lockedPackage['package']) === $package->getName()) { $package->setSourceReference($lockedPackage['source-reference']); break; } } } } $this->installationManager->execute($operation); $this->eventDispatcher->dispatchPackageEvent(constant('Composer\\Script\\ScriptEvents::POST_PACKAGE_' . strtoupper($operation->getJobType())), $operation); } } if (!$dryRun) { if ($update || !$this->locker->isLocked()) { $this->locker->setLockData($localRepo->getPackages(), $aliases); $this->io->write('<info>Writing lock file</info>'); } $localRepo->write(); $this->io->write('<info>Generating autoload files</info>'); $generator = new AutoloadGenerator(); $generator->dump($localRepo, $this->package, $this->installationManager, $this->installationManager->getVendorPath() . '/.composer'); // dispatch post event $eventName = $update ? ScriptEvents::POST_UPDATE_CMD : ScriptEvents::POST_INSTALL_CMD; $this->eventDispatcher->dispatchCommandEvent($eventName); } }
public function createDownloadManager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null) { $cache = null; if ($config->get('cache-files-ttl') > 0) { $cache = new Cache($io, $config->get('cache-files-dir'), 'a-z0-9_./'); } $dm = new Downloader\DownloadManager(); switch ($config->get('preferred-install')) { case 'dist': $dm->setPreferDist(true); break; case 'source': $dm->setPreferSource(true); break; case 'auto': default: break; } $dm->setDownloader('git', new Downloader\GitDownloader($io, $config)); $dm->setDownloader('svn', new Downloader\SvnDownloader($io, $config)); $dm->setDownloader('hg', new Downloader\HgDownloader($io, $config)); $dm->setDownloader('perforce', new Downloader\PerforceDownloader($io, $config)); $dm->setDownloader('zip', new Downloader\ZipDownloader($io, $config, $eventDispatcher, $cache)); $dm->setDownloader('rar', new Downloader\RarDownloader($io, $config, $eventDispatcher, $cache)); $dm->setDownloader('tar', new Downloader\TarDownloader($io, $config, $eventDispatcher, $cache)); $dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $eventDispatcher, $cache)); $dm->setDownloader('file', new Downloader\FileDownloader($io, $config, $eventDispatcher, $cache)); return $dm; }
/** * Runs the script: connect to packagist, download everything it can! */ public function run() { // TODO: each package is there twice. Find why. $filesystem = new Filesystem(); if (file_exists(DOWNLOAD_DIR . "/last_analyzed_package")) { $lastAnalyzedPackage = file_get_contents(DOWNLOAD_DIR . "/last_analyzed_package"); } else { $lastAnalyzedPackage = ""; } $providerNames = $this->packagistRepository->getProviderNames(); // If analyzis is over, let's start from the beginning again. if ($lastAnalyzedPackage >= $providerNames[count($providerNames) - 1]) { $lastAnalyzedPackage = ''; } $this->logger->debug("Starting script."); $found = false; sort($providerNames); foreach ($providerNames as $packageName) { if ($this->forcedPackage && $this->forcedPackage != $packageName) { continue; } else { $found = true; } if (!$this->forcedPackage && $packageName <= $lastAnalyzedPackage) { continue; } // Let's write the name of the last package we are going to analyze // We will use it to start again from next package in case this package fails. if (!$this->forcedPackage) { file_put_contents(DOWNLOAD_DIR . "/last_analyzed_package", $packageName); } $this->logger->debug("Analyzing {packageName}.", array("packageName" => $packageName)); //if ($packageName != '10up/wp_mock') continue; //var_dump($packagistRepo->findPackages($packageName)); $packages = $this->packagistRepository->findPackages($packageName); $packages = array_filter($packages, function ($package) use($packageName) { return $package->getName() == $packageName; }); // Warning: findPackages uses "whatProvides". For instance: symfony/symonfy provides symfony/finder. // When a new version of finder is released, we don't want to remove symfony. Therefore, we need to restrict // the packages returned by "findPackages" $importantPackages = $this->getImportantVersions($packages); // DELETE PACKAGES VERSION BEFORE REINSERTION! // Only delete packages that are not important anymore. $notImportantPackages = array_diff($packages, $importantPackages); foreach ($notImportantPackages as $notImportantPackage) { if ($this->packageDao->get($notImportantPackage->getName(), $notImportantPackage->getPrettyVersion())) { $this->logger->info("Removing {packageName} {version}. A newer package is available.", array("packageName" => $notImportantPackage->getPrettyName(), "version" => $notImportantPackage->getPrettyVersion())); $this->itemDao->deletePackage($notImportantPackage->getName(), $notImportantPackage->getPrettyVersion()); $this->packageDao->deletePackage($notImportantPackage->getName(), $notImportantPackage->getPrettyVersion()); $downloadPath = DOWNLOAD_DIR . "/" . $notImportantPackage->getName() . "/" . $notImportantPackage->getPrettyVersion(); $filesystem->removeDirectory($downloadPath); } } foreach ($importantPackages as $package) { /* @var $package PackageInterface */ try { // Let's reset to null (in case an exception happens on first line). $packageVersionEntity = null; // Let's get the update date of each version and let's compare it with the one we stored. $packageVersion = $this->packageDao->get($package->getName(), $package->getPrettyVersion()); if (!$this->force && (!isset($packageVersion['refresh']) || !$packageVersion['refresh'])) { if ($packageVersion && $packageVersion['releaseDate']->sec == $package->getReleaseDate()->getTimestamp()) { if (isset($packageVersion['onError'])) { if ($packageVersion['onError'] == false || $packageVersion['onError'] == true && !$this->retryOnError) { $this->logger->debug("{packageName} {version} has not moved since last run. Ignoring.", array("packageName" => $package->getPrettyName(), "version" => $package->getPrettyVersion())); continue; } } } } $this->itemDao->deletePackage($package->getName(), $package->getPrettyVersion()); $this->packageDao->deletePackage($package->getName(), $package->getPrettyVersion()); $this->logger->info("Downloading {packageName} {version}{additional}", array("packageName" => $package->getPrettyName(), "version" => $package->getPrettyVersion(), "additional" => isset($packageVersion['refresh']) && $packageVersion['refresh'] ? " (forced via force-refresh)" : "")); //var_dump($package->getDistUrls()); //var_dump($package->getSourceUrls()); $downloadPath = DOWNLOAD_DIR . "/" . $package->getName() . "/" . $package->getPrettyVersion(); $this->downloadManager->download($package, $downloadPath); $packageVersion = $this->packageDao->createOrUpdatePackage($package); $this->classesDetector->storePackage($downloadPath, $packageVersion); $packageVersion['onError'] = false; $packageVersion['errorMsg'] = ''; unset($packageVersion['refresh']); } catch (\Exception $e) { if (!$packageVersion) { $packageVersion = $this->packageDao->createOrUpdatePackage($package); } $this->logger->error("Package {packageName} {version} failed to download. Exception: " . $e->getMessage() . " - " . $e->getTraceAsString(), array("packageName" => $package->getName(), "version" => $package->getPrettyVersion(), "exception" => $e)); $packageVersion['packageName'] = $package->getName(); $packageVersion['packageVersion'] = $package->getPrettyVersion(); $packageVersion['onError'] = true; $packageVersion['errorMsg'] = $e->getMessage() . "\n" . $e->getTraceAsString(); } $this->packageDao->save($packageVersion); } } if ($this->forcedPackage && !$found) { $this->logger->error("Unable to find package '{packageName}'", ['packageName' => $this->forcedPackage]); } //var_dump("Nb packages: ".count($repositories->getPackages())); }
/** * 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; }
/** * @param Package $package * @return $this */ public function download(Package $package) { $this->downloadManager->download($package, DIRECTORY_SEPARATOR . $package->getTargetDir(), false); return $this; }
/** * @param IO\IOInterface $io * @param Config $config * @param EventDispatcher $eventDispatcher * @return Downloader\DownloadManager */ public function createDownloadManager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null) { $cache = null; if ($config->get('cache-files-ttl') > 0) { $cache = new Cache($io, $config->get('cache-files-dir'), 'a-z0-9_./'); } $dm = new Downloader\DownloadManager($io); switch ($config->get('preferred-install')) { case 'dist': $dm->setPreferDist(true); break; case 'source': $dm->setPreferSource(true); break; case 'auto': default: // noop break; } $executor = new ProcessExecutor($io); $fs = new Filesystem($executor); $dm->setDownloader('git', new Downloader\GitDownloader($io, $config, $executor, $fs)); $dm->setDownloader('svn', new Downloader\SvnDownloader($io, $config, $executor, $fs)); $dm->setDownloader('hg', new Downloader\HgDownloader($io, $config, $executor, $fs)); $dm->setDownloader('perforce', new Downloader\PerforceDownloader($io, $config)); $dm->setDownloader('zip', new Downloader\ZipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs)); $dm->setDownloader('rar', new Downloader\RarDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs)); $dm->setDownloader('tar', new Downloader\TarDownloader($io, $config, $eventDispatcher, $cache, $rfs)); $dm->setDownloader('gzip', new Downloader\GzipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs)); $dm->setDownloader('xz', new Downloader\XzDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs)); $dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $eventDispatcher, $cache, $rfs)); $dm->setDownloader('file', new Downloader\FileDownloader($io, $config, $eventDispatcher, $cache, $rfs)); $dm->setDownloader('path', new Downloader\PathDownloader($io, $config, $eventDispatcher, $cache, $rfs)); return $dm; }
protected function createDownloadManager(IOInterface $io) { $dm = new Downloader\DownloadManager(); $dm->setDownloader('git', new Downloader\GitDownloader($io)); $dm->setDownloader('svn', new Downloader\SvnDownloader($io)); $dm->setDownloader('hg', new Downloader\HgDownloader($io)); $dm->setDownloader('pear', new Downloader\PearDownloader($io)); $dm->setDownloader('zip', new Downloader\ZipDownloader($io)); $dm->setDownloader('tar', new Downloader\TarDownloader($io)); $dm->setDownloader('phar', new Downloader\PharDownloader($io)); return $dm; }
/** * 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 IO\IOInterface $io * @return Downloader\DownloadManager */ public function createDownloadManager(IOInterface $io, Config $config) { $dm = new Downloader\DownloadManager(); $dm->setDownloader('git', new Downloader\GitDownloader($io, $config)); $dm->setDownloader('svn', new Downloader\SvnDownloader($io, $config)); $dm->setDownloader('hg', new Downloader\HgDownloader($io, $config)); $dm->setDownloader('zip', new Downloader\ZipDownloader($io)); $dm->setDownloader('tar', new Downloader\TarDownloader($io)); $dm->setDownloader('phar', new Downloader\PharDownloader($io)); $dm->setDownloader('file', new Downloader\FileDownloader($io)); return $dm; }