Skip to content

Instantly share code, notes, and snippets.

@shnjp
Created February 27, 2010 13:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shnjp/316701 to your computer and use it in GitHub Desktop.
Save shnjp/316701 to your computer and use it in GitHub Desktop.
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