You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
149 lines
3.0 KiB
Python
149 lines
3.0 KiB
Python
#!/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)
|
|
|