Skip to content
Snippets Groups Projects
Commit 2d8b2289 authored by Ted Bowman's avatar Ted Bowman
Browse files

Issue #3409491: Add handling of the Composer dependencies to the conversion script

parent e4fe8675
No related branches found
No related tags found
1 merge request!997Issue #3409491 add composer dependencies in conversion script
......@@ -29,14 +29,14 @@
"Composer\\Config::disableProcessTimeout",
"scripts/phpunit.sh"
],
"core-convert": "Drupal\\automatic_updates\\Development\\Converter::doConvert",
"core-commit": "Drupal\\automatic_updates\\Development\\Converter::makeCommit"
"core-convert": "Drupal\\automatic_updates\\Development\\ConverterCommand",
"core-commit": "Drupal\\automatic_updates\\Development\\ConverterCommand::makeCommit"
},
"scripts-descriptions": {
"phpcbf": "Automatically fixes standards violations where possible.",
"phpcs": "Checks code for standards compliance.",
"test": "Runs PHPUnit tests.",
"core-convert": "Converts this module to a core merge request. Excepts 2 arguments. 1) The core clone directory. 2) The core merge request branch.",
"core-convert": "Converts this module to a core merge request. For arguments and options see \\Drupal\\automatic_updates\\Development\\ConverterCommand::configure().",
"core-commit": "Converts this module to a core merge request. Excepts 1 arguments. The core clone directory."
},
"autoload": {
......
......@@ -5,6 +5,11 @@ declare(strict_types = 1);
namespace Drupal\automatic_updates\Development;
use Composer\Script\Event;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Filesystem\Filesystem;
/**
......@@ -20,9 +25,114 @@ use Symfony\Component\Filesystem\Filesystem;
*
* The core clone should already have the core merge request locally.
*/
class Converter {
class ConverterCommand extends Command {
private const RUN_CHECKS = TRUE;
private string $core_dir;
private string $core_branch;
private string $contrib_branch;
private bool $package_manager_only;
private string $core_target_branch;
private string $contrib_dir;
private bool $no_commit;
private bool $skipCoreChecks;
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output) {
$this->core_dir = $input->getArgument('core_dir');
$this->core_branch = $input->getArgument('core_branch');
$this->contrib_branch = $input->getArgument('contrib_branch');
$this->package_manager_only = $input->getOption('package_manager_only');
$this->core_target_branch = $input->getOption('core_target_branch');
$this->contrib_dir = realpath(__DIR__ . '/../..');
$this->skipCoreChecks = $input->getOption('skip_core_checks');
$this->no_commit = $input->getOption('no_commit');
// Esnure core_dir is a directory.
if (!is_dir($this->core_dir)) {
throw new \Exception("$this->core_dir is not a directory.");
}
// Switch to core_target_branch to ensure it is clean.
chdir($this->core_dir);
static::switchToBranch($this->core_target_branch);
// Git pull to ensure we are up to date.
static::executeCommand('git pull');
// change back the previous directory.
chdir($this->contrib_dir);
// Ensure we are on the correct branches.
static::switchToBranches($this->core_dir, $this->core_branch, $this->contrib_branch);
// Switch to the core directory and checkout the files and folders that this
// conversion script will automatically update based on our composer.json
// file and our dictionary.txt file.
chdir($this->core_dir);
static::executeCommand("git checkout {$this->core_target_branch} -- composer.json");
static::executeCommand("git checkout {$this->core_target_branch} -- composer.lock");
static::executeCommand("git checkout {$this->core_target_branch} -- composer");
static::executeCommand("git checkout {$this->core_target_branch} -- core/composer.json");
static::executeCommand("git checkout {$this->core_target_branch} -- core/misc/cspell/dictionary.txt");
// Switch to the core directory and require all of the packages there are in
// this module's composer.json require section.
chdir('core');
$require_section = $this->getContribModuleComposerJsonSection('require');
// Hardcode symfony version to 6.4 for core.
$core_symfony_version_update = function ($package_name, $version): string {
if (str_starts_with($package_name, 'symfony/')) {
return '^6.4';
}
return $version;
};
foreach ($require_section as $package_name => $version) {
$version = $core_symfony_version_update($package_name, $version);
static::executeCommand("composer require $package_name:$version --no-update");
}
// Switch back to the parent directory.
chdir('..');
// Run composer update for just this packages.
static::executeCommand("composer update " . implode(' ', array_keys($require_section)));
$require_dev_section = $this->getContribModuleComposerJsonSection('require-dev');
foreach ($require_dev_section as $package_name => $version) {
$version = $core_symfony_version_update($package_name, $version);
static::executeCommand("composer require --dev $package_name:$version");
}
$this->doConvert();
return Command::SUCCESS;
}
/**
* Executes a command and throws an exception if it fails.
*
* @param string $cmd
* The command to execute.
*/
private static function executeCommand(string $cmd): void {
$result = NULL;
system($cmd, $result);
if ($result !== 0) {
throw new \Exception("Command failed: $cmd");
}
}
/**
* {@inheritdoc}
*/
protected function configure() {
$this->addArgument('core_dir', InputArgument::REQUIRED, 'The path to the root of Drupal Core');
$this->addArgument('core_branch', InputArgument::REQUIRED, 'The core merge request branch');
$this->addArgument('contrib_branch', InputArgument::OPTIONAL, 'The contrib branch to switch to', '3.0.x');
$this->addOption('package_manager_only', NULL, InputOption::VALUE_NONE, 'Only convert package manager');
$this->addOption('core_target_branch', NULL, InputOption::VALUE_REQUIRED, 'The core target branch', '11.x');
$this->addOption('skip_core_checks', NULL, InputOption::VALUE_NONE, 'Skip core checks');
$this->addOption('no_commit', NULL, InputOption::VALUE_NONE, 'Do not make commit');
}
/**
* Prints message.
......@@ -36,36 +146,15 @@ class Converter {
/**
* Converts the contrib module to core merge request.
*
* @param \Composer\Script\Event $event
* The Composer event.
*/
public static function doConvert(Event $event): void {
$args = $event->getArguments();
$count_arg = count($args);
if (!($count_arg === 3 || $count_arg === 4)) {
throw new \Exception("This scripts 3 required arguments: a directory that is a core clone and the branch and to convert either package_manager or automatic_updates.\nIt has 1 optional arguments: the branch of this module to use which defaults to 3.0.x");
}
$core_dir = $args[0];
$core_branch = $args[1];
if (!is_dir($core_dir)) {
throw new \Exception("$core_dir is not a directory.");
}
$package_manager_only = match($args[2]) {
'package_manager' => TRUE,
'automatic_updates' => FALSE,
default => throw new \UnexpectedValueException("The 3nd argument must be package_manager or automatic_updates"),
};
$contrib_branch = $count_arg === 3 ? '3.0.x' : $args[3];
private function doConvert(): void {
$old_machine_name = 'automatic_updates';
$new_machine_name = 'auto_updates';
static::switchToBranches($core_dir, $core_branch, $contrib_branch);
self::info('Switched branches');
$fs = new Filesystem();
$core_module_path = static::getCoreModulePath($core_dir);
$package_manager_core_path = $core_dir . "/core/modules/package_manager";
$core_module_path = static::getCoreModulePath($this->core_dir);
$package_manager_core_path = $this->core_dir . "/core/modules/package_manager";
// Remove old module.
$fs->remove($core_module_path);
self::info('Removed old core module');
......@@ -93,10 +182,10 @@ class Converter {
}
self::info('Replacements done.');
static::removeLines($core_dir);
static::removeLines($this->core_dir);
self::info('Remove unneeded lines');
self::moveScripts($core_dir, $core_module_path, $package_manager_only);
self::moveScripts($this->core_dir, $core_module_path, $this->package_manager_only);
self::info('Moved scripts');
// Remove unneeded.
......@@ -135,36 +224,39 @@ class Converter {
$fs->rename("$core_module_path/package_manager", $package_manager_core_path);
self::info('Move package manager');
static::copyGenericTest($package_manager_core_path, $core_dir);
static::copyGenericTest($package_manager_core_path, $this->core_dir);
// Run phpcbf because removing code from merge request may result in unused
// use statements or multiple empty lines.
system("composer phpcbf $package_manager_core_path");
if ($package_manager_only) {
if ($this->package_manager_only) {
$fs->remove($core_module_path);
}
else {
static::copyGenericTest($core_module_path, $core_dir);
static::copyGenericTest($core_module_path, $this->core_dir);
system("composer phpcbf $core_module_path");
}
static::addWordsToDictionary($core_dir, self::getContribDir() . "/dictionary.txt");
static::addWordsToDictionary($this->core_dir, self::getContribDir() . "/dictionary.txt");
self::info("Added to dictionary");
chdir($core_dir);
chdir($this->core_dir);
if (self::RUN_CHECKS) {
static::runCoreChecks($core_dir);
self::info('Ran core checks');
if ($this->skipCoreChecks) {
self::info('⚠️Skipped core checks');
}
else {
self::info('⚠️Skipped core checks');
static::runCoreChecks($this->core_dir);
self::info('Ran core checks');
}
static::doMakeCommit($core_dir);
self::info('Make commit');
self::info("Done. Probably good but you should check before you push. These are the files present in the contrib module absent in core:");
print shell_exec(sprintf("tree %s/package_manager > /tmp/contrib.txt && tree %s/core/modules/package_manager > /tmp/core.txt && diff /tmp/contrib.txt /tmp/core.txt", self::getContribDir(), $core_dir));
self::info('(Run diff /tmp/contrib.txt /tmp/core.txt to see that with color.');
if (!$this->no_commit) {
static::doMakeCommit($this->core_dir);
self::info('Make commit');
self::info("Done. Probably good but you should check before you push. These are the files present in the contrib module absent in core:");
print shell_exec(sprintf("tree %s/package_manager > /tmp/contrib.txt && tree %s/core/modules/package_manager > /tmp/core.txt && diff /tmp/contrib.txt /tmp/core.txt", self::getContribDir(), $this->core_dir));
self::info('(Run diff /tmp/contrib.txt /tmp/core.txt to see that with color.');
}
}
/**
......@@ -344,7 +436,7 @@ class Converter {
static::ensureGitClean();
shell_exec("git checkout $branch");
if ($branch !== static::getCurrentBranch()) {
throw new \Exception("could not check $branch");
throw new \Exception("could not checkout $branch");
}
}
......@@ -546,4 +638,9 @@ class Converter {
static::replaceContents([new \SplFileInfo($new_test)], 'action', $module_name);
}
private function getContribModuleComposerJsonSection(string $section): array {
$composer_json = json_decode(file_get_contents($this->contrib_dir . '/composer.json'), TRUE);
return $composer_json[$section];
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment