From 9cf5df77abcbceefa84e5ddd10db67865870394b Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Fri, 26 Jul 2019 16:04:00 +0200 Subject: [PATCH] Add --watch option to cache:clear command --- .../Command/CacheClearCommand.php | 54 +++++++++++++++++++ .../Bundle/FrameworkBundle/composer.json | 1 + 2 files changed, 55 insertions(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php index 24aa8171ca5ef..70accacf18d69 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php @@ -16,6 +16,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\OutputStyle; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Filesystem\Exception\IOException; @@ -56,6 +57,7 @@ protected function configure() ->setDefinition([ new InputOption('no-warmup', '', InputOption::VALUE_NONE, 'Do not warm up the cache'), new InputOption('no-optional-warmers', '', InputOption::VALUE_NONE, 'Skip optional cache warmers (faster)'), + new InputOption('watch', '', InputOption::VALUE_NONE, 'Watch files and recompile whenever they change'), ]) ->setDescription('Clears the cache') ->setHelp(<<<'EOF' @@ -175,6 +177,10 @@ protected function execute(InputInterface $input, OutputInterface $output) } $io->success(sprintf('Cache for the "%s" environment (debug=%s) was successfully cleared.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); + + if ($input->getOption('watch')) { + $this->watch($kernel->getContainer()->getParameter('kernel.project_dir'), $realCacheDir, $io); + } } private function warmup(string $warmupDir, string $realCacheDir, bool $enableOptionalWarmers = true) @@ -204,4 +210,52 @@ private function warmup(string $warmupDir, string $realCacheDir, bool $enableOpt } } } + + private function watch(string $projectDir, string $realCacheDir, OutputStyle $io) + { + if (!\function_exists('inotify_init')) { + throw new \RuntimeException('The "inotify" extension is required for watching the project files.'); + } + + $io->comment('Preparing for watching...'); + + $watchers = []; + $inotify = inotify_init(); + $baseMask = IN_CREATE | IN_ATTRIB | IN_MODIFY | IN_MOVE | IN_MOVE_SELF | IN_DELETE | IN_DELETE_SELF; + $watchers[inotify_add_watch($inotify, $projectDir, $baseMask)] = $projectDir; + foreach (Finder::create()->in($projectDir)->directories()->exclude([substr($realCacheDir, \strlen($projectDir) + 1), 'vendor'])->sortByName() as $dir) { // FIXME ignoreVCSIgnored(true) does not work here + $watchers[inotify_add_watch($inotify, $dir->getRealPath(), $baseMask)] = $dir; + } + + $io->comment(sprintf('Watching %s (%s subdirs)', $projectDir, \count($watchers))); + + while ($events = inotify_read($inotify)) { + $paths = []; + foreach ($events as $e) { + $path = rtrim($watchers[$e['wd']].'/'.$e['name'], '/'); + $paths[$path] = ($paths[$path] ?? 0) | $e['mask']; + } + + $warmup = false; + foreach ($paths as $path => $mask) { + if ($mask & IN_CREATE && is_dir($path)) { + $watchers[inotify_add_watch($inotify, $path, $baseMask)] = $path; + $io->write(substr($path, \strlen($projectDir) + 1).' '); + } + if ($mask & $baseMask) { + $warmup = true; + $io->write(substr($path, \strlen($projectDir) + 1).' '); + } + } + + if ($warmup) { + try { + $this->warmup($realCacheDir, $realCacheDir); + $io->writeln('ok'); + } catch (\Exception $e) { + $io->writeln(sprintf('%s', $e->getMessage())); + } + } + } + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 3c4f7f0b0b0af..87c1c9efd5aaf 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -86,6 +86,7 @@ }, "suggest": { "ext-apcu": "For best performance of the system caches", + "ext-inotify": "For watching files and recompiling whenever they change", "symfony/console": "For using the console commands", "symfony/form": "For using forms", "symfony/serializer": "For using the serializer service", pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy