Browse Source

Refactor init & require commands

Jordi Boggiano 12 years ago
parent
commit
27f8019dbd

+ 18 - 6
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(<<<EOT
 The <info>init</info> 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 <package> <version> 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;

+ 34 - 38
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 <jeremy@free-agent.fr>
+ * @author Jordi Boggiano <j.boggiano@seld.be>
  */
 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(<<<EOT
-The add package command adds a required package to a given composer.json
+The require command adds requirements to your composer.json
 
 EOT
             )
@@ -44,7 +47,8 @@ EOT
 
     protected function execute(InputInterface $input, OutputInterface $output)
     {
-        $file = $input->getArgument('file');
+        $factory = new Factory;
+        $file = $factory->getComposerFile();
 
         if (!file_exists($file)) {
             $output->writeln('<error>'.$file.' not found.</error>');
@@ -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('<error>'.$file.' has an error. Run the validate command for more info</error>');
-            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('<info>'.$file.' has been updated</info>');
+    }
+
+    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('<info>'.$file.' has been updated</info>');
+        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)

+ 0 - 10
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);
-    }
 }