Add --dry-run to require and remove commands, fixes #7793
parent
fdfdee03c1
commit
d14d411fa4
|
@ -198,6 +198,7 @@ If you do not specify a package, composer will prompt you to search for a packag
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
* **--dev:** Add packages to `require-dev`.
|
* **--dev:** Add packages to `require-dev`.
|
||||||
|
* **--dry-run:** Simulate the command without actually doing anything.
|
||||||
* **--prefer-source:** Install packages from `source` when available.
|
* **--prefer-source:** Install packages from `source` when available.
|
||||||
* **--prefer-dist:** Install packages from `dist` when available.
|
* **--prefer-dist:** Install packages from `dist` when available.
|
||||||
* **--no-progress:** Removes the progress display that can mess with some
|
* **--no-progress:** Removes the progress display that can mess with some
|
||||||
|
@ -236,6 +237,7 @@ uninstalled.
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
* **--dev:** Remove packages from `require-dev`.
|
* **--dev:** Remove packages from `require-dev`.
|
||||||
|
* **--dry-run:** Simulate the command without actually doing anything.
|
||||||
* **--no-progress:** Removes the progress display that can mess with some
|
* **--no-progress:** Removes the progress display that can mess with some
|
||||||
terminals or scripts which don't handle backspace characters.
|
terminals or scripts which don't handle backspace characters.
|
||||||
* **--no-update:** Disables the automatic update of the dependencies.
|
* **--no-update:** Disables the automatic update of the dependencies.
|
||||||
|
|
|
@ -38,6 +38,7 @@ class RemoveCommand extends BaseCommand
|
||||||
->setDefinition(array(
|
->setDefinition(array(
|
||||||
new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'Packages that should be removed.'),
|
new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'Packages that should be removed.'),
|
||||||
new InputOption('dev', null, InputOption::VALUE_NONE, 'Removes a package from the require-dev section.'),
|
new InputOption('dev', null, InputOption::VALUE_NONE, 'Removes a package from the require-dev section.'),
|
||||||
|
new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
|
||||||
new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
|
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('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
|
||||||
new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
|
new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
|
||||||
|
@ -92,29 +93,47 @@ EOT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$dryRun = $input->getOption('dry-run');
|
||||||
|
$toRemove = array();
|
||||||
foreach ($packages as $package) {
|
foreach ($packages as $package) {
|
||||||
if (isset($composer[$type][$package])) {
|
if (isset($composer[$type][$package])) {
|
||||||
|
if ($dryRun) {
|
||||||
|
$toRemove[$type][] = $composer[$type][$package];
|
||||||
|
} else {
|
||||||
$json->removeLink($type, $composer[$type][$package]);
|
$json->removeLink($type, $composer[$type][$package]);
|
||||||
|
}
|
||||||
} elseif (isset($composer[$altType][$package])) {
|
} elseif (isset($composer[$altType][$package])) {
|
||||||
$io->writeError('<warning>' . $composer[$altType][$package] . ' could not be found in ' . $type . ' but it is present in ' . $altType . '</warning>');
|
$io->writeError('<warning>' . $composer[$altType][$package] . ' could not be found in ' . $type . ' but it is present in ' . $altType . '</warning>');
|
||||||
if ($io->isInteractive()) {
|
if ($io->isInteractive()) {
|
||||||
if ($io->askConfirmation('Do you want to remove it from ' . $altType . ' [<comment>yes</comment>]? ', true)) {
|
if ($io->askConfirmation('Do you want to remove it from ' . $altType . ' [<comment>yes</comment>]? ', true)) {
|
||||||
|
if ($dryRun) {
|
||||||
|
$toRemove[$altType][] = $composer[$altType][$package];
|
||||||
|
} else {
|
||||||
$json->removeLink($altType, $composer[$altType][$package]);
|
$json->removeLink($altType, $composer[$altType][$package]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} elseif (isset($composer[$type]) && $matches = preg_grep(BasePackage::packageNameToRegexp($package), array_keys($composer[$type]))) {
|
} elseif (isset($composer[$type]) && $matches = preg_grep(BasePackage::packageNameToRegexp($package), array_keys($composer[$type]))) {
|
||||||
foreach ($matches as $matchedPackage) {
|
foreach ($matches as $matchedPackage) {
|
||||||
|
if ($dryRun) {
|
||||||
|
$toRemove[$type][] = $matchedPackage;
|
||||||
|
} else {
|
||||||
$json->removeLink($type, $matchedPackage);
|
$json->removeLink($type, $matchedPackage);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} elseif (isset($composer[$altType]) && $matches = preg_grep(BasePackage::packageNameToRegexp($package), array_keys($composer[$altType]))) {
|
} elseif (isset($composer[$altType]) && $matches = preg_grep(BasePackage::packageNameToRegexp($package), array_keys($composer[$altType]))) {
|
||||||
foreach ($matches as $matchedPackage) {
|
foreach ($matches as $matchedPackage) {
|
||||||
$io->writeError('<warning>' . $matchedPackage . ' could not be found in ' . $type . ' but it is present in ' . $altType . '</warning>');
|
$io->writeError('<warning>' . $matchedPackage . ' could not be found in ' . $type . ' but it is present in ' . $altType . '</warning>');
|
||||||
if ($io->isInteractive()) {
|
if ($io->isInteractive()) {
|
||||||
if ($io->askConfirmation('Do you want to remove it from ' . $altType . ' [<comment>yes</comment>]? ', true)) {
|
if ($io->askConfirmation('Do you want to remove it from ' . $altType . ' [<comment>yes</comment>]? ', true)) {
|
||||||
|
if ($dryRun) {
|
||||||
|
$toRemove[$altType][] = $matchedPackage;
|
||||||
|
} else {
|
||||||
$json->removeLink($altType, $matchedPackage);
|
$json->removeLink($altType, $matchedPackage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$io->writeError('<warning>'.$package.' is not required in your composer.json and has not been removed</warning>');
|
$io->writeError('<warning>'.$package.' is not required in your composer.json and has not been removed</warning>');
|
||||||
}
|
}
|
||||||
|
@ -128,6 +147,21 @@ EOT
|
||||||
$this->resetComposer();
|
$this->resetComposer();
|
||||||
$composer = $this->getComposer(true, $input->getOption('no-plugins'));
|
$composer = $this->getComposer(true, $input->getOption('no-plugins'));
|
||||||
|
|
||||||
|
if ($dryRun) {
|
||||||
|
$rootPackage = $composer->getPackage();
|
||||||
|
$links = array(
|
||||||
|
'require' => $rootPackage->getRequires(),
|
||||||
|
'require-dev' => $rootPackage->getDevRequires(),
|
||||||
|
);
|
||||||
|
foreach ($toRemove as $type => $packages) {
|
||||||
|
foreach ($packages as $package) {
|
||||||
|
unset($links[$type][$package]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$rootPackage->setRequires($links['require']);
|
||||||
|
$rootPackage->setDevRequires($links['require-dev']);
|
||||||
|
}
|
||||||
|
|
||||||
$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'remove', $input, $output);
|
$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'remove', $input, $output);
|
||||||
$composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
|
$composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
|
||||||
|
|
||||||
|
@ -149,6 +183,7 @@ EOT
|
||||||
->setWhitelistTransitiveDependencies(!$input->getOption('no-update-with-dependencies'))
|
->setWhitelistTransitiveDependencies(!$input->getOption('no-update-with-dependencies'))
|
||||||
->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
|
->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
|
||||||
->setRunScripts(!$input->getOption('no-scripts'))
|
->setRunScripts(!$input->getOption('no-scripts'))
|
||||||
|
->setDryRun($dryRun)
|
||||||
;
|
;
|
||||||
|
|
||||||
$status = $install->run();
|
$status = $install->run();
|
||||||
|
|
|
@ -21,6 +21,8 @@ use Composer\Installer;
|
||||||
use Composer\Json\JsonFile;
|
use Composer\Json\JsonFile;
|
||||||
use Composer\Json\JsonManipulator;
|
use Composer\Json\JsonManipulator;
|
||||||
use Composer\Package\Version\VersionParser;
|
use Composer\Package\Version\VersionParser;
|
||||||
|
use Composer\Package\Loader\ArrayLoader;
|
||||||
|
use Composer\Package\BasePackage;
|
||||||
use Composer\Plugin\CommandEvent;
|
use Composer\Plugin\CommandEvent;
|
||||||
use Composer\Plugin\PluginEvents;
|
use Composer\Plugin\PluginEvents;
|
||||||
use Composer\Repository\CompositeRepository;
|
use Composer\Repository\CompositeRepository;
|
||||||
|
@ -48,6 +50,7 @@ class RequireCommand extends InitCommand
|
||||||
->setDefinition(array(
|
->setDefinition(array(
|
||||||
new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Optional package name can also include a version constraint, e.g. foo/bar or foo/bar:1.0.0 or foo/bar=1.0.0 or "foo/bar 1.0.0"'),
|
new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Optional package name can also include a version constraint, e.g. foo/bar or foo/bar:1.0.0 or foo/bar=1.0.0 or "foo/bar 1.0.0"'),
|
||||||
new InputOption('dev', null, InputOption::VALUE_NONE, 'Add requirement to require-dev.'),
|
new InputOption('dev', null, InputOption::VALUE_NONE, 'Add requirement to require-dev.'),
|
||||||
|
new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
|
||||||
new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
|
new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
|
||||||
new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
|
new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
|
||||||
new InputOption('fixed', null, InputOption::VALUE_NONE, 'Write fixed version to the composer.json.'),
|
new InputOption('fixed', null, InputOption::VALUE_NONE, 'Write fixed version to the composer.json.'),
|
||||||
|
@ -195,7 +198,7 @@ EOT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->updateFileCleanly($this->json, $requirements, $requireKey, $removeKey, $sortPackages)) {
|
if (!$input->getOption('dry-run') && !$this->updateFileCleanly($this->json, $requirements, $requireKey, $removeKey, $sortPackages)) {
|
||||||
$composerDefinition = $this->json->read();
|
$composerDefinition = $this->json->read();
|
||||||
foreach ($requirements as $package => $version) {
|
foreach ($requirements as $package => $version) {
|
||||||
$composerDefinition[$requireKey][$package] = $version;
|
$composerDefinition[$requireKey][$package] = $version;
|
||||||
|
@ -211,19 +214,35 @@ EOT
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return $this->doUpdate($input, $output, $io, $requirements);
|
return $this->doUpdate($input, $output, $io, $requirements, $requireKey, $removeKey);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$this->revertComposerFile(false);
|
$this->revertComposerFile(false);
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function doUpdate(InputInterface $input, OutputInterface $output, IOInterface $io, array $requirements)
|
private function doUpdate(InputInterface $input, OutputInterface $output, IOInterface $io, array $requirements, $requireKey, $removeKey)
|
||||||
{
|
{
|
||||||
// Update packages
|
// Update packages
|
||||||
$this->resetComposer();
|
$this->resetComposer();
|
||||||
$composer = $this->getComposer(true, $input->getOption('no-plugins'));
|
$composer = $this->getComposer(true, $input->getOption('no-plugins'));
|
||||||
|
|
||||||
|
if ($input->getOption('dry-run')) {
|
||||||
|
$rootPackage = $composer->getPackage();
|
||||||
|
$links = array(
|
||||||
|
'require' => $rootPackage->getRequires(),
|
||||||
|
'require-dev' => $rootPackage->getDevRequires(),
|
||||||
|
);
|
||||||
|
$loader = new ArrayLoader();
|
||||||
|
$newLinks = $loader->parseLinks($rootPackage->getName(), $rootPackage->getPrettyVersion(), BasePackage::$supportedLinkTypes[$requireKey]['description'], $requirements);
|
||||||
|
$links[$requireKey] = array_merge($links[$requireKey], $newLinks);
|
||||||
|
foreach ($requirements as $package => $constraint) {
|
||||||
|
unset($links[$removeKey][$package]);
|
||||||
|
}
|
||||||
|
$rootPackage->setRequires($links['require']);
|
||||||
|
$rootPackage->setDevRequires($links['require-dev']);
|
||||||
|
}
|
||||||
|
|
||||||
$updateDevMode = !$input->getOption('update-no-dev');
|
$updateDevMode = !$input->getOption('update-no-dev');
|
||||||
$optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
|
$optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
|
||||||
$authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
|
$authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
|
||||||
|
@ -250,6 +269,7 @@ EOT
|
||||||
->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
|
->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
|
||||||
->setPreferStable($input->getOption('prefer-stable'))
|
->setPreferStable($input->getOption('prefer-stable'))
|
||||||
->setPreferLowest($input->getOption('prefer-lowest'))
|
->setPreferLowest($input->getOption('prefer-lowest'))
|
||||||
|
->setDryRun($input->getOption('dry-run'))
|
||||||
;
|
;
|
||||||
|
|
||||||
// if no lock is present, or the file is brand new, we do not do a
|
// if no lock is present, or the file is brand new, we do not do a
|
||||||
|
|
Loading…
Reference in New Issue