public function setUp() { $this->composerMock = $this->getMockBuilder(Composer::class)->disableOriginalConstructor()->getMock(); $this->lockerMock = $this->getMockBuilder(Locker::class)->disableOriginalConstructor()->getMock(); $this->lockerRepositoryMock = $this->getMockForAbstractClass(\Composer\Repository\RepositoryInterface::class); $this->packageMock = $this->getMockForAbstractClass(\Composer\Package\CompletePackageInterface::class); $this->lockerMock->method('getLockedRepository')->willReturn($this->lockerRepositoryMock); $this->packageMock->method('getType')->willReturn('metapackage'); $this->packageMock->method('getPrettyName')->willReturn('magento/product-test-package-name'); $this->packageMock->method('getName')->willReturn('magento/product-test-package-name'); $this->packageMock->method('getPrettyVersion')->willReturn('123.456.789'); $this->lockerRepositoryMock->method('getPackages')->willReturn([$this->packageMock]); $objectManager = new ObjectManager($this); $this->composerInformation = $objectManager->getObject(\Magento\Framework\Composer\ComposerInformation::class, ['composer' => $this->composerMock, 'locker' => $this->lockerMock]); }
/** * Collect required packages and types from root composer.lock file * * @return array */ public function getRootRequiredPackageTypesByName() { $packages = []; /** @var PackageInterface $package */ foreach ($this->locker->getLockedRepository()->getPackages() as $package) { $packages[$package->getName()] = $package->getType(); } return $packages; }
/** * Collect all installed Magento packages from composer.lock * * @return array */ public function getInstalledMagentoPackages() { $packages = []; /** @var CompletePackageInterface $package */ foreach ($this->locker->getLockedRepository()->getPackages() as $package) { if (in_array($package->getType(), self::$packageTypes) && !$this->isSystemPackage($package->getPrettyName())) { $packages[$package->getName()] = ['name' => $package->getName(), 'type' => $package->getType(), 'version' => $package->getPrettyVersion()]; } } return $packages; }
private function getRootAliases() { if (!$this->update && $this->locker->isLocked()) { $aliases = $this->locker->getAliases(); } else { $aliases = $this->package->getAliases(); } $normalizedAliases = array(); foreach ($aliases as $alias) { $normalizedAliases[$alias['package']][$alias['version']] = array('alias' => $alias['alias'], 'alias_normalized' => $alias['alias_normalized']); } return $normalizedAliases; }
private function aliasPackages() { if (!$this->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->setAlias($alias['alias_normalized']); $package->setPrettyAlias($alias['alias']); $package->getRepository()->addPackage($aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias'])); $aliasPackage->setRootPackageAlias(true); } } return $aliases; }
/** * @expectedException \RuntimeException * @expectedExceptionMessage We cannot retrieve information on magento/product-community-edition. */ public function testGetPackageVersionsFailed() { $communityPackage = $this->getMock('\\Composer\\Package\\Package', [], [], '', false); $enterprisePackage = $this->getMock('\\Composer\\Package\\Package', [], [], '', false); $communityPackage->expects($this->once())->method('getName')->willReturn('magento/product-community-edition'); $enterprisePackage->expects($this->once())->method('getName')->willReturn('magento/product-enterprise-edition'); $this->composerInformation->expects($this->any())->method('isSystemPackage')->willReturn(true); $this->composerInformation->expects($this->once())->method('isPackageInComposerJson')->willReturn(true); $this->repository->expects($this->once())->method('getPackages')->willReturn([$communityPackage, $enterprisePackage]); $this->locker->expects($this->once())->method('getLockedRepository')->willReturn($this->repository); $this->composer->expects($this->once())->method('getLocker')->willReturn($this->locker); $this->magentoComposerApp->expects($this->once())->method('createComposer')->willReturn($this->composer); $this->composerAppFactory->expects($this->once())->method('create')->willReturn($this->magentoComposerApp); $this->composerAppFactory->expects($this->once())->method('createInfoCommand')->willReturn($this->infoCommand); $this->systemPackage = new SystemPackage($this->composerAppFactory, $this->composerInformation); $this->infoCommand->expects($this->once())->method('run')->with('magento/product-community-edition')->willReturn(false); $this->systemPackage->getPackageVersions(); }
/** * Retrieve list of required extensions * * Collect required extensions from composer.lock file * * @return array * @throws \Exception If attributes are missing in composer.lock file. */ public function getRequiredExtensions() { $requiredExtensions = []; $allPlatformReqs = array_keys($this->locker->getPlatformRequirements(true)); if (!$this->isMagentoRoot()) { /** @var \Composer\Package\CompletePackage $package */ foreach ($this->locker->getLockedRepository()->getPackages() as $package) { $requires = array_keys($package->getRequires()); $requires = array_merge($requires, array_keys($package->getDevRequires())); $allPlatformReqs = array_merge($allPlatformReqs, $requires); } } foreach ($allPlatformReqs as $reqIndex) { if (substr($reqIndex, 0, 4) === 'ext-') { $requiredExtensions[] = substr($reqIndex, 4); } } return array_unique($requiredExtensions); }
/** * Initializes path repository. * * This method will basically read the folder and add the found package. */ protected function initialize() { parent::initialize(); foreach ($this->getUrlMatches() as $url) { $path = realpath($url) . DIRECTORY_SEPARATOR; $composerFilePath = $path . 'composer.json'; if (!file_exists($composerFilePath)) { continue; } $json = file_get_contents($composerFilePath); $package = JsonFile::parseJson($json, $composerFilePath); $package['dist'] = array('type' => 'path', 'url' => $url, 'reference' => ''); if (!isset($package['version'])) { $package['version'] = $this->versionGuesser->guessVersion($package, $path) ?: 'dev-master'; } $output = ''; if (is_dir($path . DIRECTORY_SEPARATOR . '.git') && 0 === $this->process->execute('git log -n1 --pretty=%H', $output, $path)) { $package['dist']['reference'] = trim($output); } else { $package['dist']['reference'] = Locker::getContentHash($json); } $package = $this->loader->load($package); $this->addPackage($package); } if (count($this->getPackages()) == 0) { throw new \RuntimeException(sprintf('No `composer.json` file found in any path repository in "%s"', $this->url)); } }
public function testIsFreshFalse() { $json = $this->createJsonFileMock(); $repo = $this->createRepositoryManagerMock(); $inst = $this->createInstallationManagerMock(); $locker = new Locker($json, $repo, $inst, 'md5'); $json ->expects($this->once()) ->method('read') ->will($this->returnValue(array('hash' => 'oldmd5'))); $this->assertFalse($locker->isFresh()); }
public function testIsFreshFalseWithContentHash() { $json = $this->createJsonFileMock(); $repo = $this->createRepositoryManagerMock(); $inst = $this->createInstallationManagerMock(); $locker = new Locker(new NullIO, $json, $repo, $inst, $this->getJsonContent()); $differentHash = md5($this->getJsonContent(array('name' => 'test2'))); $json ->expects($this->once()) ->method('read') ->will($this->returnValue(array('hash' => $differentHash, 'content-hash' => $differentHash))); $this->assertFalse($locker->isFresh()); }
/** * 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); } }
/** * @param Locker $locker * @param RootPackageInterface $rootPackage * * @return \Generator|\string[] */ private static function getVersions(Locker $locker, RootPackageInterface $rootPackage) : \Generator { $lockData = $locker->getLockData(); foreach (array_merge($lockData['packages'], $lockData['packages-dev']) as $package) { (yield $package['name'] => $package['version'] . '@' . $package['source']['reference']); } (yield $rootPackage->getName() => $rootPackage->getVersion() . '@' . $rootPackage->getSourceReference()); }
/** * @param Locker $locker * @param RootPackageInterface $rootPackage * * @return \Generator|\string[] */ private static function getVersions(Locker $locker, RootPackageInterface $rootPackage) { $lockData = $locker->getLockData(); $lockData['packages-dev'] = isset($lockData['packages-dev']) ? $lockData['packages-dev'] : []; foreach (array_merge($lockData['packages'], $lockData['packages-dev']) as $package) { (yield $package['name'] => $package['version'] . '@' . (isset($package['source']['reference']) ? $package['source']['reference'] : (isset($package['dist']['reference']) ? $package['dist']['reference'] : ''))); } (yield $rootPackage->getName() => $rootPackage->getVersion() . '@' . $rootPackage->getSourceReference()); }