1
0
Fork 0

Add types to `Util` namespace, refs #10159 (#10190)

pull/10198/head
Martin Herndl 2021-10-19 14:35:37 +02:00 committed by GitHub
parent 261d93aacf
commit 995bf5a932
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 402 additions and 32 deletions

View File

@ -469,7 +469,7 @@ class GitHubDriver extends VcsDriver
} }
} }
$rateLimited = $gitHubUtil->isRateLimited($e->getHeaders()); $rateLimited = $gitHubUtil->isRateLimited((array) $e->getHeaders());
if (!$this->io->hasAuthentication($this->originUrl)) { if (!$this->io->hasAuthentication($this->originUrl)) {
if (!$this->io->isInteractive()) { if (!$this->io->isInteractive()) {

View File

@ -37,6 +37,8 @@ class AuthHelper
/** /**
* @param string $origin * @param string $origin
* @param string|bool $storeAuth * @param string|bool $storeAuth
*
* @return void
*/ */
public function storeAuth($origin, $storeAuth) public function storeAuth($origin, $storeAuth)
{ {
@ -192,10 +194,11 @@ class AuthHelper
} }
/** /**
* @param array $headers * @param string[] $headers
* @param string $origin * @param string $origin
* @param string $url * @param string $url
* @return array updated headers array *
* @return string[] updated headers array
*/ */
public function addAuthenticationHeader(array $headers, $origin, $url) public function addAuthenticationHeader(array $headers, $origin, $url)
{ {

View File

@ -211,16 +211,17 @@ class Bitbucket
throw new \LogicException('Failed to initialize token above'); throw new \LogicException('Failed to initialize token above');
} }
// side effect above caused this, https://github.com/phpstan/phpstan/issues/5129
// @phpstan-ignore-next-line
return $this->token['access_token']; return $this->token['access_token'];
} }
/** /**
* Store the new/updated credentials to the configuration * Store the new/updated credentials to the configuration
*
* @param string $originUrl * @param string $originUrl
* @param string $consumerKey * @param string $consumerKey
* @param string $consumerSecret * @param string $consumerSecret
*
* @return void
*/ */
private function storeInAuthConfig($originUrl, $consumerKey, $consumerSecret) private function storeInAuthConfig($originUrl, $consumerKey, $consumerSecret)
{ {

View File

@ -19,6 +19,16 @@ namespace Composer\Util;
*/ */
class ComposerMirror class ComposerMirror
{ {
/**
* @param string $mirrorUrl
* @param string $packageName
* @param string $version
* @param string|null $reference
* @param string|null $type
* @param string|null $prettyVersion
*
* @return string
*/
public static function processUrl($mirrorUrl, $packageName, $version, $reference, $type, $prettyVersion = null) public static function processUrl($mirrorUrl, $packageName, $version, $reference, $type, $prettyVersion = null)
{ {
if ($reference) { if ($reference) {
@ -36,6 +46,14 @@ class ComposerMirror
return str_replace($from, $to, $mirrorUrl); return str_replace($from, $to, $mirrorUrl);
} }
/**
* @param string $mirrorUrl
* @param string $packageName
* @param string $url
* @param string|null $type
*
* @return string
*/
public static function processGitUrl($mirrorUrl, $packageName, $url, $type) public static function processGitUrl($mirrorUrl, $packageName, $url, $type)
{ {
if (preg_match('#^(?:(?:https?|git)://github\.com/|git@github\.com:)([^/]+)/(.+?)(?:\.git)?$#', $url, $match)) { if (preg_match('#^(?:(?:https?|git)://github\.com/|git@github\.com:)([^/]+)/(.+?)(?:\.git)?$#', $url, $match)) {
@ -53,6 +71,14 @@ class ComposerMirror
); );
} }
/**
* @param string $mirrorUrl
* @param string $packageName
* @param string $url
* @param string $type
*
* @return string
*/
public static function processHgUrl($mirrorUrl, $packageName, $url, $type) public static function processHgUrl($mirrorUrl, $packageName, $url, $type)
{ {
return self::processGitUrl($mirrorUrl, $packageName, $url, $type); return self::processGitUrl($mirrorUrl, $packageName, $url, $type);

View File

@ -45,7 +45,7 @@ class ConfigValidator
* @param int $arrayLoaderValidationFlags Flags for ArrayLoader validation * @param int $arrayLoaderValidationFlags Flags for ArrayLoader validation
* @param int $flags Flags for validation * @param int $flags Flags for validation
* *
* @return array a triple containing the errors, publishable errors, and warnings * @return array{list<string>, list<string>, list<string>} a triple containing the errors, publishable errors, and warnings
*/ */
public function validate($file, $arrayLoaderValidationFlags = ValidatingArrayLoader::CHECK_ALL, $flags = self::CHECK_VERSION) public function validate($file, $arrayLoaderValidationFlags = ValidatingArrayLoader::CHECK_ALL, $flags = self::CHECK_VERSION)
{ {

View File

@ -82,6 +82,8 @@ class ErrorHandler
* Register error handler. * Register error handler.
* *
* @param IOInterface|null $io * @param IOInterface|null $io
*
* @return void
*/ */
public static function register(IOInterface $io = null) public static function register(IOInterface $io = null)
{ {

View File

@ -32,6 +32,11 @@ class Filesystem
$this->processExecutor = $executor; $this->processExecutor = $executor;
} }
/**
* @param string $file
*
* @return bool
*/
public function remove($file) public function remove($file)
{ {
if (is_dir($file)) { if (is_dir($file)) {
@ -62,6 +67,12 @@ class Filesystem
return \count($finder) === 0; return \count($finder) === 0;
} }
/**
* @param string $dir
* @param bool $ensureDirectoryExists
*
* @return void
*/
public function emptyDirectory($dir, $ensureDirectoryExists = true) public function emptyDirectory($dir, $ensureDirectoryExists = true)
{ {
if (is_link($dir) && file_exists($dir)) { if (is_link($dir) && file_exists($dir)) {
@ -163,6 +174,7 @@ class Filesystem
/** /**
* @param string $directory * @param string $directory
* @param bool $fallbackToPhp
* *
* @return bool|null Returns null, when no edge case was hit. Otherwise a bool whether removal was successfull * @return bool|null Returns null, when no edge case was hit. Otherwise a bool whether removal was successfull
*/ */
@ -240,6 +252,11 @@ class Filesystem
return $this->rmdir($directory); return $this->rmdir($directory);
} }
/**
* @param string $directory
*
* @return void
*/
public function ensureDirectoryExists($directory) public function ensureDirectoryExists($directory)
{ {
if (!is_dir($directory)) { if (!is_dir($directory)) {
@ -326,6 +343,8 @@ class Filesystem
* *
* @param string $source * @param string $source
* @param string $target * @param string $target
*
* @return void
*/ */
public function copyThenRemove($source, $target) public function copyThenRemove($source, $target)
{ {
@ -370,6 +389,12 @@ class Filesystem
return $result; return $result;
} }
/**
* @param string $source
* @param string $target
*
* @return void
*/
public function rename($source, $target) public function rename($source, $target)
{ {
if (true === @rename($source, $target)) { if (true === @rename($source, $target)) {
@ -605,13 +630,18 @@ class Filesystem
return (bool) preg_match('{^(file://(?!//)|/(?!/)|/?[a-z]:[\\\\/]|\.\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i', $path); return (bool) preg_match('{^(file://(?!//)|/(?!/)|/?[a-z]:[\\\\/]|\.\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i', $path);
} }
/**
* @param string $path
*
* @return string
*/
public static function getPlatformPath($path) public static function getPlatformPath($path)
{ {
if (Platform::isWindows()) { if (Platform::isWindows()) {
$path = preg_replace('{^(?:file:///([a-z]):?/)}i', 'file://$1:/', $path); $path = preg_replace('{^(?:file:///([a-z]):?/)}i', 'file://$1:/', $path);
} }
return preg_replace('{^file://}i', '', $path); return (string) preg_replace('{^file://}i', '', $path);
} }
/** /**
@ -641,6 +671,11 @@ class Filesystem
return false; return false;
} }
/**
* @param string $directory
*
* @return int
*/
protected function directorySize($directory) protected function directorySize($directory)
{ {
$it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS); $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
@ -767,6 +802,8 @@ class Filesystem
* *
* @param string $target * @param string $target
* @param string $junction * @param string $junction
*
* @return void
*/ */
public function junction($target, $junction) public function junction($target, $junction)
{ {
@ -845,6 +882,12 @@ class Filesystem
return $this->rmdir($junction); return $this->rmdir($junction);
} }
/**
* @param string $path
* @param string $content
*
* @return int|false
*/
public function filePutContentsIfModified($path, $content) public function filePutContentsIfModified($path, $content)
{ {
$currentContent = @file_get_contents($path); $currentContent = @file_get_contents($path);
@ -860,6 +903,8 @@ class Filesystem
* *
* @param string $source * @param string $source
* @param string $target * @param string $target
*
* @return void
*/ */
public function safeCopy($source, $target) public function safeCopy($source, $target)
{ {
@ -876,6 +921,11 @@ class Filesystem
/** /**
* compare 2 files * compare 2 files
* https://stackoverflow.com/questions/3060125/can-i-use-file-get-contents-to-compare-two-files * https://stackoverflow.com/questions/3060125/can-i-use-file-get-contents-to-compare-two-files
*
* @param string $a
* @param string $b
*
* @return bool
*/ */
private function filesAreEqual($a, $b) private function filesAreEqual($a, $b)
{ {

View File

@ -40,6 +40,14 @@ class Git
$this->filesystem = $fs; $this->filesystem = $fs;
} }
/**
* @param callable $commandCallable
* @param string $url
* @param string|null $cwd
* @param bool $initialClone
*
* @return void
*/
public function runCommand($commandCallable, $url, $cwd, $initialClone = false) public function runCommand($commandCallable, $url, $cwd, $initialClone = false)
{ {
// Ensure we are allowed to use this URL by config // Ensure we are allowed to use this URL by config
@ -257,6 +265,12 @@ class Git
} }
} }
/**
* @param string $url
* @param string $dir
*
* @return bool
*/
public function syncMirror($url, $dir) public function syncMirror($url, $dir)
{ {
if (getenv('COMPOSER_DISABLE_NETWORK') && getenv('COMPOSER_DISABLE_NETWORK') !== 'prime') { if (getenv('COMPOSER_DISABLE_NETWORK') && getenv('COMPOSER_DISABLE_NETWORK') !== 'prime') {
@ -295,6 +309,13 @@ class Git
return true; return true;
} }
/**
* @param string $url
* @param string $dir
* @param string $ref
*
* @return bool
*/
public function fetchRefOrSyncMirror($url, $dir, $ref) public function fetchRefOrSyncMirror($url, $dir, $ref)
{ {
if ($this->checkRefIsInMirror($dir, $ref)) { if ($this->checkRefIsInMirror($dir, $ref)) {
@ -308,6 +329,9 @@ class Git
return false; return false;
} }
/**
* @return string
*/
public static function getNoShowSignatureFlag(ProcessExecutor $process) public static function getNoShowSignatureFlag(ProcessExecutor $process)
{ {
$gitVersion = self::getVersion($process); $gitVersion = self::getVersion($process);
@ -318,6 +342,12 @@ class Git
return ''; return '';
} }
/**
* @param string $dir
* @param string $ref
*
* @return bool
*/
private function checkRefIsInMirror($dir, $ref) private function checkRefIsInMirror($dir, $ref)
{ {
if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') { if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') {
@ -331,6 +361,12 @@ class Git
return false; return false;
} }
/**
* @param string $url
* @param string[] $match
*
* @return bool
*/
private function isAuthenticationFailure($url, &$match) private function isAuthenticationFailure($url, &$match)
{ {
if (!preg_match('{^(https?://)([^/]+)(.*)$}i', $url, $match)) { if (!preg_match('{^(https?://)([^/]+)(.*)$}i', $url, $match)) {
@ -355,6 +391,9 @@ class Git
return false; return false;
} }
/**
* @return void
*/
public static function cleanEnv() public static function cleanEnv()
{ {
if (PHP_VERSION_ID < 50400 && ini_get('safe_mode') && false === strpos(ini_get('safe_mode_allowed_env_vars'), 'GIT_ASKPASS')) { if (PHP_VERSION_ID < 50400 && ini_get('safe_mode') && false === strpos(ini_get('safe_mode_allowed_env_vars'), 'GIT_ASKPASS')) {
@ -383,16 +422,28 @@ class Git
Platform::clearEnv('DYLD_LIBRARY_PATH'); Platform::clearEnv('DYLD_LIBRARY_PATH');
} }
/**
* @return non-empty-string
*/
public static function getGitHubDomainsRegex(Config $config) public static function getGitHubDomainsRegex(Config $config)
{ {
return '(' . implode('|', array_map('preg_quote', $config->get('github-domains'))) . ')'; return '(' . implode('|', array_map('preg_quote', $config->get('github-domains'))) . ')';
} }
/**
* @return non-empty-string
*/
public static function getGitLabDomainsRegex(Config $config) public static function getGitLabDomainsRegex(Config $config)
{ {
return '(' . implode('|', array_map('preg_quote', $config->get('gitlab-domains'))) . ')'; return '(' . implode('|', array_map('preg_quote', $config->get('gitlab-domains'))) . ')';
} }
/**
* @param non-empty-string $message
* @param string $url
*
* @return never
*/
private function throwException($message, $url) private function throwException($message, $url)
{ {
// git might delete a directory when it fails and php will not know // git might delete a directory when it fails and php will not know

View File

@ -134,9 +134,9 @@ class GitHub
/** /**
* Extract rate limit from response. * Extract rate limit from response.
* *
* @param array $headers Headers from Composer\Downloader\TransportException. * @param string[] $headers Headers from Composer\Downloader\TransportException.
* *
* @return array Associative array with the keys limit and reset. * @return array{limit: int|'?', reset: string}
*/ */
public function getRateLimit(array $headers) public function getRateLimit(array $headers)
{ {
@ -167,7 +167,7 @@ class GitHub
/** /**
* Finds whether a request failed due to rate limiting * Finds whether a request failed due to rate limiting
* *
* @param array $headers Headers from Composer\Downloader\TransportException. * @param string[] $headers Headers from Composer\Downloader\TransportException.
* *
* @return bool * @return bool
*/ */

View File

@ -160,6 +160,14 @@ class GitLab
throw new \RuntimeException('Invalid GitLab credentials 5 times in a row, aborting.'); throw new \RuntimeException('Invalid GitLab credentials 5 times in a row, aborting.');
} }
/**
* @param string $scheme
* @param string $originUrl
*
* @return array{access_token: non-empty-string, token_type: non-empty-string, expires_in: positive-int}
*
* @see https://docs.gitlab.com/ee/api/oauth2.html#resource-owner-password-credentials-flow
*/
private function createToken($scheme, $originUrl) private function createToken($scheme, $originUrl)
{ {
$username = $this->io->ask('Username: '); $username = $this->io->ask('Username: ');

View File

@ -45,6 +45,13 @@ class Hg
$this->process = $process; $this->process = $process;
} }
/**
* @param callable $commandCallable
* @param string $url
* @param string|null $cwd
*
* @return void
*/
public function runCommand($commandCallable, $url, $cwd) public function runCommand($commandCallable, $url, $cwd)
{ {
$this->config->prohibitUrlByConfig($url, $this->io); $this->config->prohibitUrlByConfig($url, $this->io);
@ -75,6 +82,12 @@ class Hg
$this->throwException('Failed to clone ' . $url . ', ' . "\n\n" . $error, $url); $this->throwException('Failed to clone ' . $url . ', ' . "\n\n" . $error, $url);
} }
/**
* @param non-empty-string $message
* @param string $url
*
* @return never
*/
private function throwException($message, $url) private function throwException($message, $url)
{ {
if (null === self::getVersion($this->process)) { if (null === self::getVersion($this->process)) {

View File

@ -23,8 +23,9 @@ class ProxyHelper
/** /**
* Returns proxy environment values * Returns proxy environment values
* *
* @return array{string|null, string|null, string|null} httpProxy, httpsProxy, noProxy values
*
* @throws \RuntimeException on malformed url * @throws \RuntimeException on malformed url
* @return array httpProxy, httpsProxy, noProxy values
*/ */
public static function getProxyData() public static function getProxyData()
{ {
@ -60,7 +61,8 @@ class ProxyHelper
* Returns http context options for the proxy url * Returns http context options for the proxy url
* *
* @param string $proxyUrl * @param string $proxyUrl
* @return array *
* @return array{http: array{proxy: string, header?: string}}
*/ */
public static function getContextOptions($proxyUrl) public static function getContextOptions($proxyUrl)
{ {
@ -91,7 +93,9 @@ class ProxyHelper
* Sets/unsets request_fulluri value in http context options array * Sets/unsets request_fulluri value in http context options array
* *
* @param string $requestUrl * @param string $requestUrl
* @param array $options Set by method * @param mixed[] $options Set by method
*
* @return void
*/ */
public static function setRequestFullUri($requestUrl, array &$options) public static function setRequestFullUri($requestUrl, array &$options)
{ {
@ -105,8 +109,9 @@ class ProxyHelper
/** /**
* Searches $_SERVER for case-sensitive values * Searches $_SERVER for case-sensitive values
* *
* @param array $names Names to search for * @param string[] $names Names to search for
* @param mixed $name Name of any found value * @param string|null $name Name of any found value
*
* @return string|null The found value * @return string|null The found value
*/ */
private static function getProxyEnv(array $names, &$name) private static function getProxyEnv(array $names, &$name)
@ -151,8 +156,9 @@ class ProxyHelper
/** /**
* Formats a url from its component parts * Formats a url from its component parts
* *
* @param array $proxy Values from parse_url * @param array{scheme: string, host: string, port?: int, user?: string, pass?: string} $proxy
* @param bool $includeAuth Whether to include authorization values * @param bool $includeAuth
*
* @return string The formatted value * @return string The formatted value
*/ */
private static function formatParsedUrl(array $proxy, $includeAuth) private static function formatParsedUrl(array $proxy, $includeAuth)

View File

@ -71,6 +71,8 @@ class ProxyManager
/** /**
* Clears the persistent instance * Clears the persistent instance
*
* @return void
*/ */
public static function reset() public static function reset()
{ {
@ -130,6 +132,8 @@ class ProxyManager
/** /**
* Initializes proxy values from the environment * Initializes proxy values from the environment
*
* @return void
*/ */
private function initProxyData() private function initProxyData()
{ {
@ -160,8 +164,10 @@ class ProxyManager
/** /**
* Sets initial data * Sets initial data
* *
* @param string $url Proxy url * @param non-empty-string $url Proxy url
* @param 'http'|'https' $scheme Environment variable scheme * @param 'http'|'https' $scheme Environment variable scheme
*
* @return non-empty-string
*/ */
private function setData($url, $scheme) private function setData($url, $scheme)
{ {

View File

@ -17,6 +17,8 @@ use Symfony\Component\Process\Process;
/** /**
* @author Matt Whittom <Matt.Whittom@veteransunited.com> * @author Matt Whittom <Matt.Whittom@veteransunited.com>
*
* @phpstan-type RepoConfig array{unique_perforce_client_name?: string, depot?: string, branch?: string, p4user?: string, p4password?: string}
*/ */
class Perforce class Perforce
{ {
@ -30,7 +32,7 @@ class Perforce
protected $p4User; protected $p4User;
/** @var ?string */ /** @var ?string */
protected $p4Password; protected $p4Password;
/** @var int */ /** @var string */
protected $p4Port; protected $p4Port;
/** @var string */ /** @var string */
protected $p4Stream; protected $p4Stream;
@ -55,6 +57,14 @@ class Perforce
/** @var Filesystem */ /** @var Filesystem */
protected $filesystem; protected $filesystem;
/**
* @phpstan-param RepoConfig $repoConfig
* @param string $port
* @param string $path
* @param ProcessExecutor $process
* @param bool $isWindows
* @param IOInterface $io
*/
public function __construct($repoConfig, $port, $path, ProcessExecutor $process, $isWindows, IOInterface $io) public function __construct($repoConfig, $port, $path, ProcessExecutor $process, $isWindows, IOInterface $io)
{ {
$this->windowsFlag = $isWindows; $this->windowsFlag = $isWindows;
@ -65,11 +75,26 @@ class Perforce
$this->io = $io; $this->io = $io;
} }
/**
* @phpstan-param RepoConfig $repoConfig
* @param string $port
* @param string $path
* @param ProcessExecutor $process
* @param IOInterface $io
*
* @return self
*/
public static function create($repoConfig, $port, $path, ProcessExecutor $process, IOInterface $io) public static function create($repoConfig, $port, $path, ProcessExecutor $process, IOInterface $io)
{ {
return new Perforce($repoConfig, $port, $path, $process, Platform::isWindows(), $io); return new Perforce($repoConfig, $port, $path, $process, Platform::isWindows(), $io);
} }
/**
* @param string $url
* @param ProcessExecutor $processExecutor
*
* @return bool
*/
public static function checkServerExists($url, ProcessExecutor $processExecutor) public static function checkServerExists($url, ProcessExecutor $processExecutor)
{ {
$output = null; $output = null;
@ -77,6 +102,11 @@ class Perforce
return 0 === $processExecutor->execute('p4 -p ' . ProcessExecutor::escape($url) . ' info -s', $output); return 0 === $processExecutor->execute('p4 -p ' . ProcessExecutor::escape($url) . ' info -s', $output);
} }
/**
* @phpstan-param RepoConfig $repoConfig
*
* @return void
*/
public function initialize($repoConfig) public function initialize($repoConfig)
{ {
$this->uniquePerforceClientName = $this->generateUniquePerforceClientName(); $this->uniquePerforceClientName = $this->generateUniquePerforceClientName();
@ -103,6 +133,12 @@ class Perforce
} }
} }
/**
* @param string|null $depot
* @param string|null $branch
*
* @return void
*/
public function initializeDepotAndBranch($depot, $branch) public function initializeDepotAndBranch($depot, $branch)
{ {
if (isset($depot)) { if (isset($depot)) {
@ -113,11 +149,17 @@ class Perforce
} }
} }
/**
* @return non-empty-string
*/
public function generateUniquePerforceClientName() public function generateUniquePerforceClientName()
{ {
return gethostname() . "_" . time(); return gethostname() . "_" . time();
} }
/**
* @return void
*/
public function cleanupClientSpec() public function cleanupClientSpec()
{ {
$client = $this->getClient(); $client = $this->getClient();
@ -130,6 +172,11 @@ class Perforce
$fileSystem->remove($clientSpec); $fileSystem->remove($clientSpec);
} }
/**
* @param non-empty-string $command
*
* @return int
*/
protected function executeCommand($command) protected function executeCommand($command)
{ {
$this->commandResult = ''; $this->commandResult = '';
@ -137,6 +184,9 @@ class Perforce
return $this->process->execute($command, $this->commandResult); return $this->process->execute($command, $this->commandResult);
} }
/**
* @return string
*/
public function getClient() public function getClient()
{ {
if (!isset($this->p4Client)) { if (!isset($this->p4Client)) {
@ -147,11 +197,19 @@ class Perforce
return $this->p4Client; return $this->p4Client;
} }
/**
* @return string
*/
protected function getPath() protected function getPath()
{ {
return $this->path; return $this->path;
} }
/**
* @param string $path
*
* @return void
*/
public function initializePath($path) public function initializePath($path)
{ {
$this->path = $path; $this->path = $path;
@ -159,11 +217,19 @@ class Perforce
$fs->ensureDirectoryExists($path); $fs->ensureDirectoryExists($path);
} }
/**
* @return string
*/
protected function getPort() protected function getPort()
{ {
return $this->p4Port; return $this->p4Port;
} }
/**
* @param string $stream
*
* @return void
*/
public function setStream($stream) public function setStream($stream)
{ {
$this->p4Stream = $stream; $this->p4Stream = $stream;
@ -174,11 +240,17 @@ class Perforce
} }
} }
/**
* @return bool
*/
public function isStream() public function isStream()
{ {
return is_string($this->p4DepotType) && (strcmp($this->p4DepotType, 'stream') === 0); return is_string($this->p4DepotType) && (strcmp($this->p4DepotType, 'stream') === 0);
} }
/**
* @return string
*/
public function getStream() public function getStream()
{ {
if (!isset($this->p4Stream)) { if (!isset($this->p4Stream)) {
@ -192,6 +264,11 @@ class Perforce
return $this->p4Stream; return $this->p4Stream;
} }
/**
* @param string $stream
*
* @return string
*/
public function getStreamWithoutLabel($stream) public function getStreamWithoutLabel($stream)
{ {
$index = strpos($stream, '@'); $index = strpos($stream, '@');
@ -202,21 +279,35 @@ class Perforce
return substr($stream, 0, $index); return substr($stream, 0, $index);
} }
/**
* @return non-empty-string
*/
public function getP4ClientSpec() public function getP4ClientSpec()
{ {
return $this->path . '/' . $this->getClient() . '.p4.spec'; return $this->path . '/' . $this->getClient() . '.p4.spec';
} }
/**
* @return string|null
*/
public function getUser() public function getUser()
{ {
return $this->p4User; return $this->p4User;
} }
/**
* @param string $user
*
* @return void
*/
public function setUser($user) public function setUser($user)
{ {
$this->p4User = $user; $this->p4User = $user;
} }
/**
* @return void
*/
public function queryP4User() public function queryP4User()
{ {
$this->getUser(); $this->getUser();
@ -272,6 +363,9 @@ class Perforce
return $result; return $result;
} }
/**
* @return string|null
*/
public function queryP4Password() public function queryP4Password()
{ {
if (isset($this->p4Password)) { if (isset($this->p4Password)) {
@ -286,6 +380,12 @@ class Perforce
return $password; return $password;
} }
/**
* @param string $command
* @param bool $useClient
*
* @return non-empty-string
*/
public function generateP4Command($command, $useClient = true) public function generateP4Command($command, $useClient = true)
{ {
$p4Command = 'p4 '; $p4Command = 'p4 ';
@ -298,6 +398,9 @@ class Perforce
return $p4Command; return $p4Command;
} }
/**
* @return bool
*/
public function isLoggedIn() public function isLoggedIn()
{ {
$command = $this->generateP4Command('login -s', false); $command = $this->generateP4Command('login -s', false);
@ -318,6 +421,9 @@ class Perforce
return true; return true;
} }
/**
* @return void
*/
public function connectClient() public function connectClient()
{ {
$p4CreateClientCommand = $this->generateP4Command( $p4CreateClientCommand = $this->generateP4Command(
@ -326,6 +432,11 @@ class Perforce
$this->executeCommand($p4CreateClientCommand); $this->executeCommand($p4CreateClientCommand);
} }
/**
* @param string|null $sourceReference
*
* @return void
*/
public function syncCodeBase($sourceReference) public function syncCodeBase($sourceReference)
{ {
$prevDir = getcwd(); $prevDir = getcwd();
@ -338,6 +449,11 @@ class Perforce
chdir($prevDir); chdir($prevDir);
} }
/**
* @param resource|false $spec
*
* @return void
*/
public function writeClientSpecToFile($spec) public function writeClientSpecToFile($spec)
{ {
fwrite($spec, 'Client: ' . $this->getClient() . PHP_EOL . PHP_EOL); fwrite($spec, 'Client: ' . $this->getClient() . PHP_EOL . PHP_EOL);
@ -361,6 +477,9 @@ class Perforce
} }
} }
/**
* @return void
*/
public function writeP4ClientSpec() public function writeP4ClientSpec()
{ {
$clientSpec = $this->getP4ClientSpec(); $clientSpec = $this->getP4ClientSpec();
@ -374,6 +493,12 @@ class Perforce
fclose($spec); fclose($spec);
} }
/**
* @param resource $pipe
* @param mixed $name
*
* @return void
*/
protected function read($pipe, $name) protected function read($pipe, $name)
{ {
if (feof($pipe)) { if (feof($pipe)) {
@ -385,6 +510,11 @@ class Perforce
} }
} }
/**
* @param string|null $password
*
* @return int
*/
public function windowsLogin($password) public function windowsLogin($password)
{ {
$command = $this->generateP4Command(' login -a'); $command = $this->generateP4Command(' login -a');
@ -393,12 +523,16 @@ class Perforce
if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) { if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
$process = Process::fromShellCommandline($command, null, null, $password); $process = Process::fromShellCommandline($command, null, null, $password);
} else { } else {
// @phpstan-ignore-next-line
$process = new Process($command, null, null, $password); $process = new Process($command, null, null, $password);
} }
return $process->run(); return $process->run();
} }
/**
* @return void
*/
public function p4Login() public function p4Login()
{ {
$this->queryP4User(); $this->queryP4User();
@ -416,6 +550,11 @@ class Perforce
} }
} }
/**
* @param string $identifier
*
* @return mixed|void
*/
public function getComposerInformation($identifier) public function getComposerInformation($identifier)
{ {
$composerFileContent = $this->getFileContent('composer.json', $identifier); $composerFileContent = $this->getFileContent('composer.json', $identifier);
@ -427,6 +566,12 @@ class Perforce
return json_decode($composerFileContent, true); return json_decode($composerFileContent, true);
} }
/**
* @param string $file
* @param string $identifier
*
* @return string|null
*/
public function getFileContent($file, $identifier) public function getFileContent($file, $identifier)
{ {
$path = $this->getFilePath($file, $identifier); $path = $this->getFilePath($file, $identifier);
@ -442,6 +587,12 @@ class Perforce
return $result; return $result;
} }
/**
* @param string $file
* @param string $identifier
*
* @return string|null
*/
public function getFilePath($file, $identifier) public function getFilePath($file, $identifier)
{ {
$index = strpos($identifier, '@'); $index = strpos($identifier, '@');
@ -467,6 +618,9 @@ class Perforce
return null; return null;
} }
/**
* @return array{master: string}
*/
public function getBranches() public function getBranches()
{ {
$possibleBranches = array(); $possibleBranches = array();
@ -496,6 +650,9 @@ class Perforce
return array('master' => $possibleBranches[$this->p4Branch] . '@'. $lastCommitNum); return array('master' => $possibleBranches[$this->p4Branch] . '@'. $lastCommitNum);
} }
/**
* @return array<string, string>
*/
public function getTags() public function getTags()
{ {
$command = $this->generateP4Command('labels'); $command = $this->generateP4Command('labels');
@ -513,6 +670,9 @@ class Perforce
return $tags; return $tags;
} }
/**
* @return bool
*/
public function checkStream() public function checkStream()
{ {
$command = $this->generateP4Command('depots', false); $command = $this->generateP4Command('depots', false);
@ -578,6 +738,9 @@ class Perforce
return $this->commandResult; return $this->commandResult;
} }
/**
* @return Filesystem
*/
public function getFilesystem() public function getFilesystem()
{ {
if (empty($this->filesystem)) { if (empty($this->filesystem)) {
@ -587,6 +750,9 @@ class Perforce
return $this->filesystem; return $this->filesystem;
} }
/**
* @return void
*/
public function setFilesystem(Filesystem $fs) public function setFilesystem(Filesystem $fs)
{ {
$this->filesystem = $fs; $this->filesystem = $fs;

View File

@ -555,6 +555,7 @@ class RemoteFilesystem
* @param string $originUrl The origin URL * @param string $originUrl The origin URL
* @param string $fileUrl The file URL * @param string $fileUrl The file URL
* @param resource $context The stream context * @param resource $context The stream context
* @param string[] $responseHeaders
* @param int $maxFileSize The maximum allowed file size * @param int $maxFileSize The maximum allowed file size
* *
* @return string|false The response contents or false on failure * @return string|false The response contents or false on failure
@ -598,6 +599,9 @@ class RemoteFilesystem
* @param int $messageCode The message code * @param int $messageCode The message code
* @param int $bytesTransferred The loaded size * @param int $bytesTransferred The loaded size
* @param int $bytesMax The total size * @param int $bytesMax The total size
*
* @return void
*
* @throws TransportException * @throws TransportException
*/ */
protected function callbackGet($notificationCode, $severity, $message, $messageCode, $bytesTransferred, $bytesMax) protected function callbackGet($notificationCode, $severity, $message, $messageCode, $bytesTransferred, $bytesMax)
@ -631,6 +635,13 @@ class RemoteFilesystem
} }
} }
/**
* @param positive-int $httpStatus
* @param string|null $reason
* @param string[] $headers
*
* @return void
*/
protected function promptAuthAndRetry($httpStatus, $reason = null, $headers = array()) protected function promptAuthAndRetry($httpStatus, $reason = null, $headers = array())
{ {
$result = $this->authHelper->promptAuthIfNeeded($this->fileUrl, $this->originUrl, $httpStatus, $reason, $headers); $result = $this->authHelper->promptAuthIfNeeded($this->fileUrl, $this->originUrl, $httpStatus, $reason, $headers);
@ -643,6 +654,12 @@ class RemoteFilesystem
} }
} }
/**
* @param string $originUrl
* @param mixed[] $additionalOptions
*
* @return mixed[]
*/
protected function getOptionsForUrl($originUrl, $additionalOptions) protected function getOptionsForUrl($originUrl, $additionalOptions)
{ {
$tlsOptions = array(); $tlsOptions = array();
@ -714,6 +731,13 @@ class RemoteFilesystem
return $options; return $options;
} }
/**
* @param string[] $http_response_header
* @param mixed[] $additionalOptions
* @param string|false $result
*
* @return bool|string
*/
private function handleRedirect(array $http_response_header, array $additionalOptions, $result) private function handleRedirect(array $http_response_header, array $additionalOptions, $result)
{ {
if ($locationHeader = Response::findHeaderValue($http_response_header, 'location')) { if ($locationHeader = Response::findHeaderValue($http_response_header, 'location')) {
@ -763,6 +787,9 @@ class RemoteFilesystem
* *
* @todo Remove when PHP 5.6 is minimum supported version. * @todo Remove when PHP 5.6 is minimum supported version.
* *
* @param string $url
* @param mixed[] $options
*
* @return ?array{cn: string, fp: string} * @return ?array{cn: string, fp: string}
*/ */
private function getCertificateCnAndFp($url, $options) private function getCertificateCnAndFp($url, $options)
@ -807,6 +834,11 @@ class RemoteFilesystem
return null; return null;
} }
/**
* @param string $url
*
* @return string
*/
private function getUrlAuthority($url) private function getUrlAuthority($url)
{ {
$defaultPorts = array( $defaultPorts = array(
@ -832,6 +864,12 @@ class RemoteFilesystem
return parse_url($url, PHP_URL_HOST).':'.$port; return parse_url($url, PHP_URL_HOST).':'.$port;
} }
/**
* @param string|false $result
* @param string[] $http_response_header
*
* @return string|false
*/
private function decodeResult($result, $http_response_header) private function decodeResult($result, $http_response_header)
{ {
// decode gzip // decode gzip