diff --git a/src/Composer/Command/InitCommand.php b/src/Composer/Command/InitCommand.php index f363ddb1b..e405df919 100644 --- a/src/Composer/Command/InitCommand.php +++ b/src/Composer/Command/InitCommand.php @@ -60,7 +60,8 @@ class InitCommand extends Command new InputOption('author', null, InputOption::VALUE_NONE, 'Author name of package'), // new InputOption('version', null, InputOption::VALUE_NONE, 'Version of package'), new InputOption('homepage', null, InputOption::VALUE_NONE, 'Homepage of package'), - new InputOption('require', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'An array required packages'), + new InputOption('require', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Package to require with a version constraint, e.g. foo/bar:1.0.0 or foo/bar=1.0.0 or "foo/bar 1.0.0"'), + new InputOption('require-dev', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Package to require for development with a version constraint, e.g. foo/bar:1.0.0 or foo/bar=1.0.0 or "foo/bar 1.0.0"'), )) ->setHelp(<<init command creates a basic composer.json file @@ -216,10 +217,15 @@ EOT )); $requirements = array(); - if ($dialog->askConfirmation($output, $dialog->getQuestion('Would you like to define your dependencies interactively', 'yes', '?'), true)) { - $requirements = $this->determineRequirements($input, $output); + if ($dialog->askConfirmation($output, $dialog->getQuestion('Would you like to define your dependencies (require) interactively', 'yes', '?'), true)) { + $requirements = $this->determineRequirements($input, $output, $input->getOption('require')); } $input->setOption('require', $requirements); + $devRequirements = array(); + if ($dialog->askConfirmation($output, $dialog->getQuestion('Would you like to define your dev dependencies (require-dev) interactively', 'yes', '?'), true)) { + $devRequirements = $this->determineRequirements($input, $output, $input->getOption('require-dev')); + } + $input->setOption('require-dev', $devRequirements); } protected function findPackages($name) @@ -246,12 +252,18 @@ EOT return $packages; } - protected function determineRequirements(InputInterface $input, OutputInterface $output) + protected function determineRequirements(InputInterface $input, OutputInterface $output, $requires = array()) { $dialog = $this->getHelperSet()->get('dialog'); $prompt = $dialog->getQuestion('Search for a package', false, ':'); - $requires = $input->getOption('require') ?: array(); + if ($requires) { + foreach ($requires as $key => $requirement) { + $requires[$key] = preg_replace('{^([^=: ]+)[=: ](.*)$}', '$1 $2', $requirement); + } + + return $requires; + } while (null !== $package = $dialog->ask($output, $prompt)) { $matches = $this->findPackages($package); @@ -287,7 +299,7 @@ EOT return sprintf('%s %s', $package->getName(), $package->getPrettyVersion()); }; - $package = $dialog->askAndValidate($output, $dialog->getQuestion('Enter package # to add, or a couple if it is not listed', false, ':'), $validator, 3); + $package = $dialog->askAndValidate($output, $dialog->getQuestion('Enter package # to add, or a "[package] [version]" couple if it is not listed', false, ':'), $validator, 3); if (false !== $package) { $requires[] = $package; diff --git a/src/Composer/Command/RequireCommand.php b/src/Composer/Command/RequireCommand.php index 80cc68e02..26840e7f3 100644 --- a/src/Composer/Command/RequireCommand.php +++ b/src/Composer/Command/RequireCommand.php @@ -16,12 +16,15 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +use Composer\Factory; use Composer\Json\JsonFile; +use Composer\Json\JsonManipulator; use Composer\Json\JsonValidationException; use Composer\Util\RemoteFilesystem; /** * @author Jérémy Romey + * @author Jordi Boggiano */ class RequireCommand extends InitCommand { @@ -31,11 +34,11 @@ class RequireCommand extends InitCommand ->setName('require') ->setDescription('Adds a required package to a composer.json') ->setDefinition(array( - new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file', './composer.json'), - new InputOption('require', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'An array of required packages'), + new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Required package with a version constraint, e.g. 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.'), )) ->setHelp(<<getArgument('file'); + $factory = new Factory; + $file = $factory->getComposerFile(); if (!file_exists($file)) { $output->writeln(''.$file.' not found.'); @@ -55,52 +59,44 @@ EOT return 1; } - $laxValid = false; - try { - $json = new JsonFile($file, new RemoteFilesystem($this->getIO())); - $json->read(); - - $json->validateSchema(JsonFile::LAX_SCHEMA); - $laxValid = true; - $json->validateSchema(); - - } catch (\Exception $e) { - $output->writeln(''.$file.' has an error. Run the validate command for more info'); - return 1; - } - - $output->writeln(array( - '', - 'Updating your dependencies.', - '' - )); - $dialog = $this->getHelperSet()->get('dialog'); - $options = json_decode($json->getResult(), true); + $json = new JsonFile($file); + $composer = $json->read(); - $requirements = array(); - $requirements = $this->determineRequirements($input, $output); + $requirements = $this->determineRequirements($input, $output, $input->getArgument('packages')); - $baseRequirements = array_key_exists('require', $options) ? $options['require'] : array(); + $requireKey = $input->getOption('dev') ? 'require-dev' : 'require'; + $baseRequirements = array_key_exists($requireKey, $composer) ? $composer[$requireKey] : array(); $requirements = $this->formatRequirements($requirements); - foreach ($requirements as $package => $version) { - if (array_key_exists($package, $baseRequirements)) { - if ($dialog->askConfirmation($output, $dialog->getQuestion('The package '.$package.' is already in requirements. Would you like to update the version required from '.$baseRequirements[$package].' to '.$version, 'yes', '?'), true)) { - $baseRequirements[$package] = $version; - } - } else { + if (!$this->updateFileCleanly($json, $baseRequirements, $requirements, $requireKey)) { + foreach ($requirements as $package => $version) { $baseRequirements[$package] = $version; } + + $composer[$requireKey] = $baseRequirements; + $json->write($composer); } - $options['require'] = $baseRequirements; + $output->writeln(''.$file.' has been updated'); + } + + private function updateFileCleanly($json, array $base, array $new, $requireKey) + { + $contents = file_get_contents($json->getPath()); - $json->encode($options); - $json->write($options); + $manipulator = new JsonManipulator($contents); - $output->writeln(''.$file.' has been updated'); + foreach ($new as $package => $constraint) { + if (!$manipulator->addLink($requireKey, $package, $constraint)) { + return false; + } + } + + file_put_contents($json->getPath(), $manipulator->getContents()); + + return true; } protected function interact(InputInterface $input, OutputInterface $output) diff --git a/src/Composer/Json/JsonFile.php b/src/Composer/Json/JsonFile.php index 09ae3eb0f..f463c777e 100644 --- a/src/Composer/Json/JsonFile.php +++ b/src/Composer/Json/JsonFile.php @@ -299,14 +299,4 @@ class JsonFile throw $result; } - - /** - * Returns the content of the file - * - * @return string result - */ - public function getResult() - { - return $this->rfs->getContents($this->path, $this->path, false); - } }