diff --git a/src/Composer/Installer/InstallationManager.php b/src/Composer/Installer/InstallationManager.php index 01148583a..8cbf62668 100644 --- a/src/Composer/Installer/InstallationManager.php +++ b/src/Composer/Installer/InstallationManager.php @@ -26,6 +26,7 @@ use Composer\DependencyResolver\Operation\MarkAliasInstalledOperation; use Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation; use Composer\EventDispatcher\EventDispatcher; use Composer\Util\Loop; +use Composer\Util\Platform; use React\Promise\PromiseInterface; /** @@ -440,6 +441,8 @@ class InstallationManager $this->waitOnPromises($promises); } + Platform::workaroundFilesystemIssues(); + foreach ($postExecCallbacks as $cb) { $cb(); } diff --git a/src/Composer/Installer/PluginInstaller.php b/src/Composer/Installer/PluginInstaller.php index 5c63a6d1f..e41938816 100644 --- a/src/Composer/Installer/PluginInstaller.php +++ b/src/Composer/Installer/PluginInstaller.php @@ -18,6 +18,7 @@ use Composer\Repository\InstalledRepositoryInterface; use Composer\Package\PackageInterface; use Composer\Util\Filesystem; use Composer\Installer\InstallationManager; +use Composer\Util\Platform; use React\Promise\PromiseInterface; /** @@ -97,6 +98,7 @@ class PluginInstaller extends LibraryInstaller return $promise->then(function () use ($self, $pluginManager, $initial, $target, $repo) { try { + Platform::workaroundFilesystemIssues(); $pluginManager->deactivatePackage($initial, true); $pluginManager->registerPackage($target, true); } catch (\Exception $e) { diff --git a/src/Composer/Util/Platform.php b/src/Composer/Util/Platform.php index aeddce5e6..a18af5356 100644 --- a/src/Composer/Util/Platform.php +++ b/src/Composer/Util/Platform.php @@ -19,6 +19,9 @@ namespace Composer\Util; */ class Platform { + /** @var ?bool */ + private static $isVagrantGuest = null; + /** * Parses tildes and environment variables in paths. * @@ -117,4 +120,37 @@ class Platform // Check if formatted mode is S_IFCHR return $stat ? 0020000 === ($stat['mode'] & 0170000) : false; } + + public static function workaroundFilesystemIssues() + { + if (self::isVagrantGuest()) { + usleep(200000); + } + } + + /** + * Attempts detection of vagrant guest VMs + * + * This works based on the process' user being "vagrant", or the COMPOSER_RUNTIME_ENV env var being set to "vagrant" + * + * @return bool + */ + private static function isVagrantGuest() + { + if (null === self::$isVagrantGuest) { + self::$isVagrantGuest = false; + if (!self::isWindows() && function_exists('posix_getpwuid') && function_exists('posix_geteuid')) { + $processUser = posix_getpwuid(posix_geteuid()); + if ($processUser && $processUser['name'] === 'vagrant') { + return self::$isVagrantGuest = true; + } + } + + if (getenv('COMPOSER_RUNTIME_ENV') === 'vagrant') { + return self::$isVagrantGuest = true; + } + } + + return self::$isVagrantGuest; + } }