ExecCommand.php 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. <?php
  2. /*
  3. * This file is part of Composer.
  4. *
  5. * (c) Nils Adermann <naderman@naderman.de>
  6. * Jordi Boggiano <j.boggiano@seld.be>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. namespace Composer\Command;
  12. use Symfony\Component\Console\Input\InputInterface;
  13. use Symfony\Component\Console\Input\InputOption;
  14. use Symfony\Component\Console\Output\OutputInterface;
  15. use Symfony\Component\Console\Input\InputArgument;
  16. /**
  17. * @author Davey Shafik <me@daveyshafik.com>
  18. */
  19. class ExecCommand extends BaseCommand
  20. {
  21. protected function configure()
  22. {
  23. $this
  24. ->setName('exec')
  25. ->setDescription('Executes a vendored binary/script.')
  26. ->setDefinition(array(
  27. new InputOption('list', 'l', InputOption::VALUE_NONE),
  28. new InputArgument('binary', InputArgument::OPTIONAL, 'The binary to run, e.g. phpunit'),
  29. new InputArgument(
  30. 'args',
  31. InputArgument::IS_ARRAY | InputArgument::OPTIONAL,
  32. 'Arguments to pass to the binary. Use <info>--</info> to separate from composer arguments'
  33. ),
  34. ))
  35. ->setHelp(
  36. <<<EOT
  37. Executes a vendored binary/script.
  38. Read more at https://getcomposer.org/doc/03-cli.md#exec
  39. EOT
  40. )
  41. ;
  42. }
  43. protected function execute(InputInterface $input, OutputInterface $output)
  44. {
  45. $composer = $this->getComposer();
  46. $binDir = $composer->getConfig()->get('bin-dir');
  47. if ($input->getOption('list') || !$input->getArgument('binary')) {
  48. $bins = glob($binDir . '/*');
  49. $bins = array_merge($bins, array_map(function ($e) {
  50. return "$e (local)";
  51. }, $composer->getPackage()->getBinaries()));
  52. if (!$bins) {
  53. throw new \RuntimeException("No binaries found in composer.json or in bin-dir ($binDir)");
  54. }
  55. $this->getIO()->write(
  56. <<<EOT
  57. <comment>Available binaries:</comment>
  58. EOT
  59. );
  60. foreach ($bins as $bin) {
  61. // skip .bat copies
  62. if (isset($previousBin) && $bin === $previousBin.'.bat') {
  63. continue;
  64. }
  65. $previousBin = $bin;
  66. $bin = basename($bin);
  67. $this->getIO()->write(
  68. <<<EOT
  69. <info>- $bin</info>
  70. EOT
  71. );
  72. }
  73. return 0;
  74. }
  75. $binary = $input->getArgument('binary');
  76. $dispatcher = $composer->getEventDispatcher();
  77. $dispatcher->addListener('__exec_command', $binary);
  78. if ($output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL) {
  79. $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
  80. }
  81. if (getcwd() !== $this->getApplication()->getWorkingDirectory()) {
  82. try {
  83. chdir($this->getApplication()->getWorkingDirectory());
  84. } catch (\Exception $e) {
  85. throw new \RuntimeException('Could not switch back to working directory "'.$this->getApplication()->getWorkingDirectory().'"', 0, $e);
  86. }
  87. }
  88. return $dispatcher->dispatchScript('__exec_command', true, $input->getArgument('args'));
  89. }
  90. }