diff options
Diffstat (limited to 'bitbake/lib/bb/data_smart.py')
| -rw-r--r-- | bitbake/lib/bb/data_smart.py | 158 |
1 files changed, 36 insertions, 122 deletions
diff --git a/bitbake/lib/bb/data_smart.py b/bitbake/lib/bb/data_smart.py index 52f391dec1..fbd4167fe4 100644 --- a/bitbake/lib/bb/data_smart.py +++ b/bitbake/lib/bb/data_smart.py | |||
| @@ -8,7 +8,7 @@ BitBake build tools. | |||
| 8 | 8 | ||
| 9 | Copyright (C) 2003, 2004 Chris Larson | 9 | Copyright (C) 2003, 2004 Chris Larson |
| 10 | Copyright (C) 2004, 2005 Seb Frankengul | 10 | Copyright (C) 2004, 2005 Seb Frankengul |
| 11 | Copyright (C) 2005 Holger Hans Peter Freyther | 11 | Copyright (C) 2005, 2006 Holger Hans Peter Freyther |
| 12 | Copyright (C) 2005 Uli Luckas | 12 | Copyright (C) 2005 Uli Luckas |
| 13 | Copyright (C) 2005 ROAD GmbH | 13 | Copyright (C) 2005 ROAD GmbH |
| 14 | 14 | ||
| @@ -29,7 +29,8 @@ Based on functions from the base bb module, Copyright 2003 Holger Schurig | |||
| 29 | """ | 29 | """ |
| 30 | 30 | ||
| 31 | import copy, os, re, sys, time, types | 31 | import copy, os, re, sys, time, types |
| 32 | from bb import note, debug, fatal, utils | 32 | from bb import note, debug, error, fatal, utils, methodpool |
| 33 | from sets import Set | ||
| 33 | 34 | ||
| 34 | try: | 35 | try: |
| 35 | import cPickle as pickle | 36 | import cPickle as pickle |
| @@ -37,9 +38,8 @@ except ImportError: | |||
| 37 | import pickle | 38 | import pickle |
| 38 | print "NOTE: Importing cPickle failed. Falling back to a very slow implementation." | 39 | print "NOTE: Importing cPickle failed. Falling back to a very slow implementation." |
| 39 | 40 | ||
| 40 | 41 | __setvar_keyword__ = ["_append","_prepend"] | |
| 41 | __setvar_keyword__ = ["_append","_prepend","_delete"] | 42 | __setvar_regexp__ = re.compile('(?P<base>.*?)(?P<keyword>_append|_prepend)(_(?P<add>.*))?') |
| 42 | __setvar_regexp__ = re.compile('(?P<base>.*?)(?P<keyword>_append|_prepend|_delete)(_(?P<add>.*))?') | ||
| 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 | ||
| @@ -48,6 +48,10 @@ class DataSmart: | |||
| 48 | def __init__(self): | 48 | def __init__(self): |
| 49 | self.dict = {} | 49 | self.dict = {} |
| 50 | 50 | ||
| 51 | # cookie monster tribute | ||
| 52 | self._special_values = {} | ||
| 53 | self._seen_overrides = {} | ||
| 54 | |||
| 51 | def expand(self,s, varname): | 55 | def expand(self,s, varname): |
| 52 | def var_sub(match): | 56 | def var_sub(match): |
| 53 | key = match.group()[2:-1] | 57 | key = match.group()[2:-1] |
| @@ -78,8 +82,7 @@ class DataSmart: | |||
| 78 | s = __expand_python_regexp__.sub(python_sub, s) | 82 | s = __expand_python_regexp__.sub(python_sub, s) |
| 79 | if s == olds: break | 83 | if s == olds: break |
| 80 | if type(s) is not types.StringType: # sanity check | 84 | if type(s) is not types.StringType: # sanity check |
| 81 | import bb | 85 | error('expansion of %s returned non-string %s' % (olds, s)) |
| 82 | bb.error('expansion of %s returned non-string %s' % (olds, s)) | ||
| 83 | except KeyboardInterrupt: | 86 | except KeyboardInterrupt: |
| 84 | raise | 87 | raise |
| 85 | except: | 88 | except: |
| @@ -91,18 +94,6 @@ class DataSmart: | |||
| 91 | if not var in self.dict: | 94 | if not var in self.dict: |
| 92 | self.dict[var] = {} | 95 | self.dict[var] = {} |
| 93 | 96 | ||
| 94 | def pickle_prep(self, cfg): | ||
| 95 | if "_data" in self.dict: | ||
| 96 | if self.dict["_data"] == cfg: | ||
| 97 | self.dict["_data"] = "cfg"; | ||
| 98 | else: # this is an unknown array for the moment | ||
| 99 | pass | ||
| 100 | |||
| 101 | def unpickle_prep(self, cfg): | ||
| 102 | if "_data" in self.dict: | ||
| 103 | if self.dict["_data"] == "cfg": | ||
| 104 | self.dict["_data"] = cfg; | ||
| 105 | |||
| 106 | def _findVar(self,var): | 97 | def _findVar(self,var): |
| 107 | _dest = self.dict | 98 | _dest = self.dict |
| 108 | 99 | ||
| @@ -116,14 +107,6 @@ class DataSmart: | |||
| 116 | return _dest[var] | 107 | return _dest[var] |
| 117 | return None | 108 | return None |
| 118 | 109 | ||
| 119 | def _copyVar(self,var,name): | ||
| 120 | local_var = self._findVar(var) | ||
| 121 | if local_var: | ||
| 122 | self.dict[name] = copy.copy(local_var) | ||
| 123 | else: | ||
| 124 | debug(1,"Warning, _copyVar %s to %s, %s does not exists" % (var,name,var)) | ||
| 125 | |||
| 126 | |||
| 127 | def _makeShadowCopy(self, var): | 110 | def _makeShadowCopy(self, var): |
| 128 | if var in self.dict: | 111 | if var in self.dict: |
| 129 | return | 112 | return |
| @@ -142,11 +125,20 @@ class DataSmart: | |||
| 142 | keyword = match.group("keyword") | 125 | keyword = match.group("keyword") |
| 143 | override = match.group('add') | 126 | override = match.group('add') |
| 144 | l = self.getVarFlag(base, keyword) or [] | 127 | l = self.getVarFlag(base, keyword) or [] |
| 145 | if override == 'delete': | ||
| 146 | if l.count([value, None]): | ||
| 147 | del l[l.index([value, None])] | ||
| 148 | l.append([value, override]) | 128 | l.append([value, override]) |
| 149 | self.setVarFlag(base, match.group("keyword"), l) | 129 | self.setVarFlag(base, keyword, l) |
| 130 | |||
| 131 | # pay the cookie monster | ||
| 132 | try: | ||
| 133 | self._special_values[keyword].add( base ) | ||
| 134 | except: | ||
| 135 | self._special_values[keyword] = Set() | ||
| 136 | self._special_values[keyword].add( base ) | ||
| 137 | |||
| 138 | # SRC_URI_append_simpad is both a flag and a override | ||
| 139 | #if not override in self._seen_overrides: | ||
| 140 | # self._seen_overrides[override] = Set() | ||
| 141 | #self._seen_overrides[override].add( base ) | ||
| 150 | return | 142 | return |
| 151 | 143 | ||
| 152 | if not var in self.dict: | 144 | if not var in self.dict: |
| @@ -155,6 +147,13 @@ class DataSmart: | |||
| 155 | self.delVarFlag(var, 'matchesenv') | 147 | self.delVarFlag(var, 'matchesenv') |
| 156 | self.setVarFlag(var, 'export', 1) | 148 | self.setVarFlag(var, 'export', 1) |
| 157 | 149 | ||
| 150 | # more cookies for the cookie monster | ||
| 151 | if '_' in var: | ||
| 152 | override = var[var.rfind('_')+1:] | ||
| 153 | if not override in self._seen_overrides: | ||
| 154 | self._seen_overrides[override] = Set() | ||
| 155 | self._seen_overrides[override].add( var ) | ||
| 156 | |||
| 158 | # setting var | 157 | # setting var |
| 159 | self.dict[var]["content"] = value | 158 | self.dict[var]["content"] = value |
| 160 | 159 | ||
| @@ -237,6 +236,8 @@ class DataSmart: | |||
| 237 | # we really want this to be a DataSmart... | 236 | # we really want this to be a DataSmart... |
| 238 | data = DataSmart() | 237 | data = DataSmart() |
| 239 | data.dict["_data"] = self.dict | 238 | data.dict["_data"] = self.dict |
| 239 | data._seen_overrides = copy.deepcopy(self._seen_overrides) | ||
| 240 | data._special_values = copy.deepcopy(self._special_values) | ||
| 240 | 241 | ||
| 241 | return data | 242 | return data |
| 242 | 243 | ||
| @@ -254,98 +255,11 @@ class DataSmart: | |||
| 254 | return keytab.keys() | 255 | return keytab.keys() |
| 255 | 256 | ||
| 256 | def __getitem__(self,item): | 257 | def __getitem__(self,item): |
| 257 | start = self.dict | 258 | #print "Warning deprecated" |
| 258 | while start: | 259 | return self.getVar(item, False) |
| 259 | if item in start: | ||
| 260 | return start[item] | ||
| 261 | elif "_data" in start: | ||
| 262 | start = start["_data"] | ||
| 263 | else: | ||
| 264 | start = None | ||
| 265 | return None | ||
| 266 | 260 | ||
| 267 | def __setitem__(self,var,data): | 261 | def __setitem__(self,var,data): |
| 268 | self._makeShadowCopy(var) | 262 | #print "Warning deprecated" |
| 269 | self.dict[var] = data | 263 | self.setVar(var,data) |
| 270 | |||
| 271 | |||
| 272 | class DataSmartPackage(DataSmart): | ||
| 273 | """ | ||
| 274 | Persistent Data Storage | ||
| 275 | """ | ||
| 276 | def sanitize_filename(bbfile): | ||
| 277 | return bbfile.replace( '/', '_' ) | ||
| 278 | sanitize_filename = staticmethod(sanitize_filename) | ||
| 279 | 264 | ||
| 280 | def unpickle(self): | ||
| 281 | """ | ||
| 282 | Restore the dict from memory | ||
| 283 | """ | ||
| 284 | cache_bbfile = self.sanitize_filename(self.bbfile) | ||
| 285 | p = pickle.Unpickler( file("%s/%s"%(self.cache,cache_bbfile),"rb")) | ||
| 286 | self.dict = p.load() | ||
| 287 | self.unpickle_prep() | ||
| 288 | funcstr = self.getVar('__functions__', 0) | ||
| 289 | if funcstr: | ||
| 290 | comp = utils.better_compile(funcstr, "<pickled>", self.bbfile) | ||
| 291 | utils.better_exec(comp, __builtins__, funcstr, self.bbfile) | ||
| 292 | |||
| 293 | def linkDataSet(self): | ||
| 294 | if not self.parent == None: | ||
| 295 | # assume parent is a DataSmartInstance | ||
| 296 | self.dict["_data"] = self.parent.dict | ||
| 297 | |||
| 298 | |||
| 299 | def __init__(self,cache,name,clean,parent): | ||
| 300 | """ | ||
| 301 | Construct a persistent data instance | ||
| 302 | """ | ||
| 303 | #Initialize the dictionary | ||
| 304 | DataSmart.__init__(self) | ||
| 305 | |||
| 306 | self.cache = cache | ||
| 307 | self.bbfile = os.path.abspath( name ) | ||
| 308 | self.parent = parent | ||
| 309 | |||
| 310 | # Either unpickle the data or do copy on write | ||
| 311 | if clean: | ||
| 312 | self.linkDataSet() | ||
| 313 | else: | ||
| 314 | self.unpickle() | ||
| 315 | |||
| 316 | def commit(self, mtime): | ||
| 317 | """ | ||
| 318 | Save the package to a permanent storage | ||
| 319 | """ | ||
| 320 | self.pickle_prep() | ||
| 321 | |||
| 322 | cache_bbfile = self.sanitize_filename(self.bbfile) | ||
| 323 | p = pickle.Pickler(file("%s/%s" %(self.cache,cache_bbfile), "wb" ), -1 ) | ||
| 324 | p.dump( self.dict ) | ||
| 325 | |||
| 326 | self.unpickle_prep() | ||
| 327 | 265 | ||
| 328 | def mtime(cache,bbfile): | ||
| 329 | cache_bbfile = DataSmartPackage.sanitize_filename(bbfile) | ||
| 330 | try: | ||
| 331 | return os.stat( "%s/%s" % (cache,cache_bbfile) )[8] | ||
| 332 | except OSError: | ||
| 333 | return 0 | ||
| 334 | mtime = staticmethod(mtime) | ||
| 335 | |||
| 336 | def pickle_prep(self): | ||
| 337 | """ | ||
| 338 | If self.dict contains a _data key and it is a configuration | ||
| 339 | we will remember we had a configuration instance attached | ||
| 340 | """ | ||
| 341 | if "_data" in self.dict: | ||
| 342 | if self.dict["_data"] == self.parent: | ||
| 343 | dest["_data"] = "cfg" | ||
| 344 | |||
| 345 | def unpickle_prep(self): | ||
| 346 | """ | ||
| 347 | If we had a configuration instance attached, we will reattach it | ||
| 348 | """ | ||
| 349 | if "_data" in self.dict: | ||
| 350 | if self.dict["_data"] == "cfg": | ||
| 351 | self.dict["_data"] = self.parent | ||
