diff --git a/src/Composer/Config.php b/src/Composer/Config.php index ead9c67a8..2d823cea3 100644 --- a/src/Composer/Config.php +++ b/src/Composer/Config.php @@ -21,6 +21,10 @@ class Config { const RELATIVE_PATHS = 1; + const INSTALL_PREFERENCE_AUTO = 'auto'; + const INSTALL_PREFERENCE_DIST = 'dist'; + const INSTALL_PREFERENCE_SOURCE = 'source'; + public static $defaultConfig = array( 'process-timeout' => 300, 'use-include-path' => false, diff --git a/src/Composer/Downloader/DownloadManager.php b/src/Composer/Downloader/DownloadManager.php index 675b7a051..857a404dc 100644 --- a/src/Composer/Downloader/DownloadManager.php +++ b/src/Composer/Downloader/DownloadManager.php @@ -12,6 +12,7 @@ namespace Composer\Downloader; +use Composer\Config; use Composer\Package\PackageInterface; use Composer\IO\IOInterface; use Composer\Util\Filesystem; @@ -198,17 +199,7 @@ class DownloadManager throw new \InvalidArgumentException('Package '.$package.' must have a source or dist specified'); } - if (!$this->preferDist && !$preferSource) { - foreach ($this->packagePreferences as $pattern => $preference) { - $pattern = '{^'.str_replace('*', '.*', $pattern).'$}i'; - if (preg_match($pattern, $package->getName())) { - if ('dist' === $preference || (!$package->isDev() && 'auto' === $preference)) { - $sources = array_reverse($sources); - } - break; - } - } - } elseif ((!$package->isDev() || $this->preferDist) && !$preferSource) { + if (Config::INSTALL_PREFERENCE_DIST === $this->resolvePackageInstallPreference($package, $preferSource)) { $sources = array_reverse($sources); } @@ -296,4 +287,25 @@ class DownloadManager $downloader->remove($package, $targetDir); } } + + protected function resolvePackageInstallPreference(PackageInterface $package, $preferSource = false) + { + if ($this->preferSource || $preferSource) { + return Config::INSTALL_PREFERENCE_SOURCE; + } + if ($this->preferDist) { + return Config::INSTALL_PREFERENCE_DIST; + } + foreach ($this->packagePreferences as $pattern => $preference) { + $pattern = '{^'.str_replace('*', '.*', $pattern).'$}i'; + if (preg_match($pattern, $package->getName())) { + if (Config::INSTALL_PREFERENCE_DIST === $preference || (!$package->isDev() && Config::INSTALL_PREFERENCE_AUTO === $preference)) { + return Config::INSTALL_PREFERENCE_DIST; + } + return Config::INSTALL_PREFERENCE_SOURCE; + } + } + + return $package->isDev() ? Config::INSTALL_PREFERENCE_SOURCE : Config::INSTALL_PREFERENCE_DIST; + } } diff --git a/tests/Composer/Test/ConfigTest.php b/tests/Composer/Test/ConfigTest.php index e50af5e87..fb7a5ef22 100644 --- a/tests/Composer/Test/ConfigTest.php +++ b/tests/Composer/Test/ConfigTest.php @@ -112,6 +112,26 @@ class ConfigTest extends \PHPUnit_Framework_TestCase return $data; } + public function testPreferredInstallAsString() + { + $config = new Config(false); + $config->merge(array('config' => array('preferred-install' => 'source'))); + + $this->assertEquals(array('*' => 'source'), $config->get('preferred-install')); + } + + public function testMergePreferredInstall() + { + $config = new Config(false); + $config->merge(array('config' => array('preferred-install' => 'dist'))); + $config->merge(array('config' => array('preferred-install' => array('foo/*' => 'source')))); + + // This assertion needs to make sure full wildcard preferences are placed last + // Handled by composer because we convert string preferences for BC, all other + // care for ordering and collision prevention is up to the user + $this->assertEquals(array('foo/*' => 'source', '*' => 'dist'), $config->get('preferred-install')); + } + public function testMergeGithubOauth() { $config = new Config(false);