From d65e1c0112944666ea31e16fbb66e9b809efb2da Mon Sep 17 00:00:00 2001 From: Pierre du Plessis Date: Wed, 15 Aug 2018 12:59:05 +0200 Subject: [PATCH] Revert composer.json changes when require process stops --- src/Composer/Command/RequireCommand.php | 67 ++++++++++++++++--------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/src/Composer/Command/RequireCommand.php b/src/Composer/Command/RequireCommand.php index 01439207f..147e0cf74 100644 --- a/src/Composer/Command/RequireCommand.php +++ b/src/Composer/Command/RequireCommand.php @@ -32,6 +32,11 @@ use Composer\Repository\PlatformRepository; */ class RequireCommand extends InitCommand { + private $newlyCreated; + private $json; + private $file; + private $composerBackup; + protected function configure() { $this @@ -75,32 +80,39 @@ EOT protected function execute(InputInterface $input, OutputInterface $output) { - $file = Factory::getComposerFile(); + if (function_exists('pcntl_async_signals')) { + pcntl_async_signals(true); + pcntl_signal(SIGINT, array($this, 'revertComposerFile')); + pcntl_signal(SIGTERM, array($this, 'revertComposerFile')); + pcntl_signal(SIGHUP, array($this, 'revertComposerFile')); + } + + $this->file = Factory::getComposerFile(); $io = $this->getIO(); - $newlyCreated = !file_exists($file); - if ($newlyCreated && !file_put_contents($file, "{\n}\n")) { - $io->writeError(''.$file.' could not be created.'); + $this->newlyCreated = !file_exists($this->file); + if ($this->newlyCreated && !file_put_contents($this->file, "{\n}\n")) { + $io->writeError(''.$this->file.' could not be created.'); return 1; } - if (!is_readable($file)) { - $io->writeError(''.$file.' is not readable.'); + if (!is_readable($this->file)) { + $io->writeError(''.$this->file.' is not readable.'); return 1; } - if (!is_writable($file)) { - $io->writeError(''.$file.' is not writable.'); + if (!is_writable($this->file)) { + $io->writeError(''.$this->file.' is not writable.'); return 1; } - if (filesize($file) === 0) { - file_put_contents($file, "{\n}\n"); + if (filesize($this->file) === 0) { + file_put_contents($this->file, "{\n}\n"); } - $json = new JsonFile($file); - $composerBackup = file_get_contents($json->getPath()); + $this->json = new JsonFile($this->file); + $this->composerBackup = file_get_contents($this->json->getPath()); $composer = $this->getComposer(true, $input->getOption('no-plugins')); $repos = $composer->getRepositoryManager()->getRepositories(); @@ -133,16 +145,16 @@ EOT $sortPackages = $input->getOption('sort-packages') || $composer->getConfig()->get('sort-packages'); - if (!$this->updateFileCleanly($json, $requirements, $requireKey, $removeKey, $sortPackages)) { - $composerDefinition = $json->read(); + if (!$this->updateFileCleanly($this->json, $requirements, $requireKey, $removeKey, $sortPackages)) { + $composerDefinition = $this->json->read(); foreach ($requirements as $package => $version) { $composerDefinition[$requireKey][$package] = $version; unset($composerDefinition[$removeKey][$package]); } - $json->write($composerDefinition); + $this->json->write($composerDefinition); } - $io->writeError(''.$file.' has been '.($newlyCreated ? 'created' : 'updated').''); + $io->writeError(''.$this->file.' has been '.($this->newlyCreated ? 'created' : 'updated').''); if ($input->getOption('no-update')) { return 0; @@ -183,13 +195,7 @@ EOT $status = $install->run(); if ($status !== 0) { - if ($newlyCreated) { - $io->writeError("\n".'Installation failed, deleting '.$file.'.'); - unlink($json->getPath()); - } else { - $io->writeError("\n".'Installation failed, reverting '.$file.' to its original content.'); - file_put_contents($json->getPath(), $composerBackup); - } + $this->revertComposerFile(); } return $status; @@ -219,4 +225,19 @@ EOT { return; } + + public function revertComposerFile() + { + $io = $this->getIO(); + + if ($this->newlyCreated) { + $io->writeError("\n".'Installation failed, deleting '.$this->file.'.'); + unlink($this->json->getPath()); + } else { + $io->writeError("\n".'Installation failed, reverting '.$this->file.' to its original content.'); + file_put_contents($this->json->getPath(), $this->composerBackup); + } + + exit(1); + } }