From 2c01c9dd05db405dd756d3f841ffab73d738ef5a Mon Sep 17 00:00:00 2001 From: Richard George Date: Mon, 24 Feb 2014 11:28:08 +0000 Subject: [PATCH] Avoid "Package foo/* listed for update is not installed" error Previously 'compose update foo/*' gave an error "Package foo/* listed for update is not installed. Ignoring" even if some foo/* packages were present; however the packages *would* then be updated as requested. This removes the false error iff foo/SOMEPACKAGE is required. --- src/Composer/Installer.php | 41 ++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index e1dbd496f..358d35d94 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -105,6 +105,11 @@ class Installer protected $verbose = false; protected $update = false; protected $runScripts = true; + /** + * Array of package names/globs flagged for update + * + * @var array|null + */ protected $updateWhitelist = null; protected $whitelistDependencies = false; @@ -785,9 +790,8 @@ class Installer } foreach ($this->updateWhitelist as $whiteListedPattern => $void) { - $cleanedWhiteListedPattern = str_replace('\\*', '.*', preg_quote($whiteListedPattern)); - - if (preg_match("{^".$cleanedWhiteListedPattern."$}i", $package->getName())) { + $patternRegexp = $this->packageNameToRegexp($whiteListedPattern); + if (preg_match($patternRegexp, $package->getName())) { return true; } } @@ -795,6 +799,19 @@ class Installer return false; } + /** + * Build a regexp from a package name, expanding * globs as required + * + * @param $whiteListedPattern + * @return string + */ + private function packageNameToRegexp($whiteListedPattern) + { + $cleanedWhiteListedPattern = str_replace('\\*', '.*', preg_quote($whiteListedPattern)); + $patternRegexp = "{^" . $cleanedWhiteListedPattern . "$}i"; + return $patternRegexp; + } + private function extractPlatformRequirements($links) { $platformReqs = array(); @@ -844,11 +861,27 @@ class Installer $seen = array(); + $rootRequiredPackageNames = array_keys($rootRequires); + foreach ($this->updateWhitelist as $packageName => $void) { $packageQueue = new \SplQueue; $depPackages = $pool->whatProvides($packageName); - if (count($depPackages) == 0 && !in_array($packageName, $requiredPackageNames) && !in_array($packageName, array('nothing', 'lock'))) { + + $nameMatchesRequiredPackage = in_array($packageName, $requiredPackageNames); + + if (!$nameMatchesRequiredPackage) { + //maybe the name is a glob or similar that won't match directly + $whitelistPatternRegexp = $this->packageNameToRegexp($packageName); + foreach ($rootRequiredPackageNames as $rootRequiredPackageName) { + if (preg_match($whitelistPatternRegexp, $rootRequiredPackageName)) { + $nameMatchesRequiredPackage = true; + break; + } + } + } + + if (count($depPackages) == 0 && !$nameMatchesRequiredPackage && !in_array($packageName, array('nothing', 'lock'))) { $this->io->write('Package "' . $packageName . '" listed for update is not installed. Ignoring.'); }