Introduce a cross-platform safe version of is_readable to support UNC / wsl$ paths on Windows (#9861)
parent
bfea0f7d1e
commit
3380178798
|
@ -346,7 +346,7 @@ EOF;
|
|||
$classmapFile .= ");\n";
|
||||
|
||||
if (!$suffix) {
|
||||
if (!$config->get('autoloader-suffix') && is_readable($vendorPath.'/autoload.php')) {
|
||||
if (!$config->get('autoloader-suffix') && Filesystem::isReadable($vendorPath.'/autoload.php')) {
|
||||
$content = file_get_contents($vendorPath.'/autoload.php');
|
||||
if (preg_match('{ComposerAutoloaderInit([^:\s]+)::}', $content, $match)) {
|
||||
$suffix = $match[1];
|
||||
|
@ -1131,7 +1131,7 @@ INITIALIZER;
|
|||
|
||||
foreach ($autoload[$type] as $namespace => $paths) {
|
||||
foreach ((array) $paths as $path) {
|
||||
if (($type === 'files' || $type === 'classmap' || $type === 'exclude-from-classmap') && $package->getTargetDir() && !is_readable($installPath.'/'.$path)) {
|
||||
if (($type === 'files' || $type === 'classmap' || $type === 'exclude-from-classmap') && $package->getTargetDir() && !Filesystem::isReadable($installPath.'/'.$path)) {
|
||||
// remove target-dir from file paths of the root package
|
||||
if ($package === $rootPackage) {
|
||||
$targetDir = str_replace('\\<dirsep\\>', '[\\\\/]', preg_quote(str_replace(array('/', '\\'), '<dirsep>', $package->getTargetDir())));
|
||||
|
|
|
@ -225,7 +225,7 @@ class ClassMapGenerator
|
|||
if (!$contents) {
|
||||
if (!file_exists($path)) {
|
||||
$message = 'File at "%s" does not exist, check your classmap definitions';
|
||||
} elseif (!is_readable($path)) {
|
||||
} elseif (!Filesystem::isReadable($path)) {
|
||||
$message = 'File at "%s" is not readable, check its permissions';
|
||||
} elseif ('' === trim(file_get_contents($path))) {
|
||||
// The input file was really empty and thus contains no classes
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
namespace Composer\Command;
|
||||
|
||||
use Composer\Util\Filesystem;
|
||||
use Composer\Util\Platform;
|
||||
use Composer\Util\Silencer;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
@ -411,7 +412,7 @@ EOT
|
|||
'secure-http' => array($booleanValidator, $booleanNormalizer),
|
||||
'cafile' => array(
|
||||
function ($val) {
|
||||
return file_exists($val) && is_readable($val);
|
||||
return file_exists($val) && Filesystem::isReadable($val);
|
||||
},
|
||||
function ($val) {
|
||||
return $val === 'null' ? null : $val;
|
||||
|
@ -419,7 +420,7 @@ EOT
|
|||
),
|
||||
'capath' => array(
|
||||
function ($val) {
|
||||
return is_dir($val) && is_readable($val);
|
||||
return is_dir($val) && Filesystem::isReadable($val);
|
||||
},
|
||||
function ($val) {
|
||||
return $val === 'null' ? null : $val;
|
||||
|
|
|
@ -796,7 +796,7 @@ EOT
|
|||
}
|
||||
|
||||
$file = Factory::getComposerFile();
|
||||
if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
|
||||
if (is_file($file) && Filesystem::isReadable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
|
||||
if (!empty($composer['minimum-stability'])) {
|
||||
return VersionParser::normalizeStability($composer['minimum-stability']);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
namespace Composer\Command;
|
||||
|
||||
use Composer\DependencyResolver\Request;
|
||||
use Composer\Util\Filesystem;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
@ -119,9 +120,7 @@ EOT
|
|||
|
||||
return 1;
|
||||
}
|
||||
// check for readability by reading the file as is_readable can not be trusted on network-mounts
|
||||
// see https://github.com/composer/composer/issues/8231 and https://bugs.php.net/bug.php?id=68926
|
||||
if (!is_readable($this->file) && false === Silencer::call('file_get_contents', $this->file)) {
|
||||
if (!Filesystem::isReadable($this->file)) {
|
||||
$io->writeError('<error>'.$this->file.' is not readable.</error>');
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -381,7 +381,7 @@ TAGSPUBKEY
|
|||
if (!is_file($oldFile)) {
|
||||
throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be found');
|
||||
}
|
||||
if (!is_readable($oldFile)) {
|
||||
if (!Filesystem::isReadable($oldFile)) {
|
||||
throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be read');
|
||||
}
|
||||
|
||||
|
@ -582,7 +582,7 @@ EOT;
|
|||
@unlink($script);
|
||||
|
||||
// see if the file was moved and is still accessible
|
||||
if ($result = is_readable($localFilename) && (hash_file('sha256', $localFilename) === $checksum)) {
|
||||
if ($result = Filesystem::isReadable($localFilename) && (hash_file('sha256', $localFilename) === $checksum)) {
|
||||
$io->writeError('<info>Operation succeeded.</info>');
|
||||
@unlink($newFilename);
|
||||
} else {
|
||||
|
|
|
@ -17,6 +17,7 @@ use Composer\Package\Loader\ValidatingArrayLoader;
|
|||
use Composer\Plugin\CommandEvent;
|
||||
use Composer\Plugin\PluginEvents;
|
||||
use Composer\Util\ConfigValidator;
|
||||
use Composer\Util\Filesystem;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
@ -77,7 +78,7 @@ EOT
|
|||
|
||||
return 3;
|
||||
}
|
||||
if (!is_readable($file)) {
|
||||
if (!Filesystem::isReadable($file)) {
|
||||
$io->writeError('<error>' . $file . ' is not readable.</error>');
|
||||
|
||||
return 3;
|
||||
|
|
|
@ -15,6 +15,7 @@ namespace Composer\Config;
|
|||
use Composer\Json\JsonFile;
|
||||
use Composer\Json\JsonManipulator;
|
||||
use Composer\Json\JsonValidationException;
|
||||
use Composer\Util\Filesystem;
|
||||
use Composer\Util\Silencer;
|
||||
|
||||
/**
|
||||
|
@ -217,7 +218,7 @@ class JsonConfigSource implements ConfigSourceInterface
|
|||
throw new \RuntimeException(sprintf('The file "%s" is not writable.', $this->file->getPath()));
|
||||
}
|
||||
|
||||
if (!is_readable($this->file->getPath())) {
|
||||
if (!Filesystem::isReadable($this->file->getPath())) {
|
||||
throw new \RuntimeException(sprintf('The file "%s" is not readable.', $this->file->getPath()));
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
namespace Composer\Console;
|
||||
|
||||
use Composer\IO\NullIO;
|
||||
use Composer\Util\Filesystem;
|
||||
use Composer\Util\Platform;
|
||||
use Composer\Util\Silencer;
|
||||
use Symfony\Component\Console\Application as BaseApplication;
|
||||
|
@ -282,7 +283,7 @@ class Application extends BaseApplication
|
|||
|
||||
// add non-standard scripts as own commands
|
||||
$file = Factory::getComposerFile();
|
||||
if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
|
||||
if (is_file($file) && Filesystem::isReadable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
|
||||
if (isset($composer['scripts']) && is_array($composer['scripts'])) {
|
||||
foreach ($composer['scripts'] as $script => $dummy) {
|
||||
if (!defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
|
||||
|
|
|
@ -79,7 +79,7 @@ class LibraryInstaller implements InstallerInterface, BinaryPresenceInterface
|
|||
|
||||
$installPath = $this->getInstallPath($package);
|
||||
|
||||
if (is_readable($installPath)) {
|
||||
if (Filesystem::isReadable($installPath)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ class LibraryInstaller implements InstallerInterface, BinaryPresenceInterface
|
|||
$downloadPath = $this->getInstallPath($package);
|
||||
|
||||
// remove the binaries if it appears the package files are missing
|
||||
if (!is_readable($downloadPath) && $repo->hasPackage($package)) {
|
||||
if (!Filesystem::isReadable($downloadPath) && $repo->hasPackage($package)) {
|
||||
$this->binaryInstaller->removeBinaries($package);
|
||||
}
|
||||
|
||||
|
|
|
@ -600,6 +600,33 @@ class Filesystem
|
|||
return preg_replace('{^file://}i', '', $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cross-platform safe version of is_readable()
|
||||
*
|
||||
* This will also check for readability by reading the file as is_readable can not be trusted on network-mounts
|
||||
* and \\wsl$ paths. See https://github.com/composer/composer/issues/8231 and https://bugs.php.net/bug.php?id=68926
|
||||
*
|
||||
* @param string $path
|
||||
* @return bool
|
||||
*/
|
||||
public static function isReadable($path)
|
||||
{
|
||||
if (is_readable($path)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_file($path)) {
|
||||
return false !== Silencer::call('file_get_contents', $path, false, null, 0, 1);
|
||||
}
|
||||
|
||||
if (is_dir($path)) {
|
||||
return false !== Silencer::call('opendir', $path);
|
||||
}
|
||||
|
||||
// assume false otherwise
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function directorySize($directory)
|
||||
{
|
||||
$it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
|
||||
|
|
|
@ -211,11 +211,11 @@ final class StreamContextFactory
|
|||
}
|
||||
}
|
||||
|
||||
if (isset($defaults['ssl']['cafile']) && (!is_readable($defaults['ssl']['cafile']) || !CaBundle::validateCaFile($defaults['ssl']['cafile'], $logger))) {
|
||||
if (isset($defaults['ssl']['cafile']) && (!Filesystem::isReadable($defaults['ssl']['cafile']) || !CaBundle::validateCaFile($defaults['ssl']['cafile'], $logger))) {
|
||||
throw new TransportException('The configured cafile was not valid or could not be read.');
|
||||
}
|
||||
|
||||
if (isset($defaults['ssl']['capath']) && (!is_dir($defaults['ssl']['capath']) || !is_readable($defaults['ssl']['capath']))) {
|
||||
if (isset($defaults['ssl']['capath']) && (!is_dir($defaults['ssl']['capath']) || !Filesystem::isReadable($defaults['ssl']['capath']))) {
|
||||
throw new TransportException('The configured capath was not valid or could not be read.');
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue