Skip to content

Instantly share code, notes, and snippets.

@Majkl578
Created July 6, 2013 19:54
Show Gist options
  • Save Majkl578/5941053 to your computer and use it in GitHub Desktop.
Save Majkl578/5941053 to your computer and use it in GitHub Desktop.
Simple realtime inotify-based script watching for file updates, updates all files on update. Requires inotify extension, can be found at http://pecl.php.net/package/inotify. Usage: $ php scripts/watcher.php doc-2.0 cs ../web-content /tmp/webcontent Based on https://github.com/nette/web-content/tree/convertor
<?php
/**
* Simple realtime inotify-based script watching for file updates, updates all files on update.
* Requires inotify extension, can be found at http://pecl.php.net/package/inotify.
* Usage: $ php scripts/watcher.php doc-2.0 cs ../web-content /tmp/webcontent
* @author Michael Moravec
*/
require __DIR__ . '/../vendor/autoload.php';
require __DIR__ . '/../vendor/other/fshl/fshl.php';
require __DIR__ . '/../src/Link.php';
require __DIR__ . '/../src/Convertor.php';
if (!extension_loaded('inotify')) {
throw new RuntimeException('Extension inotify is not loaded.');
}
if ($argc !== 5) {
throw new RuntimeException('Invalid arguments.');
}
$book = $argv[1];
$lang = $argv[2];
$sourcePath = $argv[3];
$targetPath = $argv[4];
if (!is_dir($sourcePath) || !is_dir($targetPath)) {
throw new RuntimeException('Source path and target path must exist.');
}
$sourcePath = realpath($sourcePath);
$targetPath = realpath($targetPath);
$files = [];
$dirsMap = [];
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($sourcePath)) as $file) {
/** @var SplFileInfo $file */
$pathName = $file->getPathname();
if (!$file->isFile() || !preg_match('~\.texy\z~i', $pathName)) {
continue;
}
$dir = dirname($pathName);
$targetDir = str_replace($sourcePath, $targetPath, $dir);
@mkdir($targetDir, 0777, TRUE);
$dirsMap[$dir] = $targetDir;
$files[] = $pathName;
}
// recompile all first
foreach ($files as $file) {
recompileFile($file);
}
$inotify = inotify_init();
if ($inotify === FALSE) {
throw new RuntimeException('Failed to obtain an inotify instance!');
}
$watches = []; // dir => watch
$descriptors = []; // wd => dir
foreach (array_keys($dirsMap) as $dir) {
$watch = inotify_add_watch($inotify, $dir, IN_ALL_EVENTS);
if ($watch === FALSE) {
throw new RuntimeException("Failed to watch directory '" . $dir . "'.");
}
$watches[$dir] = $watch;
$descriptors[$watch] = $dir;
}
echo 'Starting watching for changes...', PHP_EOL;
while (($events = inotify_read($inotify)) !== FALSE) {
foreach($events as $event) {
if (!($event['mask'] & IN_MODIFY || $event['mask'] & IN_CREATE || $event['mask'] & IN_MOVED_TO)) {
continue;
}
$path = $descriptors[$event['wd']];
if (!isset($dirsMap[$path]) || empty($event['name'])) {
continue;
}
$file = $path . DIRECTORY_SEPARATOR . $event['name'];
if (!preg_match('~\.(texy|txt|sql|php|jpe?g|gif|png)\z~i', $file)) {
continue;
}
recompileFile($file);
}
}
foreach ($watches as $watch) {
inotify_rm_watch($inotify, $watch);
}
fclose($inotify);
function recompileFile($sourceFile)
{
global $book, $lang, $sourcePath, $targetPath;
$target = preg_replace('~\.texy\z~i', '.html', str_replace($sourcePath, $targetPath, $sourceFile));
$name = basename($sourceFile);
$convertor = new Text\Convertor($book, $lang, $name);
$convertor->parse(file_get_contents($sourceFile));
file_put_contents(
$target,
'<!doctype html><meta charset="utf-8">'
. '<link rel="stylesheet" href="http://files.nette.org/css/combined.css">'
. '<body><div id=page><div id=main class=sidebar><div id=content>'
. $convertor->html
);
echo 'Recompiled file ', str_replace($sourcePath . PATH_SEPARATOR, '', $sourceFile), '.', PHP_EOL;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment