From 1b196720bf451774f65a55e35b2298b9ef5482a4 Mon Sep 17 00:00:00 2001 From: Fred Emmott Date: Tue, 22 Jan 2019 13:45:25 -0800 Subject: [PATCH 1/4] Support identifying the HHVM version when not running with HHVM hhvm-nightly (and the next release) are no longer able to execute Composer. Support executing Composer with PHP to install dependencies for hack projects. The goal is for this to be temporary, until Hack identifies a new package manager, given that Composer does not aim to be a multi-language package manager. fixes #7734 --- .../Repository/PlatformRepository.php | 29 ++++++-- .../Repository/PlatformRepositoryTest.php | 69 +++++++++++++++++++ 2 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 tests/Composer/Test/Repository/PlatformRepositoryTest.php diff --git a/src/Composer/Repository/PlatformRepository.php b/src/Composer/Repository/PlatformRepository.php index 221f2eb97..56dc6ced5 100644 --- a/src/Composer/Repository/PlatformRepository.php +++ b/src/Composer/Repository/PlatformRepository.php @@ -16,8 +16,11 @@ use Composer\Package\CompletePackage; use Composer\Package\PackageInterface; use Composer\Package\Version\VersionParser; use Composer\Plugin\PluginInterface; +use Composer\Util\ProcessExecutor; use Composer\Util\Silencer; +use Composer\Util\Platform; use Composer\XdebugHandler\XdebugHandler; +use Symfony\Component\Process\ExecutableFinder; /** * @author Jordi Boggiano @@ -37,8 +40,11 @@ class PlatformRepository extends ArrayRepository */ private $overrides = array(); - public function __construct(array $packages = array(), array $overrides = array()) + private $process; + + public function __construct(array $packages = array(), array $overrides = array(), ProcessExecutor $process = null) { + $this->process = $process === null ? (new ProcessExecutor()) : $process; foreach ($overrides as $name => $version) { $this->overrides[strtolower($name)] = array('name' => $name, 'version' => $version); } @@ -220,12 +226,27 @@ class PlatformRepository extends ArrayRepository $this->addPackage($lib); } - if (defined('HHVM_VERSION')) { + $hhvmVersion = defined('HHVM_VERSION') ? HHVM_VERSION : null; + if ($hhvmVersion === null && !Platform::isWindows()) { + $finder = new ExecutableFinder(); + $hhvm = $finder->find('hhvm'); + if ($hhvm !== null) { + $exitCode = $this->process->execute( + ProcessExecutor::escape($hhvm). + ' --php -d hhvm.jit=0 -r "echo HHVM_VERSION;" 2>/dev/null', + $hhvmVersion + ); + if ($exitCode !== 0) { + $hhvmVersion = null; + } + } + } + if ($hhvmVersion) { try { - $prettyVersion = HHVM_VERSION; + $prettyVersion = $hhvmVersion; $version = $this->versionParser->normalize($prettyVersion); } catch (\UnexpectedValueException $e) { - $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', HHVM_VERSION); + $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', $hhvmVersion); $version = $this->versionParser->normalize($prettyVersion); } diff --git a/tests/Composer/Test/Repository/PlatformRepositoryTest.php b/tests/Composer/Test/Repository/PlatformRepositoryTest.php new file mode 100644 index 000000000..90674d4a3 --- /dev/null +++ b/tests/Composer/Test/Repository/PlatformRepositoryTest.php @@ -0,0 +1,69 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Test\Repository; + +use Composer\Repository\PlatformRepository; +use Composer\Test\TestCase; +use Composer\Util\Platform; +use Symfony\Component\Process\ExecutableFinder; + +class PlatformRepositoryTest extends TestCase { + public function testHHVMVersionWhenExecutingInHHVM() { + if (!defined('HHVM_VERSION_ID')) { + $this->markTestSkipped('Not running with HHVM'); + return; + } + $repository = new PlatformRepository(); + $package = $repository->findPackage('hhvm', '*'); + $this->assertNotNull($package, 'failed to find HHVM package'); + $this->assertSame( + sprintf('%d.%d.%d', + HHVM_VERSION_ID / 10000, + (HHVM_VERSION_ID / 100) % 100, + HHVM_VERSION_ID % 100 + ), + $package->getPrettyVersion() + ); + } + + public function testHHVMVersionWhenExecutingInPHP() { + if (defined('HHVM_VERSION_ID')) { + $this->markTestSkipped('Running with HHVM'); + return; + } + if (PHP_VERSION_ID < 50400) { + $this->markTestSkipped('Test only works on PHP 5.4+'); + return; + } + if (Platform::isWindows()) { + $this->markTestSkipped('Test does not run on Windows'); + return; + } + $hhvm = (new ExecutableFinder())->find('hhvm'); + if ($hhvm === null) { + $this->markTestSkipped('HHVM is not installed'); + } + $process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock(); + $process->expects($this->once())->method('execute')->will($this->returnCallback( + function($command, &$out) { + $this->assertContains('HHVM_VERSION', $command); + $out = '4.0.1-dev'; + return 0; + } + )); + $repository = new PlatformRepository(array(), array(), $process); + $package = $repository->findPackage('hhvm', '*'); + $this->assertNotNull($package, 'failed to find HHVM package'); + $this->assertSame('4.0.1.0-dev', $package->getVersion()); + } +} From bac2ef3dfdfe60cec4c1cea7371f776fa6073d0a Mon Sep 17 00:00:00 2001 From: Fred Emmott Date: Fri, 1 Feb 2019 11:20:34 -0800 Subject: [PATCH 2/4] Don't do (new Foo())->bar() - not 5.3-compatible --- tests/Composer/Test/Repository/PlatformRepositoryTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Composer/Test/Repository/PlatformRepositoryTest.php b/tests/Composer/Test/Repository/PlatformRepositoryTest.php index 90674d4a3..aa51a2fc6 100644 --- a/tests/Composer/Test/Repository/PlatformRepositoryTest.php +++ b/tests/Composer/Test/Repository/PlatformRepositoryTest.php @@ -49,7 +49,8 @@ class PlatformRepositoryTest extends TestCase { $this->markTestSkipped('Test does not run on Windows'); return; } - $hhvm = (new ExecutableFinder())->find('hhvm'); + $finder = new ExecutableFinder(); + $hhvm = $finder->find('hhvm'); if ($hhvm === null) { $this->markTestSkipped('HHVM is not installed'); } From 17788c76f635f0f4ff43e19e672e651fc144faf4 Mon Sep 17 00:00:00 2001 From: Fred Emmott Date: Wed, 6 Feb 2019 12:51:30 -0800 Subject: [PATCH 3/4] Better error message for present but incompatible versions hhvm-nightly (and next week's release) now report 4.x, so all the 3.x constraints are now giving misleading error messages with this patch. Before: ``` - facebook/fbexpect v2.3.0 requires hhvm ^3.28 -> you are running this with PHP and not HHVM. ``` After: ``` - facebook/fbexpect v2.3.0 requires hhvm ^3.28 -> your HHVM version (4.0.0-dev) does not satisfy that requirement. ``` --- src/Composer/DependencyResolver/Rule.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Composer/DependencyResolver/Rule.php b/src/Composer/DependencyResolver/Rule.php index 4760b8964..82c9c499c 100644 --- a/src/Composer/DependencyResolver/Rule.php +++ b/src/Composer/DependencyResolver/Rule.php @@ -175,13 +175,18 @@ abstract class Rule return $text . ' -> your HHVM version does not satisfy that requirement.'; } - if ($targetName === 'hhvm') { - return $text . ' -> you are running this with PHP and not HHVM.'; - } - $packages = $pool->whatProvides($targetName); $package = count($packages) ? current($packages) : phpversion(); + if ($targetName === 'hhvm') { + if ($package instanceof CompletePackage) { + return $text . ' -> your HHVM version ('.$package->getPrettyVersion().') does not satisfy that requirement.'; + } else { + return $text . ' -> you are running this with PHP and not HHVM.'; + } + } + + if (!($package instanceof CompletePackage)) { return $text . ' -> your PHP version ('.phpversion().') does not satisfy that requirement.'; } From 41c7f4d2bfedcd7266e854240e2ac22e582473c3 Mon Sep 17 00:00:00 2001 From: Fred Emmott Date: Wed, 6 Feb 2019 13:11:04 -0800 Subject: [PATCH 4/4] Same but for Problem.php --- src/Composer/DependencyResolver/Problem.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/DependencyResolver/Problem.php b/src/Composer/DependencyResolver/Problem.php index de24b0991..073f64e2d 100644 --- a/src/Composer/DependencyResolver/Problem.php +++ b/src/Composer/DependencyResolver/Problem.php @@ -106,7 +106,7 @@ class Problem $msg = "\n - This package requires ".$job['packageName'].$this->constraintToText($job['constraint']).' but '; - if (defined('HHVM_VERSION')) { + if (defined('HHVM_VERSION') || count($available)) { return $msg . 'your HHVM version does not satisfy that requirement.'; }