Fix issue extracting archives into paths that already exist, fixes composer/installers#479
parent
0879e80d56
commit
b451bcb1ac
|
@ -109,6 +109,34 @@ abstract class ArchiveDownloader extends FileDownloader
|
||||||
|
|
||||||
return iterator_to_array($finder);
|
return iterator_to_array($finder);
|
||||||
};
|
};
|
||||||
|
$renameRecursively = null;
|
||||||
|
/**
|
||||||
|
* Renames (and recursively merges if needed) a folder into another one
|
||||||
|
*
|
||||||
|
* For custom installers, where packages may share paths, and given Composer 2's parallelism, we need to make sure
|
||||||
|
* that the source directory gets merged into the target one if the target exists. Otherwise rename() by default would
|
||||||
|
* put the source into the target e.g. src/ => target/src/ (assuming target exists) instead of src/ => target/
|
||||||
|
*
|
||||||
|
* @param string $from Directory
|
||||||
|
* @param string $to Directory
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
$renameRecursively = function ($from, $to) use ($filesystem, $getFolderContent, $package, &$renameRecursively) {
|
||||||
|
$contentDir = $getFolderContent($from);
|
||||||
|
|
||||||
|
// move files back out of the temp dir
|
||||||
|
foreach ($contentDir as $file) {
|
||||||
|
$file = (string) $file;
|
||||||
|
if (is_dir($to . '/' . basename($file))) {
|
||||||
|
if (!is_dir($file)) {
|
||||||
|
throw new \RuntimeException('Installing '.$package.' would lead to overwriting the '.$to.'/'.basename($file).' directory with a file from the package, invalid operation.');
|
||||||
|
}
|
||||||
|
$renameRecursively($file, $to . '/' . basename($file));
|
||||||
|
} else {
|
||||||
|
$filesystem->rename($file, $to . '/' . basename($file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
$renameAsOne = false;
|
$renameAsOne = false;
|
||||||
if (!file_exists($path) || ($filesystem->isDirEmpty($path) && $filesystem->removeDirectory($path))) {
|
if (!file_exists($path) || ($filesystem->isDirEmpty($path) && $filesystem->removeDirectory($path))) {
|
||||||
|
@ -128,15 +156,12 @@ abstract class ArchiveDownloader extends FileDownloader
|
||||||
$filesystem->rename($extractedDir, $path);
|
$filesystem->rename($extractedDir, $path);
|
||||||
} else {
|
} else {
|
||||||
// only one dir in the archive, extract its contents out of it
|
// only one dir in the archive, extract its contents out of it
|
||||||
|
$from = $temporaryDir;
|
||||||
if ($singleDirAtTopLevel) {
|
if ($singleDirAtTopLevel) {
|
||||||
$contentDir = $getFolderContent((string) reset($contentDir));
|
$from = (string) reset($contentDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
// move files back out of the temp dir
|
$renameRecursively($from, $path);
|
||||||
foreach ($contentDir as $file) {
|
|
||||||
$file = (string) $file;
|
|
||||||
$filesystem->rename($file, $path . '/' . basename($file));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$filesystem->removeDirectory($temporaryDir);
|
$filesystem->removeDirectory($temporaryDir);
|
||||||
|
|
Loading…
Reference in New Issue