diff --git a/src/RecipeCommandBehaviour.php b/src/RecipeCommandBehaviour.php index e7a3202..017d28f 100644 --- a/src/RecipeCommandBehaviour.php +++ b/src/RecipeCommandBehaviour.php @@ -182,4 +182,75 @@ trait RecipeCommandBehaviour // Cannot guess; Let composer choose (equivalent to `composer require vendor/library`) return null; } + + /** + * Install or update a recipe with a given constraint and current version + * + * @param OutputInterface $output + * @param string $recipe + * @param string $constraint + * @param string $installedVersion + * @return int + */ + protected function installRecipe(OutputInterface $output, $recipe, $constraint, $installedVersion) + { + if ($installedVersion) { + if ($constraint) { + $output->writeln( + "Updating existing recipe from {$installedVersion} to {$constraint}" + ); + } else { + // Show a guessed constraint + $constraint = $this->findBestConstraint($installedVersion); + if ($constraint) { + $output->writeln( + "Updating existing recipe from {$installedVersion} to {$constraint} " + . "(auto-detected constraint)" + ); + } else { + $output->writeln( + "Updating existing recipe from {$installedVersion} to latest version" + ); + } + } + } + + // Ensure composer require includes this recipe + $returnCode = $this->requireRecipe($output, $recipe, $constraint); + if ($returnCode) { + return $returnCode; + } + + // Begin modification of composer.json + $composerData = $this->loadComposer(getcwd() . '/composer.json'); + + // Get composer data for both root and newly installed recipe + $installedRecipe = $this + ->getComposer() + ->getRepositoryManager() + ->getLocalRepository() + ->findPackage($recipe, '*'); + if ($installedRecipe) { + $output->writeln("Inlining all dependencies for recipe {$recipe}:"); + foreach ($installedRecipe->getRequires() as $requireName => $require) { + $requireVersion = $require->getPrettyConstraint(); + $output->writeln( + " * Inline dependency {$requireName} as {$requireVersion}" + ); + $composerData['require'][$requireName] = $requireVersion; + } + } + + // Move recipe from 'require' to 'provide' + $installedVersion = $this->findInstalledVersion($recipe) ?: $installedVersion; + unset($composerData['require'][$recipe]); + if (!isset($composerData['provide'])) { + $composerData['provide'] = []; + } + $composerData['provide'][$recipe] = $installedVersion; + + // Update composer.json and synchronise composer.lock + $this->saveComposer(getcwd(), $composerData); + return $this->updateProject($output); + } } diff --git a/src/RecipeCommandProvider.php b/src/RecipeCommandProvider.php index 167c567..8e2c10e 100644 --- a/src/RecipeCommandProvider.php +++ b/src/RecipeCommandProvider.php @@ -15,7 +15,8 @@ class RecipeCommandProvider implements CommandProvider public function getCommands() { return [ - new RequireRecipeCommand() + new RequireRecipeCommand(), + new UpdateRecipeCommand(), ]; } } diff --git a/src/RequireRecipeCommand.php b/src/RequireRecipeCommand.php index f514cfd..ed4d806 100644 --- a/src/RequireRecipeCommand.php +++ b/src/RequireRecipeCommand.php @@ -58,63 +58,8 @@ HELP // Check if this is already installed and notify users $installedVersion = $this->findInstalledVersion($recipe); - if ($installedVersion) { - if ($constraint) { - $output->writeln( - "Updating existing recipe from {$installedVersion} to {$constraint}" - ); - } else { - // Show a guessed constraint - $constraint = $this->findBestConstraint($installedVersion); - if ($constraint) { - $output->writeln( - "Updating existing recipe from {$installedVersion} to {$constraint} " - . "(auto-detected constraint)" - ); - } else { - $output->writeln( - "Updating existing recipe from {$installedVersion} to latest version" - ); - } - } - } - // Ensure composer require includes this recipe - $returnCode = $this->requireRecipe($output, $recipe, $constraint); - if ($returnCode) { - return $returnCode; - } - - // Begin modification of composer.json - $composerData = $this->loadComposer(getcwd() .'/composer.json'); - - // Get composer data for both root and newly installed recipe - $installedRecipe = $this - ->getComposer() - ->getRepositoryManager() - ->getLocalRepository() - ->findPackage($recipe, '*'); - if ($installedRecipe) { - $output->writeln("Inlining all dependencies for recipe {$recipe}:"); - foreach ($installedRecipe->getRequires() as $requireName => $require) { - $requireVersion = $require->getPrettyConstraint(); - $output->writeln( - " * Inline dependency {$requireName} as {$requireVersion}" - ); - $composerData['require'][$requireName] = $requireVersion; - } - } - - // Move recipe from 'require' to 'provide' - $installedVersion = $this->findInstalledVersion($recipe) ?: $installedVersion; - unset($composerData['require'][$recipe]); - if (!isset($composerData['provide'])) { - $composerData['provide'] = []; - } - $composerData['provide'][$recipe] = $installedVersion; - - // Update composer.json and synchronise composer.lock - $this->saveComposer(getcwd(), $composerData); - return $this->updateProject($output); + // Install recipe + return $this->installRecipe($output, $recipe, $constraint, $installedVersion); } } diff --git a/src/UpdateRecipeCommand.php b/src/UpdateRecipeCommand.php new file mode 100644 index 0000000..0d5fe57 --- /dev/null +++ b/src/UpdateRecipeCommand.php @@ -0,0 +1,54 @@ +setName('update-recipe'); + $this->setDescription('Invoke this command to update an existing recipe'); + $this->addArgument( + 'recipe', + InputArgument::REQUIRED, + 'Recipe name to require inline' + ); + $this->addArgument( + 'version', + InputArgument::OPTIONAL, + 'Version or constraint to update to' + ); + $this->addUsage('silverstripe/recipe-blogging'); + $this->setHelp( + <<getArgument('recipe'); + $constraint = $input->getArgument('version'); + + // Check if this is already installed and notify users + $installedVersion = $this->findInstalledVersion($recipe); + if (!$installedVersion) { + throw new BadMethodCallException( + "Recipe {$recipe} is not installed. Please install with require or require-recipe first" + ); + } + + // Update recipe + return $this->installRecipe($output, $recipe, $constraint, $installedVersion); + } +}