Skip to content
Snippets Groups Projects
Commit e7953e24 authored by Adam G-H's avatar Adam G-H Committed by Wim Leers
Browse files

Issue #3345762: GitExcluder should use ComposerInspector instead of ComposerUtility

parent b7fadb4d
No related branches found
No related tags found
No related merge requests found
......@@ -7,6 +7,7 @@ namespace Drupal\package_manager\Event;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\package_manager\Stage;
use Drupal\package_manager\ValidationResult;
use Drupal\system\SystemManager;
/**
* Event fired to check the status of the system to use Package Manager.
......@@ -16,19 +17,37 @@ use Drupal\package_manager\ValidationResult;
*/
class StatusCheckEvent extends PreOperationStageEvent {
use ExcludedPathsTrait;
/**
* Returns paths to exclude or NULL if a base requirement is not fulfilled.
*
* @return string[]|null
* The paths to exclude, or NULL if a base requirement is not fulfilled.
*
* @throws \LogicException
* Thrown if the excluded paths are NULL and no errors have been added to
* this event.
*/
public function getExcludedPaths(): ?array {
if (isset($this->excludedPaths)) {
return array_unique($this->excludedPaths);
}
if (empty($this->getResults(SystemManager::REQUIREMENT_ERROR))) {
throw new \LogicException('$ignored_paths should only be NULL if the error that caused the paths to not be collected was added to the status check event.');
}
return NULL;
}
/**
* Constructs a StatusCheckEvent object.
*
* @param \Drupal\package_manager\Stage $stage
* The stage which fired this event.
* @param string[] $ignored_paths
* The list of ignored paths.
* @param string[]|null $excludedPaths
* The list of ignored paths, or NULL if they could not be collected.
*/
public function __construct(Stage $stage, array $ignored_paths) {
public function __construct(Stage $stage, private ?array $excludedPaths) {
parent::__construct($stage);
$this->excludedPaths = $ignored_paths;
}
/**
......
......@@ -4,7 +4,7 @@ declare(strict_types = 1);
namespace Drupal\package_manager\PathExcluder;
use Drupal\Core\File\FileSystemInterface;
use Drupal\package_manager\ComposerInspector;
use Drupal\package_manager\Event\CollectIgnoredPathsEvent;
use Drupal\package_manager\PathLocator;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
......@@ -26,10 +26,10 @@ final class GitExcluder implements EventSubscriberInterface {
*
* @param \Drupal\package_manager\PathLocator $path_locator
* The path locator service.
* @param \Drupal\Core\File\FileSystemInterface $fileSystem
* The file system service.
* @param \Drupal\package_manager\ComposerInspector $composerInspector
* The Composer inspector service.
*/
public function __construct(PathLocator $path_locator, protected FileSystemInterface $fileSystem) {
public function __construct(PathLocator $path_locator, private ComposerInspector $composerInspector) {
$this->pathLocator = $path_locator;
}
......@@ -53,10 +53,11 @@ final class GitExcluder implements EventSubscriberInterface {
$installed_paths = [];
// Collect the paths of every installed package.
$installed_packages = $event->stage->getActiveComposer()->getInstalledPackagesData();
foreach ($installed_packages as $package_data) {
if (array_key_exists('install_path', $package_data) && !empty($package_data['install_path'])) {
$installed_paths[] = $this->fileSystem->realpath($package_data['install_path']);
$project_root = $this->pathLocator->getProjectRoot();
$installed_packages = $this->composerInspector->getInstalledPackagesList($project_root);
foreach ($installed_packages as $package) {
if (!empty($package->path)) {
$installed_paths[] = $package->path;
}
}
$paths = $this->scanForDirectoriesByName('.git');
......
......@@ -33,15 +33,22 @@ trait StatusCheckTrait {
protected function runStatusCheck(Stage $stage, EventDispatcherInterface $event_dispatcher = NULL): array {
$event_dispatcher ??= \Drupal::service('event_dispatcher');
try {
$ignored_paths = new CollectIgnoredPathsEvent($stage);
$event_dispatcher->dispatch($ignored_paths);
$ignored_paths_event = new CollectIgnoredPathsEvent($stage);
$event_dispatcher->dispatch($ignored_paths_event);
$event = new StatusCheckEvent($stage, $ignored_paths_event->getAll());
}
catch (\Throwable $throwable) {
// We can't dispatch the status check event without the ignored paths.
return [ValidationResult::createErrorFromThrowable($throwable, t("Unable to collect ignored paths, therefore can't perform status checks."))];
// We can dispatch the status check event without the ignored paths, but
// it must be set explicitly to NULL, to allow those status checks to run
// that do not need the ignored paths.
$event = new StatusCheckEvent($stage, NULL);
// Add the error that was encountered so that regardless of any other
// validation errors BaseRequirementsFulfilledValidator will stop the
// event propagation after the base requirement validators have run.
// @see \Drupal\package_manager\Validator\BaseRequirementsFulfilledValidator
$event->addErrorFromThrowable($throwable, t('Unable to collect the ignored paths.'));
}
$event = new StatusCheckEvent($stage, $ignored_paths->getAll());
$event_dispatcher->dispatch($event);
return $event->getResults();
}
......
......@@ -69,8 +69,16 @@ class SymlinkValidator implements EventSubscriberInterface {
}
$stage_dir = $this->pathFactory->create($stage_dir);
$ignored_paths = $event->getExcludedPaths();
// Return early if no ignored paths were collected because this validator
// is dependent on knowing which paths to ignore when searching for
// symlinks.
// @see \Drupal\package_manager\StatusCheckTrait::runStatusCheck()
if ($ignored_paths === NULL) {
return;
}
try {
$ignored_paths = $event->getExcludedPaths();
$this->precondition->assertIsFulfilled($active_dir, $stage_dir, new PathList($ignored_paths));
}
catch (PreconditionException $e) {
......
......@@ -4,8 +4,6 @@ declare(strict_types = 1);
namespace Drupal\Tests\package_manager\Kernel\PathExcluder;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Serialization\Yaml;
use Drupal\fixture_manipulator\ActiveFixtureManipulator;
use Drupal\Tests\package_manager\Kernel\PackageManagerKernelTestBase;
......@@ -18,13 +16,6 @@ use Symfony\Component\Filesystem\Filesystem;
*/
class GitExcluderTest extends PackageManagerKernelTestBase {
/**
* The mocked file system service.
*
* @var \Drupal\Core\File\FileSystemInterface|\Prophecy\Prophecy\ObjectProphecy
*/
private $fileSystem;
/**
* {@inheritdoc}
*/
......@@ -43,18 +34,6 @@ class GitExcluderTest extends PackageManagerKernelTestBase {
->commitChanges();
}
/**
* {@inheritdoc}
*/
public function register(ContainerBuilder $container) {
parent::register($container);
$this->fileSystem = $this->prophesize(FileSystemInterface::class);
$container->getDefinition('package_manager.git_excluder')
->setArgument('$fileSystem', $this->fileSystem->reveal());
}
/**
* Tests that Git directories are excluded from stage during PreCreate.
*/
......
......@@ -616,9 +616,8 @@ class StageTest extends PackageManagerKernelTestBase {
->getProjectRoot();
unlink($project_root . '/composer.json');
$this->expectException(StageException::class);
$this->expectExceptionMessage("Composer could not find the config file: $project_root/composer.json\n");
$stage = $this->createStage();
$stage->create();
$this->expectExceptionMessage("composer.json not found.");
$this->createStage()->create();
}
/**
......
......@@ -36,21 +36,17 @@ class StatusCheckTraitTest extends PackageManagerKernelTestBase {
}
/**
* Tests StatusCheckTrait returns an error when unable to get ignored paths.
* Tests that any error will be added to the status check event.
*/
public function testErrorIgnoredPathsCollected(): void {
$exception = new \Exception("Not a chance, friend.");
$expected_result = ValidationResult::createErrorFromThrowable(
$exception,
t("Unable to collect ignored paths, therefore can't perform status checks.")
);
$this->addEventTestListener(function () use ($exception): void {
throw $exception;
public function testNoErrorIfIgnoredPathsCannotBeCollected(): void {
$this->addEventTestListener(function (): void {
throw new \Exception('Not a chance, friend.');
}, CollectIgnoredPathsEvent::class);
$this->assertStatusCheckResults([$expected_result]);
$result = ValidationResult::createError(
[t('Not a chance, friend.')],
t('Unable to collect the ignored paths.'),
);
$this->assertStatusCheckResults([$result]);
}
}
<?php
declare(strict_types = 1);
namespace Drupal\Tests\package_manager\Unit;
use Drupal\package_manager\Event\StatusCheckEvent;
use Drupal\package_manager\Stage;
use Drupal\Tests\UnitTestCase;
/**
* @coversDefaultClass \Drupal\package_manager\Event\StatusCheckEvent
* @group package_manager
*/
class StatusCheckEventTest extends UnitTestCase {
/**
* @covers ::getExcludedPaths
*/
public function testNoPathsNoErrorException(): void {
$event = new StatusCheckEvent(
$this->prophesize(Stage::class)->reveal(),
NULL
);
$this->expectException(\LogicException::class);
$this->expectExceptionMessage('$ignored_paths should only be NULL if the error that caused the paths to not be collected was added to the status check event.');
$event->getExcludedPaths();
}
}
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