Fix all 5.3 $this-in-closure usages
parent
5805a68645
commit
4e6d54b731
|
@ -69,13 +69,8 @@
|
||||||
},
|
},
|
||||||
"autoload-dev": {
|
"autoload-dev": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Composer\\Test\\": "tests/Composer/Test",
|
"Composer\\Test\\": "tests/Composer/Test"
|
||||||
"Composer\\PHPStanRules\\": "phpstan/Rules/src",
|
}
|
||||||
"Composer\\PHPStanRulesTests\\": "phpstan/Rules/tests"
|
|
||||||
},
|
|
||||||
"classmap": [
|
|
||||||
"phpstan/Rules/tests/data"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"bin": [
|
"bin": [
|
||||||
"bin/composer"
|
"bin/composer"
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
<?php declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace Composer\PHPStanRules;
|
|
||||||
|
|
||||||
use PhpParser\Node;
|
|
||||||
use PHPStan\Analyser\Scope;
|
|
||||||
use PHPStan\Rules\Rule;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @phpstan-implements Rule<\PhpParser\Node\Expr\Variable>
|
|
||||||
*/
|
|
||||||
final class AnonymousFunctionWithThisRule implements Rule
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
public function getNodeType(): string
|
|
||||||
{
|
|
||||||
return \PhpParser\Node\Expr\Variable::class;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
public function processNode(Node $node, Scope $scope): array
|
|
||||||
{
|
|
||||||
if (!\is_string($node->name) || $node->name !== 'this') {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($scope->isInClosureBind()) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$scope->isInClass()) {
|
|
||||||
// reported in other standard rule on level 0
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($scope->isInAnonymousFunction()) {
|
|
||||||
return ['Using $this inside anonymous function is prohibited because of PHP 5.3 support.'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
<?php declare(strict_types = 1);
|
|
||||||
|
|
||||||
namespace Composer\PHPStanRulesTests;
|
|
||||||
|
|
||||||
use Composer\PHPStanRules\AnonymousFunctionWithThisRule;
|
|
||||||
use PHPStan\Testing\RuleTestCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @phpstan-extends RuleTestCase<AnonymousFunctionWithThisRule>
|
|
||||||
*/
|
|
||||||
final class AnonymousFunctionWithThisRuleTest extends RuleTestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
protected function getRule(): \PHPStan\Rules\Rule
|
|
||||||
{
|
|
||||||
return new AnonymousFunctionWithThisRule();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testWithThis(): void
|
|
||||||
{
|
|
||||||
$this->analyse([__DIR__ . '/data/method-with-this.php'], [
|
|
||||||
['Using $this inside anonymous function is prohibited because of PHP 5.3 support.', 13],
|
|
||||||
['Using $this inside anonymous function is prohibited because of PHP 5.3 support.', 17],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
class FirstClass
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $firstProp = 9;
|
|
||||||
|
|
||||||
public function funMethod()
|
|
||||||
{
|
|
||||||
function() {
|
|
||||||
$this->firstProp;
|
|
||||||
};
|
|
||||||
|
|
||||||
call_user_func(function() {
|
|
||||||
$this->funMethod();
|
|
||||||
}, $this);
|
|
||||||
|
|
||||||
$bind = 'bind';
|
|
||||||
function() use($bind) {
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function global_ok() {
|
|
||||||
$_SERVER['REMOTE_ADDR'];
|
|
||||||
}
|
|
||||||
|
|
||||||
function global_this() {
|
|
||||||
// not checked by our rule, it is checked with standard phpstan rule on level 0
|
|
||||||
$this['REMOTE_ADDR'];
|
|
||||||
}
|
|
|
@ -56,6 +56,3 @@ parameters:
|
||||||
- Composer\Composer::VERSION
|
- Composer\Composer::VERSION
|
||||||
- Composer\Composer::RELEASE_DATE
|
- Composer\Composer::RELEASE_DATE
|
||||||
- Composer\Composer::SOURCE_VERSION
|
- Composer\Composer::SOURCE_VERSION
|
||||||
|
|
||||||
rules:
|
|
||||||
- Composer\PHPStanRules\AnonymousFunctionWithThisRule
|
|
||||||
|
|
|
@ -348,15 +348,14 @@ EOT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$self = $this;
|
|
||||||
$author = $io->askAndValidate(
|
$author = $io->askAndValidate(
|
||||||
'Author [<comment>'.$author.'</comment>, n to skip]: ',
|
'Author [<comment>'.$author.'</comment>, n to skip]: ',
|
||||||
function ($value) use ($self, $author) {
|
function ($value) use ($author) {
|
||||||
if ($value === 'n' || $value === 'no') {
|
if ($value === 'n' || $value === 'no') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$value = $value ?: $author;
|
$value = $value ?: $author;
|
||||||
$author = $self->parseAuthorString($value);
|
$author = $this->parseAuthorString($value);
|
||||||
|
|
||||||
return sprintf('%s <%s>', $author['name'], $author['email']);
|
return sprintf('%s <%s>', $author['name'], $author['email']);
|
||||||
},
|
},
|
||||||
|
|
|
@ -514,14 +514,12 @@ class Config
|
||||||
*/
|
*/
|
||||||
private function process($value, $flags)
|
private function process($value, $flags)
|
||||||
{
|
{
|
||||||
$config = $this;
|
|
||||||
|
|
||||||
if (!is_string($value)) {
|
if (!is_string($value)) {
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Preg::replaceCallback('#\{\$(.+)\}#', function ($match) use ($config, $flags) {
|
return Preg::replaceCallback('#\{\$(.+)\}#', function ($match) use ($flags) {
|
||||||
return $config->get($match[1], $flags);
|
return $this->get($match[1], $flags);
|
||||||
}, $value);
|
}, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,11 +64,10 @@ class DefaultPolicy implements PolicyInterface
|
||||||
public function selectPreferredPackages(Pool $pool, array $literals, $requiredPackage = null)
|
public function selectPreferredPackages(Pool $pool, array $literals, $requiredPackage = null)
|
||||||
{
|
{
|
||||||
$packages = $this->groupLiteralsByName($pool, $literals);
|
$packages = $this->groupLiteralsByName($pool, $literals);
|
||||||
$policy = $this;
|
|
||||||
|
|
||||||
foreach ($packages as &$nameLiterals) {
|
foreach ($packages as &$nameLiterals) {
|
||||||
usort($nameLiterals, function ($a, $b) use ($policy, $pool, $requiredPackage) {
|
usort($nameLiterals, function ($a, $b) use ($pool, $requiredPackage) {
|
||||||
return $policy->compareByPriority($pool, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage, true);
|
return $this->compareByPriority($pool, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,8 +79,8 @@ class DefaultPolicy implements PolicyInterface
|
||||||
$selected = \call_user_func_array('array_merge', array_values($packages));
|
$selected = \call_user_func_array('array_merge', array_values($packages));
|
||||||
|
|
||||||
// now sort the result across all packages to respect replaces across packages
|
// now sort the result across all packages to respect replaces across packages
|
||||||
usort($selected, function ($a, $b) use ($policy, $pool, $requiredPackage) {
|
usort($selected, function ($a, $b) use ($pool, $requiredPackage) {
|
||||||
return $policy->compareByPriority($pool, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage);
|
return $this->compareByPriority($pool, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage);
|
||||||
});
|
});
|
||||||
|
|
||||||
return $selected;
|
return $selected;
|
||||||
|
|
|
@ -28,9 +28,8 @@ abstract class ArchiveDownloader extends FileDownloader
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var array<string, true>
|
* @var array<string, true>
|
||||||
* @protected
|
|
||||||
*/
|
*/
|
||||||
public $cleanupExecuted = array();
|
protected $cleanupExecuted = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return PromiseInterface|null
|
* @return PromiseInterface|null
|
||||||
|
@ -92,22 +91,20 @@ abstract class ArchiveDownloader extends FileDownloader
|
||||||
$fileName = $this->getFileName($package, $path);
|
$fileName = $this->getFileName($package, $path);
|
||||||
|
|
||||||
$filesystem = $this->filesystem;
|
$filesystem = $this->filesystem;
|
||||||
$self = $this;
|
|
||||||
|
|
||||||
$cleanup = function () use ($path, $filesystem, $temporaryDir, $package, $self) {
|
$cleanup = function () use ($path, $filesystem, $temporaryDir, $package) {
|
||||||
// remove cache if the file was corrupted
|
// remove cache if the file was corrupted
|
||||||
$self->clearLastCacheWrite($package);
|
$this->clearLastCacheWrite($package);
|
||||||
|
|
||||||
// clean up
|
// clean up
|
||||||
$filesystem->removeDirectory($temporaryDir);
|
$filesystem->removeDirectory($temporaryDir);
|
||||||
if (is_dir($path) && realpath($path) !== getcwd()) {
|
if (is_dir($path) && realpath($path) !== getcwd()) {
|
||||||
$filesystem->removeDirectory($path);
|
$filesystem->removeDirectory($path);
|
||||||
}
|
}
|
||||||
$self->removeCleanupPath($package, $temporaryDir);
|
$this->removeCleanupPath($package, $temporaryDir);
|
||||||
$self->removeCleanupPath($package, realpath($path));
|
$this->removeCleanupPath($package, realpath($path));
|
||||||
};
|
};
|
||||||
|
|
||||||
$promise = null;
|
|
||||||
try {
|
try {
|
||||||
$promise = $this->extract($package, $fileName, $temporaryDir);
|
$promise = $this->extract($package, $fileName, $temporaryDir);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
|
@ -119,7 +116,7 @@ abstract class ArchiveDownloader extends FileDownloader
|
||||||
$promise = \React\Promise\resolve();
|
$promise = \React\Promise\resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $promise->then(function () use ($self, $package, $filesystem, $fileName, $temporaryDir, $path) {
|
return $promise->then(function () use ($package, $filesystem, $fileName, $temporaryDir, $path) {
|
||||||
$filesystem->unlink($fileName);
|
$filesystem->unlink($fileName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -203,9 +200,9 @@ abstract class ArchiveDownloader extends FileDownloader
|
||||||
|
|
||||||
$promise = $filesystem->removeDirectoryAsync($temporaryDir);
|
$promise = $filesystem->removeDirectoryAsync($temporaryDir);
|
||||||
|
|
||||||
return $promise->then(function () use ($self, $package, $path, $temporaryDir) {
|
return $promise->then(function () use ($package, $path, $temporaryDir) {
|
||||||
$self->removeCleanupPath($package, $temporaryDir);
|
$this->removeCleanupPath($package, $temporaryDir);
|
||||||
$self->removeCleanupPath($package, $path);
|
$this->removeCleanupPath($package, $path);
|
||||||
});
|
});
|
||||||
}, function ($e) use ($cleanup) {
|
}, function ($e) use ($cleanup) {
|
||||||
$cleanup();
|
$cleanup();
|
||||||
|
|
|
@ -192,16 +192,15 @@ class DownloadManager
|
||||||
$sources = $this->getAvailableSources($package, $prevPackage);
|
$sources = $this->getAvailableSources($package, $prevPackage);
|
||||||
|
|
||||||
$io = $this->io;
|
$io = $this->io;
|
||||||
$self = $this;
|
|
||||||
|
|
||||||
$download = function ($retry = false) use (&$sources, $io, $package, $self, $targetDir, &$download, $prevPackage) {
|
$download = function ($retry = false) use (&$sources, $io, $package, $targetDir, &$download, $prevPackage) {
|
||||||
$source = array_shift($sources);
|
$source = array_shift($sources);
|
||||||
if ($retry) {
|
if ($retry) {
|
||||||
$io->writeError(' <warning>Now trying to download from ' . $source . '</warning>');
|
$io->writeError(' <warning>Now trying to download from ' . $source . '</warning>');
|
||||||
}
|
}
|
||||||
$package->setInstallationSource($source);
|
$package->setInstallationSource($source);
|
||||||
|
|
||||||
$downloader = $self->getDownloaderForPackage($package);
|
$downloader = $this->getDownloaderForPackage($package);
|
||||||
if (!$downloader) {
|
if (!$downloader) {
|
||||||
return \React\Promise\resolve();
|
return \React\Promise\resolve();
|
||||||
}
|
}
|
||||||
|
@ -332,10 +331,8 @@ class DownloadManager
|
||||||
// we wipe the dir and do a new install instead of updating it
|
// we wipe the dir and do a new install instead of updating it
|
||||||
$promise = $initialDownloader->remove($initial, $targetDir);
|
$promise = $initialDownloader->remove($initial, $targetDir);
|
||||||
if ($promise) {
|
if ($promise) {
|
||||||
$self = $this;
|
return $promise->then(function ($res) use ($target, $targetDir) {
|
||||||
|
return $this->install($target, $targetDir);
|
||||||
return $promise->then(function ($res) use ($self, $target, $targetDir) {
|
|
||||||
return $self->install($target, $targetDir);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -150,11 +150,10 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface
|
||||||
$httpDownloader = $this->httpDownloader;
|
$httpDownloader = $this->httpDownloader;
|
||||||
$eventDispatcher = $this->eventDispatcher;
|
$eventDispatcher = $this->eventDispatcher;
|
||||||
$filesystem = $this->filesystem;
|
$filesystem = $this->filesystem;
|
||||||
$self = $this;
|
|
||||||
|
|
||||||
$accept = null;
|
$accept = null;
|
||||||
$reject = null;
|
$reject = null;
|
||||||
$download = function () use ($io, $output, $httpDownloader, $cache, $cacheKeyGenerator, $eventDispatcher, $package, $fileName, &$urls, &$accept, &$reject, $self) {
|
$download = function () use ($io, $output, $httpDownloader, $cache, $cacheKeyGenerator, $eventDispatcher, $package, $fileName, &$urls, &$accept, &$reject) {
|
||||||
/** @var array{base: string, processed: string, cacheKey: string} $url */
|
/** @var array{base: string, processed: string, cacheKey: string} $url */
|
||||||
$url = reset($urls);
|
$url = reset($urls);
|
||||||
$index = key($urls);
|
$index = key($urls);
|
||||||
|
@ -184,7 +183,7 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface
|
||||||
// the cache is corrupt the archive will be deleted and the next attempt will re-download it
|
// the cache is corrupt the archive will be deleted and the next attempt will re-download it
|
||||||
// see https://github.com/composer/composer/issues/10028
|
// see https://github.com/composer/composer/issues/10028
|
||||||
if (!$cache->isReadOnly()) {
|
if (!$cache->isReadOnly()) {
|
||||||
$self->lastCacheWrites[$package->getName()] = $cacheKey;
|
$this->lastCacheWrites[$package->getName()] = $cacheKey;
|
||||||
}
|
}
|
||||||
$result = \React\Promise\resolve($fileName);
|
$result = \React\Promise\resolve($fileName);
|
||||||
} else {
|
} else {
|
||||||
|
@ -222,13 +221,13 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$accept = function ($response) use ($cache, $package, $fileName, $self, &$urls) {
|
$accept = function ($response) use ($cache, $package, $fileName, &$urls) {
|
||||||
$url = reset($urls);
|
$url = reset($urls);
|
||||||
$cacheKey = $url['cacheKey'];
|
$cacheKey = $url['cacheKey'];
|
||||||
FileDownloader::$downloadMetadata[$package->getName()] = @filesize($fileName) ?: $response->getHeader('Content-Length') ?: '?';
|
FileDownloader::$downloadMetadata[$package->getName()] = @filesize($fileName) ?: $response->getHeader('Content-Length') ?: '?';
|
||||||
|
|
||||||
if ($cache && !$cache->isReadOnly()) {
|
if ($cache && !$cache->isReadOnly()) {
|
||||||
$self->lastCacheWrites[$package->getName()] = $cacheKey;
|
$this->lastCacheWrites[$package->getName()] = $cacheKey;
|
||||||
$cache->copyFrom($cacheKey, $fileName);
|
$cache->copyFrom($cacheKey, $fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,12 +236,12 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface
|
||||||
return $fileName;
|
return $fileName;
|
||||||
};
|
};
|
||||||
|
|
||||||
$reject = function ($e) use ($io, &$urls, $download, $fileName, $package, &$retries, $filesystem, $self) {
|
$reject = function ($e) use ($io, &$urls, $download, $fileName, $package, &$retries, $filesystem) {
|
||||||
// clean up
|
// clean up
|
||||||
if (file_exists($fileName)) {
|
if (file_exists($fileName)) {
|
||||||
$filesystem->unlink($fileName);
|
$filesystem->unlink($fileName);
|
||||||
}
|
}
|
||||||
$self->clearLastCacheWrite($package);
|
$this->clearLastCacheWrite($package);
|
||||||
|
|
||||||
if ($e instanceof IrrecoverableDownloadException) {
|
if ($e instanceof IrrecoverableDownloadException) {
|
||||||
throw $e;
|
throw $e;
|
||||||
|
@ -361,12 +360,9 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO mark private in v3
|
|
||||||
* @protected This is public due to PHP 5.3
|
|
||||||
*
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function clearLastCacheWrite(PackageInterface $package)
|
protected function clearLastCacheWrite(PackageInterface $package)
|
||||||
{
|
{
|
||||||
if ($this->cache && isset($this->lastCacheWrites[$package->getName()])) {
|
if ($this->cache && isset($this->lastCacheWrites[$package->getName()])) {
|
||||||
$this->cache->remove($this->lastCacheWrites[$package->getName()]);
|
$this->cache->remove($this->lastCacheWrites[$package->getName()]);
|
||||||
|
@ -375,27 +371,21 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO mark private in v3
|
|
||||||
* @protected This is public due to PHP 5.3
|
|
||||||
*
|
|
||||||
* @param string $path
|
* @param string $path
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function addCleanupPath(PackageInterface $package, $path)
|
protected function addCleanupPath(PackageInterface $package, $path)
|
||||||
{
|
{
|
||||||
$this->additionalCleanupPaths[$package->getName()][] = $path;
|
$this->additionalCleanupPaths[$package->getName()][] = $path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO mark private in v3
|
|
||||||
* @protected This is public due to PHP 5.3
|
|
||||||
*
|
|
||||||
* @param string $path
|
* @param string $path
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function removeCleanupPath(PackageInterface $package, $path)
|
protected function removeCleanupPath(PackageInterface $package, $path)
|
||||||
{
|
{
|
||||||
if (isset($this->additionalCleanupPaths[$package->getName()])) {
|
if (isset($this->additionalCleanupPaths[$package->getName()])) {
|
||||||
$idx = array_search($path, $this->additionalCleanupPaths[$package->getName()]);
|
$idx = array_search($path, $this->additionalCleanupPaths[$package->getName()]);
|
||||||
|
@ -416,11 +406,9 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface
|
||||||
if (!$promise instanceof PromiseInterface) {
|
if (!$promise instanceof PromiseInterface) {
|
||||||
$promise = \React\Promise\resolve();
|
$promise = \React\Promise\resolve();
|
||||||
}
|
}
|
||||||
$self = $this;
|
|
||||||
$io = $this->io;
|
|
||||||
|
|
||||||
return $promise->then(function () use ($self, $target, $path) {
|
return $promise->then(function () use ($target, $path) {
|
||||||
$promise = $self->install($target, $path, false);
|
$promise = $this->install($target, $path, false);
|
||||||
|
|
||||||
return $promise;
|
return $promise;
|
||||||
});
|
});
|
||||||
|
|
|
@ -126,9 +126,8 @@ class ZipDownloader extends ArchiveDownloader
|
||||||
|
|
||||||
$executable = $commandSpec[0];
|
$executable = $commandSpec[0];
|
||||||
|
|
||||||
$self = $this;
|
|
||||||
$io = $this->io;
|
$io = $this->io;
|
||||||
$tryFallback = function ($processError) use ($isLastChance, $io, $self, $file, $path, $package, $executable) {
|
$tryFallback = function ($processError) use ($isLastChance, $io, $file, $path, $package, $executable) {
|
||||||
if ($isLastChance) {
|
if ($isLastChance) {
|
||||||
throw $processError;
|
throw $processError;
|
||||||
}
|
}
|
||||||
|
@ -143,15 +142,15 @@ class ZipDownloader extends ArchiveDownloader
|
||||||
$io->writeError(' Unzip with '.$executable.' command failed, falling back to ZipArchive class');
|
$io->writeError(' Unzip with '.$executable.' command failed, falling back to ZipArchive class');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $self->extractWithZipArchive($package, $file, $path);
|
return $this->extractWithZipArchive($package, $file, $path);
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$promise = $this->process->executeAsync($command);
|
$promise = $this->process->executeAsync($command);
|
||||||
|
|
||||||
return $promise->then(function ($process) use ($tryFallback, $command, $package, $file, $self) {
|
return $promise->then(function ($process) use ($tryFallback, $command, $package, $file) {
|
||||||
if (!$process->isSuccessful()) {
|
if (!$process->isSuccessful()) {
|
||||||
if (isset($self->cleanupExecuted[$package->getName()])) {
|
if (isset($this->cleanupExecuted[$package->getName()])) {
|
||||||
throw new \RuntimeException('Failed to extract '.$package->getName().' as the installation was aborted by another package operation.');
|
throw new \RuntimeException('Failed to extract '.$package->getName().' as the installation was aborted by another package operation.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,11 +173,8 @@ class ZipDownloader extends ArchiveDownloader
|
||||||
* @param string $file File to extract
|
* @param string $file File to extract
|
||||||
* @param string $path Path where to extract file
|
* @param string $path Path where to extract file
|
||||||
* @return PromiseInterface
|
* @return PromiseInterface
|
||||||
*
|
|
||||||
* TODO v3 should make this private once we can drop PHP 5.3 support
|
|
||||||
* @protected
|
|
||||||
*/
|
*/
|
||||||
public function extractWithZipArchive(PackageInterface $package, $file, $path)
|
private function extractWithZipArchive(PackageInterface $package, $file, $path)
|
||||||
{
|
{
|
||||||
$processError = null;
|
$processError = null;
|
||||||
$zipArchive = $this->zipArchiveObject ?: new ZipArchive();
|
$zipArchive = $this->zipArchiveObject ?: new ZipArchive();
|
||||||
|
@ -214,11 +210,8 @@ class ZipDownloader extends ArchiveDownloader
|
||||||
* @param string $file File to extract
|
* @param string $file File to extract
|
||||||
* @param string $path Path where to extract file
|
* @param string $path Path where to extract file
|
||||||
* @return PromiseInterface|null
|
* @return PromiseInterface|null
|
||||||
*
|
|
||||||
* TODO v3 should make this private once we can drop PHP 5.3 support
|
|
||||||
* @protected
|
|
||||||
*/
|
*/
|
||||||
public function extract(PackageInterface $package, $file, $path)
|
protected function extract(PackageInterface $package, $file, $path)
|
||||||
{
|
{
|
||||||
return $this->extractWithSystemUnzip($package, $file, $path);
|
return $this->extractWithSystemUnzip($package, $file, $path);
|
||||||
}
|
}
|
||||||
|
|
|
@ -436,7 +436,6 @@ class InstallationManager
|
||||||
}
|
}
|
||||||
|
|
||||||
$dispatcher = $this->eventDispatcher;
|
$dispatcher = $this->eventDispatcher;
|
||||||
$installManager = $this;
|
|
||||||
$io = $this->io;
|
$io = $this->io;
|
||||||
|
|
||||||
$promise = $installer->prepare($opType, $package, $initialPackage);
|
$promise = $installer->prepare($opType, $package, $initialPackage);
|
||||||
|
@ -444,11 +443,11 @@ class InstallationManager
|
||||||
$promise = \React\Promise\resolve();
|
$promise = \React\Promise\resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
$promise = $promise->then(function () use ($opType, $installManager, $repo, $operation) {
|
$promise = $promise->then(function () use ($opType, $repo, $operation) {
|
||||||
return $installManager->$opType($repo, $operation);
|
return $this->$opType($repo, $operation);
|
||||||
})->then($cleanupPromises[$index])
|
})->then($cleanupPromises[$index])
|
||||||
->then(function () use ($installManager, $devMode, $repo) {
|
->then(function () use ($devMode, $repo) {
|
||||||
$repo->write($devMode, $installManager);
|
$repo->write($devMode, $this);
|
||||||
}, function ($e) use ($opType, $package, $io) {
|
}, function ($e) use ($opType, $package, $io) {
|
||||||
$io->writeError(' <error>' . ucfirst($opType) .' of '.$package->getPrettyName().' failed</error>');
|
$io->writeError(' <error>' . ucfirst($opType) .' of '.$package->getPrettyName().' failed</error>');
|
||||||
|
|
||||||
|
|
|
@ -287,15 +287,8 @@ class LibraryInstaller implements InstallerInterface, BinaryPresenceInterface
|
||||||
$promise = \React\Promise\resolve();
|
$promise = \React\Promise\resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
$self = $this;
|
return $promise->then(function () use ($target) {
|
||||||
|
return $this->installCode($target);
|
||||||
return $promise->then(function () use ($self, $target) {
|
|
||||||
$reflMethod = new \ReflectionMethod($self, 'installCode');
|
|
||||||
$reflMethod->setAccessible(true);
|
|
||||||
|
|
||||||
// equivalent of $this->installCode($target) with php 5.3 support
|
|
||||||
// TODO remove this once 5.3 support is dropped
|
|
||||||
return $reflMethod->invoke($self, $target);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,15 +70,12 @@ class PluginInstaller extends LibraryInstaller
|
||||||
$promise = \React\Promise\resolve();
|
$promise = \React\Promise\resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
$pluginManager = $this->composer->getPluginManager();
|
return $promise->then(function () use ($package, $repo) {
|
||||||
$self = $this;
|
|
||||||
|
|
||||||
return $promise->then(function () use ($self, $pluginManager, $package, $repo) {
|
|
||||||
try {
|
try {
|
||||||
Platform::workaroundFilesystemIssues();
|
Platform::workaroundFilesystemIssues();
|
||||||
$pluginManager->registerPackage($package, true);
|
$this->composer->getPluginManager()->registerPackage($package, true);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$self->rollbackInstall($e, $repo, $package);
|
$this->rollbackInstall($e, $repo, $package);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -93,16 +90,13 @@ class PluginInstaller extends LibraryInstaller
|
||||||
$promise = \React\Promise\resolve();
|
$promise = \React\Promise\resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
$pluginManager = $this->composer->getPluginManager();
|
return $promise->then(function () use ($initial, $target, $repo) {
|
||||||
$self = $this;
|
|
||||||
|
|
||||||
return $promise->then(function () use ($self, $pluginManager, $initial, $target, $repo) {
|
|
||||||
try {
|
try {
|
||||||
Platform::workaroundFilesystemIssues();
|
Platform::workaroundFilesystemIssues();
|
||||||
$pluginManager->deactivatePackage($initial);
|
$this->composer->getPluginManager()->deactivatePackage($initial);
|
||||||
$pluginManager->registerPackage($target, true);
|
$this->composer->getPluginManager()->registerPackage($target, true);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$self->rollbackInstall($e, $repo, $target);
|
$this->rollbackInstall($e, $repo, $target);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -114,13 +108,7 @@ class PluginInstaller extends LibraryInstaller
|
||||||
return parent::uninstall($repo, $package);
|
return parent::uninstall($repo, $package);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function rollbackInstall(\Exception $e, InstalledRepositoryInterface $repo, PackageInterface $package): void
|
||||||
* TODO v3 should make this private once we can drop PHP 5.3 support
|
|
||||||
* @private
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function rollbackInstall(\Exception $e, InstalledRepositoryInterface $repo, PackageInterface $package)
|
|
||||||
{
|
{
|
||||||
$this->io->writeError('Plugin initialization failed ('.$e->getMessage().'), uninstalling plugin');
|
$this->io->writeError('Plugin initialization failed ('.$e->getMessage().'), uninstalling plugin');
|
||||||
parent::uninstall($repo, $package);
|
parent::uninstall($repo, $package);
|
||||||
|
|
|
@ -294,12 +294,10 @@ class JsonManipulator
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$that = $this;
|
|
||||||
|
|
||||||
// child exists
|
// child exists
|
||||||
$childRegex = '{'.self::$DEFINES.'(?P<start>"'.preg_quote($name).'"\s*:\s*)(?P<content>(?&json))(?P<end>,?)}x';
|
$childRegex = '{'.self::$DEFINES.'(?P<start>"'.preg_quote($name).'"\s*:\s*)(?P<content>(?&json))(?P<end>,?)}x';
|
||||||
if (Preg::isMatch($childRegex, $children, $matches)) {
|
if (Preg::isMatch($childRegex, $children, $matches)) {
|
||||||
$children = Preg::replaceCallback($childRegex, function ($matches) use ($subName, $value, $that) {
|
$children = Preg::replaceCallback($childRegex, function ($matches) use ($subName, $value) {
|
||||||
if ($subName !== null) {
|
if ($subName !== null) {
|
||||||
$curVal = json_decode($matches['content'], true);
|
$curVal = json_decode($matches['content'], true);
|
||||||
if (!is_array($curVal)) {
|
if (!is_array($curVal)) {
|
||||||
|
@ -309,7 +307,7 @@ class JsonManipulator
|
||||||
$value = $curVal;
|
$value = $curVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $matches['start'] . $that->format($value, 1) . $matches['end'];
|
return $matches['start'] . $this->format($value, 1) . $matches['end'];
|
||||||
}, $children);
|
}, $children);
|
||||||
} else {
|
} else {
|
||||||
Preg::match('#^{ (?P<leadingspace>\s*?) (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $children, $match);
|
Preg::match('#^{ (?P<leadingspace>\s*?) (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $children, $match);
|
||||||
|
@ -452,12 +450,11 @@ class JsonManipulator
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$that = $this;
|
$this->contents = Preg::replaceCallback($nodeRegex, function ($matches) use ($name, $subName, $childrenClean) {
|
||||||
$this->contents = Preg::replaceCallback($nodeRegex, function ($matches) use ($that, $name, $subName, $childrenClean) {
|
|
||||||
if ($subName !== null) {
|
if ($subName !== null) {
|
||||||
$curVal = json_decode($matches['content'], true);
|
$curVal = json_decode($matches['content'], true);
|
||||||
unset($curVal[$name][$subName]);
|
unset($curVal[$name][$subName]);
|
||||||
$childrenClean = $that->format($curVal);
|
$childrenClean = $this->format($curVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $matches['start'] . $childrenClean . $matches['end'];
|
return $matches['start'] . $childrenClean . $matches['end'];
|
||||||
|
|
|
@ -106,28 +106,23 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
private $partialPackagesByName = null;
|
private $partialPackagesByName = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO v3 should make this private once we can drop PHP 5.3 support
|
|
||||||
* @private
|
|
||||||
* @var array list of package names which are fresh and can be loaded from the cache directly in case loadPackage is called several times
|
* @var array list of package names which are fresh and can be loaded from the cache directly in case loadPackage is called several times
|
||||||
* useful for v2 metadata repositories with lazy providers
|
* useful for v2 metadata repositories with lazy providers
|
||||||
* @phpstan-var array<string, true>
|
* @phpstan-var array<string, true>
|
||||||
*/
|
*/
|
||||||
public $freshMetadataUrls = array();
|
private $freshMetadataUrls = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO v3 should make this private once we can drop PHP 5.3 support
|
|
||||||
* @private
|
|
||||||
* @var array list of package names which returned a 404 and should not be re-fetched in case loadPackage is called several times
|
* @var array list of package names which returned a 404 and should not be re-fetched in case loadPackage is called several times
|
||||||
* useful for v2 metadata repositories with lazy providers
|
* useful for v2 metadata repositories with lazy providers
|
||||||
* @phpstan-var array<string, true>
|
* @phpstan-var array<string, true>
|
||||||
*/
|
*/
|
||||||
public $packagesNotFoundCache = array();
|
private $packagesNotFoundCache = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO v3 should make this private once we can drop PHP 5.3 support
|
|
||||||
* @private
|
|
||||||
* @var VersionParser
|
* @var VersionParser
|
||||||
*/
|
*/
|
||||||
public $versionParser;
|
private $versionParser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<string, mixed> $repoConfig
|
* @param array<string, mixed> $repoConfig
|
||||||
|
@ -867,7 +862,6 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
$packages = array();
|
$packages = array();
|
||||||
$namesFound = array();
|
$namesFound = array();
|
||||||
$promises = array();
|
$promises = array();
|
||||||
$repo = $this;
|
|
||||||
|
|
||||||
if (!$this->lazyProvidersUrl) {
|
if (!$this->lazyProvidersUrl) {
|
||||||
throw new \LogicException('loadAsyncPackages only supports v2 protocol composer repos with a metadata-url');
|
throw new \LogicException('loadAsyncPackages only supports v2 protocol composer repos with a metadata-url');
|
||||||
|
@ -903,7 +897,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
}
|
}
|
||||||
|
|
||||||
$promises[] = $this->asyncFetchFile($url, $cacheKey, $lastModified)
|
$promises[] = $this->asyncFetchFile($url, $cacheKey, $lastModified)
|
||||||
->then(function ($response) use (&$packages, &$namesFound, $url, $cacheKey, $contents, $realName, $constraint, $repo, $acceptableStabilities, $stabilityFlags, $alreadyLoaded) {
|
->then(function ($response) use (&$packages, &$namesFound, $url, $cacheKey, $contents, $realName, $constraint, $acceptableStabilities, $stabilityFlags, $alreadyLoaded) {
|
||||||
$packagesSource = 'downloaded file ('.Url::sanitize($url).')';
|
$packagesSource = 'downloaded file ('.Url::sanitize($url).')';
|
||||||
|
|
||||||
if (true === $response) {
|
if (true === $response) {
|
||||||
|
@ -925,10 +919,10 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
$versionsToLoad = array();
|
$versionsToLoad = array();
|
||||||
foreach ($versions as $version) {
|
foreach ($versions as $version) {
|
||||||
if (!isset($version['version_normalized'])) {
|
if (!isset($version['version_normalized'])) {
|
||||||
$version['version_normalized'] = $repo->versionParser->normalize($version['version']);
|
$version['version_normalized'] = $this->versionParser->normalize($version['version']);
|
||||||
} elseif ($version['version_normalized'] === VersionParser::DEFAULT_BRANCH_ALIAS) {
|
} elseif ($version['version_normalized'] === VersionParser::DEFAULT_BRANCH_ALIAS) {
|
||||||
// handling of existing repos which need to remain composer v1 compatible, in case the version_normalized contained VersionParser::DEFAULT_BRANCH_ALIAS, we renormalize it
|
// handling of existing repos which need to remain composer v1 compatible, in case the version_normalized contained VersionParser::DEFAULT_BRANCH_ALIAS, we renormalize it
|
||||||
$version['version_normalized'] = $repo->versionParser->normalize($version['version']);
|
$version['version_normalized'] = $this->versionParser->normalize($version['version']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// avoid loading packages which have already been loaded
|
// avoid loading packages which have already been loaded
|
||||||
|
@ -936,18 +930,18 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($repo->isVersionAcceptable($constraint, $realName, $version, $acceptableStabilities, $stabilityFlags)) {
|
if ($this->isVersionAcceptable($constraint, $realName, $version, $acceptableStabilities, $stabilityFlags)) {
|
||||||
$versionsToLoad[] = $version;
|
$versionsToLoad[] = $version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$loadedPackages = $repo->createPackages($versionsToLoad, $packagesSource);
|
$loadedPackages = $this->createPackages($versionsToLoad, $packagesSource);
|
||||||
foreach ($loadedPackages as $package) {
|
foreach ($loadedPackages as $package) {
|
||||||
$package->setRepository($repo);
|
$package->setRepository($this);
|
||||||
$packages[spl_object_hash($package)] = $package;
|
$packages[spl_object_hash($package)] = $package;
|
||||||
|
|
||||||
if ($package instanceof AliasPackage && !isset($packages[spl_object_hash($package->getAliasOf())])) {
|
if ($package instanceof AliasPackage && !isset($packages[spl_object_hash($package->getAliasOf())])) {
|
||||||
$package->getAliasOf()->setRepository($repo);
|
$package->getAliasOf()->setRepository($this);
|
||||||
$packages[spl_object_hash($package->getAliasOf())] = $package->getAliasOf();
|
$packages[spl_object_hash($package->getAliasOf())] = $package->getAliasOf();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -961,10 +955,6 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO v3 should make this private once we can drop PHP 5.3 support
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
*
|
|
||||||
* @param ConstraintInterface|null $constraint
|
* @param ConstraintInterface|null $constraint
|
||||||
* @param string $name package name (must be lowercased already)
|
* @param string $name package name (must be lowercased already)
|
||||||
* @param array<string, mixed> $versionData
|
* @param array<string, mixed> $versionData
|
||||||
|
@ -975,7 +965,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isVersionAcceptable($constraint, $name, $versionData, array $acceptableStabilities = null, array $stabilityFlags = null)
|
private function isVersionAcceptable($constraint, $name, $versionData, array $acceptableStabilities = null, array $stabilityFlags = null)
|
||||||
{
|
{
|
||||||
$versions = array($versionData['version_normalized']);
|
$versions = array($versionData['version_normalized']);
|
||||||
|
|
||||||
|
@ -1248,15 +1238,12 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO v3 should make this private once we can drop PHP 5.3 support
|
|
||||||
* @private
|
|
||||||
*
|
|
||||||
* @param mixed[] $packages
|
* @param mixed[] $packages
|
||||||
* @param string|null $source
|
* @param string|null $source
|
||||||
*
|
*
|
||||||
* @return list<CompletePackage|CompleteAliasPackage>
|
* @return list<CompletePackage|CompleteAliasPackage>
|
||||||
*/
|
*/
|
||||||
public function createPackages(array $packages, $source = null)
|
private function createPackages(array $packages, $source = null)
|
||||||
{
|
{
|
||||||
if (!$packages) {
|
if (!$packages) {
|
||||||
return array();
|
return array();
|
||||||
|
@ -1499,25 +1486,24 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
$cache = $this->cache;
|
$cache = $this->cache;
|
||||||
$degradedMode = &$this->degradedMode;
|
$degradedMode = &$this->degradedMode;
|
||||||
$eventDispatcher = $this->eventDispatcher;
|
$eventDispatcher = $this->eventDispatcher;
|
||||||
$repo = $this;
|
|
||||||
|
|
||||||
$accept = function ($response) use ($io, $url, $filename, $cache, $cacheKey, $eventDispatcher, $repo) {
|
$accept = function ($response) use ($io, $url, $filename, $cache, $cacheKey, $eventDispatcher) {
|
||||||
// package not found is acceptable for a v2 protocol repository
|
// package not found is acceptable for a v2 protocol repository
|
||||||
if ($response->getStatusCode() === 404) {
|
if ($response->getStatusCode() === 404) {
|
||||||
$repo->packagesNotFoundCache[$filename] = true;
|
$this->packagesNotFoundCache[$filename] = true;
|
||||||
|
|
||||||
return array('packages' => array());
|
return array('packages' => array());
|
||||||
}
|
}
|
||||||
|
|
||||||
$json = (string) $response->getBody();
|
$json = (string) $response->getBody();
|
||||||
if ($json === '' && $response->getStatusCode() === 304) {
|
if ($json === '' && $response->getStatusCode() === 304) {
|
||||||
$repo->freshMetadataUrls[$filename] = true;
|
$this->freshMetadataUrls[$filename] = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($eventDispatcher) {
|
if ($eventDispatcher) {
|
||||||
$postFileDownloadEvent = new PostFileDownloadEvent(PluginEvents::POST_FILE_DOWNLOAD, null, null, $filename, 'metadata', array('response' => $response, 'repository' => $repo));
|
$postFileDownloadEvent = new PostFileDownloadEvent(PluginEvents::POST_FILE_DOWNLOAD, null, null, $filename, 'metadata', array('response' => $response, 'repository' => $this));
|
||||||
$eventDispatcher->dispatch($postFileDownloadEvent->getName(), $postFileDownloadEvent);
|
$eventDispatcher->dispatch($postFileDownloadEvent->getName(), $postFileDownloadEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1533,14 +1519,14 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
|
||||||
if (!$cache->isReadOnly()) {
|
if (!$cache->isReadOnly()) {
|
||||||
$cache->write($cacheKey, $json);
|
$cache->write($cacheKey, $json);
|
||||||
}
|
}
|
||||||
$repo->freshMetadataUrls[$filename] = true;
|
$this->freshMetadataUrls[$filename] = true;
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
};
|
};
|
||||||
|
|
||||||
$reject = function ($e) use ($filename, $accept, $io, $url, &$degradedMode, $repo, $lastModifiedTime) {
|
$reject = function ($e) use ($filename, $accept, $io, $url, &$degradedMode, $lastModifiedTime) {
|
||||||
if ($e instanceof TransportException && $e->getStatusCode() === 404) {
|
if ($e instanceof TransportException && $e->getStatusCode() === 404) {
|
||||||
$repo->packagesNotFoundCache[$filename] = true;
|
$this->packagesNotFoundCache[$filename] = true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,9 +157,7 @@ class Filesystem
|
||||||
|
|
||||||
$promise = $this->getProcess()->executeAsync($cmd);
|
$promise = $this->getProcess()->executeAsync($cmd);
|
||||||
|
|
||||||
$self = $this;
|
return $promise->then(function ($process) use ($directory) {
|
||||||
|
|
||||||
return $promise->then(function ($process) use ($directory, $self) {
|
|
||||||
// clear stat cache because external processes aren't tracked by the php stat cache
|
// clear stat cache because external processes aren't tracked by the php stat cache
|
||||||
clearstatcache();
|
clearstatcache();
|
||||||
|
|
||||||
|
@ -169,7 +167,7 @@ class Filesystem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return \React\Promise\resolve($self->removeDirectoryPhp($directory));
|
return \React\Promise\resolve($this->removeDirectoryPhp($directory));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -264,7 +264,6 @@ class HttpDownloader
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
$downloader = $this;
|
|
||||||
$curl = $this->curl;
|
$curl = $this->curl;
|
||||||
|
|
||||||
$canceler = function () use (&$job, $curl) {
|
$canceler = function () use (&$job, $curl) {
|
||||||
|
@ -282,19 +281,18 @@ class HttpDownloader
|
||||||
};
|
};
|
||||||
|
|
||||||
$promise = new Promise($resolver, $canceler);
|
$promise = new Promise($resolver, $canceler);
|
||||||
$promise = $promise->then(function ($response) use (&$job, $downloader) {
|
$promise = $promise->then(function ($response) use (&$job) {
|
||||||
$job['status'] = HttpDownloader::STATUS_COMPLETED;
|
$job['status'] = HttpDownloader::STATUS_COMPLETED;
|
||||||
$job['response'] = $response;
|
$job['response'] = $response;
|
||||||
|
|
||||||
// TODO 3.0 this should be done directly on $this when PHP 5.3 is dropped
|
$this->markJobDone();
|
||||||
$downloader->markJobDone();
|
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}, function ($e) use (&$job, $downloader) {
|
}, function ($e) use (&$job) {
|
||||||
$job['status'] = HttpDownloader::STATUS_FAILED;
|
$job['status'] = HttpDownloader::STATUS_FAILED;
|
||||||
$job['exception'] = $e;
|
$job['exception'] = $e;
|
||||||
|
|
||||||
$downloader->markJobDone();
|
$this->markJobDone();
|
||||||
|
|
||||||
throw $e;
|
throw $e;
|
||||||
});
|
});
|
||||||
|
@ -351,11 +349,7 @@ class HttpDownloader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function markJobDone(): void
|
||||||
* @private
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function markJobDone()
|
|
||||||
{
|
{
|
||||||
$this->runningJobs--;
|
$this->runningJobs--;
|
||||||
}
|
}
|
||||||
|
|
|
@ -344,12 +344,7 @@ class ProcessExecutor
|
||||||
return $active;
|
return $active;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function markJobDone(): void
|
||||||
* @private
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function markJobDone()
|
|
||||||
{
|
{
|
||||||
$this->runningJobs--;
|
$this->runningJobs--;
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,6 @@ class AutoloadGeneratorTest extends TestCase
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
$this->fs = new Filesystem;
|
$this->fs = new Filesystem;
|
||||||
$that = $this;
|
|
||||||
|
|
||||||
$this->workingDir = $this->getUniqueTmpDirectory();
|
$this->workingDir = $this->getUniqueTmpDirectory();
|
||||||
$this->vendorDir = $this->workingDir.DIRECTORY_SEPARATOR.'composer-test-autoload';
|
$this->vendorDir = $this->workingDir.DIRECTORY_SEPARATOR.'composer-test-autoload';
|
||||||
|
@ -101,8 +100,8 @@ class AutoloadGeneratorTest extends TestCase
|
||||||
$this->config = $this->getMockBuilder('Composer\Config')->getMock();
|
$this->config = $this->getMockBuilder('Composer\Config')->getMock();
|
||||||
|
|
||||||
$this->configValueMap = array(
|
$this->configValueMap = array(
|
||||||
'vendor-dir' => function () use ($that) {
|
'vendor-dir' => function () {
|
||||||
return $that->vendorDir;
|
return $this->vendorDir;
|
||||||
},
|
},
|
||||||
'platform-check' => function () {
|
'platform-check' => function () {
|
||||||
return true;
|
return true;
|
||||||
|
@ -111,10 +110,10 @@ class AutoloadGeneratorTest extends TestCase
|
||||||
|
|
||||||
$this->config->expects($this->atLeastOnce())
|
$this->config->expects($this->atLeastOnce())
|
||||||
->method('get')
|
->method('get')
|
||||||
->will($this->returnCallback(function ($arg) use ($that) {
|
->will($this->returnCallback(function ($arg) {
|
||||||
$ret = null;
|
$ret = null;
|
||||||
if (isset($that->configValueMap[$arg])) {
|
if (isset($this->configValueMap[$arg])) {
|
||||||
$ret = $that->configValueMap[$arg];
|
$ret = $this->configValueMap[$arg];
|
||||||
if (is_callable($ret)) {
|
if (is_callable($ret)) {
|
||||||
$ret = $ret();
|
$ret = $ret();
|
||||||
}
|
}
|
||||||
|
@ -131,10 +130,10 @@ class AutoloadGeneratorTest extends TestCase
|
||||||
->getMock();
|
->getMock();
|
||||||
$this->im->expects($this->any())
|
$this->im->expects($this->any())
|
||||||
->method('getInstallPath')
|
->method('getInstallPath')
|
||||||
->will($this->returnCallback(function ($package) use ($that) {
|
->will($this->returnCallback(function ($package) {
|
||||||
$targetDir = $package->getTargetDir();
|
$targetDir = $package->getTargetDir();
|
||||||
|
|
||||||
return $that->vendorDir.'/'.$package->getName() . ($targetDir ? '/'.$targetDir : '');
|
return $this->vendorDir.'/'.$package->getName() . ($targetDir ? '/'.$targetDir : '');
|
||||||
}));
|
}));
|
||||||
$this->repository = $this->getMockBuilder('Composer\Repository\InstalledRepositoryInterface')->getMock();
|
$this->repository = $this->getMockBuilder('Composer\Repository\InstalledRepositoryInterface')->getMock();
|
||||||
$this->repository->expects($this->any())
|
$this->repository->expects($this->any())
|
||||||
|
|
|
@ -180,8 +180,6 @@ class FileDownloaderTest extends TestCase
|
||||||
|
|
||||||
public function testDownloadWithCustomProcessedUrl()
|
public function testDownloadWithCustomProcessedUrl()
|
||||||
{
|
{
|
||||||
$self = $this;
|
|
||||||
|
|
||||||
$path = $this->getUniqueTmpDirectory();
|
$path = $this->getUniqueTmpDirectory();
|
||||||
|
|
||||||
$packageMock = $this->getMockBuilder('Composer\Package\PackageInterface')->getMock();
|
$packageMock = $this->getMockBuilder('Composer\Package\PackageInterface')->getMock();
|
||||||
|
@ -232,16 +230,16 @@ class FileDownloaderTest extends TestCase
|
||||||
$cacheMock
|
$cacheMock
|
||||||
->expects($this->any())
|
->expects($this->any())
|
||||||
->method('copyTo')
|
->method('copyTo')
|
||||||
->will($this->returnCallback(function ($cacheKey) use ($self, $expectedCacheKey) {
|
->will($this->returnCallback(function ($cacheKey) use ($expectedCacheKey) {
|
||||||
$self->assertEquals($expectedCacheKey, $cacheKey, 'Failed assertion on $cacheKey argument of Cache::copyTo method:');
|
$this->assertEquals($expectedCacheKey, $cacheKey, 'Failed assertion on $cacheKey argument of Cache::copyTo method:');
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}));
|
}));
|
||||||
$cacheMock
|
$cacheMock
|
||||||
->expects($this->any())
|
->expects($this->any())
|
||||||
->method('copyFrom')
|
->method('copyFrom')
|
||||||
->will($this->returnCallback(function ($cacheKey) use ($self, $expectedCacheKey) {
|
->will($this->returnCallback(function ($cacheKey) use ($expectedCacheKey) {
|
||||||
$self->assertEquals($expectedCacheKey, $cacheKey, 'Failed assertion on $cacheKey argument of Cache::copyFrom method:');
|
$this->assertEquals($expectedCacheKey, $cacheKey, 'Failed assertion on $cacheKey argument of Cache::copyFrom method:');
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}));
|
}));
|
||||||
|
@ -250,8 +248,8 @@ class FileDownloaderTest extends TestCase
|
||||||
$httpDownloaderMock
|
$httpDownloaderMock
|
||||||
->expects($this->any())
|
->expects($this->any())
|
||||||
->method('addCopy')
|
->method('addCopy')
|
||||||
->will($this->returnCallback(function ($url) use ($self, $expectedUrl) {
|
->will($this->returnCallback(function ($url) use ($expectedUrl) {
|
||||||
$self->assertEquals($expectedUrl, $url, 'Failed assertion on $url argument of HttpDownloader::addCopy method:');
|
$this->assertEquals($expectedUrl, $url, 'Failed assertion on $url argument of HttpDownloader::addCopy method:');
|
||||||
|
|
||||||
return \React\Promise\resolve(
|
return \React\Promise\resolve(
|
||||||
new Response(array('url' => 'http://example.org/'), 200, array(), 'file~')
|
new Response(array('url' => 'http://example.org/'), 200, array(), 'file~')
|
||||||
|
@ -281,8 +279,6 @@ class FileDownloaderTest extends TestCase
|
||||||
|
|
||||||
public function testDownloadWithCustomCacheKey()
|
public function testDownloadWithCustomCacheKey()
|
||||||
{
|
{
|
||||||
$self = $this;
|
|
||||||
|
|
||||||
$path = $this->getUniqueTmpDirectory();
|
$path = $this->getUniqueTmpDirectory();
|
||||||
|
|
||||||
$packageMock = $this->getMockBuilder('Composer\Package\PackageInterface')->getMock();
|
$packageMock = $this->getMockBuilder('Composer\Package\PackageInterface')->getMock();
|
||||||
|
@ -334,16 +330,16 @@ class FileDownloaderTest extends TestCase
|
||||||
$cacheMock
|
$cacheMock
|
||||||
->expects($this->any())
|
->expects($this->any())
|
||||||
->method('copyTo')
|
->method('copyTo')
|
||||||
->will($this->returnCallback(function ($cacheKey) use ($self, $expectedCacheKey) {
|
->will($this->returnCallback(function ($cacheKey) use ($expectedCacheKey) {
|
||||||
$self->assertEquals($expectedCacheKey, $cacheKey, 'Failed assertion on $cacheKey argument of Cache::copyTo method:');
|
$this->assertEquals($expectedCacheKey, $cacheKey, 'Failed assertion on $cacheKey argument of Cache::copyTo method:');
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}));
|
}));
|
||||||
$cacheMock
|
$cacheMock
|
||||||
->expects($this->any())
|
->expects($this->any())
|
||||||
->method('copyFrom')
|
->method('copyFrom')
|
||||||
->will($this->returnCallback(function ($cacheKey) use ($self, $expectedCacheKey) {
|
->will($this->returnCallback(function ($cacheKey) use ($expectedCacheKey) {
|
||||||
$self->assertEquals($expectedCacheKey, $cacheKey, 'Failed assertion on $cacheKey argument of Cache::copyFrom method:');
|
$this->assertEquals($expectedCacheKey, $cacheKey, 'Failed assertion on $cacheKey argument of Cache::copyFrom method:');
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}));
|
}));
|
||||||
|
@ -352,8 +348,8 @@ class FileDownloaderTest extends TestCase
|
||||||
$httpDownloaderMock
|
$httpDownloaderMock
|
||||||
->expects($this->any())
|
->expects($this->any())
|
||||||
->method('addCopy')
|
->method('addCopy')
|
||||||
->will($this->returnCallback(function ($url) use ($self, $expectedUrl) {
|
->will($this->returnCallback(function ($url) use ($expectedUrl) {
|
||||||
$self->assertEquals($expectedUrl, $url, 'Failed assertion on $url argument of HttpDownloader::addCopy method:');
|
$this->assertEquals($expectedUrl, $url, 'Failed assertion on $url argument of HttpDownloader::addCopy method:');
|
||||||
|
|
||||||
return \React\Promise\resolve(
|
return \React\Promise\resolve(
|
||||||
new Response(array('url' => 'http://example.org/'), 200, array(), 'file~')
|
new Response(array('url' => 'http://example.org/'), 200, array(), 'file~')
|
||||||
|
|
|
@ -79,13 +79,12 @@ class BasePackageTest extends TestCase
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
$self = $this;
|
$createPackage = function ($arr) {
|
||||||
$createPackage = function ($arr) use ($self) {
|
$package = $this->getMockForAbstractClass('\Composer\Package\BasePackage', array(), '', false);
|
||||||
$package = $self->getMockForAbstractClass('\Composer\Package\BasePackage', array(), '', false);
|
$package->expects($this->once())->method('isDev')->will($this->returnValue(true));
|
||||||
$package->expects($self->once())->method('isDev')->will($self->returnValue(true));
|
$package->expects($this->any())->method('getSourceType')->will($this->returnValue('git'));
|
||||||
$package->expects($self->any())->method('getSourceType')->will($self->returnValue('git'));
|
$package->expects($this->once())->method('getPrettyVersion')->will($this->returnValue('PrettyVersion'));
|
||||||
$package->expects($self->once())->method('getPrettyVersion')->will($self->returnValue('PrettyVersion'));
|
$package->expects($this->any())->method('getSourceReference')->will($this->returnValue($arr['sourceReference']));
|
||||||
$package->expects($self->any())->method('getSourceReference')->will($self->returnValue($arr['sourceReference']));
|
|
||||||
|
|
||||||
return array($package, $arr['truncate'], $arr['expected']);
|
return array($package, $arr['truncate'], $arr['expected']);
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,7 +37,7 @@ class ComposerRepositoryTest extends TestCase
|
||||||
);
|
);
|
||||||
|
|
||||||
$repository = $this->getMockBuilder('Composer\Repository\ComposerRepository')
|
$repository = $this->getMockBuilder('Composer\Repository\ComposerRepository')
|
||||||
->onlyMethods(array('loadRootServerFile', 'createPackages'))
|
->onlyMethods(array('loadRootServerFile'))
|
||||||
->setConstructorArgs(array(
|
->setConstructorArgs(array(
|
||||||
$repoConfig,
|
$repoConfig,
|
||||||
new NullIO,
|
new NullIO,
|
||||||
|
@ -52,22 +52,15 @@ class ComposerRepositoryTest extends TestCase
|
||||||
->method('loadRootServerFile')
|
->method('loadRootServerFile')
|
||||||
->will($this->returnValue($repoPackages));
|
->will($this->returnValue($repoPackages));
|
||||||
|
|
||||||
$stubs = array();
|
|
||||||
foreach ($expected as $at => $arg) {
|
|
||||||
$stubs[] = $this->getPackage('stub/stub', '1.0.0');
|
|
||||||
}
|
|
||||||
|
|
||||||
$repository
|
|
||||||
->expects($this->once())
|
|
||||||
->method('createPackages')
|
|
||||||
->with($this->identicalTo($expected), $this->equalTo('root file (http://example.org/packages.json)'))
|
|
||||||
->will($this->returnValue($stubs));
|
|
||||||
|
|
||||||
// Triggers initialization
|
// Triggers initialization
|
||||||
$packages = $repository->getPackages();
|
$packages = $repository->getPackages();
|
||||||
|
|
||||||
// Final sanity check, ensure the correct number of packages were added.
|
// Final sanity check, ensure the correct number of packages were added.
|
||||||
$this->assertCount(count($expected), $packages);
|
$this->assertCount(count($expected), $packages);
|
||||||
|
|
||||||
|
foreach ($expected as $index => $pkg) {
|
||||||
|
self::assertSame($pkg['name'].' '.$pkg['version'], $packages[$index]->getName().' '.$packages[$index]->getPrettyVersion());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function loadDataProvider()
|
public function loadDataProvider()
|
||||||
|
|
|
@ -49,9 +49,8 @@ class GitTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function testRunCommandPublicGitHubRepositoryNotInitialClone($protocol, $expectedUrl)
|
public function testRunCommandPublicGitHubRepositoryNotInitialClone($protocol, $expectedUrl)
|
||||||
{
|
{
|
||||||
$that = $this;
|
$commandCallable = function ($url) use ($expectedUrl) {
|
||||||
$commandCallable = function ($url) use ($that, $expectedUrl) {
|
$this->assertSame($expectedUrl, $url);
|
||||||
$that->assertSame($expectedUrl, $url);
|
|
||||||
|
|
||||||
return 'git command';
|
return 'git command';
|
||||||
};
|
};
|
||||||
|
@ -75,9 +74,8 @@ class GitTest extends TestCase
|
||||||
{
|
{
|
||||||
self::expectException('RuntimeException');
|
self::expectException('RuntimeException');
|
||||||
|
|
||||||
$that = $this;
|
$commandCallable = function ($url) {
|
||||||
$commandCallable = function ($url) use ($that) {
|
$this->assertSame('https://github.com/acme/repo', $url);
|
||||||
$that->assertSame('https://github.com/acme/repo', $url);
|
|
||||||
|
|
||||||
return 'git command';
|
return 'git command';
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue