Skip to content

Commit

Permalink
Merge pull request #1008 from drbyte/valet-use-improvements
Browse files Browse the repository at this point in the history
Improvements to "valet use" command
  • Loading branch information
mattstauffer authored Nov 30, 2020
2 parents acb55d3 + 7d98b24 commit 04d42b3
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 166 deletions.
51 changes: 38 additions & 13 deletions cli/Valet/Brew.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,23 @@ function __construct(CommandLine $cli, Filesystem $files)
}

/**
* Determine if the given formula is installed.
* Ensure the formula exists in the current Homebrew configuration
*
* @param string $formula
* @return bool
*/
function installed($formula)
{
return in_array($formula, explode(PHP_EOL, $this->cli->runAsUser('brew list --formula | grep '.$formula)));
$result = $this->cli->runAsUser("brew info $formula --json");

// should be a json response, but if not installed then "Error: No available formula ..."
if (starts_with($result, 'Error: No')) {
return false;
}

$details = json_decode($result);

return !empty($details[0]->installed);
}

/**
Expand All @@ -58,9 +67,11 @@ function installed($formula)
*/
function hasInstalledPhp()
{
return $this->supportedPhpVersions()->contains(function ($version) {
return $this->installed($version);
$installed = $this->installedPhpFormulae()->first(function ($formula) {
return $this->supportedPhpVersions()->contains($formula);
});

return !empty($installed);
}

/**
Expand All @@ -73,13 +84,25 @@ function supportedPhpVersions()
return collect(static::SUPPORTED_PHP_VERSIONS);
}

function installedPhpFormulae()
{
return collect(
explode(PHP_EOL, $this->cli->runAsUser('brew list --formula | grep php'))
);
}

/**
* Get the aliased formula version from Homebrew
*/
function determineAliasedVersion($formula)
{
$details = json_decode($this->cli->runAsUser("brew info $formula --json"));
return $details[0]->aliases[0] ?: 'ERROR - NO BREW ALIAS FOUND';

if (!empty($details[0]->aliases[0])) {
return $details[0]->aliases[0];
}

return 'ERROR - NO BREW ALIAS FOUND';
}

/**
Expand Down Expand Up @@ -135,6 +158,9 @@ function installOrFail($formula, $options = [], $taps = [])
}

output('<info>['.$formula.'] is not installed, installing it now via Brew...</info> 🍻');
if ($formula !== 'php' && starts_with($formula, 'php') && preg_replace('/[^\d]/', '', $formula) < '73') {
warning('Note: older PHP versions may take 10+ minutes to compile from source. Please wait ...');
}

$this->cli->runAsUser(trim('brew install '.$formula.' '.implode(' ', $options)), function ($exitCode, $errorOutput) use ($formula) {
output($errorOutput);
Expand Down Expand Up @@ -213,16 +239,16 @@ function hasLinkedPhp()
function getParsedLinkedPhp()
{
if (! $this->hasLinkedPhp()) {
throw new DomainException("Homebrew PHP appears not to be linked.");
throw new DomainException("Homebrew PHP appears not to be linked. Please run [valet use [email protected]]");
}

$resolvedPath = $this->files->readLink(BREW_PREFIX.'/bin/php');

/**
* Typical homebrew path resolutions are like:
* "../Cellar/php@7.2/7.2.13/bin/php"
* "../Cellar/php@7.4/7.4.13/bin/php"
* or older styles:
* "../Cellar/php/7.2.9_2/bin/php
* "../Cellar/php/7.4.9_2/bin/php
* "../Cellar/php55/bin/php
*/
preg_match('~\w{3,}/(php)(@?\d\.?\d)?/(\d\.\d)?([_\d\.]*)?/?\w{3,}~', $resolvedPath, $matches);
Expand All @@ -231,12 +257,11 @@ function getParsedLinkedPhp()
}

/**
* Gets the currently linked formula
* E.g if under php, will be php, if under [email protected] will be that
* Different to ->linkedPhp() in that this will just get the linked directory name (whether that is php, php55 or
* [email protected])
* Gets the currently linked formula by identifying the symlink in the hombrew bin directory.
* Different to ->linkedPhp() in that this will just get the linked directory name,
* whether that is php, php74 or [email protected]
*
* @return mixed
* @return string
*/
function getLinkedPhpFormula()
{
Expand Down
1 change: 1 addition & 0 deletions cli/Valet/Diagnose.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class Diagnose
'brew services list',
'brew list --formula --versions | grep -E "(php|nginx|dnsmasq|mariadb|mysql|mailhog|openssl)(@\d\..*)?\s"',
'brew outdated',
'brew tap',
'php -v',
'which -a php',
'php --ini',
Expand Down
67 changes: 46 additions & 21 deletions cli/Valet/PhpFpm.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ class PhpFpm
var $brew, $cli, $files;

var $taps = [
'homebrew/homebrew-core'
'homebrew/homebrew-core',
'shivammathur/php',
];

/**
Expand Down Expand Up @@ -142,11 +143,8 @@ function fpmConfigPath()
{
$version = $this->brew->linkedPhp();

$versionNormalized = preg_replace(
'/php@?(\d)\.?(\d)/',
'$1.$2',
$version === 'php' ? Brew::LATEST_PHP_VERSION : $version
);
$versionNormalized = $this->normalizePhpVersion($version === 'php' ? Brew::LATEST_PHP_VERSION : $version);
$versionNormalized = preg_replace('~[^\d\.]~', '', $versionNormalized);

return $versionNormalized === '5.6'
? BREW_PREFIX.'/etc/php/5.6/php-fpm.conf'
Expand All @@ -171,14 +169,26 @@ function stopRunning()
* Use a specific version of php
*
* @param $version
* @param $force
* @return string
*/
function useVersion($version)
function useVersion($version, $force = false)
{
$version = $this->validateRequestedVersion($version);

// Install the relevant formula if not already installed
$this->brew->ensureInstalled($version);
try {
if ($this->brew->linkedPhp() === $version && !$force) {
output(sprintf('<info>Valet is already using version: <comment>%s</comment>.</info> To re-link and re-configure use the --force parameter.' . PHP_EOL,
$version));
exit();
}
} catch (DomainException $e)
{ /* ignore thrown exception when no linked php is found */ }

if (!$this->brew->installed($version)) {
// Install the relevant formula if not already installed
$this->brew->ensureInstalled($version, [], $this->taps);
}

// Unlink the current php if there is one
if ($this->brew->hasLinkedPhp()) {
Expand All @@ -190,11 +200,23 @@ function useVersion($version)
info(sprintf('Linking new version: %s', $version));
$this->brew->link($version, true);

$this->stopRunning();

// ensure configuration is correct and start the linked version
$this->install();

return $version === 'php' ? $this->brew->determineAliasedVersion($version) : $version;
}


/**
* If passed php7.4 or php74 formats, normalize to [email protected] format.
*/
function normalizePhpVersion($version)
{
return preg_replace('/(php)([0-9+])(?:.)?([0-9+])/i', '$1@$2.$3', $version);
}

/**
* Validate the requested version to be sure we can support it.
*
Expand All @@ -203,18 +225,7 @@ function useVersion($version)
*/
function validateRequestedVersion($version)
{
// If passed php7.2 or php72 formats, normalize to [email protected] format:
$version = preg_replace('/(php)([0-9+])(?:.)?([0-9+])/i', '$1@$2.$3', $version);

if ($version === 'php') {
if (strpos($this->brew->determineAliasedVersion($version), '@')) {
return $version;
}

if ($this->brew->hasInstalledPhp()) {
throw new DomainException('Brew is already using PHP '.PHP_VERSION.' as \'php\' in Homebrew. To use another version, please specify. eg: [email protected]');
}
}
$version = $this->normalizePhpVersion($version);

if (!$this->brew->supportedPhpVersions()->contains($version)) {
throw new DomainException(
Expand All @@ -225,6 +236,20 @@ function validateRequestedVersion($version)
);
}

if (strpos($aliasedVersion = $this->brew->determineAliasedVersion($version), '@')) {
return $aliasedVersion;
}

if ($version === 'php') {
if (strpos($aliasedVersion = $this->brew->determineAliasedVersion($version), '@')) {
return $aliasedVersion;
}

if ($this->brew->hasInstalledPhp()) {
throw new DomainException('Brew is already using PHP '.PHP_VERSION.' as \'php\' in Homebrew. To use another version, please specify. eg: [email protected]');
}
}

return $version;
}
}
20 changes: 20 additions & 0 deletions cli/includes/helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,26 @@ function ends_with($haystack, $needles) {
}
}

if (! function_exists('starts_with')) {
/**
* Determine if a given string starts with a given substring.
*
* @param string $haystack
* @param string|string[] $needles
* @return bool
*/
function starts_with($haystack, $needles)
{
foreach ((array) $needles as $needle) {
if ((string) $needle !== '' && strncmp($haystack, $needle, strlen($needle)) === 0) {
return true;
}
}

return false;
}
}

/**
* Get the user
*/
Expand Down
9 changes: 6 additions & 3 deletions cli/valet.php
Original file line number Diff line number Diff line change
Expand Up @@ -462,11 +462,14 @@
/**
* Allow the user to change the version of php valet uses
*/
$app->command('use phpVersion', function ($phpVersion) {
$app->command('use [phpVersion] [--force]', function ($phpVersion, $force) {
if (!$phpVersion) {
return info('Valet is using ' . Brew::linkedPhp());
}

PhpFpm::validateRequestedVersion($phpVersion);

PhpFpm::stopRunning();
$newVersion = PhpFpm::useVersion($phpVersion);
$newVersion = PhpFpm::useVersion($phpVersion, $force);

Nginx::restart();
info(sprintf('Valet is now using %s.', $newVersion) . PHP_EOL);
Expand Down
Loading

0 comments on commit 04d42b3

Please sign in to comment.