From 9fcf01695c5e8a2891fd5d2a36292b6f5422e9dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Bj=C3=B8rnskov?= Date: Thu, 12 Jan 2012 12:54:26 +0100 Subject: [PATCH 01/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f0693158b..ebdcf2479 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Global installation of composer (via homebrew) Installing via this homebrew formula will always get you the latest composer version. -1. run `brew uninstall composer ; brew install https://raw.github.com/gist/1574469/composer.rb` +1. run `brew uninstall composer ; brew install --HEAD https://raw.github.com/gist/1574469/composer.rb` 2. Change into a project directory `cd /path/to/my/project` 3. Use composer as you normally would `composer.phar install` From cc1dbbc36ffd4784b1d6debcb7e17f57666a94a3 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sun, 15 Jan 2012 13:00:39 +0100 Subject: [PATCH 02/14] Add --link-type option to select link types in DependsCommand --- src/Composer/Command/DependsCommand.php | 41 +++++++++++++++++-------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/src/Composer/Command/DependsCommand.php b/src/Composer/Command/DependsCommand.php index aa720adaa..f695487ff 100644 --- a/src/Composer/Command/DependsCommand.php +++ b/src/Composer/Command/DependsCommand.php @@ -16,10 +16,12 @@ 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; /** * @author Justin Rainbow + * @author Jordi Boggiano */ class DependsCommand extends Command { @@ -27,13 +29,14 @@ class DependsCommand extends Command { $this ->setName('depends') - ->setDescription('Where is a package used?') + ->setDescription('Shows which packages depend on the given package') ->setDefinition(array( - new InputArgument('package', InputArgument::REQUIRED, 'the package to inspect') + new InputArgument('package', InputArgument::REQUIRED, 'Package to inspect'), + new InputOption('link-type', '', InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Link types to show', array('requires', 'recommends', 'suggests')) )) ->setHelp(<<php composer.phar depends composer/composer EOT @@ -46,7 +49,11 @@ EOT $composer = $this->getComposer(); $references = $this->getReferences($input, $output, $composer); - $this->printReferences($input, $output, $references); + if ($input->getOption('verbose')) { + $this->printReferences($input, $output, $references); + } else { + $this->printPackages($input, $output, $references); + } } /** @@ -63,18 +70,20 @@ EOT $needle = $input->getArgument('package'); $references = array(); + $verbose = (Boolean) $input->getOption('verbose'); - // check if we have a local installation so we can grab the right package/version - $repos = array_merge( - array($composer->getRepositoryManager()->getLocalRepository()), - $composer->getRepositoryManager()->getRepositories() - ); + $repos = $composer->getRepositoryManager()->getRepositories(); + $types = $input->getOption('link-type'); foreach ($repos as $repository) { foreach ($repository->getPackages() as $package) { - foreach (array('requires', 'recommends', 'suggests') as $type) { + foreach ($types as $type) { foreach ($package->{'get'.$type}() as $link) { if ($link->getTarget() === $needle) { - $references[] = array($type, $package, $link); + if ($verbose) { + $references[] = array($type, $package, $link); + } else { + $references[$package->getName()] = $package->getPrettyName(); + } } } } @@ -90,4 +99,12 @@ EOT $output->writeln($ref[1]->getPrettyName() . ' ' . $ref[1]->getPrettyVersion() . ' ' . $ref[0] . ' ' . $ref[2]->getPrettyConstraint()); } } + + private function printPackages(InputInterface $input, OutputInterface $output, array $packages) + { + ksort($packages); + foreach ($packages as $package) { + $output->writeln($package); + } + } } \ No newline at end of file From 8b1b4527bdbd16dc9e6fac23d14ba868ecbea6c3 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sun, 15 Jan 2012 13:50:29 +0100 Subject: [PATCH 03/14] Fix code coverage report, fixes #205 --- phpunit.xml.dist | 3 +++ 1 file changed, 3 insertions(+) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 7ba5d7997..246d305e4 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -20,6 +20,9 @@ ./src/Composer/ + + ./src/Composer/Autoload/ClassLoader.php + From 098ba8e58346f2891b9d7074bb7be6073b142c9d Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sun, 15 Jan 2012 14:15:53 +0100 Subject: [PATCH 04/14] Add test --- .../Test/DependencyResolver/SolverTest.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/Composer/Test/DependencyResolver/SolverTest.php b/tests/Composer/Test/DependencyResolver/SolverTest.php index c2ed0f2bf..7496834e6 100644 --- a/tests/Composer/Test/DependencyResolver/SolverTest.php +++ b/tests/Composer/Test/DependencyResolver/SolverTest.php @@ -115,6 +115,25 @@ class SolverTest extends TestCase $this->checkSolverResult(array()); } + public function testSolverUpdateDoesOnlyUpdate() + { + $this->repoInstalled->addPackage($packageA = $this->getPackage('A', '1.0')); + $this->repoInstalled->addPackage($packageB = $this->getPackage('B', '1.0')); + $this->repo->addPackage($newPackageB = $this->getPackage('B', '1.1')); + $this->reposComplete(); + + $packageA->setRequires(array(new Link('A', 'B', new VersionConstraint('>=', '1.0.0.0'), 'requires'))); + + $this->request->install('A', new VersionConstraint('=', '1.0.0.0')); + $this->request->install('B', new VersionConstraint('=', '1.1.0.0')); + $this->request->update('A', new VersionConstraint('=', '1.0.0.0')); + $this->request->update('B', new VersionConstraint('=', '1.0.0.0')); + + $this->checkSolverResult(array( + array('job' => 'update', 'from' => $packageB, 'to' => $newPackageB), + )); + } + public function testSolverUpdateSingle() { $this->repoInstalled->addPackage($packageA = $this->getPackage('A', '1.0')); From fc17e26bc326948ca38679464a2228716073e95f Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Mon, 16 Jan 2012 12:44:47 +0100 Subject: [PATCH 05/14] Added a method to find packages by name --- src/Composer/Repository/ArrayRepository.php | 13 +++++++++++++ src/Composer/Repository/RepositoryInterface.php | 9 +++++++++ 2 files changed, 22 insertions(+) diff --git a/src/Composer/Repository/ArrayRepository.php b/src/Composer/Repository/ArrayRepository.php index 06910bbe3..724f9bd4c 100644 --- a/src/Composer/Repository/ArrayRepository.php +++ b/src/Composer/Repository/ArrayRepository.php @@ -41,6 +41,19 @@ class ArrayRepository implements RepositoryInterface } } + /** + * {@inheritDoc} + */ + public function findPackagesByName($name) + { + // normalize name + $name = strtolower($name); + + return array_filter($this->getPackages(), function(PackageInterface $package) use ($name) { + return $package->getName() === $name; + }); + } + /** * {@inheritDoc} */ diff --git a/src/Composer/Repository/RepositoryInterface.php b/src/Composer/Repository/RepositoryInterface.php index a94ecea4c..d791b161d 100644 --- a/src/Composer/Repository/RepositoryInterface.php +++ b/src/Composer/Repository/RepositoryInterface.php @@ -41,6 +41,15 @@ interface RepositoryInterface extends \Countable */ function findPackage($name, $version); + /** + * Searches for packages by it's name . + * + * @param string $name package name + * + * @return array + */ + function findPackagesByName($name); + /** * Returns list of registered packages. * From 1fdb7aef56ec6d380bd23da24de83a7ef8a7f97a Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Mon, 16 Jan 2012 12:52:17 +0100 Subject: [PATCH 06/14] Changed the ShowCommand to use the new method --- src/Composer/Command/ShowCommand.php | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/Composer/Command/ShowCommand.php b/src/Composer/Command/ShowCommand.php index 224053c8e..334cd8997 100644 --- a/src/Composer/Command/ShowCommand.php +++ b/src/Composer/Command/ShowCommand.php @@ -85,11 +85,9 @@ EOT $composer->getRepositoryManager()->getRepositories() ); foreach ($repos as $repository) { - foreach ($repository->getPackages() as $package) { - if ($package->getName() === $input->getArgument('package')) { - if (null === $highestVersion || version_compare($package->getVersion(), $highestVersion->getVersion(), '>=')) { - $highestVersion = $package; - } + foreach ($repository->findPackagesByName($input->getArgument('package')) as $package) { + if (null === $highestVersion || version_compare($package->getVersion(), $highestVersion->getVersion(), '>=')) { + $highestVersion = $package; } } } @@ -135,10 +133,8 @@ EOT $versions = array(); foreach ($composer->getRepositoryManager()->getRepositories() as $repository) { - foreach ($repository->getPackages() as $version) { - if ($version->getName() === $package->getName()) { - $versions[] = $version->getPrettyVersion(); - } + foreach ($repository->findPackagesByName($package->getName()) as $version) { + $versions[] = $version->getPrettyVersion(); } } From bd1d20b2c971dfe67d7db2b4fac0c141dae80678 Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Mon, 16 Jan 2012 22:11:31 +0100 Subject: [PATCH 07/14] Fixed CS --- src/Composer/Repository/ArrayRepository.php | 2 +- src/Composer/Repository/RepositoryInterface.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Composer/Repository/ArrayRepository.php b/src/Composer/Repository/ArrayRepository.php index 724f9bd4c..8d3898f3d 100644 --- a/src/Composer/Repository/ArrayRepository.php +++ b/src/Composer/Repository/ArrayRepository.php @@ -49,7 +49,7 @@ class ArrayRepository implements RepositoryInterface // normalize name $name = strtolower($name); - return array_filter($this->getPackages(), function(PackageInterface $package) use ($name) { + return array_filter($this->getPackages(), function (PackageInterface $package) use ($name) { return $package->getName() === $name; }); } diff --git a/src/Composer/Repository/RepositoryInterface.php b/src/Composer/Repository/RepositoryInterface.php index d791b161d..2c1f7d43c 100644 --- a/src/Composer/Repository/RepositoryInterface.php +++ b/src/Composer/Repository/RepositoryInterface.php @@ -42,7 +42,7 @@ interface RepositoryInterface extends \Countable function findPackage($name, $version); /** - * Searches for packages by it's name . + * Searches for packages by it's name. * * @param string $name package name * From 38a5f04ea024c28429d583b2eb18e5cbac54d43f Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Mon, 16 Jan 2012 22:29:22 +0100 Subject: [PATCH 08/14] Added a test for the new findPackagesByName method --- .../Test/Repository/ArrayRepositoryTest.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/Composer/Test/Repository/ArrayRepositoryTest.php b/tests/Composer/Test/Repository/ArrayRepositoryTest.php index def78e36e..5e29f5ed6 100644 --- a/tests/Composer/Test/Repository/ArrayRepositoryTest.php +++ b/tests/Composer/Test/Repository/ArrayRepositoryTest.php @@ -50,4 +50,20 @@ class ArrayRepositoryTest extends TestCase $this->assertTrue($repo->hasPackage($this->getPackage('foo', '1'))); $this->assertFalse($repo->hasPackage($this->getPackage('bar', '1'))); } + + public function testFindPackagesByName() + { + $repo = new ArrayRepository(); + $repo->addPackage($this->getPackage('foo', '1')); + $repo->addPackage($this->getPackage('bar', '2')); + $repo->addPackage($this->getPackage('bar', '3')); + + $foo = $repo->findPackagesByName('foo'); + $this->assertCount(1, $foo); + $this->assertEquals('foo', $foo[0]->getName()); + + $bar = $repo->findPackagesByName('bar'); + $this->assertCount(2, $bar); + $this->assertEquals('bar', $bar[0]->getName()); + } } From bca786d5c33eaeb9242b1273a279146ec5f3bbbe Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Mon, 16 Jan 2012 22:40:14 +0100 Subject: [PATCH 09/14] Fixed the tests array_filter preserves the keys even when filtering an array indexed numerically. --- src/Composer/Repository/ArrayRepository.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Composer/Repository/ArrayRepository.php b/src/Composer/Repository/ArrayRepository.php index 8d3898f3d..36ed56b0b 100644 --- a/src/Composer/Repository/ArrayRepository.php +++ b/src/Composer/Repository/ArrayRepository.php @@ -48,10 +48,15 @@ class ArrayRepository implements RepositoryInterface { // normalize name $name = strtolower($name); + $packages = array(); - return array_filter($this->getPackages(), function (PackageInterface $package) use ($name) { - return $package->getName() === $name; - }); + foreach ($this->getPackages() as $package) { + if ($package->getName() === $name) { + $packages[] = $package; + } + } + + return $packages; } /** From 447230d77aa1389285fdea337a9689ad95aa3920 Mon Sep 17 00:00:00 2001 From: Justin Rainbow Date: Mon, 16 Jan 2012 16:42:30 -0700 Subject: [PATCH 10/14] Extracting JsonFile additions for prettifying JSON --- src/Composer/Json/JsonFile.php | 81 +++++++++++++++++++++-- tests/Composer/Test/Json/JsonFileTest.php | 17 +++++ 2 files changed, 92 insertions(+), 6 deletions(-) diff --git a/src/Composer/Json/JsonFile.php b/src/Composer/Json/JsonFile.php index 22aa4d265..6b05dff12 100644 --- a/src/Composer/Json/JsonFile.php +++ b/src/Composer/Json/JsonFile.php @@ -15,11 +15,6 @@ namespace Composer\Json; use Composer\Repository\RepositoryManager; use Composer\Composer; -// defined as of PHP 5.4 -if (!defined('JSON_PRETTY_PRINT')) { - define('JSON_PRETTY_PRINT', 128); -} - /** * Reads/writes json files. * @@ -96,7 +91,81 @@ class JsonFile ); } } - file_put_contents($this->path, json_encode($hash, JSON_PRETTY_PRINT)); + file_put_contents($this->path, $this->encode($hash)); + } + + /** + * Indents a flat JSON string to make it more human-readable + * + * Original code for this function can be found at: + * http://recursive-design.com/blog/2008/03/11/format-json-with-php/ + * + * @param array $hash Data to encode into a formatted JSON string + * @return string Indented version of the original JSON string + */ + public function encode(array $hash) + { + if (defined('JSON_PRETTY_PRINT')) { + return json_encode($hash, JSON_PRETTY_PRINT); + } + + $json = json_encode($hash); + + $result = ''; + $pos = 0; + $strLen = strlen($json); + $indentStr = ' '; + $newLine = "\n"; + $prevChar = ''; + $outOfQuotes = true; + + for ($i = 0; $i <= $strLen; $i++) { + // Grab the next character in the string + $char = substr($json, $i, 1); + + // Are we inside a quoted string? + if ('"' === $char && '\\' !== $prevChar) { + $outOfQuotes = !$outOfQuotes; + } else if (':' === $char && $outOfQuotes) { + // Add a space after the : character + $char .= ' '; + } else if (('}' === $char || ']' === $char) && $outOfQuotes) { + $pos--; + + if ('{' !== $prevChar && '[' !== $prevChar) { + // If this character is the end of an element, + // output a new line and indent the next line + $result .= $newLine; + for ($j = 0; $j < $pos; $j++) { + $result .= $indentStr; + } + } else { + // Collapse empty {} and [] + $result = rtrim($result); + } + } + + // Add the character to the result string + $result .= $char; + + // If the last character was the beginning of an element, + // output a new line and indent the next line + if ((',' === $char || '{' === $char || '[' === $char) && $outOfQuotes) { + $result .= $newLine; + + if ('{' === $char || '[' === $char) { + $pos++; + } + + for ($j = 0; $j < $pos; $j++) { + $result .= $indentStr; + } + } + + $prevChar = $char; + } + + return $result; } /** diff --git a/tests/Composer/Test/Json/JsonFileTest.php b/tests/Composer/Test/Json/JsonFileTest.php index 93f7ecef7..75e798388 100644 --- a/tests/Composer/Test/Json/JsonFileTest.php +++ b/tests/Composer/Test/Json/JsonFileTest.php @@ -84,6 +84,15 @@ class JsonFileTest extends \PHPUnit_Framework_TestCase $this->expectParseException('missing comma on line 2, char 21', $json); } + public function testSimpleJsonString() + { + $data = array('name' => 'composer/composer'); + $json = '{ + "name": "composer\/composer" +}'; + $this->assertJsonFormat($json, $data); + } + private function expectParseException($text, $json) { try { @@ -93,4 +102,12 @@ class JsonFileTest extends \PHPUnit_Framework_TestCase $this->assertContains($text, $e->getMessage()); } } + + private function assertJsonFormat($json, $data) + { + $file = new JsonFile('composer.json'); + + $this->assertEquals($json, $file->encode($data)); + } + } From bfe28905d0994968e38efd2cd8cd4e5b75235a5b Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 17 Jan 2012 01:33:02 +0100 Subject: [PATCH 11/14] Fix formatting and make pretty-printing optional --- src/Composer/Json/JsonFile.php | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/Composer/Json/JsonFile.php b/src/Composer/Json/JsonFile.php index 6b05dff12..03c85250e 100644 --- a/src/Composer/Json/JsonFile.php +++ b/src/Composer/Json/JsonFile.php @@ -75,8 +75,9 @@ class JsonFile * Writes json file. * * @param array $hash writes hash into json file + * @param Boolean $prettyPrint If true, output is pretty-printed */ - public function write(array $hash) + public function write(array $hash, $prettyPrint = true) { $dir = dirname($this->path); if (!is_dir($dir)) { @@ -91,26 +92,31 @@ class JsonFile ); } } - file_put_contents($this->path, $this->encode($hash)); + file_put_contents($this->path, $this->encode($hash, $prettyPrint)); } /** - * Indents a flat JSON string to make it more human-readable + * Encodes an array into (optionally pretty-printed) JSON * * Original code for this function can be found at: * http://recursive-design.com/blog/2008/03/11/format-json-with-php/ * * @param array $hash Data to encode into a formatted JSON string + * @param Boolean $prettyPrint If true, output is pretty-printed * @return string Indented version of the original JSON string */ - public function encode(array $hash) + public function encode(array $hash, $prettyPrint = true) { - if (defined('JSON_PRETTY_PRINT')) { + if ($prettyPrint && defined('JSON_PRETTY_PRINT')) { return json_encode($hash, JSON_PRETTY_PRINT); } $json = json_encode($hash); + if (!$prettyPrint) { + return $json; + } + $result = ''; $pos = 0; $strLen = strlen($json); @@ -126,10 +132,10 @@ class JsonFile // Are we inside a quoted string? if ('"' === $char && '\\' !== $prevChar) { $outOfQuotes = !$outOfQuotes; - } else if (':' === $char && $outOfQuotes) { + } elseif (':' === $char && $outOfQuotes) { // Add a space after the : character $char .= ' '; - } else if (('}' === $char || ']' === $char) && $outOfQuotes) { + } elseif (('}' === $char || ']' === $char) && $outOfQuotes) { $pos--; if ('{' !== $prevChar && '[' !== $prevChar) { From 81f9adc596dc24ae7c5dd8be150369e04d8d8c31 Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Tue, 17 Jan 2012 10:00:53 +0100 Subject: [PATCH 12/14] Refactor Application::bootstrapComposer into a factory class (split from #178) --- src/Composer/Console/Application.php | 100 ++---------------- src/Composer/Factory.php | 147 +++++++++++++++++++++++++++ 2 files changed, 154 insertions(+), 93 deletions(-) create mode 100644 src/Composer/Factory.php diff --git a/src/Composer/Console/Application.php b/src/Composer/Console/Application.php index af68185be..c8bcd67bf 100644 --- a/src/Composer/Console/Application.php +++ b/src/Composer/Console/Application.php @@ -21,11 +21,7 @@ use Symfony\Component\Console\Formatter\OutputFormatterStyle; use Symfony\Component\Finder\Finder; use Composer\Command; use Composer\Composer; -use Composer\Installer; -use Composer\Downloader; -use Composer\Repository; -use Composer\Package; -use Composer\Json\JsonFile; +use Composer\Factory; /** * The console application that handles the commands @@ -73,99 +69,17 @@ class Application extends BaseApplication public function getComposer() { if (null === $this->composer) { - $this->composer = self::bootstrapComposer(); + try { + $this->composer = Factory::create(); + } catch (\InvalidArgumentException $e) { + echo $e->getMessage().PHP_EOL; + exit(1); + } } return $this->composer; } - /** - * Bootstraps a Composer instance - * - * @return Composer - */ - public static function bootstrapComposer($composerFile = null) - { - // load Composer configuration - if (null === $composerFile) { - $composerFile = getenv('COMPOSER') ?: 'composer.json'; - } - - $file = new JsonFile($composerFile); - if (!$file->exists()) { - if ($composerFile === 'composer.json') { - echo 'Composer could not find a composer.json file in '.getcwd().PHP_EOL; - } else { - echo 'Composer could not find the config file: '.$composerFile.PHP_EOL; - } - echo 'To initialize a project, please create a composer.json file as described on the http://packagist.org/ "Getting Started" section'.PHP_EOL; - exit(1); - } - - // Configuration defaults - $composerConfig = array( - 'vendor-dir' => 'vendor', - ); - - $packageConfig = $file->read(); - - if (isset($packageConfig['config']) && is_array($packageConfig['config'])) { - $packageConfig['config'] = array_merge($composerConfig, $packageConfig['config']); - } else { - $packageConfig['config'] = $composerConfig; - } - - $vendorDir = getenv('COMPOSER_VENDOR_DIR') ?: $packageConfig['config']['vendor-dir']; - if (!isset($packageConfig['config']['bin-dir'])) { - $packageConfig['config']['bin-dir'] = $vendorDir.'/bin'; - } - $binDir = getenv('COMPOSER_BIN_DIR') ?: $packageConfig['config']['bin-dir']; - - // initialize repository manager - $rm = new Repository\RepositoryManager(); - $rm->setLocalRepository(new Repository\FilesystemRepository(new JsonFile($vendorDir.'/.composer/installed.json'))); - $rm->setRepositoryClass('composer', 'Composer\Repository\ComposerRepository'); - $rm->setRepositoryClass('vcs', 'Composer\Repository\VcsRepository'); - $rm->setRepositoryClass('pear', 'Composer\Repository\PearRepository'); - $rm->setRepositoryClass('package', 'Composer\Repository\PackageRepository'); - - // initialize download manager - $dm = new Downloader\DownloadManager(); - $dm->setDownloader('git', new Downloader\GitDownloader()); - $dm->setDownloader('svn', new Downloader\SvnDownloader()); - $dm->setDownloader('hg', new Downloader\HgDownloader()); - $dm->setDownloader('pear', new Downloader\PearDownloader()); - $dm->setDownloader('zip', new Downloader\ZipDownloader()); - - // initialize installation manager - $im = new Installer\InstallationManager($vendorDir); - $im->addInstaller(new Installer\LibraryInstaller($vendorDir, $binDir, $dm, $rm->getLocalRepository(), null)); - $im->addInstaller(new Installer\InstallerInstaller($vendorDir, $binDir, $dm, $rm->getLocalRepository(), $im)); - - // load package - $loader = new Package\Loader\RootPackageLoader($rm); - $package = $loader->load($packageConfig); - - // load default repository unless it's explicitly disabled - if (!isset($packageConfig['repositories']['packagist']) || $packageConfig['repositories']['packagist'] !== false) { - $rm->addRepository(new Repository\ComposerRepository(array('url' => 'http://packagist.org'))); - } - - // init locker - $lockFile = substr($composerFile, -5) === '.json' ? substr($composerFile, 0, -4).'lock' : $composerFile . '.lock'; - $locker = new Package\Locker(new JsonFile($lockFile), $rm, md5_file($composerFile)); - - // initialize composer - $composer = new Composer(); - $composer->setPackage($package); - $composer->setLocker($locker); - $composer->setRepositoryManager($rm); - $composer->setDownloadManager($dm); - $composer->setInstallationManager($im); - - return $composer; - } - /** * Initializes all the composer commands */ diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php new file mode 100644 index 000000000..e9fa4c9d6 --- /dev/null +++ b/src/Composer/Factory.php @@ -0,0 +1,147 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer; + +use Composer\Json\JsonFile; + +/** + * Creates an configured instance of composer. + * + * @author Ryan Weaver + * @author Jordi Boggiano + * @author Igor Wiedler + */ +class Factory +{ + protected $vendorDir; + + /** + * Creates a Composer instance + * + * @return Composer + */ + public function createComposer($composerFile = null) + { + // load Composer configuration + if (null === $composerFile) { + $composerFile = getenv('COMPOSER') ?: 'composer.json'; + } + + $file = new JsonFile($composerFile); + if (!$file->exists()) { + if ($composerFile === 'composer.json') { + $message = 'Composer could not find a composer.json file in '.getcwd(); + } else { + $message = 'Composer could not find the config file: '.$composerFile; + } + $instructions = 'To initialize a project, please create a composer.json file as described on the http://packagist.org/ "Getting Started" section'; + throw new \InvalidArgumentException($message.PHP_EOL.$instructions); + } + + $baseDir = rtrim(dirname($composerFile), '/').'/'; + + // Configuration defaults + $composerConfig = array( + 'vendor-dir' => 'vendor', + ); + + $packageConfig = $file->read(); + + if (isset($packageConfig['config']) && is_array($packageConfig['config'])) { + $packageConfig['config'] = array_merge($composerConfig, $packageConfig['config']); + } else { + $packageConfig['config'] = $composerConfig; + } + + $vendorDir = getenv('COMPOSER_VENDOR_DIR') ?: $packageConfig['config']['vendor-dir']; + if (!isset($packageConfig['config']['bin-dir'])) { + $packageConfig['config']['bin-dir'] = $vendorDir.'/bin'; + } + $binDir = getenv('COMPOSER_BIN_DIR') ?: $packageConfig['config']['bin-dir']; + + $this->vendorDir = $baseDir.$vendorDir; + $this->binDir = $baseDir.$binDir; + + // initialize repository manager + $rm = $this->createRepositoryManager(); + + // initialize download manager + $dm = $this->createDownloadManager(); + + // initialize installation manager + $im = $this->createInstallationManager($rm, $dm); + + // load package + $loader = new Package\Loader\RootPackageLoader($rm); + $package = $loader->load($packageConfig); + + // load default repository unless it's explicitly disabled + if (!isset($packageConfig['repositories']['packagist']) || $packageConfig['repositories']['packagist'] !== false) { + $rm->addRepository(new Repository\ComposerRepository(array('url' => 'http://packagist.org'))); + } + + // init locker + $lockFile = substr($composerFile, -5) === '.json' ? substr($composerFile, 0, -4).'lock' : $composerFile . '.lock'; + $locker = new Package\Locker(new JsonFile($lockFile), $rm, md5_file($composerFile)); + + // initialize composer + $composer = new Composer(); + $composer->setPackage($package); + $composer->setLocker($locker); + $composer->setRepositoryManager($rm); + $composer->setDownloadManager($dm); + $composer->setInstallationManager($im); + + return $composer; + } + + protected function createRepositoryManager() + { + $rm = new Repository\RepositoryManager(); + $rm->setLocalRepository(new Repository\FilesystemRepository(new JsonFile($this->vendorDir.'/.composer/installed.json'))); + $rm->setRepositoryClass('composer', 'Composer\Repository\ComposerRepository'); + $rm->setRepositoryClass('vcs', 'Composer\Repository\VcsRepository'); + $rm->setRepositoryClass('pear', 'Composer\Repository\PearRepository'); + $rm->setRepositoryClass('package', 'Composer\Repository\PackageRepository'); + + return $rm; + } + + protected function createDownloadManager() + { + $dm = new Downloader\DownloadManager(); + $dm->setDownloader('git', new Downloader\GitDownloader()); + $dm->setDownloader('svn', new Downloader\SvnDownloader()); + $dm->setDownloader('hg', new Downloader\HgDownloader()); + $dm->setDownloader('pear', new Downloader\PearDownloader()); + $dm->setDownloader('zip', new Downloader\ZipDownloader()); + + return $dm; + } + + protected function createInstallationManager(Repository\RepositoryManager $rm, Downloader\DownloadManager $dm) + { + $im = new Installer\InstallationManager($this->vendorDir); + $im->addInstaller(new Installer\LibraryInstaller($this->vendorDir, $this->binDir, $dm, $rm->getLocalRepository(), null)); + $im->addInstaller(new Installer\InstallerInstaller($this->vendorDir, $this->binDir, $dm, $rm->getLocalRepository(), $im)); + + return $im; + } + + static public function create($composerFile = null) + { + $factory = new static(); + + return $factory->createComposer($composerFile); + } +} From 3bed815b19791afff93abf76ce38af92f3e39040 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 17 Jan 2012 11:54:02 +0100 Subject: [PATCH 13/14] Restore bindir/vendordir behavior, fixes #216 --- src/Composer/Factory.php | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index e9fa4c9d6..d364ae4af 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -23,8 +23,6 @@ use Composer\Json\JsonFile; */ class Factory { - protected $vendorDir; - /** * Creates a Composer instance * @@ -48,8 +46,6 @@ class Factory throw new \InvalidArgumentException($message.PHP_EOL.$instructions); } - $baseDir = rtrim(dirname($composerFile), '/').'/'; - // Configuration defaults $composerConfig = array( 'vendor-dir' => 'vendor', @@ -69,9 +65,6 @@ class Factory } $binDir = getenv('COMPOSER_BIN_DIR') ?: $packageConfig['config']['bin-dir']; - $this->vendorDir = $baseDir.$vendorDir; - $this->binDir = $baseDir.$binDir; - // initialize repository manager $rm = $this->createRepositoryManager(); @@ -79,7 +72,7 @@ class Factory $dm = $this->createDownloadManager(); // initialize installation manager - $im = $this->createInstallationManager($rm, $dm); + $im = $this->createInstallationManager($rm, $dm, $vendorDir, $binDir); // load package $loader = new Package\Loader\RootPackageLoader($rm); @@ -105,10 +98,10 @@ class Factory return $composer; } - protected function createRepositoryManager() + protected function createRepositoryManager($vendorDir) { $rm = new Repository\RepositoryManager(); - $rm->setLocalRepository(new Repository\FilesystemRepository(new JsonFile($this->vendorDir.'/.composer/installed.json'))); + $rm->setLocalRepository(new Repository\FilesystemRepository(new JsonFile($vendorDir.'/.composer/installed.json'))); $rm->setRepositoryClass('composer', 'Composer\Repository\ComposerRepository'); $rm->setRepositoryClass('vcs', 'Composer\Repository\VcsRepository'); $rm->setRepositoryClass('pear', 'Composer\Repository\PearRepository'); @@ -129,11 +122,11 @@ class Factory return $dm; } - protected function createInstallationManager(Repository\RepositoryManager $rm, Downloader\DownloadManager $dm) + protected function createInstallationManager(Repository\RepositoryManager $rm, Downloader\DownloadManager $dm, $vendorDir, $binDir) { - $im = new Installer\InstallationManager($this->vendorDir); - $im->addInstaller(new Installer\LibraryInstaller($this->vendorDir, $this->binDir, $dm, $rm->getLocalRepository(), null)); - $im->addInstaller(new Installer\InstallerInstaller($this->vendorDir, $this->binDir, $dm, $rm->getLocalRepository(), $im)); + $im = new Installer\InstallationManager($vendorDir); + $im->addInstaller(new Installer\LibraryInstaller($vendorDir, $binDir, $dm, $rm->getLocalRepository(), null)); + $im->addInstaller(new Installer\InstallerInstaller($vendorDir, $binDir, $dm, $rm->getLocalRepository(), $im)); return $im; } From d1416a35a2729f790a7325d8c791f67255ea6008 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 17 Jan 2012 12:10:34 +0100 Subject: [PATCH 14/14] Fix missing arg --- src/Composer/Factory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index d364ae4af..f30609ca7 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -66,7 +66,7 @@ class Factory $binDir = getenv('COMPOSER_BIN_DIR') ?: $packageConfig['config']['bin-dir']; // initialize repository manager - $rm = $this->createRepositoryManager(); + $rm = $this->createRepositoryManager($vendorDir); // initialize download manager $dm = $this->createDownloadManager();