waf

FORK: waf with some random patches
git clone https://git.neptards.moe/neptards/waf.git
Log | Files | Refs | README

daemon.py (3090B)


      1 #!/usr/bin/env python
      2 # encoding: utf-8
      3 # Matthias Jahn 2006
      4 # rewritten by Thomas Nagy 2009
      5 
      6 """
      7 Start a new build as soon as something changes in the build directory.
      8 
      9 PyInotify, Fam, Gamin or time-threshold are used for the detection
     10 
     11 For now only PyInotify and time threshold are supported
     12 Watching for new svn revisions could be added too
     13 """
     14 
     15 import select, errno, os, time
     16 from waflib import Utils, Scripting, Logs, Build, Node, Context, Options
     17 
     18 w_pyinotify = w_fam = w_gamin = None
     19 def check_support():
     20 	global w_pyinotify, w_fam, w_gamin
     21 	try:
     22 		import pyinotify as w_pyinotify
     23 	except ImportError:
     24 		w_pyinotify = None
     25 	else:
     26 		try:
     27 			wm = w_pyinotify.WatchManager()
     28 			wm = w_pyinotify.Notifier(wm)
     29 			wm = None
     30 		except:
     31 			raise
     32 			w_pyinotify = None
     33 
     34 	try:
     35 		import gamin as w_gamin
     36 	except ImportError:
     37 		w_gamin = None
     38 	else:
     39 		try:
     40 			test = w_gamin.WatchMonitor()
     41 			test.disconnect()
     42 			test = None
     43 		except:
     44 			w_gamin = None
     45 
     46 	try:
     47 		import _fam as w_fam
     48 	except ImportError:
     49 		w_fam = None
     50 	else:
     51 		try:
     52 			test = w_fam.open()
     53 			test.close()
     54 			test = None
     55 		except:
     56 			w_fam = None
     57 
     58 def daemon(ctx):
     59 	"""waf command: rebuild as soon as something changes"""
     60 	bld = None
     61 	while True:
     62 		bld = Context.create_context('build')
     63 		try:
     64 			bld.options = Options.options
     65 			bld.cmd = 'build'
     66 			bld.execute()
     67 		except ctx.errors.WafError as e:
     68 			print(e)
     69 		except KeyboardInterrupt:
     70 			Utils.pprint('RED', 'interrupted')
     71 			break
     72 
     73 		try:
     74 			x = ctx.state
     75 		except AttributeError:
     76 			setattr(ctx, 'state', DirWatch())
     77 			x = ctx.state
     78 
     79 		x.wait(bld)
     80 
     81 def options(opt):
     82 	"""So this shows how to add new commands from tools"""
     83 	Context.g_module.__dict__['daemon'] = daemon
     84 
     85 class DirWatch(object):
     86 	def __init__(self):
     87 		check_support()
     88 		if w_pyinotify:
     89 			self.sup = 'pyinotify'
     90 		elif w_gamin:
     91 			self.sup = 'gamin'
     92 		elif w_fam:
     93 			self.sup = 'fam'
     94 		else:
     95 			self.sup = 'dumb'
     96 		#self.sup = 'dumb'
     97 
     98 	def wait(self, bld):
     99 		return getattr(self.__class__, 'wait_' + self.sup)(self, bld)
    100 
    101 	def enumerate(self, node):
    102 		if os.path.exists(node.abspath()):
    103 			yield node.abspath()
    104 		try:
    105 			for x in node.children.values():
    106 				for k in self.enumerate(x):
    107 					yield k
    108 		except AttributeError:
    109 			pass
    110 
    111 	def wait_pyinotify(self, bld):
    112 
    113 		class PE(w_pyinotify.ProcessEvent):
    114 			def stop(self, event):
    115 				self.notif.ev = True
    116 				self.notif.stop()
    117 				raise ValueError("stop for delete")
    118 
    119 			process_IN_DELETE = stop
    120 			process_IN_CLOSE = stop
    121 			process_default = stop
    122 
    123 		proc = PE()
    124 		wm = w_pyinotify.WatchManager()
    125 		notif = w_pyinotify.Notifier(wm, proc)
    126 		proc.notif = notif
    127 
    128 		# well, we should add all the folders to watch here
    129 		for x in self.enumerate(bld.srcnode):
    130 			wm.add_watch(x, w_pyinotify.IN_DELETE | w_pyinotify.IN_CLOSE_WRITE)
    131 
    132 		try:
    133 			# pyinotify uses an infinite loop ... not too nice, so we have to use an exception
    134 			notif.loop()
    135 		except ValueError:
    136 			pass
    137 		if not hasattr(notif, 'ev'):
    138 			raise KeyboardInterrupt
    139 
    140 	def wait_dumb(self, bld):
    141 		time.sleep(5)
    142 
    143 	def wait_gamin(self, bld):
    144 		time.sleep(5)
    145 
    146 	def wait_fam(self, bld):
    147 		time.sleep(5)
    148