diff --git a/doc/03-cli.md b/doc/03-cli.md index 9c07776ff..74e9958ad 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -150,6 +150,24 @@ to the command. * **--no-progress:** Removes the progress display that can mess with some terminals or scripts which don't handle backspace characters. +## remove + +The `remove` command removes packages from the `composer.json` file from +the current directory. + + $ php composer.phar remove + +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 + ## global The global command allows you to run other commands like `install`, `require` diff --git a/src/Composer/Command/RemoveCommand.php b/src/Composer/Command/RemoveCommand.php new file mode 100755 index 000000000..97e6adc0e --- /dev/null +++ b/src/Composer/Command/RemoveCommand.php @@ -0,0 +1,106 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Command; + +use Composer\Config\JsonConfigSource; +use Composer\Installer; +use Composer\Plugin\CommandEvent; +use Composer\Plugin\PluginEvents; +use Composer\Json\JsonFile; +use Composer\Factory; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Pierre du Plessis + */ +class RemoveCommand extends Command +{ + protected function configure() + { + $this + ->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.') + )) + ->setHelp(<<remove command removes a package from the current +list of installed packages + +php composer.phar remove + +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); + $composerBackup = file_get_contents($json->getPath()); + + $json = new JsonConfigSource($json); + + $type = $input->getOption('dev') ? 'require-dev' : 'require'; + + foreach ($packages as $package) { + $json->removeLink($type, $package); + } + + if ($input->getOption('no-update')) { + if ($input->getOption('dry-run')) { + file_put_contents($json->getPath(), $composerBackup); + } + + return 0; + } + + $composer = Factory::create($io); + + $install = Installer::create($io, $composer); + + $install + ->setDryRun($input->getOption('dry-run')) + ->setVerbose($input->getOption('verbose')) + ->setDevMode($input->getOption('dev')) + ->setUpdate(true) + ->setUpdateWhitelist($packages) + ; + + if (!$install->run()) { + $output->writeln("\n".'Remove failed, reverting '.$file.' to its original content.'); + file_put_contents($json->getPath(), $composerBackup); + + return 1; + } + + return 0; + } +} diff --git a/src/Composer/Console/Application.php b/src/Composer/Console/Application.php index 9d622cf67..6350e06d2 100644 --- a/src/Composer/Console/Application.php +++ b/src/Composer/Console/Application.php @@ -227,6 +227,7 @@ class Application extends BaseApplication $commands[] = new Command\RunScriptCommand(); $commands[] = new Command\LicensesCommand(); $commands[] = new Command\GlobalCommand(); + $commands[] = new Command\RemoveCommand(); if ('phar:' === substr(__FILE__, 0, 5)) { $commands[] = new Command\SelfUpdateCommand();