Skip to content
Snippets Groups Projects
Commit badd6080 authored by Yash Rode's avatar Yash Rode Committed by Ted Bowman
Browse files

Issue #3320836 by yash.rode, TravisCarden, tedbow: Handle runtime error...

Issue #3320836 by yash.rode, TravisCarden, tedbow: Handle runtime error correctly in ComposerExecutableValidator
parent 0d6f4b70
No related branches found
No related tags found
No related merge requests found
......@@ -67,6 +67,8 @@ services:
- '@PhpTuf\ComposerStager\Domain\Service\ProcessRunner\ComposerRunnerInterface'
- '@module_handler'
- '@string_translation'
- '@PhpTuf\ComposerStager\Domain\Service\Precondition\ComposerIsAvailableInterface'
- '@PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface'
tags:
- { name: event_subscriber }
package_manager.validator.disk_space:
......
......@@ -13,8 +13,11 @@ use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\package_manager\Event\StatusCheckEvent;
use PhpTuf\ComposerStager\Domain\Exception\ExceptionInterface;
use PhpTuf\ComposerStager\Domain\Exception\PreconditionException;
use PhpTuf\ComposerStager\Domain\Service\Precondition\ComposerIsAvailableInterface;
use PhpTuf\ComposerStager\Domain\Service\ProcessOutputCallback\ProcessOutputCallbackInterface;
use PhpTuf\ComposerStager\Domain\Service\ProcessRunner\ComposerRunnerInterface;
use PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
......@@ -43,6 +46,13 @@ class ComposerExecutableValidator implements EventSubscriberInterface {
*/
protected $composer;
/**
* The "Composer is available" precondition service.
*
* @var \PhpTuf\ComposerStager\Domain\Service\Precondition\ComposerIsAvailableInterface
*/
protected $composerIsAvailable;
/**
* The module handler service.
*
......@@ -50,6 +60,13 @@ class ComposerExecutableValidator implements EventSubscriberInterface {
*/
protected $moduleHandler;
/**
* The path factory service.
*
* @var \PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface
*/
protected $pathFactory;
/**
* Constructs a ComposerExecutableValidator object.
*
......@@ -59,17 +76,38 @@ class ComposerExecutableValidator implements EventSubscriberInterface {
* The module handler service.
* @param \Drupal\Core\StringTranslation\TranslationInterface $translation
* The translation service.
* @param \PhpTuf\ComposerStager\Domain\Service\Precondition\ComposerIsAvailableInterface $composer_is_available
* The "Composer is available" precondition service.
* @param \PhpTuf\ComposerStager\Infrastructure\Factory\Path\PathFactoryInterface $path_factory
* The path factory service.
*/
public function __construct(ComposerRunnerInterface $composer, ModuleHandlerInterface $module_handler, TranslationInterface $translation) {
public function __construct(ComposerRunnerInterface $composer, ModuleHandlerInterface $module_handler, TranslationInterface $translation, ComposerIsAvailableInterface $composer_is_available, PathFactoryInterface $path_factory) {
$this->composer = $composer;
$this->moduleHandler = $module_handler;
$this->setStringTranslation($translation);
$this->composerIsAvailable = $composer_is_available;
$this->pathFactory = $path_factory;
}
/**
* {@inheritdoc}
*/
public function validateStagePreOperation(PreOperationStageEvent $event): void {
// Return early if Composer is not available.
try {
// The "Composer is available" precondition requires active and staging
// directories, but they don't actually matter to it, nor do path
// exclusions, so dummies can be passed for simplicity.
$active_dir = $this->pathFactory::create(__DIR__);
$stage_dir = $active_dir;
$this->composerIsAvailable->assertIsFulfilled($active_dir, $stage_dir);
}
catch (PreconditionException $e) {
$event->addError([$e->getMessage()]);
return;
}
try {
$output = $this->runCommand();
}
......
......@@ -10,7 +10,10 @@ use Drupal\package_manager\Event\PreCreateEvent;
use Drupal\package_manager\Validator\ComposerExecutableValidator;
use Drupal\package_manager\ValidationResult;
use PhpTuf\ComposerStager\Domain\Exception\IOException;
use PhpTuf\ComposerStager\Domain\Exception\LogicException;
use PhpTuf\ComposerStager\Infrastructure\Service\Finder\ExecutableFinderInterface;
use PHPUnit\Framework\Assert;
use Symfony\Component\DependencyInjection\Reference;
/**
* @covers \Drupal\package_manager\Validator\ComposerExecutableValidator
......@@ -27,6 +30,8 @@ class ComposerExecutableValidatorTest extends PackageManagerKernelTestBase {
$container->getDefinition('package_manager.validator.composer_executable')
->setClass(TestComposerExecutableValidator::class);
$container
->register('test.terrible_composer_finder', TestFailingComposerFinder::class);
}
/**
......@@ -47,6 +52,26 @@ class ComposerExecutableValidatorTest extends PackageManagerKernelTestBase {
$this->assertResultsWithHelp([$error], PreCreateEvent::class);
}
/**
* Test RuntimeError is handled correctly.
*/
public function testComposerNotFound(): void {
// @see \PhpTuf\ComposerStager\Infrastructure\Service\Precondition\ComposerIsAvailable::getUnfulfilledStatusMessage()
$exception = new \Exception('Composer cannot be found.');
TestComposerExecutableValidator::setCommandOutput($exception);
// Change ComposerRunnerInterface path to throw a LogicException.
$definition = $this->container->getDefinition('PhpTuf\ComposerStager\Domain\Service\Precondition\ComposerIsAvailableInterface');
$definition->setArgument(0, new Reference('test.terrible_composer_finder'));
// The validator should translate that exception into an error.
$error = ValidationResult::createError([
$exception->getMessage(),
]);
$this->assertStatusCheckResults([$error]);
$this->assertResults([$error], PreCreateEvent::class);
}
/**
* Data provider for testComposerVersionValidation().
*
......@@ -212,3 +237,17 @@ class TestComposerExecutableValidator extends ComposerExecutableValidator {
}
}
/**
* A test-only version of ExecutableFinderInterface that throws LogicException.
*/
class TestFailingComposerFinder implements ExecutableFinderInterface {
/**
* {@inheritdoc}
*/
public function find(string $name): string {
throw new LogicException();
}
}
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