summaryrefslogtreecommitdiffstats
path: root/bitbake-dev/lib
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake-dev/lib')
-rw-r--r--bitbake-dev/lib/bb/build.py8
-rw-r--r--bitbake-dev/lib/bb/command.py16
-rw-r--r--bitbake-dev/lib/bb/cooker.py26
-rw-r--r--bitbake-dev/lib/bb/event.py108
-rw-r--r--bitbake-dev/lib/bb/fetch/cvs.py2
-rw-r--r--bitbake-dev/lib/bb/fetch/git.py86
-rw-r--r--bitbake-dev/lib/bb/fetch/local.py4
-rw-r--r--bitbake-dev/lib/bb/fetch/svk.py2
-rw-r--r--bitbake-dev/lib/bb/fetch/wget.py2
-rw-r--r--bitbake-dev/lib/bb/msg.py16
-rw-r--r--bitbake-dev/lib/bb/parse/parse_py/BBHandler.py2
-rw-r--r--bitbake-dev/lib/bb/parse/parse_py/ConfHandler.py13
-rw-r--r--bitbake-dev/lib/bb/runqueue.py98
-rw-r--r--bitbake-dev/lib/bb/server/__init__.py1
-rw-r--r--bitbake-dev/lib/bb/server/none.py164
-rw-r--r--bitbake-dev/lib/bb/server/xmlrpc.py50
-rw-r--r--bitbake-dev/lib/bb/taskdata.py35
-rw-r--r--bitbake-dev/lib/bb/ui/crumbs/runningbuild.py28
-rw-r--r--bitbake-dev/lib/bb/ui/depexp.py20
-rw-r--r--bitbake-dev/lib/bb/ui/knotty.py66
-rw-r--r--bitbake-dev/lib/bb/ui/ncurses.py44
-rw-r--r--bitbake-dev/lib/bb/ui/uievent.py24
-rw-r--r--bitbake-dev/lib/bb/ui/uihelper.py22
23 files changed, 491 insertions, 346 deletions
diff --git a/bitbake-dev/lib/bb/build.py b/bitbake-dev/lib/bb/build.py
index 65e8118b4f..6d80b4b549 100644
--- a/bitbake-dev/lib/bb/build.py
+++ b/bitbake-dev/lib/bb/build.py
@@ -55,7 +55,7 @@ class TaskBase(event.Event):
55 def __init__(self, t, d ): 55 def __init__(self, t, d ):
56 self._task = t 56 self._task = t
57 self._package = bb.data.getVar("PF", d, 1) 57 self._package = bb.data.getVar("PF", d, 1)
58 event.Event.__init__(self, d) 58 event.Event.__init__(self)
59 self._message = "package %s: task %s: %s" % (bb.data.getVar("PF", d, 1), t, bb.event.getName(self)[4:]) 59 self._message = "package %s: task %s: %s" % (bb.data.getVar("PF", d, 1), t, bb.event.getName(self)[4:])
60 60
61 def getTask(self): 61 def getTask(self):
@@ -286,9 +286,9 @@ def exec_task(task, d):
286 data.setVar('OVERRIDES', 'task-%s:%s' % (task[3:], old_overrides), localdata) 286 data.setVar('OVERRIDES', 'task-%s:%s' % (task[3:], old_overrides), localdata)
287 data.update_data(localdata) 287 data.update_data(localdata)
288 data.expandKeys(localdata) 288 data.expandKeys(localdata)
289 event.fire(TaskStarted(task, localdata)) 289 event.fire(TaskStarted(task, localdata), localdata)
290 exec_func(task, localdata) 290 exec_func(task, localdata)
291 event.fire(TaskSucceeded(task, localdata)) 291 event.fire(TaskSucceeded(task, localdata), localdata)
292 except FuncFailed, message: 292 except FuncFailed, message:
293 # Try to extract the optional logfile 293 # Try to extract the optional logfile
294 try: 294 try:
@@ -298,7 +298,7 @@ def exec_task(task, d):
298 msg = message 298 msg = message
299 bb.msg.note(1, bb.msg.domain.Build, "Task failed: %s" % message ) 299 bb.msg.note(1, bb.msg.domain.Build, "Task failed: %s" % message )
300 failedevent = TaskFailed(msg, logfile, task, d) 300 failedevent = TaskFailed(msg, logfile, task, d)
301 event.fire(failedevent) 301 event.fire(failedevent, d)
302 raise EventException("Function failed in task: %s" % message, failedevent) 302 raise EventException("Function failed in task: %s" % message, failedevent)
303 303
304 # make stamp, or cause event and raise exception 304 # make stamp, or cause event and raise exception
diff --git a/bitbake-dev/lib/bb/command.py b/bitbake-dev/lib/bb/command.py
index 1a1bf00b33..2bb5365c0c 100644
--- a/bitbake-dev/lib/bb/command.py
+++ b/bitbake-dev/lib/bb/command.py
@@ -94,9 +94,9 @@ class Command:
94 94
95 def finishAsyncCommand(self, error = None): 95 def finishAsyncCommand(self, error = None):
96 if error: 96 if error:
97 bb.event.fire(bb.command.CookerCommandFailed(self.cooker.configuration.event_data, error)) 97 bb.event.fire(bb.command.CookerCommandFailed(error), self.cooker.configuration.event_data)
98 else: 98 else:
99 bb.event.fire(bb.command.CookerCommandCompleted(self.cooker.configuration.event_data)) 99 bb.event.fire(bb.command.CookerCommandCompleted(), self.cooker.configuration.event_data)
100 self.currentAsyncCommand = None 100 self.currentAsyncCommand = None
101 101
102 102
@@ -247,24 +247,24 @@ class CookerCommandCompleted(bb.event.Event):
247 """ 247 """
248 Cooker command completed 248 Cooker command completed
249 """ 249 """
250 def __init__(self, data): 250 def __init__(self):
251 bb.event.Event.__init__(self, data) 251 bb.event.Event.__init__(self)
252 252
253 253
254class CookerCommandFailed(bb.event.Event): 254class CookerCommandFailed(bb.event.Event):
255 """ 255 """
256 Cooker command completed 256 Cooker command completed
257 """ 257 """
258 def __init__(self, data, error): 258 def __init__(self, error):
259 bb.event.Event.__init__(self, data) 259 bb.event.Event.__init__(self)
260 self.error = error 260 self.error = error
261 261
262class CookerCommandSetExitCode(bb.event.Event): 262class CookerCommandSetExitCode(bb.event.Event):
263 """ 263 """
264 Set the exit code for a cooker command 264 Set the exit code for a cooker command
265 """ 265 """
266 def __init__(self, data, exitcode): 266 def __init__(self, exitcode):
267 bb.event.Event.__init__(self, data) 267 bb.event.Event.__init__(self)
268 self.exitcode = int(exitcode) 268 self.exitcode = int(exitcode)
269 269
270 270
diff --git a/bitbake-dev/lib/bb/cooker.py b/bitbake-dev/lib/bb/cooker.py
index 1bf7d4bd14..25131b7406 100644
--- a/bitbake-dev/lib/bb/cooker.py
+++ b/bitbake-dev/lib/bb/cooker.py
@@ -245,7 +245,7 @@ class BBCooker:
245 245
246 def compareRevisions(self): 246 def compareRevisions(self):
247 ret = bb.fetch.fetcher_compare_revisons(self.configuration.data) 247 ret = bb.fetch.fetcher_compare_revisons(self.configuration.data)
248 bb.event.fire(bb.command.CookerCommandSetExitCode(self.configuration.event_data, ret)) 248 bb.event.fire(bb.command.CookerCommandSetExitCode(ret), self.configuration.event_data)
249 249
250 def showEnvironment(self, buildfile = None, pkgs_to_build = []): 250 def showEnvironment(self, buildfile = None, pkgs_to_build = []):
251 """ 251 """
@@ -403,7 +403,7 @@ class BBCooker:
403 Generate an event with the result 403 Generate an event with the result
404 """ 404 """
405 depgraph = self.generateDepTreeData(pkgs_to_build, task) 405 depgraph = self.generateDepTreeData(pkgs_to_build, task)
406 bb.event.fire(bb.event.DepTreeGenerated(self.configuration.data, depgraph)) 406 bb.event.fire(bb.event.DepTreeGenerated(depgraph), self.configuration.data)
407 407
408 def generateDotGraphFiles(self, pkgs_to_build, task): 408 def generateDotGraphFiles(self, pkgs_to_build, task):
409 """ 409 """
@@ -544,7 +544,7 @@ class BBCooker:
544 544
545 bb.fetch.fetcher_init(self.configuration.data) 545 bb.fetch.fetcher_init(self.configuration.data)
546 546
547 bb.event.fire(bb.event.ConfigParsed(self.configuration.data)) 547 bb.event.fire(bb.event.ConfigParsed(), self.configuration.data)
548 548
549 except IOError, e: 549 except IOError, e:
550 bb.msg.fatal(bb.msg.domain.Parsing, "Error when parsing %s: %s" % (afile, str(e))) 550 bb.msg.fatal(bb.msg.domain.Parsing, "Error when parsing %s: %s" % (afile, str(e)))
@@ -657,7 +657,7 @@ class BBCooker:
657 taskdata.add_provider(self.configuration.data, self.status, item) 657 taskdata.add_provider(self.configuration.data, self.status, item)
658 658
659 buildname = bb.data.getVar("BUILDNAME", self.configuration.data) 659 buildname = bb.data.getVar("BUILDNAME", self.configuration.data)
660 bb.event.fire(bb.event.BuildStarted(buildname, [item], self.configuration.event_data)) 660 bb.event.fire(bb.event.BuildStarted(buildname, [item]), self.configuration.event_data)
661 661
662 # Execute the runqueue 662 # Execute the runqueue
663 runlist = [[item, "do_%s" % task]] 663 runlist = [[item, "do_%s" % task]]
@@ -680,7 +680,7 @@ class BBCooker:
680 retval = False 680 retval = False
681 if not retval: 681 if not retval:
682 self.command.finishAsyncCommand() 682 self.command.finishAsyncCommand()
683 bb.event.fire(bb.event.BuildCompleted(buildname, item, self.configuration.event_data, failures)) 683 bb.event.fire(bb.event.BuildCompleted(buildname, item, failures), self.configuration.event_data)
684 return False 684 return False
685 return 0.5 685 return 0.5
686 686
@@ -716,14 +716,14 @@ class BBCooker:
716 retval = False 716 retval = False
717 if not retval: 717 if not retval:
718 self.command.finishAsyncCommand() 718 self.command.finishAsyncCommand()
719 bb.event.fire(bb.event.BuildCompleted(buildname, targets, self.configuration.event_data, failures)) 719 bb.event.fire(bb.event.BuildCompleted(buildname, targets, failures), self.configuration.event_data)
720 return None 720 return None
721 return 0.5 721 return 0.5
722 722
723 self.buildSetVars() 723 self.buildSetVars()
724 724
725 buildname = bb.data.getVar("BUILDNAME", self.configuration.data) 725 buildname = bb.data.getVar("BUILDNAME", self.configuration.data)
726 bb.event.fire(bb.event.BuildStarted(buildname, targets, self.configuration.event_data)) 726 bb.event.fire(bb.event.BuildStarted(buildname, targets), self.configuration.event_data)
727 727
728 localdata = data.createCopy(self.configuration.data) 728 localdata = data.createCopy(self.configuration.data)
729 bb.data.update_data(localdata) 729 bb.data.update_data(localdata)
@@ -786,7 +786,7 @@ class BBCooker:
786 self.cookerState = cookerParsed 786 self.cookerState = cookerParsed
787 return None 787 return None
788 788
789 return 0.00001 789 return True
790 790
791 def checkPackages(self, pkgs_to_build): 791 def checkPackages(self, pkgs_to_build):
792 792
@@ -904,15 +904,15 @@ class BBCooker:
904 else: 904 else:
905 self.server.serve_forever() 905 self.server.serve_forever()
906 906
907 bb.event.fire(CookerExit(self.configuration.event_data)) 907 bb.event.fire(CookerExit(), self.configuration.event_data)
908 908
909class CookerExit(bb.event.Event): 909class CookerExit(bb.event.Event):
910 """ 910 """
911 Notify clients of the Cooker shutdown 911 Notify clients of the Cooker shutdown
912 """ 912 """
913 913
914 def __init__(self, d): 914 def __init__(self):
915 bb.event.Event.__init__(self, d) 915 bb.event.Event.__init__(self)
916 916
917class CookerParser: 917class CookerParser:
918 def __init__(self, cooker, filelist, masked): 918 def __init__(self, cooker, filelist, masked):
@@ -932,8 +932,6 @@ class CookerParser:
932 self.pointer = 0 932 self.pointer = 0
933 933
934 def parse_next(self): 934 def parse_next(self):
935 print "Pointer %d" % self.pointer
936
937 if self.pointer < len(self.filelist): 935 if self.pointer < len(self.filelist):
938 f = self.filelist[self.pointer] 936 f = self.filelist[self.pointer]
939 cooker = self.cooker 937 cooker = self.cooker
@@ -964,7 +962,7 @@ class CookerParser:
964 cooker.bb_cache.remove(f) 962 cooker.bb_cache.remove(f)
965 raise 963 raise
966 finally: 964 finally:
967 bb.event.fire(bb.event.ParseProgress(cooker.configuration.event_data, self.cached, self.parsed, self.skipped, self.masked, self.error, self.total)) 965 bb.event.fire(bb.event.ParseProgress(self.cached, self.parsed, self.skipped, self.masked, self.error, self.total), cooker.configuration.event_data)
968 966
969 self.pointer += 1 967 self.pointer += 1
970 968
diff --git a/bitbake-dev/lib/bb/event.py b/bitbake-dev/lib/bb/event.py
index 86b566febf..3062dc51be 100644
--- a/bitbake-dev/lib/bb/event.py
+++ b/bitbake-dev/lib/bb/event.py
@@ -24,27 +24,19 @@ BitBake build tools.
24 24
25import os, re 25import os, re
26import bb.utils 26import bb.utils
27import pickle
27 28
28# This is the pid for which we should generate the event. This is set when 29# This is the pid for which we should generate the event. This is set when
29# the runqueue forks off. 30# the runqueue forks off.
30worker_pid = 0 31worker_pid = 0
32worker_pipe = None
31 33
32class Event: 34class Event:
33 """Base class for events""" 35 """Base class for events"""
34 type = "Event"
35 36
36 def __init__(self, d): 37 def __init__(self):
37 self._data = d
38 self.pid = worker_pid 38 self.pid = worker_pid
39 39
40 def getData(self):
41 return self._data
42
43 def setData(self, data):
44 self._data = data
45
46 data = property(getData, setData, None, "data property")
47
48NotHandled = 0 40NotHandled = 0
49Handled = 1 41Handled = 1
50 42
@@ -56,33 +48,48 @@ _handlers = {}
56_ui_handlers = {} 48_ui_handlers = {}
57_ui_handler_seq = 0 49_ui_handler_seq = 0
58 50
59def fire(event): 51def fire(event, d):
60 """Fire off an Event""" 52 """Fire off an Event"""
61 53
54 if worker_pid != 0:
55 worker_fire(event, d)
56 return
57
62 for handler in _handlers: 58 for handler in _handlers:
63 h = _handlers[handler] 59 h = _handlers[handler]
60 event.data = d
64 if type(h).__name__ == "code": 61 if type(h).__name__ == "code":
65 exec(h) 62 exec(h)
66 tmpHandler(event) 63 tmpHandler(event)
67 else: 64 else:
68 h(event) 65 h(event)
69 66 del event.data
70 # Remove the event data elements for UI handlers - too much data otherwise
71 # They can request data if they need it
72 event.data = None
73 event._data = None
74 67
75 errors = [] 68 errors = []
76 for h in _ui_handlers: 69 for h in _ui_handlers:
77 #print "Sending event %s" % event 70 #print "Sending event %s" % event
78 classid = "%s.%s" % (event.__class__.__module__, event.__class__.__name__)
79 try: 71 try:
80 _ui_handlers[h].event.send((classid, event)) 72 # We use pickle here since it better handles object instances
73 # which xmlrpc's marshaller does not. Events *must* be serializable
74 # by pickle.
75 _ui_handlers[h].event.send((pickle.dumps(event)))
81 except: 76 except:
82 errors.append(h) 77 errors.append(h)
83 for h in errors: 78 for h in errors:
84 del _ui_handlers[h] 79 del _ui_handlers[h]
85 80
81def worker_fire(event, d):
82 data = "<event>" + pickle.dumps(event) + "</event>"
83 if os.write(worker_pipe, data) != len (data):
84 print "Error sending event to server (short write)"
85
86def fire_from_worker(event, d):
87 if not event.startswith("<event>") or not event.endswith("</event>"):
88 print "Error, not an event"
89 return
90 event = pickle.loads(event[7:-8])
91 bb.event.fire(event, d)
92
86def register(name, handler): 93def register(name, handler):
87 """Register an Event handler""" 94 """Register an Event handler"""
88 95
@@ -128,17 +135,17 @@ class ConfigParsed(Event):
128class RecipeParsed(Event): 135class RecipeParsed(Event):
129 """ Recipe Parsing Complete """ 136 """ Recipe Parsing Complete """
130 137
131 def __init__(self, fn, d): 138 def __init__(self, fn):
132 self.fn = fn 139 self.fn = fn
133 Event.__init__(self, d) 140 Event.__init__(self)
134 141
135class StampUpdate(Event): 142class StampUpdate(Event):
136 """Trigger for any adjustment of the stamp files to happen""" 143 """Trigger for any adjustment of the stamp files to happen"""
137 144
138 def __init__(self, targets, stampfns, d): 145 def __init__(self, targets, stampfns):
139 self._targets = targets 146 self._targets = targets
140 self._stampfns = stampfns 147 self._stampfns = stampfns
141 Event.__init__(self, d) 148 Event.__init__(self)
142 149
143 def getStampPrefix(self): 150 def getStampPrefix(self):
144 return self._stampfns 151 return self._stampfns
@@ -149,30 +156,13 @@ class StampUpdate(Event):
149 stampPrefix = property(getStampPrefix) 156 stampPrefix = property(getStampPrefix)
150 targets = property(getTargets) 157 targets = property(getTargets)
151 158
152class PkgBase(Event):
153 """Base class for package events"""
154
155 def __init__(self, t, d):
156 self._pkg = t
157 Event.__init__(self, d)
158 self._message = "package %s: %s" % (bb.data.getVar("P", d, 1), getName(self)[3:])
159
160 def getPkg(self):
161 return self._pkg
162
163 def setPkg(self, pkg):
164 self._pkg = pkg
165
166 pkg = property(getPkg, setPkg, None, "pkg property")
167
168
169class BuildBase(Event): 159class BuildBase(Event):
170 """Base class for bbmake run events""" 160 """Base class for bbmake run events"""
171 161
172 def __init__(self, n, p, c, failures = 0): 162 def __init__(self, n, p, failures = 0):
173 self._name = n 163 self._name = n
174 self._pkgs = p 164 self._pkgs = p
175 Event.__init__(self, c) 165 Event.__init__(self)
176 self._failures = failures 166 self._failures = failures
177 167
178 def getPkgs(self): 168 def getPkgs(self):
@@ -204,20 +194,7 @@ class BuildBase(Event):
204 cfg = property(getCfg, setCfg, None, "cfg property") 194 cfg = property(getCfg, setCfg, None, "cfg property")
205 195
206 196
207class DepBase(PkgBase):
208 """Base class for dependency events"""
209 197
210 def __init__(self, t, data, d):
211 self._dep = d
212 PkgBase.__init__(self, t, data)
213
214 def getDep(self):
215 return self._dep
216
217 def setDep(self, dep):
218 self._dep = dep
219
220 dep = property(getDep, setDep, None, "dep property")
221 198
222 199
223class BuildStarted(BuildBase): 200class BuildStarted(BuildBase):
@@ -228,18 +205,13 @@ class BuildCompleted(BuildBase):
228 """bbmake build run completed""" 205 """bbmake build run completed"""
229 206
230 207
231class UnsatisfiedDep(DepBase):
232 """Unsatisfied Dependency"""
233
234 208
235class RecursiveDep(DepBase):
236 """Recursive Dependency"""
237 209
238class NoProvider(Event): 210class NoProvider(Event):
239 """No Provider for an Event""" 211 """No Provider for an Event"""
240 212
241 def __init__(self, item, data, runtime=False): 213 def __init__(self, item, runtime=False):
242 Event.__init__(self, data) 214 Event.__init__(self)
243 self._item = item 215 self._item = item
244 self._runtime = runtime 216 self._runtime = runtime
245 217
@@ -252,8 +224,8 @@ class NoProvider(Event):
252class MultipleProviders(Event): 224class MultipleProviders(Event):
253 """Multiple Providers""" 225 """Multiple Providers"""
254 226
255 def __init__(self, item, candidates, data, runtime = False): 227 def __init__(self, item, candidates, runtime = False):
256 Event.__init__(self, data) 228 Event.__init__(self)
257 self._item = item 229 self._item = item
258 self._candidates = candidates 230 self._candidates = candidates
259 self._is_runtime = runtime 231 self._is_runtime = runtime
@@ -281,8 +253,8 @@ class ParseProgress(Event):
281 Parsing Progress Event 253 Parsing Progress Event
282 """ 254 """
283 255
284 def __init__(self, d, cached, parsed, skipped, masked, errors, total): 256 def __init__(self, cached, parsed, skipped, masked, errors, total):
285 Event.__init__(self, d) 257 Event.__init__(self)
286 self.cached = cached 258 self.cached = cached
287 self.parsed = parsed 259 self.parsed = parsed
288 self.skipped = skipped 260 self.skipped = skipped
@@ -296,7 +268,7 @@ class DepTreeGenerated(Event):
296 Event when a dependency tree has been generated 268 Event when a dependency tree has been generated
297 """ 269 """
298 270
299 def __init__(self, d, depgraph): 271 def __init__(self, depgraph):
300 Event.__init__(self, d) 272 Event.__init__(self)
301 self._depgraph = depgraph 273 self._depgraph = depgraph
302 274
diff --git a/bitbake-dev/lib/bb/fetch/cvs.py b/bitbake-dev/lib/bb/fetch/cvs.py
index d8bd4eaf75..90a006500e 100644
--- a/bitbake-dev/lib/bb/fetch/cvs.py
+++ b/bitbake-dev/lib/bb/fetch/cvs.py
@@ -41,7 +41,7 @@ class Cvs(Fetch):
41 """ 41 """
42 Check to see if a given url can be fetched with cvs. 42 Check to see if a given url can be fetched with cvs.
43 """ 43 """
44 return ud.type in ['cvs', 'pserver'] 44 return ud.type in ['cvs']
45 45
46 def localpath(self, url, ud, d): 46 def localpath(self, url, ud, d):
47 if not "module" in ud.parm: 47 if not "module" in ud.parm:
diff --git a/bitbake-dev/lib/bb/fetch/git.py b/bitbake-dev/lib/bb/fetch/git.py
index 43053d6c46..0e68325db9 100644
--- a/bitbake-dev/lib/bb/fetch/git.py
+++ b/bitbake-dev/lib/bb/fetch/git.py
@@ -51,6 +51,10 @@ class Git(Fetch):
51 51
52 ud.branch = ud.parm.get("branch", "master") 52 ud.branch = ud.parm.get("branch", "master")
53 53
54 gitsrcname = '%s%s' % (ud.host, ud.path.replace('/', '.'))
55 ud.mirrortarball = 'git_%s.tar.gz' % (gitsrcname)
56 ud.clonedir = os.path.join(data.expand('${GITDIR}', d), gitsrcname)
57
54 tag = Fetch.srcrev_internal_helper(ud, d) 58 tag = Fetch.srcrev_internal_helper(ud, d)
55 if tag is True: 59 if tag is True:
56 ud.tag = self.latest_revision(url, ud, d) 60 ud.tag = self.latest_revision(url, ud, d)
@@ -60,7 +64,18 @@ class Git(Fetch):
60 if not ud.tag or ud.tag == "master": 64 if not ud.tag or ud.tag == "master":
61 ud.tag = self.latest_revision(url, ud, d) 65 ud.tag = self.latest_revision(url, ud, d)
62 66
63 ud.localfile = data.expand('git_%s%s_%s.tar.gz' % (ud.host, ud.path.replace('/', '.'), ud.tag), d) 67 subdir = ud.parm.get("subpath", "")
68 if subdir != "":
69 if subdir.endswith("/"):
70 subdir = subdir[:-1]
71 subdirpath = os.path.join(ud.path, subdir);
72 else:
73 subdirpath = ud.path;
74
75 if 'fullclone' in ud.parm:
76 ud.localfile = ud.mirrortarball
77 else:
78 ud.localfile = data.expand('git_%s%s_%s.tar.gz' % (ud.host, subdirpath.replace('/', '.'), ud.tag), d)
64 79
65 return os.path.join(data.getVar("DL_DIR", d, True), ud.localfile) 80 return os.path.join(data.getVar("DL_DIR", d, True), ud.localfile)
66 81
@@ -76,24 +91,20 @@ class Git(Fetch):
76 else: 91 else:
77 username = "" 92 username = ""
78 93
79 gitsrcname = '%s%s' % (ud.host, ud.path.replace('/', '.')) 94 repofile = os.path.join(data.getVar("DL_DIR", d, 1), ud.mirrortarball)
80
81 repofilename = 'git_%s.tar.gz' % (gitsrcname)
82 repofile = os.path.join(data.getVar("DL_DIR", d, 1), repofilename)
83 repodir = os.path.join(data.expand('${GITDIR}', d), gitsrcname)
84 95
85 coname = '%s' % (ud.tag) 96 coname = '%s' % (ud.tag)
86 codir = os.path.join(repodir, coname) 97 codir = os.path.join(ud.clonedir, coname)
87 98
88 if not os.path.exists(repodir): 99 if not os.path.exists(ud.clonedir):
89 if Fetch.try_mirror(d, repofilename): 100 if Fetch.try_mirror(d, ud.mirrortarball):
90 bb.mkdirhier(repodir) 101 bb.mkdirhier(ud.clonedir)
91 os.chdir(repodir) 102 os.chdir(ud.clonedir)
92 runfetchcmd("tar -xzf %s" % (repofile), d) 103 runfetchcmd("tar -xzf %s" % (repofile), d)
93 else: 104 else:
94 runfetchcmd("git clone -n %s://%s%s%s %s" % (ud.proto, username, ud.host, ud.path, repodir), d) 105 runfetchcmd("git clone -n %s://%s%s%s %s" % (ud.proto, username, ud.host, ud.path, ud.clonedir), d)
95 106
96 os.chdir(repodir) 107 os.chdir(ud.clonedir)
97 # Remove all but the .git directory 108 # Remove all but the .git directory
98 if not self._contains_ref(ud.tag, d): 109 if not self._contains_ref(ud.tag, d):
99 runfetchcmd("rm * -Rf", d) 110 runfetchcmd("rm * -Rf", d)
@@ -102,25 +113,45 @@ class Git(Fetch):
102 runfetchcmd("git prune-packed", d) 113 runfetchcmd("git prune-packed", d)
103 runfetchcmd("git pack-redundant --all | xargs -r rm", d) 114 runfetchcmd("git pack-redundant --all | xargs -r rm", d)
104 115
105 os.chdir(repodir) 116 os.chdir(ud.clonedir)
106 mirror_tarballs = data.getVar("BB_GENERATE_MIRROR_TARBALLS", d, True) 117 mirror_tarballs = data.getVar("BB_GENERATE_MIRROR_TARBALLS", d, True)
107 if mirror_tarballs != "0": 118 if mirror_tarballs != "0" or 'fullclone' in ud.parm:
108 bb.msg.note(1, bb.msg.domain.Fetcher, "Creating tarball of git repository") 119 bb.msg.note(1, bb.msg.domain.Fetcher, "Creating tarball of git repository")
109 runfetchcmd("tar -czf %s %s" % (repofile, os.path.join(".", ".git", "*") ), d) 120 runfetchcmd("tar -czf %s %s" % (repofile, os.path.join(".", ".git", "*") ), d)
110 121
122 if 'fullclone' in ud.parm:
123 return
124
111 if os.path.exists(codir): 125 if os.path.exists(codir):
112 bb.utils.prunedir(codir) 126 bb.utils.prunedir(codir)
113 127
128 subdir = ud.parm.get("subpath", "")
129 if subdir != "":
130 if subdir.endswith("/"):
131 subdirbase = os.path.basename(subdir[:-1])
132 else:
133 subdirbase = os.path.basename(subdir)
134 else:
135 subdirbase = ""
136
137 if subdir != "":
138 readpathspec = ":%s" % (subdir)
139 codir = os.path.join(codir, "git")
140 coprefix = os.path.join(codir, subdirbase, "")
141 else:
142 readpathspec = ""
143 coprefix = os.path.join(codir, "git", "")
144
114 bb.mkdirhier(codir) 145 bb.mkdirhier(codir)
115 os.chdir(repodir) 146 os.chdir(ud.clonedir)
116 runfetchcmd("git read-tree %s" % (ud.tag), d) 147 runfetchcmd("git read-tree %s%s" % (ud.tag, readpathspec), d)
117 runfetchcmd("git checkout-index -q -f --prefix=%s -a" % (os.path.join(codir, "git", "")), d) 148 runfetchcmd("git checkout-index -q -f --prefix=%s -a" % (coprefix), d)
118 149
119 os.chdir(codir) 150 os.chdir(codir)
120 bb.msg.note(1, bb.msg.domain.Fetcher, "Creating tarball of git checkout") 151 bb.msg.note(1, bb.msg.domain.Fetcher, "Creating tarball of git checkout")
121 runfetchcmd("tar -czf %s %s" % (ud.localpath, os.path.join(".", "*") ), d) 152 runfetchcmd("tar -czf %s %s" % (ud.localpath, os.path.join(".", "*") ), d)
122 153
123 os.chdir(repodir) 154 os.chdir(ud.clonedir)
124 bb.utils.prunedir(codir) 155 bb.utils.prunedir(codir)
125 156
126 def suppports_srcrev(self): 157 def suppports_srcrev(self):
@@ -145,7 +176,10 @@ class Git(Fetch):
145 else: 176 else:
146 username = "" 177 username = ""
147 178
148 output = runfetchcmd("git ls-remote %s://%s%s%s %s" % (ud.proto, username, ud.host, ud.path, ud.branch), d, True) 179 cmd = "git ls-remote %s://%s%s%s %s" % (ud.proto, username, ud.host, ud.path, ud.branch)
180 output = runfetchcmd(cmd, d, True)
181 if not output:
182 raise bb.fetch.FetchError("Fetch command %s gave empty output\n" % (cmd))
149 return output.split()[0] 183 return output.split()[0]
150 184
151 def _build_revision(self, url, ud, d): 185 def _build_revision(self, url, ud, d):
@@ -156,20 +190,20 @@ class Git(Fetch):
156 Return a suitable buildindex for the revision specified. This is done by counting revisions 190 Return a suitable buildindex for the revision specified. This is done by counting revisions
157 using "git rev-list" which may or may not work in different circumstances. 191 using "git rev-list" which may or may not work in different circumstances.
158 """ 192 """
159 gitsrcname = '%s%s' % (ud.host, ud.path.replace('/', '.'))
160 repodir = os.path.join(data.expand('${GITDIR}', d), gitsrcname)
161 193
162 cwd = os.getcwd() 194 cwd = os.getcwd()
163 195
164 # Check if we have the rev already 196 # Check if we have the rev already
165 if not os.path.exists(repodir): 197
198 if not os.path.exists(ud.clonedir):
199 print "no repo"
166 self.go(None, ud, d) 200 self.go(None, ud, d)
167 if not os.path.exists(repodir): 201 if not os.path.exists(ud.clonedir):
168 bb.msg.error(bb.msg.domain.Fetcher, "GIT repository for %s doesn't exist in %s, cannot get sortable buildnumber, using old value" % (url, repodir)) 202 bb.msg.error(bb.msg.domain.Fetcher, "GIT repository for %s doesn't exist in %s, cannot get sortable buildnumber, using old value" % (url, ud.clonedir))
169 return None 203 return None
170 204
171 205
172 os.chdir(repodir) 206 os.chdir(ud.clonedir)
173 if not self._contains_ref(rev, d): 207 if not self._contains_ref(rev, d):
174 self.go(None, ud, d) 208 self.go(None, ud, d)
175 209
diff --git a/bitbake-dev/lib/bb/fetch/local.py b/bitbake-dev/lib/bb/fetch/local.py
index 577774e597..f9bdf589cb 100644
--- a/bitbake-dev/lib/bb/fetch/local.py
+++ b/bitbake-dev/lib/bb/fetch/local.py
@@ -33,9 +33,9 @@ from bb.fetch import Fetch
33class Local(Fetch): 33class Local(Fetch):
34 def supports(self, url, urldata, d): 34 def supports(self, url, urldata, d):
35 """ 35 """
36 Check to see if a given url can be fetched with cvs. 36 Check to see if a given url represents a local fetch.
37 """ 37 """
38 return urldata.type in ['file','patch'] 38 return urldata.type in ['file']
39 39
40 def localpath(self, url, urldata, d): 40 def localpath(self, url, urldata, d):
41 """ 41 """
diff --git a/bitbake-dev/lib/bb/fetch/svk.py b/bitbake-dev/lib/bb/fetch/svk.py
index 442f85804f..120dad9d4e 100644
--- a/bitbake-dev/lib/bb/fetch/svk.py
+++ b/bitbake-dev/lib/bb/fetch/svk.py
@@ -36,7 +36,7 @@ class Svk(Fetch):
36 """Class to fetch a module or modules from svk repositories""" 36 """Class to fetch a module or modules from svk repositories"""
37 def supports(self, url, ud, d): 37 def supports(self, url, ud, d):
38 """ 38 """
39 Check to see if a given url can be fetched with cvs. 39 Check to see if a given url can be fetched with svk.
40 """ 40 """
41 return ud.type in ['svk'] 41 return ud.type in ['svk']
42 42
diff --git a/bitbake-dev/lib/bb/fetch/wget.py b/bitbake-dev/lib/bb/fetch/wget.py
index a0dca94040..fd93c7ec46 100644
--- a/bitbake-dev/lib/bb/fetch/wget.py
+++ b/bitbake-dev/lib/bb/fetch/wget.py
@@ -36,7 +36,7 @@ class Wget(Fetch):
36 """Class to fetch urls via 'wget'""" 36 """Class to fetch urls via 'wget'"""
37 def supports(self, url, ud, d): 37 def supports(self, url, ud, d):
38 """ 38 """
39 Check to see if a given url can be fetched with cvs. 39 Check to see if a given url can be fetched with wget.
40 """ 40 """
41 return ud.type in ['http','https','ftp'] 41 return ud.type in ['http','https','ftp']
42 42
diff --git a/bitbake-dev/lib/bb/msg.py b/bitbake-dev/lib/bb/msg.py
index 7990833c2e..3fcf7091be 100644
--- a/bitbake-dev/lib/bb/msg.py
+++ b/bitbake-dev/lib/bb/msg.py
@@ -47,9 +47,9 @@ domain = bb.utils.Enum(
47class MsgBase(bb.event.Event): 47class MsgBase(bb.event.Event):
48 """Base class for messages""" 48 """Base class for messages"""
49 49
50 def __init__(self, msg, d ): 50 def __init__(self, msg):
51 self._message = msg 51 self._message = msg
52 event.Event.__init__(self, d) 52 event.Event.__init__(self)
53 53
54class MsgDebug(MsgBase): 54class MsgDebug(MsgBase):
55 """Debug Message""" 55 """Debug Message"""
@@ -100,26 +100,26 @@ def debug(level, domain, msg, fn = None):
100 if not domain: 100 if not domain:
101 domain = 'default' 101 domain = 'default'
102 if debug_level[domain] >= level: 102 if debug_level[domain] >= level:
103 bb.event.fire(MsgDebug(msg, None)) 103 bb.event.fire(MsgDebug(msg), None)
104 104
105def note(level, domain, msg, fn = None): 105def note(level, domain, msg, fn = None):
106 if not domain: 106 if not domain:
107 domain = 'default' 107 domain = 'default'
108 if level == 1 or verbose or debug_level[domain] >= 1: 108 if level == 1 or verbose or debug_level[domain] >= 1:
109 bb.event.fire(MsgNote(msg, None)) 109 bb.event.fire(MsgNote(msg), None)
110 110
111def warn(domain, msg, fn = None): 111def warn(domain, msg, fn = None):
112 bb.event.fire(MsgWarn(msg, None)) 112 bb.event.fire(MsgWarn(msg), None)
113 113
114def error(domain, msg, fn = None): 114def error(domain, msg, fn = None):
115 bb.event.fire(MsgError(msg, None)) 115 bb.event.fire(MsgError(msg), None)
116 print 'ERROR: ' + msg 116 print 'ERROR: ' + msg
117 117
118def fatal(domain, msg, fn = None): 118def fatal(domain, msg, fn = None):
119 bb.event.fire(MsgFatal(msg, None)) 119 bb.event.fire(MsgFatal(msg), None)
120 print 'FATAL: ' + msg 120 print 'FATAL: ' + msg
121 sys.exit(1) 121 sys.exit(1)
122 122
123def plain(msg, fn = None): 123def plain(msg, fn = None):
124 bb.event.fire(MsgPlain(msg, None)) 124 bb.event.fire(MsgPlain(msg), None)
125 125
diff --git a/bitbake-dev/lib/bb/parse/parse_py/BBHandler.py b/bitbake-dev/lib/bb/parse/parse_py/BBHandler.py
index f0c3409568..f34599136c 100644
--- a/bitbake-dev/lib/bb/parse/parse_py/BBHandler.py
+++ b/bitbake-dev/lib/bb/parse/parse_py/BBHandler.py
@@ -114,7 +114,7 @@ def finalise(fn, d):
114 tasklist = data.getVar('__BBTASKS', d) or [] 114 tasklist = data.getVar('__BBTASKS', d) or []
115 bb.build.add_tasks(tasklist, d) 115 bb.build.add_tasks(tasklist, d)
116 116
117 bb.event.fire(bb.event.RecipeParsed(fn, d)) 117 bb.event.fire(bb.event.RecipeParsed(fn), d)
118 118
119 119
120def handle(fn, d, include = 0): 120def handle(fn, d, include = 0):
diff --git a/bitbake-dev/lib/bb/parse/parse_py/ConfHandler.py b/bitbake-dev/lib/bb/parse/parse_py/ConfHandler.py
index c9f1ea13fb..23316ada58 100644
--- a/bitbake-dev/lib/bb/parse/parse_py/ConfHandler.py
+++ b/bitbake-dev/lib/bb/parse/parse_py/ConfHandler.py
@@ -34,10 +34,17 @@ __require_regexp__ = re.compile( r"require\s+(.+)" )
34__export_regexp__ = re.compile( r"export\s+(.+)" ) 34__export_regexp__ = re.compile( r"export\s+(.+)" )
35 35
36def init(data): 36def init(data):
37 if not bb.data.getVar('TOPDIR', data): 37 topdir = bb.data.getVar('TOPDIR', data)
38 bb.data.setVar('TOPDIR', os.getcwd(), data) 38 if not topdir:
39 topdir = os.getcwd()
40 bb.data.setVar('TOPDIR', topdir, data)
39 if not bb.data.getVar('BBPATH', data): 41 if not bb.data.getVar('BBPATH', data):
40 bb.data.setVar('BBPATH', os.path.join(sys.prefix, 'share', 'bitbake'), data) 42 from pkg_resources import Requirement, resource_filename
43 bitbake = Requirement.parse("bitbake")
44 datadir = resource_filename(bitbake, "../share/bitbake")
45 basedir = resource_filename(bitbake, "..")
46 bb.data.setVar('BBPATH', '%s:%s:%s' % (topdir, datadir, basedir), data)
47
41 48
42def supports(fn, d): 49def supports(fn, d):
43 return localpath(fn, d)[-5:] == ".conf" 50 return localpath(fn, d)[-5:] == ".conf"
diff --git a/bitbake-dev/lib/bb/runqueue.py b/bitbake-dev/lib/bb/runqueue.py
index 8b6e12d185..c3ad442e47 100644
--- a/bitbake-dev/lib/bb/runqueue.py
+++ b/bitbake-dev/lib/bb/runqueue.py
@@ -857,6 +857,7 @@ class RunQueue:
857 self.runq_running = [] 857 self.runq_running = []
858 self.runq_complete = [] 858 self.runq_complete = []
859 self.build_pids = {} 859 self.build_pids = {}
860 self.build_pipes = {}
860 self.failed_fnids = [] 861 self.failed_fnids = []
861 862
862 # Mark initial buildable tasks 863 # Mark initial buildable tasks
@@ -870,7 +871,7 @@ class RunQueue:
870 871
871 self.state = runQueueRunning 872 self.state = runQueueRunning
872 873
873 event.fire(bb.event.StampUpdate(self.target_pairs, self.dataCache.stamp, self.cfgData)) 874 event.fire(bb.event.StampUpdate(self.target_pairs, self.dataCache.stamp), self.cfgData)
874 875
875 def task_complete(self, task): 876 def task_complete(self, task):
876 """ 877 """
@@ -903,7 +904,7 @@ class RunQueue:
903 self.stats.taskFailed() 904 self.stats.taskFailed()
904 fnid = self.runq_fnid[task] 905 fnid = self.runq_fnid[task]
905 self.failed_fnids.append(fnid) 906 self.failed_fnids.append(fnid)
906 bb.event.fire(runQueueTaskFailed(task, self.stats, self, self.cfgData)) 907 bb.event.fire(runQueueTaskFailed(task, self.stats, self), self.cfgData)
907 if self.taskData.abort: 908 if self.taskData.abort:
908 self.state = runQueueCleanup 909 self.state = runQueueCleanup
909 910
@@ -935,53 +936,67 @@ class RunQueue:
935 936
936 sys.stdout.flush() 937 sys.stdout.flush()
937 sys.stderr.flush() 938 sys.stderr.flush()
938 try: 939 try:
940 pipein, pipeout = os.pipe()
939 pid = os.fork() 941 pid = os.fork()
940 except OSError, e: 942 except OSError, e:
941 bb.msg.fatal(bb.msg.domain.RunQueue, "fork failed: %d (%s)" % (e.errno, e.strerror)) 943 bb.msg.fatal(bb.msg.domain.RunQueue, "fork failed: %d (%s)" % (e.errno, e.strerror))
942 if pid == 0: 944 if pid == 0:
945 os.close(pipein)
943 # Save out the PID so that the event can include it the 946 # Save out the PID so that the event can include it the
944 # events 947 # events
945 bb.event.worker_pid = os.getpid() 948 bb.event.worker_pid = os.getpid()
949 bb.event.worker_pipe = pipeout
946 950
947 bb.event.fire(runQueueTaskStarted(task, self.stats, self, self.cfgData))
948 bb.msg.note(1, bb.msg.domain.RunQueue,
949 "Running task %d of %d (ID: %s, %s)" % (self.stats.completed + self.stats.active + 1,
950 self.stats.total,
951 task,
952 self.get_user_idstring(task)))
953 self.state = runQueueChildProcess 951 self.state = runQueueChildProcess
954 # Make the child the process group leader 952 # Make the child the process group leader
955 os.setpgid(0, 0) 953 os.setpgid(0, 0)
954 # No stdin
956 newsi = os.open('/dev/null', os.O_RDWR) 955 newsi = os.open('/dev/null', os.O_RDWR)
957 os.dup2(newsi, sys.stdin.fileno()) 956 os.dup2(newsi, sys.stdin.fileno())
957
958 bb.event.fire(runQueueTaskStarted(task, self.stats, self), self.cfgData)
959 bb.msg.note(1, bb.msg.domain.RunQueue,
960 "Running task %d of %d (ID: %s, %s)" % (self.stats.completed + self.stats.active + 1,
961 self.stats.total,
962 task,
963 self.get_user_idstring(task)))
964
958 bb.data.setVar("__RUNQUEUE_DO_NOT_USE_EXTERNALLY", self, self.cooker.configuration.data) 965 bb.data.setVar("__RUNQUEUE_DO_NOT_USE_EXTERNALLY", self, self.cooker.configuration.data)
959 try: 966 try:
960 self.cooker.tryBuild(fn, taskname[3:]) 967 self.cooker.tryBuild(fn, taskname[3:])
961 except bb.build.EventException: 968 except bb.build.EventException:
962 bb.msg.error(bb.msg.domain.Build, "Build of " + fn + " " + taskname + " failed") 969 bb.msg.error(bb.msg.domain.Build, "Build of " + fn + " " + taskname + " failed")
963 sys.exit(1) 970 os._exit(1)
964 except: 971 except:
965 bb.msg.error(bb.msg.domain.Build, "Build of " + fn + " " + taskname + " failed") 972 bb.msg.error(bb.msg.domain.Build, "Build of " + fn + " " + taskname + " failed")
966 raise 973 os._exit(1)
967 sys.exit(0) 974 os._exit(0)
975
968 self.build_pids[pid] = task 976 self.build_pids[pid] = task
977 self.build_pipes[pid] = runQueuePipe(pipein, pipeout, self.cfgData)
969 self.runq_running[task] = 1 978 self.runq_running[task] = 1
970 self.stats.taskActive() 979 self.stats.taskActive()
971 if self.stats.active < self.number_tasks: 980 if self.stats.active < self.number_tasks:
972 continue 981 continue
982
983 for pipe in self.build_pipes:
984 self.build_pipes[pipe].read()
985
973 if self.stats.active > 0: 986 if self.stats.active > 0:
974 result = os.waitpid(-1, os.WNOHANG) 987 result = os.waitpid(-1, os.WNOHANG)
975 if result[0] is 0 and result[1] is 0: 988 if result[0] is 0 and result[1] is 0:
976 return 989 return
977 task = self.build_pids[result[0]] 990 task = self.build_pids[result[0]]
978 del self.build_pids[result[0]] 991 del self.build_pids[result[0]]
992 self.build_pipes[result[0]].close()
993 del self.build_pipes[result[0]]
979 if result[1] != 0: 994 if result[1] != 0:
980 self.task_fail(task, result[1]) 995 self.task_fail(task, result[1])
981 return 996 return
982 self.task_complete(task) 997 self.task_complete(task)
983 self.stats.taskCompleted() 998 self.stats.taskCompleted()
984 bb.event.fire(runQueueTaskCompleted(task, self.stats, self, self.cfgData)) 999 bb.event.fire(runQueueTaskCompleted(task, self.stats, self), self.cfgData)
985 continue 1000 continue
986 1001
987 if len(self.failed_fnids) != 0: 1002 if len(self.failed_fnids) != 0:
@@ -1006,6 +1021,8 @@ class RunQueue:
1006 os.kill(-k, signal.SIGINT) 1021 os.kill(-k, signal.SIGINT)
1007 except: 1022 except:
1008 pass 1023 pass
1024 for pipe in self.build_pipes:
1025 self.build_pipes[pipe].read()
1009 1026
1010 def finish_runqueue(self, now = False): 1027 def finish_runqueue(self, now = False):
1011 self.state = runQueueCleanUp 1028 self.state = runQueueCleanUp
@@ -1013,7 +1030,7 @@ class RunQueue:
1013 self.finish_runqueue_now() 1030 self.finish_runqueue_now()
1014 try: 1031 try:
1015 while self.stats.active > 0: 1032 while self.stats.active > 0:
1016 bb.event.fire(runQueueExitWait(self.stats.active, self.cfgData)) 1033 bb.event.fire(runQueueExitWait(self.stats.active), self.cfgData)
1017 bb.msg.note(1, bb.msg.domain.RunQueue, "Waiting for %s active tasks to finish" % self.stats.active) 1034 bb.msg.note(1, bb.msg.domain.RunQueue, "Waiting for %s active tasks to finish" % self.stats.active)
1018 tasknum = 1 1035 tasknum = 1
1019 for k, v in self.build_pids.iteritems(): 1036 for k, v in self.build_pids.iteritems():
@@ -1024,11 +1041,13 @@ class RunQueue:
1024 return 1041 return
1025 task = self.build_pids[result[0]] 1042 task = self.build_pids[result[0]]
1026 del self.build_pids[result[0]] 1043 del self.build_pids[result[0]]
1044 self.build_pipes[result[0]].close()
1045 del self.build_pipes[result[0]]
1027 if result[1] != 0: 1046 if result[1] != 0:
1028 self.task_fail(task, result[1]) 1047 self.task_fail(task, result[1])
1029 else: 1048 else:
1030 self.stats.taskCompleted() 1049 self.stats.taskCompleted()
1031 bb.event.fire(runQueueTaskCompleted(task, self.stats, self, self.cfgData)) 1050 bb.event.fire(runQueueTaskCompleted(task, self.stats, self), self.cfgData)
1032 except: 1051 except:
1033 self.finish_runqueue_now() 1052 self.finish_runqueue_now()
1034 raise 1053 raise
@@ -1078,43 +1097,43 @@ class runQueueExitWait(bb.event.Event):
1078 Event when waiting for task processes to exit 1097 Event when waiting for task processes to exit
1079 """ 1098 """
1080 1099
1081 def __init__(self, remain, d): 1100 def __init__(self, remain):
1082 self.remain = remain 1101 self.remain = remain
1083 self.message = "Waiting for %s active tasks to finish" % remain 1102 self.message = "Waiting for %s active tasks to finish" % remain
1084 bb.event.Event.__init__(self, d) 1103 bb.event.Event.__init__(self)
1085 1104
1086class runQueueEvent(bb.event.Event): 1105class runQueueEvent(bb.event.Event):
1087 """ 1106 """
1088 Base runQueue event class 1107 Base runQueue event class
1089 """ 1108 """
1090 def __init__(self, task, stats, rq, d): 1109 def __init__(self, task, stats, rq):
1091 self.taskid = task 1110 self.taskid = task
1092 self.taskstring = rq.get_user_idstring(task) 1111 self.taskstring = rq.get_user_idstring(task)
1093 self.stats = stats 1112 self.stats = stats
1094 bb.event.Event.__init__(self, d) 1113 bb.event.Event.__init__(self)
1095 1114
1096class runQueueTaskStarted(runQueueEvent): 1115class runQueueTaskStarted(runQueueEvent):
1097 """ 1116 """
1098 Event notifing a task was started 1117 Event notifing a task was started
1099 """ 1118 """
1100 def __init__(self, task, stats, rq, d): 1119 def __init__(self, task, stats, rq):
1101 runQueueEvent.__init__(self, task, stats, rq, d) 1120 runQueueEvent.__init__(self, task, stats, rq)
1102 self.message = "Running task %s (%d of %d) (%s)" % (task, stats.completed + stats.active + 1, self.stats.total, self.taskstring) 1121 self.message = "Running task %s (%d of %d) (%s)" % (task, stats.completed + stats.active + 1, self.stats.total, self.taskstring)
1103 1122
1104class runQueueTaskFailed(runQueueEvent): 1123class runQueueTaskFailed(runQueueEvent):
1105 """ 1124 """
1106 Event notifing a task failed 1125 Event notifing a task failed
1107 """ 1126 """
1108 def __init__(self, task, stats, rq, d): 1127 def __init__(self, task, stats, rq):
1109 runQueueEvent.__init__(self, task, stats, rq, d) 1128 runQueueEvent.__init__(self, task, stats, rq)
1110 self.message = "Task %s failed (%s)" % (task, self.taskstring) 1129 self.message = "Task %s failed (%s)" % (task, self.taskstring)
1111 1130
1112class runQueueTaskCompleted(runQueueEvent): 1131class runQueueTaskCompleted(runQueueEvent):
1113 """ 1132 """
1114 Event notifing a task completed 1133 Event notifing a task completed
1115 """ 1134 """
1116 def __init__(self, task, stats, rq, d): 1135 def __init__(self, task, stats, rq):
1117 runQueueEvent.__init__(self, task, stats, rq, d) 1136 runQueueEvent.__init__(self, task, stats, rq)
1118 self.message = "Task %s completed (%s)" % (task, self.taskstring) 1137 self.message = "Task %s completed (%s)" % (task, self.taskstring)
1119 1138
1120def check_stamp_fn(fn, taskname, d): 1139def check_stamp_fn(fn, taskname, d):
@@ -1124,3 +1143,32 @@ def check_stamp_fn(fn, taskname, d):
1124 if taskid is not None: 1143 if taskid is not None:
1125 return rq.check_stamp_task(taskid) 1144 return rq.check_stamp_task(taskid)
1126 return None 1145 return None
1146
1147class runQueuePipe():
1148 """
1149 Abstraction for a pipe between a worker thread and the server
1150 """
1151 def __init__(self, pipein, pipeout, d):
1152 self.fd = pipein
1153 os.close(pipeout)
1154 self.queue = ""
1155 self.d = d
1156
1157 def read(self):
1158 start = len(self.queue)
1159 self.queue = self.queue + os.read(self.fd, 1024)
1160 end = len(self.queue)
1161 index = self.queue.find("</event>")
1162 while index != -1:
1163 bb.event.fire_from_worker(self.queue[:index+8], self.d)
1164 self.queue = self.queue[index+8:]
1165 index = self.queue.find("</event>")
1166 return (end > start)
1167
1168 def close(self):
1169 while self.read():
1170 continue
1171 if len(self.queue) > 0:
1172 print "Warning, worker left partial message"
1173 os.close(self.fd)
1174
diff --git a/bitbake-dev/lib/bb/server/__init__.py b/bitbake-dev/lib/bb/server/__init__.py
index 0dd04cf724..1a732236e2 100644
--- a/bitbake-dev/lib/bb/server/__init__.py
+++ b/bitbake-dev/lib/bb/server/__init__.py
@@ -1 +1,2 @@
1import xmlrpc 1import xmlrpc
2import none
diff --git a/bitbake-dev/lib/bb/server/none.py b/bitbake-dev/lib/bb/server/none.py
index ef061bc5dd..ebda111582 100644
--- a/bitbake-dev/lib/bb/server/none.py
+++ b/bitbake-dev/lib/bb/server/none.py
@@ -1,5 +1,5 @@
1# 1#
2# BitBake XMLRPC Server 2# BitBake 'dummy' Passthrough Server
3# 3#
4# Copyright (C) 2006 - 2007 Michael 'Mickey' Lauer 4# Copyright (C) 2006 - 2007 Michael 'Mickey' Lauer
5# Copyright (C) 2006 - 2008 Richard Purdie 5# Copyright (C) 2006 - 2008 Richard Purdie
@@ -31,8 +31,11 @@
31 in the server's main loop. 31 in the server's main loop.
32""" 32"""
33 33
34import time
34import bb 35import bb
36from bb.ui import uievent
35import xmlrpclib 37import xmlrpclib
38import pickle
36 39
37DEBUG = False 40DEBUG = False
38 41
@@ -44,31 +47,19 @@ class BitBakeServerCommands():
44 self.cooker = cooker 47 self.cooker = cooker
45 self.server = server 48 self.server = server
46 49
47 def registerEventHandler(self, host, port):
48 """
49 Register a remote UI Event Handler
50 """
51 s = xmlrpclib.Server("http://%s:%d" % (host, port), allow_none=True)
52 return bb.event.register_UIHhandler(s)
53
54 def unregisterEventHandler(self, handlerNum):
55 """
56 Unregister a remote UI Event Handler
57 """
58 return bb.event.unregister_UIHhandler(handlerNum)
59
60 def runCommand(self, command): 50 def runCommand(self, command):
61 """ 51 """
62 Run a cooker command on the server 52 Run a cooker command on the server
63 """ 53 """
54 #print "Running Command %s" % command
64 return self.cooker.command.runCommand(command) 55 return self.cooker.command.runCommand(command)
65 56
66 def terminateServer(self): 57 def terminateServer(self):
67 """ 58 """
68 Trigger the server to quit 59 Trigger the server to quit
69 """ 60 """
70 self.server.quit = True 61 self.server.server_exit()
71 print "Server (cooker) exitting" 62 #print "Server (cooker) exitting"
72 return 63 return
73 64
74 def ping(self): 65 def ping(self):
@@ -77,63 +68,84 @@ class BitBakeServerCommands():
77 """ 68 """
78 return True 69 return True
79 70
80class BitBakeXMLRPCServer(SimpleXMLRPCServer): 71eventQueue = []
72
73class BBUIEventQueue:
74 class event:
75 def __init__(self, parent):
76 self.parent = parent
77 @staticmethod
78 def send(event):
79 bb.server.none.eventQueue.append(pickle.loads(event))
80 @staticmethod
81 def quit():
82 return
83
84 def __init__(self, BBServer):
85 self.eventQueue = bb.server.none.eventQueue
86 self.BBServer = BBServer
87 self.EventHandle = bb.event.register_UIHhandler(self)
88
89 def getEvent(self):
90 if len(self.eventQueue) == 0:
91 return None
92
93 return self.eventQueue.pop(0)
94
95 def waitEvent(self, delay):
96 event = self.getEvent()
97 if event:
98 return event
99 self.BBServer.idle_commands(delay)
100 return self.getEvent()
101
102 def queue_event(self, event):
103 self.eventQueue.append(event)
104
105 def system_quit( self ):
106 bb.event.unregister_UIHhandler(self.EventHandle)
107
108class BitBakeServer():
81 # remove this when you're done with debugging 109 # remove this when you're done with debugging
82 # allow_reuse_address = True 110 # allow_reuse_address = True
83 111
84 def __init__(self, cooker, interface = ("localhost", 0)): 112 def __init__(self, cooker):
85 """
86 Constructor
87 """
88 SimpleXMLRPCServer.__init__(self, interface,
89 requestHandler=SimpleXMLRPCRequestHandler,
90 logRequests=False, allow_none=True)
91 self._idlefuns = {} 113 self._idlefuns = {}
92 self.host, self.port = self.socket.getsockname() 114 self.commands = BitBakeServerCommands(self, cooker)
93 #self.register_introspection_functions()
94 commands = BitBakeServerCommands(self, cooker)
95 self.autoregister_all_functions(commands, "")
96
97 def autoregister_all_functions(self, context, prefix):
98 """
99 Convenience method for registering all functions in the scope
100 of this class that start with a common prefix
101 """
102 methodlist = inspect.getmembers(context, inspect.ismethod)
103 for name, method in methodlist:
104 if name.startswith(prefix):
105 self.register_function(method, name[len(prefix):])
106 115
107 def register_idle_function(self, function, data): 116 def register_idle_function(self, function, data):
108 """Register a function to be called while the server is idle""" 117 """Register a function to be called while the server is idle"""
109 assert callable(function) 118 assert callable(function)
110 self._idlefuns[function] = data 119 self._idlefuns[function] = data
111 120
112 def serve_forever(self): 121 def idle_commands(self, delay):
113 """ 122 #print "Idle queue length %s" % len(self._idlefuns)
114 Serve Requests. Overloaded to honor a quit command 123 #print "Idle timeout, running idle functions"
115 """ 124 #if len(self._idlefuns) == 0:
116 self.quit = False 125 nextsleep = delay
117 while not self.quit: 126 for function, data in self._idlefuns.items():
118 #print "Idle queue length %s" % len(self._idlefuns) 127 try:
119 if len(self._idlefuns) == 0: 128 retval = function(self, data, False)
120 self.timeout = None 129 #print "Idle function returned %s" % (retval)
121 else: 130 if retval is False:
122 self.timeout = 0 131 del self._idlefuns[function]
123 self.handle_request() 132 elif retval is True:
124 #print "Idle timeout, running idle functions" 133 nextsleep = None
125 for function, data in self._idlefuns.items(): 134 elif nextsleep is None:
126 try: 135 continue
127 retval = function(self, data, False) 136 elif retval < nextsleep:
128 if not retval: 137 nextsleep = retval
129 del self._idlefuns[function] 138 except SystemExit:
130 except SystemExit: 139 raise
131 raise 140 except:
132 except: 141 import traceback
133 import traceback 142 traceback.print_exc()
134 traceback.print_exc() 143 pass
135 pass 144 if nextsleep is not None:
145 #print "Sleeping for %s (%s)" % (nextsleep, delay)
146 time.sleep(nextsleep)
136 147
148 def server_exit(self):
137 # Tell idle functions we're exiting 149 # Tell idle functions we're exiting
138 for function, data in self._idlefuns.items(): 150 for function, data in self._idlefuns.items():
139 try: 151 try:
@@ -141,5 +153,29 @@ class BitBakeXMLRPCServer(SimpleXMLRPCServer):
141 except: 153 except:
142 pass 154 pass
143 155
144 self.server_close() 156class BitbakeServerInfo():
145 return 157 def __init__(self, server):
158 self.server = server
159 self.commands = server.commands
160
161class BitBakeServerFork():
162 def __init__(self, serverinfo, command, logfile):
163 serverinfo.forkCommand = command
164 serverinfo.logfile = logfile
165
166class BitBakeServerConnection():
167 def __init__(self, serverinfo):
168 self.server = serverinfo.server
169 self.connection = serverinfo.commands
170 self.events = bb.server.none.BBUIEventQueue(self.server)
171
172 def terminate(self):
173 try:
174 self.events.system_quit()
175 except:
176 pass
177 try:
178 self.connection.terminateServer()
179 except:
180 pass
181
diff --git a/bitbake-dev/lib/bb/server/xmlrpc.py b/bitbake-dev/lib/bb/server/xmlrpc.py
index c5937abd66..b4d69f7be3 100644
--- a/bitbake-dev/lib/bb/server/xmlrpc.py
+++ b/bitbake-dev/lib/bb/server/xmlrpc.py
@@ -33,6 +33,8 @@
33 33
34import bb 34import bb
35import xmlrpclib 35import xmlrpclib
36from bb import daemonize
37from bb.ui import uievent
36 38
37DEBUG = False 39DEBUG = False
38 40
@@ -114,26 +116,34 @@ class BitBakeServer(SimpleXMLRPCServer):
114 Serve Requests. Overloaded to honor a quit command 116 Serve Requests. Overloaded to honor a quit command
115 """ 117 """
116 self.quit = False 118 self.quit = False
119 self.timeout = 0 # Run Idle calls for our first callback
117 while not self.quit: 120 while not self.quit:
118 #print "Idle queue length %s" % len(self._idlefuns) 121 #print "Idle queue length %s" % len(self._idlefuns)
119 if len(self._idlefuns) == 0:
120 self.timeout = None
121 else:
122 self.timeout = 0
123 self.handle_request() 122 self.handle_request()
124 #print "Idle timeout, running idle functions" 123 #print "Idle timeout, running idle functions"
124 nextsleep = None
125 for function, data in self._idlefuns.items(): 125 for function, data in self._idlefuns.items():
126 try: 126 try:
127 retval = function(self, data, False) 127 retval = function(self, data, False)
128 if not retval: 128 if retval is False:
129 del self._idlefuns[function] 129 del self._idlefuns[function]
130 elif retval is True:
131 nextsleep = 0
132 elif nextsleep is 0:
133 continue
134 elif nextsleep is None:
135 nextsleep = retval
136 elif retval < nextsleep:
137 nextsleep = retval
130 except SystemExit: 138 except SystemExit:
131 raise 139 raise
132 except: 140 except:
133 import traceback 141 import traceback
134 traceback.print_exc() 142 traceback.print_exc()
135 pass 143 pass
136 144 if nextsleep is None and len(self._idlefuns) > 0:
145 nextsleep = 0
146 self.timeout = nextsleep
137 # Tell idle functions we're exiting 147 # Tell idle functions we're exiting
138 for function, data in self._idlefuns.items(): 148 for function, data in self._idlefuns.items():
139 try: 149 try:
@@ -143,3 +153,31 @@ class BitBakeServer(SimpleXMLRPCServer):
143 153
144 self.server_close() 154 self.server_close()
145 return 155 return
156
157class BitbakeServerInfo():
158 def __init__(self, server):
159 self.host = server.host
160 self.port = server.port
161
162class BitBakeServerFork():
163 def __init__(self, serverinfo, command, logfile):
164 daemonize.createDaemon(command, logfile)
165
166class BitBakeServerConnection():
167 def __init__(self, serverinfo):
168 self.connection = xmlrpclib.Server("http://%s:%s" % (serverinfo.host, serverinfo.port), allow_none=True)
169 self.events = uievent.BBUIEventQueue(self.connection)
170
171 def terminate(self):
172 # Don't wait for server indefinitely
173 import socket
174 socket.setdefaulttimeout(2)
175 try:
176 self.events.system_quit()
177 except:
178 pass
179 try:
180 self.connection.terminateServer()
181 except:
182 pass
183
diff --git a/bitbake-dev/lib/bb/taskdata.py b/bitbake-dev/lib/bb/taskdata.py
index 73ec2aa750..e3a60b9884 100644
--- a/bitbake-dev/lib/bb/taskdata.py
+++ b/bitbake-dev/lib/bb/taskdata.py
@@ -25,6 +25,19 @@ Task data collection and handling
25 25
26import bb 26import bb
27 27
28def re_match_strings(target, strings):
29 """
30 Whether or not the string 'target' matches
31 any one string of the strings which can be regular expression string
32 """
33 import re
34
35 for name in strings:
36 if (name==target or
37 re.search(name,target)!=None):
38 return True
39 return False
40
28class TaskData: 41class TaskData:
29 """ 42 """
30 BitBake Task Data implementation 43 BitBake Task Data implementation
@@ -261,7 +274,7 @@ class TaskData:
261 """ 274 """
262 unresolved = [] 275 unresolved = []
263 for target in self.build_names_index: 276 for target in self.build_names_index:
264 if target in dataCache.ignored_dependencies: 277 if re_match_strings(target, dataCache.ignored_dependencies):
265 continue 278 continue
266 if self.build_names_index.index(target) in self.failed_deps: 279 if self.build_names_index.index(target) in self.failed_deps:
267 continue 280 continue
@@ -276,7 +289,7 @@ class TaskData:
276 """ 289 """
277 unresolved = [] 290 unresolved = []
278 for target in self.run_names_index: 291 for target in self.run_names_index:
279 if target in dataCache.ignored_dependencies: 292 if re_match_strings(target, dataCache.ignored_dependencies):
280 continue 293 continue
281 if self.run_names_index.index(target) in self.failed_rdeps: 294 if self.run_names_index.index(target) in self.failed_rdeps:
282 continue 295 continue
@@ -356,7 +369,7 @@ class TaskData:
356 added internally during dependency resolution 369 added internally during dependency resolution
357 """ 370 """
358 371
359 if item in dataCache.ignored_dependencies: 372 if re_match_strings(item, dataCache.ignored_dependencies):
360 return 373 return
361 374
362 if not item in dataCache.providers: 375 if not item in dataCache.providers:
@@ -364,7 +377,7 @@ class TaskData:
364 bb.msg.note(2, bb.msg.domain.Provider, "Nothing PROVIDES '%s' (but '%s' DEPENDS on or otherwise requires it)" % (item, self.get_dependees_str(item))) 377 bb.msg.note(2, bb.msg.domain.Provider, "Nothing PROVIDES '%s' (but '%s' DEPENDS on or otherwise requires it)" % (item, self.get_dependees_str(item)))
365 else: 378 else:
366 bb.msg.note(2, bb.msg.domain.Provider, "Nothing PROVIDES '%s'" % (item)) 379 bb.msg.note(2, bb.msg.domain.Provider, "Nothing PROVIDES '%s'" % (item))
367 bb.event.fire(bb.event.NoProvider(item, cfgData)) 380 bb.event.fire(bb.event.NoProvider(item), cfgData)
368 raise bb.providers.NoProvider(item) 381 raise bb.providers.NoProvider(item)
369 382
370 if self.have_build_target(item): 383 if self.have_build_target(item):
@@ -377,7 +390,7 @@ class TaskData:
377 390
378 if not eligible: 391 if not eligible:
379 bb.msg.note(2, bb.msg.domain.Provider, "No buildable provider PROVIDES '%s' but '%s' DEPENDS on or otherwise requires it. Enable debugging and see earlier logs to find unbuildable providers." % (item, self.get_dependees_str(item))) 392 bb.msg.note(2, bb.msg.domain.Provider, "No buildable provider PROVIDES '%s' but '%s' DEPENDS on or otherwise requires it. Enable debugging and see earlier logs to find unbuildable providers." % (item, self.get_dependees_str(item)))
380 bb.event.fire(bb.event.NoProvider(item, cfgData)) 393 bb.event.fire(bb.event.NoProvider(item), cfgData)
381 raise bb.providers.NoProvider(item) 394 raise bb.providers.NoProvider(item)
382 395
383 if len(eligible) > 1 and foundUnique == False: 396 if len(eligible) > 1 and foundUnique == False:
@@ -387,7 +400,7 @@ class TaskData:
387 providers_list.append(dataCache.pkg_fn[fn]) 400 providers_list.append(dataCache.pkg_fn[fn])
388 bb.msg.note(1, bb.msg.domain.Provider, "multiple providers are available for %s (%s);" % (item, ", ".join(providers_list))) 401 bb.msg.note(1, bb.msg.domain.Provider, "multiple providers are available for %s (%s);" % (item, ", ".join(providers_list)))
389 bb.msg.note(1, bb.msg.domain.Provider, "consider defining PREFERRED_PROVIDER_%s" % item) 402 bb.msg.note(1, bb.msg.domain.Provider, "consider defining PREFERRED_PROVIDER_%s" % item)
390 bb.event.fire(bb.event.MultipleProviders(item, providers_list, cfgData)) 403 bb.event.fire(bb.event.MultipleProviders(item, providers_list), cfgData)
391 self.consider_msgs_cache.append(item) 404 self.consider_msgs_cache.append(item)
392 405
393 for fn in eligible: 406 for fn in eligible:
@@ -407,7 +420,7 @@ class TaskData:
407 (takes item names from RDEPENDS/PACKAGES namespace) 420 (takes item names from RDEPENDS/PACKAGES namespace)
408 """ 421 """
409 422
410 if item in dataCache.ignored_dependencies: 423 if re_match_strings(item, dataCache.ignored_dependencies):
411 return 424 return
412 425
413 if self.have_runtime_target(item): 426 if self.have_runtime_target(item):
@@ -417,7 +430,7 @@ class TaskData:
417 430
418 if not all_p: 431 if not all_p:
419 bb.msg.error(bb.msg.domain.Provider, "'%s' RDEPENDS/RRECOMMENDS or otherwise requires the runtime entity '%s' but it wasn't found in any PACKAGE or RPROVIDES variables" % (self.get_rdependees_str(item), item)) 432 bb.msg.error(bb.msg.domain.Provider, "'%s' RDEPENDS/RRECOMMENDS or otherwise requires the runtime entity '%s' but it wasn't found in any PACKAGE or RPROVIDES variables" % (self.get_rdependees_str(item), item))
420 bb.event.fire(bb.event.NoProvider(item, cfgData, runtime=True)) 433 bb.event.fire(bb.event.NoProvider(item, runtime=True), cfgData)
421 raise bb.providers.NoRProvider(item) 434 raise bb.providers.NoRProvider(item)
422 435
423 eligible, numberPreferred = bb.providers.filterProvidersRunTime(all_p, item, cfgData, dataCache) 436 eligible, numberPreferred = bb.providers.filterProvidersRunTime(all_p, item, cfgData, dataCache)
@@ -425,7 +438,7 @@ class TaskData:
425 438
426 if not eligible: 439 if not eligible:
427 bb.msg.error(bb.msg.domain.Provider, "'%s' RDEPENDS/RRECOMMENDS or otherwise requires the runtime entity '%s' but it wasn't found in any PACKAGE or RPROVIDES variables of any buildable targets.\nEnable debugging and see earlier logs to find unbuildable targets." % (self.get_rdependees_str(item), item)) 440 bb.msg.error(bb.msg.domain.Provider, "'%s' RDEPENDS/RRECOMMENDS or otherwise requires the runtime entity '%s' but it wasn't found in any PACKAGE or RPROVIDES variables of any buildable targets.\nEnable debugging and see earlier logs to find unbuildable targets." % (self.get_rdependees_str(item), item))
428 bb.event.fire(bb.event.NoProvider(item, cfgData, runtime=True)) 441 bb.event.fire(bb.event.NoProvider(item, runtime=True), cfgData)
429 raise bb.providers.NoRProvider(item) 442 raise bb.providers.NoRProvider(item)
430 443
431 if len(eligible) > 1 and numberPreferred == 0: 444 if len(eligible) > 1 and numberPreferred == 0:
@@ -435,7 +448,7 @@ class TaskData:
435 providers_list.append(dataCache.pkg_fn[fn]) 448 providers_list.append(dataCache.pkg_fn[fn])
436 bb.msg.note(2, bb.msg.domain.Provider, "multiple providers are available for runtime %s (%s);" % (item, ", ".join(providers_list))) 449 bb.msg.note(2, bb.msg.domain.Provider, "multiple providers are available for runtime %s (%s);" % (item, ", ".join(providers_list)))
437 bb.msg.note(2, bb.msg.domain.Provider, "consider defining a PREFERRED_PROVIDER entry to match runtime %s" % item) 450 bb.msg.note(2, bb.msg.domain.Provider, "consider defining a PREFERRED_PROVIDER entry to match runtime %s" % item)
438 bb.event.fire(bb.event.MultipleProviders(item,providers_list, cfgData, runtime=True)) 451 bb.event.fire(bb.event.MultipleProviders(item,providers_list, runtime=True), cfgData)
439 self.consider_msgs_cache.append(item) 452 self.consider_msgs_cache.append(item)
440 453
441 if numberPreferred > 1: 454 if numberPreferred > 1:
@@ -445,7 +458,7 @@ class TaskData:
445 providers_list.append(dataCache.pkg_fn[fn]) 458 providers_list.append(dataCache.pkg_fn[fn])
446 bb.msg.note(2, bb.msg.domain.Provider, "multiple providers are available for runtime %s (top %s entries preferred) (%s);" % (item, numberPreferred, ", ".join(providers_list))) 459 bb.msg.note(2, bb.msg.domain.Provider, "multiple providers are available for runtime %s (top %s entries preferred) (%s);" % (item, numberPreferred, ", ".join(providers_list)))
447 bb.msg.note(2, bb.msg.domain.Provider, "consider defining only one PREFERRED_PROVIDER entry to match runtime %s" % item) 460 bb.msg.note(2, bb.msg.domain.Provider, "consider defining only one PREFERRED_PROVIDER entry to match runtime %s" % item)
448 bb.event.fire(bb.event.MultipleProviders(item,providers_list, cfgData, runtime=True)) 461 bb.event.fire(bb.event.MultipleProviders(item,providers_list, runtime=True), cfgData)
449 self.consider_msgs_cache.append(item) 462 self.consider_msgs_cache.append(item)
450 463
451 # run through the list until we find one that we can build 464 # run through the list until we find one that we can build
diff --git a/bitbake-dev/lib/bb/ui/crumbs/runningbuild.py b/bitbake-dev/lib/bb/ui/crumbs/runningbuild.py
index 34f65d2396..401559255b 100644
--- a/bitbake-dev/lib/bb/ui/crumbs/runningbuild.py
+++ b/bitbake-dev/lib/bb/ui/crumbs/runningbuild.py
@@ -61,36 +61,36 @@ class RunningBuild (gobject.GObject):
61 # If we have a pid attached to this message/event try and get the 61 # If we have a pid attached to this message/event try and get the
62 # (package, task) pair for it. If we get that then get the parent iter 62 # (package, task) pair for it. If we get that then get the parent iter
63 # for the message. 63 # for the message.
64 if event[1].has_key ('pid'): 64 if hassattr(event, 'pid'):
65 pid = event[1]['pid'] 65 pid = event.pid
66 if self.pids_to_task.has_key(pid): 66 if self.pids_to_task.has_key(pid):
67 (package, task) = self.pids_to_task[pid] 67 (package, task) = self.pids_to_task[pid]
68 parent = self.tasks_to_iter[(package, task)] 68 parent = self.tasks_to_iter[(package, task)]
69 69
70 if event[0].startswith('bb.msg.Msg'): 70 if isinstance(event, bb.msg.Msg):
71 # Set a pretty icon for the message based on it's type. 71 # Set a pretty icon for the message based on it's type.
72 if (event[0].startswith ('bb.msg.MsgWarn')): 72 if isinstance(event, bb.msg.MsgWarn):
73 icon = "dialog-warning" 73 icon = "dialog-warning"
74 elif (event[0].startswith ('bb.msg.MsgErr')): 74 elif isinstance(event, bb.msg.MsgErr):
75 icon = "dialog-error" 75 icon = "dialog-error"
76 else: 76 else:
77 icon = None 77 icon = None
78 78
79 # Ignore the "Running task i of n .." messages 79 # Ignore the "Running task i of n .." messages
80 if (event[1]['_message'].startswith ("Running task")): 80 if (event._message.startswith ("Running task")):
81 return 81 return
82 82
83 # Add the message to the tree either at the top level if parent is 83 # Add the message to the tree either at the top level if parent is
84 # None otherwise as a descendent of a task. 84 # None otherwise as a descendent of a task.
85 self.model.append (parent, 85 self.model.append (parent,
86 (event[0].split()[-1], # e.g. MsgWarn, MsgError 86 (event.__name__.split()[-1], # e.g. MsgWarn, MsgError
87 package, 87 package,
88 task, 88 task,
89 event[1]['_message'], 89 event._message,
90 icon, 90 icon,
91 False)) 91 False))
92 elif event[0].startswith('bb.build.TaskStarted'): 92 elif isinstance(event, bb.build.TaskStarted):
93 (package, task) = (event[1]['_package'], event[1]['_task']) 93 (package, task) = (event._package, event._task)
94 94
95 # Save out this PID. 95 # Save out this PID.
96 self.pids_to_task[pid] = (package,task) 96 self.pids_to_task[pid] = (package,task)
@@ -128,9 +128,9 @@ class RunningBuild (gobject.GObject):
128 # Mark this task as active. 128 # Mark this task as active.
129 self.model.set(i, self.model.COL_ICON, "gtk-execute") 129 self.model.set(i, self.model.COL_ICON, "gtk-execute")
130 130
131 elif event[0].startswith('bb.build.Task'): 131 elif isinstance(event, bb.build.Task):
132 132
133 if event[0].startswith('bb.build.TaskFailed'): 133 if isinstance(event, bb.build.TaskFailed):
134 # Mark the task as failed 134 # Mark the task as failed
135 i = self.tasks_to_iter[(package, task)] 135 i = self.tasks_to_iter[(package, task)]
136 self.model.set(i, self.model.COL_ICON, "dialog-error") 136 self.model.set(i, self.model.COL_ICON, "dialog-error")
@@ -153,8 +153,8 @@ class RunningBuild (gobject.GObject):
153 del self.tasks_to_iter[(package, task)] 153 del self.tasks_to_iter[(package, task)]
154 del self.pids_to_task[pid] 154 del self.pids_to_task[pid]
155 155
156 elif event[0].startswith('bb.event.BuildCompleted'): 156 elif isinstance(event, bb.event.BuildCompleted):
157 failures = int (event[1]['_failures']) 157 failures = int (event._failures)
158 158
159 # Emit the appropriate signal depending on the number of failures 159 # Emit the appropriate signal depending on the number of failures
160 if (failures > 1): 160 if (failures > 1):
diff --git a/bitbake-dev/lib/bb/ui/depexp.py b/bitbake-dev/lib/bb/ui/depexp.py
index 0c559c7976..cfa5b6564e 100644
--- a/bitbake-dev/lib/bb/ui/depexp.py
+++ b/bitbake-dev/lib/bb/ui/depexp.py
@@ -229,12 +229,12 @@ def init(server, eventHandler):
229 229
230 if event is None: 230 if event is None:
231 continue 231 continue
232 if event[0].startswith('bb.event.ParseProgress'): 232 if isinstance(event, bb.event.ParseProgress):
233 x = event[1]['sofar'] 233 x = event.sofar
234 y = event[1]['total'] 234 y = event.total
235 if x == y: 235 if x == y:
236 print("\nParsing finished. %d cached, %d parsed, %d skipped, %d masked, %d errors." 236 print("\nParsing finished. %d cached, %d parsed, %d skipped, %d masked, %d errors."
237 % ( event[1]['cached'], event[1]['parsed'], event[1]['skipped'], event[1]['masked'], event[1]['errors'])) 237 % ( event.cached, event.parsed, event.skipped, event.masked, event.errors))
238 pbar.hide() 238 pbar.hide()
239 gtk.gdk.threads_enter() 239 gtk.gdk.threads_enter()
240 pbar.progress.set_fraction(float(x)/float(y)) 240 pbar.progress.set_fraction(float(x)/float(y))
@@ -242,17 +242,17 @@ def init(server, eventHandler):
242 gtk.gdk.threads_leave() 242 gtk.gdk.threads_leave()
243 continue 243 continue
244 244
245 if event[0] == "bb.event.DepTreeGenerated": 245 if isinstance(event, bb.event.DepTreeGenerated):
246 gtk.gdk.threads_enter() 246 gtk.gdk.threads_enter()
247 parse(event[1]['_depgraph'], dep.pkg_model, dep.depends_model) 247 parse(event._depgraph, dep.pkg_model, dep.depends_model)
248 gtk.gdk.threads_leave() 248 gtk.gdk.threads_leave()
249 249
250 if event[0] == 'bb.command.CookerCommandCompleted': 250 if isinstance(event, bb.command.CookerCommandCompleted):
251 continue 251 continue
252 if event[0] == 'bb.command.CookerCommandFailed': 252 if isinstance(event, bb.command.CookerCommandFailed):
253 print "Command execution failed: %s" % event[1]['error'] 253 print "Command execution failed: %s" % event.error
254 break 254 break
255 if event[0] == 'bb.cooker.CookerExit': 255 if isinstance(event, bb.cooker.CookerExit):
256 break 256 break
257 257
258 continue 258 continue
diff --git a/bitbake-dev/lib/bb/ui/knotty.py b/bitbake-dev/lib/bb/ui/knotty.py
index 8a2afeeb6d..6baed836a1 100644
--- a/bitbake-dev/lib/bb/ui/knotty.py
+++ b/bitbake-dev/lib/bb/ui/knotty.py
@@ -53,29 +53,29 @@ def init(server, eventHandler):
53 if event is None: 53 if event is None:
54 continue 54 continue
55 #print event 55 #print event
56 if event[0].startswith('bb.msg.MsgPlain'): 56 if isinstance(event, bb.msg.MsgPlain):
57 print event[1]['_message'] 57 print event._message
58 continue 58 continue
59 if event[0].startswith('bb.msg.MsgDebug'): 59 if isinstance(event, bb.msg.MsgDebug):
60 print 'DEBUG: ' + event[1]['_message'] 60 print 'DEBUG: ' + event._message
61 continue 61 continue
62 if event[0].startswith('bb.msg.MsgNote'): 62 if isinstance(event, bb.msg.MsgNote):
63 print 'NOTE: ' + event[1]['_message'] 63 print 'NOTE: ' + event._message
64 continue 64 continue
65 if event[0].startswith('bb.msg.MsgWarn'): 65 if isinstance(event, bb.msg.MsgWarn):
66 print 'WARNING: ' + event[1]['_message'] 66 print 'WARNING: ' + event._message
67 continue 67 continue
68 if event[0].startswith('bb.msg.MsgError'): 68 if isinstance(event, bb.msg.MsgError):
69 return_value = 1 69 return_value = 1
70 print 'ERROR: ' + event[1]['_message'] 70 print 'ERROR: ' + event._message
71 continue 71 continue
72 if event[0].startswith('bb.msg.MsgFatal'): 72 if isinstance(event, bb.msg.MsgFatal):
73 return_value = 1 73 return_value = 1
74 print 'FATAL: ' + event[1]['_message'] 74 print 'FATAL: ' + event._message
75 break 75 break
76 if event[0].startswith('bb.build.TaskFailed'): 76 if isinstance(event, bb.build.TaskFailed):
77 return_value = 1 77 return_value = 1
78 logfile = event[1]['logfile'] 78 logfile = event.logfile
79 if logfile: 79 if logfile:
80 print "ERROR: Logfile of failure stored in %s." % logfile 80 print "ERROR: Logfile of failure stored in %s." % logfile
81 if 1 or includelogs: 81 if 1 or includelogs:
@@ -97,12 +97,12 @@ def init(server, eventHandler):
97 if lines: 97 if lines:
98 for line in lines: 98 for line in lines:
99 print line 99 print line
100 if event[0].startswith('bb.build.Task'): 100 if isinstance(event, bb.build.TaskBase):
101 print "NOTE: %s" % event[1]['_message'] 101 print "NOTE: %s" % event._message
102 continue 102 continue
103 if event[0].startswith('bb.event.ParseProgress'): 103 if isinstance(event, bb.event.ParseProgress):
104 x = event[1]['sofar'] 104 x = event.sofar
105 y = event[1]['total'] 105 y = event.total
106 if os.isatty(sys.stdout.fileno()): 106 if os.isatty(sys.stdout.fileno()):
107 sys.stdout.write("\rNOTE: Handling BitBake files: %s (%04d/%04d) [%2d %%]" % ( parsespin.next(), x, y, x*100/y ) ) 107 sys.stdout.write("\rNOTE: Handling BitBake files: %s (%04d/%04d) [%2d %%]" % ( parsespin.next(), x, y, x*100/y ) )
108 sys.stdout.flush() 108 sys.stdout.flush()
@@ -115,35 +115,35 @@ def init(server, eventHandler):
115 sys.stdout.flush() 115 sys.stdout.flush()
116 if x == y: 116 if x == y:
117 print("\nParsing finished. %d cached, %d parsed, %d skipped, %d masked, %d errors." 117 print("\nParsing finished. %d cached, %d parsed, %d skipped, %d masked, %d errors."
118 % ( event[1]['cached'], event[1]['parsed'], event[1]['skipped'], event[1]['masked'], event[1]['errors'])) 118 % ( event.cached, event.parsed, event.skipped, event.masked, event.errors))
119 continue 119 continue
120 120
121 if event[0] == 'bb.command.CookerCommandCompleted': 121 if isinstance(event, bb.command.CookerCommandCompleted):
122 break 122 break
123 if event[0] == 'bb.command.CookerCommandSetExitCode': 123 if isinstance(event, bb.command.CookerCommandSetExitCode):
124 return_value = event[1]['exitcode'] 124 return_value = event.exitcode
125 continue 125 continue
126 if event[0] == 'bb.command.CookerCommandFailed': 126 if isinstance(event, bb.command.CookerCommandFailed):
127 return_value = 1 127 return_value = 1
128 print "Command execution failed: %s" % event[1]['error'] 128 print "Command execution failed: %s" % event.error
129 break 129 break
130 if event[0] == 'bb.cooker.CookerExit': 130 if isinstance(event, bb.cooker.CookerExit):
131 break 131 break
132 132
133 # ignore 133 # ignore
134 if event[0].startswith('bb.event.BuildStarted'): 134 if isinstance(event, bb.event.BuildStarted):
135 continue 135 continue
136 if event[0].startswith('bb.event.BuildCompleted'): 136 if isinstance(event, bb.event.BuildCompleted):
137 continue 137 continue
138 if event[0].startswith('bb.event.MultipleProviders'): 138 if isinstance(event, bb.event.MultipleProviders):
139 continue 139 continue
140 if event[0].startswith('bb.runqueue.runQueue'): 140 if isinstance(event, bb.runqueue.runQueueEvent):
141 continue 141 continue
142 if event[0].startswith('bb.event.StampUpdate'): 142 if isinstance(event, bb.event.StampUpdate):
143 continue 143 continue
144 if event[0].startswith('bb.event.ConfigParsed'): 144 if isinstance(event, bb.event.ConfigParsed):
145 continue 145 continue
146 if event[0].startswith('bb.event.RecipeParsed'): 146 if isinstance(event, bb.event.RecipeParsed):
147 continue 147 continue
148 print "Unknown Event: %s" % event 148 print "Unknown Event: %s" % event
149 149
diff --git a/bitbake-dev/lib/bb/ui/ncurses.py b/bitbake-dev/lib/bb/ui/ncurses.py
index 2cd7e8e6e7..14310dc124 100644
--- a/bitbake-dev/lib/bb/ui/ncurses.py
+++ b/bitbake-dev/lib/bb/ui/ncurses.py
@@ -246,29 +246,29 @@ class NCursesUI:
246 continue 246 continue
247 helper.eventHandler(event) 247 helper.eventHandler(event)
248 #mw.appendText("%s\n" % event[0]) 248 #mw.appendText("%s\n" % event[0])
249 if event[0].startswith('bb.build.Task'): 249 if isinstance(event, bb.build.Task):
250 mw.appendText("NOTE: %s\n" % event[1]['_message']) 250 mw.appendText("NOTE: %s\n" % event._message)
251 if event[0].startswith('bb.msg.MsgDebug'): 251 if isinstance(event, bb.msg.MsgDebug):
252 mw.appendText('DEBUG: ' + event[1]['_message'] + '\n') 252 mw.appendText('DEBUG: ' + event._message + '\n')
253 if event[0].startswith('bb.msg.MsgNote'): 253 if isinstance(event, bb.msg.MsgNote):
254 mw.appendText('NOTE: ' + event[1]['_message'] + '\n') 254 mw.appendText('NOTE: ' + event._message + '\n')
255 if event[0].startswith('bb.msg.MsgWarn'): 255 if isinstance(event, bb.msg.MsgWarn):
256 mw.appendText('WARNING: ' + event[1]['_message'] + '\n') 256 mw.appendText('WARNING: ' + event._message + '\n')
257 if event[0].startswith('bb.msg.MsgError'): 257 if isinstance(event, bb.msg.MsgError):
258 mw.appendText('ERROR: ' + event[1]['_message'] + '\n') 258 mw.appendText('ERROR: ' + event._message + '\n')
259 if event[0].startswith('bb.msg.MsgFatal'): 259 if isinstance(event, bb.msg.MsgFatal):
260 mw.appendText('FATAL: ' + event[1]['_message'] + '\n') 260 mw.appendText('FATAL: ' + event._message + '\n')
261 if event[0].startswith('bb.event.ParseProgress'): 261 if isinstance(event, bb.event.ParseProgress):
262 x = event[1]['sofar'] 262 x = event.sofar
263 y = event[1]['total'] 263 y = event.total
264 if x == y: 264 if x == y:
265 mw.setStatus("Idle") 265 mw.setStatus("Idle")
266 mw.appendText("Parsing finished. %d cached, %d parsed, %d skipped, %d masked." 266 mw.appendText("Parsing finished. %d cached, %d parsed, %d skipped, %d masked."
267 % ( event[1]['cached'], event[1]['parsed'], event[1]['skipped'], event[1]['masked'] )) 267 % ( event.cached, event.parsed, event.skipped, event.masked ))
268 else: 268 else:
269 mw.setStatus("Parsing: %s (%04d/%04d) [%2d %%]" % ( parsespin.next(), x, y, x*100/y ) ) 269 mw.setStatus("Parsing: %s (%04d/%04d) [%2d %%]" % ( parsespin.next(), x, y, x*100/y ) )
270# if event[0].startswith('bb.build.TaskFailed'): 270# if isinstance(event, bb.build.TaskFailed):
271# if event[1]['logfile']: 271# if event.logfile:
272# if data.getVar("BBINCLUDELOGS", d): 272# if data.getVar("BBINCLUDELOGS", d):
273# bb.msg.error(bb.msg.domain.Build, "log data follows (%s)" % logfile) 273# bb.msg.error(bb.msg.domain.Build, "log data follows (%s)" % logfile)
274# number_of_lines = data.getVar("BBINCLUDELOGS_LINES", d) 274# number_of_lines = data.getVar("BBINCLUDELOGS_LINES", d)
@@ -286,13 +286,13 @@ class NCursesUI:
286# else: 286# else:
287# bb.msg.error(bb.msg.domain.Build, "see log in %s" % logfile) 287# bb.msg.error(bb.msg.domain.Build, "see log in %s" % logfile)
288 288
289 if event[0] == 'bb.command.CookerCommandCompleted': 289 if isinstance(event, bb.command.CookerCommandCompleted):
290 exitflag = True 290 exitflag = True
291 if event[0] == 'bb.command.CookerCommandFailed': 291 if isinstance(event, bb.command.CookerCommandFailed):
292 mw.appendText("Command execution failed: %s" % event[1]['error']) 292 mw.appendText("Command execution failed: %s" % event.error)
293 time.sleep(2) 293 time.sleep(2)
294 exitflag = True 294 exitflag = True
295 if event[0] == 'bb.cooker.CookerExit': 295 if isinstance(event, bb.cooker.CookerExit):
296 exitflag = True 296 exitflag = True
297 297
298 if helper.needUpdate: 298 if helper.needUpdate:
diff --git a/bitbake-dev/lib/bb/ui/uievent.py b/bitbake-dev/lib/bb/ui/uievent.py
index 23fdd0f961..36302f4da7 100644
--- a/bitbake-dev/lib/bb/ui/uievent.py
+++ b/bitbake-dev/lib/bb/ui/uievent.py
@@ -24,7 +24,7 @@ server and queue them for the UI to process. This process must be used to avoid
24client/server deadlocks. 24client/server deadlocks.
25""" 25"""
26 26
27import socket, threading 27import socket, threading, pickle
28from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler 28from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
29 29
30class BBUIEventQueue: 30class BBUIEventQueue:
@@ -37,8 +37,8 @@ class BBUIEventQueue:
37 self.BBServer = BBServer 37 self.BBServer = BBServer
38 38
39 self.t = threading.Thread() 39 self.t = threading.Thread()
40 self.t.setDaemon(True) 40 self.t.setDaemon(True)
41 self.t.run = self.startCallbackHandler 41 self.t.run = self.startCallbackHandler
42 self.t.start() 42 self.t.start()
43 43
44 def getEvent(self): 44 def getEvent(self):
@@ -55,7 +55,6 @@ class BBUIEventQueue:
55 self.eventQueueNotify.clear() 55 self.eventQueueNotify.clear()
56 56
57 self.eventQueueLock.release() 57 self.eventQueueLock.release()
58
59 return item 58 return item
60 59
61 def waitEvent(self, delay): 60 def waitEvent(self, delay):
@@ -63,16 +62,15 @@ class BBUIEventQueue:
63 return self.getEvent() 62 return self.getEvent()
64 63
65 def queue_event(self, event): 64 def queue_event(self, event):
66
67 self.eventQueueLock.acquire() 65 self.eventQueueLock.acquire()
68 self.eventQueue.append(event) 66 self.eventQueue.append(pickle.loads(event))
69 self.eventQueueNotify.set() 67 self.eventQueueNotify.set()
70 self.eventQueueLock.release() 68 self.eventQueueLock.release()
71 69
72 def startCallbackHandler(self): 70 def startCallbackHandler(self):
73 71
74 server = UIXMLRPCServer() 72 server = UIXMLRPCServer()
75 self.host, self.port = server.socket.getsockname() 73 self.host, self.port = server.socket.getsockname()
76 74
77 server.register_function( self.system_quit, "event.quit" ) 75 server.register_function( self.system_quit, "event.quit" )
78 server.register_function( self.queue_event, "event.send" ) 76 server.register_function( self.queue_event, "event.send" )
@@ -85,7 +83,7 @@ class BBUIEventQueue:
85 server.handle_request() 83 server.handle_request()
86 server.server_close() 84 server.server_close()
87 85
88 def system_quit( self ): 86 def system_quit( self ):
89 """ 87 """
90 Shut down the callback thread 88 Shut down the callback thread
91 """ 89 """
@@ -97,11 +95,11 @@ class BBUIEventQueue:
97 95
98class UIXMLRPCServer (SimpleXMLRPCServer): 96class UIXMLRPCServer (SimpleXMLRPCServer):
99 97
100 def __init__( self, interface = ("localhost", 0) ): 98 def __init__( self, interface = ("localhost", 0) ):
101 self.quit = False 99 self.quit = False
102 SimpleXMLRPCServer.__init__( self, 100 SimpleXMLRPCServer.__init__( self,
103 interface, 101 interface,
104 requestHandler=SimpleXMLRPCRequestHandler, 102 requestHandler=SimpleXMLRPCRequestHandler,
105 logRequests=False, allow_none=True) 103 logRequests=False, allow_none=True)
106 104
107 def get_request(self): 105 def get_request(self):
@@ -123,5 +121,5 @@ class UIXMLRPCServer (SimpleXMLRPCServer):
123 if request is None: 121 if request is None:
124 return 122 return
125 SimpleXMLRPCServer.process_request(self, request, client_address) 123 SimpleXMLRPCServer.process_request(self, request, client_address)
126 124
127 125
diff --git a/bitbake-dev/lib/bb/ui/uihelper.py b/bitbake-dev/lib/bb/ui/uihelper.py
index 246844c9d2..151ffc5854 100644
--- a/bitbake-dev/lib/bb/ui/uihelper.py
+++ b/bitbake-dev/lib/bb/ui/uihelper.py
@@ -24,25 +24,25 @@ class BBUIHelper:
24 self.failed_tasks = {} 24 self.failed_tasks = {}
25 25
26 def eventHandler(self, event): 26 def eventHandler(self, event):
27 if event[0].startswith('bb.build.TaskStarted'): 27 if isinstance(event, bb.build.TaskStarted):
28 self.running_tasks["%s %s\n" % (event[1]['_package'], event[1]['_task'])] = "" 28 self.running_tasks["%s %s\n" % (event._package, event._task)] = ""
29 self.needUpdate = True 29 self.needUpdate = True
30 if event[0].startswith('bb.build.TaskSucceeded'): 30 if isinstance(event, bb.build.TaskSucceeded):
31 del self.running_tasks["%s %s\n" % (event[1]['_package'], event[1]['_task'])] 31 del self.running_tasks["%s %s\n" % (event._package, event._task)]
32 self.needUpdate = True 32 self.needUpdate = True
33 if event[0].startswith('bb.build.TaskFailed'): 33 if isinstance(event, bb.build.TaskFailed):
34 del self.running_tasks["%s %s\n" % (event[1]['_package'], event[1]['_task'])] 34 del self.running_tasks["%s %s\n" % (event._package, event._task)]
35 self.failed_tasks["%s %s\n" % (event[1]['_package'], event[1]['_task'])] = "" 35 self.failed_tasks["%s %s\n" % (event._package, event._task)] = ""
36 self.needUpdate = True 36 self.needUpdate = True
37 37
38 # Add runqueue event handling 38 # Add runqueue event handling
39 #if event[0].startswith('bb.runqueue.runQueueTaskCompleted'): 39 #if isinstance(event, bb.runqueue.runQueueTaskCompleted):
40 # a = 1 40 # a = 1
41 #if event[0].startswith('bb.runqueue.runQueueTaskStarted'): 41 #if isinstance(event, bb.runqueue.runQueueTaskStarted):
42 # a = 1 42 # a = 1
43 #if event[0].startswith('bb.runqueue.runQueueTaskFailed'): 43 #if isinstance(event, bb.runqueue.runQueueTaskFailed):
44 # a = 1 44 # a = 1
45 #if event[0].startswith('bb.runqueue.runQueueExitWait'): 45 #if isinstance(event, bb.runqueue.runQueueExitWait):
46 # a = 1 46 # a = 1
47 47
48 def getTasks(self): 48 def getTasks(self):