public function getMissingVersions($currentVersion, $requiredVersion) { $currentVersion = trim($currentVersion); $missingVersions = array(); if (empty($currentVersion)) { if (!empty($requiredVersion)) { $missingVersions[] = (string) $requiredVersion; } return $missingVersions; } $requiredVersion = $this->makeVersionBackwardsCompatibleIfNoComparisonDefined($requiredVersion); $version = new VersionParser(); $constraintsExisting = $version->parseConstraints($currentVersion); $requiredVersions = explode(',', (string) $requiredVersion); foreach ($requiredVersions as $required) { $required = trim($required); if (empty($required)) { continue; } $required = $this->makeVersionBackwardsCompatibleIfNoComparisonDefined($required); $constraintRequired = $version->parseConstraints($required); if (!$constraintRequired->matches($constraintsExisting)) { $missingVersions[] = $required; } } return $missingVersions; }
/** * @dataProvider getRecommendedRequireVersionPackages */ public function testFindRecommendedRequireVersion($prettyVersion, $isDev, $stability, $expectedVersion, $branchAlias = null) { $pool = $this->createMockPool(); $versionSelector = new VersionSelector($pool); $versionParser = new VersionParser(); $package = $this->getMock('\Composer\Package\PackageInterface'); $package->expects($this->any()) ->method('getPrettyVersion') ->will($this->returnValue($prettyVersion)); $package->expects($this->any()) ->method('getVersion') ->will($this->returnValue($versionParser->normalize($prettyVersion))); $package->expects($this->any()) ->method('isDev') ->will($this->returnValue($isDev)); $package->expects($this->any()) ->method('getStability') ->will($this->returnValue($stability)); $branchAlias = $branchAlias === null ? array() : array('branch-alias' => array($prettyVersion => $branchAlias)); $package->expects($this->any()) ->method('getExtra') ->will($this->returnValue($branchAlias)); $recommended = $versionSelector->findRecommendedRequireVersion($package); // assert that the recommended version is what we expect $this->assertEquals($expectedVersion, $recommended); }
/** * Execute. * * @param string $packageName Package to inspect. * @param string $textConstraint Optional version constraint * @param bool $onlyLocal * * @return Dependency[]|null */ public function execute($packageName, $textConstraint = '*', $onlyLocal = true) { // Find packages that are or provide the requested package first $pool = $this->getRequiredPool($packageName, $textConstraint, $onlyLocal); $packages = $pool->whatProvides($packageName); if (empty($packages)) { // sprintf('Could not find package "%s" in your project', $packageName), return null; } // Get the needle stack $needles = $this->getNeedles($packageName, $packages, $this->inverted); // Parse constraint if one was supplied $constraint = null; if ($textConstraint !== '*') { $versionParser = new VersionParser(); $constraint = $versionParser->parseConstraints($textConstraint); } $extra = $constraint !== null ? sprintf(' in versions %s "%s"', $this->inverted ? 'not matching' : 'matching', $textConstraint) : ''; // Resolve dependencies /** @var InstalledFilesystemRepository $repository */ $repository = $this->getComposer()->getRepositoryManager()->getLocalRepository(); $results = $repository->getDependents($needles, $constraint, $this->inverted, $this->recursive); if (empty($results)) { // sprintf('There is no installed package depending on "%s"%s', $packageName, $extra), return null; } // sprintf('The following packages are involved in the dependency on "%s"%s', $packageName, $extra), return $this->getDependencies($results); }
public function resolveFeatureBranch(Event $event) { if (empty($this->featureBranchRepositories)) { $this->io->write('No feature branches configured, continuing!'); return; } $package = $this->composer->getPackage(); if ($package->isDev()) { $featureBranchConstraint = new Constraint('=', $this->versionParser->normalize($package->getVersion())); $featureBranchConstraint->setPrettyString($package->getVersion()); $requires = $package->getRequires(); $this->io->write(sprintf("<info>Checking for feature branch '%s'</info>", $featureBranchConstraint->getPrettyString())); foreach ($requires as $key => $require) { if ($this->hasFeatureBranch($require, $featureBranchConstraint)) { $requires[$key] = new Link($require->getSource(), $require->getTarget(), $featureBranchConstraint, 'requires', $featureBranchConstraint->getPrettyString()); } else { $fallbackBranch = $this->getFallbackBranch($require); if ($fallbackBranch !== false) { $fallbackConstraint = new Constraint('=', $this->versionParser->normalize($fallbackBranch)); $fallbackConstraint->setPrettyString($fallbackBranch); $requires[$key] = new Link($require->getSource(), $require->getTarget(), $fallbackConstraint, 'requires', $fallbackConstraint->getPrettyString()); } } $this->io->write(''); } $package->setRequires($requires); } }
/** * Tests memory package marshalling/serialization semantics * @dataProvider providerVersioningSchemes */ public function testPackageHasExpectedMarshallingSemantics($name, $version) { $versionParser = new VersionParser(); $normVersion = $versionParser->normalize($version); $package = new Package($name, $normVersion, $version); $this->assertEquals(strtolower($name) . '-' . $normVersion, (string) $package); }
/** * Checks a composer.lock file. * * @param string $lock The path to the composer.lock file * * @return array Result array * * @throws \InvalidArgumentException When the output format is unsupported * @throws \RuntimeException When the lock file does not exist * @throws \RuntimeException When curl does not work or is unavailable */ public function check($lock) { if (is_dir($lock) && file_exists($lock . '/composer.lock')) { $lock = $lock . '/composer.lock'; } elseif (preg_match('/composer\\.json$/', $lock)) { $lock = str_replace('composer.json', 'composer.lock', $lock); } if (!is_file($lock)) { throw new \RuntimeException('Lock file does not exist.'); } $results = array(); $client = new Client(); $vp = new VersionParser(); $data = json_decode(file_get_contents($lock), 1); foreach ($data['packages'] as $package) { $name = $package['name']; $status = 'found'; $localVersion = $vp->normalize($package['version']); $localStatus = $this->parseStatus($localVersion); $stableVersion = 0; $stableStatus = ''; $devVersion = 0; $devStatus = ''; $remoteData = null; try { $response = $client->get("https://packagist.org/packages/{$name}.json"); $body = $response->getBody(); $statusCode = $response->getStatusCode(); if (200 === $statusCode) { $remoteData = json_decode($body, true); } else { $status = 'error'; } } catch (\Exception $e) { $status = 'error'; } if ($remoteData) { foreach ($remoteData['package']['versions'] as $versionName => $versionData) { if ($this->isStable($versionData['version_normalized']) && Comparator::greaterThan($versionData['version_normalized'], $stableVersion)) { $stableVersion = $versionData['version_normalized']; $stableStatus = $this->diffVersion($localVersion, $stableVersion); } } foreach ($remoteData['package']['versions'] as $versionName => $versionData) { if ($this->isTaggedDev($versionData['version_normalized']) && Comparator::greaterThan($versionData['version_normalized'], $devVersion) && Comparator::greaterThan($versionData['version_normalized'], $stableVersion) && ($localVersion === '9999999-dev' || Comparator::greaterThan($versionData['version_normalized'], $localVersion))) { $devVersion = $versionData['version_normalized']; $devStatus = $this->diffVersion($localVersion, $devVersion); } } } else { $stableVersion = 'Not found'; $stableStatus = 'error'; $devVersion = 'Not found'; $devStatus = 'error'; } $results[$name] = array('name' => $name, 'status' => $status, 'localVersion' => $localVersion, 'localStatus' => $localStatus, 'stableVersion' => $stableVersion, 'stableStatus' => $stableStatus, 'devVersion' => $devVersion, 'devStatus' => $devStatus); } return $results; }
/** * Check that the provided constraint is compatible with the current version of core * * @param string $constraint Something like ">= 1.26" * @return bool */ public function check($constraint) { if ($this->coreVersion === false) { // Couldn't parse the core version, so we can't check anything return true; } return $this->versionParser->parseConstraints($constraint)->matches($this->coreVersion); }
private function getPackageMatches($repository, $name, $version = null) { $pool = new Pool('dev'); $pool->addRepository($repository); $constraint = null; if ($version) { $parser = new VersionParser(); $constraint = $parser->parseConstraints($version); } return $pool->whatProvides($name, $constraint); }
/** * @param array $install [name => version, name => version, ...] * @return bool */ public function install(array $install) { $this->addPackages($install); $refresh = []; $versionParser = new VersionParser(); foreach ($install as $name => $version) { $normalized = $versionParser->normalize($version); $refresh[] = new Package($name, $normalized, $version); } $this->composerUpdate(array_keys($install), $refresh); $this->writeConfig(); }
/** * Loops over packages and adjusts the dependency constraints * * @param array $packages * @return array */ protected function adjustGitFlowPackages(array $packages) { $newRequires = []; $versionParser = new VersionParser(); foreach ($packages as $packageName => $package) { if ('dev-master' === $package->getPrettyConstraint()) { $branch = $this->findStabilityBranch($packageName); $this->getIO()->writeError(' - Adjusting ' . $packageName . ' to ' . $branch); $link = new Link($package->getSource(), $package->getTarget(), $versionParser->parseConstraints($branch), $package->getDescription(), $branch); $newRequires[$packageName] = $link; } } return $newRequires; }
/** * {@inheritDoc} */ public function parseConstraints($constraints) { if (!isset(self::$constraints[$constraints])) { self::$constraints[$constraints] = parent::parseConstraints($constraints); } return self::$constraints[$constraints]; }
/** * finds a package by name and version if provided * * @param RepositoryInterface $installedRepo * @param RepositoryInterface $repos * @param string $name * @param ConstraintInterface|string $version * * @throws \InvalidArgumentException * @return CompletePackageInterface */ private function getPackage(RepositoryInterface $installedRepo, RepositoryInterface $repos, $name, $version = null) { $name = strtolower($name); $constraint = is_string($version) ? $this->versionParser->parseConstraints($version) : $version; $policy = new DefaultPolicy(); $pool = new Pool('dev'); $pool->addRepository($repos); $matchedPackage = null; $matches = $pool->whatProvides($name, $constraint); foreach ($matches as $index => $package) { // skip providers/replacers if ($package->getName() !== $name) { unset($matches[$index]); continue; } // select an exact match if it is in the installed repo and no specific version was required if (null === $version && $installedRepo->hasPackage($package)) { $matchedPackage = $package; } $matches[$index] = $package->getId(); } // select preferred package according to policy rules if (!$matchedPackage && $matches && ($preferred = $policy->selectPreferredPackages($pool, [], $matches))) { $matchedPackage = $pool->literalToPackage($preferred[0]); } return $matchedPackage; }
private function guessSvnVersion(array $packageConfig, $path) { SvnUtil::cleanEnv(); // try to fetch current version from svn if (0 === $this->process->execute('svn info --xml', $output, $path)) { $trunkPath = isset($packageConfig['trunk-path']) ? preg_quote($packageConfig['trunk-path'], '#') : 'trunk'; $branchesPath = isset($packageConfig['branches-path']) ? preg_quote($packageConfig['branches-path'], '#') : 'branches'; $tagsPath = isset($packageConfig['tags-path']) ? preg_quote($packageConfig['tags-path'], '#') : 'tags'; $urlPattern = '#<url>.*/(' . $trunkPath . '|(' . $branchesPath . '|' . $tagsPath . ')/(.*))</url>#'; if (preg_match($urlPattern, $output, $matches)) { if (isset($matches[2]) && ($branchesPath === $matches[2] || $tagsPath === $matches[2])) { // we are in a branches path $version = $this->versionParser->normalizeBranch($matches[3]); $prettyVersion = 'dev-' . $matches[3]; if ('9999999-dev' === $version) { $version = $prettyVersion; } return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion); } $prettyVersion = trim($matches[1]); $version = $this->versionParser->normalize($prettyVersion); return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion); } } }
private function validateTag($version) { try { return $this->versionParser->normalize($version); } catch (Exception $e) { } return false; }
/** * @param array $install [name => version, name => version, ...] * @param bool $packagist * @param bool $writeConfig * @param bool $preferSource * @return bool */ public function install(array $install, $packagist = false, $writeConfig = true, $preferSource = false) { $this->addPackages($install); $refresh = []; $versionParser = new VersionParser(); foreach ($install as $name => $version) { try { $normalized = $versionParser->normalize($version); $refresh[] = new Package($name, $normalized, $version); } catch (\UnexpectedValueException $e) { } } $this->composerUpdate(array_keys($install), $refresh, $packagist, $preferSource); if ($writeConfig) { $this->writeConfig(); } }
private function isNormalisible($refName) { try { $this->versionParser->normalize($refName); return true; } catch (UnexpectedValueException $e) { // this shouldnt happen, means branches are in release list return false; } }
/** * {@inheritDoc} */ public function findPackages($name, $constraint = null) { // normalize name $name = strtolower($name); $packages = array(); if (null !== $constraint && !$constraint instanceof ConstraintInterface) { $versionParser = new VersionParser(); $constraint = $versionParser->parseConstraints($constraint); } foreach ($this->getPackages() as $package) { if ($name === $package->getName()) { $pkgConstraint = new Constraint('==', $package->getVersion()); if (null === $constraint || $constraint->matches($pkgConstraint)) { $packages[] = $package; } } } return $packages; }
/** * @param \Composer\Package\Link $packageLink * @param bool $ignoreRequiredVersion * @param bool $exactAsTilda * @return \Composer\Package\PackageInterface[] */ private function getVersionsByPackageLink(Link $packageLink, $ignoreRequiredVersion = FALSE, $exactAsTilda = FALSE) { $constraint = $packageLink->getConstraint(); if ($this->versionParser->parseStability($constraint->getPrettyString()) !== 'dev') { if ($ignoreRequiredVersion) { $constraint = NULL; } elseif ($exactAsTilda && $this->isExact($constraint)) { $constraint = $this->versionParser->parseConstraints(sprintf('~%s', $constraint->getPrettyString())); } } return $this->getVersions($packageLink->getTarget(), $constraint); }
/** * All descendants' constructors should call this parent constructor * * @param PackageInterface $aliasOf The package this package is an alias of * @param string $version The version the alias must report * @param string $prettyVersion The alias's non-normalized version */ public function __construct(PackageInterface $aliasOf, $version, $prettyVersion) { parent::__construct($aliasOf->getName()); $this->version = $version; $this->prettyVersion = $prettyVersion; $this->aliasOf = $aliasOf; $this->stability = VersionParser::parseStability($version); $this->dev = $this->stability === 'dev'; foreach (array('requires', 'devRequires', 'conflicts', 'provides', 'replaces') as $type) { $links = $aliasOf->{'get' . ucfirst($type)}(); $this->{$type} = $this->replaceSelfVersionDependencies($links, $type); } }
public function resolve($name, $constraint, $isDevelopment) { $name = strtolower($name); if (array_key_exists($name, $this->dependencies)) { return; } if (!$constraint instanceof ConstraintInterface) { $constraint = $this->versionParser->parseConstraints($constraint); } $package = $this->manager->findPackage($name, $constraint); if (!$package) { throw new RuntimeException(sprintf('Unable to find package "%s"', $name)); } foreach ($package->getDependencies() as $dependencyName => $dependencyVersion) { $this->resolve($dependencyName, $dependencyVersion, false); } foreach ($package->getDevelopmentDependencies() as $dependencyName => $dependencyVersion) { $this->resolve($dependencyName, $dependencyVersion, true); } $package->setDevelopmentPackage($isDevelopment); $this->dependencies[$name] = $package; }
public function testWhatProvides() { $repo = $this->getMockBuilder('Composer\\Repository\\ComposerRepository')->disableOriginalConstructor()->setMethods(array('fetchFile'))->getMock(); $cache = $this->getMockBuilder('Composer\\Cache')->disableOriginalConstructor()->getMock(); $cache->expects($this->any())->method('sha256')->will($this->returnValue(false)); $properties = array('cache' => $cache, 'loader' => new ArrayLoader(), 'providerListing' => array('a' => array('sha256' => 'xxx')), 'providersUrl' => 'https://dummy.test.link/to/%package%/file'); foreach ($properties as $property => $value) { $ref = new \ReflectionProperty($repo, $property); $ref->setAccessible(true); $ref->setValue($repo, $value); } $repo->expects($this->any())->method('fetchFile')->will($this->returnValue(array('packages' => array(array(array('uid' => 1, 'name' => 'a', 'version' => 'dev-master', 'extra' => array('branch-alias' => array('dev-master' => '1.0.x-dev')))), array(array('uid' => 2, 'name' => 'a', 'version' => 'dev-develop', 'extra' => array('branch-alias' => array('dev-develop' => '1.1.x-dev')))), array(array('uid' => 3, 'name' => 'a', 'version' => '0.6')))))); $pool = $this->getMock('Composer\\DependencyResolver\\Pool'); $pool->expects($this->any())->method('isPackageAcceptable')->will($this->returnValue(true)); $versionParser = new VersionParser(); $repo->setRootAliases(array('a' => array($versionParser->normalize('0.6') => array('alias' => 'dev-feature', 'alias_normalized' => $versionParser->normalize('dev-feature')), $versionParser->normalize('1.1.x-dev') => array('alias' => '1.0', 'alias_normalized' => $versionParser->normalize('1.0'))))); $packages = $repo->whatProvides($pool, 'a'); $this->assertCount(7, $packages); $this->assertEquals(array('1', '1-alias', '2', '2-alias', '2-root', '3', '3-root'), array_keys($packages)); $this->assertInstanceOf('Composer\\Package\\AliasPackage', $packages['2-root']); $this->assertSame($packages['2'], $packages['2-root']->getAliasOf()); $this->assertSame($packages['2'], $packages['2-alias']->getAliasOf()); }
public static function Construct(IOInterface $io) { $repo = new ArrayRepository(); try { $web_folder = Locator::getWebFolderPath(); $version_file = $web_folder . '/intranet/setup/_init/version.txt'; if (!file_exists($version_file)) { throw new \Exception("No version.txt for core found - assuming framework is not installed"); } $version_data = file($version_file); $core_version = $version_data[1]; $normalizer = new VersionParser(); $core_version_normalized = $normalizer->normalize($core_version); $io->write("Detected core version {$core_version} ({$core_version_normalized})"); $core_package = new Package(FrameworkInstallerV8::PACKAGE_NAME, $core_version_normalized, $core_version); $repo->addPackage($core_package); } catch (\Exception $e) { $io->write($e->getMessage()); // if can't determine location of 'web' folder, not adding the core package therefore letting // composer install it } return $repo; }
/** * Get the last version number from a list of versions. * * @param array $versions * * @return string */ public static function latest(array $versions) { // Normalize version numbers. $versions = array_map(function ($version) { return static::normalize($version); }, $versions); // Get the highest version number. $latest = array_reduce($versions, function ($carry, $item) { // Skip unstable versions. if (VersionParser::parseStability($item) !== 'stable') { return $carry; } return Comparator::greaterThan($carry, $item) ? $carry : $item; }, '0.0.0'); return $latest; }
/** * Try to validate the version constraint. * * @param Request $request The request. * * @return JsonResponse * * @throws \RuntimeException For invalid user classes. * * @ApiDoc( * section="misc", * statusCodes = { * 200 = "When everything worked out ok", * 400 = "When the request payload was invalid." * }, * authentication = true, * authenticationRoles = { * "ROLE_NONE" * } * ) * @ApiDescription( * request={ * "constraint" = { * "description" = "The constraint to test.", * "dataType" = "string", * "required" = true * } * }, * response={ * "status" = { * "dataType" = "choice", * "description" = "OK or ERROR", * "format" = "['OK', 'ERROR']", * }, * "error" = { * "dataType" = "string", * "description" = "The error message (if any).", * } * } * ) */ public function checkVersionConstraintAction(Request $request) { try { $inputData = new JsonArray($request->getContent()); } catch (\Exception $exception) { return new JsonResponse(['status' => 'ERROR', 'error' => 'invalid payload'], JsonResponse::HTTP_BAD_REQUEST); } $versionParser = new VersionParser(); if (!$inputData->has('constraint')) { return new JsonResponse(['status' => 'ERROR', 'error' => 'invalid payload'], JsonResponse::HTTP_BAD_REQUEST); } try { $versionParser->parseConstraints($inputData->get('constraint')); } catch (\Exception $exception) { return new JsonResponse(['status' => 'ERROR', 'error' => $exception->getMessage()], JsonResponse::HTTP_OK); } return new JsonResponse(['status' => 'OK'], JsonResponse::HTTP_OK); }
private function extractReferences(array $requires, array $references) { foreach ($requires as $reqName => $reqVersion) { $reqVersion = preg_replace('{^([^,\\s@]+) as .+$}', '$1', $reqVersion); if (preg_match('{^[^,\\s@]+?#([a-f0-9]+)$}', $reqVersion, $match) && 'dev' === ($stabilityName = VersionParser::parseStability($reqVersion))) { $name = strtolower($reqName); $references[$name] = $match[1]; } } return $references; }
protected function execute(InputInterface $input, OutputInterface $output) { $file = Factory::getComposerFile(); $io = $this->getIO(); $newlyCreated = !file_exists($file); if (!file_exists($file) && !file_put_contents($file, "{\n}\n")) { $io->writeError('<error>' . $file . ' could not be created.</error>'); return 1; } if (!is_readable($file)) { $io->writeError('<error>' . $file . ' is not readable.</error>'); return 1; } if (!is_writable($file)) { $io->writeError('<error>' . $file . ' is not writable.</error>'); return 1; } if (filesize($file) === 0) { file_put_contents($file, "{\n}\n"); } $json = new JsonFile($file); $composerDefinition = $json->read(); $composerBackup = file_get_contents($json->getPath()); $composer = $this->getComposer(); $repos = $composer->getRepositoryManager()->getRepositories(); $this->repos = new CompositeRepository(array_merge(array(new PlatformRepository()), $repos)); $requirements = $this->determineRequirements($input, $output, $input->getArgument('packages')); $requireKey = $input->getOption('dev') ? 'require-dev' : 'require'; $removeKey = $input->getOption('dev') ? 'require' : 'require-dev'; $baseRequirements = array_key_exists($requireKey, $composerDefinition) ? $composerDefinition[$requireKey] : array(); $requirements = $this->formatRequirements($requirements); // validate requirements format $versionParser = new VersionParser(); foreach ($requirements as $constraint) { $versionParser->parseConstraints($constraint); } $sortPackages = $input->getOption('sort-packages'); if (!$this->updateFileCleanly($json, $baseRequirements, $requirements, $requireKey, $removeKey, $sortPackages)) { foreach ($requirements as $package => $version) { $baseRequirements[$package] = $version; if (isset($composerDefinition[$removeKey][$package])) { unset($composerDefinition[$removeKey][$package]); } } $composerDefinition[$requireKey] = $baseRequirements; $json->write($composerDefinition); } $io->writeError('<info>' . $file . ' has been ' . ($newlyCreated ? 'created' : 'updated') . '</info>'); if ($input->getOption('no-update')) { return 0; } $updateDevMode = !$input->getOption('update-no-dev'); $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader'); $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative'); // Update packages $this->resetComposer(); $composer = $this->getComposer(); $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress')); $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'require', $input, $output); $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); $install = Installer::create($io, $composer); $install->setVerbose($input->getOption('verbose'))->setPreferSource($input->getOption('prefer-source'))->setPreferDist($input->getOption('prefer-dist'))->setDevMode($updateDevMode)->setOptimizeAutoloader($optimize)->setClassMapAuthoritative($authoritative)->setUpdate(true)->setUpdateWhitelist(array_keys($requirements))->setWhitelistDependencies($input->getOption('update-with-dependencies'))->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs')); $status = $install->run(); if ($status !== 0) { if ($newlyCreated) { $io->writeError("\n" . '<error>Installation failed, deleting ' . $file . '.</error>'); unlink($json->getPath()); } else { $io->writeError("\n" . '<error>Installation failed, reverting ' . $file . ' to its original content.</error>'); file_put_contents($json->getPath(), $composerBackup); } } return $status; }
protected function initialize() { parent::initialize(); $versionParser = new VersionParser(); // Add each of the override versions as options. // Later we might even replace the extensions instead. foreach ($this->overrides as $override) { // Check that it's a platform package. if (!preg_match(self::PLATFORM_PACKAGE_REGEX, $override['name'])) { throw new \InvalidArgumentException('Invalid platform package name in config.platform: ' . $override['name']); } $version = $versionParser->normalize($override['version']); $package = new CompletePackage($override['name'], $version, $override['version']); $package->setDescription('Package overridden via config.platform'); $package->setExtra(array('config.platform' => true)); parent::addPackage($package); } $prettyVersion = PluginInterface::PLUGIN_API_VERSION; $version = $versionParser->normalize($prettyVersion); $composerPluginApi = new CompletePackage('composer-plugin-api', $version, $prettyVersion); $composerPluginApi->setDescription('The Composer Plugin API'); $this->addPackage($composerPluginApi); try { $prettyVersion = PHP_VERSION; $version = $versionParser->normalize($prettyVersion); } catch (\UnexpectedValueException $e) { $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', PHP_VERSION); $version = $versionParser->normalize($prettyVersion); } $php = new CompletePackage('php', $version, $prettyVersion); $php->setDescription('The PHP interpreter'); $this->addPackage($php); if (PHP_INT_SIZE === 8) { $php64 = new CompletePackage('php-64bit', $version, $prettyVersion); $php64->setDescription('The PHP interpreter, 64bit'); $this->addPackage($php64); } $loadedExtensions = get_loaded_extensions(); // Extensions scanning foreach ($loadedExtensions as $name) { if (in_array($name, array('standard', 'Core'))) { continue; } $reflExt = new \ReflectionExtension($name); try { $prettyVersion = $reflExt->getVersion(); $version = $versionParser->normalize($prettyVersion); } catch (\UnexpectedValueException $e) { $prettyVersion = '0'; $version = $versionParser->normalize($prettyVersion); } $packageName = $this->buildPackageName($name); $ext = new CompletePackage($packageName, $version, $prettyVersion); $ext->setDescription('The ' . $name . ' PHP extension'); $this->addPackage($ext); } // Another quick loop, just for possible libraries // Doing it this way to know that functions or constants exist before // relying on them. foreach ($loadedExtensions as $name) { $prettyVersion = null; $description = 'The ' . $name . ' PHP library'; switch ($name) { case 'curl': $curlVersion = curl_version(); $prettyVersion = $curlVersion['version']; break; case 'iconv': $prettyVersion = ICONV_VERSION; break; case 'intl': $name = 'ICU'; if (defined('INTL_ICU_VERSION')) { $prettyVersion = INTL_ICU_VERSION; } else { $reflector = new \ReflectionExtension('intl'); ob_start(); $reflector->info(); $output = ob_get_clean(); preg_match('/^ICU version => (.*)$/m', $output, $matches); $prettyVersion = $matches[1]; } break; case 'libxml': $prettyVersion = LIBXML_DOTTED_VERSION; break; case 'openssl': $prettyVersion = preg_replace_callback('{^(?:OpenSSL\\s*)?([0-9.]+)([a-z]*).*}', function ($match) { if (empty($match[2])) { return $match[1]; } // OpenSSL versions add another letter when they reach Z. // e.g. OpenSSL 0.9.8zh 3 Dec 2015 if (!preg_match('{^z*[a-z]$}', $match[2])) { // 0.9.8abc is garbage return 0; } $len = strlen($match[2]); $patchVersion = ($len - 1) * 26; // All Z $patchVersion += ord($match[2][$len - 1]) - 96; return $match[1] . '.' . $patchVersion; }, OPENSSL_VERSION_TEXT); $description = OPENSSL_VERSION_TEXT; break; case 'pcre': $prettyVersion = preg_replace('{^(\\S+).*}', '$1', PCRE_VERSION); break; case 'uuid': $prettyVersion = phpversion('uuid'); break; case 'xsl': $prettyVersion = LIBXSLT_DOTTED_VERSION; break; default: // None handled extensions have no special cases, skip continue 2; } try { $version = $versionParser->normalize($prettyVersion); } catch (\UnexpectedValueException $e) { continue; } $lib = new CompletePackage('lib-' . $name, $version, $prettyVersion); $lib->setDescription($description); $this->addPackage($lib); } if (defined('HHVM_VERSION')) { try { $prettyVersion = HHVM_VERSION; $version = $versionParser->normalize($prettyVersion); } catch (\UnexpectedValueException $e) { $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', HHVM_VERSION); $version = $versionParser->normalize($prettyVersion); } $hhvm = new CompletePackage('hhvm', $version, $prettyVersion); $hhvm->setDescription('The HHVM Runtime (64bit)'); $this->addPackage($hhvm); } }
/** * Builds CompletePackages from PEAR package definition data. * * @param ChannelInfo $channelInfo * @param SemverVersionParser $versionParser * @return CompletePackage */ private function buildComposerPackages(ChannelInfo $channelInfo, SemverVersionParser $versionParser) { $result = array(); foreach ($channelInfo->getPackages() as $packageDefinition) { foreach ($packageDefinition->getReleases() as $version => $releaseInfo) { try { $normalizedVersion = $versionParser->normalize($version); } catch (\UnexpectedValueException $e) { $this->io->writeError('Could not load ' . $packageDefinition->getPackageName() . ' ' . $version . ': ' . $e->getMessage(), true, IOInterface::VERBOSE); continue; } $composerPackageName = $this->buildComposerPackageName($packageDefinition->getChannelName(), $packageDefinition->getPackageName()); // distribution url must be read from /r/{packageName}/{version}.xml::/r/g:text() // but this location is 'de-facto' standard $urlBits = parse_url($this->url); $scheme = isset($urlBits['scheme']) && 'https' === $urlBits['scheme'] && extension_loaded('openssl') ? 'https' : 'http'; $distUrl = "{$scheme}://{$packageDefinition->getChannelName()}/get/{$packageDefinition->getPackageName()}-{$version}.tgz"; $requires = array(); $suggests = array(); $conflicts = array(); $replaces = array(); // alias package only when its channel matches repository channel, // cause we've know only repository channel alias if ($channelInfo->getName() == $packageDefinition->getChannelName()) { $composerPackageAlias = $this->buildComposerPackageName($channelInfo->getAlias(), $packageDefinition->getPackageName()); $aliasConstraint = new Constraint('==', $normalizedVersion); $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint); } // alias package with user-specified prefix. it makes private pear channels looks like composer's. if (!empty($this->vendorAlias) && ($this->vendorAlias != 'pear-' . $channelInfo->getAlias() || $channelInfo->getName() != $packageDefinition->getChannelName())) { $composerPackageAlias = "{$this->vendorAlias}/{$packageDefinition->getPackageName()}"; $aliasConstraint = new Constraint('==', $normalizedVersion); $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint); } foreach ($releaseInfo->getDependencyInfo()->getRequires() as $dependencyConstraint) { $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName()); $constraint = $versionParser->parseConstraints($dependencyConstraint->getConstraint()); $link = new Link($composerPackageName, $dependencyPackageName, $constraint, $dependencyConstraint->getType(), $dependencyConstraint->getConstraint()); switch ($dependencyConstraint->getType()) { case 'required': $requires[] = $link; break; case 'conflicts': $conflicts[] = $link; break; case 'replaces': $replaces[] = $link; break; } } foreach ($releaseInfo->getDependencyInfo()->getOptionals() as $group => $dependencyConstraints) { foreach ($dependencyConstraints as $dependencyConstraint) { $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName()); $suggests[$group . '-' . $dependencyPackageName] = $dependencyConstraint->getConstraint(); } } $package = new CompletePackage($composerPackageName, $normalizedVersion, $version); $package->setType('pear-library'); $package->setDescription($packageDefinition->getDescription()); $package->setLicense(array($packageDefinition->getLicense())); $package->setDistType('file'); $package->setDistUrl($distUrl); $package->setAutoload(array('classmap' => array(''))); $package->setIncludePaths(array('/')); $package->setRequires($requires); $package->setConflicts($conflicts); $package->setSuggests($suggests); $package->setReplaces($replaces); $result[] = $package; } } return $result; }
protected function execute(InputInterface $input, OutputInterface $output) { $composer = $this->getComposer(); $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'depends', $input, $output); $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); $platformOverrides = $composer->getConfig()->get('platform') ?: array(); $repo = new CompositeRepository(array(new ArrayRepository(array($composer->getPackage())), $composer->getRepositoryManager()->getLocalRepository(), new PlatformRepository(array(), $platformOverrides))); $needle = $input->getArgument('package'); $pool = new Pool(); $pool->addRepository($repo); $packages = $pool->whatProvides($needle); if (empty($packages)) { throw new \InvalidArgumentException('Could not find package "' . $needle . '" in your project.'); } $linkTypes = $this->linkTypes; $types = array_map(function ($type) use($linkTypes) { $type = rtrim($type, 's'); if (!isset($linkTypes[$type])) { throw new \InvalidArgumentException('Unexpected link type: ' . $type . ', valid types: ' . implode(', ', array_keys($linkTypes))); } return $type; }, $input->getOption('link-type')); $versionParser = new VersionParser(); $constraint = $versionParser->parseConstraints($input->getOption('match-constraint')); $matchInvert = $input->getOption('invert-match-constraint'); $needles = array($needle); if (true === $input->getOption('with-replaces')) { foreach ($packages as $package) { $needles = array_merge($needles, array_map(function (Link $link) { return $link->getTarget(); }, $package->getReplaces())); } } $messages = array(); $outputPackages = array(); $io = $this->getIO(); /** @var PackageInterface $package */ foreach ($repo->getPackages() as $package) { foreach ($types as $type) { /** @var Link $link */ foreach ($package->{'get' . $linkTypes[$type][0]}() as $link) { foreach ($needles as $needle) { if ($link->getTarget() === $needle && ($link->getConstraint()->matches($constraint) ? !$matchInvert : $matchInvert)) { if (!isset($outputPackages[$package->getName()])) { $messages[] = '<info>' . $package->getPrettyName() . '</info> ' . $linkTypes[$type][1] . ' ' . $needle . ' (<info>' . $link->getPrettyConstraint() . '</info>)'; $outputPackages[$package->getName()] = true; } } } } } } if ($messages) { sort($messages); $io->write($messages); } else { $matchText = ''; if ($input->getOption('match-constraint') !== '*') { $matchText = ' in versions ' . ($matchInvert ? 'not ' : '') . 'matching ' . $input->getOption('match-constraint'); } $io->writeError('<info>There is no installed package depending on "' . $needle . '"' . $matchText . '.</info>'); } }
private function createPackage($version) { $parser = new VersionParser(); return new Package('foo', $parser->normalize($version), $version); }