1
0
Fork 0

Remove junctions first in PathDownloader

When removing a package from a Path repository, ensure Windows junctions
are handled first. This avoids a potential problem using realpath() when
comparing dist and install paths.

See https://bugs.php.net/bug.php?id=77639
pull/9388/head
Jason Stephens 2020-10-30 17:10:24 -05:00
parent 5ad3d5aaf4
commit f486da4578
1 changed files with 8 additions and 10 deletions

View File

@ -178,17 +178,11 @@ class PathDownloader extends FileDownloader implements VcsCapableDownloaderInter
*/ */
public function remove(PackageInterface $package, $path, $output = true) public function remove(PackageInterface $package, $path, $output = true)
{ {
$realUrl = realpath($package->getDistUrl());
if (realpath($path) === $realUrl) {
if ($output) {
$this->io->writeError(" - " . UninstallOperation::format($package).", source is still present in $path");
}
return;
}
/** /**
* realpath() may resolve Windows junctions to the source path, so we'll check for a junction first
* to prevent a false positive when checking if the dist and install paths are the same.
* See https://bugs.php.net/bug.php?id=77639
*
* For junctions don't blindly rely on Filesystem::removeDirectory as it may be overzealous. If a process * 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 * 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. * is disastrous within a junction. So in that case we have no other real choice but to fail hard.
@ -201,6 +195,10 @@ class PathDownloader extends FileDownloader implements VcsCapableDownloaderInter
$this->io->writeError(" <warning>Could not remove junction at " . $path . " - is another process locking it?</warning>"); $this->io->writeError(" <warning>Could not remove junction at " . $path . " - is another process locking it?</warning>");
throw new \RuntimeException('Could not reliably remove junction for package ' . $package->getName()); throw new \RuntimeException('Could not reliably remove junction for package ' . $package->getName());
} }
} elseif (realpath($path) === realpath($package->getDistUrl())) {
if ($output) {
$this->io->writeError(" - " . UninstallOperation::format($package).", source is still present in $path");
}
} else { } else {
parent::remove($package, $path, $output); parent::remove($package, $path, $output);
} }