1
0
mirror of https://git.yoctoproject.org/poky synced 2026-05-30 12:29:55 +00:00

bitbake-dev: Sync with upstream

Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
This commit is contained in:
Richard Purdie
2010-01-19 14:48:19 +00:00
parent cefe87fc3c
commit 22a271aaa9
24 changed files with 503 additions and 374 deletions
+12 -28
View File
@@ -26,9 +26,8 @@ import sys, os, getopt, re, time, optparse, xmlrpclib
sys.path.insert(0,os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib')) sys.path.insert(0,os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib'))
import bb import bb
from bb import cooker from bb import cooker
from bb import daemonize
from bb import ui from bb import ui
from bb.ui import uievent
__version__ = "1.9.0" __version__ = "1.9.0"
@@ -144,11 +143,14 @@ Default BBFILES are the .bb files in the current directory.""" )
configuration.pkgs_to_build = [] configuration.pkgs_to_build = []
configuration.pkgs_to_build.extend(args[1:]) configuration.pkgs_to_build.extend(args[1:])
#server = bb.server.xmlrpc
server = bb.server.none
# Save a logfile for cooker into the current working directory. When the # Save a logfile for cooker into the current working directory. When the
# server is daemonized this logfile will be truncated. # server is daemonized this logfile will be truncated.
cooker_logfile = os.path.join (os.getcwd(), "cooker.log") cooker_logfile = os.path.join (os.getcwd(), "cooker.log")
cooker = bb.cooker.BBCooker(configuration, bb.server.xmlrpc) cooker = bb.cooker.BBCooker(configuration, server)
# Clear away any spurious environment variables. But don't wipe the # Clear away any spurious environment variables. But don't wipe the
# environment totally. This is necessary to ensure the correct operation # environment totally. This is necessary to ensure the correct operation
@@ -157,19 +159,15 @@ Default BBFILES are the .bb files in the current directory.""" )
cooker.parseCommandLine() cooker.parseCommandLine()
serverinfo = server.BitbakeServerInfo(cooker.server)
server.BitBakeServerFork(serverinfo, cooker.serve, cooker_logfile)
host = cooker.server.host
port = cooker.server.port
daemonize.createDaemon(cooker.serve, cooker_logfile)
del cooker del cooker
sys.excepthook = print_exception
# Setup a connection to the server (cooker) # Setup a connection to the server (cooker)
server = xmlrpclib.Server("http://%s:%s" % (host, port), allow_none=True) serverConnection = server.BitBakeServerConnection(serverinfo)
# Setup an event receiving queue
eventHandler = uievent.BBUIEventQueue(server)
# Launch the UI # Launch the UI
if configuration.ui: if configuration.ui:
@@ -182,30 +180,16 @@ Default BBFILES are the .bb files in the current directory.""" )
# suggest a fixed set this allows you to have flexibility in which # suggest a fixed set this allows you to have flexibility in which
# ones are available. # ones are available.
exec "from bb.ui import " + ui exec "from bb.ui import " + ui
exec "return_value = " + ui + ".init(server, eventHandler)" exec "return_value = " + ui + ".init(serverConnection.connection, serverConnection.events)"
except ImportError: except ImportError:
print "FATAL: Invalid user interface '%s' specified. " % ui print "FATAL: Invalid user interface '%s' specified. " % ui
print "Valid interfaces are 'ncurses', 'depexp' or the default, 'knotty'." print "Valid interfaces are 'ncurses', 'depexp' or the default, 'knotty'."
except Exception, e: except Exception, e:
print "FATAL: Unable to start to '%s' UI: %s." % (configuration.ui, e.message) print "FATAL: Unable to start to '%s' UI: %s." % (configuration.ui, e.message)
finally: finally:
# Don't wait for server indefinitely serverConnection.terminate()
import socket
socket.setdefaulttimeout(2)
try:
eventHandler.system_quit()
except:
pass
try:
server.terminateServer()
except:
pass
return return_value return return_value
if __name__ == "__main__": if __name__ == "__main__":
print """WARNING, WARNING, WARNING
This is a Bitbake from the Unstable/Development 1.9 Branch. This software is a work in progress and should only be used by Bitbake developers/testers"""
ret = main() ret = main()
sys.exit(ret) sys.exit(ret)
+4 -4
View File
@@ -55,7 +55,7 @@ class TaskBase(event.Event):
def __init__(self, t, d ): def __init__(self, t, d ):
self._task = t self._task = t
self._package = bb.data.getVar("PF", d, 1) self._package = bb.data.getVar("PF", d, 1)
event.Event.__init__(self, d) event.Event.__init__(self)
self._message = "package %s: task %s: %s" % (bb.data.getVar("PF", d, 1), t, bb.event.getName(self)[4:]) self._message = "package %s: task %s: %s" % (bb.data.getVar("PF", d, 1), t, bb.event.getName(self)[4:])
def getTask(self): def getTask(self):
@@ -286,9 +286,9 @@ def exec_task(task, d):
data.setVar('OVERRIDES', 'task-%s:%s' % (task[3:], old_overrides), localdata) data.setVar('OVERRIDES', 'task-%s:%s' % (task[3:], old_overrides), localdata)
data.update_data(localdata) data.update_data(localdata)
data.expandKeys(localdata) data.expandKeys(localdata)
event.fire(TaskStarted(task, localdata)) event.fire(TaskStarted(task, localdata), localdata)
exec_func(task, localdata) exec_func(task, localdata)
event.fire(TaskSucceeded(task, localdata)) event.fire(TaskSucceeded(task, localdata), localdata)
except FuncFailed, message: except FuncFailed, message:
# Try to extract the optional logfile # Try to extract the optional logfile
try: try:
@@ -298,7 +298,7 @@ def exec_task(task, d):
msg = message msg = message
bb.msg.note(1, bb.msg.domain.Build, "Task failed: %s" % message ) bb.msg.note(1, bb.msg.domain.Build, "Task failed: %s" % message )
failedevent = TaskFailed(msg, logfile, task, d) failedevent = TaskFailed(msg, logfile, task, d)
event.fire(failedevent) event.fire(failedevent, d)
raise EventException("Function failed in task: %s" % message, failedevent) raise EventException("Function failed in task: %s" % message, failedevent)
# make stamp, or cause event and raise exception # make stamp, or cause event and raise exception
+8 -8
View File
@@ -94,9 +94,9 @@ class Command:
def finishAsyncCommand(self, error = None): def finishAsyncCommand(self, error = None):
if error: if error:
bb.event.fire(bb.command.CookerCommandFailed(self.cooker.configuration.event_data, error)) bb.event.fire(bb.command.CookerCommandFailed(error), self.cooker.configuration.event_data)
else: else:
bb.event.fire(bb.command.CookerCommandCompleted(self.cooker.configuration.event_data)) bb.event.fire(bb.command.CookerCommandCompleted(), self.cooker.configuration.event_data)
self.currentAsyncCommand = None self.currentAsyncCommand = None
@@ -247,24 +247,24 @@ class CookerCommandCompleted(bb.event.Event):
""" """
Cooker command completed Cooker command completed
""" """
def __init__(self, data): def __init__(self):
bb.event.Event.__init__(self, data) bb.event.Event.__init__(self)
class CookerCommandFailed(bb.event.Event): class CookerCommandFailed(bb.event.Event):
""" """
Cooker command completed Cooker command completed
""" """
def __init__(self, data, error): def __init__(self, error):
bb.event.Event.__init__(self, data) bb.event.Event.__init__(self)
self.error = error self.error = error
class CookerCommandSetExitCode(bb.event.Event): class CookerCommandSetExitCode(bb.event.Event):
""" """
Set the exit code for a cooker command Set the exit code for a cooker command
""" """
def __init__(self, data, exitcode): def __init__(self, exitcode):
bb.event.Event.__init__(self, data) bb.event.Event.__init__(self)
self.exitcode = int(exitcode) self.exitcode = int(exitcode)
+12 -14
View File
@@ -245,7 +245,7 @@ class BBCooker:
def compareRevisions(self): def compareRevisions(self):
ret = bb.fetch.fetcher_compare_revisons(self.configuration.data) ret = bb.fetch.fetcher_compare_revisons(self.configuration.data)
bb.event.fire(bb.command.CookerCommandSetExitCode(self.configuration.event_data, ret)) bb.event.fire(bb.command.CookerCommandSetExitCode(ret), self.configuration.event_data)
def showEnvironment(self, buildfile = None, pkgs_to_build = []): def showEnvironment(self, buildfile = None, pkgs_to_build = []):
""" """
@@ -403,7 +403,7 @@ class BBCooker:
Generate an event with the result Generate an event with the result
""" """
depgraph = self.generateDepTreeData(pkgs_to_build, task) depgraph = self.generateDepTreeData(pkgs_to_build, task)
bb.event.fire(bb.event.DepTreeGenerated(self.configuration.data, depgraph)) bb.event.fire(bb.event.DepTreeGenerated(depgraph), self.configuration.data)
def generateDotGraphFiles(self, pkgs_to_build, task): def generateDotGraphFiles(self, pkgs_to_build, task):
""" """
@@ -544,7 +544,7 @@ class BBCooker:
bb.fetch.fetcher_init(self.configuration.data) bb.fetch.fetcher_init(self.configuration.data)
bb.event.fire(bb.event.ConfigParsed(self.configuration.data)) bb.event.fire(bb.event.ConfigParsed(), self.configuration.data)
except IOError, e: except IOError, e:
bb.msg.fatal(bb.msg.domain.Parsing, "Error when parsing %s: %s" % (afile, str(e))) bb.msg.fatal(bb.msg.domain.Parsing, "Error when parsing %s: %s" % (afile, str(e)))
@@ -657,7 +657,7 @@ class BBCooker:
taskdata.add_provider(self.configuration.data, self.status, item) taskdata.add_provider(self.configuration.data, self.status, item)
buildname = bb.data.getVar("BUILDNAME", self.configuration.data) buildname = bb.data.getVar("BUILDNAME", self.configuration.data)
bb.event.fire(bb.event.BuildStarted(buildname, [item], self.configuration.event_data)) bb.event.fire(bb.event.BuildStarted(buildname, [item]), self.configuration.event_data)
# Execute the runqueue # Execute the runqueue
runlist = [[item, "do_%s" % task]] runlist = [[item, "do_%s" % task]]
@@ -680,7 +680,7 @@ class BBCooker:
retval = False retval = False
if not retval: if not retval:
self.command.finishAsyncCommand() self.command.finishAsyncCommand()
bb.event.fire(bb.event.BuildCompleted(buildname, item, self.configuration.event_data, failures)) bb.event.fire(bb.event.BuildCompleted(buildname, item, failures), self.configuration.event_data)
return False return False
return 0.5 return 0.5
@@ -716,14 +716,14 @@ class BBCooker:
retval = False retval = False
if not retval: if not retval:
self.command.finishAsyncCommand() self.command.finishAsyncCommand()
bb.event.fire(bb.event.BuildCompleted(buildname, targets, self.configuration.event_data, failures)) bb.event.fire(bb.event.BuildCompleted(buildname, targets, failures), self.configuration.event_data)
return None return None
return 0.5 return 0.5
self.buildSetVars() self.buildSetVars()
buildname = bb.data.getVar("BUILDNAME", self.configuration.data) buildname = bb.data.getVar("BUILDNAME", self.configuration.data)
bb.event.fire(bb.event.BuildStarted(buildname, targets, self.configuration.event_data)) bb.event.fire(bb.event.BuildStarted(buildname, targets), self.configuration.event_data)
localdata = data.createCopy(self.configuration.data) localdata = data.createCopy(self.configuration.data)
bb.data.update_data(localdata) bb.data.update_data(localdata)
@@ -786,7 +786,7 @@ class BBCooker:
self.cookerState = cookerParsed self.cookerState = cookerParsed
return None return None
return 0.00001 return True
def checkPackages(self, pkgs_to_build): def checkPackages(self, pkgs_to_build):
@@ -904,15 +904,15 @@ class BBCooker:
else: else:
self.server.serve_forever() self.server.serve_forever()
bb.event.fire(CookerExit(self.configuration.event_data)) bb.event.fire(CookerExit(), self.configuration.event_data)
class CookerExit(bb.event.Event): class CookerExit(bb.event.Event):
""" """
Notify clients of the Cooker shutdown Notify clients of the Cooker shutdown
""" """
def __init__(self, d): def __init__(self):
bb.event.Event.__init__(self, d) bb.event.Event.__init__(self)
class CookerParser: class CookerParser:
def __init__(self, cooker, filelist, masked): def __init__(self, cooker, filelist, masked):
@@ -932,8 +932,6 @@ class CookerParser:
self.pointer = 0 self.pointer = 0
def parse_next(self): def parse_next(self):
print "Pointer %d" % self.pointer
if self.pointer < len(self.filelist): if self.pointer < len(self.filelist):
f = self.filelist[self.pointer] f = self.filelist[self.pointer]
cooker = self.cooker cooker = self.cooker
@@ -964,7 +962,7 @@ class CookerParser:
cooker.bb_cache.remove(f) cooker.bb_cache.remove(f)
raise raise
finally: finally:
bb.event.fire(bb.event.ParseProgress(cooker.configuration.event_data, self.cached, self.parsed, self.skipped, self.masked, self.error, self.total)) bb.event.fire(bb.event.ParseProgress(self.cached, self.parsed, self.skipped, self.masked, self.error, self.total), cooker.configuration.event_data)
self.pointer += 1 self.pointer += 1
+40 -68
View File
@@ -24,27 +24,19 @@ BitBake build tools.
import os, re import os, re
import bb.utils import bb.utils
import pickle
# This is the pid for which we should generate the event. This is set when # This is the pid for which we should generate the event. This is set when
# the runqueue forks off. # the runqueue forks off.
worker_pid = 0 worker_pid = 0
worker_pipe = None
class Event: class Event:
"""Base class for events""" """Base class for events"""
type = "Event"
def __init__(self, d): def __init__(self):
self._data = d
self.pid = worker_pid self.pid = worker_pid
def getData(self):
return self._data
def setData(self, data):
self._data = data
data = property(getData, setData, None, "data property")
NotHandled = 0 NotHandled = 0
Handled = 1 Handled = 1
@@ -56,33 +48,48 @@ _handlers = {}
_ui_handlers = {} _ui_handlers = {}
_ui_handler_seq = 0 _ui_handler_seq = 0
def fire(event): def fire(event, d):
"""Fire off an Event""" """Fire off an Event"""
if worker_pid != 0:
worker_fire(event, d)
return
for handler in _handlers: for handler in _handlers:
h = _handlers[handler] h = _handlers[handler]
event.data = d
if type(h).__name__ == "code": if type(h).__name__ == "code":
exec(h) exec(h)
tmpHandler(event) tmpHandler(event)
else: else:
h(event) h(event)
del event.data
# Remove the event data elements for UI handlers - too much data otherwise
# They can request data if they need it
event.data = None
event._data = None
errors = [] errors = []
for h in _ui_handlers: for h in _ui_handlers:
#print "Sending event %s" % event #print "Sending event %s" % event
classid = "%s.%s" % (event.__class__.__module__, event.__class__.__name__)
try: try:
_ui_handlers[h].event.send((classid, event)) # We use pickle here since it better handles object instances
# which xmlrpc's marshaller does not. Events *must* be serializable
# by pickle.
_ui_handlers[h].event.send((pickle.dumps(event)))
except: except:
errors.append(h) errors.append(h)
for h in errors: for h in errors:
del _ui_handlers[h] del _ui_handlers[h]
def worker_fire(event, d):
data = "<event>" + pickle.dumps(event) + "</event>"
if os.write(worker_pipe, data) != len (data):
print "Error sending event to server (short write)"
def fire_from_worker(event, d):
if not event.startswith("<event>") or not event.endswith("</event>"):
print "Error, not an event"
return
event = pickle.loads(event[7:-8])
bb.event.fire(event, d)
def register(name, handler): def register(name, handler):
"""Register an Event handler""" """Register an Event handler"""
@@ -128,17 +135,17 @@ class ConfigParsed(Event):
class RecipeParsed(Event): class RecipeParsed(Event):
""" Recipe Parsing Complete """ """ Recipe Parsing Complete """
def __init__(self, fn, d): def __init__(self, fn):
self.fn = fn self.fn = fn
Event.__init__(self, d) Event.__init__(self)
class StampUpdate(Event): class StampUpdate(Event):
"""Trigger for any adjustment of the stamp files to happen""" """Trigger for any adjustment of the stamp files to happen"""
def __init__(self, targets, stampfns, d): def __init__(self, targets, stampfns):
self._targets = targets self._targets = targets
self._stampfns = stampfns self._stampfns = stampfns
Event.__init__(self, d) Event.__init__(self)
def getStampPrefix(self): def getStampPrefix(self):
return self._stampfns return self._stampfns
@@ -149,30 +156,13 @@ class StampUpdate(Event):
stampPrefix = property(getStampPrefix) stampPrefix = property(getStampPrefix)
targets = property(getTargets) targets = property(getTargets)
class PkgBase(Event):
"""Base class for package events"""
def __init__(self, t, d):
self._pkg = t
Event.__init__(self, d)
self._message = "package %s: %s" % (bb.data.getVar("P", d, 1), getName(self)[3:])
def getPkg(self):
return self._pkg
def setPkg(self, pkg):
self._pkg = pkg
pkg = property(getPkg, setPkg, None, "pkg property")
class BuildBase(Event): class BuildBase(Event):
"""Base class for bbmake run events""" """Base class for bbmake run events"""
def __init__(self, n, p, c, failures = 0): def __init__(self, n, p, failures = 0):
self._name = n self._name = n
self._pkgs = p self._pkgs = p
Event.__init__(self, c) Event.__init__(self)
self._failures = failures self._failures = failures
def getPkgs(self): def getPkgs(self):
@@ -204,20 +194,7 @@ class BuildBase(Event):
cfg = property(getCfg, setCfg, None, "cfg property") cfg = property(getCfg, setCfg, None, "cfg property")
class DepBase(PkgBase):
"""Base class for dependency events"""
def __init__(self, t, data, d):
self._dep = d
PkgBase.__init__(self, t, data)
def getDep(self):
return self._dep
def setDep(self, dep):
self._dep = dep
dep = property(getDep, setDep, None, "dep property")
class BuildStarted(BuildBase): class BuildStarted(BuildBase):
@@ -228,18 +205,13 @@ class BuildCompleted(BuildBase):
"""bbmake build run completed""" """bbmake build run completed"""
class UnsatisfiedDep(DepBase):
"""Unsatisfied Dependency"""
class RecursiveDep(DepBase):
"""Recursive Dependency"""
class NoProvider(Event): class NoProvider(Event):
"""No Provider for an Event""" """No Provider for an Event"""
def __init__(self, item, data, runtime=False): def __init__(self, item, runtime=False):
Event.__init__(self, data) Event.__init__(self)
self._item = item self._item = item
self._runtime = runtime self._runtime = runtime
@@ -252,8 +224,8 @@ class NoProvider(Event):
class MultipleProviders(Event): class MultipleProviders(Event):
"""Multiple Providers""" """Multiple Providers"""
def __init__(self, item, candidates, data, runtime = False): def __init__(self, item, candidates, runtime = False):
Event.__init__(self, data) Event.__init__(self)
self._item = item self._item = item
self._candidates = candidates self._candidates = candidates
self._is_runtime = runtime self._is_runtime = runtime
@@ -281,8 +253,8 @@ class ParseProgress(Event):
Parsing Progress Event Parsing Progress Event
""" """
def __init__(self, d, cached, parsed, skipped, masked, errors, total): def __init__(self, cached, parsed, skipped, masked, errors, total):
Event.__init__(self, d) Event.__init__(self)
self.cached = cached self.cached = cached
self.parsed = parsed self.parsed = parsed
self.skipped = skipped self.skipped = skipped
@@ -296,7 +268,7 @@ class DepTreeGenerated(Event):
Event when a dependency tree has been generated Event when a dependency tree has been generated
""" """
def __init__(self, d, depgraph): def __init__(self, depgraph):
Event.__init__(self, d) Event.__init__(self)
self._depgraph = depgraph self._depgraph = depgraph
+1 -1
View File
@@ -41,7 +41,7 @@ class Cvs(Fetch):
""" """
Check to see if a given url can be fetched with cvs. Check to see if a given url can be fetched with cvs.
""" """
return ud.type in ['cvs', 'pserver'] return ud.type in ['cvs']
def localpath(self, url, ud, d): def localpath(self, url, ud, d):
if not "module" in ud.parm: if not "module" in ud.parm:
+60 -26
View File
@@ -51,6 +51,10 @@ class Git(Fetch):
ud.branch = ud.parm.get("branch", "master") ud.branch = ud.parm.get("branch", "master")
gitsrcname = '%s%s' % (ud.host, ud.path.replace('/', '.'))
ud.mirrortarball = 'git_%s.tar.gz' % (gitsrcname)
ud.clonedir = os.path.join(data.expand('${GITDIR}', d), gitsrcname)
tag = Fetch.srcrev_internal_helper(ud, d) tag = Fetch.srcrev_internal_helper(ud, d)
if tag is True: if tag is True:
ud.tag = self.latest_revision(url, ud, d) ud.tag = self.latest_revision(url, ud, d)
@@ -60,7 +64,18 @@ class Git(Fetch):
if not ud.tag or ud.tag == "master": if not ud.tag or ud.tag == "master":
ud.tag = self.latest_revision(url, ud, d) ud.tag = self.latest_revision(url, ud, d)
ud.localfile = data.expand('git_%s%s_%s.tar.gz' % (ud.host, ud.path.replace('/', '.'), ud.tag), d) subdir = ud.parm.get("subpath", "")
if subdir != "":
if subdir.endswith("/"):
subdir = subdir[:-1]
subdirpath = os.path.join(ud.path, subdir);
else:
subdirpath = ud.path;
if 'fullclone' in ud.parm:
ud.localfile = ud.mirrortarball
else:
ud.localfile = data.expand('git_%s%s_%s.tar.gz' % (ud.host, subdirpath.replace('/', '.'), ud.tag), d)
return os.path.join(data.getVar("DL_DIR", d, True), ud.localfile) return os.path.join(data.getVar("DL_DIR", d, True), ud.localfile)
@@ -76,24 +91,20 @@ class Git(Fetch):
else: else:
username = "" username = ""
gitsrcname = '%s%s' % (ud.host, ud.path.replace('/', '.')) repofile = os.path.join(data.getVar("DL_DIR", d, 1), ud.mirrortarball)
repofilename = 'git_%s.tar.gz' % (gitsrcname)
repofile = os.path.join(data.getVar("DL_DIR", d, 1), repofilename)
repodir = os.path.join(data.expand('${GITDIR}', d), gitsrcname)
coname = '%s' % (ud.tag) coname = '%s' % (ud.tag)
codir = os.path.join(repodir, coname) codir = os.path.join(ud.clonedir, coname)
if not os.path.exists(repodir): if not os.path.exists(ud.clonedir):
if Fetch.try_mirror(d, repofilename): if Fetch.try_mirror(d, ud.mirrortarball):
bb.mkdirhier(repodir) bb.mkdirhier(ud.clonedir)
os.chdir(repodir) os.chdir(ud.clonedir)
runfetchcmd("tar -xzf %s" % (repofile), d) runfetchcmd("tar -xzf %s" % (repofile), d)
else: else:
runfetchcmd("git clone -n %s://%s%s%s %s" % (ud.proto, username, ud.host, ud.path, repodir), d) runfetchcmd("git clone -n %s://%s%s%s %s" % (ud.proto, username, ud.host, ud.path, ud.clonedir), d)
os.chdir(repodir) os.chdir(ud.clonedir)
# Remove all but the .git directory # Remove all but the .git directory
if not self._contains_ref(ud.tag, d): if not self._contains_ref(ud.tag, d):
runfetchcmd("rm * -Rf", d) runfetchcmd("rm * -Rf", d)
@@ -102,25 +113,45 @@ class Git(Fetch):
runfetchcmd("git prune-packed", d) runfetchcmd("git prune-packed", d)
runfetchcmd("git pack-redundant --all | xargs -r rm", d) runfetchcmd("git pack-redundant --all | xargs -r rm", d)
os.chdir(repodir) os.chdir(ud.clonedir)
mirror_tarballs = data.getVar("BB_GENERATE_MIRROR_TARBALLS", d, True) mirror_tarballs = data.getVar("BB_GENERATE_MIRROR_TARBALLS", d, True)
if mirror_tarballs != "0": if mirror_tarballs != "0" or 'fullclone' in ud.parm:
bb.msg.note(1, bb.msg.domain.Fetcher, "Creating tarball of git repository") bb.msg.note(1, bb.msg.domain.Fetcher, "Creating tarball of git repository")
runfetchcmd("tar -czf %s %s" % (repofile, os.path.join(".", ".git", "*") ), d) runfetchcmd("tar -czf %s %s" % (repofile, os.path.join(".", ".git", "*") ), d)
if 'fullclone' in ud.parm:
return
if os.path.exists(codir): if os.path.exists(codir):
bb.utils.prunedir(codir) bb.utils.prunedir(codir)
subdir = ud.parm.get("subpath", "")
if subdir != "":
if subdir.endswith("/"):
subdirbase = os.path.basename(subdir[:-1])
else:
subdirbase = os.path.basename(subdir)
else:
subdirbase = ""
if subdir != "":
readpathspec = ":%s" % (subdir)
codir = os.path.join(codir, "git")
coprefix = os.path.join(codir, subdirbase, "")
else:
readpathspec = ""
coprefix = os.path.join(codir, "git", "")
bb.mkdirhier(codir) bb.mkdirhier(codir)
os.chdir(repodir) os.chdir(ud.clonedir)
runfetchcmd("git read-tree %s" % (ud.tag), d) runfetchcmd("git read-tree %s%s" % (ud.tag, readpathspec), d)
runfetchcmd("git checkout-index -q -f --prefix=%s -a" % (os.path.join(codir, "git", "")), d) runfetchcmd("git checkout-index -q -f --prefix=%s -a" % (coprefix), d)
os.chdir(codir) os.chdir(codir)
bb.msg.note(1, bb.msg.domain.Fetcher, "Creating tarball of git checkout") bb.msg.note(1, bb.msg.domain.Fetcher, "Creating tarball of git checkout")
runfetchcmd("tar -czf %s %s" % (ud.localpath, os.path.join(".", "*") ), d) runfetchcmd("tar -czf %s %s" % (ud.localpath, os.path.join(".", "*") ), d)
os.chdir(repodir) os.chdir(ud.clonedir)
bb.utils.prunedir(codir) bb.utils.prunedir(codir)
def suppports_srcrev(self): def suppports_srcrev(self):
@@ -145,7 +176,10 @@ class Git(Fetch):
else: else:
username = "" username = ""
output = runfetchcmd("git ls-remote %s://%s%s%s %s" % (ud.proto, username, ud.host, ud.path, ud.branch), d, True) cmd = "git ls-remote %s://%s%s%s %s" % (ud.proto, username, ud.host, ud.path, ud.branch)
output = runfetchcmd(cmd, d, True)
if not output:
raise bb.fetch.FetchError("Fetch command %s gave empty output\n" % (cmd))
return output.split()[0] return output.split()[0]
def _build_revision(self, url, ud, d): def _build_revision(self, url, ud, d):
@@ -156,20 +190,20 @@ class Git(Fetch):
Return a suitable buildindex for the revision specified. This is done by counting revisions Return a suitable buildindex for the revision specified. This is done by counting revisions
using "git rev-list" which may or may not work in different circumstances. using "git rev-list" which may or may not work in different circumstances.
""" """
gitsrcname = '%s%s' % (ud.host, ud.path.replace('/', '.'))
repodir = os.path.join(data.expand('${GITDIR}', d), gitsrcname)
cwd = os.getcwd() cwd = os.getcwd()
# Check if we have the rev already # Check if we have the rev already
if not os.path.exists(repodir):
if not os.path.exists(ud.clonedir):
print "no repo"
self.go(None, ud, d) self.go(None, ud, d)
if not os.path.exists(repodir): if not os.path.exists(ud.clonedir):
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)) 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))
return None return None
os.chdir(repodir) os.chdir(ud.clonedir)
if not self._contains_ref(rev, d): if not self._contains_ref(rev, d):
self.go(None, ud, d) self.go(None, ud, d)
+2 -2
View File
@@ -33,9 +33,9 @@ from bb.fetch import Fetch
class Local(Fetch): class Local(Fetch):
def supports(self, url, urldata, d): def supports(self, url, urldata, d):
""" """
Check to see if a given url can be fetched with cvs. Check to see if a given url represents a local fetch.
""" """
return urldata.type in ['file','patch'] return urldata.type in ['file']
def localpath(self, url, urldata, d): def localpath(self, url, urldata, d):
""" """
+1 -1
View File
@@ -36,7 +36,7 @@ class Svk(Fetch):
"""Class to fetch a module or modules from svk repositories""" """Class to fetch a module or modules from svk repositories"""
def supports(self, url, ud, d): def supports(self, url, ud, d):
""" """
Check to see if a given url can be fetched with cvs. Check to see if a given url can be fetched with svk.
""" """
return ud.type in ['svk'] return ud.type in ['svk']
+1 -1
View File
@@ -36,7 +36,7 @@ class Wget(Fetch):
"""Class to fetch urls via 'wget'""" """Class to fetch urls via 'wget'"""
def supports(self, url, ud, d): def supports(self, url, ud, d):
""" """
Check to see if a given url can be fetched with cvs. Check to see if a given url can be fetched with wget.
""" """
return ud.type in ['http','https','ftp'] return ud.type in ['http','https','ftp']
+8 -8
View File
@@ -47,9 +47,9 @@ domain = bb.utils.Enum(
class MsgBase(bb.event.Event): class MsgBase(bb.event.Event):
"""Base class for messages""" """Base class for messages"""
def __init__(self, msg, d ): def __init__(self, msg):
self._message = msg self._message = msg
event.Event.__init__(self, d) event.Event.__init__(self)
class MsgDebug(MsgBase): class MsgDebug(MsgBase):
"""Debug Message""" """Debug Message"""
@@ -100,26 +100,26 @@ def debug(level, domain, msg, fn = None):
if not domain: if not domain:
domain = 'default' domain = 'default'
if debug_level[domain] >= level: if debug_level[domain] >= level:
bb.event.fire(MsgDebug(msg, None)) bb.event.fire(MsgDebug(msg), None)
def note(level, domain, msg, fn = None): def note(level, domain, msg, fn = None):
if not domain: if not domain:
domain = 'default' domain = 'default'
if level == 1 or verbose or debug_level[domain] >= 1: if level == 1 or verbose or debug_level[domain] >= 1:
bb.event.fire(MsgNote(msg, None)) bb.event.fire(MsgNote(msg), None)
def warn(domain, msg, fn = None): def warn(domain, msg, fn = None):
bb.event.fire(MsgWarn(msg, None)) bb.event.fire(MsgWarn(msg), None)
def error(domain, msg, fn = None): def error(domain, msg, fn = None):
bb.event.fire(MsgError(msg, None)) bb.event.fire(MsgError(msg), None)
print 'ERROR: ' + msg print 'ERROR: ' + msg
def fatal(domain, msg, fn = None): def fatal(domain, msg, fn = None):
bb.event.fire(MsgFatal(msg, None)) bb.event.fire(MsgFatal(msg), None)
print 'FATAL: ' + msg print 'FATAL: ' + msg
sys.exit(1) sys.exit(1)
def plain(msg, fn = None): def plain(msg, fn = None):
bb.event.fire(MsgPlain(msg, None)) bb.event.fire(MsgPlain(msg), None)
@@ -114,7 +114,7 @@ def finalise(fn, d):
tasklist = data.getVar('__BBTASKS', d) or [] tasklist = data.getVar('__BBTASKS', d) or []
bb.build.add_tasks(tasklist, d) bb.build.add_tasks(tasklist, d)
bb.event.fire(bb.event.RecipeParsed(fn, d)) bb.event.fire(bb.event.RecipeParsed(fn), d)
def handle(fn, d, include = 0): def handle(fn, d, include = 0):
@@ -34,10 +34,17 @@ __require_regexp__ = re.compile( r"require\s+(.+)" )
__export_regexp__ = re.compile( r"export\s+(.+)" ) __export_regexp__ = re.compile( r"export\s+(.+)" )
def init(data): def init(data):
if not bb.data.getVar('TOPDIR', data): topdir = bb.data.getVar('TOPDIR', data)
bb.data.setVar('TOPDIR', os.getcwd(), data) if not topdir:
topdir = os.getcwd()
bb.data.setVar('TOPDIR', topdir, data)
if not bb.data.getVar('BBPATH', data): if not bb.data.getVar('BBPATH', data):
bb.data.setVar('BBPATH', os.path.join(sys.prefix, 'share', 'bitbake'), data) from pkg_resources import Requirement, resource_filename
bitbake = Requirement.parse("bitbake")
datadir = resource_filename(bitbake, "../share/bitbake")
basedir = resource_filename(bitbake, "..")
bb.data.setVar('BBPATH', '%s:%s:%s' % (topdir, datadir, basedir), data)
def supports(fn, d): def supports(fn, d):
return localpath(fn, d)[-5:] == ".conf" return localpath(fn, d)[-5:] == ".conf"
+73 -25
View File
@@ -857,6 +857,7 @@ class RunQueue:
self.runq_running = [] self.runq_running = []
self.runq_complete = [] self.runq_complete = []
self.build_pids = {} self.build_pids = {}
self.build_pipes = {}
self.failed_fnids = [] self.failed_fnids = []
# Mark initial buildable tasks # Mark initial buildable tasks
@@ -870,7 +871,7 @@ class RunQueue:
self.state = runQueueRunning self.state = runQueueRunning
event.fire(bb.event.StampUpdate(self.target_pairs, self.dataCache.stamp, self.cfgData)) event.fire(bb.event.StampUpdate(self.target_pairs, self.dataCache.stamp), self.cfgData)
def task_complete(self, task): def task_complete(self, task):
""" """
@@ -903,7 +904,7 @@ class RunQueue:
self.stats.taskFailed() self.stats.taskFailed()
fnid = self.runq_fnid[task] fnid = self.runq_fnid[task]
self.failed_fnids.append(fnid) self.failed_fnids.append(fnid)
bb.event.fire(runQueueTaskFailed(task, self.stats, self, self.cfgData)) bb.event.fire(runQueueTaskFailed(task, self.stats, self), self.cfgData)
if self.taskData.abort: if self.taskData.abort:
self.state = runQueueCleanup self.state = runQueueCleanup
@@ -935,53 +936,67 @@ class RunQueue:
sys.stdout.flush() sys.stdout.flush()
sys.stderr.flush() sys.stderr.flush()
try: try:
pipein, pipeout = os.pipe()
pid = os.fork() pid = os.fork()
except OSError, e: except OSError, e:
bb.msg.fatal(bb.msg.domain.RunQueue, "fork failed: %d (%s)" % (e.errno, e.strerror)) bb.msg.fatal(bb.msg.domain.RunQueue, "fork failed: %d (%s)" % (e.errno, e.strerror))
if pid == 0: if pid == 0:
os.close(pipein)
# Save out the PID so that the event can include it the # Save out the PID so that the event can include it the
# events # events
bb.event.worker_pid = os.getpid() bb.event.worker_pid = os.getpid()
bb.event.worker_pipe = pipeout
bb.event.fire(runQueueTaskStarted(task, self.stats, self, self.cfgData)) self.state = runQueueChildProcess
# Make the child the process group leader
os.setpgid(0, 0)
# No stdin
newsi = os.open('/dev/null', os.O_RDWR)
os.dup2(newsi, sys.stdin.fileno())
bb.event.fire(runQueueTaskStarted(task, self.stats, self), self.cfgData)
bb.msg.note(1, bb.msg.domain.RunQueue, bb.msg.note(1, bb.msg.domain.RunQueue,
"Running task %d of %d (ID: %s, %s)" % (self.stats.completed + self.stats.active + 1, "Running task %d of %d (ID: %s, %s)" % (self.stats.completed + self.stats.active + 1,
self.stats.total, self.stats.total,
task, task,
self.get_user_idstring(task))) self.get_user_idstring(task)))
self.state = runQueueChildProcess
# Make the child the process group leader
os.setpgid(0, 0)
newsi = os.open('/dev/null', os.O_RDWR)
os.dup2(newsi, sys.stdin.fileno())
bb.data.setVar("__RUNQUEUE_DO_NOT_USE_EXTERNALLY", self, self.cooker.configuration.data) bb.data.setVar("__RUNQUEUE_DO_NOT_USE_EXTERNALLY", self, self.cooker.configuration.data)
try: try:
self.cooker.tryBuild(fn, taskname[3:]) self.cooker.tryBuild(fn, taskname[3:])
except bb.build.EventException: except bb.build.EventException:
bb.msg.error(bb.msg.domain.Build, "Build of " + fn + " " + taskname + " failed") bb.msg.error(bb.msg.domain.Build, "Build of " + fn + " " + taskname + " failed")
sys.exit(1) os._exit(1)
except: except:
bb.msg.error(bb.msg.domain.Build, "Build of " + fn + " " + taskname + " failed") bb.msg.error(bb.msg.domain.Build, "Build of " + fn + " " + taskname + " failed")
raise os._exit(1)
sys.exit(0) os._exit(0)
self.build_pids[pid] = task self.build_pids[pid] = task
self.build_pipes[pid] = runQueuePipe(pipein, pipeout, self.cfgData)
self.runq_running[task] = 1 self.runq_running[task] = 1
self.stats.taskActive() self.stats.taskActive()
if self.stats.active < self.number_tasks: if self.stats.active < self.number_tasks:
continue continue
for pipe in self.build_pipes:
self.build_pipes[pipe].read()
if self.stats.active > 0: if self.stats.active > 0:
result = os.waitpid(-1, os.WNOHANG) result = os.waitpid(-1, os.WNOHANG)
if result[0] is 0 and result[1] is 0: if result[0] is 0 and result[1] is 0:
return return
task = self.build_pids[result[0]] task = self.build_pids[result[0]]
del self.build_pids[result[0]] del self.build_pids[result[0]]
self.build_pipes[result[0]].close()
del self.build_pipes[result[0]]
if result[1] != 0: if result[1] != 0:
self.task_fail(task, result[1]) self.task_fail(task, result[1])
return return
self.task_complete(task) self.task_complete(task)
self.stats.taskCompleted() self.stats.taskCompleted()
bb.event.fire(runQueueTaskCompleted(task, self.stats, self, self.cfgData)) bb.event.fire(runQueueTaskCompleted(task, self.stats, self), self.cfgData)
continue continue
if len(self.failed_fnids) != 0: if len(self.failed_fnids) != 0:
@@ -1006,6 +1021,8 @@ class RunQueue:
os.kill(-k, signal.SIGINT) os.kill(-k, signal.SIGINT)
except: except:
pass pass
for pipe in self.build_pipes:
self.build_pipes[pipe].read()
def finish_runqueue(self, now = False): def finish_runqueue(self, now = False):
self.state = runQueueCleanUp self.state = runQueueCleanUp
@@ -1013,7 +1030,7 @@ class RunQueue:
self.finish_runqueue_now() self.finish_runqueue_now()
try: try:
while self.stats.active > 0: while self.stats.active > 0:
bb.event.fire(runQueueExitWait(self.stats.active, self.cfgData)) bb.event.fire(runQueueExitWait(self.stats.active), self.cfgData)
bb.msg.note(1, bb.msg.domain.RunQueue, "Waiting for %s active tasks to finish" % self.stats.active) bb.msg.note(1, bb.msg.domain.RunQueue, "Waiting for %s active tasks to finish" % self.stats.active)
tasknum = 1 tasknum = 1
for k, v in self.build_pids.iteritems(): for k, v in self.build_pids.iteritems():
@@ -1024,11 +1041,13 @@ class RunQueue:
return return
task = self.build_pids[result[0]] task = self.build_pids[result[0]]
del self.build_pids[result[0]] del self.build_pids[result[0]]
self.build_pipes[result[0]].close()
del self.build_pipes[result[0]]
if result[1] != 0: if result[1] != 0:
self.task_fail(task, result[1]) self.task_fail(task, result[1])
else: else:
self.stats.taskCompleted() self.stats.taskCompleted()
bb.event.fire(runQueueTaskCompleted(task, self.stats, self, self.cfgData)) bb.event.fire(runQueueTaskCompleted(task, self.stats, self), self.cfgData)
except: except:
self.finish_runqueue_now() self.finish_runqueue_now()
raise raise
@@ -1078,43 +1097,43 @@ class runQueueExitWait(bb.event.Event):
Event when waiting for task processes to exit Event when waiting for task processes to exit
""" """
def __init__(self, remain, d): def __init__(self, remain):
self.remain = remain self.remain = remain
self.message = "Waiting for %s active tasks to finish" % remain self.message = "Waiting for %s active tasks to finish" % remain
bb.event.Event.__init__(self, d) bb.event.Event.__init__(self)
class runQueueEvent(bb.event.Event): class runQueueEvent(bb.event.Event):
""" """
Base runQueue event class Base runQueue event class
""" """
def __init__(self, task, stats, rq, d): def __init__(self, task, stats, rq):
self.taskid = task self.taskid = task
self.taskstring = rq.get_user_idstring(task) self.taskstring = rq.get_user_idstring(task)
self.stats = stats self.stats = stats
bb.event.Event.__init__(self, d) bb.event.Event.__init__(self)
class runQueueTaskStarted(runQueueEvent): class runQueueTaskStarted(runQueueEvent):
""" """
Event notifing a task was started Event notifing a task was started
""" """
def __init__(self, task, stats, rq, d): def __init__(self, task, stats, rq):
runQueueEvent.__init__(self, task, stats, rq, d) runQueueEvent.__init__(self, task, stats, rq)
self.message = "Running task %s (%d of %d) (%s)" % (task, stats.completed + stats.active + 1, self.stats.total, self.taskstring) self.message = "Running task %s (%d of %d) (%s)" % (task, stats.completed + stats.active + 1, self.stats.total, self.taskstring)
class runQueueTaskFailed(runQueueEvent): class runQueueTaskFailed(runQueueEvent):
""" """
Event notifing a task failed Event notifing a task failed
""" """
def __init__(self, task, stats, rq, d): def __init__(self, task, stats, rq):
runQueueEvent.__init__(self, task, stats, rq, d) runQueueEvent.__init__(self, task, stats, rq)
self.message = "Task %s failed (%s)" % (task, self.taskstring) self.message = "Task %s failed (%s)" % (task, self.taskstring)
class runQueueTaskCompleted(runQueueEvent): class runQueueTaskCompleted(runQueueEvent):
""" """
Event notifing a task completed Event notifing a task completed
""" """
def __init__(self, task, stats, rq, d): def __init__(self, task, stats, rq):
runQueueEvent.__init__(self, task, stats, rq, d) runQueueEvent.__init__(self, task, stats, rq)
self.message = "Task %s completed (%s)" % (task, self.taskstring) self.message = "Task %s completed (%s)" % (task, self.taskstring)
def check_stamp_fn(fn, taskname, d): def check_stamp_fn(fn, taskname, d):
@@ -1124,3 +1143,32 @@ def check_stamp_fn(fn, taskname, d):
if taskid is not None: if taskid is not None:
return rq.check_stamp_task(taskid) return rq.check_stamp_task(taskid)
return None return None
class runQueuePipe():
"""
Abstraction for a pipe between a worker thread and the server
"""
def __init__(self, pipein, pipeout, d):
self.fd = pipein
os.close(pipeout)
self.queue = ""
self.d = d
def read(self):
start = len(self.queue)
self.queue = self.queue + os.read(self.fd, 1024)
end = len(self.queue)
index = self.queue.find("</event>")
while index != -1:
bb.event.fire_from_worker(self.queue[:index+8], self.d)
self.queue = self.queue[index+8:]
index = self.queue.find("</event>")
return (end > start)
def close(self):
while self.read():
continue
if len(self.queue) > 0:
print "Warning, worker left partial message"
os.close(self.fd)
+1
View File
@@ -1 +1,2 @@
import xmlrpc import xmlrpc
import none
+100 -64
View File
@@ -1,5 +1,5 @@
# #
# BitBake XMLRPC Server # BitBake 'dummy' Passthrough Server
# #
# Copyright (C) 2006 - 2007 Michael 'Mickey' Lauer # Copyright (C) 2006 - 2007 Michael 'Mickey' Lauer
# Copyright (C) 2006 - 2008 Richard Purdie # Copyright (C) 2006 - 2008 Richard Purdie
@@ -31,8 +31,11 @@
in the server's main loop. in the server's main loop.
""" """
import time
import bb import bb
from bb.ui import uievent
import xmlrpclib import xmlrpclib
import pickle
DEBUG = False DEBUG = False
@@ -44,31 +47,19 @@ class BitBakeServerCommands():
self.cooker = cooker self.cooker = cooker
self.server = server self.server = server
def registerEventHandler(self, host, port):
"""
Register a remote UI Event Handler
"""
s = xmlrpclib.Server("http://%s:%d" % (host, port), allow_none=True)
return bb.event.register_UIHhandler(s)
def unregisterEventHandler(self, handlerNum):
"""
Unregister a remote UI Event Handler
"""
return bb.event.unregister_UIHhandler(handlerNum)
def runCommand(self, command): def runCommand(self, command):
""" """
Run a cooker command on the server Run a cooker command on the server
""" """
#print "Running Command %s" % command
return self.cooker.command.runCommand(command) return self.cooker.command.runCommand(command)
def terminateServer(self): def terminateServer(self):
""" """
Trigger the server to quit Trigger the server to quit
""" """
self.server.quit = True self.server.server_exit()
print "Server (cooker) exitting" #print "Server (cooker) exitting"
return return
def ping(self): def ping(self):
@@ -77,63 +68,84 @@ class BitBakeServerCommands():
""" """
return True return True
class BitBakeXMLRPCServer(SimpleXMLRPCServer): eventQueue = []
class BBUIEventQueue:
class event:
def __init__(self, parent):
self.parent = parent
@staticmethod
def send(event):
bb.server.none.eventQueue.append(pickle.loads(event))
@staticmethod
def quit():
return
def __init__(self, BBServer):
self.eventQueue = bb.server.none.eventQueue
self.BBServer = BBServer
self.EventHandle = bb.event.register_UIHhandler(self)
def getEvent(self):
if len(self.eventQueue) == 0:
return None
return self.eventQueue.pop(0)
def waitEvent(self, delay):
event = self.getEvent()
if event:
return event
self.BBServer.idle_commands(delay)
return self.getEvent()
def queue_event(self, event):
self.eventQueue.append(event)
def system_quit( self ):
bb.event.unregister_UIHhandler(self.EventHandle)
class BitBakeServer():
# remove this when you're done with debugging # remove this when you're done with debugging
# allow_reuse_address = True # allow_reuse_address = True
def __init__(self, cooker, interface = ("localhost", 0)): def __init__(self, cooker):
"""
Constructor
"""
SimpleXMLRPCServer.__init__(self, interface,
requestHandler=SimpleXMLRPCRequestHandler,
logRequests=False, allow_none=True)
self._idlefuns = {} self._idlefuns = {}
self.host, self.port = self.socket.getsockname() self.commands = BitBakeServerCommands(self, cooker)
#self.register_introspection_functions()
commands = BitBakeServerCommands(self, cooker)
self.autoregister_all_functions(commands, "")
def autoregister_all_functions(self, context, prefix):
"""
Convenience method for registering all functions in the scope
of this class that start with a common prefix
"""
methodlist = inspect.getmembers(context, inspect.ismethod)
for name, method in methodlist:
if name.startswith(prefix):
self.register_function(method, name[len(prefix):])
def register_idle_function(self, function, data): def register_idle_function(self, function, data):
"""Register a function to be called while the server is idle""" """Register a function to be called while the server is idle"""
assert callable(function) assert callable(function)
self._idlefuns[function] = data self._idlefuns[function] = data
def serve_forever(self): def idle_commands(self, delay):
""" #print "Idle queue length %s" % len(self._idlefuns)
Serve Requests. Overloaded to honor a quit command #print "Idle timeout, running idle functions"
""" #if len(self._idlefuns) == 0:
self.quit = False nextsleep = delay
while not self.quit: for function, data in self._idlefuns.items():
#print "Idle queue length %s" % len(self._idlefuns) try:
if len(self._idlefuns) == 0: retval = function(self, data, False)
self.timeout = None #print "Idle function returned %s" % (retval)
else: if retval is False:
self.timeout = 0 del self._idlefuns[function]
self.handle_request() elif retval is True:
#print "Idle timeout, running idle functions" nextsleep = None
for function, data in self._idlefuns.items(): elif nextsleep is None:
try: continue
retval = function(self, data, False) elif retval < nextsleep:
if not retval: nextsleep = retval
del self._idlefuns[function] except SystemExit:
except SystemExit: raise
raise except:
except: import traceback
import traceback traceback.print_exc()
traceback.print_exc() pass
pass if nextsleep is not None:
#print "Sleeping for %s (%s)" % (nextsleep, delay)
time.sleep(nextsleep)
def server_exit(self):
# Tell idle functions we're exiting # Tell idle functions we're exiting
for function, data in self._idlefuns.items(): for function, data in self._idlefuns.items():
try: try:
@@ -141,5 +153,29 @@ class BitBakeXMLRPCServer(SimpleXMLRPCServer):
except: except:
pass pass
self.server_close() class BitbakeServerInfo():
return def __init__(self, server):
self.server = server
self.commands = server.commands
class BitBakeServerFork():
def __init__(self, serverinfo, command, logfile):
serverinfo.forkCommand = command
serverinfo.logfile = logfile
class BitBakeServerConnection():
def __init__(self, serverinfo):
self.server = serverinfo.server
self.connection = serverinfo.commands
self.events = bb.server.none.BBUIEventQueue(self.server)
def terminate(self):
try:
self.events.system_quit()
except:
pass
try:
self.connection.terminateServer()
except:
pass
+44 -6
View File
@@ -33,6 +33,8 @@
import bb import bb
import xmlrpclib import xmlrpclib
from bb import daemonize
from bb.ui import uievent
DEBUG = False DEBUG = False
@@ -114,26 +116,34 @@ class BitBakeServer(SimpleXMLRPCServer):
Serve Requests. Overloaded to honor a quit command Serve Requests. Overloaded to honor a quit command
""" """
self.quit = False self.quit = False
self.timeout = 0 # Run Idle calls for our first callback
while not self.quit: while not self.quit:
#print "Idle queue length %s" % len(self._idlefuns) #print "Idle queue length %s" % len(self._idlefuns)
if len(self._idlefuns) == 0:
self.timeout = None
else:
self.timeout = 0
self.handle_request() self.handle_request()
#print "Idle timeout, running idle functions" #print "Idle timeout, running idle functions"
nextsleep = None
for function, data in self._idlefuns.items(): for function, data in self._idlefuns.items():
try: try:
retval = function(self, data, False) retval = function(self, data, False)
if not retval: if retval is False:
del self._idlefuns[function] del self._idlefuns[function]
elif retval is True:
nextsleep = 0
elif nextsleep is 0:
continue
elif nextsleep is None:
nextsleep = retval
elif retval < nextsleep:
nextsleep = retval
except SystemExit: except SystemExit:
raise raise
except: except:
import traceback import traceback
traceback.print_exc() traceback.print_exc()
pass pass
if nextsleep is None and len(self._idlefuns) > 0:
nextsleep = 0
self.timeout = nextsleep
# Tell idle functions we're exiting # Tell idle functions we're exiting
for function, data in self._idlefuns.items(): for function, data in self._idlefuns.items():
try: try:
@@ -143,3 +153,31 @@ class BitBakeServer(SimpleXMLRPCServer):
self.server_close() self.server_close()
return return
class BitbakeServerInfo():
def __init__(self, server):
self.host = server.host
self.port = server.port
class BitBakeServerFork():
def __init__(self, serverinfo, command, logfile):
daemonize.createDaemon(command, logfile)
class BitBakeServerConnection():
def __init__(self, serverinfo):
self.connection = xmlrpclib.Server("http://%s:%s" % (serverinfo.host, serverinfo.port), allow_none=True)
self.events = uievent.BBUIEventQueue(self.connection)
def terminate(self):
# Don't wait for server indefinitely
import socket
socket.setdefaulttimeout(2)
try:
self.events.system_quit()
except:
pass
try:
self.connection.terminateServer()
except:
pass
+24 -11
View File
@@ -25,6 +25,19 @@ Task data collection and handling
import bb import bb
def re_match_strings(target, strings):
"""
Whether or not the string 'target' matches
any one string of the strings which can be regular expression string
"""
import re
for name in strings:
if (name==target or
re.search(name,target)!=None):
return True
return False
class TaskData: class TaskData:
""" """
BitBake Task Data implementation BitBake Task Data implementation
@@ -261,7 +274,7 @@ class TaskData:
""" """
unresolved = [] unresolved = []
for target in self.build_names_index: for target in self.build_names_index:
if target in dataCache.ignored_dependencies: if re_match_strings(target, dataCache.ignored_dependencies):
continue continue
if self.build_names_index.index(target) in self.failed_deps: if self.build_names_index.index(target) in self.failed_deps:
continue continue
@@ -276,7 +289,7 @@ class TaskData:
""" """
unresolved = [] unresolved = []
for target in self.run_names_index: for target in self.run_names_index:
if target in dataCache.ignored_dependencies: if re_match_strings(target, dataCache.ignored_dependencies):
continue continue
if self.run_names_index.index(target) in self.failed_rdeps: if self.run_names_index.index(target) in self.failed_rdeps:
continue continue
@@ -356,7 +369,7 @@ class TaskData:
added internally during dependency resolution added internally during dependency resolution
""" """
if item in dataCache.ignored_dependencies: if re_match_strings(item, dataCache.ignored_dependencies):
return return
if not item in dataCache.providers: if not item in dataCache.providers:
@@ -364,7 +377,7 @@ class TaskData:
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))) 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)))
else: else:
bb.msg.note(2, bb.msg.domain.Provider, "Nothing PROVIDES '%s'" % (item)) bb.msg.note(2, bb.msg.domain.Provider, "Nothing PROVIDES '%s'" % (item))
bb.event.fire(bb.event.NoProvider(item, cfgData)) bb.event.fire(bb.event.NoProvider(item), cfgData)
raise bb.providers.NoProvider(item) raise bb.providers.NoProvider(item)
if self.have_build_target(item): if self.have_build_target(item):
@@ -377,7 +390,7 @@ class TaskData:
if not eligible: if not eligible:
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))) 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)))
bb.event.fire(bb.event.NoProvider(item, cfgData)) bb.event.fire(bb.event.NoProvider(item), cfgData)
raise bb.providers.NoProvider(item) raise bb.providers.NoProvider(item)
if len(eligible) > 1 and foundUnique == False: if len(eligible) > 1 and foundUnique == False:
@@ -387,7 +400,7 @@ class TaskData:
providers_list.append(dataCache.pkg_fn[fn]) providers_list.append(dataCache.pkg_fn[fn])
bb.msg.note(1, bb.msg.domain.Provider, "multiple providers are available for %s (%s);" % (item, ", ".join(providers_list))) bb.msg.note(1, bb.msg.domain.Provider, "multiple providers are available for %s (%s);" % (item, ", ".join(providers_list)))
bb.msg.note(1, bb.msg.domain.Provider, "consider defining PREFERRED_PROVIDER_%s" % item) bb.msg.note(1, bb.msg.domain.Provider, "consider defining PREFERRED_PROVIDER_%s" % item)
bb.event.fire(bb.event.MultipleProviders(item, providers_list, cfgData)) bb.event.fire(bb.event.MultipleProviders(item, providers_list), cfgData)
self.consider_msgs_cache.append(item) self.consider_msgs_cache.append(item)
for fn in eligible: for fn in eligible:
@@ -407,7 +420,7 @@ class TaskData:
(takes item names from RDEPENDS/PACKAGES namespace) (takes item names from RDEPENDS/PACKAGES namespace)
""" """
if item in dataCache.ignored_dependencies: if re_match_strings(item, dataCache.ignored_dependencies):
return return
if self.have_runtime_target(item): if self.have_runtime_target(item):
@@ -417,7 +430,7 @@ class TaskData:
if not all_p: if not all_p:
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)) 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))
bb.event.fire(bb.event.NoProvider(item, cfgData, runtime=True)) bb.event.fire(bb.event.NoProvider(item, runtime=True), cfgData)
raise bb.providers.NoRProvider(item) raise bb.providers.NoRProvider(item)
eligible, numberPreferred = bb.providers.filterProvidersRunTime(all_p, item, cfgData, dataCache) eligible, numberPreferred = bb.providers.filterProvidersRunTime(all_p, item, cfgData, dataCache)
@@ -425,7 +438,7 @@ class TaskData:
if not eligible: if not eligible:
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)) 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))
bb.event.fire(bb.event.NoProvider(item, cfgData, runtime=True)) bb.event.fire(bb.event.NoProvider(item, runtime=True), cfgData)
raise bb.providers.NoRProvider(item) raise bb.providers.NoRProvider(item)
if len(eligible) > 1 and numberPreferred == 0: if len(eligible) > 1 and numberPreferred == 0:
@@ -435,7 +448,7 @@ class TaskData:
providers_list.append(dataCache.pkg_fn[fn]) providers_list.append(dataCache.pkg_fn[fn])
bb.msg.note(2, bb.msg.domain.Provider, "multiple providers are available for runtime %s (%s);" % (item, ", ".join(providers_list))) bb.msg.note(2, bb.msg.domain.Provider, "multiple providers are available for runtime %s (%s);" % (item, ", ".join(providers_list)))
bb.msg.note(2, bb.msg.domain.Provider, "consider defining a PREFERRED_PROVIDER entry to match runtime %s" % item) bb.msg.note(2, bb.msg.domain.Provider, "consider defining a PREFERRED_PROVIDER entry to match runtime %s" % item)
bb.event.fire(bb.event.MultipleProviders(item,providers_list, cfgData, runtime=True)) bb.event.fire(bb.event.MultipleProviders(item,providers_list, runtime=True), cfgData)
self.consider_msgs_cache.append(item) self.consider_msgs_cache.append(item)
if numberPreferred > 1: if numberPreferred > 1:
@@ -445,7 +458,7 @@ class TaskData:
providers_list.append(dataCache.pkg_fn[fn]) providers_list.append(dataCache.pkg_fn[fn])
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))) 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)))
bb.msg.note(2, bb.msg.domain.Provider, "consider defining only one PREFERRED_PROVIDER entry to match runtime %s" % item) bb.msg.note(2, bb.msg.domain.Provider, "consider defining only one PREFERRED_PROVIDER entry to match runtime %s" % item)
bb.event.fire(bb.event.MultipleProviders(item,providers_list, cfgData, runtime=True)) bb.event.fire(bb.event.MultipleProviders(item,providers_list, runtime=True), cfgData)
self.consider_msgs_cache.append(item) self.consider_msgs_cache.append(item)
# run through the list until we find one that we can build # run through the list until we find one that we can build
+14 -14
View File
@@ -61,36 +61,36 @@ class RunningBuild (gobject.GObject):
# If we have a pid attached to this message/event try and get the # If we have a pid attached to this message/event try and get the
# (package, task) pair for it. If we get that then get the parent iter # (package, task) pair for it. If we get that then get the parent iter
# for the message. # for the message.
if event[1].has_key ('pid'): if hassattr(event, 'pid'):
pid = event[1]['pid'] pid = event.pid
if self.pids_to_task.has_key(pid): if self.pids_to_task.has_key(pid):
(package, task) = self.pids_to_task[pid] (package, task) = self.pids_to_task[pid]
parent = self.tasks_to_iter[(package, task)] parent = self.tasks_to_iter[(package, task)]
if event[0].startswith('bb.msg.Msg'): if isinstance(event, bb.msg.Msg):
# Set a pretty icon for the message based on it's type. # Set a pretty icon for the message based on it's type.
if (event[0].startswith ('bb.msg.MsgWarn')): if isinstance(event, bb.msg.MsgWarn):
icon = "dialog-warning" icon = "dialog-warning"
elif (event[0].startswith ('bb.msg.MsgErr')): elif isinstance(event, bb.msg.MsgErr):
icon = "dialog-error" icon = "dialog-error"
else: else:
icon = None icon = None
# Ignore the "Running task i of n .." messages # Ignore the "Running task i of n .." messages
if (event[1]['_message'].startswith ("Running task")): if (event._message.startswith ("Running task")):
return return
# Add the message to the tree either at the top level if parent is # Add the message to the tree either at the top level if parent is
# None otherwise as a descendent of a task. # None otherwise as a descendent of a task.
self.model.append (parent, self.model.append (parent,
(event[0].split()[-1], # e.g. MsgWarn, MsgError (event.__name__.split()[-1], # e.g. MsgWarn, MsgError
package, package,
task, task,
event[1]['_message'], event._message,
icon, icon,
False)) False))
elif event[0].startswith('bb.build.TaskStarted'): elif isinstance(event, bb.build.TaskStarted):
(package, task) = (event[1]['_package'], event[1]['_task']) (package, task) = (event._package, event._task)
# Save out this PID. # Save out this PID.
self.pids_to_task[pid] = (package,task) self.pids_to_task[pid] = (package,task)
@@ -128,9 +128,9 @@ class RunningBuild (gobject.GObject):
# Mark this task as active. # Mark this task as active.
self.model.set(i, self.model.COL_ICON, "gtk-execute") self.model.set(i, self.model.COL_ICON, "gtk-execute")
elif event[0].startswith('bb.build.Task'): elif isinstance(event, bb.build.Task):
if event[0].startswith('bb.build.TaskFailed'): if isinstance(event, bb.build.TaskFailed):
# Mark the task as failed # Mark the task as failed
i = self.tasks_to_iter[(package, task)] i = self.tasks_to_iter[(package, task)]
self.model.set(i, self.model.COL_ICON, "dialog-error") self.model.set(i, self.model.COL_ICON, "dialog-error")
@@ -153,8 +153,8 @@ class RunningBuild (gobject.GObject):
del self.tasks_to_iter[(package, task)] del self.tasks_to_iter[(package, task)]
del self.pids_to_task[pid] del self.pids_to_task[pid]
elif event[0].startswith('bb.event.BuildCompleted'): elif isinstance(event, bb.event.BuildCompleted):
failures = int (event[1]['_failures']) failures = int (event._failures)
# Emit the appropriate signal depending on the number of failures # Emit the appropriate signal depending on the number of failures
if (failures > 1): if (failures > 1):
+10 -10
View File
@@ -229,12 +229,12 @@ def init(server, eventHandler):
if event is None: if event is None:
continue continue
if event[0].startswith('bb.event.ParseProgress'): if isinstance(event, bb.event.ParseProgress):
x = event[1]['sofar'] x = event.sofar
y = event[1]['total'] y = event.total
if x == y: if x == y:
print("\nParsing finished. %d cached, %d parsed, %d skipped, %d masked, %d errors." print("\nParsing finished. %d cached, %d parsed, %d skipped, %d masked, %d errors."
% ( event[1]['cached'], event[1]['parsed'], event[1]['skipped'], event[1]['masked'], event[1]['errors'])) % ( event.cached, event.parsed, event.skipped, event.masked, event.errors))
pbar.hide() pbar.hide()
gtk.gdk.threads_enter() gtk.gdk.threads_enter()
pbar.progress.set_fraction(float(x)/float(y)) pbar.progress.set_fraction(float(x)/float(y))
@@ -242,17 +242,17 @@ def init(server, eventHandler):
gtk.gdk.threads_leave() gtk.gdk.threads_leave()
continue continue
if event[0] == "bb.event.DepTreeGenerated": if isinstance(event, bb.event.DepTreeGenerated):
gtk.gdk.threads_enter() gtk.gdk.threads_enter()
parse(event[1]['_depgraph'], dep.pkg_model, dep.depends_model) parse(event._depgraph, dep.pkg_model, dep.depends_model)
gtk.gdk.threads_leave() gtk.gdk.threads_leave()
if event[0] == 'bb.command.CookerCommandCompleted': if isinstance(event, bb.command.CookerCommandCompleted):
continue continue
if event[0] == 'bb.command.CookerCommandFailed': if isinstance(event, bb.command.CookerCommandFailed):
print "Command execution failed: %s" % event[1]['error'] print "Command execution failed: %s" % event.error
break break
if event[0] == 'bb.cooker.CookerExit': if isinstance(event, bb.cooker.CookerExit):
break break
continue continue
+33 -33
View File
@@ -53,29 +53,29 @@ def init(server, eventHandler):
if event is None: if event is None:
continue continue
#print event #print event
if event[0].startswith('bb.msg.MsgPlain'): if isinstance(event, bb.msg.MsgPlain):
print event[1]['_message'] print event._message
continue continue
if event[0].startswith('bb.msg.MsgDebug'): if isinstance(event, bb.msg.MsgDebug):
print 'DEBUG: ' + event[1]['_message'] print 'DEBUG: ' + event._message
continue continue
if event[0].startswith('bb.msg.MsgNote'): if isinstance(event, bb.msg.MsgNote):
print 'NOTE: ' + event[1]['_message'] print 'NOTE: ' + event._message
continue continue
if event[0].startswith('bb.msg.MsgWarn'): if isinstance(event, bb.msg.MsgWarn):
print 'WARNING: ' + event[1]['_message'] print 'WARNING: ' + event._message
continue continue
if event[0].startswith('bb.msg.MsgError'): if isinstance(event, bb.msg.MsgError):
return_value = 1 return_value = 1
print 'ERROR: ' + event[1]['_message'] print 'ERROR: ' + event._message
continue continue
if event[0].startswith('bb.msg.MsgFatal'): if isinstance(event, bb.msg.MsgFatal):
return_value = 1 return_value = 1
print 'FATAL: ' + event[1]['_message'] print 'FATAL: ' + event._message
break break
if event[0].startswith('bb.build.TaskFailed'): if isinstance(event, bb.build.TaskFailed):
return_value = 1 return_value = 1
logfile = event[1]['logfile'] logfile = event.logfile
if logfile: if logfile:
print "ERROR: Logfile of failure stored in %s." % logfile print "ERROR: Logfile of failure stored in %s." % logfile
if 1 or includelogs: if 1 or includelogs:
@@ -97,12 +97,12 @@ def init(server, eventHandler):
if lines: if lines:
for line in lines: for line in lines:
print line print line
if event[0].startswith('bb.build.Task'): if isinstance(event, bb.build.TaskBase):
print "NOTE: %s" % event[1]['_message'] print "NOTE: %s" % event._message
continue continue
if event[0].startswith('bb.event.ParseProgress'): if isinstance(event, bb.event.ParseProgress):
x = event[1]['sofar'] x = event.sofar
y = event[1]['total'] y = event.total
if os.isatty(sys.stdout.fileno()): if os.isatty(sys.stdout.fileno()):
sys.stdout.write("\rNOTE: Handling BitBake files: %s (%04d/%04d) [%2d %%]" % ( parsespin.next(), x, y, x*100/y ) ) sys.stdout.write("\rNOTE: Handling BitBake files: %s (%04d/%04d) [%2d %%]" % ( parsespin.next(), x, y, x*100/y ) )
sys.stdout.flush() sys.stdout.flush()
@@ -115,35 +115,35 @@ def init(server, eventHandler):
sys.stdout.flush() sys.stdout.flush()
if x == y: if x == y:
print("\nParsing finished. %d cached, %d parsed, %d skipped, %d masked, %d errors." print("\nParsing finished. %d cached, %d parsed, %d skipped, %d masked, %d errors."
% ( event[1]['cached'], event[1]['parsed'], event[1]['skipped'], event[1]['masked'], event[1]['errors'])) % ( event.cached, event.parsed, event.skipped, event.masked, event.errors))
continue continue
if event[0] == 'bb.command.CookerCommandCompleted': if isinstance(event, bb.command.CookerCommandCompleted):
break break
if event[0] == 'bb.command.CookerCommandSetExitCode': if isinstance(event, bb.command.CookerCommandSetExitCode):
return_value = event[1]['exitcode'] return_value = event.exitcode
continue continue
if event[0] == 'bb.command.CookerCommandFailed': if isinstance(event, bb.command.CookerCommandFailed):
return_value = 1 return_value = 1
print "Command execution failed: %s" % event[1]['error'] print "Command execution failed: %s" % event.error
break break
if event[0] == 'bb.cooker.CookerExit': if isinstance(event, bb.cooker.CookerExit):
break break
# ignore # ignore
if event[0].startswith('bb.event.BuildStarted'): if isinstance(event, bb.event.BuildStarted):
continue continue
if event[0].startswith('bb.event.BuildCompleted'): if isinstance(event, bb.event.BuildCompleted):
continue continue
if event[0].startswith('bb.event.MultipleProviders'): if isinstance(event, bb.event.MultipleProviders):
continue continue
if event[0].startswith('bb.runqueue.runQueue'): if isinstance(event, bb.runqueue.runQueueEvent):
continue continue
if event[0].startswith('bb.event.StampUpdate'): if isinstance(event, bb.event.StampUpdate):
continue continue
if event[0].startswith('bb.event.ConfigParsed'): if isinstance(event, bb.event.ConfigParsed):
continue continue
if event[0].startswith('bb.event.RecipeParsed'): if isinstance(event, bb.event.RecipeParsed):
continue continue
print "Unknown Event: %s" % event print "Unknown Event: %s" % event
+22 -22
View File
@@ -246,29 +246,29 @@ class NCursesUI:
continue continue
helper.eventHandler(event) helper.eventHandler(event)
#mw.appendText("%s\n" % event[0]) #mw.appendText("%s\n" % event[0])
if event[0].startswith('bb.build.Task'): if isinstance(event, bb.build.Task):
mw.appendText("NOTE: %s\n" % event[1]['_message']) mw.appendText("NOTE: %s\n" % event._message)
if event[0].startswith('bb.msg.MsgDebug'): if isinstance(event, bb.msg.MsgDebug):
mw.appendText('DEBUG: ' + event[1]['_message'] + '\n') mw.appendText('DEBUG: ' + event._message + '\n')
if event[0].startswith('bb.msg.MsgNote'): if isinstance(event, bb.msg.MsgNote):
mw.appendText('NOTE: ' + event[1]['_message'] + '\n') mw.appendText('NOTE: ' + event._message + '\n')
if event[0].startswith('bb.msg.MsgWarn'): if isinstance(event, bb.msg.MsgWarn):
mw.appendText('WARNING: ' + event[1]['_message'] + '\n') mw.appendText('WARNING: ' + event._message + '\n')
if event[0].startswith('bb.msg.MsgError'): if isinstance(event, bb.msg.MsgError):
mw.appendText('ERROR: ' + event[1]['_message'] + '\n') mw.appendText('ERROR: ' + event._message + '\n')
if event[0].startswith('bb.msg.MsgFatal'): if isinstance(event, bb.msg.MsgFatal):
mw.appendText('FATAL: ' + event[1]['_message'] + '\n') mw.appendText('FATAL: ' + event._message + '\n')
if event[0].startswith('bb.event.ParseProgress'): if isinstance(event, bb.event.ParseProgress):
x = event[1]['sofar'] x = event.sofar
y = event[1]['total'] y = event.total
if x == y: if x == y:
mw.setStatus("Idle") mw.setStatus("Idle")
mw.appendText("Parsing finished. %d cached, %d parsed, %d skipped, %d masked." mw.appendText("Parsing finished. %d cached, %d parsed, %d skipped, %d masked."
% ( event[1]['cached'], event[1]['parsed'], event[1]['skipped'], event[1]['masked'] )) % ( event.cached, event.parsed, event.skipped, event.masked ))
else: else:
mw.setStatus("Parsing: %s (%04d/%04d) [%2d %%]" % ( parsespin.next(), x, y, x*100/y ) ) mw.setStatus("Parsing: %s (%04d/%04d) [%2d %%]" % ( parsespin.next(), x, y, x*100/y ) )
# if event[0].startswith('bb.build.TaskFailed'): # if isinstance(event, bb.build.TaskFailed):
# if event[1]['logfile']: # if event.logfile:
# if data.getVar("BBINCLUDELOGS", d): # if data.getVar("BBINCLUDELOGS", d):
# bb.msg.error(bb.msg.domain.Build, "log data follows (%s)" % logfile) # bb.msg.error(bb.msg.domain.Build, "log data follows (%s)" % logfile)
# number_of_lines = data.getVar("BBINCLUDELOGS_LINES", d) # number_of_lines = data.getVar("BBINCLUDELOGS_LINES", d)
@@ -286,13 +286,13 @@ class NCursesUI:
# else: # else:
# bb.msg.error(bb.msg.domain.Build, "see log in %s" % logfile) # bb.msg.error(bb.msg.domain.Build, "see log in %s" % logfile)
if event[0] == 'bb.command.CookerCommandCompleted': if isinstance(event, bb.command.CookerCommandCompleted):
exitflag = True exitflag = True
if event[0] == 'bb.command.CookerCommandFailed': if isinstance(event, bb.command.CookerCommandFailed):
mw.appendText("Command execution failed: %s" % event[1]['error']) mw.appendText("Command execution failed: %s" % event.error)
time.sleep(2) time.sleep(2)
exitflag = True exitflag = True
if event[0] == 'bb.cooker.CookerExit': if isinstance(event, bb.cooker.CookerExit):
exitflag = True exitflag = True
if helper.needUpdate: if helper.needUpdate:
+11 -13
View File
@@ -24,7 +24,7 @@ server and queue them for the UI to process. This process must be used to avoid
client/server deadlocks. client/server deadlocks.
""" """
import socket, threading import socket, threading, pickle
from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
class BBUIEventQueue: class BBUIEventQueue:
@@ -37,8 +37,8 @@ class BBUIEventQueue:
self.BBServer = BBServer self.BBServer = BBServer
self.t = threading.Thread() self.t = threading.Thread()
self.t.setDaemon(True) self.t.setDaemon(True)
self.t.run = self.startCallbackHandler self.t.run = self.startCallbackHandler
self.t.start() self.t.start()
def getEvent(self): def getEvent(self):
@@ -55,7 +55,6 @@ class BBUIEventQueue:
self.eventQueueNotify.clear() self.eventQueueNotify.clear()
self.eventQueueLock.release() self.eventQueueLock.release()
return item return item
def waitEvent(self, delay): def waitEvent(self, delay):
@@ -63,16 +62,15 @@ class BBUIEventQueue:
return self.getEvent() return self.getEvent()
def queue_event(self, event): def queue_event(self, event):
self.eventQueueLock.acquire() self.eventQueueLock.acquire()
self.eventQueue.append(event) self.eventQueue.append(pickle.loads(event))
self.eventQueueNotify.set() self.eventQueueNotify.set()
self.eventQueueLock.release() self.eventQueueLock.release()
def startCallbackHandler(self): def startCallbackHandler(self):
server = UIXMLRPCServer() server = UIXMLRPCServer()
self.host, self.port = server.socket.getsockname() self.host, self.port = server.socket.getsockname()
server.register_function( self.system_quit, "event.quit" ) server.register_function( self.system_quit, "event.quit" )
server.register_function( self.queue_event, "event.send" ) server.register_function( self.queue_event, "event.send" )
@@ -85,7 +83,7 @@ class BBUIEventQueue:
server.handle_request() server.handle_request()
server.server_close() server.server_close()
def system_quit( self ): def system_quit( self ):
""" """
Shut down the callback thread Shut down the callback thread
""" """
@@ -97,11 +95,11 @@ class BBUIEventQueue:
class UIXMLRPCServer (SimpleXMLRPCServer): class UIXMLRPCServer (SimpleXMLRPCServer):
def __init__( self, interface = ("localhost", 0) ): def __init__( self, interface = ("localhost", 0) ):
self.quit = False self.quit = False
SimpleXMLRPCServer.__init__( self, SimpleXMLRPCServer.__init__( self,
interface, interface,
requestHandler=SimpleXMLRPCRequestHandler, requestHandler=SimpleXMLRPCRequestHandler,
logRequests=False, allow_none=True) logRequests=False, allow_none=True)
def get_request(self): def get_request(self):
@@ -123,5 +121,5 @@ class UIXMLRPCServer (SimpleXMLRPCServer):
if request is None: if request is None:
return return
SimpleXMLRPCServer.process_request(self, request, client_address) SimpleXMLRPCServer.process_request(self, request, client_address)
+11 -11
View File
@@ -24,25 +24,25 @@ class BBUIHelper:
self.failed_tasks = {} self.failed_tasks = {}
def eventHandler(self, event): def eventHandler(self, event):
if event[0].startswith('bb.build.TaskStarted'): if isinstance(event, bb.build.TaskStarted):
self.running_tasks["%s %s\n" % (event[1]['_package'], event[1]['_task'])] = "" self.running_tasks["%s %s\n" % (event._package, event._task)] = ""
self.needUpdate = True self.needUpdate = True
if event[0].startswith('bb.build.TaskSucceeded'): if isinstance(event, bb.build.TaskSucceeded):
del self.running_tasks["%s %s\n" % (event[1]['_package'], event[1]['_task'])] del self.running_tasks["%s %s\n" % (event._package, event._task)]
self.needUpdate = True self.needUpdate = True
if event[0].startswith('bb.build.TaskFailed'): if isinstance(event, bb.build.TaskFailed):
del self.running_tasks["%s %s\n" % (event[1]['_package'], event[1]['_task'])] del self.running_tasks["%s %s\n" % (event._package, event._task)]
self.failed_tasks["%s %s\n" % (event[1]['_package'], event[1]['_task'])] = "" self.failed_tasks["%s %s\n" % (event._package, event._task)] = ""
self.needUpdate = True self.needUpdate = True
# Add runqueue event handling # Add runqueue event handling
#if event[0].startswith('bb.runqueue.runQueueTaskCompleted'): #if isinstance(event, bb.runqueue.runQueueTaskCompleted):
# a = 1 # a = 1
#if event[0].startswith('bb.runqueue.runQueueTaskStarted'): #if isinstance(event, bb.runqueue.runQueueTaskStarted):
# a = 1 # a = 1
#if event[0].startswith('bb.runqueue.runQueueTaskFailed'): #if isinstance(event, bb.runqueue.runQueueTaskFailed):
# a = 1 # a = 1
#if event[0].startswith('bb.runqueue.runQueueExitWait'): #if isinstance(event, bb.runqueue.runQueueExitWait):
# a = 1 # a = 1
def getTasks(self): def getTasks(self):