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.
main
Adriano Ferreira 4 years ago
parent dbcf592ea2
commit acc040f745

@ -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]);
}
}
}
}

@ -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') {

Loading…
Cancel
Save