src/Composer/Installer.php
private function movePluginsToFront(array $operations)
    {
        $pluginsNoDeps = array();
        $pluginsWithDeps = array();
        $pluginRequires = array();

        foreach (array_reverse($operations, true) as $idx => $op) {
            if ($op instanceof InstallOperation) {
                $package = $op->getPackage();
            } elseif ($op instanceof UpdateOperation) {
                $package = $op->getTargetPackage();
            } else {
                continue;
            }

            // is this package a plugin?
            $isPlugin = $package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer';

            // is this a plugin or a dependency of a plugin?
            if ($isPlugin || count(array_intersect($package->getNames(), $pluginRequires))) {
                // get the package's requires, but filter out any platform requirements or 'composer-plugin-api'
                $requires = array_filter(array_keys($package->getRequires()), function ($req) {
                    return $req !== 'composer-plugin-api' && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req);
                });

                // is this a plugin with no meaningful dependencies?
                if ($isPlugin && !count($requires)) {
                    // plugins with no dependencies go to the very front
                    array_unshift($pluginsNoDeps, $op);
                } else {
                    // capture the requirements for this package so those packages will be moved up as well
                    $pluginRequires = array_merge($pluginRequires, $requires);
                    // move the operation to the front
                    array_unshift($pluginsWithDeps, $op);
                }

                unset($operations[$idx]);
            }
        }

        return array_merge($pluginsNoDeps, $pluginsWithDeps, $operations);
    }
private function movePluginsToFront(array $operations)
    {
        $pluginsNoDeps = array();
        $pluginsWithDeps = array();
        $pluginRequires = array();

        foreach (array_reverse($operations, true) as $idx => $op) {
            if ($op instanceof InstallOperation) {
                $package = $op->getPackage();
            } elseif ($op instanceof UpdateOperation) {
                $package = $op->getTargetPackage();
            } else {
                continue;
            }

            // is this package a plugin?
            $isPlugin = $package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer';

            // is this a plugin or a dependency of a plugin?
            if ($isPlugin || count(array_intersect($package->getNames(), $pluginRequires))) {
                // get the package's requires, but filter out any platform requirements or 'composer-plugin-api'
                $requires = array_filter(array_keys($package->getRequires()), function ($req) {
                    return $req !== 'composer-plugin-api' && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req);
                });

                // is this a plugin with no meaningful dependencies?
                if ($isPlugin && !count($requires)) {
                    // plugins with no dependencies go to the very front
                    array_unshift($pluginsNoDeps, $op);
                } else {
                    // capture the requirements for this package so those packages will be moved up as well
                    $pluginRequires = array_merge($pluginRequires, $requires);
                    // move the operation to the front
                    array_unshift($pluginsWithDeps, $op);
                }

                unset($operations[$idx]);
            }
        }

        return array_merge($pluginsNoDeps, $pluginsWithDeps, $operations);
    }
private function movePluginsToFront ( array $ operations ) { $ pluginsNoDeps = array ( ) ; $ pluginsWithDeps = array ( ) ; $ pluginRequires = array ( ) ; foreach ( array_reverse ( $ operations , true ) as $ idx => $ op ) { if ( $ op instanceof InstallOperation ) { $ package = $ op -> getPackage ( ) ; } elseif ( $ op instanceof UpdateOperation ) { $ package = $ op -> getTargetPackage ( ) ; } else { continue ; } // is this package a plugin? $ isPlugin = $ package -> getType ( ) === 'composer-plugin' || $ package -> getType ( ) === 'composer-installer' ; // is this a plugin or a dependency of a plugin? if ( $ isPlugin || count ( array_intersect ( $ package -> getNames ( ) , $ pluginRequires ) ) ) { // get the package's requires, but filter out any platform requirements or 'composer-plugin-api' $ requires = array_filter ( array_keys ( $ package -> getRequires ( ) ) , function ( $ req ) { return $ req !== 'composer-plugin-api' && ! preg_match ( PlatformRepository :: PLATFORM_PACKAGE_REGEX , $ req ) ; } ) ; // is this a plugin with no meaningful dependencies? if ( $ isPlugin && ! count ( $ requires ) ) { // plugins with no dependencies go to the very front array_unshift ( $ pluginsNoDeps , $ op ) ; } else { // capture the requirements for this package so those packages will be moved up as well $ pluginRequires = array_merge ( $ pluginRequires , $ requires ) ; // move the operation to the front array_unshift ( $ pluginsWithDeps , $ op ) ; } unset ( $ operations [ $ idx ] ) ; } } return array_merge ( $ pluginsNoDeps , $ pluginsWithDeps , $ operations ) ; }
Workaround: if your packages depend on plugins, we must be sure
that those are installed / updated first; else it would lead to packages
being installed multiple times in different folders, when running Composer
twice.

While this does not fix the root-causes of https://github.com/composer/composer/issues/1147,
it at least fixes the symptoms and makes usage of composer possible (again)
in such scenarios.

@param  OperationInterface[] $operations
@return OperationInterface[] reordered operation list
Workaround : if your packages depend on plugins we must be sure that those are installed / updated first ; else it would lead to packages being installed multiple times in different folders when running Composer twice .