1
0
Fork 0

PHPStan level 6 in src/Composer/Repository (#10197)

pull/10211/head
Anatoly Pashin 2021-10-25 20:58:31 +10:00 committed by GitHub
parent 3fa7a6cb51
commit b1a96a3141
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 393 additions and 61 deletions

View File

@ -14,6 +14,7 @@ namespace Composer\Command;
use Composer\Package\Link;
use Composer\Package\PackageInterface;
use Composer\Package\CompletePackageInterface;
use Composer\Package\RootPackage;
use Composer\Repository\InstalledArrayRepository;
use Composer\Repository\CompositeRepository;
@ -121,7 +122,7 @@ class BaseDependencyCommand extends BaseCommand
} elseif ($renderTree) {
$this->initStyles($output);
$root = $packages[0];
$this->getIO()->write(sprintf('<info>%s</info> %s %s', $root->getPrettyName(), $root->getPrettyVersion(), $root->getDescription()));
$this->getIO()->write(sprintf('<info>%s</info> %s %s', $root->getPrettyName(), $root->getPrettyVersion(), $root instanceof CompletePackageInterface ? $root->getDescription() : ''));
$this->printTree($results);
} else {
$this->printTable($output, $results);

View File

@ -430,7 +430,7 @@ EOT
$packageViewData['latest-status'] = $this->getUpdateStatus($latestPackage, $package);
$latestLength = max($latestLength, strlen($latestPackage->getFullPrettyVersion()));
}
if ($writeDescription) {
if ($writeDescription && $package instanceof CompletePackageInterface) {
$packageViewData['description'] = $package->getDescription();
}
if ($writePath) {

View File

@ -38,6 +38,9 @@ class ArrayRepository implements RepositoryInterface
*/
protected $packageMap = null;
/**
* @param array<PackageInterface> $packages
*/
public function __construct(array $packages = array())
{
foreach ($packages as $package) {
@ -188,6 +191,8 @@ class ArrayRepository implements RepositoryInterface
* Adds a new package to the repository
*
* @param PackageInterface $package
*
* @return void
*/
public function addPackage(PackageInterface $package)
{
@ -236,6 +241,9 @@ class ArrayRepository implements RepositoryInterface
/**
* @phpstan-param PackageInterface&BasePackage $package
* @param string $alias
* @param string $prettyAlias
*
* @return AliasPackage|CompleteAliasPackage
*/
protected function createAliasPackage(PackageInterface $package, $alias, $prettyAlias)
@ -255,6 +263,8 @@ class ArrayRepository implements RepositoryInterface
* Removes package from repository.
*
* @param PackageInterface $package package instance
*
* @return void
*/
public function removePackage(PackageInterface $package)
{
@ -305,6 +315,8 @@ class ArrayRepository implements RepositoryInterface
/**
* Initializes the packages array. Mostly meant as an extension point.
*
* @return void
*/
protected function initialize()
{

View File

@ -14,6 +14,7 @@ namespace Composer\Repository;
use Composer\IO\IOInterface;
use Composer\Json\JsonFile;
use Composer\Package\BasePackage;
use Composer\Package\Loader\ArrayLoader;
use Composer\Package\Loader\LoaderInterface;
use Composer\Util\Tar;
@ -29,11 +30,14 @@ class ArtifactRepository extends ArrayRepository implements ConfigurableReposito
/** @var string */
protected $lookup;
/** @var mixed[] */
/** @var array{url: string} */
protected $repoConfig;
/** @var IOInterface */
private $io;
/**
* @param array{url: string} $repoConfig
*/
public function __construct(array $repoConfig, IOInterface $io)
{
parent::__construct();
@ -64,6 +68,11 @@ class ArtifactRepository extends ArrayRepository implements ConfigurableReposito
$this->scanDirectory($this->lookup);
}
/**
* @param string $path
*
* @return void
*/
private function scanDirectory($path)
{
$io = $this->io;
@ -90,6 +99,9 @@ class ArtifactRepository extends ArrayRepository implements ConfigurableReposito
}
}
/**
* @return ?BasePackage
*/
private function getComposerInformation(\SplFileInfo $file)
{
$json = null;
@ -114,7 +126,7 @@ class ArtifactRepository extends ArrayRepository implements ConfigurableReposito
}
if (null === $json) {
return false;
return null;
}
$package = JsonFile::parseJson($json, $file->getPathname().'#composer.json');

View File

@ -128,6 +128,10 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
*/
public $versionParser;
/**
* @param array<string, mixed> $repoConfig
* @phpstan-param array{url: string, options?: mixed[], type?: 'composer', allow_ssl_downgrade?: bool} $repoConfig
*/
public function __construct(array $repoConfig, IOInterface $io, Config $config, HttpDownloader $httpDownloader, EventDispatcher $eventDispatcher = null)
{
parent::__construct();
@ -263,6 +267,13 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
return parent::findPackages($name, $constraint);
}
/**
* @param array<BasePackage> $packages
* @param ConstraintInterface|null $constraint
* @param bool $returnFirstMatch
*
* @return BasePackage|array<BasePackage>|null
*/
private function filterPackages(array $packages, $constraint = null, $returnFirstMatch = false)
{
if (null === $constraint) {
@ -324,6 +335,11 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
return parent::getPackages();
}
/**
* @param string|null $packageFilter
*
* @return string[]
*/
public function getPackageNames($packageFilter = null)
{
$hasProviders = $this->hasProviders();
@ -523,6 +539,9 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
return $result;
}
/**
* @return string[]
*/
private function getProviderNames()
{
$this->loadRootServerFile();
@ -543,6 +562,9 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
return array();
}
/**
* @return void
*/
protected function configurePackageTransportOptions(PackageInterface $package)
{
foreach ($package->getDistUrls() as $url) {
@ -554,6 +576,9 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
}
}
/**
* @return bool
*/
private function hasProviders()
{
$this->loadRootServerFile();
@ -563,7 +588,13 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
/**
* @param string $name package name
* @return array|mixed
* @param array<string, int>|null $acceptableStabilities
* @phpstan-param array<string, BasePackage::STABILITY_*>|null $acceptableStabilities
* @param array<string, int>|null $stabilityFlags an array of package name => BasePackage::STABILITY_* value
* @phpstan-param array<string, BasePackage::STABILITY_*>|null $stabilityFlags
* @param array<string, array<string, PackageInterface>> $alreadyLoaded
*
* @return array<string, BasePackage>
*/
private function whatProvides($name, array $acceptableStabilities = null, array $stabilityFlags = null, array $alreadyLoaded = array())
{
@ -724,7 +755,14 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
}
/**
* @param array $packageNames array of package name => ConstraintInterface|null - if a constraint is provided, only packages matching it will be loaded
* @param array<string, ConstraintInterface|null> $packageNames array of package name => ConstraintInterface|null - if a constraint is provided, only packages matching it will be loaded
* @param array<string, int>|null $acceptableStabilities
* @phpstan-param array<string, BasePackage::STABILITY_*>|null $acceptableStabilities
* @param array<string, int>|null $stabilityFlags an array of package name => BasePackage::STABILITY_* value
* @phpstan-param array<string, BasePackage::STABILITY_*>|null $stabilityFlags
* @param array<string, array<string, PackageInterface>> $alreadyLoaded
*
* @return array{namesFound: array<string, true>, packages: array<string, BasePackage>}
*/
private function loadAsyncPackages(array $packageNames, array $acceptableStabilities = null, array $stabilityFlags = null, array $alreadyLoaded = array())
{
@ -829,8 +867,17 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
/**
* TODO v3 should make this private once we can drop PHP 5.3 support
*
* @param string $name package name (must be lowercased already)
* @private
*
* @param ConstraintInterface|null $constraint
* @param string $name package name (must be lowercased already)
* @param array<string, mixed> $versionData
* @param array<string, int>|null $acceptableStabilities
* @phpstan-param array<string, BasePackage::STABILITY_*>|null $acceptableStabilities
* @param array<string, int>|null $stabilityFlags an array of package name => BasePackage::STABILITY_* value
* @phpstan-param array<string, BasePackage::STABILITY_*>|null $stabilityFlags
*
* @return bool
*/
public function isVersionAcceptable($constraint, $name, $versionData, array $acceptableStabilities = null, array $stabilityFlags = null)
{
@ -855,6 +902,9 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
return false;
}
/**
* @return string
*/
private function getPackagesJsonUrl()
{
$jsonUrlParts = parse_url($this->url);
@ -866,6 +916,9 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
return $this->url . '/packages.json';
}
/**
* @return array<string, mixed>
*/
protected function loadRootServerFile()
{
if (null !== $this->rootData) {
@ -977,6 +1030,11 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
return $this->rootData = $data;
}
/**
* @param string $url
*
* @return string
*/
private function canonicalizeUrl($url)
{
if ('/' === $url[0]) {
@ -990,6 +1048,9 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
return $url;
}
/**
* @return array[]
*/
private function loadDataFromServer()
{
$data = $this->loadRootServerFile();
@ -997,6 +1058,9 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
return $this->loadIncludes($data);
}
/**
* @return bool
*/
private function hasPartialPackages()
{
if ($this->hasPartialPackages && null === $this->partialPackagesByName) {
@ -1006,6 +1070,11 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
return $this->hasPartialPackages;
}
/**
* @param array{providers?: array, provider-includes?: array} $data
*
* @return void
*/
private function loadProviderListings($data)
{
if (isset($data['providers'])) {
@ -1031,6 +1100,11 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
}
}
/**
* @param array[] $data
*
* @return array[]
*/
private function loadIncludes($data)
{
$packages = array();
@ -1072,8 +1146,11 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
/**
* TODO v3 should make this private once we can drop PHP 5.3 support
*
* @private
*
* @param array[] $packages
* @param string|null $source
*
* @return list<CompletePackage|CompleteAliasPackage>
*/
public function createPackages(array $packages, $source = null)
@ -1105,6 +1182,14 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
}
}
/**
* @param string $filename
* @param string|null $cacheKey
* @param string|null $sha256
* @param bool $storeLastModifiedTime
*
* @return array<mixed>
*/
protected function fetchFile($filename, $cacheKey = null, $sha256 = null, $storeLastModifiedTime = false)
{
if (null === $cacheKey) {
@ -1218,6 +1303,13 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
return $data;
}
/**
* @param string $filename
* @param string $cacheKey
* @param string $lastModifiedTime
*
* @return array<mixed>|true
*/
private function fetchFileIfLastModified($filename, $cacheKey, $lastModifiedTime)
{
$retries = 3;
@ -1283,8 +1375,17 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
return true;
}
}
throw new \LogicException('Should not happen');
}
/**
* @param string $filename
* @param string $cacheKey
* @param string|null $lastModifiedTime
*
* @return \React\Promise\PromiseInterface
*/
private function asyncFetchFile($filename, $cacheKey, $lastModifiedTime = null)
{
$retries = 3;
@ -1410,6 +1511,8 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
* This initializes the packages key of a partial packages.json that contain some packages inlined + a providers-lazy-url
*
* This should only be called once
*
* @return void
*/
private function initializePartialPackages()
{

View File

@ -49,7 +49,7 @@ class CompositeRepository implements RepositoryInterface
/**
* Returns all the wrapped repositories
*
* @return array
* @return RepositoryInterface[]
*/
public function getRepositories()
{
@ -164,7 +164,7 @@ class CompositeRepository implements RepositoryInterface
}
/**
* {@inheritdoc}
* @return void
*/
public function removePackage(PackageInterface $package)
{
@ -193,6 +193,8 @@ class CompositeRepository implements RepositoryInterface
/**
* Add a repository.
* @param RepositoryInterface $repository
*
* @return void
*/
public function addRepository(RepositoryInterface $repository)
{

View File

@ -154,6 +154,12 @@ class FilesystemRepository extends WritableArrayRepository
}
}
/**
* @param array<mixed> $array
* @param int $level
*
* @return string
*/
private function dumpToPhpCode(array $array = array(), $level = 0)
{
$lines = "array(\n";
@ -186,7 +192,11 @@ class FilesystemRepository extends WritableArrayRepository
}
/**
* @return ?array
* @param array<string, string> $installPaths
* @param bool $devMode
* @param string $repoDir
*
* @return ?array<mixed>
*/
private function generateInstalledVersions(InstallationManager $installationManager, array $installPaths, $devMode, $repoDir)
{

View File

@ -31,6 +31,9 @@ class FilterRepository implements RepositoryInterface
/** @var RepositoryInterface */
private $repo;
/**
* @param array{only?: array<string>, exclude?: array<string>, canonical?: bool} $options
*/
public function __construct(RepositoryInterface $repo, array $options)
{
if (isset($options['only'])) {
@ -191,6 +194,11 @@ class FilterRepository implements RepositoryInterface
return 0;
}
/**
* @param string $name
*
* @return bool
*/
private function isAllowed($name)
{
if (!$this->only && !$this->exclude) {

View File

@ -12,6 +12,8 @@
namespace Composer\Repository;
use Composer\Package\BasePackage;
use Composer\Package\PackageInterface;
use Composer\Package\Version\VersionParser;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Semver\Constraint\Constraint;
@ -30,6 +32,12 @@ use Composer\Package\Link;
*/
class InstalledRepository extends CompositeRepository
{
/**
* @param string $name
* @param ConstraintInterface|string|null $constraint
*
* @return BasePackage[]
*/
public function findPackagesWithReplacersAndProviders($name, $constraint = null)
{
$name = strtolower($name);
@ -52,7 +60,7 @@ class InstalledRepository extends CompositeRepository
foreach (array_merge($candidate->getProvides(), $candidate->getReplaces()) as $link) {
if (
$name === $link->getTarget()
&& ($constraint === null || $link->getConstraint() === null || $constraint->matches($link->getConstraint()))
&& ($constraint === null || $constraint->matches($link->getConstraint()))
) {
$matches[] = $candidate;
continue 2;
@ -75,7 +83,9 @@ class InstalledRepository extends CompositeRepository
* @param bool $invert Whether to invert matches to discover reasons for the package *NOT* to be installed.
* @param bool $recurse Whether to recursively expand the requirement tree up to the root package.
* @param string[] $packagesFound Used internally when recurring
* @return array An associative array of arrays as described above.
*
* @return array[] An associative array of arrays as described above.
* @phpstan-return array<array{0: PackageInterface, 1: Link, 2: mixed[]|bool}>
*/
public function getDependents($needle, $constraint = null, $invert = false, $recurse = true, $packagesFound = null)
{
@ -247,8 +257,7 @@ class InstalledRepository extends CompositeRepository
}
/**
* Add a repository.
* @param RepositoryInterface $repository
* {@inheritDoc}
*/
public function addRepository(RepositoryInterface $repository)
{
@ -258,7 +267,9 @@ class InstalledRepository extends CompositeRepository
|| $repository instanceof RootPackageRepository
|| $repository instanceof PlatformRepository
) {
return parent::addRepository($repository);
parent::addRepository($repository);
return;
}
throw new \LogicException('An InstalledRepository can not contain a repository of type '.get_class($repository).' ('.$repository->getRepoName().')');

View File

@ -28,7 +28,7 @@ class PackageRepository extends ArrayRepository
/**
* Initializes filesystem repository.
*
* @param array $config package definition
* @param array{package: array} $config package definition
*/
public function __construct(array $config)
{

View File

@ -95,7 +95,7 @@ class PathRepository extends ArrayRepository implements ConfigurableRepositoryIn
/**
* Initializes path repository.
*
* @param array $repoConfig
* @param array{url: string, options?: array{symlink?: bool, relative?: bool, versions?: array<string, string>}} $repoConfig
* @param IOInterface $io
* @param Config $config
*/

View File

@ -57,6 +57,9 @@ class PlatformRepository extends ArrayRepository
/** @var HhvmDetector */
private $hhvmDetector;
/**
* @param array<string, string> $overrides
*/
public function __construct(array $packages = array(), array $overrides = array(), Runtime $runtime = null, HhvmDetector $hhvmDetector = null)
{
$this->runtime = $runtime ?: new Runtime();
@ -523,6 +526,9 @@ class PlatformRepository extends ArrayRepository
}
/**
* @param array{version: string, name: string} $override
* @param string|null $name
*
* @return CompletePackage
*/
private function addOverriddenPackage(array $override, $name = null)
@ -545,6 +551,8 @@ class PlatformRepository extends ArrayRepository
*
* @param string $name
* @param null|string $prettyVersion
*
* @return void
*/
private function addExtension($name, $prettyVersion)
{
@ -590,6 +598,8 @@ class PlatformRepository extends ArrayRepository
* @param string|null $description
* @param string[] $replaces
* @param string[] $provides
*
* @return void
*/
private function addLibrary($name, $prettyVersion, $description = null, array $replaces = array(), array $provides = array())
{
@ -640,6 +650,7 @@ class PlatformRepository extends ArrayRepository
* be correct.
*
* @internal
* @return string|null
*/
public static function getPlatformPhpVersion()
{

View File

@ -73,7 +73,7 @@ class RepositoryFactory
/**
* @param IOInterface $io
* @param Config $config
* @param array $repoConfig
* @param array<string, mixed> $repoConfig
* @return RepositoryInterface
*/
public static function createRepo(IOInterface $io, Config $config, array $repoConfig, RepositoryManager $rm = null)
@ -140,6 +140,8 @@ class RepositoryFactory
}
/**
* @param array<int|string, mixed> $repoConfigs
*
* @return RepositoryInterface[]
*/
private static function createRepos(RepositoryManager $rm, array $repoConfigs)
@ -168,6 +170,13 @@ class RepositoryFactory
return $repos;
}
/**
* @param int|string $index
* @param array{url?: string} $repo
* @param array<string, mixed> $existingRepos
*
* @return string
*/
public static function generateRepositoryName($index, array $repo, array $existingRepos)
{
$name = is_int($index) && isset($repo['url']) ? preg_replace('{^https?://}i', '', $repo['url']) : $index;

View File

@ -43,8 +43,7 @@ interface RepositoryInterface extends \Countable
* @param string $name package name
* @param string|ConstraintInterface $constraint package version or version constraint to match against
*
* @return PackageInterface|null
* @phpstan-return (BasePackage&PackageInterface)|null
* @return BasePackage|null
*/
public function findPackage($name, $constraint);
@ -54,16 +53,14 @@ interface RepositoryInterface extends \Countable
* @param string $name package name
* @param string|ConstraintInterface $constraint package version or version constraint to match against
*
* @return PackageInterface[]
* @phpstan-return array<BasePackage&PackageInterface>
* @return BasePackage[]
*/
public function findPackages($name, $constraint = null);
/**
* Returns list of registered packages.
*
* @return PackageInterface[]
* @phpstan-return array<BasePackage&PackageInterface>
* @return BasePackage[]
*/
public function getPackages();
@ -81,7 +78,7 @@ interface RepositoryInterface extends \Countable
* @return array
*
* @phpstan-param array<string, ConstraintInterface|null> $packageNameMap
* @phpstan-return array{namesFound: string[], packages: array<BasePackage&PackageInterface>}
* @phpstan-return array{namesFound: array<string>, packages: array<BasePackage>}
*/
public function loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = array());

View File

@ -32,7 +32,7 @@ class RepositoryManager
private $localRepository;
/** @var list<RepositoryInterface> */
private $repositories = array();
/** @var array<string, string> */
/** @var array<string, class-string<RepositoryInterface>> */
private $repositoryClasses = array();
/** @var IOInterface */
private $io;
@ -97,6 +97,8 @@ class RepositoryManager
* Adds repository
*
* @param RepositoryInterface $repository repository instance
*
* @return void
*/
public function addRepository(RepositoryInterface $repository)
{
@ -109,6 +111,8 @@ class RepositoryManager
* This is useful when injecting additional repositories that should trump Packagist, e.g. from a plugin.
*
* @param RepositoryInterface $repository repository instance
*
* @return void
*/
public function prependRepository(RepositoryInterface $repository)
{
@ -119,7 +123,7 @@ class RepositoryManager
* Returns a new repository for a specific installation type.
*
* @param string $type repository type
* @param array $config repository configuration
* @param array<string, mixed> $config repository configuration
* @param string $name repository name
* @throws \InvalidArgumentException if repository for provided type is not registered
* @return RepositoryInterface
@ -154,7 +158,9 @@ class RepositoryManager
* Stores repository class for a specific installation type.
*
* @param string $type installation type
* @param string $class class name of the repo implementation
* @param class-string<RepositoryInterface> $class class name of the repo implementation
*
* @return void
*/
public function setRepositoryClass($type, $class)
{
@ -175,6 +181,8 @@ class RepositoryManager
* Sets local repository for the project.
*
* @param InstalledRepositoryInterface $repository repository instance
*
* @return void
*/
public function setLocalRepository(InstalledRepositoryInterface $repository)
{

View File

@ -23,6 +23,7 @@ use Composer\Package\AliasPackage;
use Composer\Package\CompleteAliasPackage;
use Composer\Package\CompletePackage;
use Composer\Package\CompletePackageInterface;
use Composer\Package\PackageInterface;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Package\Version\StabilityFilter;
@ -113,6 +114,11 @@ class RepositorySet
}
}
/**
* @param bool $allow
*
* @return void
*/
public function allowInstalledRepositories($allow = true)
{
$this->allowInstalledRepositories = $allow;
@ -134,6 +140,8 @@ class RepositorySet
* repository the search for that package ends, and following repos will not be consulted.
*
* @param RepositoryInterface $repo A package repository
*
* @return void
*/
public function addRepository(RepositoryInterface $repo)
{
@ -160,7 +168,7 @@ class RepositorySet
* @param string $name
* @param ConstraintInterface|null $constraint
* @param int $flags any of the ALLOW_* constants from this class to tweak what is returned
* @return array
* @return BasePackage[]
*/
public function findPackages($name, ConstraintInterface $constraint = null, $flags = 0)
{
@ -292,12 +300,22 @@ class RepositorySet
return new Pool($packages);
}
// TODO unify this with above in some simpler version without "request"?
/**
* @param string $packageName
*
* @return Pool
*/
public function createPoolForPackage($packageName, LockArrayRepository $lockedRepo = null)
{
// TODO unify this with above in some simpler version without "request"?
return $this->createPoolForPackages(array($packageName), $lockedRepo);
}
/**
* @param string[] $packageNames
*
* @return Pool
*/
public function createPoolForPackages($packageNames, LockArrayRepository $lockedRepo = null)
{
$request = new Request($lockedRepo);
@ -313,6 +331,12 @@ class RepositorySet
return $this->createPool($request, new NullIO());
}
/**
* @param array[] $aliases
* @phpstan-param list<array{package: string, version: string, alias: string, alias_normalized: string}> $aliases
*
* @return array<string, array<string, array{alias: string, alias_normalized: string}>>
*/
private static function getRootAliasesPerPackage(array $aliases)
{
$normalizedAliases = array();

View File

@ -393,11 +393,11 @@ abstract class BitbucketDriver extends VcsDriver
}
if (!$this->io->isInteractive() && $fetchingRepoData) {
if ($this->attemptCloneFallback()) {
$this->attemptCloneFallback();
return new Response(array('url' => 'dummy'), 200, array(), 'null');
}
}
}
throw $e;
}
@ -412,6 +412,9 @@ abstract class BitbucketDriver extends VcsDriver
/**
* @phpstan-impure
*
* @return true
* @throws \RuntimeException
*/
protected function attemptCloneFallback()
{
@ -437,7 +440,7 @@ abstract class BitbucketDriver extends VcsDriver
abstract protected function setupFallbackDriver($url);
/**
* @param array $cloneLinks
* @param array<array{name: string, href: string}> $cloneLinks
* @return void
*/
protected function parseCloneUrls(array $cloneLinks)
@ -452,7 +455,7 @@ abstract class BitbucketDriver extends VcsDriver
}
/**
* @return array|null
* @return (array{name: string}&mixed[])|null
*/
protected function getMainBranchData()
{

View File

@ -67,6 +67,8 @@ class FossilDriver extends VcsDriver
/**
* Check that fossil can be invoked via command line.
*
* @return void
*/
protected function checkFossil()
{
@ -77,6 +79,8 @@ class FossilDriver extends VcsDriver
/**
* Clone or update existing local fossil repository.
*
* @return void
*/
protected function updateLocalRepo()
{

View File

@ -77,6 +77,9 @@ class GitHubDriver extends VcsDriver
$this->fetchRootIdentifier();
}
/**
* @return string
*/
public function getRepositoryUrl()
{
return 'https://'.$this->originUrl.'/'.$this->owner.'/'.$this->repository;
@ -107,7 +110,7 @@ class GitHubDriver extends VcsDriver
}
/**
* {@inheritDoc}
* @return string
*/
protected function getApiUrl()
{
@ -192,6 +195,9 @@ class GitHubDriver extends VcsDriver
return $this->infoCache[$identifier];
}
/**
* @return array<int, array{type: string, url: string}>|false
*/
private function getFundingInfo()
{
if (null !== $this->fundingInfo) {
@ -388,7 +394,7 @@ class GitHubDriver extends VcsDriver
/**
* Gives back the loaded <github-api>/repos/<owner>/<repo> result
*
* @return array|null
* @return mixed[]|null
*/
public function getRepoData()
{
@ -413,6 +419,8 @@ class GitHubDriver extends VcsDriver
/**
* {@inheritDoc}
*
* @param bool $fetchingRepoData
*/
protected function getContents($url, $fetchingRepoData = false)
{
@ -434,10 +442,10 @@ class GitHubDriver extends VcsDriver
}
if (!$this->io->isInteractive()) {
if ($this->attemptCloneFallback()) {
$this->attemptCloneFallback();
return new Response(array('url' => 'dummy'), 200, array(), 'null');
}
}
$scopesIssued = array();
$scopesNeeded = array();
@ -464,10 +472,10 @@ class GitHubDriver extends VcsDriver
}
if (!$this->io->isInteractive() && $fetchingRepoData) {
if ($this->attemptCloneFallback()) {
$this->attemptCloneFallback();
return new Response(array('url' => 'dummy'), 200, array(), 'null');
}
}
$rateLimited = $gitHubUtil->isRateLimited((array) $e->getHeaders());
@ -502,6 +510,7 @@ class GitHubDriver extends VcsDriver
/**
* Fetch root identifier from GitHub
*
* @return void
* @throws TransportException
*/
protected function fetchRootIdentifier()
@ -540,6 +549,12 @@ class GitHubDriver extends VcsDriver
$this->isArchived = !empty($this->repoData['archived']);
}
/**
* @phpstan-impure
*
* @return true
* @throws \RuntimeException
*/
protected function attemptCloneFallback()
{
$this->isPrivate = true;
@ -560,6 +575,11 @@ class GitHubDriver extends VcsDriver
}
}
/**
* @param string $url
*
* @return void
*/
protected function setupGitDriver($url)
{
$this->gitDriver = new GitDriver(
@ -572,12 +592,14 @@ class GitHubDriver extends VcsDriver
$this->gitDriver->initialize();
}
/**
* @return string|null
*/
protected function getNextPage(Response $response)
{
$header = $response->getHeader('link');
if (!$header) {
return;
return null;
}
$links = explode(',', $header);
@ -586,5 +608,7 @@ class GitHubDriver extends VcsDriver
return $match[1];
}
}
return null;
}
}

View File

@ -132,6 +132,8 @@ class GitLabDriver extends VcsDriver
* Mainly useful for tests.
*
* @internal
*
* @return void
*/
public function setHttpDownloader(HttpDownloader $httpDownloader)
{
@ -223,7 +225,7 @@ class GitLabDriver extends VcsDriver
}
/**
* {@inheritDoc}
* @return string
*/
public function getRepositoryUrl()
{
@ -373,6 +375,9 @@ class GitLabDriver extends VcsDriver
return $references;
}
/**
* @return void
*/
protected function fetchProject()
{
// we need to fetch the default branch from the api
@ -386,6 +391,12 @@ class GitLabDriver extends VcsDriver
}
}
/**
* @phpstan-impure
*
* @return true
* @throws \RuntimeException
*/
protected function attemptCloneFallback()
{
if ($this->isPrivate === false) {
@ -423,11 +434,19 @@ class GitLabDriver extends VcsDriver
return 'git@' . $this->originUrl . ':'.$this->namespace.'/'.$this->repository.'.git';
}
/**
* @return string
*/
protected function generatePublicUrl()
{
return $this->scheme . '://' . $this->originUrl . '/'.$this->namespace.'/'.$this->repository.'.git';
}
/**
* @param string $url
*
* @return void
*/
protected function setupGitDriver($url)
{
$this->gitDriver = new GitDriver(
@ -442,6 +461,8 @@ class GitLabDriver extends VcsDriver
/**
* {@inheritDoc}
*
* @param bool $fetchingRepoData
*/
protected function getContents($url, $fetchingRepoData = false)
{
@ -470,7 +491,9 @@ class GitLabDriver extends VcsDriver
if (!$moreThanGuestAccess) {
$this->io->writeError('<warning>GitLab token with Guest only access detected</warning>');
return $this->attemptCloneFallback();
$this->attemptCloneFallback();
return new Response(array('url' => 'dummy'), 200, array(), 'null');
}
}
@ -501,10 +524,10 @@ class GitLabDriver extends VcsDriver
}
if (!$this->io->isInteractive()) {
if ($this->attemptCloneFallback()) {
$this->attemptCloneFallback();
return new Response(array('url' => 'dummy'), 200, array(), 'null');
}
}
$this->io->writeError('<warning>Failed to download ' . $this->namespace . '/' . $this->repository . ':' . $e->getMessage() . '</warning>');
$gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, 'Your credentials are required to fetch private repository metadata (<info>'.$this->url.'</info>)');
@ -516,10 +539,10 @@ class GitLabDriver extends VcsDriver
}
if (!$this->io->isInteractive() && $fetchingRepoData) {
if ($this->attemptCloneFallback()) {
$this->attemptCloneFallback();
return new Response(array('url' => 'dummy'), 200, array(), 'null');
}
}
throw $e;
@ -558,6 +581,9 @@ class GitLabDriver extends VcsDriver
return true;
}
/**
* @return string|null
*/
protected function getNextPage(Response $response)
{
$header = $response->getHeader('link');
@ -568,13 +594,17 @@ class GitLabDriver extends VcsDriver
return $match[1];
}
}
return null;
}
/**
* @param array $configuredDomains
* @param array<string> $configuredDomains
* @param string $guessedDomain
* @param array $urlParts
* @return bool|string
* @param array<string> $urlParts
* @param string $portNumber
*
* @return string|false
*/
private static function determineOrigin(array $configuredDomains, $guessedDomain, array &$urlParts, $portNumber)
{

View File

@ -49,6 +49,11 @@ class PerforceDriver extends VcsDriver
$this->perforce->connectClient();
}
/**
* @param array<string, mixed> $repoConfig
*
* @return void
*/
private function initPerforce($repoConfig)
{
if (!empty($this->perforce)) {
@ -171,11 +176,17 @@ class PerforceDriver extends VcsDriver
$this->perforce = null;
}
/**
* @return string
*/
public function getDepot()
{
return $this->depot;
}
/**
* @return string
*/
public function getBranch()
{
return $this->branch;

View File

@ -51,7 +51,7 @@ abstract class VcsDriver implements VcsDriverInterface
/**
* Constructor.
*
* @param array $repoConfig The repository configuration
* @param array{url: string}&array<string, mixed> $repoConfig The repository configuration
* @param IOInterface $io The IO instance
* @param Config $config The composer configuration
* @param HttpDownloader $httpDownloader Remote Filesystem, injectable for mocking
@ -105,6 +105,11 @@ abstract class VcsDriver implements VcsDriverInterface
return $this->infoCache[$identifier];
}
/**
* @param string $identifier
*
* @return array<string, mixed>|null
*/
protected function getBaseComposerInformation($identifier)
{
$composerFileContent = $this->getFileContent('composer.json', $identifier);

View File

@ -58,7 +58,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
protected $processExecutor;
/** @var bool */
protected $branchErrorOccurred = false;
/** @var array<string, class-string> */
/** @var array<string, class-string<VcsDriverInterface>> */
private $drivers;
/** @var ?VcsDriverInterface */
private $driver;
@ -69,6 +69,10 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
/** @var array<'tags'|'branches', array<string, \Throwable>> */
private $versionTransportExceptions = array();
/**
* @param array{url: string, type?: string}&array<string, mixed> $repoConfig
* @param array<string, class-string<VcsDriverInterface>>|null $drivers
*/
public function __construct(array $repoConfig, IOInterface $io, Config $config, HttpDownloader $httpDownloader, EventDispatcher $dispatcher = null, ProcessExecutor $process = null, array $drivers = null, VersionCacheInterface $versionCache = null)
{
parent::__construct();
@ -113,11 +117,17 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
return $this->repoConfig;
}
/**
* @return void
*/
public function setLoader(LoaderInterface $loader)
{
$this->loader = $loader;
}
/**
* @return VcsDriverInterface|null
*/
public function getDriver()
{
if ($this->driver) {
@ -149,18 +159,29 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
return $this->driver;
}
}
return null;
}
/**
* @return bool
*/
public function hadInvalidBranches()
{
return $this->branchErrorOccurred;
}
/**
* @return string[]
*/
public function getEmptyReferences()
{
return $this->emptyReferences;
}
/**
* @return array<'tags'|'branches', array<string, \Throwable>>
*/
public function getVersionTransportExceptions()
{
return $this->versionTransportExceptions;
@ -399,6 +420,13 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
}
}
/**
* @param VcsDriverInterface $driver
* @param array{name?: string, dist?: array{type: string, url: string, reference: string, shasum: string}, source?: array{type: string, url: string, reference: string}} $data
* @param string $identifier
*
* @return array{name: string|null, dist: array{type: string, url: string, reference: string, shasum: string}|null, source: array{type: string, url: string, reference: string}}
*/
protected function preProcess(VcsDriverInterface $driver, array $data, $identifier)
{
// keep the name of the main identifier for all packages
@ -417,6 +445,11 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
return $data;
}
/**
* @param string $branch
*
* @return string|false
*/
private function validateBranch($branch)
{
try {
@ -432,6 +465,11 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
return false;
}
/**
* @param string $version
*
* @return string|false
*/
private function validateTag($version)
{
try {
@ -442,10 +480,19 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
return false;
}
/**
* @param string $version
* @param string $identifier
* @param bool $isVerbose
* @param bool $isVeryVerbose
* @param bool $isDefaultBranch
*
* @return \Composer\Package\CompletePackage|\Composer\Package\CompleteAliasPackage|null|false null if no cache present, false if the absence of a version was cached
*/
private function getCachedPackageVersion($version, $identifier, $isVerbose, $isVeryVerbose, $isDefaultBranch = false)
{
if (!$this->versionCache) {
return;
return null;
}
$cachedPackage = $this->versionCache->getVersionPackage($version, $identifier);