summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/command.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb/command.py')
-rw-r--r--bitbake/lib/bb/command.py100
1 files changed, 67 insertions, 33 deletions
diff --git a/bitbake/lib/bb/command.py b/bitbake/lib/bb/command.py
index f530cf844b..1fcb9bf14c 100644
--- a/bitbake/lib/bb/command.py
+++ b/bitbake/lib/bb/command.py
@@ -51,23 +51,32 @@ class Command:
"""
A queue of asynchronous commands for bitbake
"""
- def __init__(self, cooker):
+ def __init__(self, cooker, process_server):
self.cooker = cooker
self.cmds_sync = CommandsSync()
self.cmds_async = CommandsAsync()
self.remotedatastores = None
- # FIXME Add lock for this
+ self.process_server = process_server
+ # Access with locking using process_server.{get/set/clear}_async_cmd()
self.currentAsyncCommand = None
- def runCommand(self, commandline, ro_only = False):
+ def runCommand(self, commandline, process_server, ro_only=False):
command = commandline.pop(0)
# Ensure cooker is ready for commands
- if command != "updateConfig" and command != "setFeatures":
- self.cooker.init_configdata()
- if not self.remotedatastores:
- self.remotedatastores = bb.remotedata.RemoteDatastores(self.cooker)
+ if command not in ["updateConfig", "setFeatures", "ping"]:
+ try:
+ self.cooker.init_configdata()
+ if not self.remotedatastores:
+ self.remotedatastores = bb.remotedata.RemoteDatastores(self.cooker)
+ except (Exception, SystemExit) as exc:
+ import traceback
+ if isinstance(exc, bb.BBHandledException):
+ # We need to start returning real exceptions here. Until we do, we can't
+ # tell if an exception is an instance of bb.BBHandledException
+ return None, "bb.BBHandledException()\n" + traceback.format_exc()
+ return None, traceback.format_exc()
if hasattr(CommandsSync, command):
# Can run synchronous commands straight away
@@ -76,7 +85,6 @@ class Command:
if not hasattr(command_method, 'readonly') or not getattr(command_method, 'readonly'):
return None, "Not able to execute not readonly commands in readonly mode"
try:
- self.cooker.process_inotify_updates()
if getattr(command_method, 'needconfig', True):
self.cooker.updateCacheSync()
result = command_method(self, commandline)
@@ -91,24 +99,23 @@ class Command:
return None, traceback.format_exc()
else:
return result, None
- if self.currentAsyncCommand is not None:
- return None, "Busy (%s in progress)" % self.currentAsyncCommand[0]
if command not in CommandsAsync.__dict__:
return None, "No such command"
- self.currentAsyncCommand = (command, commandline)
- self.cooker.idleCallBackRegister(self.cooker.runCommands, self.cooker)
+ if not process_server.set_async_cmd((command, commandline)):
+ return None, "Busy (%s in progress)" % self.process_server.get_async_cmd()[0]
+ self.cooker.idleCallBackRegister(self.runAsyncCommand, process_server)
return True, None
- def runAsyncCommand(self):
+ def runAsyncCommand(self, _, process_server, halt):
try:
- self.cooker.process_inotify_updates()
if self.cooker.state in (bb.cooker.state.error, bb.cooker.state.shutdown, bb.cooker.state.forceshutdown):
# updateCache will trigger a shutdown of the parser
# and then raise BBHandledException triggering an exit
self.cooker.updateCache()
- return False
- if self.currentAsyncCommand is not None:
- (command, options) = self.currentAsyncCommand
+ return bb.server.process.idleFinish("Cooker in error state")
+ cmd = process_server.get_async_cmd()
+ if cmd is not None:
+ (command, options) = cmd
commandmethod = getattr(CommandsAsync, command)
needcache = getattr( commandmethod, "needcache" )
if needcache and self.cooker.state != bb.cooker.state.running:
@@ -118,24 +125,21 @@ class Command:
commandmethod(self.cmds_async, self, options)
return False
else:
- return False
+ return bb.server.process.idleFinish("Nothing to do, no async command?")
except KeyboardInterrupt as exc:
- self.finishAsyncCommand("Interrupted")
- return False
+ return bb.server.process.idleFinish("Interrupted")
except SystemExit as exc:
arg = exc.args[0]
if isinstance(arg, str):
- self.finishAsyncCommand(arg)
+ return bb.server.process.idleFinish(arg)
else:
- self.finishAsyncCommand("Exited with %s" % arg)
- return False
+ return bb.server.process.idleFinish("Exited with %s" % arg)
except Exception as exc:
import traceback
if isinstance(exc, bb.BBHandledException):
- self.finishAsyncCommand("")
+ return bb.server.process.idleFinish("")
else:
- self.finishAsyncCommand(traceback.format_exc())
- return False
+ return bb.server.process.idleFinish(traceback.format_exc())
def finishAsyncCommand(self, msg=None, code=None):
if msg or msg == "":
@@ -144,8 +148,8 @@ class Command:
bb.event.fire(CommandExit(code), self.cooker.data)
else:
bb.event.fire(CommandCompleted(), self.cooker.data)
- self.currentAsyncCommand = None
self.cooker.finishcommand()
+ self.process_server.clear_async_cmd()
def reset(self):
if self.remotedatastores:
@@ -158,6 +162,14 @@ class CommandsSync:
These must not influence any running synchronous command.
"""
+ def ping(self, command, params):
+ """
+ Allow a UI to check the server is still alive
+ """
+ return "Still alive!"
+ ping.needconfig = False
+ ping.readonly = True
+
def stateShutdown(self, command, params):
"""
Trigger cooker 'shutdown' mode
@@ -295,6 +307,11 @@ class CommandsSync:
return ret
getLayerPriorities.readonly = True
+ def revalidateCaches(self, command, params):
+ """Called by UI clients when metadata may have changed"""
+ command.cooker.revalidateCaches()
+ parseConfiguration.needconfig = False
+
def getRecipes(self, command, params):
try:
mc = params[0]
@@ -533,8 +550,8 @@ class CommandsSync:
and return a datastore object representing the environment
for the recipe.
"""
- fn = params[0]
- mc = bb.runqueue.mc_from_tid(fn)
+ virtualfn = params[0]
+ (fn, cls, mc) = bb.cache.virtualfn2realfn(virtualfn)
appends = params[1]
appendlist = params[2]
if len(params) > 3:
@@ -549,6 +566,7 @@ class CommandsSync:
appendfiles = command.cooker.collections[mc].get_file_appends(fn)
else:
appendfiles = []
+ layername = command.cooker.collections[mc].calc_bbfile_priority(fn)[2]
# We are calling bb.cache locally here rather than on the server,
# but that's OK because it doesn't actually need anything from
# the server barring the global datastore (which we have a remote
@@ -556,11 +574,10 @@ class CommandsSync:
if config_data:
# We have to use a different function here if we're passing in a datastore
# NOTE: we took a copy above, so we don't do it here again
- envdata = bb.cache.parse_recipe(config_data, fn, appendfiles, mc)['']
+ envdata = command.cooker.databuilder._parse_recipe(config_data, fn, appendfiles, mc, layername)[cls]
else:
# Use the standard path
- parser = bb.cache.NoCache(command.cooker.databuilder)
- envdata = parser.loadDataFull(fn, appendfiles)
+ envdata = command.cooker.databuilder.parseRecipe(virtualfn, appendfiles, layername)
idx = command.remotedatastores.store(envdata)
return DataStoreConnectionHandle(idx)
parseRecipeFile.readonly = True
@@ -659,6 +676,16 @@ class CommandsAsync:
command.finishAsyncCommand()
findFilesMatchingInDir.needcache = False
+ def testCookerCommandEvent(self, command, params):
+ """
+ Dummy command used by OEQA selftest to test tinfoil without IO
+ """
+ pattern = params[0]
+
+ command.cooker.testCookerCommandEvent(pattern)
+ command.finishAsyncCommand()
+ testCookerCommandEvent.needcache = False
+
def findConfigFilePath(self, command, params):
"""
Find the path of the requested configuration file
@@ -723,7 +750,7 @@ class CommandsAsync:
"""
event = params[0]
bb.event.fire(eval(event), command.cooker.data)
- command.currentAsyncCommand = None
+ process_server.clear_async_cmd()
triggerEvent.needcache = False
def resetCooker(self, command, params):
@@ -750,7 +777,14 @@ class CommandsAsync:
(mc, pn) = bb.runqueue.split_mc(params[0])
taskname = params[1]
sigs = params[2]
+ bb.siggen.check_siggen_version(bb.siggen)
res = bb.siggen.find_siginfo(pn, taskname, sigs, command.cooker.databuilder.mcdata[mc])
bb.event.fire(bb.event.FindSigInfoResult(res), command.cooker.databuilder.mcdata[mc])
command.finishAsyncCommand()
findSigInfo.needcache = False
+
+ def getTaskSignatures(self, command, params):
+ res = command.cooker.getTaskSignatures(params[0], params[1])
+ bb.event.fire(bb.event.GetTaskSignatureResult(res), command.cooker.data)
+ command.finishAsyncCommand()
+ getTaskSignatures.needcache = True