123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- #!/usr/bin/env python
- # encoding: utf-8
- # Matthias Jahn 2006
- # rewritten by Thomas Nagy 2009
- """
- Start a new build as soon as something changes in the build directory.
- PyInotify, Fam, Gamin or time-threshold are used for the detection
- For now only PyInotify and time threshold are supported
- Watching for new svn revisions could be added too
- """
- import select, errno, os, time
- from waflib import Utils, Scripting, Logs, Build, Node, Context, Options
- w_pyinotify = w_fam = w_gamin = None
- def check_support():
- global w_pyinotify, w_fam, w_gamin
- try:
- import pyinotify as w_pyinotify
- except ImportError:
- w_pyinotify = None
- else:
- try:
- wm = w_pyinotify.WatchManager()
- wm = w_pyinotify.Notifier(wm)
- wm = None
- except:
- raise
- w_pyinotify = None
- try:
- import gamin as w_gamin
- except ImportError:
- w_gamin = None
- else:
- try:
- test = w_gamin.WatchMonitor()
- test.disconnect()
- test = None
- except:
- w_gamin = None
- try:
- import _fam as w_fam
- except ImportError:
- w_fam = None
- else:
- try:
- test = w_fam.open()
- test.close()
- test = None
- except:
- w_fam = None
- def daemon(ctx):
- """waf command: rebuild as soon as something changes"""
- bld = None
- while True:
- bld = Context.create_context('build')
- try:
- bld.options = Options.options
- bld.cmd = 'build'
- bld.execute()
- except ctx.errors.WafError as e:
- print(e)
- except KeyboardInterrupt:
- Utils.pprint('RED', 'interrupted')
- break
- try:
- x = ctx.state
- except AttributeError:
- setattr(ctx, 'state', DirWatch())
- x = ctx.state
- x.wait(bld)
- def options(opt):
- """So this shows how to add new commands from tools"""
- Context.g_module.__dict__['daemon'] = daemon
- class DirWatch(object):
- def __init__(self):
- check_support()
- if w_pyinotify:
- self.sup = 'pyinotify'
- elif w_gamin:
- self.sup = 'gamin'
- elif w_fam:
- self.sup = 'fam'
- else:
- self.sup = 'dumb'
- #self.sup = 'dumb'
- def wait(self, bld):
- return getattr(self.__class__, 'wait_' + self.sup)(self, bld)
- def enumerate(self, node):
- if os.path.exists(node.abspath()):
- yield node.abspath()
- try:
- for x in node.children.values():
- for k in self.enumerate(x):
- yield k
- except AttributeError:
- pass
- def wait_pyinotify(self, bld):
- class PE(w_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 = w_pyinotify.WatchManager()
- notif = w_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, w_pyinotify.IN_DELETE | w_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
- def wait_dumb(self, bld):
- time.sleep(5)
- def wait_gamin(self, bld):
- time.sleep(5)
- def wait_fam(self, bld):
- time.sleep(5)
|