From e9fc0e6548b252733282ea09ed33cc614c72cde3 Mon Sep 17 00:00:00 2001 From: Jeremy Benoist Date: Mon, 28 Mar 2016 23:15:13 +0200 Subject: [PATCH 1/2] Re-install binaries on update/install Binaries are re-installed after an update/install (ie: removed and then installed) --- src/Composer/Factory.php | 1 - src/Composer/Installer.php | 6 ++++ .../Installer/InstallationManager.php | 16 ++++++++++ src/Composer/Installer/LibraryInstaller.php | 11 +++++++ .../functional/create-project-command.test | 1 + .../Fixtures/installer/abandoned-listed.test | 1 + .../installer/github-issues-4795-2.test | 1 + .../installer/github-issues-4795.test | 1 + .../Fixtures/installer/suggest-installed.test | 1 + .../Test/Fixtures/installer/suggest-prod.test | 1 + .../Fixtures/installer/suggest-replaced.test | 1 + .../installer/suggest-uninstalled.test | 1 + .../Installer/InstallationManagerTest.php | 29 +++++++++++++++++++ .../Test/Installer/LibraryInstallerTest.php | 26 +++++++++++++++++ 14 files changed, 96 insertions(+), 1 deletion(-) diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index 720a2f066..b87e56d19 100644 --- a/src/Composer/Factory.php +++ b/src/Composer/Factory.php @@ -292,7 +292,6 @@ class Factory } $vendorDir = $config->get('vendor-dir'); - $binDir = $config->get('bin-dir'); // initialize composer $composer = new Composer(); diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 4f118fa89..7ba1ab59a 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -337,6 +337,12 @@ class Installer $this->eventDispatcher->dispatchScript($eventName, $this->devMode); } + // force binaries re-generation + $this->io->writeError('Installing binaries files'); + foreach ($localRepo->getPackages() as $package) { + $this->installationManager->installBinary($package); + } + $vendorDir = $this->config->get('vendor-dir'); if (is_dir($vendorDir)) { // suppress errors as this fails sometimes on OSX for no apparent reason diff --git a/src/Composer/Installer/InstallationManager.php b/src/Composer/Installer/InstallationManager.php index 203f7ec1a..96a194232 100644 --- a/src/Composer/Installer/InstallationManager.php +++ b/src/Composer/Installer/InstallationManager.php @@ -127,6 +127,22 @@ class InstallationManager return $this->getInstaller($package->getType())->isInstalled($repo, $package); } + /** + * Install binary for the given package. + * If the installer associated to this package doesn't handle that function, it'll do nothing. + * + * @param PackageInterface $package Package instance + */ + public function installBinary(PackageInterface $package) + { + try { + $installer = $this->getInstaller($package->getType()); + $installer->installBinary($package); + } catch (\InvalidArgumentException $e) { + // the given installer doesn't support installing binaries + } + } + /** * Executes solver operation. * diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index 241d55eea..0b8444d6a 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -149,6 +149,17 @@ class LibraryInstaller implements InstallerInterface return $basePath . ($targetDir ? '/'.$targetDir : ''); } + /** + * Re-install binary by removing previous one + * + * @param PackageInterface $package Package instance + */ + public function installBinary(PackageInterface $package) + { + $this->binaryInstaller->removeBinaries($package); + $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package)); + } + /** * Returns the base path of the package without target-dir path * diff --git a/tests/Composer/Test/Fixtures/functional/create-project-command.test b/tests/Composer/Test/Fixtures/functional/create-project-command.test index bdb04303c..73b3700ce 100644 --- a/tests/Composer/Test/Fixtures/functional/create-project-command.test +++ b/tests/Composer/Test/Fixtures/functional/create-project-command.test @@ -11,3 +11,4 @@ Updating dependencies (including require-dev) Nothing to install or update Writing lock file Generating autoload files +Installing binaries files diff --git a/tests/Composer/Test/Fixtures/installer/abandoned-listed.test b/tests/Composer/Test/Fixtures/installer/abandoned-listed.test index bc8a0cdb6..d550bfda5 100644 --- a/tests/Composer/Test/Fixtures/installer/abandoned-listed.test +++ b/tests/Composer/Test/Fixtures/installer/abandoned-listed.test @@ -30,6 +30,7 @@ Updating dependencies (including require-dev) Package c/c is abandoned, you should avoid using it. Use b/b instead. Writing lock file Generating autoload files +Installing binaries files --EXPECT-- Installing a/a (1.0.0) diff --git a/tests/Composer/Test/Fixtures/installer/github-issues-4795-2.test b/tests/Composer/Test/Fixtures/installer/github-issues-4795-2.test index 29fc0d38f..7785f4ff2 100644 --- a/tests/Composer/Test/Fixtures/installer/github-issues-4795-2.test +++ b/tests/Composer/Test/Fixtures/installer/github-issues-4795-2.test @@ -38,6 +38,7 @@ Loading composer repositories with package information Updating dependencies (including require-dev) Writing lock file Generating autoload files +Installing binaries files --EXPECT-- Updating a (1.0.0) to a (1.1.0) diff --git a/tests/Composer/Test/Fixtures/installer/github-issues-4795.test b/tests/Composer/Test/Fixtures/installer/github-issues-4795.test index 5a1158f26..739e3fc6c 100644 --- a/tests/Composer/Test/Fixtures/installer/github-issues-4795.test +++ b/tests/Composer/Test/Fixtures/installer/github-issues-4795.test @@ -40,5 +40,6 @@ Updating dependencies (including require-dev) Nothing to install or update Writing lock file Generating autoload files +Installing binaries files --EXPECT-- diff --git a/tests/Composer/Test/Fixtures/installer/suggest-installed.test b/tests/Composer/Test/Fixtures/installer/suggest-installed.test index df573c997..bc16f1fc6 100644 --- a/tests/Composer/Test/Fixtures/installer/suggest-installed.test +++ b/tests/Composer/Test/Fixtures/installer/suggest-installed.test @@ -23,6 +23,7 @@ Loading composer repositories with package information Updating dependencies (including require-dev) Writing lock file Generating autoload files +Installing binaries files --EXPECT-- Installing a/a (1.0.0) diff --git a/tests/Composer/Test/Fixtures/installer/suggest-prod.test b/tests/Composer/Test/Fixtures/installer/suggest-prod.test index 0fe9c8853..853735d58 100644 --- a/tests/Composer/Test/Fixtures/installer/suggest-prod.test +++ b/tests/Composer/Test/Fixtures/installer/suggest-prod.test @@ -21,6 +21,7 @@ Loading composer repositories with package information Updating dependencies Writing lock file Generating autoload files +Installing binaries files --EXPECT-- Installing a/a (1.0.0) diff --git a/tests/Composer/Test/Fixtures/installer/suggest-replaced.test b/tests/Composer/Test/Fixtures/installer/suggest-replaced.test index 38755d7fb..d4cb04000 100644 --- a/tests/Composer/Test/Fixtures/installer/suggest-replaced.test +++ b/tests/Composer/Test/Fixtures/installer/suggest-replaced.test @@ -23,6 +23,7 @@ Loading composer repositories with package information Updating dependencies (including require-dev) Writing lock file Generating autoload files +Installing binaries files --EXPECT-- Installing c/c (1.0.0) diff --git a/tests/Composer/Test/Fixtures/installer/suggest-uninstalled.test b/tests/Composer/Test/Fixtures/installer/suggest-uninstalled.test index fda020699..2b321cb03 100644 --- a/tests/Composer/Test/Fixtures/installer/suggest-uninstalled.test +++ b/tests/Composer/Test/Fixtures/installer/suggest-uninstalled.test @@ -22,6 +22,7 @@ Updating dependencies (including require-dev) a/a suggests installing b/b (an obscure reason) Writing lock file Generating autoload files +Installing binaries files --EXPECT-- Installing a/a (1.0.0) diff --git a/tests/Composer/Test/Installer/InstallationManagerTest.php b/tests/Composer/Test/Installer/InstallationManagerTest.php index 9f31d776c..76fe55c12 100644 --- a/tests/Composer/Test/Installer/InstallationManagerTest.php +++ b/tests/Composer/Test/Installer/InstallationManagerTest.php @@ -240,6 +240,35 @@ class InstallationManagerTest extends \PHPUnit_Framework_TestCase $manager->uninstall($this->repository, $operation); } + public function testInstallBinary() + { + $installer = $this->getMockBuilder('Composer\Installer\LibraryInstaller') + ->disableOriginalConstructor() + ->getMock(); + $manager = new InstallationManager(); + $manager->addInstaller($installer); + + $package = $this->createPackageMock(); + + $package + ->expects($this->once()) + ->method('getType') + ->will($this->returnValue('library')); + + $installer + ->expects($this->once()) + ->method('supports') + ->with('library') + ->will($this->returnValue(true)); + + $installer + ->expects($this->once()) + ->method('installBinary') + ->with($package); + + $manager->installBinary($package); + } + private function createInstallerMock() { return $this->getMockBuilder('Composer\Installer\InstallerInterface') diff --git a/tests/Composer/Test/Installer/LibraryInstallerTest.php b/tests/Composer/Test/Installer/LibraryInstallerTest.php index 257232b0c..8fd0ee60a 100644 --- a/tests/Composer/Test/Installer/LibraryInstallerTest.php +++ b/tests/Composer/Test/Installer/LibraryInstallerTest.php @@ -255,6 +255,32 @@ class LibraryInstallerTest extends TestCase $this->assertEquals($this->vendorDir.'/'.$package->getPrettyName().'/Some/Namespace', $library->getInstallPath($package)); } + /** + * @depends testInstallerCreationShouldNotCreateVendorDirectory + * @depends testInstallerCreationShouldNotCreateBinDirectory + */ + public function testInstallBinary() + { + $binaryInstallerMock = $this->getMockBuilder('Composer\Installer\BinaryInstaller') + ->disableOriginalConstructor() + ->getMock(); + + $library = new LibraryInstaller($this->io, $this->composer, 'library', null, $binaryInstallerMock); + $package = $this->createPackageMock(); + + $binaryInstallerMock + ->expects($this->once()) + ->method('removeBinaries') + ->with($package); + + $binaryInstallerMock + ->expects($this->once()) + ->method('installBinaries') + ->with($package, $library->getInstallPath($package)); + + $library->installBinary($package); + } + protected function createPackageMock() { return $this->getMockBuilder('Composer\Package\Package') From 4f7fbbc879c88e1878551d715e1c537cc56dd410 Mon Sep 17 00:00:00 2001 From: Jeremy Benoist Date: Tue, 31 May 2016 12:19:53 +0200 Subject: [PATCH 2/2] Introduce InstallerBinaryInterface This is an interface for Installer which should support installing binary. ATM there is only the `LibraryInstaller`. It eases the check for supported method when installing binaries for all packages --- src/Composer/Installer.php | 2 +- .../Installer/InstallationManager.php | 9 ++++-- .../Installer/InstallerBinaryInterface.php | 31 +++++++++++++++++++ src/Composer/Installer/LibraryInstaller.php | 2 +- 4 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 src/Composer/Installer/InstallerBinaryInterface.php diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 7ba1ab59a..0a4bda6f0 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -340,7 +340,7 @@ class Installer // force binaries re-generation $this->io->writeError('Installing binaries files'); foreach ($localRepo->getPackages() as $package) { - $this->installationManager->installBinary($package); + $this->installationManager->installBinary($package); } $vendorDir = $this->config->get('vendor-dir'); diff --git a/src/Composer/Installer/InstallationManager.php b/src/Composer/Installer/InstallationManager.php index 96a194232..6734aa7e3 100644 --- a/src/Composer/Installer/InstallationManager.php +++ b/src/Composer/Installer/InstallationManager.php @@ -137,9 +137,14 @@ class InstallationManager { try { $installer = $this->getInstaller($package->getType()); - $installer->installBinary($package); } catch (\InvalidArgumentException $e) { - // the given installer doesn't support installing binaries + // no installer found for the current package type (@see `getInstaller()`) + return; + } + + // if the given installer support installing binaries + if ($installer instanceof InstallerBinaryInterface) { + $installer->installBinary($package); } } diff --git a/src/Composer/Installer/InstallerBinaryInterface.php b/src/Composer/Installer/InstallerBinaryInterface.php new file mode 100644 index 000000000..e87a62bd3 --- /dev/null +++ b/src/Composer/Installer/InstallerBinaryInterface.php @@ -0,0 +1,31 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Installer; + +use Composer\Package\PackageInterface; + +/** + * Interface for the package installation manager that handle binary installation. + * + * @author Konstantin Kudryashov + * @author Jordi Boggiano + */ +interface InstallerBinaryInterface +{ + /** + * Installs binary file for a specific package. + * + * @param PackageInterface $package package instance + */ + public function installBinary(PackageInterface $package); +} diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index 0b8444d6a..bd929062f 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -25,7 +25,7 @@ use Composer\Util\Silencer; * @author Jordi Boggiano * @author Konstantin Kudryashov */ -class LibraryInstaller implements InstallerInterface +class LibraryInstaller implements InstallerInterface, InstallerBinaryInterface { protected $composer; protected $vendorDir;