Prefer ZipArchive over unzip on Windows

main
Nicolas Grekas 8 years ago
parent 8bf46768f3
commit 08d48cb61a

@ -346,13 +346,9 @@ composer update
See also https://github.com/composer/composer/issues/4180 for more information.
## Zip archives are being reported as corrupted or not unpacked correctly.
## Zip archives are not unpacked correctly.
Composer can unpack zipballs using either a system-provided `unzip` utility or PHP's
native `ZipArchiver` class, preferring the first. The `ZipArchiver` class however is
known to occassionally report valid zip files as corrupted, and does not support certain
advanced features with permissions and symlinks.
If you have issues with zip files you should install a native implementation of unzip
and verify whether the problem persists. If so it is likely a real issue in the file
itself and you should contact the provider.
native `ZipArchiver` class. The `ZipArchiver` class is preferred on Windows. On other
OSes where ZIP files can contain permissions and symlinks, the `unzip` utility is
preferred. You're advised to install it if you need these features.

@ -48,7 +48,18 @@ class ZipDownloader extends ArchiveDownloader
}
if (!class_exists('ZipArchive') && !self::$hasSystemUnzip) {
throw new \RuntimeException('The zip extension and unzip command are both missing, skipping');
// php.ini path is added to the error message to help users find the correct file
$iniPath = php_ini_loaded_file();
if ($iniPath) {
$iniMessage = 'The php.ini used by your command-line PHP is: ' . $iniPath;
} else {
$iniMessage = 'A php.ini file does not exist. You will have to create one.';
}
$error = "The zip extension and unzip command are both missing, skipping.\n" . $iniMessage;
throw new \RuntimeException($error);
}
return parent::download($package, $path);
@ -58,7 +69,7 @@ class ZipDownloader extends ArchiveDownloader
{
$processError = null;
if (self::$hasSystemUnzip) {
if (self::$hasSystemUnzip && !(class_exists('ZipArchive') && Platform::isWindows())) {
$command = 'unzip '.ProcessExecutor::escape($file).' -d '.ProcessExecutor::escape($path);
if (!Platform::isWindows()) {
$command .= ' && chmod -R u+w ' . ProcessExecutor::escape($path);
@ -73,22 +84,10 @@ class ZipDownloader extends ArchiveDownloader
} catch (\Exception $e) {
$processError = 'Failed to execute ' . $command . "\n\n" . $e->getMessage();
}
}
if (!class_exists('ZipArchive')) {
// php.ini path is added to the error message to help users find the correct file
$iniPath = php_ini_loaded_file();
if ($iniPath) {
$iniMessage = 'The php.ini used by your command-line PHP is: ' . $iniPath;
} else {
$iniMessage = 'A php.ini file does not exist. You will have to create one.';
if (!class_exists('ZipArchive')) {
throw new \RuntimeException($processError);
}
$error = "Could not decompress the archive, enable the PHP zip extension or install unzip.\n"
. $iniMessage . ($processError ? "\n" . $processError : '');
throw new \RuntimeException($error);
}
$zipArchive = new ZipArchive();
@ -98,10 +97,7 @@ class ZipDownloader extends ArchiveDownloader
}
if (true !== $zipArchive->extractTo($path)) {
$this->io->writeError("<warn>As there is no 'unzip' command installed zip files are being unpacked using the PHP zip extension.</warn>");
$this->io->writeError("<warn>This may cause invalid reports of corrupted archives. Installing 'unzip' may remediate them.</warn>");
throw new \RuntimeException("There was an error extracting the ZIP file, it is either corrupted or using an invalid format");
throw new \RuntimeException(rtrim("There was an error extracting the ZIP file, it is either corrupted or using an invalid format.\n".$processError));
}
$zipArchive->close();

Loading…
Cancel
Save