diff --git a/doc/03-cli.md b/doc/03-cli.md index b91196516..7d557a8d3 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -163,6 +163,7 @@ php composer.phar require vendor/package:2.* vendor/package2:dev-master * **--no-update:** Disables the automatic update of the dependencies. * **--no-progress:** Removes the progress display that can mess with some terminals or scripts which don't handle backspace characters. +* **--update-no-dev** Run the dependency update with the --no-dev option. * **--update-with-dependencies** Also update dependencies of the newly required packages. @@ -171,18 +172,20 @@ php composer.phar require vendor/package:2.* vendor/package2:dev-master The `remove` command removes packages from the `composer.json` file from the current directory. - $ php composer.phar remove +```sh +php composer.phar remove vendor/package vendor/package2 +``` After removing the requirements, the modified requirements will be uninstalled. ### Options -* **--dry-run:** If you want to run through an uninstallation without actually - uninstalling a package, you can use `--dry-run`. This will simulate the - uninstallation and show you what would happen. -* **--dev:** Add packages to `require-dev`. -* **--no-update:** Only remove the package from the composer.json file, but - won't remove the files or update the composer.lock +* **--dev:** Remove packages from `require-dev`. +* **--no-update:** Disables the automatic update of the dependencies. +* **--no-progress:** Removes the progress display that can mess with some + terminals or scripts which don't handle backspace characters. +* **--update-no-dev** Run the dependency update with the --no-dev option. +* **--update-with-dependencies** Also update dependencies of the removed packages. ## global diff --git a/src/Composer/Command/RemoveCommand.php b/src/Composer/Command/RemoveCommand.php index 97e6adc0e..be110d650 100755 --- a/src/Composer/Command/RemoveCommand.php +++ b/src/Composer/Command/RemoveCommand.php @@ -25,6 +25,7 @@ use Symfony\Component\Console\Output\OutputInterface; /** * @author Pierre du Plessis + * @author Jordi Boggiano */ class RemoveCommand extends Command { @@ -34,11 +35,12 @@ class RemoveCommand extends Command ->setName('remove') ->setDescription('Removes a package from the require or require-dev') ->setDefinition(array( - new InputArgument('packages', InputArgument::IS_ARRAY, 'Packages that should be removed, if not provided all packages are.'), - new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'), - new InputOption('dev', null, InputOption::VALUE_NONE, 'Removes a package from the require-dev section'), - new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'), - new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.') + new InputArgument('packages', InputArgument::IS_ARRAY, 'Packages that should be removed.'), + new InputOption('dev', null, InputOption::VALUE_NONE, 'Removes a package from the require-dev section.'), + new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), + new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'), + new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'), + new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies.'), )) ->setHelp(<<remove command removes a package from the current @@ -53,54 +55,64 @@ EOT protected function execute(InputInterface $input, OutputInterface $output) { - $composer = $this->getComposer(); $packages = $input->getArgument('packages'); - $io = $this->getIO(); - - $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'remove', $input, $output); - $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); - $file = Factory::getComposerFile(); $json = new JsonFile($file); + $composer = $json->read(); $composerBackup = file_get_contents($json->getPath()); $json = new JsonConfigSource($json); $type = $input->getOption('dev') ? 'require-dev' : 'require'; + $altType = !$input->getOption('dev') ? 'require-dev' : 'require'; foreach ($packages as $package) { - $json->removeLink($type, $package); + if (isset($composer[$type][$package])) { + $json->removeLink($type, $package); + } elseif (isset($composer[$altType][$package])) { + $output->writeln(''.$package.' could not be found in '.$type.' but it is present in '.$altType.''); + $dialog = $this->getHelperSet()->get('dialog'); + if ($this->getIO()->isInteractive()) { + if ($dialog->askConfirmation($output, $dialog->getQuestion('Do you want to remove it from '.$altType, 'yes', '?'), true)) { + $json->removeLink($altType, $package); + } + } + } else { + $output->writeln(''.$package.' is not required in your composer.json and has not been removed'); + } } if ($input->getOption('no-update')) { - if ($input->getOption('dry-run')) { - file_put_contents($json->getPath(), $composerBackup); - } - return 0; } - $composer = Factory::create($io); + // Update packages + $composer = $this->getComposer(); + $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress')); + $io = $this->getIO(); + + $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'remove', $input, $output); + $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); $install = Installer::create($io, $composer); + $updateDevMode = !$input->getOption('update-no-dev'); $install - ->setDryRun($input->getOption('dry-run')) ->setVerbose($input->getOption('verbose')) - ->setDevMode($input->getOption('dev')) + ->setDevMode($updateDevMode) ->setUpdate(true) ->setUpdateWhitelist($packages) + ->setWhitelistDependencies($input->getOption('update-with-dependencies')); ; - if (!$install->run()) { - $output->writeln("\n".'Remove failed, reverting '.$file.' to its original content.'); + $status = $install->run(); + if ($status !== 0) { + $output->writeln("\n".'Removal failed, reverting '.$file.' to its original content.'); file_put_contents($json->getPath(), $composerBackup); - - return 1; } - return 0; + return $status; } }