function BinaryInstaller::generateUnixyProxyCode
1 call to BinaryInstaller::generateUnixyProxyCode()
- BinaryInstaller::installUnixyProxyBinaries in vendor/
composer/ composer/ src/ Composer/ Installer/ BinaryInstaller.php
File
-
vendor/
composer/ composer/ src/ Composer/ Installer/ BinaryInstaller.php, line 209
Class
- BinaryInstaller
- Utility to handle installation of package "bin"/binaries
Namespace
Composer\InstallerCode
protected function generateUnixyProxyCode(string $bin, string $link) : string {
$binPath = $this->filesystem
->findShortestPath($link, $bin);
$binDir = ProcessExecutor::escape(dirname($binPath));
$binFile = basename($binPath);
$binContents = (string) file_get_contents($bin, false, null, 0, 500);
// For php files, we generate a PHP proxy instead of a shell one,
// which allows calling the proxy with a custom php process
if (Preg::isMatch('{^(#!.*\\r?\\n)?[\\r\\n\\t ]*<\\?php}', $binContents, $match)) {
// carry over the existing shebang if present, otherwise add our own
$proxyCode = $match[1] === null ? '#!/usr/bin/env php' : trim($match[1]);
$binPathExported = $this->filesystem
->findShortestPathCode($link, $bin, false, true);
$streamProxyCode = $streamHint = '';
$globalsCode = '$GLOBALS[\'_composer_bin_dir\'] = __DIR__;' . "\n";
$phpunitHack1 = $phpunitHack2 = '';
// Don't expose autoload path when vendor dir was not set in custom installers
if ($this->vendorDir !== null) {
// ensure comparisons work accurately if the CWD is a symlink, as $link is realpath'd already
$vendorDirReal = realpath($this->vendorDir);
if ($vendorDirReal === false) {
$vendorDirReal = $this->vendorDir;
}
$globalsCode .= '$GLOBALS[\'_composer_autoload_path\'] = ' . $this->filesystem
->findShortestPathCode($link, $vendorDirReal . '/autoload.php', false, true) . ";\n";
}
// Add workaround for PHPUnit process isolation
if ($this->filesystem
->normalizePath($bin) === $this->filesystem
->normalizePath($this->vendorDir . '/phpunit/phpunit/phpunit')) {
// workaround issue on PHPUnit 6.5+ running on PHP 8+
$globalsCode .= '$GLOBALS[\'__PHPUNIT_ISOLATION_EXCLUDE_LIST\'] = $GLOBALS[\'__PHPUNIT_ISOLATION_BLACKLIST\'] = array(realpath(' . $binPathExported . '));' . "\n";
// workaround issue on all PHPUnit versions running on PHP <8
$phpunitHack1 = "'phpvfscomposer://'.";
$phpunitHack2 = '
$data = str_replace(\'__DIR__\', var_export(dirname($this->realpath), true), $data);
$data = str_replace(\'__FILE__\', var_export($this->realpath, true), $data);';
}
if (trim($match[0]) !== '<?php') {
$streamHint = ' using a stream wrapper to prevent the shebang from being output on PHP<8' . "\n *";
$streamProxyCode = <<<STREAMPROXY
if (PHP_VERSION_ID < 80000) {
if (!class_exists('Composer\\BinProxyWrapper')) {
/**
* @internal
*/
final class BinProxyWrapper
{
private \$handle;
private \$position;
private \$realpath;
public function stream_open(\$path, \$mode, \$options, &\$opened_path)
{
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
\$opened_path = substr(\$path, 17);
\$this->realpath = realpath(\$opened_path) ?: \$opened_path;
\$opened_path = {<span class="php-variable">$phpunitHack1</span>}\$this->realpath;
\$this->handle = fopen(\$this->realpath, \$mode);
\$this->position = 0;
return (bool) \$this->handle;
}
public function stream_read(\$count)
{
\$data = fread(\$this->handle, \$count);
if (\$this->position === 0) {
\$data = preg_replace('{^#!.*\\r?\\n}', '', \$data);
}{<span class="php-variable">$phpunitHack2</span>}
\$this->position += strlen(\$data);
return \$data;
}
public function stream_cast(\$castAs)
{
return \$this->handle;
}
public function stream_close()
{
fclose(\$this->handle);
}
public function stream_lock(\$operation)
{
return \$operation ? flock(\$this->handle, \$operation) : true;
}
public function stream_seek(\$offset, \$whence)
{
if (0 === fseek(\$this->handle, \$offset, \$whence)) {
\$this->position = ftell(\$this->handle);
return true;
}
return false;
}
public function stream_tell()
{
return \$this->position;
}
public function stream_eof()
{
return feof(\$this->handle);
}
public function stream_stat()
{
return array();
}
public function stream_set_option(\$option, \$arg1, \$arg2)
{
return true;
}
public function url_stat(\$path, \$flags)
{
\$path = substr(\$path, 17);
if (file_exists(\$path)) {
return stat(\$path);
}
return false;
}
}
}
if (
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\\BinProxyWrapper'))
) {
return include("phpvfscomposer://" . {<span class="php-variable">$binPathExported</span>});
}
}
STREAMPROXY;
}
return $proxyCode . "\n" . <<<PROXY
<?php
/**
* Proxy PHP file generated by Composer
*
* This file includes the referenced bin path ({<span class="php-variable">$binPath</span>})
*{<span class="php-variable">$streamHint</span>}
* @generated
*/
namespace Composer;
{<span class="php-variable">$globalsCode</span>}
{<span class="php-variable">$streamProxyCode</span>}
return include {<span class="php-variable">$binPathExported</span>};
PROXY;
}
return <<<PROXY
#!/usr/bin/env sh
# Support bash to support `source` with fallback on \$0 if this does not run with bash
# https://stackoverflow.com/a/35006505/6512
selfArg="\$BASH_SOURCE"
if [ -z "\$selfArg" ]; then
selfArg="\$0"
fi
self=\$(realpath \$selfArg 2> /dev/null)
if [ -z "\$self" ]; then
self="\$selfArg"
fi
dir=\$(cd "\${self%[/\\\\]*}" > /dev/null; cd {<span class="php-variable">$binDir</span>} && pwd)
if [ -d /proc/cygdrive ]; then
case \$(which php) in
\$(readlink -n /proc/cygdrive)/*)
# We are in Cygwin using Windows php, so the path must be translated
dir=\$(cygpath -m "\$dir");
;;
esac
fi
export COMPOSER_RUNTIME_BIN_DIR="\$(cd "\${self%[/\\\\]*}" > /dev/null; pwd)"
# If bash is sourcing this file, we have to source the target as well
bashSource="\$BASH_SOURCE"
if [ -n "\$bashSource" ]; then
if [ "\$bashSource" != "\$0" ]; then
source "\${dir}/{<span class="php-variable">$binFile</span>}" "\$@"
return
fi
fi
exec "\${dir}/{<span class="php-variable">$binFile</span>}" "\$@"
PROXY;
}