From 30e89a2402489a9ca40fc2ce039af45601a16744 Mon Sep 17 00:00:00 2001 From: digitalkaoz Date: Mon, 23 Jan 2012 15:19:05 +0100 Subject: [PATCH 1/3] fixed broken packages on filesystem --- src/Composer/Command/InstallCommand.php | 6 +- .../Operation/ReplaceOperation.php | 66 +++++++++++++++++++ .../Installer/InstallationManager.php | 12 ++++ src/Composer/Installer/InstallerInterface.php | 7 ++ src/Composer/Installer/LibraryInstaller.php | 19 +++++- src/Composer/Package/BasePackage.php | 11 ++++ .../installer-v1/Installer/Custom.php | 1 + .../installer-v2/Installer/Custom2.php | 1 + .../installer-v3/Installer/Custom2.php | 1 + .../Test/Installer/LibraryInstallerTest.php | 24 +++++++ 10 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 src/Composer/DependencyResolver/Operation/ReplaceOperation.php diff --git a/src/Composer/Command/InstallCommand.php b/src/Composer/Command/InstallCommand.php index bf8bca726..dbacf89d5 100644 --- a/src/Composer/Command/InstallCommand.php +++ b/src/Composer/Command/InstallCommand.php @@ -23,6 +23,7 @@ use Composer\Repository\PlatformRepository; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +use Composer\DependencyResolver\Operation\ReplaceOperation; /** * @author Jordi Boggiano @@ -132,7 +133,10 @@ EOT // TODO this belongs in the solver, but this will do for now to report top-level deps missing at least foreach ($request->getJobs() as $job) { if ('install' === $job['cmd']) { - foreach ($installedRepo->getPackages() as $package) { + foreach ($installedRepo->getPackages() as $package ) { + if ($installedRepo->hasPackage($package) && !$package->isPlatform() && !$installationManager->isPackageInstalled($package)) { + $operations[$job['packageName']] = new ReplaceOperation($package, \Composer\DependencyResolver\Solver::RULE_PACKAGE_NOT_EXIST); + } if (in_array($job['packageName'], $package->getNames())) { continue 2; } diff --git a/src/Composer/DependencyResolver/Operation/ReplaceOperation.php b/src/Composer/DependencyResolver/Operation/ReplaceOperation.php new file mode 100644 index 000000000..1944355ac --- /dev/null +++ b/src/Composer/DependencyResolver/Operation/ReplaceOperation.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\DependencyResolver\Operation; + +use Composer\Package\PackageInterface; + +/** + * Solver replace operation. + * + * @author Robert Schönthal + */ +class ReplaceOperation extends SolverOperation +{ + protected $package; + + /** + * Initializes operation. + * + * @param PackageInterface $package package instance + * @param string $reason operation reason + */ + public function __construct(PackageInterface $package, $reason = null) + { + parent::__construct($reason); + + $this->package = $package; + } + + /** + * Returns package instance. + * + * @return PackageInterface + */ + public function getPackage() + { + return $this->package; + } + + /** + * Returns job type. + * + * @return string + */ + public function getJobType() + { + return 'replace'; + } + + /** + * {@inheritDoc} + */ + public function __toString() + { + return 'Replacing '.$this->package->getPrettyName().' ('.$this->package->getPrettyVersion().')'; + } +} diff --git a/src/Composer/Installer/InstallationManager.php b/src/Composer/Installer/InstallationManager.php index 2acb09d5b..2e7404299 100644 --- a/src/Composer/Installer/InstallationManager.php +++ b/src/Composer/Installer/InstallationManager.php @@ -17,6 +17,7 @@ use Composer\DependencyResolver\Operation\OperationInterface; use Composer\DependencyResolver\Operation\InstallOperation; use Composer\DependencyResolver\Operation\UpdateOperation; use Composer\DependencyResolver\Operation\UninstallOperation; +use Composer\DependencyResolver\Operation\ReplaceOperation; /** * Package operation manager. @@ -160,6 +161,17 @@ class InstallationManager $installer->uninstall($operation->getPackage()); } + /** + * Replaces package. + * + * @param ReplaceOperation $operation operation instance + */ + public function replace(ReplaceOperation $operation) + { + $installer = $this->getInstaller($operation->getPackage()->getType()); + $installer->replace($operation->getPackage()); + } + /** * Returns the installation path of a package * diff --git a/src/Composer/Installer/InstallerInterface.php b/src/Composer/Installer/InstallerInterface.php index 36c023b3b..9e8eafdf1 100644 --- a/src/Composer/Installer/InstallerInterface.php +++ b/src/Composer/Installer/InstallerInterface.php @@ -63,6 +63,13 @@ interface InstallerInterface */ function uninstall(PackageInterface $package); + /** + * Replaces specific package. + * + * @param PackageInterface $package package instance + */ + function replace(PackageInterface $package); + /** * Returns the installation path of a package * diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index 319ac9e98..33624cb47 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -72,7 +72,7 @@ class LibraryInstaller implements InstallerInterface */ public function isInstalled(PackageInterface $package) { - return $this->repository->hasPackage($package); + return $this->repository->hasPackage($package) && is_readable($this->getInstallPath($package)); } /** @@ -123,6 +123,23 @@ class LibraryInstaller implements InstallerInterface $this->repository->removePackage($package); } + /** + * {@inheritDoc} + */ + public function replace(PackageInterface $package) + { + if (!$this->repository->hasPackage($package)) { + throw new \InvalidArgumentException('Package is not installed: '.$package); + } + + $downloadPath = $this->getInstallPath($package); + + $this->removeBinaries($package); + + $this->downloadManager->download($package, $downloadPath); + $this->installBinaries($package); + } + /** * {@inheritDoc} */ diff --git a/src/Composer/Package/BasePackage.php b/src/Composer/Package/BasePackage.php index 786c58ae5..d5a0e5230 100644 --- a/src/Composer/Package/BasePackage.php +++ b/src/Composer/Package/BasePackage.php @@ -15,6 +15,7 @@ namespace Composer\Package; use Composer\Package\LinkConstraint\LinkConstraintInterface; use Composer\Package\LinkConstraint\VersionConstraint; use Composer\Repository\RepositoryInterface; +use Composer\Repository\PlatformRepository; /** * Base class for packages providing name storage and default match implementation @@ -134,6 +135,16 @@ abstract class BasePackage implements PackageInterface $this->repository = $repository; } + /** + * checks if this package is a platform package + * + * @return boolean + */ + public function isPlatform() + { + return $this->getRepository() instanceof PlatformRepository; + } + /** * Returns package unique name, constructed from name, version and release type. * diff --git a/tests/Composer/Test/Installer/Fixtures/installer-v1/Installer/Custom.php b/tests/Composer/Test/Installer/Fixtures/installer-v1/Installer/Custom.php index 4bb58ded8..393261893 100644 --- a/tests/Composer/Test/Installer/Fixtures/installer-v1/Installer/Custom.php +++ b/tests/Composer/Test/Installer/Fixtures/installer-v1/Installer/Custom.php @@ -14,5 +14,6 @@ class Custom implements InstallerInterface public function install(PackageInterface $package) {} public function update(PackageInterface $initial, PackageInterface $target) {} public function uninstall(PackageInterface $package) {} + public function replace(PackageInterface $package) {} public function getInstallPath(PackageInterface $package) {} } diff --git a/tests/Composer/Test/Installer/Fixtures/installer-v2/Installer/Custom2.php b/tests/Composer/Test/Installer/Fixtures/installer-v2/Installer/Custom2.php index edd264428..b454cbcfd 100644 --- a/tests/Composer/Test/Installer/Fixtures/installer-v2/Installer/Custom2.php +++ b/tests/Composer/Test/Installer/Fixtures/installer-v2/Installer/Custom2.php @@ -14,5 +14,6 @@ class Custom2 implements InstallerInterface public function install(PackageInterface $package) {} public function update(PackageInterface $initial, PackageInterface $target) {} public function uninstall(PackageInterface $package) {} + public function replace(PackageInterface $package) {} public function getInstallPath(PackageInterface $package) {} } diff --git a/tests/Composer/Test/Installer/Fixtures/installer-v3/Installer/Custom2.php b/tests/Composer/Test/Installer/Fixtures/installer-v3/Installer/Custom2.php index db211bed5..8e58c436e 100644 --- a/tests/Composer/Test/Installer/Fixtures/installer-v3/Installer/Custom2.php +++ b/tests/Composer/Test/Installer/Fixtures/installer-v3/Installer/Custom2.php @@ -14,5 +14,6 @@ class Custom2 implements InstallerInterface public function install(PackageInterface $package) {} public function update(PackageInterface $initial, PackageInterface $target) {} public function uninstall(PackageInterface $package) {} + public function replace(PackageInterface $package) {} public function getInstallPath(PackageInterface $package) {} } diff --git a/tests/Composer/Test/Installer/LibraryInstallerTest.php b/tests/Composer/Test/Installer/LibraryInstallerTest.php index ed655f983..0f85c4b21 100644 --- a/tests/Composer/Test/Installer/LibraryInstallerTest.php +++ b/tests/Composer/Test/Installer/LibraryInstallerTest.php @@ -175,6 +175,30 @@ class LibraryInstallerTest extends \PHPUnit_Framework_TestCase $library->uninstall($package); } + public function testReplace() + { + $library = new LibraryInstaller($this->vendorDir, $this->binDir, $this->dm, $this->repository, $this->io); + $package = $this->createPackageMock(); + + $package + ->expects($this->once()) + ->method('getPrettyName') + ->will($this->returnValue('pkg')); + + $this->repository + ->expects($this->once()) + ->method('hasPackage') + ->with($package) + ->will($this->onConsecutiveCalls(true, false)); + + $this->dm + ->expects($this->once()) + ->method('download') + ->with($package, $this->vendorDir.'/pkg'); + + $library->replace($package); + } + public function testGetInstallPath() { $library = new LibraryInstaller($this->vendorDir, $this->binDir, $this->dm, $this->repository, $this->io); From 4d0fae688ea749717acfe51a4856a47df014a037 Mon Sep 17 00:00:00 2001 From: digitalkaoz Date: Mon, 23 Jan 2012 15:43:42 +0100 Subject: [PATCH 2/3] removed replace, reinstalling as install --- src/Composer/Command/InstallCommand.php | 4 +- .../Operation/ReplaceOperation.php | 66 ------------------- .../Installer/InstallationManager.php | 11 ---- src/Composer/Installer/InstallerInterface.php | 7 -- src/Composer/Installer/LibraryInstaller.php | 30 ++++----- .../installer-v1/Installer/Custom.php | 1 - .../installer-v2/Installer/Custom2.php | 1 - .../installer-v3/Installer/Custom2.php | 1 - .../Test/Installer/LibraryInstallerTest.php | 26 +------- 9 files changed, 14 insertions(+), 133 deletions(-) delete mode 100644 src/Composer/DependencyResolver/Operation/ReplaceOperation.php diff --git a/src/Composer/Command/InstallCommand.php b/src/Composer/Command/InstallCommand.php index dbacf89d5..10a54cd06 100644 --- a/src/Composer/Command/InstallCommand.php +++ b/src/Composer/Command/InstallCommand.php @@ -23,7 +23,7 @@ use Composer\Repository\PlatformRepository; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -use Composer\DependencyResolver\Operation\ReplaceOperation; +use Composer\DependencyResolver\Operation\InstallOperation; /** * @author Jordi Boggiano @@ -135,7 +135,7 @@ EOT if ('install' === $job['cmd']) { foreach ($installedRepo->getPackages() as $package ) { if ($installedRepo->hasPackage($package) && !$package->isPlatform() && !$installationManager->isPackageInstalled($package)) { - $operations[$job['packageName']] = new ReplaceOperation($package, \Composer\DependencyResolver\Solver::RULE_PACKAGE_NOT_EXIST); + $operations[$job['packageName']] = new InstallOperation($package, \Composer\DependencyResolver\Solver::RULE_PACKAGE_NOT_EXIST); } if (in_array($job['packageName'], $package->getNames())) { continue 2; diff --git a/src/Composer/DependencyResolver/Operation/ReplaceOperation.php b/src/Composer/DependencyResolver/Operation/ReplaceOperation.php deleted file mode 100644 index 1944355ac..000000000 --- a/src/Composer/DependencyResolver/Operation/ReplaceOperation.php +++ /dev/null @@ -1,66 +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\DependencyResolver\Operation; - -use Composer\Package\PackageInterface; - -/** - * Solver replace operation. - * - * @author Robert Schönthal - */ -class ReplaceOperation extends SolverOperation -{ - protected $package; - - /** - * Initializes operation. - * - * @param PackageInterface $package package instance - * @param string $reason operation reason - */ - public function __construct(PackageInterface $package, $reason = null) - { - parent::__construct($reason); - - $this->package = $package; - } - - /** - * Returns package instance. - * - * @return PackageInterface - */ - public function getPackage() - { - return $this->package; - } - - /** - * Returns job type. - * - * @return string - */ - public function getJobType() - { - return 'replace'; - } - - /** - * {@inheritDoc} - */ - public function __toString() - { - return 'Replacing '.$this->package->getPrettyName().' ('.$this->package->getPrettyVersion().')'; - } -} diff --git a/src/Composer/Installer/InstallationManager.php b/src/Composer/Installer/InstallationManager.php index 2e7404299..04f8b73ec 100644 --- a/src/Composer/Installer/InstallationManager.php +++ b/src/Composer/Installer/InstallationManager.php @@ -161,17 +161,6 @@ class InstallationManager $installer->uninstall($operation->getPackage()); } - /** - * Replaces package. - * - * @param ReplaceOperation $operation operation instance - */ - public function replace(ReplaceOperation $operation) - { - $installer = $this->getInstaller($operation->getPackage()->getType()); - $installer->replace($operation->getPackage()); - } - /** * Returns the installation path of a package * diff --git a/src/Composer/Installer/InstallerInterface.php b/src/Composer/Installer/InstallerInterface.php index 9e8eafdf1..36c023b3b 100644 --- a/src/Composer/Installer/InstallerInterface.php +++ b/src/Composer/Installer/InstallerInterface.php @@ -63,13 +63,6 @@ interface InstallerInterface */ function uninstall(PackageInterface $package); - /** - * Replaces specific package. - * - * @param PackageInterface $package package instance - */ - function replace(PackageInterface $package); - /** * Returns the installation path of a package * diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index 33624cb47..8aae018c1 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -80,11 +80,20 @@ class LibraryInstaller implements InstallerInterface */ public function install(PackageInterface $package) { - $downloadPath = $this->getInstallPath($package); + $broken = !is_readable($this->getInstallPath($package)); + + //remove the binaries first if its missing on filesystem + if ($broken) { + $this->removeBinaries($package); + } + $downloadPath = $this->getInstallPath($package); $this->downloadManager->download($package, $downloadPath); $this->installBinaries($package); - $this->repository->addPackage(clone $package); + + if($broken) { + $this->repository->addPackage(clone $package); + } } /** @@ -123,23 +132,6 @@ class LibraryInstaller implements InstallerInterface $this->repository->removePackage($package); } - /** - * {@inheritDoc} - */ - public function replace(PackageInterface $package) - { - if (!$this->repository->hasPackage($package)) { - throw new \InvalidArgumentException('Package is not installed: '.$package); - } - - $downloadPath = $this->getInstallPath($package); - - $this->removeBinaries($package); - - $this->downloadManager->download($package, $downloadPath); - $this->installBinaries($package); - } - /** * {@inheritDoc} */ diff --git a/tests/Composer/Test/Installer/Fixtures/installer-v1/Installer/Custom.php b/tests/Composer/Test/Installer/Fixtures/installer-v1/Installer/Custom.php index 393261893..4bb58ded8 100644 --- a/tests/Composer/Test/Installer/Fixtures/installer-v1/Installer/Custom.php +++ b/tests/Composer/Test/Installer/Fixtures/installer-v1/Installer/Custom.php @@ -14,6 +14,5 @@ class Custom implements InstallerInterface public function install(PackageInterface $package) {} public function update(PackageInterface $initial, PackageInterface $target) {} public function uninstall(PackageInterface $package) {} - public function replace(PackageInterface $package) {} public function getInstallPath(PackageInterface $package) {} } diff --git a/tests/Composer/Test/Installer/Fixtures/installer-v2/Installer/Custom2.php b/tests/Composer/Test/Installer/Fixtures/installer-v2/Installer/Custom2.php index b454cbcfd..edd264428 100644 --- a/tests/Composer/Test/Installer/Fixtures/installer-v2/Installer/Custom2.php +++ b/tests/Composer/Test/Installer/Fixtures/installer-v2/Installer/Custom2.php @@ -14,6 +14,5 @@ class Custom2 implements InstallerInterface public function install(PackageInterface $package) {} public function update(PackageInterface $initial, PackageInterface $target) {} public function uninstall(PackageInterface $package) {} - public function replace(PackageInterface $package) {} public function getInstallPath(PackageInterface $package) {} } diff --git a/tests/Composer/Test/Installer/Fixtures/installer-v3/Installer/Custom2.php b/tests/Composer/Test/Installer/Fixtures/installer-v3/Installer/Custom2.php index 8e58c436e..db211bed5 100644 --- a/tests/Composer/Test/Installer/Fixtures/installer-v3/Installer/Custom2.php +++ b/tests/Composer/Test/Installer/Fixtures/installer-v3/Installer/Custom2.php @@ -14,6 +14,5 @@ class Custom2 implements InstallerInterface public function install(PackageInterface $package) {} public function update(PackageInterface $initial, PackageInterface $target) {} public function uninstall(PackageInterface $package) {} - public function replace(PackageInterface $package) {} public function getInstallPath(PackageInterface $package) {} } diff --git a/tests/Composer/Test/Installer/LibraryInstallerTest.php b/tests/Composer/Test/Installer/LibraryInstallerTest.php index 0f85c4b21..c5cb9d538 100644 --- a/tests/Composer/Test/Installer/LibraryInstallerTest.php +++ b/tests/Composer/Test/Installer/LibraryInstallerTest.php @@ -85,7 +85,7 @@ class LibraryInstallerTest extends \PHPUnit_Framework_TestCase $package = $this->createPackageMock(); $package - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getPrettyName') ->will($this->returnValue('some/package')); @@ -175,30 +175,6 @@ class LibraryInstallerTest extends \PHPUnit_Framework_TestCase $library->uninstall($package); } - public function testReplace() - { - $library = new LibraryInstaller($this->vendorDir, $this->binDir, $this->dm, $this->repository, $this->io); - $package = $this->createPackageMock(); - - $package - ->expects($this->once()) - ->method('getPrettyName') - ->will($this->returnValue('pkg')); - - $this->repository - ->expects($this->once()) - ->method('hasPackage') - ->with($package) - ->will($this->onConsecutiveCalls(true, false)); - - $this->dm - ->expects($this->once()) - ->method('download') - ->with($package, $this->vendorDir.'/pkg'); - - $library->replace($package); - } - public function testGetInstallPath() { $library = new LibraryInstaller($this->vendorDir, $this->binDir, $this->dm, $this->repository, $this->io); From 3d43bdce4526f9826ab92fb68bba2ba8636fedcc Mon Sep 17 00:00:00 2001 From: digitalkaoz Date: Mon, 23 Jan 2012 16:17:57 +0100 Subject: [PATCH 3/3] refactored install --- src/Composer/Command/InstallCommand.php | 3 ++- src/Composer/Installer/InstallationManager.php | 1 - src/Composer/Installer/LibraryInstaller.php | 6 ++---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Composer/Command/InstallCommand.php b/src/Composer/Command/InstallCommand.php index 10a54cd06..2a26f48c0 100644 --- a/src/Composer/Command/InstallCommand.php +++ b/src/Composer/Command/InstallCommand.php @@ -24,6 +24,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Composer\DependencyResolver\Operation\InstallOperation; +use Composer\DependencyResolver\Solver; /** * @author Jordi Boggiano @@ -135,7 +136,7 @@ EOT if ('install' === $job['cmd']) { foreach ($installedRepo->getPackages() as $package ) { if ($installedRepo->hasPackage($package) && !$package->isPlatform() && !$installationManager->isPackageInstalled($package)) { - $operations[$job['packageName']] = new InstallOperation($package, \Composer\DependencyResolver\Solver::RULE_PACKAGE_NOT_EXIST); + $operations[$job['packageName']] = new InstallOperation($package, Solver::RULE_PACKAGE_NOT_EXIST); } if (in_array($job['packageName'], $package->getNames())) { continue 2; diff --git a/src/Composer/Installer/InstallationManager.php b/src/Composer/Installer/InstallationManager.php index 04f8b73ec..2acb09d5b 100644 --- a/src/Composer/Installer/InstallationManager.php +++ b/src/Composer/Installer/InstallationManager.php @@ -17,7 +17,6 @@ use Composer\DependencyResolver\Operation\OperationInterface; use Composer\DependencyResolver\Operation\InstallOperation; use Composer\DependencyResolver\Operation\UpdateOperation; use Composer\DependencyResolver\Operation\UninstallOperation; -use Composer\DependencyResolver\Operation\ReplaceOperation; /** * Package operation manager. diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index 8aae018c1..f9c4828fb 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -80,10 +80,8 @@ class LibraryInstaller implements InstallerInterface */ public function install(PackageInterface $package) { - $broken = !is_readable($this->getInstallPath($package)); - //remove the binaries first if its missing on filesystem - if ($broken) { + if (!is_readable($this->getInstallPath($package)) && $this->repository->hasPackage($package)) { $this->removeBinaries($package); } @@ -91,7 +89,7 @@ class LibraryInstaller implements InstallerInterface $this->downloadManager->download($package, $downloadPath); $this->installBinaries($package); - if($broken) { + if(!$this->repository->hasPackage($package)) { $this->repository->addPackage(clone $package); } }