1
0
Fork 0

Append the bin dir on each listener iteration

The "composer install" can create the vendor/dir folders and be used as a script item on composer.json. Having another script running after it that relies on vendor/bir binaries (such as phpunit) will cause it to not find the binary. This fix addresses the issue by trying to append the path on each script iteration.
pull/8538/head
Adriano Ferreira 2020-01-19 22:12:11 -02:00
parent dbcf592ea2
commit acc040f745
2 changed files with 75 additions and 15 deletions

View File

@ -145,27 +145,15 @@ class EventDispatcher
*/
protected function doDispatch(Event $event)
{
$pathStr = 'PATH';
if (!isset($_SERVER[$pathStr]) && isset($_SERVER['Path'])) {
$pathStr = 'Path';
}
// add the bin dir to the PATH to make local binaries of deps usable in scripts
$binDir = $this->composer->getConfig()->get('bin-dir');
if (is_dir($binDir)) {
$binDir = realpath($binDir);
if (isset($_SERVER[$pathStr]) && !preg_match('{(^|'.PATH_SEPARATOR.')'.preg_quote($binDir).'($|'.PATH_SEPARATOR.')}', $_SERVER[$pathStr])) {
$_SERVER[$pathStr] = $binDir.PATH_SEPARATOR.getenv($pathStr);
putenv($pathStr.'='.$_SERVER[$pathStr]);
}
}
$listeners = $this->getListeners($event);
$this->pushEvent($event);
$return = 0;
foreach ($listeners as $callable) {
$this->ensureBinDirIsInPath();
if (!is_string($callable)) {
if (!is_callable($callable)) {
$className = is_object($callable[0]) ? get_class($callable[0]) : $callable[0];
@ -545,4 +533,22 @@ class EventDispatcher
{
return array_pop($this->eventStack);
}
private function ensureBinDirIsInPath()
{
$pathStr = 'PATH';
if (!isset($_SERVER[$pathStr]) && isset($_SERVER['Path'])) {
$pathStr = 'Path';
}
// add the bin dir to the PATH to make local binaries of deps usable in scripts
$binDir = $this->composer->getConfig()->get('bin-dir');
if (is_dir($binDir)) {
$binDir = realpath($binDir);
if (isset($_SERVER[$pathStr]) && !preg_match('{(^|'.PATH_SEPARATOR.')'.preg_quote($binDir).'($|'.PATH_SEPARATOR.')}', $_SERVER[$pathStr])) {
$_SERVER[$pathStr] = $binDir.PATH_SEPARATOR.getenv($pathStr);
putenv($pathStr.'='.$_SERVER[$pathStr]);
}
}
}
}

View File

@ -260,6 +260,60 @@ class EventDispatcherTest extends TestCase
$this->assertEquals($expected, $io->getOutput());
}
public function testDispatcherAppendsDirBinOnPathForEveryListener()
{
$currentDirectoryBkp = getcwd();
$composerBinDirBkp = getenv('COMPOSER_BIN_DIR');
chdir(__DIR__);
putenv('COMPOSER_BIN_DIR=' . __DIR__ . sprintf('%svendor%sbin', DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR));
$process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock();
$dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher')->setConstructorArgs(array(
$this->createComposerInstance(),
$io = new BufferIO('', OutputInterface::VERBOSITY_VERBOSE),
$process,
))->setMethods(array(
'getListeners',
))->getMock();
$listeners = array(
'Composer\\Test\\EventDispatcher\\EventDispatcherTest::createsVendorBinFolderChecksEnvDoesNotContainsBin',
'Composer\\Test\\EventDispatcher\\EventDispatcherTest::createsVendorBinFolderChecksEnvContainsBin',
);
$dispatcher->expects($this->atLeastOnce())->method('getListeners')->will($this->returnValue($listeners));
$dispatcher->dispatchScript(ScriptEvents::POST_INSTALL_CMD, false);
rmdir(__DIR__ . sprintf('%svendor%sbin', DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR));
rmdir(__DIR__ . sprintf('%svendor', DIRECTORY_SEPARATOR));
chdir($currentDirectoryBkp);
putenv('COMPOSER_BIN_DIR=' . $composerBinDirBkp);
}
static public function createsVendorBinFolderChecksEnvDoesNotContainsBin()
{
mkdir(__DIR__ . sprintf('%svendor%sbin', DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), 0700, true);
$val = getenv('PATH');
if ( ! $val ) {
$val = getenv('Path');
}
self::assertFalse(strpos($val, __DIR__ . sprintf('%svendor%sbin', DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR)));
}
static public function createsVendorBinFolderChecksEnvContainsBin()
{
$val = getenv('PATH');
if ( ! $val ) {
$val = getenv('Path');
}
self::assertNotFalse(strpos($val, __DIR__ . sprintf('%svendor%sbin', DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR)));
}
static public function getTestEnv() {
$val = getenv('ABC');
if ($val !== '123') {