From 80256655e262502e3916933a2a7f76b65435d4ca Mon Sep 17 00:00:00 2001 From: Kris Wallsmith Date: Fri, 25 Feb 2011 09:52:37 -0800 Subject: [PATCH 1/3] [AsseticBundle] added a --watch option to the assetic:dump command --- .../AsseticBundle/Command/DumpCommand.php | 101 ++++++++++++++++-- 1 file changed, 91 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Bundle/AsseticBundle/Command/DumpCommand.php b/src/Symfony/Bundle/AsseticBundle/Command/DumpCommand.php index 1d948ec5e8673..d0de874bd2aaa 100644 --- a/src/Symfony/Bundle/AsseticBundle/Command/DumpCommand.php +++ b/src/Symfony/Bundle/AsseticBundle/Command/DumpCommand.php @@ -11,9 +11,12 @@ namespace Symfony\Bundle\AsseticBundle\Command; +use Assetic\Asset\AssetInterface; +use Assetic\Factory\LazyAssetManager; use Symfony\Bundle\FrameworkBundle\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** @@ -29,6 +32,7 @@ protected function configure() ->setName('assetic:dump') ->setDescription('Dumps all assets to the filesystem') ->addArgument('base_dir', InputArgument::OPTIONAL, 'The base directory') + ->addOption('watch', null, InputOption::VALUE_NONE, 'Check for changes every second') ; } @@ -39,18 +43,95 @@ protected function execute(InputInterface $input, OutputInterface $output) } $am = $this->container->get('assetic.asset_manager'); - foreach ($am->all() as $name => $asset) { - $output->writeln('[asset] '.$name); - $asset->load(); - - $target = $baseDir . '/' . $asset->getTargetUrl(); - if (!is_dir($dir = dirname($target))) { - $output->writeln('[dir+] '.$dir); - mkdir($dir); + + if ($input->getOption('watch')) { + return $this->watch($am, $baseDir, $output, $this->container->getParameter('kernel.debug')); + } + + foreach ($am->getNames() as $name) { + $this->dumpAsset($am->get($name), $baseDir, $output); + } + } + + /** + * Watches a asset manager for changes. + * + * This method includes an infinite loop the continuously polls the asset + * manager for changes. + * + * @param LazyAssetManager $am The asset manager + * @param string $baseDir The base directory to write to + * @param OutputInterface $output The command output + * @param Boolean $debug Debug mode + */ + protected function watch(LazyAssetManager $am, $baseDir, OutputInterface $output, $debug = false) + { + $previously = array(); + + while (true) { + // reload formulae when in debug + if ($debug) { + $am->load(); + } + + foreach ($am->getNames() as $name) { + if ($asset = $this->checkAsset($am, $name, $previously)) { + $this->dumpAsset($asset, $baseDir, $output); + } + } + + sleep(1); + } + } + + /** + * Checks if an asset should be dumped. + * + * @param LazyAssetManager $am The asset manager + * @param string $name The asset name + * @param array $previously An array of previous visits + * + * @return AssetInterface|Boolean The asset if it should be dumped + */ + protected function checkAsset(LazyAssetManager $am, $name, array &$previously) + { + $formula = serialize($am->getFormula($name)); + $asset = $am->get($name); + $mtime = $asset->getLastModified(); + + if (isset($previously[$name])) { + $changed = $previously[$name]['mtime'] != $mtime || $previously[$name]['formula'] != $formula; + } else { + $changed = true; + } + + $previously[$name] = array('mtime' => $mtime, 'formula' => $formula); + + return $changed ? $asset : false; + } + + /** + * Writes an asset. + * + * @param AssetInterface $asset An asset + * @param string $baseDir The base directory to write to + * @param OutputInterface $output The command output + * + * @throws RuntimeException If there is a problem writing the asset + */ + protected function dumpAsset(AssetInterface $asset, $baseDir, OutputInterface $output) + { + $target = rtrim($baseDir, '/') . '/' . $asset->getTargetUrl(); + if (!is_dir($dir = dirname($target))) { + $output->writeln('[dir+] '.$dir); + if (false === @mkdir($dir)) { + throw new \RuntimeException('Unable to create directory '.$dir); } + } - $output->writeln('[file+] '.$asset->getTargetUrl()); - file_put_contents($target, $asset->dump()); + $output->writeln('[file+] '.$target); + if (false === @file_put_contents($target, $asset->dump())) { + throw new \RuntimeException('Unable to write file '.$target); } } } From 4816b9e711a4c3616f291ee5c2f28d0d5c49e220 Mon Sep 17 00:00:00 2001 From: Kris Wallsmith Date: Fri, 25 Feb 2011 10:01:01 -0800 Subject: [PATCH 2/3] [AsseticBundle] added a simple cache to --watch so it picks up where it left off last time --- src/Symfony/Bundle/AsseticBundle/Command/DumpCommand.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/AsseticBundle/Command/DumpCommand.php b/src/Symfony/Bundle/AsseticBundle/Command/DumpCommand.php index d0de874bd2aaa..4011c6e1f5b41 100644 --- a/src/Symfony/Bundle/AsseticBundle/Command/DumpCommand.php +++ b/src/Symfony/Bundle/AsseticBundle/Command/DumpCommand.php @@ -66,7 +66,12 @@ protected function execute(InputInterface $input, OutputInterface $output) */ protected function watch(LazyAssetManager $am, $baseDir, OutputInterface $output, $debug = false) { - $previously = array(); + $cache = sys_get_temp_dir().'/assetic_watch_'.substr(sha1($baseDir), 0, 7); + if (file_exists($cache)) { + $previously = unserialize(file_get_contents($cache)); + } else { + $previously = array(); + } while (true) { // reload formulae when in debug @@ -80,6 +85,7 @@ protected function watch(LazyAssetManager $am, $baseDir, OutputInterface $output } } + file_put_contents($cache, serialize($previously)); sleep(1); } } From 3ce1d82589c1ce379fb8a3c8b8104bc500b09f04 Mon Sep 17 00:00:00 2001 From: Kris Wallsmith Date: Fri, 25 Feb 2011 10:27:51 -0800 Subject: [PATCH 3/3] [AsseticBundle] added error handling to --watch --- .../AsseticBundle/Command/DumpCommand.php | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Bundle/AsseticBundle/Command/DumpCommand.php b/src/Symfony/Bundle/AsseticBundle/Command/DumpCommand.php index 4011c6e1f5b41..55cacb4a7a463 100644 --- a/src/Symfony/Bundle/AsseticBundle/Command/DumpCommand.php +++ b/src/Symfony/Bundle/AsseticBundle/Command/DumpCommand.php @@ -66,6 +66,10 @@ protected function execute(InputInterface $input, OutputInterface $output) */ protected function watch(LazyAssetManager $am, $baseDir, OutputInterface $output, $debug = false) { + $refl = new \ReflectionClass('Assetic\\AssetManager'); + $prop = $refl->getProperty('assets'); + $prop->setAccessible(true); + $cache = sys_get_temp_dir().'/assetic_watch_'.substr(sha1($baseDir), 0, 7); if (file_exists($cache)) { $previously = unserialize(file_get_contents($cache)); @@ -73,20 +77,31 @@ protected function watch(LazyAssetManager $am, $baseDir, OutputInterface $output $previously = array(); } + $error = ''; while (true) { - // reload formulae when in debug - if ($debug) { - $am->load(); - } + try { + foreach ($am->getNames() as $name) { + if ($asset = $this->checkAsset($am, $name, $previously)) { + $this->dumpAsset($asset, $baseDir, $output); + } + } - foreach ($am->getNames() as $name) { - if ($asset = $this->checkAsset($am, $name, $previously)) { - $this->dumpAsset($asset, $baseDir, $output); + // reset the asset manager + $prop->setValue($am, array()); + if ($debug) { + $am->load(); } - } - file_put_contents($cache, serialize($previously)); - sleep(1); + file_put_contents($cache, serialize($previously)); + $error = ''; + + sleep(1); + } catch (\Exception $e) { + if ($error != $msg = $e->getMessage()) { + $output->writeln('[error] '.$msg); + $error = $msg; + } + } } } @@ -101,7 +116,7 @@ protected function watch(LazyAssetManager $am, $baseDir, OutputInterface $output */ protected function checkAsset(LazyAssetManager $am, $name, array &$previously) { - $formula = serialize($am->getFormula($name)); + $formula = $am->hasFormula($name) ? serialize($am->getFormula($name)) : null; $asset = $am->get($name); $mtime = $asset->getLastModified();