Created
February 27, 2010 13:49
-
-
Save shnjp/316701 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import select, errno, os, time, signal | |
import Utils, Scripting, Logs, Build, Node, Options | |
def daemon(ctx): | |
"""rebuild as soon as something changes""" | |
bld = None | |
while True: | |
try: | |
bld = Utils.g_module.build_context() | |
Scripting.install(bld) | |
except Build.BuildError, e: | |
Logs.warn(e) | |
except KeyboardInterrupt: | |
Utils.pprint('RED', 'interrupted') | |
break | |
try: | |
x = ctx.state | |
except AttributeError: | |
setattr(ctx, 'state', DefaultDirWatch()) | |
x = ctx.state | |
x.wait(bld) | |
class DirWatch(object): | |
def wait(self, bld): | |
time.sleep(5) | |
def enumerate(self, node): | |
yield node.abspath() | |
for x in node.childs.values(): | |
if x.id & 3 == Node.DIR: | |
for k in self.enumerate(x): | |
yield k | |
raise StopIteration | |
DefaultDirWatch = DirWatch | |
try: | |
import pyinotify | |
except ImportError: | |
pass | |
else: | |
class PyINotifyDirWatch(DirWatch): | |
def wait(self, bld): | |
import pyinotify | |
class PE(pyinotify.ProcessEvent): | |
def stop(self, event): | |
self.notif.ev = True | |
self.notif.stop() | |
raise ValueError("stop for delete") | |
process_IN_DELETE = stop | |
process_IN_CLOSE = stop | |
process_default = stop | |
proc = PE() | |
wm = pyinotify.WatchManager() | |
notif = pyinotify.Notifier(wm, proc) | |
proc.notif = notif | |
# well, we should add all the folders to watch here | |
for x in self.enumerate(bld.srcnode): | |
wm.add_watch(x, pyinotify.IN_DELETE | pyinotify.IN_CLOSE_WRITE) | |
try: | |
# pyinotify uses an infinite loop ... not too nice, so we have to use an exception | |
notif.loop() | |
except ValueError: | |
pass | |
if not hasattr(notif, 'ev'): | |
raise KeyboardInterrupt | |
try: | |
import _fam | |
except ImportError: | |
pass | |
else: | |
# NOT WORK ON FreeBSD 7 | |
class FAMDirWatch(DirWatch): | |
def __init__(self): | |
self.dirs = {} | |
self.fc = _fam.open() | |
def wait(self, bld): | |
if 1: | |
curdirs = set(x for x in self.enumerate(bld.srcnode)) | |
olddirs = set(self.dirs.keys()) | |
deleted = olddirs - curdirs | |
added = curdirs - olddirs | |
unchanged=curdirs & olddirs | |
print `deleted, added, unchanged` | |
for x in deleted: | |
r = self.dirs[x] | |
x.cancelMonitor() | |
del self.dirs[x] | |
for x in added: | |
self.dirs[x] = self.fc.monitorDirectory(x, '') | |
#for x in unchanged: | |
# self.dirs[x].resumeMonitor() | |
if 0: | |
self.dirs = {} | |
for x in self.enumerate(bld.srcnode): | |
self.dirs[x] = self.fc.monitorDirectory(x, '') | |
while True: | |
if self.wait_for_change(): | |
# changed | |
print 'changed' | |
break | |
if 0: | |
for r in self.dirs.itervalues(): | |
r.cancelMonitor() | |
self.fc.close() | |
self.dirs = {} | |
self.fc = None | |
def wait_for_change(self): | |
return | |
print 'monitor' | |
try: | |
ri, ro, re = select.select([self.fc], [], []) | |
print `ri, ro, re` | |
except select.error, err: | |
errnumber, strerr = er | |
if errnumber == errno.EINTR: | |
print 'EINTR' | |
pass | |
else: | |
print err | |
sys.exit(1) | |
print 'done' | |
while self.fc.pending(): | |
fe = self.fc.nextEvent() | |
print 'event', fe.filename, fe.code, fe.code2str() | |
if fe.code not in (_fam.Exists, _fam.EndExist): | |
return True | |
return False | |
""" | |
finally: | |
print 'close' | |
self.fc.close() | |
self.fc = None | |
self.dirs = {} | |
#for r in self.dirs.itervalues(): | |
# r.suspendMonitor() | |
""" | |
#DefaultDirWatch = FAMDirWatch | |
try: | |
import gamin | |
except ImportError: | |
pass | |
else: | |
class GAMINDirWatch(DirWatch): | |
def __init__(self): | |
self.monitor = gamin.WatchMonitor() | |
self.changed = None | |
def wait(self, bld): | |
for x in self.enumerate(bld.srcnode): | |
self.monitor.watch_directory(x, self.callback) | |
print 'wait for modification...' | |
self.changed = False | |
while not self.changed: | |
self.monitor.event_pending() | |
self.monitor.handle_events() | |
for x in self.enumerate(bld.srcnode): | |
self.monitor.stop_watch(x) | |
def callback(self, path, event): | |
if event in (gamin.GAMAcknowledge, gamin.GAMExists, gamin.GAMEndExist): | |
pass | |
else: | |
print 'callback ', `path, event` | |
self.changed = True | |
DefaultDirWatch = GAMINDirWatch |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment