public function whatProvides(Pool $pool, $name) { if (isset($this->providers[$name])) { return $this->providers[$name]; } // skip platform packages if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name) || '__root__' === $name) { return array(); } if (null === $this->providerListing) { $this->loadProviderListings($this->loadRootServerFile()); } if ($this->lazyProvidersUrl && !isset($this->providerListing[$name])) { $hash = null; $url = str_replace('%package%', $name, $this->lazyProvidersUrl); $cacheKey = false; } elseif ($this->providersUrl) { // package does not exist in this repo if (!isset($this->providerListing[$name])) { return array(); } $hash = $this->providerListing[$name]['sha256']; $url = str_replace(array('%package%', '%hash%'), array($name, $hash), $this->providersUrl); $cacheKey = 'provider-' . strtr($name, '/', '$') . '.json'; } else { // BC handling for old providers-includes $url = 'p/' . $name . '.json'; // package does not exist in this repo if (!isset($this->providerListing[$url])) { return array(); } $hash = $this->providerListing[$url]['sha256']; $cacheKey = null; } if ($cacheKey && $this->cache->sha256($cacheKey) === $hash) { $packages = json_decode($this->cache->read($cacheKey), true); } else { $packages = $this->fetchFile($url, $cacheKey, $hash); } $this->providers[$name] = array(); foreach ($packages['packages'] as $versions) { foreach ($versions as $version) { // avoid loading the same objects twice if (isset($this->providersByUid[$version['uid']])) { // skip if already assigned if (!isset($this->providers[$name][$version['uid']])) { // expand alias in two packages if ($this->providersByUid[$version['uid']] instanceof AliasPackage) { $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']]->getAliasOf(); $this->providers[$name][$version['uid'] . '-alias'] = $this->providersByUid[$version['uid']]; } else { $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']]; } // check for root aliases if (isset($this->providersByUid[$version['uid'] . '-root'])) { $this->providers[$name][$version['uid'] . '-root'] = $this->providersByUid[$version['uid'] . '-root']; } } } else { if (isset($version['provide']) || isset($version['replace'])) { // collect names $names = array(strtolower($version['name']) => true); if (isset($version['provide'])) { foreach ($version['provide'] as $target => $constraint) { $names[strtolower($target)] = true; } } if (isset($version['replace'])) { foreach ($version['replace'] as $target => $constraint) { $names[strtolower($target)] = true; } } $names = array_keys($names); } else { $names = array(strtolower($version['name'])); } if (!$pool->isPackageAcceptable(strtolower($version['name']), VersionParser::parseStability($version['version']))) { continue; } // load acceptable packages in the providers $package = $this->createPackage($version, 'Composer\\Package\\Package'); $package->setRepository($this); if ($package instanceof AliasPackage) { $aliased = $package->getAliasOf(); $aliased->setRepository($this); $this->providers[$name][$version['uid']] = $aliased; $this->providers[$name][$version['uid'] . '-alias'] = $package; // override provider with its alias so it can be expanded in the if block above $this->providersByUid[$version['uid']] = $package; } else { $this->providers[$name][$version['uid']] = $package; $this->providersByUid[$version['uid']] = $package; } // handle root package aliases unset($rootAliasData); if (isset($this->rootAliases[$package->getName()][$package->getVersion()])) { $rootAliasData = $this->rootAliases[$package->getName()][$package->getVersion()]; } elseif ($package instanceof AliasPackage && isset($this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()])) { $rootAliasData = $this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()]; } if (isset($rootAliasData)) { $alias = $this->createAliasPackage($package, $rootAliasData['alias_normalized'], $rootAliasData['alias']); $alias->setRepository($this); $this->providers[$name][$version['uid'] . '-root'] = $alias; $this->providersByUid[$version['uid'] . '-root'] = $alias; } } } } return $this->providers[$name]; }
/** * @param Pool $pool * @param string $name package name * @param bool $bypassFilters If set to true, this bypasses the stability filtering, and forces a recompute without cache * @return array|mixed */ public function whatProvides(Pool $pool, $name, $bypassFilters = false) { if (isset($this->providers[$name]) && !$bypassFilters) { return $this->providers[$name]; } // skip platform packages, root package and composer-plugin-api if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name) || '__root__' === $name || 'composer-plugin-api' === $name) { return array(); } if (null === $this->providerListing) { $this->loadProviderListings($this->loadRootServerFile()); } $useLastModifiedCheck = false; if ($this->lazyProvidersUrl && !isset($this->providerListing[$name])) { $hash = null; $url = str_replace('%package%', $name, $this->lazyProvidersUrl); $cacheKey = 'provider-' . strtr($name, '/', '$') . '.json'; $useLastModifiedCheck = true; } elseif ($this->providersUrl) { // package does not exist in this repo if (!isset($this->providerListing[$name])) { return array(); } $hash = $this->providerListing[$name]['sha256']; $url = str_replace(array('%package%', '%hash%'), array($name, $hash), $this->providersUrl); $cacheKey = 'provider-' . strtr($name, '/', '$') . '.json'; } else { return array(); } $packages = null; if ($cacheKey) { if (!$useLastModifiedCheck && $hash && $this->cache->sha256($cacheKey) === $hash) { $packages = json_decode($this->cache->read($cacheKey), true); } elseif ($useLastModifiedCheck) { if ($contents = $this->cache->read($cacheKey)) { $contents = json_decode($contents, true); if (isset($contents['last-modified'])) { $response = $this->fetchFileIfLastModified($url, $cacheKey, $contents['last-modified']); if (true === $response) { $packages = $contents; } elseif ($response) { $packages = $response; } } } } } if (!$packages) { try { $packages = $this->fetchFile($url, $cacheKey, $hash, $useLastModifiedCheck); } catch (TransportException $e) { // 404s are acceptable for lazy provider repos if ($e->getStatusCode() === 404 && $this->lazyProvidersUrl) { $packages = array('packages' => array()); } else { throw $e; } } } $this->providers[$name] = array(); foreach ($packages['packages'] as $versions) { foreach ($versions as $version) { // avoid loading the same objects twice if (isset($this->providersByUid[$version['uid']])) { // skip if already assigned if (!isset($this->providers[$name][$version['uid']])) { // expand alias in two packages if ($this->providersByUid[$version['uid']] instanceof AliasPackage) { $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']]->getAliasOf(); $this->providers[$name][$version['uid'] . '-alias'] = $this->providersByUid[$version['uid']]; } else { $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']]; } // check for root aliases if (isset($this->providersByUid[$version['uid'] . '-root'])) { $this->providers[$name][$version['uid'] . '-root'] = $this->providersByUid[$version['uid'] . '-root']; } } } else { if (!$bypassFilters && !$pool->isPackageAcceptable(strtolower($version['name']), VersionParser::parseStability($version['version']))) { continue; } // load acceptable packages in the providers $package = $this->createPackage($version, 'Composer\\Package\\CompletePackage'); $package->setRepository($this); if ($package instanceof AliasPackage) { $aliased = $package->getAliasOf(); $aliased->setRepository($this); $this->providers[$name][$version['uid']] = $aliased; $this->providers[$name][$version['uid'] . '-alias'] = $package; // override provider with its alias so it can be expanded in the if block above $this->providersByUid[$version['uid']] = $package; } else { $this->providers[$name][$version['uid']] = $package; $this->providersByUid[$version['uid']] = $package; } // handle root package aliases unset($rootAliasData); if (isset($this->rootAliases[$package->getName()][$package->getVersion()])) { $rootAliasData = $this->rootAliases[$package->getName()][$package->getVersion()]; } elseif ($package instanceof AliasPackage && isset($this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()])) { $rootAliasData = $this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()]; } if (isset($rootAliasData)) { $alias = $this->createAliasPackage($package, $rootAliasData['alias_normalized'], $rootAliasData['alias']); $alias->setRepository($this); $this->providers[$name][$version['uid'] . '-root'] = $alias; $this->providersByUid[$version['uid'] . '-root'] = $alias; } } } } $result = $this->providers[$name]; // clean up the cache because otherwise using this puts the repo in an inconsistent state with a polluted unfiltered cache // which is likely not an issue but might cause hard to track behaviors depending on how the repo is used if ($bypassFilters) { foreach ($this->providers[$name] as $uid => $provider) { unset($this->providersByUid[$uid]); } unset($this->providers[$name]); } return $result; }
public function whatProvides(Pool $pool, $name) { // skip platform packages if ($name === 'php' || in_array(substr($name, 0, 4), array('ext-', 'lib-'), true) || $name === '__root__') { return array(); } if (isset($this->providers[$name])) { return $this->providers[$name]; } if (null === $this->providerListing) { $this->loadProviderListings($this->loadRootServerFile()); } $url = 'p/' . $name . '.json'; // package does not exist in this repo if (!isset($this->providerListing[$url])) { return array(); } if ($this->cache->sha256($url) === $this->providerListing[$url]['sha256']) { $packages = json_decode($this->cache->read($url), true); } else { $packages = $this->fetchFile($url, null, $this->providerListing[$url]['sha256']); } $this->providers[$name] = array(); foreach ($packages['packages'] as $versions) { foreach ($versions as $version) { // avoid loading the same objects twice if (isset($this->providersByUid[$version['uid']])) { // skip if already assigned if (!isset($this->providers[$name][$version['uid']])) { // expand alias in two packages if ($this->providersByUid[$version['uid']] instanceof AliasPackage) { $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']]->getAliasOf(); $this->providers[$name][$version['uid'] . '-alias'] = $this->providersByUid[$version['uid']]; } else { $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']]; } // check for root aliases if (isset($this->providersByUid[$version['uid'] . '-root'])) { $this->providers[$name][$version['uid'] . '-root'] = $this->providersByUid[$version['uid'] . '-root']; } } } else { if (!$pool->isPackageAcceptable(strtolower($version['name']), VersionParser::parseStability($version['version']))) { continue; } // load acceptable packages in the providers $package = $this->createPackage($version, 'Composer\\Package\\Package'); $package->setRepository($this); $this->providers[$name][$version['uid']] = $package; $this->providersByUid[$version['uid']] = $package; if ($package->getAlias()) { $alias = $this->createAliasPackage($package); $alias->setRepository($this); $this->providers[$name][$version['uid'] . '-alias'] = $alias; // override provider with its alias so it can be expanded in the if block above $this->providersByUid[$version['uid']] = $alias; } // handle root package aliases unset($rootAliasData); if (isset($this->rootAliases[$name][$package->getVersion()])) { $rootAliasData = $this->rootAliases[$name][$package->getVersion()]; } elseif (($aliasNormalized = $package->getAlias()) && isset($this->rootAliases[$name][$aliasNormalized])) { $rootAliasData = $this->rootAliases[$name][$aliasNormalized]; } if (isset($rootAliasData)) { $alias = $this->createAliasPackage($package, $rootAliasData['alias_normalized'], $rootAliasData['alias']); $alias->setRepository($this); $this->providers[$name][$version['uid'] . '-root'] = $alias; $this->providersByUid[$version['uid'] . '-root'] = $alias; } } } } return $this->providers[$name]; }
public function whatProvides(Pool $pool, $name) { if (isset($this->providers[$name])) { return $this->providers[$name]; } if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name) || '__root__' === $name) { return array(); } if (null === $this->providerListing) { $this->loadProviderListings($this->loadRootServerFile()); } if ($this->lazyProvidersUrl && !isset($this->providerListing[$name])) { $hash = null; $url = str_replace('%package%', $name, $this->lazyProvidersUrl); $cacheKey = false; } elseif ($this->providersUrl) { if (!isset($this->providerListing[$name])) { return array(); } $hash = $this->providerListing[$name]['sha256']; $url = str_replace(array('%package%', '%hash%'), array($name, $hash), $this->providersUrl); $cacheKey = 'provider-' . strtr($name, '/', '$') . '.json'; } else { $url = 'p/' . $name . '.json'; if (!isset($this->providerListing[$url])) { return array(); } $hash = $this->providerListing[$url]['sha256']; $cacheKey = null; } if ($cacheKey && $this->cache->sha256($cacheKey) === $hash) { $packages = json_decode($this->cache->read($cacheKey), true); } else { $packages = $this->fetchFile($url, $cacheKey, $hash); } $this->providers[$name] = array(); foreach ($packages['packages'] as $versions) { foreach ($versions as $version) { if (isset($this->providersByUid[$version['uid']])) { if (!isset($this->providers[$name][$version['uid']])) { if ($this->providersByUid[$version['uid']] instanceof AliasPackage) { $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']]->getAliasOf(); $this->providers[$name][$version['uid'] . '-alias'] = $this->providersByUid[$version['uid']]; } else { $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']]; } if (isset($this->providersByUid[$version['uid'] . '-root'])) { $this->providers[$name][$version['uid'] . '-root'] = $this->providersByUid[$version['uid'] . '-root']; } } } else { if (!$pool->isPackageAcceptable(strtolower($version['name']), VersionParser::parseStability($version['version']))) { continue; } $package = $this->createPackage($version, 'Composer\\Package\\Package'); $package->setRepository($this); if ($package instanceof AliasPackage) { $aliased = $package->getAliasOf(); $aliased->setRepository($this); $this->providers[$name][$version['uid']] = $aliased; $this->providers[$name][$version['uid'] . '-alias'] = $package; $this->providersByUid[$version['uid']] = $package; } else { $this->providers[$name][$version['uid']] = $package; $this->providersByUid[$version['uid']] = $package; } unset($rootAliasData); if (isset($this->rootAliases[$package->getName()][$package->getVersion()])) { $rootAliasData = $this->rootAliases[$package->getName()][$package->getVersion()]; } elseif ($package instanceof AliasPackage && isset($this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()])) { $rootAliasData = $this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()]; } if (isset($rootAliasData)) { $alias = $this->createAliasPackage($package, $rootAliasData['alias_normalized'], $rootAliasData['alias']); $alias->setRepository($this); $this->providers[$name][$version['uid'] . '-root'] = $alias; $this->providersByUid[$version['uid'] . '-root'] = $alias; } } } } return $this->providers[$name]; }
public function whatProvides(Pool $pool, $name, $bypassFilters = false) { // split on vendor and name if (count($parts = explode('/', $name)) !== 2) { return []; } list($vendor, $shortName) = $parts; // does the vendor match one of our virtual vendors? if (!isset($this->vendors[$vendor])) { return []; } // do we already have its packages? if (isset($this->providers[$name])) { return $this->providers[$name]; } // make sure the providers have been loaded $this->loadProviders(); // does the shortname even exist in this repo? if (!isset($this->providerHash[$shortName])) { return []; } // base url for the requested set of packages (i.e. the provider) // there should be no trailing slash $providerUrl = $this->providerHash[$shortName]; $packages = []; // get a listing of available packages // these are paths under the provider url where we should find actual packages foreach ((array) $this->repoConfig->get('package-paths') as $path) { // the relative path without surrounding slashes $relPath = trim($path, '/'); // if the path ends with a slash, we grab its subdirectories if (substr($path, -1) === '/') { // try to fetch the packages! try { if ($this->io->isVerbose()) { $this->io->writeError("Fetching available versions for {$name}"); } $pkgRaw = $this->svnUtil->execute('ls', "{$providerUrl}/{$relPath}"); } catch (\RuntimeException $e) { // @todo maybe don't throw an exception and just pass this one up? throw new \RuntimeException("SVN Error: Could not retrieve package listing for {$name}. " . $e->getMessage()); } // check the versions and add any good ones to the set foreach (SvnUtil::parseSvnList($pkgRaw) as $version) { // format the version identifier to be composer-compatible $version = Util::fixVersion($version, 'dev-default'); $version = Util::callFilter($this->repoConfig->get('version-filter'), $version, $name, $path, $providerUrl); // if the version string is empty, we don't take it if (!empty($version)) { $packages[$version] = trim("{$relPath}/{$version}", '/'); } } } else { // otherwise we add as-is (no checking is performed to see if this reference really exists) // @todo: perhaps add an optional check? $version = Util::fixVersion(basename($path), 'dev-default'); $version = Util::callFilter($this->repoConfig->get('version-filter'), $version, $name, $path, $providerUrl); // if the version string is empty, we don't take it if (!empty($version)) { $packages[$version] = $relPath; } } } // store the providers based on its full name (i.e. with vendor) // this allows the same package to be loaded as different types, // which allows the package type to be changed in composer.json, // i.e. the type that is being removed AND the type that is being installed // both have to exist during the solving $this->providers[$name] = []; // create a package for each tag foreach ($packages as $version => $reference) { if (!$pool->isPackageAcceptable($shortName, VersionParser::parseStability($version))) { continue; } // first, setup the repo-determined package properties $data = ['name' => $name, 'version' => $version, 'type' => $this->vendors[$vendor], 'source' => ['type' => 'svn', 'url' => "{$providerUrl}/", 'reference' => $reference ?: '/']]; // next, fill in any defaults that were missing if (($defaults = $this->repoConfig->get('package-defaults')) && is_array($defaults)) { $data = array_merge($defaults, $data); } // finally, apply any overrides if (($overrides = $this->repoConfig->get('package-overrides')) && is_array($overrides)) { $data = array_replace($data, $overrides); } // create the package object $package = $this->createPackage($data, 'Composer\\Package\\CompletePackage'); $package->setRepository($this); // add "replaces" array for any other vendors that this repository supports if (count($this->vendors) > 1) { $replaces = []; $constraint = new Constraint('=', $package->getVersion()); foreach ($this->vendors as $vendorName => $type) { // it doesn't replace itself if ($vendorName === $vendor) { continue; } $replaces[] = new Link($package->getName(), "{$vendorName}/{$shortName}", $constraint, "'{$type}' alias for", $package->getPrettyVersion()); } $package->setReplaces($replaces); } // apply a filter to the package object Util::callFilter($this->repoConfig->get('package-filter'), $package); // add the package object to the set $this->providers[$name][$version] = $package; // handle root aliases // @todo: not sure if this is correct (this was copped from the parent class) if (isset($this->rootAliases[$package->getName()][$package->getVersion()])) { $rootAliasData = $this->rootAliases[$package->getName()][$package->getVersion()]; $alias = $this->createAliasPackage($package, $rootAliasData['alias_normalized'], $rootAliasData['alias']); $alias->setRepository($this); $this->providers[$name][$version . '-root'] = $alias; } } return $this->providers[$name]; }