blob: 6abf38668bcb663771d79dce37b2a8ac391de669 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001"""
2BitBake 'Command' module
3
4Provide an interface to interact with the bitbake server through 'commands'
5"""
6
7# Copyright (C) 2006-2007 Richard Purdie
8#
Brad Bishopc342db32019-05-15 21:57:59 -04009# SPDX-License-Identifier: GPL-2.0-only
Patrick Williamsc124f4f2015-09-15 14:41:29 -050010#
Patrick Williamsc124f4f2015-09-15 14:41:29 -050011
12"""
13The bitbake server takes 'commands' from its UI/commandline.
14Commands are either synchronous or asynchronous.
15Async commands return data to the client in the form of events.
16Sync commands must only return data through the function return value
17and must not trigger events, directly or indirectly.
18Commands are queued in a CommandQueue
19"""
20
Brad Bishop6e60e8b2018-02-01 10:27:11 -050021from collections import OrderedDict, defaultdict
22
Patrick Williamsc124f4f2015-09-15 14:41:29 -050023import bb.event
24import bb.cooker
Brad Bishop6e60e8b2018-02-01 10:27:11 -050025import bb.remotedata
26
27class DataStoreConnectionHandle(object):
28 def __init__(self, dsindex=0):
29 self.dsindex = dsindex
Patrick Williamsc124f4f2015-09-15 14:41:29 -050030
31class CommandCompleted(bb.event.Event):
32 pass
33
34class CommandExit(bb.event.Event):
35 def __init__(self, exitcode):
36 bb.event.Event.__init__(self)
37 self.exitcode = int(exitcode)
38
39class CommandFailed(CommandExit):
40 def __init__(self, message):
41 self.error = message
42 CommandExit.__init__(self, 1)
Brad Bishopd7bf8c12018-02-25 22:55:05 -050043 def __str__(self):
44 return "Command execution failed: %s" % self.error
Patrick Williamsc124f4f2015-09-15 14:41:29 -050045
46class CommandError(Exception):
47 pass
48
49class Command:
50 """
51 A queue of asynchronous commands for bitbake
52 """
53 def __init__(self, cooker):
54 self.cooker = cooker
55 self.cmds_sync = CommandsSync()
56 self.cmds_async = CommandsAsync()
Brad Bishop6e60e8b2018-02-01 10:27:11 -050057 self.remotedatastores = bb.remotedata.RemoteDatastores(cooker)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050058
59 # FIXME Add lock for this
60 self.currentAsyncCommand = None
61
62 def runCommand(self, commandline, ro_only = False):
63 command = commandline.pop(0)
64 if hasattr(CommandsSync, command):
65 # Can run synchronous commands straight away
66 command_method = getattr(self.cmds_sync, command)
67 if ro_only:
Andrew Geissler82c905d2020-04-13 13:39:40 -050068 if not hasattr(command_method, 'readonly') or not getattr(command_method, 'readonly'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050069 return None, "Not able to execute not readonly commands in readonly mode"
70 try:
Brad Bishopd7bf8c12018-02-25 22:55:05 -050071 self.cooker.process_inotify_updates()
72 if getattr(command_method, 'needconfig', True):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050073 self.cooker.updateCacheSync()
74 result = command_method(self, commandline)
75 except CommandError as exc:
76 return None, exc.args[0]
77 except (Exception, SystemExit):
78 import traceback
79 return None, traceback.format_exc()
80 else:
81 return result, None
82 if self.currentAsyncCommand is not None:
83 return None, "Busy (%s in progress)" % self.currentAsyncCommand[0]
84 if command not in CommandsAsync.__dict__:
85 return None, "No such command"
86 self.currentAsyncCommand = (command, commandline)
87 self.cooker.configuration.server_register_idlecallback(self.cooker.runCommands, self.cooker)
88 return True, None
89
90 def runAsyncCommand(self):
91 try:
Brad Bishopd7bf8c12018-02-25 22:55:05 -050092 self.cooker.process_inotify_updates()
Patrick Williamsc124f4f2015-09-15 14:41:29 -050093 if self.cooker.state in (bb.cooker.state.error, bb.cooker.state.shutdown, bb.cooker.state.forceshutdown):
94 # updateCache will trigger a shutdown of the parser
95 # and then raise BBHandledException triggering an exit
96 self.cooker.updateCache()
97 return False
98 if self.currentAsyncCommand is not None:
99 (command, options) = self.currentAsyncCommand
100 commandmethod = getattr(CommandsAsync, command)
101 needcache = getattr( commandmethod, "needcache" )
102 if needcache and self.cooker.state != bb.cooker.state.running:
103 self.cooker.updateCache()
104 return True
105 else:
106 commandmethod(self.cmds_async, self, options)
107 return False
108 else:
109 return False
110 except KeyboardInterrupt as exc:
111 self.finishAsyncCommand("Interrupted")
112 return False
113 except SystemExit as exc:
114 arg = exc.args[0]
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600115 if isinstance(arg, str):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500116 self.finishAsyncCommand(arg)
117 else:
118 self.finishAsyncCommand("Exited with %s" % arg)
119 return False
120 except Exception as exc:
121 import traceback
122 if isinstance(exc, bb.BBHandledException):
123 self.finishAsyncCommand("")
124 else:
125 self.finishAsyncCommand(traceback.format_exc())
126 return False
127
128 def finishAsyncCommand(self, msg=None, code=None):
129 if msg or msg == "":
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500130 bb.event.fire(CommandFailed(msg), self.cooker.data)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500131 elif code:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500132 bb.event.fire(CommandExit(code), self.cooker.data)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500133 else:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500134 bb.event.fire(CommandCompleted(), self.cooker.data)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500135 self.currentAsyncCommand = None
136 self.cooker.finishcommand()
137
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500138 def reset(self):
139 self.remotedatastores = bb.remotedata.RemoteDatastores(self.cooker)
140
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500141def split_mc_pn(pn):
142 if pn.startswith("multiconfig:"):
143 _, mc, pn = pn.split(":", 2)
144 return (mc, pn)
145 return ('', pn)
146
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500147class CommandsSync:
148 """
149 A class of synchronous commands
150 These should run quickly so as not to hurt interactive performance.
151 These must not influence any running synchronous command.
152 """
153
154 def stateShutdown(self, command, params):
155 """
156 Trigger cooker 'shutdown' mode
157 """
158 command.cooker.shutdown(False)
159
160 def stateForceShutdown(self, command, params):
161 """
162 Stop the cooker
163 """
164 command.cooker.shutdown(True)
165
166 def getAllKeysWithFlags(self, command, params):
167 """
168 Returns a dump of the global state. Call with
169 variable flags to be retrieved as params.
170 """
171 flaglist = params[0]
172 return command.cooker.getAllKeysWithFlags(flaglist)
173 getAllKeysWithFlags.readonly = True
174
175 def getVariable(self, command, params):
176 """
177 Read the value of a variable from data
178 """
179 varname = params[0]
180 expand = True
181 if len(params) > 1:
182 expand = (params[1] == "True")
183
184 return command.cooker.data.getVar(varname, expand)
185 getVariable.readonly = True
186
187 def setVariable(self, command, params):
188 """
189 Set the value of variable in data
190 """
191 varname = params[0]
192 value = str(params[1])
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500193 command.cooker.extraconfigdata[varname] = value
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500194 command.cooker.data.setVar(varname, value)
195
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500196 def getSetVariable(self, command, params):
197 """
198 Read the value of a variable from data and set it into the datastore
199 which effectively expands and locks the value.
200 """
201 varname = params[0]
202 result = self.getVariable(command, params)
203 command.cooker.data.setVar(varname, result)
204 return result
205
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500206 def setConfig(self, command, params):
207 """
208 Set the value of variable in configuration
209 """
210 varname = params[0]
211 value = str(params[1])
212 setattr(command.cooker.configuration, varname, value)
213
214 def enableDataTracking(self, command, params):
215 """
216 Enable history tracking for variables
217 """
218 command.cooker.enableDataTracking()
219
220 def disableDataTracking(self, command, params):
221 """
222 Disable history tracking for variables
223 """
224 command.cooker.disableDataTracking()
225
226 def setPrePostConfFiles(self, command, params):
227 prefiles = params[0].split()
228 postfiles = params[1].split()
229 command.cooker.configuration.prefile = prefiles
230 command.cooker.configuration.postfile = postfiles
231 setPrePostConfFiles.needconfig = False
232
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500233 def matchFile(self, command, params):
234 fMatch = params[0]
235 return command.cooker.matchFile(fMatch)
236 matchFile.needconfig = False
237
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500238 def getUIHandlerNum(self, command, params):
239 return bb.event.get_uihandler()
240 getUIHandlerNum.needconfig = False
241 getUIHandlerNum.readonly = True
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500242
243 def setEventMask(self, command, params):
244 handlerNum = params[0]
245 llevel = params[1]
246 debug_domains = params[2]
247 mask = params[3]
248 return bb.event.set_UIHmask(handlerNum, llevel, debug_domains, mask)
249 setEventMask.needconfig = False
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500250 setEventMask.readonly = True
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500251
252 def setFeatures(self, command, params):
253 """
254 Set the cooker features to include the passed list of features
255 """
256 features = params[0]
257 command.cooker.setFeatures(features)
258 setFeatures.needconfig = False
259 # although we change the internal state of the cooker, this is transparent since
260 # we always take and leave the cooker in state.initial
261 setFeatures.readonly = True
262
263 def updateConfig(self, command, params):
264 options = params[0]
265 environment = params[1]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500266 cmdline = params[2]
267 command.cooker.updateConfigOpts(options, environment, cmdline)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500268 updateConfig.needconfig = False
269
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500270 def parseConfiguration(self, command, params):
271 """Instruct bitbake to parse its configuration
272 NOTE: it is only necessary to call this if you aren't calling any normal action
273 (otherwise parsing is taken care of automatically)
274 """
275 command.cooker.parseConfiguration()
276 parseConfiguration.needconfig = False
277
278 def getLayerPriorities(self, command, params):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500279 command.cooker.parseConfiguration()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500280 ret = []
281 # regex objects cannot be marshalled by xmlrpc
282 for collection, pattern, regex, pri in command.cooker.bbfile_config_priorities:
283 ret.append((collection, pattern, regex.pattern, pri))
284 return ret
285 getLayerPriorities.readonly = True
286
287 def getRecipes(self, command, params):
288 try:
289 mc = params[0]
290 except IndexError:
291 mc = ''
292 return list(command.cooker.recipecaches[mc].pkg_pn.items())
293 getRecipes.readonly = True
294
295 def getRecipeDepends(self, command, params):
296 try:
297 mc = params[0]
298 except IndexError:
299 mc = ''
300 return list(command.cooker.recipecaches[mc].deps.items())
301 getRecipeDepends.readonly = True
302
303 def getRecipeVersions(self, command, params):
304 try:
305 mc = params[0]
306 except IndexError:
307 mc = ''
308 return command.cooker.recipecaches[mc].pkg_pepvpr
309 getRecipeVersions.readonly = True
310
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500311 def getRecipeProvides(self, command, params):
312 try:
313 mc = params[0]
314 except IndexError:
315 mc = ''
316 return command.cooker.recipecaches[mc].fn_provides
317 getRecipeProvides.readonly = True
318
319 def getRecipePackages(self, command, params):
320 try:
321 mc = params[0]
322 except IndexError:
323 mc = ''
324 return command.cooker.recipecaches[mc].packages
325 getRecipePackages.readonly = True
326
327 def getRecipePackagesDynamic(self, command, params):
328 try:
329 mc = params[0]
330 except IndexError:
331 mc = ''
332 return command.cooker.recipecaches[mc].packages_dynamic
333 getRecipePackagesDynamic.readonly = True
334
335 def getRProviders(self, command, params):
336 try:
337 mc = params[0]
338 except IndexError:
339 mc = ''
340 return command.cooker.recipecaches[mc].rproviders
341 getRProviders.readonly = True
342
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500343 def getRuntimeDepends(self, command, params):
344 ret = []
345 try:
346 mc = params[0]
347 except IndexError:
348 mc = ''
349 rundeps = command.cooker.recipecaches[mc].rundeps
350 for key, value in rundeps.items():
351 if isinstance(value, defaultdict):
352 value = dict(value)
353 ret.append((key, value))
354 return ret
355 getRuntimeDepends.readonly = True
356
357 def getRuntimeRecommends(self, command, params):
358 ret = []
359 try:
360 mc = params[0]
361 except IndexError:
362 mc = ''
363 runrecs = command.cooker.recipecaches[mc].runrecs
364 for key, value in runrecs.items():
365 if isinstance(value, defaultdict):
366 value = dict(value)
367 ret.append((key, value))
368 return ret
369 getRuntimeRecommends.readonly = True
370
371 def getRecipeInherits(self, command, params):
372 try:
373 mc = params[0]
374 except IndexError:
375 mc = ''
376 return command.cooker.recipecaches[mc].inherits
377 getRecipeInherits.readonly = True
378
379 def getBbFilePriority(self, command, params):
380 try:
381 mc = params[0]
382 except IndexError:
383 mc = ''
384 return command.cooker.recipecaches[mc].bbfile_priority
385 getBbFilePriority.readonly = True
386
387 def getDefaultPreference(self, command, params):
388 try:
389 mc = params[0]
390 except IndexError:
391 mc = ''
392 return command.cooker.recipecaches[mc].pkg_dp
393 getDefaultPreference.readonly = True
394
395 def getSkippedRecipes(self, command, params):
396 # Return list sorted by reverse priority order
397 import bb.cache
398 skipdict = OrderedDict(sorted(command.cooker.skiplist.items(),
399 key=lambda x: (-command.cooker.collection.calc_bbfile_priority(bb.cache.virtualfn2realfn(x[0])[0]), x[0])))
400 return list(skipdict.items())
401 getSkippedRecipes.readonly = True
402
403 def getOverlayedRecipes(self, command, params):
404 return list(command.cooker.collection.overlayed.items())
405 getOverlayedRecipes.readonly = True
406
407 def getFileAppends(self, command, params):
408 fn = params[0]
409 return command.cooker.collection.get_file_appends(fn)
410 getFileAppends.readonly = True
411
412 def getAllAppends(self, command, params):
413 return command.cooker.collection.bbappends
414 getAllAppends.readonly = True
415
416 def findProviders(self, command, params):
Andrew Geissler82c905d2020-04-13 13:39:40 -0500417 try:
418 mc = params[0]
419 except IndexError:
420 mc = ''
421 return command.cooker.findProviders(mc)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500422 findProviders.readonly = True
423
424 def findBestProvider(self, command, params):
425 (mc, pn) = split_mc_pn(params[0])
426 return command.cooker.findBestProvider(pn, mc)
427 findBestProvider.readonly = True
428
429 def allProviders(self, command, params):
430 try:
431 mc = params[0]
432 except IndexError:
433 mc = ''
434 return list(bb.providers.allProviders(command.cooker.recipecaches[mc]).items())
435 allProviders.readonly = True
436
437 def getRuntimeProviders(self, command, params):
438 rprovide = params[0]
439 try:
440 mc = params[1]
441 except IndexError:
442 mc = ''
443 all_p = bb.providers.getRuntimeProviders(command.cooker.recipecaches[mc], rprovide)
444 if all_p:
445 best = bb.providers.filterProvidersRunTime(all_p, rprovide,
446 command.cooker.data,
447 command.cooker.recipecaches[mc])[0][0]
448 else:
449 best = None
450 return all_p, best
451 getRuntimeProviders.readonly = True
452
Andrew Geissler82c905d2020-04-13 13:39:40 -0500453 def dataStoreConnectorCmd(self, command, params):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500454 dsindex = params[0]
Andrew Geissler82c905d2020-04-13 13:39:40 -0500455 method = params[1]
456 args = params[2]
457 kwargs = params[3]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500458
Andrew Geissler82c905d2020-04-13 13:39:40 -0500459 d = command.remotedatastores[dsindex]
460 ret = getattr(d, method)(*args, **kwargs)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500461
Andrew Geissler82c905d2020-04-13 13:39:40 -0500462 if isinstance(ret, bb.data_smart.DataSmart):
463 idx = command.remotedatastores.store(ret)
464 return DataStoreConnectionHandle(idx)
465
466 return ret
467
468 def dataStoreConnectorVarHistCmd(self, command, params):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500469 dsindex = params[0]
Andrew Geissler82c905d2020-04-13 13:39:40 -0500470 method = params[1]
471 args = params[2]
472 kwargs = params[3]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500473
Andrew Geissler82c905d2020-04-13 13:39:40 -0500474 d = command.remotedatastores[dsindex].varhistory
475 return getattr(d, method)(*args, **kwargs)
476
477 def dataStoreConnectorIncHistCmd(self, command, params):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500478 dsindex = params[0]
Andrew Geissler82c905d2020-04-13 13:39:40 -0500479 method = params[1]
480 args = params[2]
481 kwargs = params[3]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500482
Andrew Geissler82c905d2020-04-13 13:39:40 -0500483 d = command.remotedatastores[dsindex].inchistory
484 return getattr(d, method)(*args, **kwargs)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500485
486 def dataStoreConnectorRelease(self, command, params):
487 dsindex = params[0]
488 if dsindex <= 0:
489 raise CommandError('dataStoreConnectorRelease: invalid index %d' % dsindex)
490 command.remotedatastores.release(dsindex)
491
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500492 def parseRecipeFile(self, command, params):
493 """
494 Parse the specified recipe file (with or without bbappends)
495 and return a datastore object representing the environment
496 for the recipe.
497 """
498 fn = params[0]
499 appends = params[1]
500 appendlist = params[2]
501 if len(params) > 3:
Andrew Geissler82c905d2020-04-13 13:39:40 -0500502 config_data = command.remotedatastores[params[3]]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500503 else:
504 config_data = None
505
506 if appends:
507 if appendlist is not None:
508 appendfiles = appendlist
509 else:
510 appendfiles = command.cooker.collection.get_file_appends(fn)
511 else:
512 appendfiles = []
513 # We are calling bb.cache locally here rather than on the server,
514 # but that's OK because it doesn't actually need anything from
515 # the server barring the global datastore (which we have a remote
516 # version of)
517 if config_data:
518 # We have to use a different function here if we're passing in a datastore
519 # NOTE: we took a copy above, so we don't do it here again
520 envdata = bb.cache.parse_recipe(config_data, fn, appendfiles)['']
521 else:
522 # Use the standard path
523 parser = bb.cache.NoCache(command.cooker.databuilder)
524 envdata = parser.loadDataFull(fn, appendfiles)
525 idx = command.remotedatastores.store(envdata)
526 return DataStoreConnectionHandle(idx)
527 parseRecipeFile.readonly = True
528
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500529class CommandsAsync:
530 """
531 A class of asynchronous commands
532 These functions communicate via generated events.
533 Any function that requires metadata parsing should be here.
534 """
535
536 def buildFile(self, command, params):
537 """
538 Build a single specified .bb file
539 """
540 bfile = params[0]
541 task = params[1]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500542 if len(params) > 2:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500543 internal = params[2]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500544 else:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500545 internal = False
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500546
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500547 if internal:
548 command.cooker.buildFileInternal(bfile, task, fireevents=False, quietlog=True)
549 else:
550 command.cooker.buildFile(bfile, task)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500551 buildFile.needcache = False
552
553 def buildTargets(self, command, params):
554 """
555 Build a set of targets
556 """
557 pkgs_to_build = params[0]
558 task = params[1]
559
560 command.cooker.buildTargets(pkgs_to_build, task)
561 buildTargets.needcache = True
562
563 def generateDepTreeEvent(self, command, params):
564 """
565 Generate an event containing the dependency information
566 """
567 pkgs_to_build = params[0]
568 task = params[1]
569
570 command.cooker.generateDepTreeEvent(pkgs_to_build, task)
571 command.finishAsyncCommand()
572 generateDepTreeEvent.needcache = True
573
574 def generateDotGraph(self, command, params):
575 """
576 Dump dependency information to disk as .dot files
577 """
578 pkgs_to_build = params[0]
579 task = params[1]
580
581 command.cooker.generateDotGraphFiles(pkgs_to_build, task)
582 command.finishAsyncCommand()
583 generateDotGraph.needcache = True
584
585 def generateTargetsTree(self, command, params):
586 """
587 Generate a tree of buildable targets.
588 If klass is provided ensure all recipes that inherit the class are
589 included in the package list.
590 If pkg_list provided use that list (plus any extras brought in by
591 klass) rather than generating a tree for all packages.
592 """
593 klass = params[0]
594 pkg_list = params[1]
595
596 command.cooker.generateTargetsTree(klass, pkg_list)
597 command.finishAsyncCommand()
598 generateTargetsTree.needcache = True
599
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500600 def findConfigFiles(self, command, params):
601 """
602 Find config files which provide appropriate values
603 for the passed configuration variable. i.e. MACHINE
604 """
605 varname = params[0]
606
607 command.cooker.findConfigFiles(varname)
608 command.finishAsyncCommand()
609 findConfigFiles.needcache = False
610
611 def findFilesMatchingInDir(self, command, params):
612 """
613 Find implementation files matching the specified pattern
614 in the requested subdirectory of a BBPATH
615 """
616 pattern = params[0]
617 directory = params[1]
618
619 command.cooker.findFilesMatchingInDir(pattern, directory)
620 command.finishAsyncCommand()
621 findFilesMatchingInDir.needcache = False
622
623 def findConfigFilePath(self, command, params):
624 """
625 Find the path of the requested configuration file
626 """
627 configfile = params[0]
628
629 command.cooker.findConfigFilePath(configfile)
630 command.finishAsyncCommand()
631 findConfigFilePath.needcache = False
632
633 def showVersions(self, command, params):
634 """
635 Show the currently selected versions
636 """
637 command.cooker.showVersions()
638 command.finishAsyncCommand()
639 showVersions.needcache = True
640
641 def showEnvironmentTarget(self, command, params):
642 """
643 Print the environment of a target recipe
644 (needs the cache to work out which recipe to use)
645 """
646 pkg = params[0]
647
648 command.cooker.showEnvironment(None, pkg)
649 command.finishAsyncCommand()
650 showEnvironmentTarget.needcache = True
651
652 def showEnvironment(self, command, params):
653 """
654 Print the standard environment
655 or if specified the environment for a specified recipe
656 """
657 bfile = params[0]
658
659 command.cooker.showEnvironment(bfile)
660 command.finishAsyncCommand()
661 showEnvironment.needcache = False
662
663 def parseFiles(self, command, params):
664 """
665 Parse the .bb files
666 """
667 command.cooker.updateCache()
668 command.finishAsyncCommand()
669 parseFiles.needcache = True
670
671 def compareRevisions(self, command, params):
672 """
673 Parse the .bb files
674 """
675 if bb.fetch.fetcher_compare_revisions(command.cooker.data):
676 command.finishAsyncCommand(code=1)
677 else:
678 command.finishAsyncCommand()
679 compareRevisions.needcache = True
680
681 def triggerEvent(self, command, params):
682 """
683 Trigger a certain event
684 """
685 event = params[0]
686 bb.event.fire(eval(event), command.cooker.data)
687 command.currentAsyncCommand = None
688 triggerEvent.needcache = False
689
690 def resetCooker(self, command, params):
691 """
692 Reset the cooker to its initial state, thus forcing a reparse for
693 any async command that has the needcache property set to True
694 """
695 command.cooker.reset()
696 command.finishAsyncCommand()
697 resetCooker.needcache = False
698
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500699 def clientComplete(self, command, params):
700 """
701 Do the right thing when the controlling client exits
702 """
703 command.cooker.clientComplete()
704 command.finishAsyncCommand()
705 clientComplete.needcache = False
706
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500707 def findSigInfo(self, command, params):
708 """
709 Find signature info files via the signature generator
710 """
711 pn = params[0]
712 taskname = params[1]
713 sigs = params[2]
714 res = bb.siggen.find_siginfo(pn, taskname, sigs, command.cooker.data)
715 bb.event.fire(bb.event.FindSigInfoResult(res), command.cooker.data)
716 command.finishAsyncCommand()
717 findSigInfo.needcache = False