From b43bcd320a39e00351f72e806576d91b7cadf585 Mon Sep 17 00:00:00 2001 From: "yash.rode" <yash.rode@3685174.no-reply.drupal.org> Date: Wed, 19 Oct 2022 13:23:03 +0000 Subject: [PATCH] Issue #3257134 by phenaproxima, yash.rode, tedbow: Don't stage node_modules directories --- package_manager/package_manager.services.yml | 6 ++ .../src/PathExcluder/NodeModulesExcluder.php | 66 +++++++++++++++++++ .../fake_site/core/node_modules/ignore.txt | 1 + .../modules/example/node_modules/ignore.txt | 1 + .../PathExcluder/NodeModulesExcluderTest.php | 58 ++++++++++++++++ 5 files changed, 132 insertions(+) create mode 100644 package_manager/src/PathExcluder/NodeModulesExcluder.php create mode 100644 package_manager/tests/fixtures/fake_site/core/node_modules/ignore.txt create mode 100644 package_manager/tests/fixtures/fake_site/modules/example/node_modules/ignore.txt create mode 100644 package_manager/tests/src/Kernel/PathExcluder/NodeModulesExcluderTest.php diff --git a/package_manager/package_manager.services.yml b/package_manager/package_manager.services.yml index 46f0a71f30..410e3ccce8 100644 --- a/package_manager/package_manager.services.yml +++ b/package_manager/package_manager.services.yml @@ -181,6 +181,12 @@ services: - '@package_manager.path_locator' tags: - { name: event_subscriber } + package_manager.node_modules_excluder: + class: Drupal\package_manager\PathExcluder\NodeModulesExcluder + arguments: + - '@package_manager.path_locator' + tags: + - { name: event_subscriber } package_manager.uninstall_validator: class: Drupal\package_manager\PackageManagerUninstallValidator tags: diff --git a/package_manager/src/PathExcluder/NodeModulesExcluder.php b/package_manager/src/PathExcluder/NodeModulesExcluder.php new file mode 100644 index 0000000000..a6e0a675c8 --- /dev/null +++ b/package_manager/src/PathExcluder/NodeModulesExcluder.php @@ -0,0 +1,66 @@ +<?php + +namespace Drupal\package_manager\PathExcluder; + +use Drupal\package_manager\Event\PreApplyEvent; +use Drupal\package_manager\Event\PreCreateEvent; +use Drupal\package_manager\Event\StageEvent; +use Drupal\package_manager\PathLocator; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\Finder\Finder; + +/** + * Excludes node_modules files from staging areas. + * + * @internal + * This is an internal part of Package Manager and may be changed or removed + * at any time without warning. External code should not interact with this + * class. + */ +class NodeModulesExcluder implements EventSubscriberInterface { + + use PathExclusionsTrait; + + /** + * Constructs a NodeModulesExcluder object. + * + * @param \Drupal\package_manager\PathLocator $path_locator + * The path locator service. + */ + public function __construct(PathLocator $path_locator) { + $this->pathLocator = $path_locator; + } + + /** + * Excludes node_modules directories from staging operations. + * + * @param \Drupal\package_manager\Event\PreApplyEvent|\Drupal\package_manager\Event\PreCreateEvent $event + * The event object. + * + * @see \Drupal\package_manager\Event\ExcludedPathsTrait::excludePath() + */ + public function excludeNodeModulesFiles(StageEvent $event): void { + $finder = Finder::create() + ->in($this->pathLocator->getProjectRoot()) + ->directories() + ->name('node_modules') + ->ignoreVCS(FALSE) + ->ignoreDotFiles(FALSE); + $paths = []; + foreach ($finder as $directory) { + $paths[] = $directory->getPathname(); + } + $this->excludeInProjectRoot($event, $paths); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents(): array { + return [ + PreCreateEvent::class => 'excludeNodeModulesFiles', + PreApplyEvent::class => 'excludeNodeModulesFiles', + ]; + } + +} diff --git a/package_manager/tests/fixtures/fake_site/core/node_modules/ignore.txt b/package_manager/tests/fixtures/fake_site/core/node_modules/ignore.txt new file mode 100644 index 0000000000..08874eba8b --- /dev/null +++ b/package_manager/tests/fixtures/fake_site/core/node_modules/ignore.txt @@ -0,0 +1 @@ +This file should never be staged. diff --git a/package_manager/tests/fixtures/fake_site/modules/example/node_modules/ignore.txt b/package_manager/tests/fixtures/fake_site/modules/example/node_modules/ignore.txt new file mode 100644 index 0000000000..08874eba8b --- /dev/null +++ b/package_manager/tests/fixtures/fake_site/modules/example/node_modules/ignore.txt @@ -0,0 +1 @@ +This file should never be staged. diff --git a/package_manager/tests/src/Kernel/PathExcluder/NodeModulesExcluderTest.php b/package_manager/tests/src/Kernel/PathExcluder/NodeModulesExcluderTest.php new file mode 100644 index 0000000000..006e207126 --- /dev/null +++ b/package_manager/tests/src/Kernel/PathExcluder/NodeModulesExcluderTest.php @@ -0,0 +1,58 @@ +<?php + +namespace Drupal\Tests\package_manager\Kernel\PathExcluder; + +use Drupal\Tests\package_manager\Kernel\PackageManagerKernelTestBase; + +/** + * @covers \Drupal\package_manager\PathExcluder\NodeModulesExcluder + * + * @group package_manager + */ +class NodeModulesExcluderTest extends PackageManagerKernelTestBase { + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + // In this test, we want to disable the lock file validator because, even + // though both the active and stage directories will have a valid lock file, + // this validator will complain because they don't differ at all. + $this->disableValidators[] = 'package_manager.validator.lock_file'; + parent::setUp(); + } + + /** + * Tests that node_modules directories are excluded from staging operations. + */ + public function testExcludedPaths(): void { + // In this test, we want to perform the actual staging operations so that we + // can be sure that files are staged as expected. + $this->setSetting('package_manager_bypass_composer_stager', FALSE); + // Ensure we have an up-to-date container. + $this->container = $this->container->get('kernel')->rebuildContainer(); + + $active_dir = $this->container->get('package_manager.path_locator') + ->getProjectRoot(); + + $stage = $this->createStage(); + $stage->create(); + $stage_dir = $stage->getStageDirectory(); + + $ignored = [ + "core/node_modules/ignore.txt", + 'modules/example/node_modules/ignore.txt', + ]; + foreach ($ignored as $path) { + $this->assertFileExists("$active_dir/$path"); + $this->assertFileDoesNotExist("$stage_dir/$path"); + } + + $stage->apply(); + // The ignored files should still be in the active directory. + foreach ($ignored as $path) { + $this->assertFileExists("$active_dir/$path"); + } + } + +} -- GitLab