Example #1
0
    public function testGetLockedPackages()
    {
        $json = $this->createJsonFileMock();
        $repo = $this->createRepositoryManagerMock();
        $inst = $this->createInstallationManagerMock();

        $locker = new Locker(new NullIO, $json, $repo, $inst, $this->getJsonContent());

        $json
            ->expects($this->once())
            ->method('exists')
            ->will($this->returnValue(true));
        $json
            ->expects($this->once())
            ->method('read')
            ->will($this->returnValue(array(
                'packages' => array(
                    array('name' => 'pkg1', 'version' => '1.0.0-beta'),
                    array('name' => 'pkg2', 'version' => '0.1.10')
                )
            )));

        $repo = $locker->getLockedRepository();
        $this->assertNotNull($repo->findPackage('pkg1', '1.0.0-beta'));
        $this->assertNotNull($repo->findPackage('pkg2', '0.1.10'));
    }
Example #2
0
 /**
  * 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;
 }
Example #4
0
 /**
  * Loads the most "current" list of packages that are installed meaning from lock ideally or from installed repo as fallback
  * @param  RepositoryInterface $installedRepo
  * @return array
  */
 private function getCurrentPackages($installedRepo)
 {
     if ($this->locker->isLocked()) {
         try {
             return $this->locker->getLockedRepository(true)->getPackages();
         } catch (\RuntimeException $e) {
             // fetch only non-dev packages from lock if doing a dev update fails due to a previously incomplete lock file
             return $this->locker->getLockedRepository()->getPackages();
         }
     }
     return $installedRepo->getPackages();
 }
Example #5
0
 /**
  * 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);
 }
Example #6
0
    public function testGetPackagesWithoutRepo()
    {
        $json = $this->createJsonFileMock();
        $repo = $this->createRepositoryManagerMock();
        $inst = $this->createInstallationManagerMock();

        $locker = new Locker($json, $repo, $inst, 'md5');

        $json
            ->expects($this->once())
            ->method('exists')
            ->will($this->returnValue(true));
        $json
            ->expects($this->once())
            ->method('read')
            ->will($this->returnValue(array(
                'packages' => array(
                    array('package' => 'pkg1', 'version' => '1.0.0-beta'),
                    array('package' => 'pkg2', 'version' => '0.1.10')
                )
            )));

        $package1 = $this->createPackageMock();
        $package2 = $this->createPackageMock();

        $repo->getLocalRepository()
            ->expects($this->exactly(2))
            ->method('findPackage')
            ->with($this->logicalOr('pkg1', 'pkg2'), $this->logicalOr('1.0.0-beta', '0.1.10'))
            ->will($this->onConsecutiveCalls($package1, null));

        $this->setExpectedException('LogicException');

        $locker->getLockedRepository();
    }
Example #7
0
 protected function doInstall($localRepo, $installedRepo, $aliases, $devMode = false)
 {
     $minimumStability = $this->package->getMinimumStability();
     $stabilityFlags = $this->package->getStabilityFlags();
     // init vars
     $lockedRepository = null;
     $repositories = null;
     // initialize locker to create aliased packages
     $installFromLock = false;
     if (!$this->update && $this->locker->isLocked($devMode)) {
         $installFromLock = true;
         $lockedRepository = $this->locker->getLockedRepository($devMode);
         $minimumStability = $this->locker->getMinimumStability();
         $stabilityFlags = $this->locker->getStabilityFlags();
     }
     $this->whitelistUpdateDependencies($localRepo, $devMode, $this->package->getRequires(), $this->package->getDevRequires());
     $this->io->write('<info>Loading composer repositories with package information</info>');
     // creating repository pool
     $policy = new DefaultPolicy();
     $pool = new Pool($minimumStability, $stabilityFlags);
     $pool->addRepository($installedRepo, $aliases);
     if ($installFromLock) {
         $pool->addRepository($lockedRepository, $aliases);
     }
     if (!$installFromLock || !$this->locker->isCompleteFormat($devMode)) {
         $repositories = $this->repositoryManager->getRepositories();
         foreach ($repositories as $repository) {
             $pool->addRepository($repository, $aliases);
         }
     }
     // creating requirements request
     $request = new Request($pool);
     $constraint = new VersionConstraint('=', $this->package->getVersion());
     $constraint->setPrettyString($this->package->getPrettyVersion());
     $request->install($this->package->getName(), $constraint);
     if ($this->update) {
         $this->io->write('<info>Updating ' . ($devMode ? 'dev ' : '') . 'dependencies</info>');
         $request->updateAll();
         $links = $devMode ? $this->package->getDevRequires() : $this->package->getRequires();
         foreach ($links as $link) {
             $request->install($link->getTarget(), $link->getConstraint());
         }
     } elseif ($installFromLock) {
         $this->io->write('<info>Installing ' . ($devMode ? 'dev ' : '') . 'dependencies from lock file</info>');
         if (!$this->locker->isCompleteFormat($devMode)) {
             $this->io->write('<warning>Warning: Your lock file is in a deprecated format. It will most likely take a *long* time for composer to install dependencies, and may cause dependency solving issues.</warning>');
         }
         if (!$this->locker->isFresh() && !$devMode) {
             $this->io->write('<warning>Warning: The lock file is not up to date with the latest changes in composer.json, you may be getting outdated dependencies, run update to update them.</warning>');
         }
         foreach ($lockedRepository->getPackages() as $package) {
             $version = $package->getVersion();
             if (isset($aliases[$package->getName()][$version])) {
                 $version = $aliases[$package->getName()][$version]['alias_normalized'];
             }
             $constraint = new VersionConstraint('=', $version);
             $constraint->setPrettyString($package->getPrettyVersion());
             $request->install($package->getName(), $constraint);
         }
     } else {
         $this->io->write('<info>Installing ' . ($devMode ? 'dev ' : '') . 'dependencies</info>');
         $links = $devMode ? $this->package->getDevRequires() : $this->package->getRequires();
         foreach ($links as $link) {
             $request->install($link->getTarget(), $link->getConstraint());
         }
     }
     // fix the version of all installed packages (+ platform) that are not
     // in the current local repo to prevent rogue updates (e.g. non-dev
     // updating when in dev)
     foreach ($installedRepo->getPackages() as $package) {
         if ($package->getRepository() === $localRepo) {
             continue;
         }
         $constraint = new VersionConstraint('=', $package->getVersion());
         $constraint->setPrettyString($package->getPrettyVersion());
         $request->install($package->getName(), $constraint);
     }
     // if the updateWhitelist is enabled, packages not in it are also fixed
     // to the version specified in the lock, or their currently installed version
     if ($this->update && $this->updateWhitelist) {
         if ($this->locker->isLocked($devMode)) {
             $currentPackages = $this->locker->getLockedRepository($devMode)->getPackages();
         } else {
             $currentPackages = $installedRepo->getPackages();
         }
         // collect links from composer as well as installed packages
         $candidates = array();
         foreach ($links as $link) {
             $candidates[$link->getTarget()] = true;
         }
         foreach ($localRepo->getPackages() as $package) {
             $candidates[$package->getName()] = true;
         }
         // fix them to the version in lock (or currently installed) if they are not updateable
         foreach ($candidates as $candidate => $dummy) {
             foreach ($currentPackages as $curPackage) {
                 if ($curPackage->getName() === $candidate) {
                     if ($this->isUpdateable($curPackage)) {
                         break;
                     }
                     $constraint = new VersionConstraint('=', $curPackage->getVersion());
                     $request->install($curPackage->getName(), $constraint);
                 }
             }
         }
     }
     // force dev packages to have the latest links if we update or install from a (potentially new) lock
     $this->processDevPackages($localRepo, $pool, $policy, $repositories, $lockedRepository, $installFromLock, 'force-links');
     // solve dependencies
     $solver = new Solver($policy, $pool, $installedRepo);
     try {
         $operations = $solver->solve($request);
     } catch (SolverProblemsException $e) {
         $this->io->write('<error>Your requirements could not be resolved to an installable set of packages.</error>');
         $this->io->write($e->getMessage());
         return false;
     }
     if ($devMode) {
         // remove bogus operations that the solver creates for stuff that was force-updated in the non-dev pass
         // TODO this should not be necessary ideally, but it seems to work around the problem quite well
         foreach ($operations as $index => $op) {
             if ('update' === $op->getJobType() && $op->getInitialPackage()->getUniqueName() === $op->getTargetPackage()->getUniqueName() && $op->getInitialPackage()->getSourceReference() === $op->getTargetPackage()->getSourceReference() && $op->getInitialPackage()->getDistReference() === $op->getTargetPackage()->getDistReference()) {
                 unset($operations[$index]);
             }
         }
     }
     // force dev packages to be updated if we update or install from a (potentially new) lock
     $operations = $this->processDevPackages($localRepo, $pool, $policy, $repositories, $lockedRepository, $installFromLock, 'force-updates', $operations);
     // execute operations
     if (!$operations) {
         $this->io->write('Nothing to install or update');
     }
     foreach ($operations as $operation) {
         // collect suggestions
         if ('install' === $operation->getJobType()) {
             foreach ($operation->getPackage()->getSuggests() as $target => $reason) {
                 $this->suggestedPackages[] = array('source' => $operation->getPackage()->getPrettyName(), 'target' => $target, 'reason' => $reason);
             }
         }
         $event = 'Composer\\Script\\ScriptEvents::PRE_PACKAGE_' . strtoupper($operation->getJobType());
         if (defined($event) && $this->runScripts) {
             $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $operation);
         }
         // not installing from lock, force dev packages' references if they're in root package refs
         if (!$installFromLock) {
             $package = null;
             if ('update' === $operation->getJobType()) {
                 $package = $operation->getTargetPackage();
             } elseif ('install' === $operation->getJobType()) {
                 $package = $operation->getPackage();
             }
             if ($package && $package->isDev()) {
                 $references = $this->package->getReferences();
                 if (isset($references[$package->getName()])) {
                     $package->setSourceReference($references[$package->getName()]);
                     $package->setDistReference($references[$package->getName()]);
                 }
             }
         }
         // output alias operations in verbose mode, or all ops in dry run
         if ($this->dryRun || $this->verbose && false !== strpos($operation->getJobType(), 'Alias')) {
             $this->io->write('  - ' . $operation);
         }
         $this->installationManager->execute($localRepo, $operation);
         $event = 'Composer\\Script\\ScriptEvents::POST_PACKAGE_' . strtoupper($operation->getJobType());
         if (defined($event) && $this->runScripts) {
             $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $operation);
         }
         if (!$this->dryRun) {
             $localRepo->write();
         }
     }
     return true;
 }
Example #8
0
 protected function doInstall($localRepo, $installedRepo, $platformRepo, $aliases, $withDevReqs)
 {
     // init vars
     $lockedRepository = null;
     $repositories = null;
     // initialize locker to create aliased packages
     $installFromLock = false;
     if (!$this->update && $this->locker->isLocked()) {
         $installFromLock = true;
         try {
             $lockedRepository = $this->locker->getLockedRepository($withDevReqs);
         } catch (\RuntimeException $e) {
             // if there are dev requires, then we really can not install
             if ($this->package->getDevRequires()) {
                 throw $e;
             }
             // no require-dev in composer.json and the lock file was created with no dev info, so skip them
             $lockedRepository = $this->locker->getLockedRepository();
         }
     }
     $this->whitelistUpdateDependencies($localRepo, $withDevReqs, $this->package->getRequires(), $this->package->getDevRequires());
     $this->io->writeError('<info>Loading composer repositories with package information</info>');
     // creating repository pool
     $policy = $this->createPolicy();
     $pool = $this->createPool($withDevReqs, $lockedRepository);
     $pool->addRepository($installedRepo, $aliases);
     if ($installFromLock) {
         $pool->addRepository($lockedRepository, $aliases);
     }
     if (!$installFromLock) {
         $repositories = $this->repositoryManager->getRepositories();
         foreach ($repositories as $repository) {
             $pool->addRepository($repository, $aliases);
         }
     }
     // creating requirements request
     $request = $this->createRequest($pool, $this->package, $platformRepo);
     if (!$installFromLock) {
         // remove unstable packages from the localRepo if they don't match the current stability settings
         $removedUnstablePackages = array();
         foreach ($localRepo->getPackages() as $package) {
             if (!$pool->isPackageAcceptable($package->getNames(), $package->getStability()) && $this->installationManager->isPackageInstalled($localRepo, $package)) {
                 $removedUnstablePackages[$package->getName()] = true;
                 $request->remove($package->getName(), new VersionConstraint('=', $package->getVersion()));
             }
         }
     }
     if ($this->update) {
         $this->io->writeError('<info>Updating dependencies' . ($withDevReqs ? ' (including require-dev)' : '') . '</info>');
         $request->updateAll();
         if ($withDevReqs) {
             $links = array_merge($this->package->getRequires(), $this->package->getDevRequires());
         } else {
             $links = $this->package->getRequires();
         }
         foreach ($links as $link) {
             $request->install($link->getTarget(), $link->getConstraint());
         }
         // if the updateWhitelist is enabled, packages not in it are also fixed
         // to the version specified in the lock, or their currently installed version
         if ($this->updateWhitelist) {
             if ($this->locker->isLocked()) {
                 try {
                     $currentPackages = $this->locker->getLockedRepository($withDevReqs)->getPackages();
                 } catch (\RuntimeException $e) {
                     // fetch only non-dev packages from lock if doing a dev update fails due to a previously incomplete lock file
                     $currentPackages = $this->locker->getLockedRepository()->getPackages();
                 }
             } else {
                 $currentPackages = $installedRepo->getPackages();
             }
             // collect packages to fixate from root requirements as well as installed packages
             $candidates = array();
             foreach ($links as $link) {
                 $candidates[$link->getTarget()] = true;
             }
             foreach ($localRepo->getPackages() as $package) {
                 $candidates[$package->getName()] = true;
             }
             // fix them to the version in lock (or currently installed) if they are not updateable
             foreach ($candidates as $candidate => $dummy) {
                 foreach ($currentPackages as $curPackage) {
                     if ($curPackage->getName() === $candidate) {
                         if (!$this->isUpdateable($curPackage) && !isset($removedUnstablePackages[$curPackage->getName()])) {
                             $constraint = new VersionConstraint('=', $curPackage->getVersion());
                             $request->install($curPackage->getName(), $constraint);
                         }
                         break;
                     }
                 }
             }
         }
     } elseif ($installFromLock) {
         $this->io->writeError('<info>Installing dependencies' . ($withDevReqs ? ' (including require-dev)' : '') . ' from lock file</info>');
         if (!$this->locker->isFresh()) {
             $this->io->writeError('<warning>Warning: The lock file is not up to date with the latest changes in composer.json. You may be getting outdated dependencies. Run update to update them.</warning>');
         }
         foreach ($lockedRepository->getPackages() as $package) {
             $version = $package->getVersion();
             if (isset($aliases[$package->getName()][$version])) {
                 $version = $aliases[$package->getName()][$version]['alias_normalized'];
             }
             $constraint = new VersionConstraint('=', $version);
             $constraint->setPrettyString($package->getPrettyVersion());
             $request->install($package->getName(), $constraint);
         }
         foreach ($this->locker->getPlatformRequirements($withDevReqs) as $link) {
             $request->install($link->getTarget(), $link->getConstraint());
         }
     } else {
         $this->io->writeError('<info>Installing dependencies' . ($withDevReqs ? ' (including require-dev)' : '') . '</info>');
         if ($withDevReqs) {
             $links = array_merge($this->package->getRequires(), $this->package->getDevRequires());
         } else {
             $links = $this->package->getRequires();
         }
         foreach ($links as $link) {
             $request->install($link->getTarget(), $link->getConstraint());
         }
     }
     // force dev packages to have the latest links if we update or install from a (potentially new) lock
     $this->processDevPackages($localRepo, $pool, $policy, $repositories, $lockedRepository, $installFromLock, 'force-links');
     // solve dependencies
     $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request);
     $solver = new Solver($policy, $pool, $installedRepo);
     try {
         $operations = $solver->solve($request, $this->ignorePlatformReqs);
         $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request, $operations);
     } catch (SolverProblemsException $e) {
         $this->io->writeError('<error>Your requirements could not be resolved to an installable set of packages.</error>');
         $this->io->writeError($e->getMessage());
         return max(1, $e->getCode());
     }
     // force dev packages to be updated if we update or install from a (potentially new) lock
     $operations = $this->processDevPackages($localRepo, $pool, $policy, $repositories, $lockedRepository, $installFromLock, 'force-updates', $operations);
     // execute operations
     if (!$operations) {
         $this->io->writeError('Nothing to install or update');
     }
     $operations = $this->movePluginsToFront($operations);
     $operations = $this->moveUninstallsToFront($operations);
     foreach ($operations as $operation) {
         // collect suggestions
         if ('install' === $operation->getJobType()) {
             foreach ($operation->getPackage()->getSuggests() as $target => $reason) {
                 $this->suggestedPackages[] = array('source' => $operation->getPackage()->getPrettyName(), 'target' => $target, 'reason' => $reason);
             }
         }
         // not installing from lock, force dev packages' references if they're in root package refs
         if (!$installFromLock) {
             $package = null;
             if ('update' === $operation->getJobType()) {
                 $package = $operation->getTargetPackage();
             } elseif ('install' === $operation->getJobType()) {
                 $package = $operation->getPackage();
             }
             if ($package && $package->isDev()) {
                 $references = $this->package->getReferences();
                 if (isset($references[$package->getName()])) {
                     $package->setSourceReference($references[$package->getName()]);
                     $package->setDistReference($references[$package->getName()]);
                 }
             }
             if ('update' === $operation->getJobType() && $operation->getTargetPackage()->isDev() && $operation->getTargetPackage()->getVersion() === $operation->getInitialPackage()->getVersion() && $operation->getTargetPackage()->getSourceReference() === $operation->getInitialPackage()->getSourceReference()) {
                 if ($this->io->isDebug()) {
                     $this->io->writeError('  - Skipping update of ' . $operation->getTargetPackage()->getPrettyName() . ' to the same reference-locked version');
                     $this->io->writeError('');
                 }
                 continue;
             }
         }
         $event = 'Composer\\Installer\\PackageEvents::PRE_PACKAGE_' . strtoupper($operation->getJobType());
         if (defined($event) && $this->runScripts) {
             $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
         }
         // output non-alias ops in dry run, output alias ops in debug verbosity
         if ($this->dryRun && false === strpos($operation->getJobType(), 'Alias')) {
             $this->io->writeError('  - ' . $operation);
             $this->io->writeError('');
         } elseif ($this->io->isDebug() && false !== strpos($operation->getJobType(), 'Alias')) {
             $this->io->writeError('  - ' . $operation);
             $this->io->writeError('');
         }
         $this->installationManager->execute($localRepo, $operation);
         // output reasons why the operation was ran, only for install/update operations
         if ($this->verbose && $this->io->isVeryVerbose() && in_array($operation->getJobType(), array('install', 'update'))) {
             $reason = $operation->getReason();
             if ($reason instanceof Rule) {
                 switch ($reason->getReason()) {
                     case Rule::RULE_JOB_INSTALL:
                         $this->io->writeError('    REASON: Required by root: ' . $reason->getPrettyString($pool));
                         $this->io->writeError('');
                         break;
                     case Rule::RULE_PACKAGE_REQUIRES:
                         $this->io->writeError('    REASON: ' . $reason->getPrettyString($pool));
                         $this->io->writeError('');
                         break;
                 }
             }
         }
         $event = 'Composer\\Installer\\PackageEvents::POST_PACKAGE_' . strtoupper($operation->getJobType());
         if (defined($event) && $this->runScripts) {
             $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
         }
         if (!$this->dryRun) {
             $localRepo->write();
         }
     }
     return 0;
 }