diff --git a/src/Composer/Downloader/PathDownloader.php b/src/Composer/Downloader/PathDownloader.php
index 1156ff62d..afb3e5de3 100644
--- a/src/Composer/Downloader/PathDownloader.php
+++ b/src/Composer/Downloader/PathDownloader.php
@@ -101,4 +101,25 @@ class PathDownloader extends FileDownloader
$this->io->writeError('');
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public function remove(PackageInterface $package, $path)
+ {
+ /**
+ * For junctions don't blindly rely on Filesystem::removeDirectory as it may be overzealous. If a process
+ * inadvertently locks the file the removal will fail, but it would fall back to recursive delete which
+ * is disastrous within a junction. So in that case we have no other real choice but to fail hard.
+ */
+ if (Platform::isWindows() && $this->filesystem->isJunction($path)) {
+ $this->io->writeError(" - Removing junction for " . $package->getName() . " (" . $package->getFullPrettyVersion() . ")");
+ if (!$this->filesystem->removeJunction($path)) {
+ $this->io->writeError("Could not remove junction at " . $path . " - is another process locking it?");
+ throw new \RuntimeException('Could not reliably remove junction for package ' . $package->getName());
+ }
+ } else {
+ parent::remove($package, $path);
+ }
+ }
}