diff options
Diffstat (limited to 'bitbake/lib')
-rw-r--r-- | bitbake/lib/bb/cooker.py | 10 | ||||
-rw-r--r-- | bitbake/lib/bb/data.py | 9 | ||||
-rw-r--r-- | bitbake/lib/bb/data_smart.py | 256 | ||||
-rw-r--r-- | bitbake/lib/bb/parse/ast.py | 30 |
4 files changed, 251 insertions, 54 deletions
diff --git a/bitbake/lib/bb/cooker.py b/bitbake/lib/bb/cooker.py index f06b71c42c..caf1123496 100644 --- a/bitbake/lib/bb/cooker.py +++ b/bitbake/lib/bb/cooker.py | |||
@@ -177,6 +177,8 @@ class BBCooker: | |||
177 | 177 | ||
178 | def initConfigurationData(self): | 178 | def initConfigurationData(self): |
179 | self.configuration.data = bb.data.init() | 179 | self.configuration.data = bb.data.init() |
180 | if self.configuration.show_environment: | ||
181 | self.configuration.data.enableTracking() | ||
180 | 182 | ||
181 | if not self.server_registration_cb: | 183 | if not self.server_registration_cb: |
182 | self.configuration.data.setVar("BB_WORKERCONTEXT", "1") | 184 | self.configuration.data.setVar("BB_WORKERCONTEXT", "1") |
@@ -185,13 +187,7 @@ class BBCooker: | |||
185 | bb.data.inheritFromOS(self.configuration.data, self.savedenv, filtered_keys) | 187 | bb.data.inheritFromOS(self.configuration.data, self.savedenv, filtered_keys) |
186 | 188 | ||
187 | def loadConfigurationData(self): | 189 | def loadConfigurationData(self): |
188 | self.configuration.data = bb.data.init() | 190 | self.initConfigurationData() |
189 | |||
190 | if not self.server_registration_cb: | ||
191 | self.configuration.data.setVar("BB_WORKERCONTEXT", "1") | ||
192 | |||
193 | filtered_keys = bb.utils.approved_variables() | ||
194 | bb.data.inheritFromOS(self.configuration.data, self.savedenv, filtered_keys) | ||
195 | 191 | ||
196 | try: | 192 | try: |
197 | self.parseConfigurationFiles(self.configuration.prefile, | 193 | self.parseConfigurationFiles(self.configuration.prefile, |
diff --git a/bitbake/lib/bb/data.py b/bitbake/lib/bb/data.py index 2c3e905a77..7047f48934 100644 --- a/bitbake/lib/bb/data.py +++ b/bitbake/lib/bb/data.py | |||
@@ -166,9 +166,9 @@ def inheritFromOS(d, savedenv, permitted): | |||
166 | for s in savedenv.keys(): | 166 | for s in savedenv.keys(): |
167 | if s in permitted: | 167 | if s in permitted: |
168 | try: | 168 | try: |
169 | d.setVar(s, getVar(s, savedenv, True)) | 169 | d.setVar(s, getVar(s, savedenv, True), op = 'from env') |
170 | if s in exportlist: | 170 | if s in exportlist: |
171 | d.setVarFlag(s, "export", True) | 171 | d.setVarFlag(s, "export", True, op = 'auto env export') |
172 | except TypeError: | 172 | except TypeError: |
173 | pass | 173 | pass |
174 | 174 | ||
@@ -194,8 +194,7 @@ def emit_var(var, o=sys.__stdout__, d = init(), all=False): | |||
194 | return 0 | 194 | return 0 |
195 | 195 | ||
196 | if all: | 196 | if all: |
197 | commentVal = re.sub('\n', '\n#', str(oval)) | 197 | d.varhistory.emit(var, oval, val, o) |
198 | o.write('# %s=%s\n' % (var, commentVal)) | ||
199 | 198 | ||
200 | if (var.find("-") != -1 or var.find(".") != -1 or var.find('{') != -1 or var.find('}') != -1 or var.find('+') != -1) and not all: | 199 | if (var.find("-") != -1 or var.find(".") != -1 or var.find('{') != -1 or var.find('}') != -1 or var.find('+') != -1) and not all: |
201 | return 0 | 200 | return 0 |
@@ -274,7 +273,7 @@ def emit_func(func, o=sys.__stdout__, d = init()): | |||
274 | 273 | ||
275 | def update_data(d): | 274 | def update_data(d): |
276 | """Performs final steps upon the datastore, including application of overrides""" | 275 | """Performs final steps upon the datastore, including application of overrides""" |
277 | d.finalize() | 276 | d.finalize(parent = True) |
278 | 277 | ||
279 | def build_dependencies(key, keys, shelldeps, vardepvals, d): | 278 | def build_dependencies(key, keys, shelldeps, vardepvals, d): |
280 | deps = set() | 279 | deps = set() |
diff --git a/bitbake/lib/bb/data_smart.py b/bitbake/lib/bb/data_smart.py index 5fdfeee2c7..ddf98e6a2e 100644 --- a/bitbake/lib/bb/data_smart.py +++ b/bitbake/lib/bb/data_smart.py | |||
@@ -28,7 +28,7 @@ BitBake build tools. | |||
28 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 28 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
29 | # Based on functions from the base bb module, Copyright 2003 Holger Schurig | 29 | # Based on functions from the base bb module, Copyright 2003 Holger Schurig |
30 | 30 | ||
31 | import copy, re | 31 | import copy, re, sys, traceback |
32 | from collections import MutableMapping | 32 | from collections import MutableMapping |
33 | import logging | 33 | import logging |
34 | import hashlib | 34 | import hashlib |
@@ -43,6 +43,42 @@ __setvar_regexp__ = re.compile('(?P<base>.*?)(?P<keyword>_append|_prepend)(_(?P< | |||
43 | __expand_var_regexp__ = re.compile(r"\${[^{}]+}") | 43 | __expand_var_regexp__ = re.compile(r"\${[^{}]+}") |
44 | __expand_python_regexp__ = re.compile(r"\${@.+?}") | 44 | __expand_python_regexp__ = re.compile(r"\${@.+?}") |
45 | 45 | ||
46 | def infer_caller_details(loginfo, parent = False, varval = True): | ||
47 | """Save the caller the trouble of specifying everything.""" | ||
48 | # Save effort. | ||
49 | if 'ignore' in loginfo and loginfo['ignore']: | ||
50 | return | ||
51 | # If nothing was provided, mark this as possibly unneeded. | ||
52 | if not loginfo: | ||
53 | loginfo['ignore'] = True | ||
54 | return | ||
55 | # Infer caller's likely values for variable (var) and value (value), | ||
56 | # to reduce clutter in the rest of the code. | ||
57 | if varval and ('variable' not in loginfo or 'detail' not in loginfo): | ||
58 | try: | ||
59 | raise Exception | ||
60 | except Exception: | ||
61 | tb = sys.exc_info()[2] | ||
62 | if parent: | ||
63 | above = tb.tb_frame.f_back.f_back | ||
64 | else: | ||
65 | above = tb.tb_frame.f_back | ||
66 | lcls = above.f_locals.items() | ||
67 | for k, v in lcls: | ||
68 | if k == 'value' and 'detail' not in loginfo: | ||
69 | loginfo['detail'] = v | ||
70 | if k == 'var' and 'variable' not in loginfo: | ||
71 | loginfo['variable'] = v | ||
72 | # Infer file/line/function from traceback | ||
73 | if 'file' not in loginfo: | ||
74 | depth = 3 | ||
75 | if parent: | ||
76 | depth = 4 | ||
77 | file, line, func, text = traceback.extract_stack(limit = depth)[0] | ||
78 | loginfo['file'] = file | ||
79 | loginfo['line'] = line | ||
80 | if func not in loginfo: | ||
81 | loginfo['func'] = func | ||
46 | 82 | ||
47 | class VariableParse: | 83 | class VariableParse: |
48 | def __init__(self, varname, d, val = None): | 84 | def __init__(self, varname, d, val = None): |
@@ -157,11 +193,80 @@ class IncludeHistory(object): | |||
157 | o.write("\n") | 193 | o.write("\n") |
158 | child.emit(o, level) | 194 | child.emit(o, level) |
159 | 195 | ||
196 | class VariableHistory(object): | ||
197 | def __init__(self, dataroot): | ||
198 | self.dataroot = dataroot | ||
199 | self.variables = COWDictBase.copy() | ||
200 | |||
201 | def copy(self): | ||
202 | new = VariableHistory(self.dataroot) | ||
203 | new.variables = self.variables.copy() | ||
204 | return new | ||
205 | |||
206 | def record(self, *kwonly, **loginfo): | ||
207 | if not self.dataroot._tracking: | ||
208 | return | ||
209 | if len(kwonly) > 0: | ||
210 | raise TypeError | ||
211 | infer_caller_details(loginfo, parent = True) | ||
212 | if 'ignore' in loginfo and loginfo['ignore']: | ||
213 | return | ||
214 | if 'op' not in loginfo or not loginfo['op']: | ||
215 | loginfo['op'] = 'set' | ||
216 | if 'detail' in loginfo: | ||
217 | loginfo['detail'] = str(loginfo['detail']) | ||
218 | if 'variable' not in loginfo or 'file' not in loginfo: | ||
219 | raise ValueError("record() missing variable or file.") | ||
220 | var = loginfo['variable'] | ||
221 | |||
222 | if var not in self.variables: | ||
223 | self.variables[var] = [] | ||
224 | self.variables[var].append(loginfo.copy()) | ||
225 | |||
226 | def variable(self, var): | ||
227 | if var in self.variables: | ||
228 | return self.variables[var] | ||
229 | else: | ||
230 | return [] | ||
231 | |||
232 | def emit(self, var, oval, val, o): | ||
233 | history = self.variable(var) | ||
234 | commentVal = re.sub('\n', '\n#', str(oval)) | ||
235 | if history: | ||
236 | if len(history) == 1: | ||
237 | o.write("#\n# $%s\n" % var) | ||
238 | else: | ||
239 | o.write("#\n# $%s [%d operations]\n" % (var, len(history))) | ||
240 | for event in history: | ||
241 | # o.write("# %s\n" % str(event)) | ||
242 | if 'func' in event: | ||
243 | # If we have a function listed, this is internal | ||
244 | # code, not an operation in a config file, and the | ||
245 | # full path is distracting. | ||
246 | event['file'] = re.sub('.*/', '', event['file']) | ||
247 | display_func = ' [%s]' % event['func'] | ||
248 | else: | ||
249 | display_func = '' | ||
250 | if 'flag' in event: | ||
251 | flag = '[%s] ' % (event['flag']) | ||
252 | else: | ||
253 | flag = '' | ||
254 | o.write("# %s %s:%s%s\n# %s\"%s\"\n" % (event['op'], event['file'], event['line'], display_func, flag, re.sub('\n', '\n# ', event['detail']))) | ||
255 | if len(history) > 1: | ||
256 | o.write("# computed:\n") | ||
257 | o.write('# "%s"\n' % (commentVal)) | ||
258 | else: | ||
259 | o.write("#\n# $%s\n# [no history recorded]\n#\n" % var) | ||
260 | o.write('# "%s"\n' % (commentVal)) | ||
261 | |||
262 | |||
160 | class DataSmart(MutableMapping): | 263 | class DataSmart(MutableMapping): |
161 | def __init__(self, special = COWDictBase.copy(), seen = COWDictBase.copy() ): | 264 | def __init__(self, special = COWDictBase.copy(), seen = COWDictBase.copy() ): |
162 | self.dict = {} | 265 | self.dict = {} |
163 | 266 | ||
164 | self.inchistory = IncludeHistory() | 267 | self.inchistory = IncludeHistory() |
268 | self.varhistory = VariableHistory(self) | ||
269 | self._tracking = False | ||
165 | 270 | ||
166 | # cookie monster tribute | 271 | # cookie monster tribute |
167 | self._special_values = special | 272 | self._special_values = special |
@@ -169,6 +274,12 @@ class DataSmart(MutableMapping): | |||
169 | 274 | ||
170 | self.expand_cache = {} | 275 | self.expand_cache = {} |
171 | 276 | ||
277 | def enableTracking(self): | ||
278 | self._tracking = True | ||
279 | |||
280 | def disableTracking(self): | ||
281 | self._tracking = False | ||
282 | |||
172 | def expandWithRefs(self, s, varname): | 283 | def expandWithRefs(self, s, varname): |
173 | 284 | ||
174 | if not isinstance(s, basestring): # sanity check | 285 | if not isinstance(s, basestring): # sanity check |
@@ -204,10 +315,14 @@ class DataSmart(MutableMapping): | |||
204 | return self.expandWithRefs(s, varname).value | 315 | return self.expandWithRefs(s, varname).value |
205 | 316 | ||
206 | 317 | ||
207 | def finalize(self): | 318 | def finalize(self, parent = False): |
208 | """Performs final steps upon the datastore, including application of overrides""" | 319 | """Performs final steps upon the datastore, including application of overrides""" |
209 | 320 | ||
210 | overrides = (self.getVar("OVERRIDES", True) or "").split(":") or [] | 321 | overrides = (self.getVar("OVERRIDES", True) or "").split(":") or [] |
322 | finalize_caller = { | ||
323 | 'op': 'finalize', | ||
324 | } | ||
325 | infer_caller_details(finalize_caller, parent = parent, varval = False) | ||
211 | 326 | ||
212 | # | 327 | # |
213 | # Well let us see what breaks here. We used to iterate | 328 | # Well let us see what breaks here. We used to iterate |
@@ -224,6 +339,9 @@ class DataSmart(MutableMapping): | |||
224 | # Then we will handle _append and _prepend | 339 | # Then we will handle _append and _prepend |
225 | # | 340 | # |
226 | 341 | ||
342 | # We only want to report finalization once per variable overridden. | ||
343 | finalizes_reported = {} | ||
344 | |||
227 | for o in overrides: | 345 | for o in overrides: |
228 | # calculate '_'+override | 346 | # calculate '_'+override |
229 | l = len(o) + 1 | 347 | l = len(o) + 1 |
@@ -236,7 +354,19 @@ class DataSmart(MutableMapping): | |||
236 | for var in vars: | 354 | for var in vars: |
237 | name = var[:-l] | 355 | name = var[:-l] |
238 | try: | 356 | try: |
239 | self.setVar(name, self.getVar(var, False)) | 357 | # Report only once, even if multiple changes. |
358 | if name not in finalizes_reported: | ||
359 | finalizes_reported[name] = True | ||
360 | finalize_caller['variable'] = name | ||
361 | finalize_caller['detail'] = 'was: ' + str(self.getVar(name, False)) | ||
362 | self.varhistory.record(**finalize_caller) | ||
363 | # Copy history of the override over. | ||
364 | for event in self.varhistory.variable(var): | ||
365 | loginfo = event.copy() | ||
366 | loginfo['variable'] = name | ||
367 | loginfo['op'] = 'override[%s]:%s' % (o, loginfo['op']) | ||
368 | self.varhistory.record(**loginfo) | ||
369 | self.setVar(name, self.getVar(var, False), op = 'finalize', file = 'override[%s]' % o, line = '') | ||
240 | self.delVar(var) | 370 | self.delVar(var) |
241 | except Exception: | 371 | except Exception: |
242 | logger.info("Untracked delVar") | 372 | logger.info("Untracked delVar") |
@@ -267,9 +397,9 @@ class DataSmart(MutableMapping): | |||
267 | 397 | ||
268 | # We save overrides that may be applied at some later stage | 398 | # We save overrides that may be applied at some later stage |
269 | if keep: | 399 | if keep: |
270 | self.setVarFlag(append, op, keep) | 400 | self.setVarFlag(append, op, keep, ignore=True) |
271 | else: | 401 | else: |
272 | self.delVarFlag(append, op) | 402 | self.delVarFlag(append, op, ignore=True) |
273 | 403 | ||
274 | def initVar(self, var): | 404 | def initVar(self, var): |
275 | self.expand_cache = {} | 405 | self.expand_cache = {} |
@@ -297,7 +427,10 @@ class DataSmart(MutableMapping): | |||
297 | else: | 427 | else: |
298 | self.initVar(var) | 428 | self.initVar(var) |
299 | 429 | ||
300 | def setVar(self, var, value): | 430 | |
431 | def setVar(self, var, value, **loginfo): | ||
432 | if 'op' not in loginfo: | ||
433 | loginfo['op'] = "set" | ||
301 | self.expand_cache = {} | 434 | self.expand_cache = {} |
302 | match = __setvar_regexp__.match(var) | 435 | match = __setvar_regexp__.match(var) |
303 | if match and match.group("keyword") in __setvar_keyword__: | 436 | if match and match.group("keyword") in __setvar_keyword__: |
@@ -306,15 +439,22 @@ class DataSmart(MutableMapping): | |||
306 | override = match.group('add') | 439 | override = match.group('add') |
307 | l = self.getVarFlag(base, keyword) or [] | 440 | l = self.getVarFlag(base, keyword) or [] |
308 | l.append([value, override]) | 441 | l.append([value, override]) |
309 | self.setVarFlag(base, keyword, l) | 442 | self.setVarFlag(base, keyword, l, ignore=True) |
310 | 443 | # And cause that to be recorded: | |
444 | loginfo['detail'] = value | ||
445 | loginfo['variable'] = base | ||
446 | if override: | ||
447 | loginfo['op'] = '%s[%s]' % (keyword, override) | ||
448 | else: | ||
449 | loginfo['op'] = keyword | ||
450 | self.varhistory.record(**loginfo) | ||
311 | # todo make sure keyword is not __doc__ or __module__ | 451 | # todo make sure keyword is not __doc__ or __module__ |
312 | # pay the cookie monster | 452 | # pay the cookie monster |
313 | try: | 453 | try: |
314 | self._special_values[keyword].add( base ) | 454 | self._special_values[keyword].add(base) |
315 | except KeyError: | 455 | except KeyError: |
316 | self._special_values[keyword] = set() | 456 | self._special_values[keyword] = set() |
317 | self._special_values[keyword].add( base ) | 457 | self._special_values[keyword].add(base) |
318 | 458 | ||
319 | return | 459 | return |
320 | 460 | ||
@@ -331,6 +471,7 @@ class DataSmart(MutableMapping): | |||
331 | 471 | ||
332 | # setting var | 472 | # setting var |
333 | self.dict[var]["_content"] = value | 473 | self.dict[var]["_content"] = value |
474 | self.varhistory.record(**loginfo) | ||
334 | 475 | ||
335 | def getVar(self, var, expand=False, noweakdefault=False): | 476 | def getVar(self, var, expand=False, noweakdefault=False): |
336 | value = self.getVarFlag(var, "_content", False, noweakdefault) | 477 | value = self.getVarFlag(var, "_content", False, noweakdefault) |
@@ -340,13 +481,17 @@ class DataSmart(MutableMapping): | |||
340 | return self.expand(value, var) | 481 | return self.expand(value, var) |
341 | return value | 482 | return value |
342 | 483 | ||
343 | def renameVar(self, key, newkey): | 484 | def renameVar(self, key, newkey, **loginfo): |
344 | """ | 485 | """ |
345 | Rename the variable key to newkey | 486 | Rename the variable key to newkey |
346 | """ | 487 | """ |
347 | val = self.getVar(key, 0) | 488 | val = self.getVar(key, 0) |
348 | if val is not None: | 489 | if val is not None: |
349 | self.setVar(newkey, val) | 490 | loginfo['variable'] = newkey |
491 | loginfo['op'] = 'rename from %s' % key | ||
492 | loginfo['detail'] = val | ||
493 | self.varhistory.record(**loginfo) | ||
494 | self.setVar(newkey, val, ignore=True) | ||
350 | 495 | ||
351 | for i in ('_append', '_prepend'): | 496 | for i in ('_append', '_prepend'): |
352 | src = self.getVarFlag(key, i) | 497 | src = self.getVarFlag(key, i) |
@@ -355,23 +500,34 @@ class DataSmart(MutableMapping): | |||
355 | 500 | ||
356 | dest = self.getVarFlag(newkey, i) or [] | 501 | dest = self.getVarFlag(newkey, i) or [] |
357 | dest.extend(src) | 502 | dest.extend(src) |
358 | self.setVarFlag(newkey, i, dest) | 503 | self.setVarFlag(newkey, i, dest, ignore=True) |
359 | 504 | ||
360 | if i in self._special_values and key in self._special_values[i]: | 505 | if i in self._special_values and key in self._special_values[i]: |
361 | self._special_values[i].remove(key) | 506 | self._special_values[i].remove(key) |
362 | self._special_values[i].add(newkey) | 507 | self._special_values[i].add(newkey) |
363 | 508 | ||
364 | self.delVar(key) | 509 | loginfo['variable'] = key |
365 | 510 | loginfo['op'] = 'rename (to)' | |
366 | def appendVar(self, key, value): | 511 | loginfo['detail'] = newkey |
367 | value = (self.getVar(key, False) or "") + value | 512 | self.varhistory.record(**loginfo) |
368 | self.setVar(key, value) | 513 | self.delVar(key, ignore=True) |
369 | 514 | ||
370 | def prependVar(self, key, value): | 515 | def appendVar(self, var, value, **loginfo): |
371 | value = value + (self.getVar(key, False) or "") | 516 | loginfo['op'] = 'append' |
372 | self.setVar(key, value) | 517 | self.varhistory.record(**loginfo) |
373 | 518 | newvalue = (self.getVar(var, False) or "") + value | |
374 | def delVar(self, var): | 519 | self.setVar(var, newvalue, ignore=True) |
520 | |||
521 | def prependVar(self, var, value, **loginfo): | ||
522 | loginfo['op'] = 'prepend' | ||
523 | self.varhistory.record(**loginfo) | ||
524 | newvalue = value + (self.getVar(var, False) or "") | ||
525 | self.setVar(var, newvalue, ignore=True) | ||
526 | |||
527 | def delVar(self, var, **loginfo): | ||
528 | loginfo['detail'] = "" | ||
529 | loginfo['op'] = 'del' | ||
530 | self.varhistory.record(**loginfo) | ||
375 | self.expand_cache = {} | 531 | self.expand_cache = {} |
376 | self.dict[var] = {} | 532 | self.dict[var] = {} |
377 | if '_' in var: | 533 | if '_' in var: |
@@ -379,10 +535,14 @@ class DataSmart(MutableMapping): | |||
379 | if override and override in self._seen_overrides and var in self._seen_overrides[override]: | 535 | if override and override in self._seen_overrides and var in self._seen_overrides[override]: |
380 | self._seen_overrides[override].remove(var) | 536 | self._seen_overrides[override].remove(var) |
381 | 537 | ||
382 | def setVarFlag(self, var, flag, flagvalue): | 538 | def setVarFlag(self, var, flag, value, **loginfo): |
539 | if 'op' not in loginfo: | ||
540 | loginfo['op'] = "set" | ||
541 | loginfo['flag'] = flag | ||
542 | self.varhistory.record(**loginfo) | ||
383 | if not var in self.dict: | 543 | if not var in self.dict: |
384 | self._makeShadowCopy(var) | 544 | self._makeShadowCopy(var) |
385 | self.dict[var][flag] = flagvalue | 545 | self.dict[var][flag] = value |
386 | 546 | ||
387 | def getVarFlag(self, var, flag, expand=False, noweakdefault=False): | 547 | def getVarFlag(self, var, flag, expand=False, noweakdefault=False): |
388 | local_var = self._findVar(var) | 548 | local_var = self._findVar(var) |
@@ -396,7 +556,7 @@ class DataSmart(MutableMapping): | |||
396 | value = self.expand(value, None) | 556 | value = self.expand(value, None) |
397 | return value | 557 | return value |
398 | 558 | ||
399 | def delVarFlag(self, var, flag): | 559 | def delVarFlag(self, var, flag, **loginfo): |
400 | local_var = self._findVar(var) | 560 | local_var = self._findVar(var) |
401 | if not local_var: | 561 | if not local_var: |
402 | return | 562 | return |
@@ -404,23 +564,38 @@ class DataSmart(MutableMapping): | |||
404 | self._makeShadowCopy(var) | 564 | self._makeShadowCopy(var) |
405 | 565 | ||
406 | if var in self.dict and flag in self.dict[var]: | 566 | if var in self.dict and flag in self.dict[var]: |
407 | del self.dict[var][flag] | 567 | loginfo['detail'] = "" |
408 | 568 | loginfo['op'] = 'delFlag' | |
409 | def appendVarFlag(self, key, flag, value): | 569 | loginfo['flag'] = flag |
410 | value = (self.getVarFlag(key, flag, False) or "") + value | 570 | self.varhistory.record(**loginfo) |
411 | self.setVarFlag(key, flag, value) | ||
412 | 571 | ||
413 | def prependVarFlag(self, key, flag, value): | 572 | del self.dict[var][flag] |
414 | value = value + (self.getVarFlag(key, flag, False) or "") | ||
415 | self.setVarFlag(key, flag, value) | ||
416 | 573 | ||
417 | def setVarFlags(self, var, flags): | 574 | def appendVarFlag(self, var, flag, value, **loginfo): |
575 | loginfo['op'] = 'append' | ||
576 | loginfo['flag'] = flag | ||
577 | self.varhistory.record(**loginfo) | ||
578 | newvalue = (self.getVarFlag(var, flag, False) or "") + value | ||
579 | self.setVarFlag(var, flag, newvalue, ignore=True) | ||
580 | |||
581 | def prependVarFlag(self, var, flag, value, **loginfo): | ||
582 | loginfo['op'] = 'prepend' | ||
583 | loginfo['flag'] = flag | ||
584 | self.varhistory.record(**loginfo) | ||
585 | newvalue = value + (self.getVarFlag(var, flag, False) or "") | ||
586 | self.setVarFlag(var, flag, newvalue, ignore=True) | ||
587 | |||
588 | def setVarFlags(self, var, flags, **loginfo): | ||
589 | infer_caller_details(loginfo) | ||
418 | if not var in self.dict: | 590 | if not var in self.dict: |
419 | self._makeShadowCopy(var) | 591 | self._makeShadowCopy(var) |
420 | 592 | ||
421 | for i in flags: | 593 | for i in flags: |
422 | if i == "_content": | 594 | if i == "_content": |
423 | continue | 595 | continue |
596 | loginfo['flag'] = i | ||
597 | loginfo['detail'] = flags[i] | ||
598 | self.varhistory.record(**loginfo) | ||
424 | self.dict[var][i] = flags[i] | 599 | self.dict[var][i] = flags[i] |
425 | 600 | ||
426 | def getVarFlags(self, var): | 601 | def getVarFlags(self, var): |
@@ -438,13 +613,16 @@ class DataSmart(MutableMapping): | |||
438 | return flags | 613 | return flags |
439 | 614 | ||
440 | 615 | ||
441 | def delVarFlags(self, var): | 616 | def delVarFlags(self, var, **loginfo): |
442 | if not var in self.dict: | 617 | if not var in self.dict: |
443 | self._makeShadowCopy(var) | 618 | self._makeShadowCopy(var) |
444 | 619 | ||
445 | if var in self.dict: | 620 | if var in self.dict: |
446 | content = None | 621 | content = None |
447 | 622 | ||
623 | loginfo['op'] = 'delete flags' | ||
624 | self.varhistory.record(**loginfo) | ||
625 | |||
448 | # try to save the content | 626 | # try to save the content |
449 | if "_content" in self.dict[var]: | 627 | if "_content" in self.dict[var]: |
450 | content = self.dict[var]["_content"] | 628 | content = self.dict[var]["_content"] |
@@ -461,8 +639,12 @@ class DataSmart(MutableMapping): | |||
461 | # we really want this to be a DataSmart... | 639 | # we really want this to be a DataSmart... |
462 | data = DataSmart(seen=self._seen_overrides.copy(), special=self._special_values.copy()) | 640 | data = DataSmart(seen=self._seen_overrides.copy(), special=self._special_values.copy()) |
463 | data.dict["_data"] = self.dict | 641 | data.dict["_data"] = self.dict |
642 | data.varhistory = self.varhistory.copy() | ||
643 | data.varhistory.datasmart = data | ||
464 | data.inchistory = self.inchistory.copy() | 644 | data.inchistory = self.inchistory.copy() |
465 | 645 | ||
646 | data._tracking = self._tracking | ||
647 | |||
466 | return data | 648 | return data |
467 | 649 | ||
468 | def expandVarref(self, variable, parents=False): | 650 | def expandVarref(self, variable, parents=False): |
diff --git a/bitbake/lib/bb/parse/ast.py b/bitbake/lib/bb/parse/ast.py index 79e9f7e170..b2657f8044 100644 --- a/bitbake/lib/bb/parse/ast.py +++ b/bitbake/lib/bb/parse/ast.py | |||
@@ -68,7 +68,7 @@ class ExportNode(AstNode): | |||
68 | self.var = var | 68 | self.var = var |
69 | 69 | ||
70 | def eval(self, data): | 70 | def eval(self, data): |
71 | data.setVarFlag(self.var, "export", 1) | 71 | data.setVarFlag(self.var, "export", 1, op = 'exported') |
72 | 72 | ||
73 | class DataNode(AstNode): | 73 | class DataNode(AstNode): |
74 | """ | 74 | """ |
@@ -90,33 +90,53 @@ class DataNode(AstNode): | |||
90 | def eval(self, data): | 90 | def eval(self, data): |
91 | groupd = self.groupd | 91 | groupd = self.groupd |
92 | key = groupd["var"] | 92 | key = groupd["var"] |
93 | loginfo = { | ||
94 | 'variable': key, | ||
95 | 'file': self.filename, | ||
96 | 'line': self.lineno, | ||
97 | } | ||
93 | if "exp" in groupd and groupd["exp"] != None: | 98 | if "exp" in groupd and groupd["exp"] != None: |
94 | data.setVarFlag(key, "export", 1) | 99 | data.setVarFlag(key, "export", 1, op = 'exported', **loginfo) |
100 | |||
101 | op = "set" | ||
95 | if "ques" in groupd and groupd["ques"] != None: | 102 | if "ques" in groupd and groupd["ques"] != None: |
96 | val = self.getFunc(key, data) | 103 | val = self.getFunc(key, data) |
104 | op = "set?" | ||
97 | if val == None: | 105 | if val == None: |
98 | val = groupd["value"] | 106 | val = groupd["value"] |
99 | elif "colon" in groupd and groupd["colon"] != None: | 107 | elif "colon" in groupd and groupd["colon"] != None: |
100 | e = data.createCopy() | 108 | e = data.createCopy() |
101 | bb.data.update_data(e) | 109 | bb.data.update_data(e) |
110 | op = "immediate" | ||
102 | val = e.expand(groupd["value"], key + "[:=]") | 111 | val = e.expand(groupd["value"], key + "[:=]") |
103 | elif "append" in groupd and groupd["append"] != None: | 112 | elif "append" in groupd and groupd["append"] != None: |
113 | op = "append" | ||
104 | val = "%s %s" % ((self.getFunc(key, data) or ""), groupd["value"]) | 114 | val = "%s %s" % ((self.getFunc(key, data) or ""), groupd["value"]) |
105 | elif "prepend" in groupd and groupd["prepend"] != None: | 115 | elif "prepend" in groupd and groupd["prepend"] != None: |
116 | op = "prepend" | ||
106 | val = "%s %s" % (groupd["value"], (self.getFunc(key, data) or "")) | 117 | val = "%s %s" % (groupd["value"], (self.getFunc(key, data) or "")) |
107 | elif "postdot" in groupd and groupd["postdot"] != None: | 118 | elif "postdot" in groupd and groupd["postdot"] != None: |
119 | op = "postdot" | ||
108 | val = "%s%s" % ((self.getFunc(key, data) or ""), groupd["value"]) | 120 | val = "%s%s" % ((self.getFunc(key, data) or ""), groupd["value"]) |
109 | elif "predot" in groupd and groupd["predot"] != None: | 121 | elif "predot" in groupd and groupd["predot"] != None: |
122 | op = "predot" | ||
110 | val = "%s%s" % (groupd["value"], (self.getFunc(key, data) or "")) | 123 | val = "%s%s" % (groupd["value"], (self.getFunc(key, data) or "")) |
111 | else: | 124 | else: |
112 | val = groupd["value"] | 125 | val = groupd["value"] |
113 | 126 | ||
127 | flag = None | ||
114 | if 'flag' in groupd and groupd['flag'] != None: | 128 | if 'flag' in groupd and groupd['flag'] != None: |
115 | data.setVarFlag(key, groupd['flag'], val) | 129 | flag = groupd['flag'] |
116 | elif groupd["lazyques"]: | 130 | elif groupd["lazyques"]: |
117 | data.setVarFlag(key, "defaultval", val) | 131 | flag = "defaultval" |
132 | |||
133 | loginfo['op'] = op | ||
134 | loginfo['detail'] = groupd["value"] | ||
135 | |||
136 | if flag: | ||
137 | data.setVarFlag(key, flag, val, **loginfo) | ||
118 | else: | 138 | else: |
119 | data.setVar(key, val) | 139 | data.setVar(key, val, **loginfo) |
120 | 140 | ||
121 | class MethodNode(AstNode): | 141 | class MethodNode(AstNode): |
122 | def __init__(self, filename, lineno, func_name, body): | 142 | def __init__(self, filename, lineno, func_name, body): |