diff options
Diffstat (limited to 'vendor/bamarni/composer-bin-plugin/src/BinCommand.php')
-rw-r--r-- | vendor/bamarni/composer-bin-plugin/src/BinCommand.php | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/vendor/bamarni/composer-bin-plugin/src/BinCommand.php b/vendor/bamarni/composer-bin-plugin/src/BinCommand.php new file mode 100644 index 0000000..e7fd540 --- /dev/null +++ b/vendor/bamarni/composer-bin-plugin/src/BinCommand.php @@ -0,0 +1,186 @@ +<?php + +namespace Bamarni\Composer\Bin; + +use Composer\Console\Application as ComposerApplication; +use Composer\Factory; +use Composer\IO\IOInterface; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\StringInput; +use Symfony\Component\Console\Output\OutputInterface; +use Composer\Command\BaseCommand; +use Composer\Json\JsonFile; + +class BinCommand extends BaseCommand +{ + /** + * {@inheritDoc} + */ + protected function configure() + { + $this + ->setName('bin') + ->setDescription('Run a command inside a bin namespace') + ->setDefinition([ + new InputArgument('namespace', InputArgument::REQUIRED), + new InputArgument('args', InputArgument::REQUIRED | InputArgument::IS_ARRAY), + ]) + ->ignoreValidationErrors() + ; + } + + /** + * {@inheritDoc} + */ + public function execute(InputInterface $input, OutputInterface $output) + { + $config = new Config($this->getComposer()); + $this->resetComposers($application = $this->getApplication()); + /** @var ComposerApplication $application */ + + if ($config->binLinksAreEnabled()) { + putenv('COMPOSER_BIN_DIR='.$this->createConfig()->get('bin-dir')); + } + + $vendorRoot = $config->getTargetDirectory(); + $namespace = $input->getArgument('namespace'); + + $input = new StringInput(preg_replace( + sprintf('/bin\s+(--ansi\s)?%s(\s.+)/', preg_quote($namespace, '/')), + '$1$2', + (string) $input, + 1 + )); + + return ('all' !== $namespace) + ? $this->executeInNamespace($application, $vendorRoot.'/'.$namespace, $input, $output) + : $this->executeAllNamespaces($application, $vendorRoot, $input, $output) + ; + } + + /** + * @param ComposerApplication $application + * @param string $binVendorRoot + * @param InputInterface $input + * @param OutputInterface $output + * + * @return int Exit code + */ + private function executeAllNamespaces(ComposerApplication $application, $binVendorRoot, InputInterface $input, OutputInterface $output) + { + $binRoots = glob($binVendorRoot.'/*', GLOB_ONLYDIR); + if (empty($binRoots)) { + $this->getIO()->writeError('<warning>Couldn\'t find any bin namespace.</warning>'); + + return 0; // Is a valid scenario: the user may not have setup any bin namespace yet + } + + $originalWorkingDir = getcwd(); + $exitCode = 0; + foreach ($binRoots as $namespace) { + $output->writeln( + sprintf('Run in namespace <comment>%s</comment>', $namespace), + OutputInterface::VERBOSITY_VERBOSE + ); + $exitCode += $this->executeInNamespace($application, $namespace, $input, $output); + + chdir($originalWorkingDir); + $this->resetComposers($application); + } + + return min($exitCode, 255); + } + + /** + * @param ComposerApplication $application + * @param string $namespace + * @param InputInterface $input + * @param OutputInterface $output + * + * @return int Exit code + */ + private function executeInNamespace(ComposerApplication $application, $namespace, InputInterface $input, OutputInterface $output) + { + if (!file_exists($namespace)) { + mkdir($namespace, 0777, true); + } + + $this->chdir($namespace); + + // some plugins require access to composer file e.g. Symfony Flex + if (!file_exists(Factory::getComposerFile())) { + file_put_contents(Factory::getComposerFile(), '{}'); + } + + $input = new StringInput((string) $input . ' --working-dir=.'); + + $this->getIO()->writeError( + sprintf('<info>Run with <comment>%s</comment></info>', $input->__toString()), + true, + IOInterface::VERBOSE + ); + + return $application->doRun($input, $output); + } + + /** + * {@inheritDoc} + */ + public function isProxyCommand() + { + return true; + } + + /** + * Resets all Composer references in the application. + * + * @param ComposerApplication $application + * @return void + */ + private function resetComposers(ComposerApplication $application) + { + $application->resetComposer(); + + foreach ($this->getApplication()->all() as $command) { + if ($command instanceof BaseCommand) { + $command->resetComposer(); + } + } + } + + /** + * @param $dir + * @return void + */ + private function chdir($dir) + { + chdir($dir); + + $this->getIO()->writeError( + sprintf('<info>Changed current directory to %s</info>', $dir), + true, + IOInterface::VERBOSE + ); + } + + /** + * @return \Composer\Config + * @throws \Composer\Json\JsonValidationException + * @throws \Seld\JsonLint\ParsingException + */ + private function createConfig() + { + $config = Factory::createConfig(); + + $file = new JsonFile(Factory::getComposerFile()); + if (!$file->exists()) { + return $config; + } + $file->validateSchema(JsonFile::LAX_SCHEMA); + + $config->merge($file->read()); + + return $config; + } +} |