Bläddra i källkod

fixed broken packages on filesystem

digitalkaoz 13 år sedan
förälder
incheckning
30e89a2402

+ 5 - 1
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 <j.boggiano@seld.be>
@@ -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;
                     }

+ 66 - 0
src/Composer/DependencyResolver/Operation/ReplaceOperation.php

@@ -0,0 +1,66 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ *     Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * 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 <seroscho@googlemail.com>
+ */
+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().')';
+    }
+}

+ 12 - 0
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
      *

+ 7 - 0
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
      *

+ 18 - 1
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}
      */

+ 11 - 0
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.
      *

+ 1 - 0
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) {}
 }

+ 1 - 0
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) {}
 }

+ 1 - 0
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) {}
 }

+ 24 - 0
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);