From 83b1b2c46743513262faea7bdb179aeb4d661546 Mon Sep 17 00:00:00 2001 From: Chris Brown Date: Tue, 8 Jan 2019 00:46:39 -0500 Subject: [PATCH] Rework PHP version resolution Last year's Homebrew's PHP packaging changes altered their version numbering strategy. Now that their changes appear to have stabilized, Valet also needs some updates to match. The `linkedPhp()` function was parsing the symlinked directory name for where the php binaries are stored, but that numbering strategy has morphed over time. This PR changes the logic to accommodate the most common directory naming strategies I can find, including those of older installs. I've included some examples of these names in code comments for future reference since finding a variety of them can be complicated. --- cli/Valet/Brew.php | 25 ++++++++++++++++++------- tests/BrewTest.php | 24 +++++++++++++++++++++--- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/cli/Valet/Brew.php b/cli/Valet/Brew.php index 62d53f0..b866e4e 100644 --- a/cli/Valet/Brew.php +++ b/cli/Valet/Brew.php @@ -192,17 +192,28 @@ function stopService($services) function linkedPhp() { if (! $this->files->isLink('/usr/local/bin/php')) { - throw new DomainException("Unable to determine linked PHP."); + throw new DomainException("Homebrew PHP appears not to be linked."); } $resolvedPath = $this->files->readLink('/usr/local/bin/php'); - return $this->supportedPhpVersions()->first(function ($version) use ($resolvedPath) { - $resolvedPathNormalized= preg_replace('/([@|\.])/', '', $resolvedPath); - $versionNormalized = preg_replace('/([@|\.])/', '', $version); - return strpos($resolvedPathNormalized, "/$versionNormalized/") !== false; - }, function () { - throw new DomainException("Unable to determine linked PHP."); + /** + * Typical homebrew path resolutions are like: + * "../Cellar/php@7.2/7.2.13/bin/php" + * or older styles: + * "../Cellar/php/7.2.9_2/bin/php + * "../Cellar/php55/bin/php + */ + preg_match('~\w{3,}/(php)(@?\d\.?\d)?/(\d\.\d)?([_\d\.]*)?/?\w{3,}~', $resolvedPath, $matches); + $resolvedPhpVersion = $matches[3] ?: $matches[2]; + + return $this->supportedPhpVersions()->first( + function ($version) use ($resolvedPhpVersion) { + $resolvedVersionNormalized = preg_replace('/[^\d]/', '', $resolvedPhpVersion); + $versionNormalized = preg_replace('/[^\d]/', '', $version); + return $resolvedVersionNormalized === $versionNormalized; + }, function () use ($resolvedPhpVersion) { + throw new DomainException("Unable to determine linked PHP when parsing '$resolvedPhpVersion'"); }); } diff --git a/tests/BrewTest.php b/tests/BrewTest.php index acc50b4..389e4d9 100644 --- a/tests/BrewTest.php +++ b/tests/BrewTest.php @@ -174,9 +174,27 @@ public function test_linked_php_returns_linked_php_formula_name() { $files = Mockery::mock(Filesystem::class); $files->shouldReceive('isLink')->once()->with('/usr/local/bin/php')->andReturn(true); - $files->shouldReceive('readLink')->once()->with('/usr/local/bin/php')->andReturn('/test/path/php71/test'); + $files->shouldReceive('readLink')->once()->with('/usr/local/bin/php')->andReturn('/test/path/php/7.3.0/test'); swap(Filesystem::class, $files); - $this->assertSame('php@7.1', resolve(Brew::class)->linkedPhp()); + $this->assertSame('php@7.3', resolve(Brew::class)->linkedPhp()); + + $files = Mockery::mock(Filesystem::class); + $files->shouldReceive('isLink')->once()->with('/usr/local/bin/php')->andReturn(true); + $files->shouldReceive('readLink')->once()->with('/usr/local/bin/php')->andReturn('/test/path/php@7.2/7.2.13/test'); + swap(Filesystem::class, $files); + $this->assertSame('php@7.2', resolve(Brew::class)->linkedPhp()); + + $files = Mockery::mock(Filesystem::class); + $files->shouldReceive('isLink')->once()->with('/usr/local/bin/php')->andReturn(true); + $files->shouldReceive('readLink')->once()->with('/usr/local/bin/php')->andReturn('/test/path/php/7.2.9_2/test'); + swap(Filesystem::class, $files); + $this->assertSame('php@7.2', resolve(Brew::class)->linkedPhp()); + + $files = Mockery::mock(Filesystem::class); + $files->shouldReceive('isLink')->once()->with('/usr/local/bin/php')->andReturn(true); + $files->shouldReceive('readLink')->once()->with('/usr/local/bin/php')->andReturn('/test/path/php72/7.2.9_2/test'); + swap(Filesystem::class, $files); + $this->assertSame('php@7.2', resolve(Brew::class)->linkedPhp()); $files = Mockery::mock(Filesystem::class); $files->shouldReceive('isLink')->once()->with('/usr/local/bin/php')->andReturn(true); @@ -205,7 +223,7 @@ public function test_linked_php_throws_exception_if_unsupported_php_version_is_l { $files = Mockery::mock(Filesystem::class); $files->shouldReceive('isLink')->once()->with('/usr/local/bin/php')->andReturn(true); - $files->shouldReceive('readLink')->once()->with('/usr/local/bin/php')->andReturn('/test/path/php42/test'); + $files->shouldReceive('readLink')->once()->with('/usr/local/bin/php')->andReturn('/test/path/php/5.4.14/test'); swap(Filesystem::class, $files); resolve(Brew::class)->linkedPhp(); }