Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

[AsseticBundle] inotify support for --watch option in assetic:dump command #205

Closed
wants to merge 2 commits into from

2 participants

Nils Adermann Kris Wallsmith
Nils Adermann

Using inotify the command does not need to busy wait for changes in any of the files defining formulae or containing assets anymore. It configures a number of inotify watches and reacts only once a change has been performed.

Depends on this pull request in assetic: kriswallsmith/assetic#13

naderman added some commits
Nils Adermann naderman [AsseticBundle] Throw exception if --watch is used without --debug. 94aacd0
Nils Adermann naderman [AsseticBundle] Implemented --watch without polling using inotify if …
…available

So far assetic:dump --watch would reload the entire asset manager once a second
to poll for changes to formulae, e.g. in template files, or changes to the
assets themselves. Now, when the inotify extension is installed it is used to
setup monitoring of the paths containing these files. The kernel will then
notify the console as soon as file changes are available and only then assets
will be regenerated.
c42c02d
Kris Wallsmith

I don't want to merge the Assetic pull request, so I suggest you deduce the asset path by using the read_from base directory. Ping me on Jabber if you want to discuss. Closing for now.

Johann Saunier ProPheT777 referenced this pull request from a commit
Fabien Potencier fabpot merged branch stealth35/add_tok (PR #205)
Commits
-------

4e6f7a5 Fix 169 Update requirements : tokenkizer

Discussion
----------

Fix #169 Update requirements : tokenkizer

Fix #169
7eb7a0b
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 9, 2011
  1. Nils Adermann
  2. Nils Adermann

    [AsseticBundle] Implemented --watch without polling using inotify if …

    naderman authored
    …available
    
    So far assetic:dump --watch would reload the entire asset manager once a second
    to poll for changes to formulae, e.g. in template files, or changes to the
    assets themselves. Now, when the inotify extension is installed it is used to
    setup monitoring of the paths containing these files. The kernel will then
    notify the console as soon as file changes are available and only then assets
    will be regenerated.
This page is out of date. Refresh to see the latest.
Showing with 93 additions and 12 deletions.
  1. +93 −12 src/Symfony/Bundle/AsseticBundle/Command/DumpCommand.php
105 src/Symfony/Bundle/AsseticBundle/Command/DumpCommand.php
View
@@ -33,7 +33,7 @@ protected function configure()
->setName('assetic:dump')
->setDescription('Dumps all assets to the filesystem')
->addArgument('write_to', InputArgument::OPTIONAL, 'Override the configured asset root')
- ->addOption('watch', null, InputOption::VALUE_NONE, 'Check for changes every second')
+ ->addOption('watch', null, InputOption::VALUE_NONE, 'Check for changes every second, debug mode only')
;
}
@@ -61,7 +61,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
* Watches a asset manager for changes.
*
* This method includes an infinite loop the continuously polls the asset
- * manager for changes.
+ * manager for changes. If available, inotify is used to wait for changes.
*
* @param LazyAssetManager $am The asset manager
* @param string $basePath The base directory to write to
@@ -70,6 +70,10 @@ protected function execute(InputInterface $input, OutputInterface $output)
*/
protected function watch(LazyAssetManager $am, $basePath, OutputInterface $output, $debug = false)
{
+ if (!$debug) {
+ throw new \RuntimeException('The --watch option is only available in debug mode.');
+ }
+
$refl = new \ReflectionClass('Assetic\\AssetManager');
$prop = $refl->getProperty('assets');
$prop->setAccessible(true);
@@ -81,25 +85,42 @@ protected function watch(LazyAssetManager $am, $basePath, OutputInterface $outpu
$previously = array();
}
+ if (function_exists('inotify_init')) {
+ $inotify = inotify_init();
+ } else {
+ $inotify = false;
+ }
+
$error = '';
while (true) {
try {
- foreach ($am->getNames() as $name) {
- if ($asset = $this->checkAsset($am, $name, $previously)) {
- $this->dumpAsset($asset, $basePath, $output);
- }
+ file_put_contents($cache, serialize($previously));
+
+ if (false !== $inotify) {
+ $reload = $this->inotifyWait($am, $output, $inotify);
+ } else {
+ sleep(1);
+ $reload = true;
}
- // reset the asset manager
- $prop->setValue($am, array());
- if ($debug) {
+ $checkAssets = array();
+ if (true === $reload) {
+ // reset the asset manager
+ $prop->setValue($am, array());
$am->load();
+
+ $checkAssets = $am->getNames();
+ } else if (is_array($reload)) {
+ $checkAssets = $reload;
}
- file_put_contents($cache, serialize($previously));
- $error = '';
+ foreach ($checkAssets as $name) {
+ if ($asset = $this->checkAsset($am, $name, $previously)) {
+ $this->dumpAsset($asset, $basePath, $output);
+ }
+ }
- sleep(1);
+ $error = '';
} catch (\Exception $e) {
if ($error != $msg = $e->getMessage()) {
$output->writeln('<error>[error]</error> '.$msg);
@@ -107,6 +128,66 @@ protected function watch(LazyAssetManager $am, $basePath, OutputInterface $outpu
}
}
}
+
+ if (false !== $inotify) {
+ fclose($inotify);
+ }
+ }
+
+ /**
+ * Sets up watches for inotify to monitor all assetic resources and assets.
+ *
+ * After waiting on inotify to find file modifications it either returns an
+ * array of modified assets or true to indicate that a resource was modifed.
+ *
+ * @param LazyAssetManager $am The asset manager
+ * @param OutputInterface $output The command output
+ * @param resource $inotify File descriptor of the inotify handle
+ *
+ * @return Boolean|array True if a resource was modified or an array of
+ * modified assets.
+ */
+ protected function inotifyWait(LazyAssetManager $am, OutputInterface $output, $inotify)
+ {
+ $flags = IN_MODIFY | IN_ATTRIB | IN_MOVE | IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MOVE_SELF;
+
+ // add a watch for every resource (e.g. template file directory)
+ $resourceWatches = array();
+ foreach ($am->getResources() as $resource) {
+ $path = (string) $resource;
+ $watch = inotify_add_watch($inotify, $path, $flags);
+ $resourceWatches[$watch] = true;
+ }
+
+ // add watches for all files involved in any formulas
+ $assetsWatches = array();
+ foreach ($am->getNames() as $name) {
+ $asset = $am->get($name);
+ foreach ($asset->getPaths() as $path) {
+ $watch = inotify_add_watch($inotify, $path, $flags);
+ $assetWatches[$watch] = $name;
+ }
+ }
+
+ // blocks until an event occurs
+ $events = inotify_read($inotify);
+
+ $reloadAssets = array();
+ $reload = false;
+ foreach ($events as $event) {
+ if (isset($resourceWatches[$event['wd']])) {
+ $reload = true;
+ } else if (isset($assetWatches[$event['wd']])) {
+ $reloadAssets[$event['wd']] = $assetWatches[$event['wd']];
+ }
+ }
+
+ if ($reload) {
+ $output->writeln('<info>[reload]</info> all asset manager resources');
+ return true;
+ }
+
+ return $reloadAssets;
}
/**
Something went wrong with that request. Please try again.