From 9c27e386542ed53d769373189227eba0189a54f0 Mon Sep 17 00:00:00 2001 From: Jordan Alliot Date: Wed, 18 Jan 2012 18:22:02 +0100 Subject: [PATCH 01/39] Moved proxy handling to a new class so that it can be reused in other parts of Composer --- src/Composer/Command/SelfUpdateCommand.php | 7 ++- src/Composer/Downloader/FileDownloader.php | 21 ++------ src/Composer/Json/JsonFile.php | 8 +-- src/Composer/Repository/PearRepository.php | 7 ++- src/Composer/Util/StreamContextFactory.php | 57 ++++++++++++++++++++++ 5 files changed, 74 insertions(+), 26 deletions(-) create mode 100644 src/Composer/Util/StreamContextFactory.php diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index 50ad96c6d..febc78295 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -13,6 +13,7 @@ namespace Composer\Command; use Composer\Composer; +use Composer\Util\StreamContextFactory; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -39,7 +40,9 @@ EOT protected function execute(InputInterface $input, OutputInterface $output) { - $latest = trim(file_get_contents('http://getcomposer.org/version')); + $ctx = StreamContextFactory::getContext(); + + $latest = trim(file_get_contents('http://getcomposer.org/version'), false, $ctx); if (Composer::VERSION !== $latest) { $output->writeln(sprintf("Updating to version %s.", $latest)); @@ -47,7 +50,7 @@ EOT $remoteFilename = 'http://getcomposer.org/composer.phar'; $localFilename = $_SERVER['argv'][0]; - file_put_contents($localFilename, file_get_contents($remoteFilename)); + copy($remoteFilename, $localFilename, $ctx); } else { $output->writeln("You are using the latest composer version."); } diff --git a/src/Composer/Downloader/FileDownloader.php b/src/Composer/Downloader/FileDownloader.php index f74ef89dd..10e63806b 100644 --- a/src/Composer/Downloader/FileDownloader.php +++ b/src/Composer/Downloader/FileDownloader.php @@ -13,6 +13,7 @@ namespace Composer\Downloader; use Composer\IO\IOInterface; use Composer\Package\PackageInterface; +use Composer\Util\StreamContextFactory; /** * Base downloader for file packages @@ -77,30 +78,14 @@ abstract class FileDownloader implements DownloaderInterface } } - // Handle system proxy - $params = array('http' => array()); - - if (isset($_SERVER['HTTP_PROXY'])) { - // http(s):// is not supported in proxy - $proxy = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $_SERVER['HTTP_PROXY']); - - if (0 === strpos($proxy, 'ssl:') && !extension_loaded('openssl')) { - throw new \RuntimeException('You must enable the openssl extension to use a proxy over https'); - } - - $params['http'] = array( - 'proxy' => $proxy, - 'request_fulluri' => true, - ); - } + $ctx = StreamContextFactory::getContext(); if ($this->io->hasAuthorization($package->getSourceUrl())) { $auth = $this->io->getAuthorization($package->getSourceUrl()); $authStr = base64_encode($auth['username'] . ':' . $auth['password']); - $params['http'] = array_merge($params['http'], array('header' => "Authorization: Basic $authStr\r\n")); + stream_context_set_option($ctx, 'http', 'header', "Authorization: Basic $authStr\r\n"); } - $ctx = stream_context_create($params); stream_context_set_params($ctx, array("notification" => array($this, 'callbackGet'))); $this->io->overwrite(" Downloading: connection...", false); diff --git a/src/Composer/Json/JsonFile.php b/src/Composer/Json/JsonFile.php index fd43c9148..00baf5f40 100644 --- a/src/Composer/Json/JsonFile.php +++ b/src/Composer/Json/JsonFile.php @@ -14,6 +14,7 @@ namespace Composer\Json; use Composer\Repository\RepositoryManager; use Composer\Composer; +use Composer\Util\StreamContextFactory; /** * Reads/writes json files. @@ -59,11 +60,10 @@ class JsonFile */ public function read() { - $context = stream_context_create(array( - 'http' => array('header' => 'User-Agent: Composer/'.Composer::VERSION."\r\n") - )); + $ctx = StreamContextFactory::getContext(); + stream_context_set_option($ctx, 'http', 'header', 'User-Agent: Composer/'.Composer::VERSION."\r\n"); - $json = file_get_contents($this->path, false, $context); + $json = file_get_contents($this->path, false, $ctx); if (!$json) { throw new \RuntimeException('Could not read '.$this->path.', you are probably offline'); } diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index 0e00a39c7..76267ff3c 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -13,6 +13,7 @@ namespace Composer\Repository; use Composer\Package\Loader\ArrayLoader; +use Composer\Util\StreamContextFactory; /** * @author Benjamin Eberlei @@ -87,7 +88,8 @@ class PearRepository extends ArrayRepository ); try { - $deps = file_get_contents($releaseLink . "/deps.".$pearVersion.".txt"); + $ctx = StreamContextFactory::getContext(); + $deps = file_get_contents($releaseLink.'/deps.'.$pearVersion.'.txt', false, $ctx); } catch (\ErrorException $e) { if (strpos($e->getMessage(), '404')) { continue; @@ -132,7 +134,8 @@ class PearRepository extends ArrayRepository */ private function requestXml($url) { - $content = file_get_contents($url); + $ctx = StreamContextFactory::getContext(); + $content = file_get_contents($url, false, $ctx); if (!$content) { throw new \UnexpectedValueException('The PEAR channel at '.$url.' did not respond.'); } diff --git a/src/Composer/Util/StreamContextFactory.php b/src/Composer/Util/StreamContextFactory.php new file mode 100644 index 000000000..d32236a83 --- /dev/null +++ b/src/Composer/Util/StreamContextFactory.php @@ -0,0 +1,57 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Util; + +/** + * Allows the creation of a basic context supporting http proxy + * + * @author Jordan Alliot + */ +final class StreamContextFactory +{ + private static $context; + + /** + * Creates a context supporting HTTP proxies + * + * @return resource Default context + * @throws \RuntimeException if https proxy required and OpenSSL uninstalled + */ + public static function getContext() + { + if (null !== self::$context) { + return self::$context; + } + + // Handle system proxy + $params = array('http' => array()); + + if (isset($_SERVER['HTTP_PROXY']) || isset($_SERVER['http_proxy'])) { + // Some systems seem to rely on a lowercased version instead... + $proxy = isset($_SERVER['HTTP_PROXY']) ? $_SERVER['HTTP_PROXY'] : $_SERVER['http_proxy']; + + // http(s):// is not supported in proxy + $proxy = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $proxy); + + if (0 === strpos($proxy, 'ssl:') && !extension_loaded('openssl')) { + throw new \RuntimeException('You must enable the openssl extension to use a proxy over https'); + } + + $params['http'] = array( + 'proxy' => $proxy, + 'request_fulluri' => true, + ); + } + + return self::$context = stream_context_create($params); + } +} \ No newline at end of file From 054faef5eb60fba87d21b18d586be89a787b5a17 Mon Sep 17 00:00:00 2001 From: Jordan Alliot Date: Wed, 18 Jan 2012 19:15:13 +0100 Subject: [PATCH 02/39] New context at each call and possibility to add more options and params to the context --- src/Composer/Downloader/FileDownloader.php | 7 +++---- src/Composer/Json/JsonFile.php | 6 ++++-- src/Composer/Util/StreamContextFactory.php | 19 ++++++++----------- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/Composer/Downloader/FileDownloader.php b/src/Composer/Downloader/FileDownloader.php index 10e63806b..189e76f59 100644 --- a/src/Composer/Downloader/FileDownloader.php +++ b/src/Composer/Downloader/FileDownloader.php @@ -78,15 +78,14 @@ abstract class FileDownloader implements DownloaderInterface } } - $ctx = StreamContextFactory::getContext(); - + $options = array(); if ($this->io->hasAuthorization($package->getSourceUrl())) { $auth = $this->io->getAuthorization($package->getSourceUrl()); $authStr = base64_encode($auth['username'] . ':' . $auth['password']); - stream_context_set_option($ctx, 'http', 'header', "Authorization: Basic $authStr\r\n"); + $options['http']['header'] = "Authorization: Basic $authStr\r\n"; } - stream_context_set_params($ctx, array("notification" => array($this, 'callbackGet'))); + $ctx = StreamContextFactory::getContext($options, array('notification' => array($this, 'callbackGet'))); $this->io->overwrite(" Downloading: connection...", false); @copy($url, $fileName, $ctx); diff --git a/src/Composer/Json/JsonFile.php b/src/Composer/Json/JsonFile.php index 00baf5f40..0c585216d 100644 --- a/src/Composer/Json/JsonFile.php +++ b/src/Composer/Json/JsonFile.php @@ -60,8 +60,10 @@ class JsonFile */ public function read() { - $ctx = StreamContextFactory::getContext(); - stream_context_set_option($ctx, 'http', 'header', 'User-Agent: Composer/'.Composer::VERSION."\r\n"); + $ctx = StreamContextFactory::getContext(array( + 'http' => array( + 'header' => 'User-Agent: Composer/'.Composer::VERSION."\r\n" + ))); $json = file_get_contents($this->path, false, $ctx); if (!$json) { diff --git a/src/Composer/Util/StreamContextFactory.php b/src/Composer/Util/StreamContextFactory.php index d32236a83..8b452482d 100644 --- a/src/Composer/Util/StreamContextFactory.php +++ b/src/Composer/Util/StreamContextFactory.php @@ -1,4 +1,5 @@ array()); + $options = array_merge(array('http' => array()), $options); + // Handle system proxy if (isset($_SERVER['HTTP_PROXY']) || isset($_SERVER['http_proxy'])) { // Some systems seem to rely on a lowercased version instead... $proxy = isset($_SERVER['HTTP_PROXY']) ? $_SERVER['HTTP_PROXY'] : $_SERVER['http_proxy']; @@ -46,12 +43,12 @@ final class StreamContextFactory throw new \RuntimeException('You must enable the openssl extension to use a proxy over https'); } - $params['http'] = array( + $options['http'] = array( 'proxy' => $proxy, 'request_fulluri' => true, ); } - return self::$context = stream_context_create($params); + return stream_context_create($options, $params); } } \ No newline at end of file From 468eb0ed8d404be2c41cb0541133c06f85f30d2b Mon Sep 17 00:00:00 2001 From: Jordan Alliot Date: Fri, 20 Jan 2012 04:35:20 -0800 Subject: [PATCH 03/39] Merge default options after buildind proxy one --- src/Composer/Util/StreamContextFactory.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Composer/Util/StreamContextFactory.php b/src/Composer/Util/StreamContextFactory.php index 8b452482d..8ca3ccd69 100644 --- a/src/Composer/Util/StreamContextFactory.php +++ b/src/Composer/Util/StreamContextFactory.php @@ -22,14 +22,14 @@ final class StreamContextFactory /** * Creates a context supporting HTTP proxies * - * @param array $options Options to merge with the default - * @param array $params Parameters to specify on the context + * @param array $defaultOptions Options to merge with the default + * @param array $defaultParams Parameters to specify on the context * @return resource Default context * @throws \RuntimeException if https proxy required and OpenSSL uninstalled */ - static public function getContext(array $options = array(), array $params = array()) + static public function getContext(array $defaultOptions = array(), array $defaultParams = array()) { - $options = array_merge(array('http' => array()), $options); + $options = array('http' => array()); // Handle system proxy if (isset($_SERVER['HTTP_PROXY']) || isset($_SERVER['http_proxy'])) { @@ -48,7 +48,9 @@ final class StreamContextFactory 'request_fulluri' => true, ); } + + $options = array_merge($options, $defaultOptions); - return stream_context_create($options, $params); + return stream_context_create($options, $defaultParams); } -} \ No newline at end of file +} From b4d87af9592b65ecfd2336cfe04655dad84a09d8 Mon Sep 17 00:00:00 2001 From: Jordan Alliot Date: Sat, 21 Jan 2012 16:29:17 +0100 Subject: [PATCH 04/39] Changed array_merge to array_merge_recursive --- src/Composer/Util/StreamContextFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Util/StreamContextFactory.php b/src/Composer/Util/StreamContextFactory.php index 8ca3ccd69..4ea31da4d 100644 --- a/src/Composer/Util/StreamContextFactory.php +++ b/src/Composer/Util/StreamContextFactory.php @@ -49,7 +49,7 @@ final class StreamContextFactory ); } - $options = array_merge($options, $defaultOptions); + $options = array_merge_recursive($options, $defaultOptions); return stream_context_create($options, $defaultParams); } From 93baa38d5c1050d6086787870dc4167258790d94 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 8 Feb 2012 10:24:36 +0100 Subject: [PATCH 05/39] Allow show command to work without a composer.json --- src/Composer/Command/Command.php | 4 +-- src/Composer/Command/ShowCommand.php | 53 +++++++++++++++------------- src/Composer/Console/Application.php | 10 ++++-- 3 files changed, 37 insertions(+), 30 deletions(-) diff --git a/src/Composer/Command/Command.php b/src/Composer/Command/Command.php index c5f83998d..8744a0da1 100644 --- a/src/Composer/Command/Command.php +++ b/src/Composer/Command/Command.php @@ -25,8 +25,8 @@ abstract class Command extends BaseCommand /** * @return \Composer\Composer */ - protected function getComposer() + protected function getComposer($required = true) { - return $this->getApplication()->getComposer(); + return $this->getApplication()->getComposer($required); } } diff --git a/src/Composer/Command/ShowCommand.php b/src/Composer/Command/ShowCommand.php index 9de3ed2de..9a2b1b6a3 100644 --- a/src/Composer/Command/ShowCommand.php +++ b/src/Composer/Command/ShowCommand.php @@ -17,6 +17,9 @@ use Composer\Package\PackageInterface; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Output\OutputInterface; +use Composer\Repository\CompositeRepository; +use Composer\Repository\PlatformRepository; +use Composer\Repository\ComposerRepository; /** * @author Robert Schönthal @@ -44,13 +47,22 @@ EOT protected function execute(InputInterface $input, OutputInterface $output) { - $composer = $this->getComposer(); - $package = $this->getPackage($input, $output, $composer); + if ($composer = $this->getComposer(false)) { + $localRepo = $composer->getRepositoryManager()->getLocalRepository(); + $installedRepo = new CompositeRepository(array($localRepo, new PlatformRepository())); + $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories())); + } else { + $output->writeln('No composer.json found in the current directory, showing packages from packagist.org'); + $installedRepo = new PlatformRepository; + $repos = new CompositeRepository(array($installedRepo, new ComposerRepository(array('url' => 'http://packagist.org')))); + } + + $package = $this->getPackage($input, $output, $installedRepo, $repos); if (!$package) { throw new \InvalidArgumentException('no package found'); } - $this->printMeta($input, $output, $package, $composer); + $this->printMeta($input, $output, $package, $installedRepo, $repos); $this->printLinks($input, $output, $package, 'requires'); $this->printLinks($input, $output, $package, 'recommends'); $this->printLinks($input, $output, $package, 'replaces'); @@ -63,16 +75,15 @@ EOT * @return PackageInterface * @throws \InvalidArgumentException */ - protected function getPackage(InputInterface $input, OutputInterface $output, Composer $composer) + protected function getPackage(InputInterface $input, OutputInterface $output, $installedRepo, $repos) { // we have a name and a version so we can use ::findPackage if ($input->getArgument('version')) { - return $composer->getRepositoryManager()->findPackage($input->getArgument('package'), $input->getArgument('version')); + return $repos->findPackage($input->getArgument('package'), $input->getArgument('version')); } // check if we have a local installation so we can grab the right package/version - $localRepo = $composer->getRepositoryManager()->getLocalRepository(); - foreach ($localRepo->getPackages() as $package) { + foreach ($installedRepo->getPackages() as $package) { if ($package->getName() === $input->getArgument('package')) { return $package; } @@ -80,15 +91,9 @@ EOT // we only have a name, so search for the highest version of the given package $highestVersion = null; - $repos = array_merge( - array($composer->getRepositoryManager()->getLocalRepository()), - $composer->getRepositoryManager()->getRepositories() - ); - foreach ($repos as $repository) { - foreach ($repository->findPackagesByName($input->getArgument('package')) as $package) { - if (null === $highestVersion || version_compare($package->getVersion(), $highestVersion->getVersion(), '>=')) { - $highestVersion = $package; - } + foreach ($repos->findPackagesByName($input->getArgument('package')) as $package) { + if (null === $highestVersion || version_compare($package->getVersion(), $highestVersion->getVersion(), '>=')) { + $highestVersion = $package; } } @@ -98,15 +103,15 @@ EOT /** * prints package meta data */ - protected function printMeta(InputInterface $input, OutputInterface $output, PackageInterface $package, Composer $composer) + protected function printMeta(InputInterface $input, OutputInterface $output, PackageInterface $package, $installedRepo, $repos) { $output->writeln('name : ' . $package->getPrettyName()); - $this->printVersions($input, $output, $package, $composer); + $this->printVersions($input, $output, $package, $installedRepo, $repos); $output->writeln('type : ' . $package->getType()); $output->writeln('names : ' . join(', ', $package->getNames())); $output->writeln('source : ' . sprintf('[%s] %s %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference())); $output->writeln('dist : ' . sprintf('[%s] %s %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference())); - $output->writeln('licence : ' . join(', ', $package->getLicense())); + $output->writeln('license : ' . join(', ', $package->getLicense())); if ($package->getAutoload()) { $output->writeln("\nautoload"); @@ -123,7 +128,7 @@ EOT /** * prints all available versions of this package and highlights the installed one if any */ - protected function printVersions(InputInterface $input, OutputInterface $output, PackageInterface $package, Composer $composer) + protected function printVersions(InputInterface $input, OutputInterface $output, PackageInterface $package, $installedRepo, $repos) { if ($input->getArgument('version')) { $output->writeln('version : ' . $package->getPrettyVersion()); @@ -132,16 +137,14 @@ EOT $versions = array(); - foreach ($composer->getRepositoryManager()->getRepositories() as $repository) { - foreach ($repository->findPackagesByName($package->getName()) as $version) { - $versions[] = $version->getPrettyVersion(); - } + foreach ($repos->findPackagesByName($package->getName()) as $version) { + $versions[] = $version->getPrettyVersion(); } $versions = join(', ', $versions); // highlight installed version - if ($composer->getRepositoryManager()->getLocalRepository()->hasPackage($package)) { + if ($installedRepo->hasPackage($package)) { $versions = str_replace($package->getPrettyVersion(), '* ' . $package->getPrettyVersion() . '', $versions); } diff --git a/src/Composer/Console/Application.php b/src/Composer/Console/Application.php index 745d5510d..fef0ed4e3 100644 --- a/src/Composer/Console/Application.php +++ b/src/Composer/Console/Application.php @@ -71,14 +71,18 @@ class Application extends BaseApplication /** * @return Composer */ - public function getComposer() + public function getComposer($required = true) { if (null === $this->composer) { try { $this->composer = Factory::create($this->io); } catch (\InvalidArgumentException $e) { - $this->io->write($e->getMessage()); - exit(1); + if ($required) { + $this->io->write($e->getMessage()); + exit(1); + } + + return; } } From 247d19e2f8c644a3caa7fc0ba77f7e37778a9629 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 8 Feb 2012 18:12:46 +0100 Subject: [PATCH 06/39] Add type hints --- src/Composer/Command/ShowCommand.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Composer/Command/ShowCommand.php b/src/Composer/Command/ShowCommand.php index 9a2b1b6a3..a860a83af 100644 --- a/src/Composer/Command/ShowCommand.php +++ b/src/Composer/Command/ShowCommand.php @@ -20,6 +20,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Composer\Repository\CompositeRepository; use Composer\Repository\PlatformRepository; use Composer\Repository\ComposerRepository; +use Composer\Repository\RepositoryInterface; /** * @author Robert Schönthal @@ -75,7 +76,7 @@ EOT * @return PackageInterface * @throws \InvalidArgumentException */ - protected function getPackage(InputInterface $input, OutputInterface $output, $installedRepo, $repos) + protected function getPackage(InputInterface $input, OutputInterface $output, RepositoryInterface $installedRepo, RepositoryInterface $repos) { // we have a name and a version so we can use ::findPackage if ($input->getArgument('version')) { @@ -103,7 +104,7 @@ EOT /** * prints package meta data */ - protected function printMeta(InputInterface $input, OutputInterface $output, PackageInterface $package, $installedRepo, $repos) + protected function printMeta(InputInterface $input, OutputInterface $output, PackageInterface $package, RepositoryInterface $installedRepo, RepositoryInterface $repos) { $output->writeln('name : ' . $package->getPrettyName()); $this->printVersions($input, $output, $package, $installedRepo, $repos); @@ -128,7 +129,7 @@ EOT /** * prints all available versions of this package and highlights the installed one if any */ - protected function printVersions(InputInterface $input, OutputInterface $output, PackageInterface $package, $installedRepo, $repos) + protected function printVersions(InputInterface $input, OutputInterface $output, PackageInterface $package, RepositoryInterface $installedRepo, RepositoryInterface $repos) { if ($input->getArgument('version')) { $output->writeln('version : ' . $package->getPrettyVersion()); From 0e7c0d918f3879213a894420007454121413bd39 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 9 Feb 2012 15:42:47 +0100 Subject: [PATCH 07/39] Add useIncludePath support to ClassLoader --- src/Composer/Autoload/ClassLoader.php | 41 +++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/src/Composer/Autoload/ClassLoader.php b/src/Composer/Autoload/ClassLoader.php index aa4669e34..773561118 100644 --- a/src/Composer/Autoload/ClassLoader.php +++ b/src/Composer/Autoload/ClassLoader.php @@ -26,6 +26,9 @@ namespace Composer\Autoload; * // activate the autoloader * $loader->register(); * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * * In this example, if you try to use a class in the Symfony\Component * namespace or one of its children (Symfony\Component\Console for instance), * the autoloader will first look for the class under the component/ @@ -41,6 +44,7 @@ class ClassLoader { private $prefixes = array(); private $fallbackDirs = array(); + private $useIncludePath = false; public function getPrefixes() { @@ -74,6 +78,27 @@ class ClassLoader } } + /** + * Turns on searching the include for class files. + * + * @param Boolean $useIncludePath + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return Boolean + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + /** * Registers this instance as an autoloader. * @@ -121,7 +146,7 @@ class ClassLoader if (false !== $pos = strrpos($class, '\\')) { // namespaced class name - $classPath = DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)); + $classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)) . DIRECTORY_SEPARATOR; $className = substr($class, $pos + 1); } else { // PEAR-like class name @@ -129,22 +154,26 @@ class ClassLoader $className = $class; } - $classPath .= DIRECTORY_SEPARATOR . str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php'; + $classPath .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php'; foreach ($this->prefixes as $prefix => $dirs) { foreach ($dirs as $dir) { if (0 === strpos($class, $prefix)) { - if (file_exists($dir . $classPath)) { - return $dir . $classPath; + if (file_exists($dir . DIRECTORY_SEPARATOR . $classPath)) { + return $dir . DIRECTORY_SEPARATOR . $classPath; } } } } foreach ($this->fallbackDirs as $dir) { - if (file_exists($dir . $classPath)) { - return $dir . $classPath; + if (file_exists($dir . DIRECTORY_SEPARATOR . $classPath)) { + return $dir . DIRECTORY_SEPARATOR . $classPath; } } + + if ($this->useIncludePath && $file = stream_resolve_include_path($classPath)) { + return $file; + } } } From 6971657ad05a7a4cae04cb90dc81769e23fc8b55 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 9 Feb 2012 16:30:55 +0100 Subject: [PATCH 08/39] Merge debug:packages into the show command (if used without package arg) --- src/Composer/Command/DebugPackagesCommand.php | 90 ------------------- src/Composer/Command/ShowCommand.php | 56 ++++++++---- 2 files changed, 41 insertions(+), 105 deletions(-) delete mode 100644 src/Composer/Command/DebugPackagesCommand.php diff --git a/src/Composer/Command/DebugPackagesCommand.php b/src/Composer/Command/DebugPackagesCommand.php deleted file mode 100644 index e3d196466..000000000 --- a/src/Composer/Command/DebugPackagesCommand.php +++ /dev/null @@ -1,90 +0,0 @@ - - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer\Command; - -use Composer\Autoload\AutoloadGenerator; -use Composer\DependencyResolver; -use Composer\DependencyResolver\Pool; -use Composer\DependencyResolver\Request; -use Composer\DependencyResolver\Operation; -use Composer\Package\LinkConstraint\VersionConstraint; -use Composer\Repository\CompositeRepository; -use Composer\Repository\PlatformRepository; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * @author Jordi Boggiano - */ -class DebugPackagesCommand extends Command -{ - protected function configure() - { - $this - ->setName('debug:packages') - ->setDescription('Lists all existing packages and their version') - ->setDefinition(array( - new InputOption('local', null, InputOption::VALUE_NONE, 'list locally installed packages only'), - new InputOption('platform', null, InputOption::VALUE_NONE, 'list platform packages only'), - )) - ->setHelp(<<php composer.phar debug:packages - -EOT - ) - ; - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - $composer = $this->getComposer(); - - // create local repo, this contains all packages that are installed in the local project - $localRepo = $composer->getRepositoryManager()->getLocalRepository(); - // create installed repo, this contains all local packages + platform packages (php & extensions) - $installedRepo = new CompositeRepository(array($localRepo, new PlatformRepository())); - - if ($input->getOption('local')) { - foreach ($localRepo->getPackages() as $package) { - $output->writeln('local: ' . $package->getPrettyName() . ' ' . $package->getPrettyVersion() . ' (' . $package->getVersion() . ')'); - } - - return; - } - - if ($input->getOption('platform')) { - $repos = array_diff($installedRepo->getPackages(), $localRepo->getPackages()); - foreach ($repos as $package) { - $output->writeln('plattform: ' . $package->getPrettyName() . ' ' . $package->getPrettyVersion() . ' (' . $package->getVersion() . ')'); - } - - return; - } - - foreach ($installedRepo->getPackages() as $package) { - if ($localRepo->hasPackage($package)) { - $output->writeln('installed: ' . $package->getPrettyName() . ' ' . $package->getPrettyVersion() . ' (' . $package->getVersion() . ')'); - } else { - $output->writeln('platform: ' . $package->getPrettyName() . ' ' . $package->getPrettyVersion() . ' (' . $package->getName() . ' ' . $package->getVersion() . ')'); - } - } - - foreach ($composer->getRepositoryManager()->getRepositories() as $repository) { - foreach ($repository->getPackages() as $package) { - $output->writeln('available: ' . $package->getPrettyName() . ' ' . $package->getPrettyVersion() . ' (' . $package->getName() . ' ' . $package->getVersion() . ')'); - } - } - } - -} \ No newline at end of file diff --git a/src/Composer/Command/ShowCommand.php b/src/Composer/Command/ShowCommand.php index a860a83af..4450966b3 100644 --- a/src/Composer/Command/ShowCommand.php +++ b/src/Composer/Command/ShowCommand.php @@ -16,6 +16,7 @@ use Composer\Composer; use Composer\Package\PackageInterface; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Composer\Repository\CompositeRepository; use Composer\Repository\PlatformRepository; @@ -32,14 +33,16 @@ class ShowCommand extends Command { $this ->setName('show') - ->setDescription('Show package details') + ->setDescription('Show information about packages') ->setDefinition(array( - new InputArgument('package', InputArgument::REQUIRED, 'the package to inspect'), - new InputArgument('version', InputArgument::OPTIONAL, 'the version'), + new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect'), + new InputArgument('version', InputArgument::OPTIONAL, 'Version to inspect'), + new InputOption('installed', null, InputOption::VALUE_NONE, 'List installed packages only'), + new InputOption('platform', null, InputOption::VALUE_NONE, 'List platform packages only'), )) ->setHelp(<<php composer.phar show composer/composer master-dev +The show command displays detailed information about a package, or +lists all packages available. EOT ) @@ -48,25 +51,48 @@ EOT protected function execute(InputInterface $input, OutputInterface $output) { - if ($composer = $this->getComposer(false)) { + // init repos + $platformRepo = new PlatformRepository; + if ($input->getOption('platform')) { + $repos = $installedRepo = $platformRepo; + } elseif ($input->getOption('installed')) { + $composer = $this->getComposer(); + $repos = $installedRepo = $composer->getRepositoryManager()->getLocalRepository(); + } elseif ($composer = $this->getComposer(false)) { $localRepo = $composer->getRepositoryManager()->getLocalRepository(); - $installedRepo = new CompositeRepository(array($localRepo, new PlatformRepository())); + $installedRepo = new CompositeRepository(array($localRepo, $platformRepo)); $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories())); } else { $output->writeln('No composer.json found in the current directory, showing packages from packagist.org'); - $installedRepo = new PlatformRepository; + $installedRepo = $platformRepo; $repos = new CompositeRepository(array($installedRepo, new ComposerRepository(array('url' => 'http://packagist.org')))); } - $package = $this->getPackage($input, $output, $installedRepo, $repos); - if (!$package) { - throw new \InvalidArgumentException('no package found'); + // show single package or single version + if ($input->getArgument('package')) { + $package = $this->getPackage($input, $output, $installedRepo, $repos); + if (!$package) { + throw new \InvalidArgumentException('Package '.$input->getArgument('package').' not found'); + } + + $this->printMeta($input, $output, $package, $installedRepo, $repos); + $this->printLinks($input, $output, $package, 'requires'); + $this->printLinks($input, $output, $package, 'recommends'); + $this->printLinks($input, $output, $package, 'replaces'); + return; } - $this->printMeta($input, $output, $package, $installedRepo, $repos); - $this->printLinks($input, $output, $package, 'requires'); - $this->printLinks($input, $output, $package, 'recommends'); - $this->printLinks($input, $output, $package, 'replaces'); + // list packages + foreach ($repos->getPackages() as $package) { + if ($platformRepo->hasPackage($package)) { + $type = 'platform: '; + } elseif ($installedRepo->hasPackage($package)) { + $type = 'installed: '; + } else { + $type = 'available: '; + } + $output->writeln($type . ' ' . $package->getPrettyName() . ' ' . $package->getPrettyVersion() . ' (' . $package->getVersion() . ')'); + } } /** From 030b81b199dff2a9f6b4c0ca5cf2b747c617fc9e Mon Sep 17 00:00:00 2001 From: Beau Simensen Date: Thu, 9 Feb 2012 08:14:06 -0800 Subject: [PATCH 09/39] DebugPackagesCommand has been removed. --- src/Composer/Console/Application.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Composer/Console/Application.php b/src/Composer/Console/Application.php index fef0ed4e3..6d1d6ba0b 100644 --- a/src/Composer/Console/Application.php +++ b/src/Composer/Console/Application.php @@ -106,7 +106,6 @@ class Application extends BaseApplication $this->add(new Command\DependsCommand()); $this->add(new Command\InstallCommand()); $this->add(new Command\UpdateCommand()); - $this->add(new Command\DebugPackagesCommand()); $this->add(new Command\SearchCommand()); $this->add(new Command\ValidateCommand()); $this->add(new Command\ShowCommand()); From ec352b1e845086e93af58e9430f420b2f2d53847 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 9 Feb 2012 18:18:43 +0100 Subject: [PATCH 10/39] Add support for adding more than one fallback dir --- src/Composer/Autoload/ClassLoader.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Composer/Autoload/ClassLoader.php b/src/Composer/Autoload/ClassLoader.php index 773561118..8d38c9900 100644 --- a/src/Composer/Autoload/ClassLoader.php +++ b/src/Composer/Autoload/ClassLoader.php @@ -65,7 +65,9 @@ class ClassLoader public function add($prefix, $paths) { if (!$prefix) { - $this->fallbackDirs = (array) $paths; + foreach ((array) $paths as $path) { + $this->fallbackDirs[] = $path; + } return; } if (isset($this->prefixes[$prefix])) { From 5da021ffa74d3997e1f9b5431cf3e2d04d0d514a Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 9 Feb 2012 18:45:28 +0100 Subject: [PATCH 11/39] Moved Filesystem to base Util namespace --- src/Composer/Autoload/AutoloadGenerator.php | 2 +- src/Composer/Downloader/DownloadManager.php | 5 +++-- src/Composer/Downloader/FileDownloader.php | 5 +++-- src/Composer/Downloader/VcsDownloader.php | 3 ++- src/Composer/Installer/LibraryInstaller.php | 2 +- src/Composer/{Downloader => }/Util/Filesystem.php | 4 +--- tests/Composer/Test/Autoload/AutoloadGeneratorTest.php | 2 +- tests/Composer/Test/Downloader/Util/FilesystemTest.php | 2 +- tests/Composer/Test/Installer/LibraryInstallerTest.php | 2 +- 9 files changed, 14 insertions(+), 13 deletions(-) rename src/Composer/{Downloader => }/Util/Filesystem.php (98%) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 37b305640..8b60e50f1 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -17,7 +17,7 @@ use Composer\Json\JsonFile; use Composer\Package\Loader\JsonLoader; use Composer\Package\PackageInterface; use Composer\Repository\RepositoryInterface; -use Composer\Downloader\Util\Filesystem; +use Composer\Util\Filesystem; /** * @author Igor Wiedler diff --git a/src/Composer/Downloader/DownloadManager.php b/src/Composer/Downloader/DownloadManager.php index a279e6e23..e466bbb09 100644 --- a/src/Composer/Downloader/DownloadManager.php +++ b/src/Composer/Downloader/DownloadManager.php @@ -14,6 +14,7 @@ namespace Composer\Downloader; use Composer\Package\PackageInterface; use Composer\Downloader\DownloaderInterface; +use Composer\Util\Filesystem; /** * Downloaders manager. @@ -134,9 +135,9 @@ class DownloadManager ); } - $fs = new Util\Filesystem(); + $fs = new Filesystem(); $fs->ensureDirectoryExists($targetDir); - + $downloader = $this->getDownloaderForInstalledPackage($package); $downloader->download($package, $targetDir); } diff --git a/src/Composer/Downloader/FileDownloader.php b/src/Composer/Downloader/FileDownloader.php index e3ccc1773..ae2b199b2 100644 --- a/src/Composer/Downloader/FileDownloader.php +++ b/src/Composer/Downloader/FileDownloader.php @@ -13,6 +13,7 @@ namespace Composer\Downloader; use Composer\IO\IOInterface; use Composer\Package\PackageInterface; +use Composer\Util\Filesystem; /** * Base downloader for file packages @@ -142,7 +143,7 @@ abstract class FileDownloader implements DownloaderInterface */ public function update(PackageInterface $initial, PackageInterface $target, $path) { - $fs = new Util\Filesystem(); + $fs = new Filesystem(); $fs->removeDirectory($path); $this->download($target, $path); } @@ -152,7 +153,7 @@ abstract class FileDownloader implements DownloaderInterface */ public function remove(PackageInterface $package, $path) { - $fs = new Util\Filesystem(); + $fs = new Filesystem(); $fs->removeDirectory($path); } diff --git a/src/Composer/Downloader/VcsDownloader.php b/src/Composer/Downloader/VcsDownloader.php index 8af2ce48e..4bcc79d0c 100644 --- a/src/Composer/Downloader/VcsDownloader.php +++ b/src/Composer/Downloader/VcsDownloader.php @@ -15,6 +15,7 @@ namespace Composer\Downloader; use Composer\Package\PackageInterface; use Composer\Util\ProcessExecutor; use Composer\IO\IOInterface; +use Composer\Util\Filesystem; /** * @author Jordi Boggiano @@ -73,7 +74,7 @@ abstract class VcsDownloader implements DownloaderInterface public function remove(PackageInterface $package, $path) { $this->enforceCleanDirectory($path); - $fs = new Util\Filesystem(); + $fs = new Filesystem(); $fs->removeDirectory($path); } diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index b1bdfa60d..db2fe535b 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -17,7 +17,7 @@ use Composer\Downloader\DownloadManager; use Composer\Repository\WritableRepositoryInterface; use Composer\DependencyResolver\Operation\OperationInterface; use Composer\Package\PackageInterface; -use Composer\Downloader\Util\Filesystem; +use Composer\Util\Filesystem; /** * Package installation manager. diff --git a/src/Composer/Downloader/Util/Filesystem.php b/src/Composer/Util/Filesystem.php similarity index 98% rename from src/Composer/Downloader/Util/Filesystem.php rename to src/Composer/Util/Filesystem.php index 6d044e40e..4f6e324ac 100644 --- a/src/Composer/Downloader/Util/Filesystem.php +++ b/src/Composer/Util/Filesystem.php @@ -10,9 +10,7 @@ * file that was distributed with this source code. */ -namespace Composer\Downloader\Util; - -use Composer\Util\ProcessExecutor; +namespace Composer\Util; /** * @author Jordi Boggiano diff --git a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php index f7eee0d69..a4e8b9449 100644 --- a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php +++ b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php @@ -13,7 +13,7 @@ namespace Composer\Test\Installer; use Composer\Autoload\AutoloadGenerator; -use Composer\Downloader\Util\Filesystem; +use Composer\Util\Filesystem; use Composer\Package\MemoryPackage; class AutoloadGeneratorTest extends \PHPUnit_Framework_TestCase diff --git a/tests/Composer/Test/Downloader/Util/FilesystemTest.php b/tests/Composer/Test/Downloader/Util/FilesystemTest.php index 243dfa7aa..9605a111c 100644 --- a/tests/Composer/Test/Downloader/Util/FilesystemTest.php +++ b/tests/Composer/Test/Downloader/Util/FilesystemTest.php @@ -12,7 +12,7 @@ namespace Composer\Test\Repository; -use Composer\Downloader\Util\Filesystem; +use Composer\Util\Filesystem; use Composer\Test\TestCase; class FilesystemTest extends TestCase diff --git a/tests/Composer/Test/Installer/LibraryInstallerTest.php b/tests/Composer/Test/Installer/LibraryInstallerTest.php index ed655f983..561143db2 100644 --- a/tests/Composer/Test/Installer/LibraryInstallerTest.php +++ b/tests/Composer/Test/Installer/LibraryInstallerTest.php @@ -14,7 +14,7 @@ namespace Composer\Test\Installer; use Composer\Installer\LibraryInstaller; use Composer\DependencyResolver\Operation; -use Composer\Downloader\Util\Filesystem; +use Composer\Util\Filesystem; class LibraryInstallerTest extends \PHPUnit_Framework_TestCase { From 8123de2feae6b40794cee7a2537ea529b791945c Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 9 Feb 2012 19:06:47 +0100 Subject: [PATCH 12/39] Simplified bootstrap --- tests/bootstrap.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 3c891e9d8..02bd0e169 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -16,6 +16,4 @@ if ((!$loader = @include __DIR__.'/../../../.composer/autoload.php') && (!$loade 'php composer.phar install'.PHP_EOL); } -$loader = require __DIR__.'/../vendor/.composer/autoload.php'; $loader->add('Composer\Test', __DIR__); -$loader->register(); From 04f0ecfc0128f2934c31e77d9355e5b10d6a82d7 Mon Sep 17 00:00:00 2001 From: Beau Simensen Date: Thu, 9 Feb 2012 10:21:16 -0800 Subject: [PATCH 13/39] Change permission of bin links if they exist and are already links --- src/Composer/Installer/LibraryInstaller.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index db2fe535b..fe135159d 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -147,6 +147,12 @@ class LibraryInstaller implements InstallerInterface foreach ($package->getBinaries() as $bin) { $link = $this->binDir.'/'.basename($bin); if (file_exists($link)) { + if (is_link($link)) { + // likely leftover from a previous install, make sure + // that the target is still executable in case this + // is a fresh install of the vendor. + chmod($link, 0777); + } $this->io->write('Skipped installation of '.$bin.' for package '.$package->getName().', name conflicts with an existing file'); continue; } From 3cbbe1fd823d2ab29e64c34a505f85bbfabdb92a Mon Sep 17 00:00:00 2001 From: Beau Simensen Date: Thu, 9 Feb 2012 14:18:25 -0800 Subject: [PATCH 14/39] No need for group or world write permissions. --- src/Composer/Installer/LibraryInstaller.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index fe135159d..0873ed63c 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -151,7 +151,7 @@ class LibraryInstaller implements InstallerInterface // likely leftover from a previous install, make sure // that the target is still executable in case this // is a fresh install of the vendor. - chmod($link, 0777); + chmod($link, 0755); } $this->io->write('Skipped installation of '.$bin.' for package '.$package->getName().', name conflicts with an existing file'); continue; @@ -162,14 +162,14 @@ class LibraryInstaller implements InstallerInterface // add unixy support for cygwin and similar environments if ('.bat' !== substr($bin, -4)) { file_put_contents($link, $this->generateUnixyProxyCode($bin, $link)); - chmod($link, 0777); + chmod($link, 0755); $link .= '.bat'; } file_put_contents($link, $this->generateWindowsProxyCode($bin, $link)); } else { symlink($bin, $link); } - chmod($link, 0777); + chmod($link, 0755); } } From d115c265cb5c5b2f7e274ecd870b7d1da1c8b4a4 Mon Sep 17 00:00:00 2001 From: Beau Simensen Date: Fri, 10 Feb 2012 07:36:36 -0800 Subject: [PATCH 15/39] Not sure I have the timing right, but figured this is a good place to start. --- doc/faqs/packagist-update-schedule.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 doc/faqs/packagist-update-schedule.md diff --git a/doc/faqs/packagist-update-schedule.md b/doc/faqs/packagist-update-schedule.md new file mode 100644 index 000000000..af476decc --- /dev/null +++ b/doc/faqs/packagist-update-schedule.md @@ -0,0 +1,24 @@ +# Packagist Update Schedule + +## How often does Packagist crawl newly added packages? + +New packages will be crawled **every five minutes**. + + +## How often does Packagist crawl existing packages? + +Existing packages will be crawled **every hour**. + + +## How often does the Packagist search index update? + +The search index is rebuilt **every hour**. It will index (or reindex) +any package that has been crawled since the last time the search +indexer ran. + + +## Can Packagist be triggered to recrawl a package (on commit or by other means)? + +Not yet. :) Want to help? See +[#81](https://github.com/composer/packagist/issues/81) +and [#67](https://github.com/composer/packagist/issues/67) \ No newline at end of file From 14adc0213e7d60b2e3b26da281a3b4bbe15614db Mon Sep 17 00:00:00 2001 From: Henrique Moody Date: Tue, 17 Jan 2012 14:53:38 -0200 Subject: [PATCH 16/39] Added suport for PEAR2 repositories. --- src/Composer/Repository/PearRepository.php | 239 +++++++++++++++------ 1 file changed, 179 insertions(+), 60 deletions(-) diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index 51c1722b4..496950af5 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -31,7 +31,7 @@ class PearRepository extends ArrayRepository throw new \UnexpectedValueException('Invalid url given for PEAR repository: '.$config['url']); } - $this->url = $config['url']; + $this->url = preg_replace('#^(.+)/+$#U', '$1', $config['url']); } protected function initialize() @@ -51,24 +51,62 @@ class PearRepository extends ArrayRepository $categories = $categoryXML->getElementsByTagName("c"); foreach ($categories as $category) { - $categoryLink = $category->getAttribute("xlink:href"); - $categoryLink = str_replace("info.xml", "packages.xml", $categoryLink); - if ('/' !== substr($categoryLink, 0, 1)) { - $categoryLink = '/' . $categoryLink; + $link = $category->getAttribute("xlink:href"); + try { + $packagesLink = str_replace("info.xml", "packagesinfo.xml", $link); + $this->fetchPear2Repositories($this->url . '/' . $packagesLink); + } catch (\ErrorException $e) { + if (false === strpos($e->getMessage(), '404')) { + throw $e; + } + $categoryLink = str_replace("info.xml", "packages.xml", $link); + $this->fetchPearRepositories($this->url . '/' . $categoryLink); } - $packagesXML = $this->requestXml($this->url . $categoryLink); - $packages = $packagesXML->getElementsByTagName('p'); - $loader = new ArrayLoader(); - foreach ($packages as $package) { - $packageName = $package->nodeValue; + } + } - $packageLink = $package->getAttribute('xlink:href'); - $releaseLink = $this->url . str_replace("/rest/p/", "/rest/r/", $packageLink); - $allReleasesLink = $releaseLink . "/allreleases2.xml"; + /** + * @param string $categoryLink + * @throws ErrorException + * @throws InvalidArgumentException + */ + private function fetchPearRepositories($categoryLink) + { + $packagesXML = $this->requestXml($categoryLink); + $packages = $packagesXML->getElementsByTagName('p'); + $loader = new ArrayLoader(); + foreach ($packages as $package) { + $packageName = $package->nodeValue; + + $packageLink = $package->getAttribute('xlink:href'); + $releaseLink = $this->url . str_replace("/rest/p/", "/rest/r/", $packageLink); + $allReleasesLink = $releaseLink . "/allreleases2.xml"; + + try { + $releasesXML = $this->requestXml($allReleasesLink); + } catch (\ErrorException $e) { + if (strpos($e->getMessage(), '404')) { + continue; + } + throw $e; + } + + $releases = $releasesXML->getElementsByTagName('r'); + + foreach ($releases as $release) { + /* @var $release DOMElement */ + $pearVersion = $release->getElementsByTagName('v')->item(0)->nodeValue; + + $packageData = array( + 'name' => $packageName, + 'type' => 'library', + 'dist' => array('type' => 'pear', 'url' => $this->url.'/get/'.$packageName.'-'.$pearVersion.".tgz"), + 'version' => $pearVersion, + ); try { - $releasesXML = $this->requestXml($allReleasesLink); + $deps = file_get_contents($releaseLink . "/deps.".$pearVersion.".txt"); } catch (\ErrorException $e) { if (strpos($e->getMessage(), '404')) { continue; @@ -76,54 +114,135 @@ class PearRepository extends ArrayRepository throw $e; } - $releases = $releasesXML->getElementsByTagName('r'); + $packageData += $this->parseDependences($deps); - foreach ($releases as $release) { - /* @var $release DOMElement */ - $pearVersion = $release->getElementsByTagName('v')->item(0)->nodeValue; + try { + $this->addPackage($loader->load($packageData)); + } catch (\UnexpectedValueException $e) { + continue; + } + } + } + } - $packageData = array( - 'name' => $packageName, - 'type' => 'library', - 'dist' => array('type' => 'pear', 'url' => $this->url.'/get/'.$packageName.'-'.$pearVersion.".tgz"), - 'version' => $pearVersion, + /** + * @todo Improve dependences of pear packages. + * @param array $options + * @return array + */ + private function parseDependencesOptions(array $depsOptions) + { + $data = array(); + foreach ($depsOptions as $name => $options) { + if ('php' == $name) { + $key = $name; + if (isset($options['min'])) { + $value = '>=' . $options['min']; + } else { + $value = '>=0.0.0'; + } + $data[$key] = $value; + + } elseif ('package' == $name) { + foreach ($options as $key => $value) { + $key = $value['name']; + if (isset($value['min'])) { + $value = '>=' . $value['min']; + } else { + $value = '>=0.0.0'; + } + $data[$key] = $value; + } + } elseif ('extension' == $name) { + foreach ($options as $key => $value) { + $key = 'ext-' . $value['name']; + $value = '*'; + $data[$key] = $value; + } + } + } + $data = array_filter($data); + return $data; + } + + /** + * @param string $deps + * @return array + * @throws InvalidArgumentException + */ + private function parseDependences($deps) + { + if (preg_match('((O:([0-9])+:"([^"]+)"))', $deps, $matches)) { + if (strlen($matches[3]) == $matches[2]) { + throw new \InvalidArgumentException("Invalid dependency data, it contains serialized objects."); + } + } + $deps = (array) @unserialize($deps); + unset($deps['required']['pearinstaller']); + + $depsData = array(); + if (isset($deps['required'])) { + $depsData['require'] = $this->parseDependencesOptions($deps['required']); + } else { + $depsData['require'] = array('php' => '>=5.3.0'); + } + + if (isset($depsData['optional'])) { + $depsData['recommend'] = $this->parseDependencesOptions($depsData['optional']); + } + + return $depsData; + } + + /** + * @param string $packagesLink + * @return void + * @throws InvalidArgumentException + */ + private function fetchPear2Repositories($packagesLink) + { + $loader = new ArrayLoader(); + $packagesXml = $this->requestXml($packagesLink); + $informations = $packagesXml->getElementsByTagName('pi'); + foreach ($informations as $information) { + $package = $information->getElementsByTagName('p')->item(0); + + $packageName = $package->getElementsByTagName('n')->item(0)->nodeValue; + $packageData = array( + 'name' => $packageName, + 'type' => 'library' + ); + $packageKeys = array('l' => 'license', 'd' => 'description'); + foreach ($packageKeys as $pear => $composer) { + if ($package->getElementsByTagName($pear)->length > 0 + && ($pear = $package->getElementsByTagName($pear)->item(0)->nodeValue)) { + $packageData[$composer] = $pear; + } + } + + $depsData = $information->getElementsByTagName('deps')->item(0); + $depsData = $depsData->getElementsByTagName('d')->item(0); + $depsData = $this->parseDependences($depsData->nodeValue); + + $revisions = $information->getElementsByTagName('a')->item(0); + $revisions = $revisions->getElementsByTagName('r'); + $packageUrl = $this->url . '/get/' . $packageName; + foreach ($revisions as $revision) { + $version = $revision->getElementsByTagName('v')->item(0)->nodeValue; + $revisionData = array( + 'dist' => array( + 'type' => 'pear', + 'url' => $packageUrl . '-' . $version . '.tgz' + ), + 'version' => $version + ); + + try { + $this->addPackage( + $loader->load($packageData + $revisionData + $depsData) ); - - try { - $deps = file_get_contents($releaseLink . "/deps.".$pearVersion.".txt"); - } catch (\ErrorException $e) { - if (strpos($e->getMessage(), '404')) { - continue; - } - throw $e; - } - - if (preg_match('((O:([0-9])+:"([^"]+)"))', $deps, $matches)) { - if (strlen($matches[3]) == $matches[2]) { - throw new \InvalidArgumentException("Invalid dependency data, it contains serialized objects."); - } - } - $deps = unserialize($deps); - if (isset($deps['required']['package'])) { - - if (isset($deps['required']['package']['name'])) { - $deps['required']['package'] = array($deps['required']['package']); - } - - foreach ($deps['required']['package'] as $dependency) { - if (isset($dependency['min'])) { - $packageData['require'][$dependency['name']] = '>='.$dependency['min']; - } else { - $packageData['require'][$dependency['name']] = '>=0.0.0'; - } - } - } - - try { - $this->addPackage($loader->load($packageData)); - } catch (\UnexpectedValueException $e) { - continue; - } + } catch (\UnexpectedValueException $e) { + continue; } } } @@ -144,4 +263,4 @@ class PearRepository extends ArrayRepository return $dom; } -} +} \ No newline at end of file From 60831ac3fc310eb549c78e022e19787be474c1e1 Mon Sep 17 00:00:00 2001 From: Henrique Moody Date: Tue, 17 Jan 2012 14:54:55 -0200 Subject: [PATCH 17/39] Update src/Composer/Repository/PearRepository.php --- src/Composer/Repository/PearRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index 496950af5..b2f12ab2a 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -31,7 +31,7 @@ class PearRepository extends ArrayRepository throw new \UnexpectedValueException('Invalid url given for PEAR repository: '.$config['url']); } - $this->url = preg_replace('#^(.+)/+$#U', '$1', $config['url']); + $this->url = rtrim($config['url'], '/'); } protected function initialize() From c7e0fb7e58bdeb8d839632a418dbea9b55a73164 Mon Sep 17 00:00:00 2001 From: Henrique Moody Date: Tue, 17 Jan 2012 16:19:25 -0200 Subject: [PATCH 18/39] Correction of typo error. --- src/Composer/Repository/PearRepository.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index b2f12ab2a..119ac1667 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -114,7 +114,7 @@ class PearRepository extends ArrayRepository throw $e; } - $packageData += $this->parseDependences($deps); + $packageData += $this->parseDependencies($deps); try { $this->addPackage($loader->load($packageData)); @@ -130,7 +130,7 @@ class PearRepository extends ArrayRepository * @param array $options * @return array */ - private function parseDependencesOptions(array $depsOptions) + private function parseDependenciesOptions(array $depsOptions) { $data = array(); foreach ($depsOptions as $name => $options) { @@ -170,7 +170,7 @@ class PearRepository extends ArrayRepository * @return array * @throws InvalidArgumentException */ - private function parseDependences($deps) + private function parseDependencies($deps) { if (preg_match('((O:([0-9])+:"([^"]+)"))', $deps, $matches)) { if (strlen($matches[3]) == $matches[2]) { @@ -182,13 +182,13 @@ class PearRepository extends ArrayRepository $depsData = array(); if (isset($deps['required'])) { - $depsData['require'] = $this->parseDependencesOptions($deps['required']); + $depsData['require'] = $this->parseDependenciesOptions($deps['required']); } else { $depsData['require'] = array('php' => '>=5.3.0'); } if (isset($depsData['optional'])) { - $depsData['recommend'] = $this->parseDependencesOptions($depsData['optional']); + $depsData['recommend'] = $this->parseDependenciesOptions($depsData['optional']); } return $depsData; @@ -222,7 +222,7 @@ class PearRepository extends ArrayRepository $depsData = $information->getElementsByTagName('deps')->item(0); $depsData = $depsData->getElementsByTagName('d')->item(0); - $depsData = $this->parseDependences($depsData->nodeValue); + $depsData = $this->parseDependencies($depsData->nodeValue); $revisions = $information->getElementsByTagName('a')->item(0); $revisions = $revisions->getElementsByTagName('r'); From 1e11aff456a9df7b57285a5f2a9db1684f65305d Mon Sep 17 00:00:00 2001 From: Henrique Moody Date: Tue, 17 Jan 2012 16:26:29 -0200 Subject: [PATCH 19/39] Create method parseVersion for parsing of package versions. Now includes "max" version of the package. --- src/Composer/Repository/PearRepository.php | 38 ++++++++++++---------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index 119ac1667..d9799598d 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -124,6 +124,23 @@ class PearRepository extends ArrayRepository } } } + + /** + * @param array $data + * @return string + */ + private function parseVersion(array $data) + { + if (isset($data['min'])) { + $version = '>=' . $data['min']; + } else { + $version = '>=0.0.0'; + } + if (isset($data['max'])) { + $version .= ',<=' . $data['max']; + } + return $version; + } /** * @todo Improve dependences of pear packages. @@ -135,29 +152,16 @@ class PearRepository extends ArrayRepository $data = array(); foreach ($depsOptions as $name => $options) { if ('php' == $name) { - $key = $name; - if (isset($options['min'])) { - $value = '>=' . $options['min']; - } else { - $value = '>=0.0.0'; - } - $data[$key] = $value; - + $data[$name] = $this->parseVersion($options); } elseif ('package' == $name) { foreach ($options as $key => $value) { - $key = $value['name']; - if (isset($value['min'])) { - $value = '>=' . $value['min']; - } else { - $value = '>=0.0.0'; - } - $data[$key] = $value; + $key = $value['name']; + $data[$key] = $this->parseVersion($value); } } elseif ('extension' == $name) { foreach ($options as $key => $value) { $key = 'ext-' . $value['name']; - $value = '*'; - $data[$key] = $value; + $data[$key] = '*'; } } } From 0c6d80679146203c1d03408ff6b4870ca32e9bc2 Mon Sep 17 00:00:00 2001 From: Henrique Moody Date: Tue, 17 Jan 2012 16:29:56 -0200 Subject: [PATCH 20/39] Correction of typo. --- src/Composer/Repository/PearRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index d9799598d..91fc5b654 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -143,7 +143,7 @@ class PearRepository extends ArrayRepository } /** - * @todo Improve dependences of pear packages. + * @todo Improve dependencies resolution of pear packages. * @param array $options * @return array */ From b62a90a981b5131fa9a014210f2e4d3b32182be1 Mon Sep 17 00:00:00 2001 From: Henrique Moody Date: Tue, 17 Jan 2012 16:33:23 -0200 Subject: [PATCH 21/39] Removed hard code - suggestion of a PHP version. --- src/Composer/Repository/PearRepository.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index 91fc5b654..7738b1a48 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -187,8 +187,6 @@ class PearRepository extends ArrayRepository $depsData = array(); if (isset($deps['required'])) { $depsData['require'] = $this->parseDependenciesOptions($deps['required']); - } else { - $depsData['require'] = array('php' => '>=5.3.0'); } if (isset($depsData['optional'])) { From 6c47d6efe2461aa8b9d8cb9e42727433fc9f952e Mon Sep 17 00:00:00 2001 From: Henrique Moody Date: Tue, 17 Jan 2012 16:38:01 -0200 Subject: [PATCH 22/39] Renamed methods of Composer\Repository\PearRepository: fetchPearRepositories() to fetchPearPackages() and fetchPear2Repositories() to fetchPea2Packages(). --- src/Composer/Repository/PearRepository.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index 7738b1a48..3c4064eb8 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -54,13 +54,13 @@ class PearRepository extends ArrayRepository $link = $category->getAttribute("xlink:href"); try { $packagesLink = str_replace("info.xml", "packagesinfo.xml", $link); - $this->fetchPear2Repositories($this->url . '/' . $packagesLink); + $this->fetchPear2Packages($this->url . '/' . $packagesLink); } catch (\ErrorException $e) { if (false === strpos($e->getMessage(), '404')) { throw $e; } $categoryLink = str_replace("info.xml", "packages.xml", $link); - $this->fetchPearRepositories($this->url . '/' . $categoryLink); + $this->fetchPearPackages($this->url . '/' . $categoryLink); } } @@ -71,7 +71,7 @@ class PearRepository extends ArrayRepository * @throws ErrorException * @throws InvalidArgumentException */ - private function fetchPearRepositories($categoryLink) + private function fetchPearPackages($categoryLink) { $packagesXML = $this->requestXml($categoryLink); $packages = $packagesXML->getElementsByTagName('p'); @@ -201,7 +201,7 @@ class PearRepository extends ArrayRepository * @return void * @throws InvalidArgumentException */ - private function fetchPear2Repositories($packagesLink) + private function fetchPear2Packages($packagesLink) { $loader = new ArrayLoader(); $packagesXml = $this->requestXml($packagesLink); From 4e6a9806b69f8f0b6a407f315f6832fb6a5b9153 Mon Sep 17 00:00:00 2001 From: Henrique Moody Date: Tue, 17 Jan 2012 16:39:16 -0200 Subject: [PATCH 23/39] Correction of wrong type suggestion. --- src/Composer/Repository/PearRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index 3c4064eb8..fb1e2b5a6 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -95,7 +95,7 @@ class PearRepository extends ArrayRepository $releases = $releasesXML->getElementsByTagName('r'); foreach ($releases as $release) { - /* @var $release DOMElement */ + /* @var $release \DOMElement */ $pearVersion = $release->getElementsByTagName('v')->item(0)->nodeValue; $packageData = array( From dd2174885bea3d7e6371e13b66aa92da67c12a7e Mon Sep 17 00:00:00 2001 From: Henrique Moody Date: Tue, 17 Jan 2012 16:49:03 -0200 Subject: [PATCH 24/39] Correction of variable overwrite used during an iteration and now the versions of PHP extensions are parsed like packages. --- src/Composer/Repository/PearRepository.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index fb1e2b5a6..695dcad25 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -155,13 +155,13 @@ class PearRepository extends ArrayRepository $data[$name] = $this->parseVersion($options); } elseif ('package' == $name) { foreach ($options as $key => $value) { - $key = $value['name']; - $data[$key] = $this->parseVersion($value); + $dataKey = $value['name']; + $data[$dataKey] = $this->parseVersion($value); } } elseif ('extension' == $name) { foreach ($options as $key => $value) { - $key = 'ext-' . $value['name']; - $data[$key] = '*'; + $dataKey = 'ext-' . $value['name']; + $data[$dataKey] = $this->parseVersion($value); } } } From be448e09b4fcdb2c51988d4aae1e7fcaa6e9eb9d Mon Sep 17 00:00:00 2001 From: Henrique Moody Date: Tue, 17 Jan 2012 16:45:34 -0200 Subject: [PATCH 25/39] Update src/Composer/Repository/PearRepository.php --- src/Composer/Repository/PearRepository.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index 695dcad25..9b1d98b93 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -165,7 +165,6 @@ class PearRepository extends ArrayRepository } } } - $data = array_filter($data); return $data; } From 234a6710a14d73103e0bea1ddaa4bfbc028f84a8 Mon Sep 17 00:00:00 2001 From: Henrique Moody Date: Tue, 17 Jan 2012 17:02:39 -0200 Subject: [PATCH 26/39] Correction at method parseVersion() of Composer\Repository\PearRepository. --- src/Composer/Repository/PearRepository.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index 9b1d98b93..06095e2fe 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -124,22 +124,24 @@ class PearRepository extends ArrayRepository } } } - + /** * @param array $data - * @return string + * @return string */ private function parseVersion(array $data) { + if (!isset($data['min']) && !isset($data['max'])) { + return '*'; + } + $versions = array(); if (isset($data['min'])) { - $version = '>=' . $data['min']; - } else { - $version = '>=0.0.0'; + $versions[] = '>=' . $data['min']; } if (isset($data['max'])) { - $version .= ',<=' . $data['max']; + $versions[] = '<=' . $data['max']; } - return $version; + return implode(',', $versions); } /** @@ -155,7 +157,7 @@ class PearRepository extends ArrayRepository $data[$name] = $this->parseVersion($options); } elseif ('package' == $name) { foreach ($options as $key => $value) { - $dataKey = $value['name']; + $dataKey = $value['name']; $data[$dataKey] = $this->parseVersion($value); } } elseif ('extension' == $name) { @@ -165,6 +167,7 @@ class PearRepository extends ArrayRepository } } } + var_dump($data);die; return $data; } From 9ca157913abbb8567ab530ae4e78b52498447faf Mon Sep 17 00:00:00 2001 From: Henrique Moody Date: Wed, 18 Jan 2012 09:04:01 -0200 Subject: [PATCH 27/39] Remotion of a debug code. --- src/Composer/Repository/PearRepository.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index 06095e2fe..f502bd0df 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -167,7 +167,6 @@ class PearRepository extends ArrayRepository } } } - var_dump($data);die; return $data; } From b3d91cab02244906f1f97f256a0b5af4ab00833d Mon Sep 17 00:00:00 2001 From: Henrique Moody Date: Sat, 11 Feb 2012 13:04:33 -0200 Subject: [PATCH 28/39] Update dependence resolution for PEAR2 packages. --- src/Composer/Repository/PearRepository.php | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index f502bd0df..1ad09637e 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -157,8 +157,10 @@ class PearRepository extends ArrayRepository $data[$name] = $this->parseVersion($options); } elseif ('package' == $name) { foreach ($options as $key => $value) { - $dataKey = $value['name']; - $data[$dataKey] = $this->parseVersion($value); + if (is_array($value)) { + $dataKey = $value['name']; + $data[$dataKey] = $this->parseVersion($value); + } } } elseif ('extension' == $name) { foreach ($options as $key => $value) { @@ -223,9 +225,13 @@ class PearRepository extends ArrayRepository } } - $depsData = $information->getElementsByTagName('deps')->item(0); - $depsData = $depsData->getElementsByTagName('d')->item(0); - $depsData = $this->parseDependencies($depsData->nodeValue); + $depsData = array(); + foreach ($information->getElementsByTagName('deps') as $depElement) { + $depsVersion = $depElement->getElementsByTagName('v')->item(0)->nodeValue; + $depsData[$depsVersion] = $this->parseDependencies( + $depElement->getElementsByTagName('d')->item(0)->nodeValue + ); + } $revisions = $information->getElementsByTagName('a')->item(0); $revisions = $revisions->getElementsByTagName('r'); @@ -239,10 +245,13 @@ class PearRepository extends ArrayRepository ), 'version' => $version ); + if (isset($depsData[$version])) { + $revisionData += $depsData[$version]; + } try { $this->addPackage( - $loader->load($packageData + $revisionData + $depsData) + $loader->load($packageData + $revisionData) ); } catch (\UnexpectedValueException $e) { continue; From 61c66b98a87b5038b42f8a5f7f52d379e54d60bb Mon Sep 17 00:00:00 2001 From: Henrique Moody Date: Sat, 11 Feb 2012 13:33:25 -0200 Subject: [PATCH 29/39] Correction of wrong variable name. --- src/Composer/Repository/PearRepository.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index 1ad09637e..7b118ad12 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -192,8 +192,8 @@ class PearRepository extends ArrayRepository $depsData['require'] = $this->parseDependenciesOptions($deps['required']); } - if (isset($depsData['optional'])) { - $depsData['recommend'] = $this->parseDependenciesOptions($depsData['optional']); + if (isset($deps['optional'])) { + $depsData['recommend'] = $this->parseDependenciesOptions($deps['optional']); } return $depsData; From 230f43d009c535fa9bb6b946a5765ecc13f73686 Mon Sep 17 00:00:00 2001 From: Henrique Moody Date: Sat, 11 Feb 2012 15:17:27 -0200 Subject: [PATCH 30/39] Chaged the key "recommend" for "suggest" in the parse of the PEAR2 dependences. --- src/Composer/Repository/PearRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index 7b118ad12..4c277af83 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -193,7 +193,7 @@ class PearRepository extends ArrayRepository } if (isset($deps['optional'])) { - $depsData['recommend'] = $this->parseDependenciesOptions($deps['optional']); + $depsData['suggest'] = $this->parseDependenciesOptions($deps['optional']); } return $depsData; From 8a5c7b39e401bdbbd8f7b5e1575403578a226652 Mon Sep 17 00:00:00 2001 From: Henrique Moody Date: Sat, 11 Feb 2012 15:58:23 -0200 Subject: [PATCH 31/39] Added "nbproject" folder to the .gitignore list. --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index dfbe013f5..5992f93fc 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ /.project /.buildpath /composer.phar -/vendor \ No newline at end of file +/vendor +/nbproject From ba2dc9b7c37cecf3503968cb23748ea0cdfe1be6 Mon Sep 17 00:00:00 2001 From: Maks3w Date: Sun, 12 Feb 2012 09:45:04 +0100 Subject: [PATCH 32/39] Typo and coding style --- doc/DefaultPolicy.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/doc/DefaultPolicy.md b/doc/DefaultPolicy.md index 4254e20bf..328ceec8f 100644 --- a/doc/DefaultPolicy.md +++ b/doc/DefaultPolicy.md @@ -27,7 +27,7 @@ Request: install A Packages Repo1.Av1, Repo2.Av1 * priority(Repo1) >= priority(Repo2) => (Repo1.Av1, Repo2.Av1) -* priority(Repo2) < priority(Repo2) => (Repo2.Av1, Repo1.Av1) +* priority(Repo1) < priority(Repo2) => (Repo2.Av1, Repo1.Av1) ### Virtual Packages (provides) @@ -39,7 +39,7 @@ Packages Av1, Bv1 Request: install X * priority(Av1.repo) >= priority(Bv1.repo) => (Av1, Bv1) -* priority(Av1.repo) < priority(Bv1.repo) => (Bv1, Av1) +* priority(Av1.repo) < priority(Bv1.repo) => (Bv1, Av1) ### Package replacements @@ -49,8 +49,7 @@ Packages: Av1, Bv2 Request: install A -* priority(Av1.repo) > priority(Bv2.repo) => (Av1, Bv2) -* priority(Av1.repo) = priority(Bv2.repo) => (Av1, Bv2) -* priority(Av1.repo) < priority(Bv2.repo) => (Bv2, Av1) +* priority(Av1.repo) >= priority(Bv2.repo) => (Av1, Bv2) +* priority(Av1.repo) < priority(Bv2.repo) => (Bv2, Av1) -Bv2.version is ignored, only the replacement version for A matters. +Bv2 version is ignored, only the replacement version for A matters. From bf0f0cf73eb8ee07bb44e0e15e6de9264133f863 Mon Sep 17 00:00:00 2001 From: Beau Simensen Date: Sun, 12 Feb 2012 15:24:18 -0600 Subject: [PATCH 33/39] Updated to reference @Seldaek notes and refer to GitHub Post-Receive URL PR. --- doc/faqs/packagist-update-schedule.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/doc/faqs/packagist-update-schedule.md b/doc/faqs/packagist-update-schedule.md index af476decc..865e48a44 100644 --- a/doc/faqs/packagist-update-schedule.md +++ b/doc/faqs/packagist-update-schedule.md @@ -2,7 +2,7 @@ ## How often does Packagist crawl newly added packages? -New packages will be crawled **every five minutes**. +New packages will be crawled **within ten minutes**. ## How often does Packagist crawl existing packages? @@ -12,13 +12,11 @@ Existing packages will be crawled **every hour**. ## How often does the Packagist search index update? -The search index is rebuilt **every hour**. It will index (or reindex) +The search index is updated **every five minutes**. It will index (or reindex) any package that has been crawled since the last time the search indexer ran. ## Can Packagist be triggered to recrawl a package (on commit or by other means)? -Not yet. :) Want to help? See -[#81](https://github.com/composer/packagist/issues/81) -and [#67](https://github.com/composer/packagist/issues/67) \ No newline at end of file +Not yet. :) See [#84](https://github.com/composer/packagist/issues/84). \ No newline at end of file From 81d41fc44287c418aa5bb142091ce79d6d325a32 Mon Sep 17 00:00:00 2001 From: Beau Simensen Date: Mon, 13 Feb 2012 13:05:44 -0800 Subject: [PATCH 34/39] Rename --dev to --prefer-source --- src/Composer/Command/InstallCommand.php | 4 ++-- src/Composer/Command/UpdateCommand.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Composer/Command/InstallCommand.php b/src/Composer/Command/InstallCommand.php index 26e1a5ba2..d656ad5d1 100644 --- a/src/Composer/Command/InstallCommand.php +++ b/src/Composer/Command/InstallCommand.php @@ -46,7 +46,7 @@ class InstallCommand extends Command ->setName('install') ->setDescription('Parses the composer.json file and downloads the needed dependencies.') ->setDefinition(array( - new InputOption('dev', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'), + new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'), new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'), new InputOption('no-install-recommends', null, InputOption::VALUE_NONE, 'Do not install recommended packages (ignored when installing from an existing lock file).'), new InputOption('install-suggests', null, InputOption::VALUE_NONE, 'Also install suggested packages (ignored when installing from an existing lock file).'), @@ -73,7 +73,7 @@ EOT $io, $composer, $eventDispatcher, - (Boolean)$input->getOption('dev'), + (Boolean)$input->getOption('prefer-source'), (Boolean)$input->getOption('dry-run'), (Boolean)$input->getOption('verbose'), (Boolean)$input->getOption('no-install-recommends'), diff --git a/src/Composer/Command/UpdateCommand.php b/src/Composer/Command/UpdateCommand.php index 3c2b394c0..7e1e8e0c1 100644 --- a/src/Composer/Command/UpdateCommand.php +++ b/src/Composer/Command/UpdateCommand.php @@ -35,7 +35,7 @@ class UpdateCommand extends Command ->setName('update') ->setDescription('Updates your dependencies to the latest version, and updates the composer.lock file.') ->setDefinition(array( - new InputOption('dev', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'), + new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'), new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'), new InputOption('no-install-recommends', null, InputOption::VALUE_NONE, 'Do not install recommended packages.'), new InputOption('install-suggests', null, InputOption::VALUE_NONE, 'Also install suggested packages.'), @@ -63,7 +63,7 @@ EOT $io, $composer, $eventDispatcher, - (Boolean)$input->getOption('dev'), + (Boolean)$input->getOption('prefer-source'), (Boolean)$input->getOption('dry-run'), (Boolean)$input->getOption('verbose'), (Boolean)$input->getOption('no-install-recommends'), From 416ae21a5a12c75965095a7e348c2a7f2889551c Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 13 Feb 2012 23:07:18 +0100 Subject: [PATCH 35/39] Robustness fixes for new PEAR2 compat code --- src/Composer/Repository/PearRepository.php | 32 ++++++++++++++-------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index 4c277af83..9543d4c22 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -54,13 +54,13 @@ class PearRepository extends ArrayRepository $link = $category->getAttribute("xlink:href"); try { $packagesLink = str_replace("info.xml", "packagesinfo.xml", $link); - $this->fetchPear2Packages($this->url . '/' . $packagesLink); + $this->fetchPear2Packages($this->url . $packagesLink); } catch (\ErrorException $e) { if (false === strpos($e->getMessage(), '404')) { throw $e; } $categoryLink = str_replace("info.xml", "packages.xml", $link); - $this->fetchPearPackages($this->url . '/' . $categoryLink); + $this->fetchPearPackages($this->url . $categoryLink); } } @@ -153,6 +153,10 @@ class PearRepository extends ArrayRepository { $data = array(); foreach ($depsOptions as $name => $options) { + // make sure single deps are wrapped in an array + if (isset($options['name'])) { + $options = array($options); + } if ('php' == $name) { $data[$name] = $this->parseVersion($options); } elseif ('package' == $name) { @@ -188,11 +192,11 @@ class PearRepository extends ArrayRepository unset($deps['required']['pearinstaller']); $depsData = array(); - if (isset($deps['required'])) { + if (!empty($deps['required'])) { $depsData['require'] = $this->parseDependenciesOptions($deps['required']); } - if (isset($deps['optional'])) { + if (!empty($deps['optional'])) { $depsData['suggest'] = $this->parseDependenciesOptions($deps['optional']); } @@ -225,7 +229,7 @@ class PearRepository extends ArrayRepository } } - $depsData = array(); + $depsData = array(); foreach ($information->getElementsByTagName('deps') as $depElement) { $depsVersion = $depElement->getElementsByTagName('v')->item(0)->nodeValue; $depsData[$depsVersion] = $this->parseDependencies( @@ -233,12 +237,16 @@ class PearRepository extends ArrayRepository ); } - $revisions = $information->getElementsByTagName('a')->item(0); - $revisions = $revisions->getElementsByTagName('r'); + $releases = $information->getElementsByTagName('a')->item(0); + if (!$releases) { + continue; + } + + $releases = $releases->getElementsByTagName('r'); $packageUrl = $this->url . '/get/' . $packageName; - foreach ($revisions as $revision) { - $version = $revision->getElementsByTagName('v')->item(0)->nodeValue; - $revisionData = array( + foreach ($releases as $release) { + $version = $release->getElementsByTagName('v')->item(0)->nodeValue; + $releaseData = array( 'dist' => array( 'type' => 'pear', 'url' => $packageUrl . '-' . $version . '.tgz' @@ -246,12 +254,12 @@ class PearRepository extends ArrayRepository 'version' => $version ); if (isset($depsData[$version])) { - $revisionData += $depsData[$version]; + $releaseData += $depsData[$version]; } try { $this->addPackage( - $loader->load($packageData + $revisionData) + $loader->load($packageData + $releaseData) ); } catch (\UnexpectedValueException $e) { continue; From 01be62d842e445f54f4e7a7626446fb100433abe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Tue, 14 Feb 2012 12:57:15 +0100 Subject: [PATCH 36/39] Updated ArrayDumper --- src/Composer/Package/Dumper/ArrayDumper.php | 9 +++ src/Composer/Package/MemoryPackage.php | 2 +- .../Test/Package/Dumper/ArrayDumperTest.php | 66 +++++++++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 tests/Composer/Test/Package/Dumper/ArrayDumperTest.php diff --git a/src/Composer/Package/Dumper/ArrayDumper.php b/src/Composer/Package/Dumper/ArrayDumper.php index ee2a0b376..f372929b1 100644 --- a/src/Composer/Package/Dumper/ArrayDumper.php +++ b/src/Composer/Package/Dumper/ArrayDumper.php @@ -24,11 +24,16 @@ class ArrayDumper { $keys = array( 'binaries' => 'bin', + 'scripts', 'type', 'names', 'extra', 'installationSource' => 'installation-source', 'license', + 'authors', + 'description', + 'homepage', + 'keywords', 'autoload', 'repositories', ); @@ -41,6 +46,10 @@ class ArrayDumper $data['target-dir'] = $package->getTargetDir(); } + if ($package->getReleaseDate()) { + $data['time'] = $package->getReleaseDate()->format('Y-m-d H:i:s'); + } + if ($package->getSourceType()) { $data['source']['type'] = $package->getSourceType(); $data['source']['url'] = $package->getSourceUrl(); diff --git a/src/Composer/Package/MemoryPackage.php b/src/Composer/Package/MemoryPackage.php index 02222e43b..d1e63e102 100644 --- a/src/Composer/Package/MemoryPackage.php +++ b/src/Composer/Package/MemoryPackage.php @@ -438,7 +438,7 @@ class MemoryPackage extends BasePackage * * @param DateTime $releaseDate */ - public function setReleasedate(\DateTime $releaseDate) + public function setReleaseDate(\DateTime $releaseDate) { $this->releaseDate = $releaseDate; } diff --git a/tests/Composer/Test/Package/Dumper/ArrayDumperTest.php b/tests/Composer/Test/Package/Dumper/ArrayDumperTest.php new file mode 100644 index 000000000..eab3450bf --- /dev/null +++ b/tests/Composer/Test/Package/Dumper/ArrayDumperTest.php @@ -0,0 +1,66 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Test\Package\Dumper; + +use Composer\Package\Dumper\ArrayDumper; +use Composer\Package\MemoryPackage; + +class ArrayDumperTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + $this->dumper = new ArrayDumper(); + } + + public function testRequiredInformations() + { + $package = new MemoryPackage('foo', '1.0.0.0', '1.0'); + + $config = $this->dumper->dump($package); + $this->assertEquals(array('name', 'version', 'version_normalized', 'type', 'names'), array_keys($config)); + } + + /** + * @dataProvider getKeys + */ + public function testKeys($key, $value, $expectedValue = null, $method = null) + { + $package = new MemoryPackage('foo', '1.0.0.0', '1.0'); + + $setter = 'set'.ucfirst($method ?: $key); + $package->$setter($value); + + $config = $this->dumper->dump($package); + $this->assertArrayHasKey($key, $config); + + $expectedValue = $expectedValue ?: $value; + $this->assertSame($expectedValue, $config[$key]); + } + + public function getKeys() + { + return array( + array('time', new \DateTime('2012-02-01'), '2012-02-01 00:00:00', 'ReleaseDate'), + array('authors', array('Nils Adermann ', 'Jordi Boggiano ')), + array('homepage', 'http://getcomposer.org'), + array('description', 'Package Manager'), + array('keywords', array('package', 'dependency', 'autoload')), + array('bin', array('bin/composer'), null, 'binaries'), + array('license', array('MIT')), + array('autoload', array('psr-0' => array('Composer' => 'src/'))), + array('repositories', array('packagist' => false)), + array('scripts', array('post-update-cmd' => 'MyVendor\\MyClass::postUpdate')), + array('extra', array('class' => 'MyVendor\\Installer')), + ); + } +} From b030a36bf58a44748ae2fa9247fca9d89209fee1 Mon Sep 17 00:00:00 2001 From: Henrique Moody Date: Tue, 14 Feb 2012 12:29:32 -0200 Subject: [PATCH 37/39] Some PEAR repositories does not works because of a wrong link parse. --- src/Composer/Repository/PearRepository.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index 9543d4c22..43ba5dc87 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -52,6 +52,9 @@ class PearRepository extends ArrayRepository foreach ($categories as $category) { $link = $category->getAttribute("xlink:href"); + if (0 !== strpos($link, '/')) { + $link = '/' . $link; + } try { $packagesLink = str_replace("info.xml", "packagesinfo.xml", $link); $this->fetchPear2Packages($this->url . $packagesLink); From cd7d0b300c65333d006702533b5764adad630cfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Bj=C3=B8rnskov?= Date: Tue, 14 Feb 2012 15:31:05 +0100 Subject: [PATCH 38/39] Formatting for the README.md install command. --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 50788a490..9dae242e9 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,9 @@ Installation / Usage 1. Download the [`composer.phar`](http://getcomposer.org/composer.phar) executable or use the installer. - + ``` sh $ curl -s http://getcomposer.org/installer | php + ``` 2. Create a composer.json defining your dependencies. Note that this example is From e92e3ba3554bcbeb34bd4ede535cb626e4c96e69 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 14 Feb 2012 16:06:09 +0100 Subject: [PATCH 39/39] Simplify code --- src/Composer/Repository/PearRepository.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Composer/Repository/PearRepository.php b/src/Composer/Repository/PearRepository.php index 43ba5dc87..ff975d99a 100644 --- a/src/Composer/Repository/PearRepository.php +++ b/src/Composer/Repository/PearRepository.php @@ -51,10 +51,7 @@ class PearRepository extends ArrayRepository $categories = $categoryXML->getElementsByTagName("c"); foreach ($categories as $category) { - $link = $category->getAttribute("xlink:href"); - if (0 !== strpos($link, '/')) { - $link = '/' . $link; - } + $link = '/' . ltrim($category->getAttribute("xlink:href"), '/'); try { $packagesLink = str_replace("info.xml", "packagesinfo.xml", $link); $this->fetchPear2Packages($this->url . $packagesLink);