diff options
Diffstat (limited to 'bitbake/lib/bb/cache.py')
| -rw-r--r-- | bitbake/lib/bb/cache.py | 369 | 
1 files changed, 196 insertions, 173 deletions
| diff --git a/bitbake/lib/bb/cache.py b/bitbake/lib/bb/cache.py index 707d81c971..3e2f698cf7 100644 --- a/bitbake/lib/bb/cache.py +++ b/bitbake/lib/bb/cache.py | |||
| @@ -30,7 +30,7 @@ | |||
| 30 | 30 | ||
| 31 | import os | 31 | import os | 
| 32 | import logging | 32 | import logging | 
| 33 | from collections import defaultdict | 33 | from collections import defaultdict, namedtuple | 
| 34 | import bb.data | 34 | import bb.data | 
| 35 | import bb.utils | 35 | import bb.utils | 
| 36 | 36 | ||
| @@ -43,7 +43,104 @@ except ImportError: | |||
| 43 | logger.info("Importing cPickle failed. " | 43 | logger.info("Importing cPickle failed. " | 
| 44 | "Falling back to a very slow implementation.") | 44 | "Falling back to a very slow implementation.") | 
| 45 | 45 | ||
| 46 | __cache_version__ = "132" | 46 | __cache_version__ = "133" | 
| 47 | |||
| 48 | recipe_fields = ( | ||
| 49 | 'pn', | ||
| 50 | 'pv', | ||
| 51 | 'pr', | ||
| 52 | 'pe', | ||
| 53 | 'defaultpref', | ||
| 54 | 'depends', | ||
| 55 | 'provides', | ||
| 56 | 'task_deps', | ||
| 57 | 'stamp', | ||
| 58 | 'broken', | ||
| 59 | 'not_world', | ||
| 60 | 'skipped', | ||
| 61 | 'timestamp', | ||
| 62 | 'packages', | ||
| 63 | 'packages_dynamic', | ||
| 64 | 'rdepends', | ||
| 65 | 'rdepends_pkg', | ||
| 66 | 'rprovides', | ||
| 67 | 'rprovides_pkg', | ||
| 68 | 'rrecommends', | ||
| 69 | 'rrecommends_pkg', | ||
| 70 | 'nocache', | ||
| 71 | 'variants', | ||
| 72 | 'file_depends', | ||
| 73 | 'tasks', | ||
| 74 | 'basetaskhashes', | ||
| 75 | 'hashfilename', | ||
| 76 | ) | ||
| 77 | |||
| 78 | |||
| 79 | class RecipeInfo(namedtuple('RecipeInfo', recipe_fields)): | ||
| 80 | __slots__ = () | ||
| 81 | |||
| 82 | @classmethod | ||
| 83 | def listvar(cls, var, metadata): | ||
| 84 | return cls.getvar(var, metadata).split() | ||
| 85 | |||
| 86 | @classmethod | ||
| 87 | def intvar(cls, var, metadata): | ||
| 88 | return int(cls.getvar(var, metadata) or 0) | ||
| 89 | |||
| 90 | @classmethod | ||
| 91 | def depvar(cls, var, metadata): | ||
| 92 | return bb.utils.explode_deps(cls.getvar(var, metadata)) | ||
| 93 | |||
| 94 | @classmethod | ||
| 95 | def pkgvar(cls, var, packages, metadata): | ||
| 96 | return dict((pkg, cls.depvar("%s_%s" % (var, pkg), metadata)) | ||
| 97 | for pkg in packages) | ||
| 98 | |||
| 99 | @classmethod | ||
| 100 | def taskvar(cls, var, tasks, metadata): | ||
| 101 | return dict((task, cls.getvar("%s_task-%s" % (var, task), metadata)) | ||
| 102 | for task in tasks) | ||
| 103 | @classmethod | ||
| 104 | def getvar(cls, var, metadata): | ||
| 105 | return metadata.getVar(var, True) or '' | ||
| 106 | |||
| 107 | @classmethod | ||
| 108 | def from_metadata(cls, filename, metadata): | ||
| 109 | tasks = metadata.getVar('__BBTASKS', False) | ||
| 110 | |||
| 111 | packages = cls.listvar('PACKAGES', metadata) | ||
| 112 | return RecipeInfo( | ||
| 113 | tasks = tasks, | ||
| 114 | basetaskhashes = cls.taskvar('BB_BASEHASH', tasks, metadata), | ||
| 115 | hashfilename = cls.getvar('BB_HASHFILENAME', metadata), | ||
| 116 | |||
| 117 | file_depends = metadata.getVar('__depends', False), | ||
| 118 | task_deps = metadata.getVar('_task_deps', False) or | ||
| 119 | {'tasks': [], 'parents': {}}, | ||
| 120 | variants = cls.listvar('__VARIANTS', metadata) + [''], | ||
| 121 | |||
| 122 | skipped = cls.getvar('__SKIPPED', metadata), | ||
| 123 | timestamp = bb.parse.cached_mtime(filename), | ||
| 124 | packages = packages, | ||
| 125 | pn = cls.getvar('PN', metadata), | ||
| 126 | pe = cls.getvar('PE', metadata), | ||
| 127 | pv = cls.getvar('PV', metadata), | ||
| 128 | pr = cls.getvar('PR', metadata), | ||
| 129 | nocache = cls.getvar('__BB_DONT_CACHE', metadata), | ||
| 130 | defaultpref = cls.intvar('DEFAULT_PREFERENCE', metadata), | ||
| 131 | broken = cls.getvar('BROKEN', metadata), | ||
| 132 | not_world = cls.getvar('EXCLUDE_FROM_WORLD', metadata), | ||
| 133 | stamp = cls.getvar('STAMP', metadata), | ||
| 134 | packages_dynamic = cls.listvar('PACKAGES_DYNAMIC', metadata), | ||
| 135 | depends = cls.depvar('DEPENDS', metadata), | ||
| 136 | provides = cls.depvar('PROVIDES', metadata), | ||
| 137 | rdepends = cls.depvar('RDEPENDS', metadata), | ||
| 138 | rprovides = cls.depvar('RPROVIDES', metadata), | ||
| 139 | rrecommends = cls.depvar('RRECOMMENDS', metadata), | ||
| 140 | rprovides_pkg = cls.pkgvar('RPROVIDES', packages, metadata), | ||
| 141 | rdepends_pkg = cls.pkgvar('RDEPENDS', packages, metadata), | ||
| 142 | rrecommends_pkg = cls.pkgvar('RRECOMMENDS', packages, metadata), | ||
| 143 | ) | ||
| 47 | 144 | ||
| 48 | 145 | ||
| 49 | class Cache(object): | 146 | class Cache(object): | 
| @@ -99,56 +196,6 @@ class Cache(object): | |||
| 99 | if os.path.isfile(self.cachefile): | 196 | if os.path.isfile(self.cachefile): | 
| 100 | logger.info("Out of date cache found, rebuilding...") | 197 | logger.info("Out of date cache found, rebuilding...") | 
| 101 | 198 | ||
| 102 | def getVar(self, var, fn, exp=0): | ||
| 103 | """ | ||
| 104 | Gets the value of a variable | ||
| 105 | (similar to getVar in the data class) | ||
| 106 | |||
| 107 | There are two scenarios: | ||
| 108 | 1. We have cached data - serve from depends_cache[fn] | ||
| 109 | 2. We're learning what data to cache - serve from data | ||
| 110 | backend but add a copy of the data to the cache. | ||
| 111 | """ | ||
| 112 | if fn in self.clean: | ||
| 113 | return self.depends_cache[fn].get(var) | ||
| 114 | |||
| 115 | self.depends_cache.setdefault(fn, {}) | ||
| 116 | |||
| 117 | if fn != self.data_fn: | ||
| 118 | # We're trying to access data in the cache which doesn't exist | ||
| 119 | # yet setData hasn't been called to setup the right access | ||
| 120 | logger.error("data_fn %s and fn %s don't match", self.data_fn, fn) | ||
| 121 | |||
| 122 | self.cacheclean = False | ||
| 123 | result = bb.data.getVar(var, self.data, exp) | ||
| 124 | if result is not None: | ||
| 125 | self.depends_cache[fn][var] = result | ||
| 126 | return result | ||
| 127 | |||
| 128 | def setData(self, virtualfn, fn, data): | ||
| 129 | """ | ||
| 130 | Called to prime bb_cache ready to learn which variables to cache. | ||
| 131 | Will be followed by calls to self.getVar which aren't cached | ||
| 132 | but can be fulfilled from self.data. | ||
| 133 | """ | ||
| 134 | self.data_fn = virtualfn | ||
| 135 | self.data = data | ||
| 136 | |||
| 137 | # Make sure __depends makes the depends_cache | ||
| 138 | # If we're a virtual class we need to make sure all our depends are | ||
| 139 | # appended to the depends of fn. | ||
| 140 | depends = self.getVar("__depends", virtualfn) or set() | ||
| 141 | self.depends_cache.setdefault(fn, {}) | ||
| 142 | if "__depends" not in self.depends_cache[fn] or not self.depends_cache[fn]["__depends"]: | ||
| 143 | self.depends_cache[fn]["__depends"] = depends | ||
| 144 | else: | ||
| 145 | self.depends_cache[fn]["__depends"].update(depends) | ||
| 146 | |||
| 147 | # Make sure the variants always make it into the cache too | ||
| 148 | self.getVar('__VARIANTS', virtualfn, True) | ||
| 149 | |||
| 150 | self.depends_cache[virtualfn]["CACHETIMESTAMP"] = bb.parse.cached_mtime(fn) | ||
| 151 | |||
| 152 | @staticmethod | 199 | @staticmethod | 
| 153 | def virtualfn2realfn(virtualfn): | 200 | def virtualfn2realfn(virtualfn): | 
| 154 | """ | 201 | """ | 
| @@ -193,38 +240,39 @@ class Cache(object): | |||
| 193 | to record the variables accessed. | 240 | to record the variables accessed. | 
| 194 | Return the cache status and whether the file was skipped when parsed | 241 | Return the cache status and whether the file was skipped when parsed | 
| 195 | """ | 242 | """ | 
| 196 | skipped = 0 | 243 | skipped, virtuals = 0, 0 | 
| 197 | virtuals = 0 | ||
| 198 | 244 | ||
| 199 | if fn not in self.checked: | 245 | if fn not in self.checked: | 
| 200 | self.cacheValidUpdate(fn) | 246 | self.cacheValidUpdate(fn) | 
| 201 | 247 | ||
| 202 | if self.cacheValid(fn): | 248 | cached = self.cacheValid(fn) | 
| 203 | multi = self.getVar('__VARIANTS', fn, True) | 249 | if not cached: | 
| 204 | for cls in (multi or "").split() + [""]: | 250 | self.cacheclean = False | 
| 205 | virtualfn = self.realfn2virtual(fn, cls) | 251 | logger.debug(1, "Parsing %s", fn) | 
| 206 | if self.depends_cache[virtualfn].get("__SKIPPED"): | 252 | datastores = self.load_bbfile(fn, appends, cfgData) | 
| 207 | skipped += 1 | 253 | depends = set() | 
| 208 | logger.debug(1, "Skipping %s", virtualfn) | 254 | for variant, data in sorted(datastores.iteritems(), | 
| 209 | continue | 255 | key=lambda i: i[0], | 
| 210 | self.handle_data(virtualfn, cacheData) | 256 | reverse=True): | 
| 211 | virtuals += 1 | 257 | virtualfn = self.realfn2virtual(fn, variant) | 
| 212 | return True, skipped, virtuals | 258 | depends |= (data.getVar("__depends", False) or set()) | 
| 213 | 259 | if depends and not variant: | |
| 214 | logger.debug(1, "Parsing %s", fn) | 260 | data.setVar("__depends", depends) | 
| 215 | 261 | info = RecipeInfo.from_metadata(fn, data) | |
| 216 | bb_data = self.load_bbfile(fn, appends, cfgData) | 262 | self.depends_cache[virtualfn] = info | 
| 217 | 263 | ||
| 218 | for data in bb_data: | 264 | info = self.depends_cache[fn] | 
| 219 | virtualfn = self.realfn2virtual(fn, data) | 265 | for variant in info.variants: | 
| 220 | self.setData(virtualfn, fn, bb_data[data]) | 266 | virtualfn = self.realfn2virtual(fn, variant) | 
| 221 | if self.getVar("__SKIPPED", virtualfn): | 267 | vinfo = self.depends_cache[virtualfn] | 
| 222 | skipped += 1 | 268 | if vinfo.skipped: | 
| 223 | logger.debug(1, "Skipping %s", virtualfn) | 269 | logger.debug(1, "Skipping %s", virtualfn) | 
| 270 | skipped += 1 | ||
| 224 | else: | 271 | else: | 
| 225 | self.handle_data(virtualfn, cacheData) | 272 | cacheData.add_from_recipeinfo(virtualfn, vinfo) | 
| 226 | virtuals += 1 | 273 | virtuals += 1 | 
| 227 | return False, skipped, virtuals | 274 | |
| 275 | return cached, skipped, virtuals | ||
| 228 | 276 | ||
| 229 | def cacheValid(self, fn): | 277 | def cacheValid(self, fn): | 
| 230 | """ | 278 | """ | 
| @@ -266,14 +314,15 @@ class Cache(object): | |||
| 266 | self.remove(fn) | 314 | self.remove(fn) | 
| 267 | return False | 315 | return False | 
| 268 | 316 | ||
| 317 | info = self.depends_cache[fn] | ||
| 269 | # Check the file's timestamp | 318 | # Check the file's timestamp | 
| 270 | if mtime != self.getVar("CACHETIMESTAMP", fn, True): | 319 | if mtime != info.timestamp: | 
| 271 | logger.debug(2, "Cache: %s changed", fn) | 320 | logger.debug(2, "Cache: %s changed", fn) | 
| 272 | self.remove(fn) | 321 | self.remove(fn) | 
| 273 | return False | 322 | return False | 
| 274 | 323 | ||
| 275 | # Check dependencies are still valid | 324 | # Check dependencies are still valid | 
| 276 | depends = self.getVar("__depends", fn, True) | 325 | depends = info.file_depends | 
| 277 | if depends: | 326 | if depends: | 
| 278 | for f, old_mtime in depends: | 327 | for f, old_mtime in depends: | 
| 279 | fmtime = bb.parse.cached_mtime_noerror(f) | 328 | fmtime = bb.parse.cached_mtime_noerror(f) | 
| @@ -290,20 +339,17 @@ class Cache(object): | |||
| 290 | self.remove(fn) | 339 | self.remove(fn) | 
| 291 | return False | 340 | return False | 
| 292 | 341 | ||
| 293 | self.clean.add(fn) | ||
| 294 | invalid = False | 342 | invalid = False | 
| 295 | # Mark extended class data as clean too | 343 | for cls in info.variants: | 
| 296 | multi = self.getVar('__VARIANTS', fn, True) | ||
| 297 | for cls in (multi or "").split(): | ||
| 298 | virtualfn = self.realfn2virtual(fn, cls) | 344 | virtualfn = self.realfn2virtual(fn, cls) | 
| 299 | self.clean.add(virtualfn) | 345 | self.clean.add(virtualfn) | 
| 300 | if not virtualfn in self.depends_cache: | 346 | if virtualfn not in self.depends_cache: | 
| 301 | logger.debug(2, "Cache: %s is not cached", virtualfn) | 347 | logger.debug(2, "Cache: %s is not cached", virtualfn) | 
| 302 | invalid = True | 348 | invalid = True | 
| 303 | 349 | ||
| 304 | # If any one of the variants is not present, mark as invalid for all | 350 | # If any one of the variants is not present, mark as invalid for all | 
| 305 | if invalid: | 351 | if invalid: | 
| 306 | for cls in (multi or "").split(): | 352 | for cls in info.variants: | 
| 307 | virtualfn = self.realfn2virtual(fn, cls) | 353 | virtualfn = self.realfn2virtual(fn, cls) | 
| 308 | if virtualfn in self.clean: | 354 | if virtualfn in self.clean: | 
| 309 | logger.debug(2, "Cache: Removing %s from cache", virtualfn) | 355 | logger.debug(2, "Cache: Removing %s from cache", virtualfn) | 
| @@ -332,7 +378,6 @@ class Cache(object): | |||
| 332 | Save the cache | 378 | Save the cache | 
| 333 | Called from the parser when complete (or exiting) | 379 | Called from the parser when complete (or exiting) | 
| 334 | """ | 380 | """ | 
| 335 | import copy | ||
| 336 | 381 | ||
| 337 | if not self.has_cache: | 382 | if not self.has_cache: | 
| 338 | return | 383 | return | 
| @@ -345,13 +390,12 @@ class Cache(object): | |||
| 345 | version_data['CACHE_VER'] = __cache_version__ | 390 | version_data['CACHE_VER'] = __cache_version__ | 
| 346 | version_data['BITBAKE_VER'] = bb.__version__ | 391 | version_data['BITBAKE_VER'] = bb.__version__ | 
| 347 | 392 | ||
| 348 | cache_data = copy.copy(self.depends_cache) | 393 | cache_data = dict(self.depends_cache) | 
| 349 | for fn in self.depends_cache: | 394 | for fn, info in self.depends_cache.iteritems(): | 
| 350 | if '__BB_DONT_CACHE' in self.depends_cache[fn] and self.depends_cache[fn]['__BB_DONT_CACHE']: | 395 | if info.nocache: | 
| 351 | logger.debug(2, "Not caching %s, marked as not cacheable", fn) | 396 | logger.debug(2, "Not caching %s, marked as not cacheable", fn) | 
| 352 | del cache_data[fn] | 397 | del cache_data[fn] | 
| 353 | elif ('PV' in self.depends_cache[fn] and | 398 | elif info.pv and 'SRCREVINACTION' in info.pv: | 
| 354 | 'SRCREVINACTION' in self.depends_cache[fn]['PV']): | ||
| 355 | logger.error("Not caching %s as it had SRCREVINACTION in PV. " | 399 | logger.error("Not caching %s as it had SRCREVINACTION in PV. " | 
| 356 | "Please report this bug", fn) | 400 | "Please report this bug", fn) | 
| 357 | del cache_data[fn] | 401 | del cache_data[fn] | 
| @@ -364,90 +408,14 @@ class Cache(object): | |||
| 364 | def mtime(cachefile): | 408 | def mtime(cachefile): | 
| 365 | return bb.parse.cached_mtime_noerror(cachefile) | 409 | return bb.parse.cached_mtime_noerror(cachefile) | 
| 366 | 410 | ||
| 367 | def handle_data(self, file_name, cacheData): | 411 | def add(self, file_name, data, cacheData): | 
| 368 | """ | 412 | """ | 
| 369 | Save data we need into the cache | 413 | Save data we need into the cache | 
| 370 | """ | 414 | """ | 
| 371 | 415 | realfn = self.virtualfn2realfn(file_name)[0] | |
| 372 | pn = self.getVar('PN', file_name, True) | 416 | info = RecipeInfo.from_metadata(realfn, data) | 
| 373 | pe = self.getVar('PE', file_name, True) or "0" | 417 | self.depends_cache[file_name] = info | 
| 374 | pv = self.getVar('PV', file_name, True) | 418 | cacheData.add_from_recipeinfo(file_name, info) | 
| 375 | if 'SRCREVINACTION' in pv: | ||
| 376 | logger.info("Found SRCREVINACTION in PV (%s) or %s. Please report this bug.", pv, file_name) | ||
| 377 | pr = self.getVar('PR', file_name, True) | ||
| 378 | dp = int(self.getVar('DEFAULT_PREFERENCE', file_name, True) or "0") | ||
| 379 | depends = bb.utils.explode_deps(self.getVar("DEPENDS", file_name, True) or "") | ||
| 380 | packages = (self.getVar('PACKAGES', file_name, True) or "").split() | ||
| 381 | packages_dynamic = (self.getVar('PACKAGES_DYNAMIC', file_name, True) or "").split() | ||
| 382 | rprovides = (self.getVar("RPROVIDES", file_name, True) or "").split() | ||
| 383 | |||
| 384 | cacheData.task_deps[file_name] = self.getVar("_task_deps", file_name) | ||
| 385 | |||
| 386 | # build PackageName to FileName lookup table | ||
| 387 | cacheData.pkg_pn[pn].append(file_name) | ||
| 388 | |||
| 389 | cacheData.stamp[file_name] = self.getVar('STAMP', file_name, True) | ||
| 390 | |||
| 391 | cacheData.tasks[file_name] = self.getVar('__BBTASKS', file_name, True) | ||
| 392 | for t in cacheData.tasks[file_name]: | ||
| 393 | cacheData.basetaskhash[file_name + "." + t] = self.getVar("BB_BASEHASH_task-%s" % t, file_name, True) | ||
| 394 | |||
| 395 | # build FileName to PackageName lookup table | ||
| 396 | cacheData.pkg_fn[file_name] = pn | ||
| 397 | cacheData.pkg_pepvpr[file_name] = (pe, pv, pr) | ||
| 398 | cacheData.pkg_dp[file_name] = dp | ||
| 399 | |||
| 400 | provides = [pn] | ||
| 401 | for provide in (self.getVar("PROVIDES", file_name, True) or "").split(): | ||
| 402 | if provide not in provides: | ||
| 403 | provides.append(provide) | ||
| 404 | |||
| 405 | # Build forward and reverse provider hashes | ||
| 406 | # Forward: virtual -> [filenames] | ||
| 407 | # Reverse: PN -> [virtuals] | ||
| 408 | cacheData.fn_provides[file_name] = provides | ||
| 409 | for provide in provides: | ||
| 410 | cacheData.providers[provide].append(file_name) | ||
| 411 | if not provide in cacheData.pn_provides[pn]: | ||
| 412 | cacheData.pn_provides[pn].append(provide) | ||
| 413 | |||
| 414 | for dep in depends: | ||
| 415 | if not dep in cacheData.deps[file_name]: | ||
| 416 | cacheData.deps[file_name].append(dep) | ||
| 417 | if not dep in cacheData.all_depends: | ||
| 418 | cacheData.all_depends.append(dep) | ||
| 419 | |||
| 420 | # Build reverse hash for PACKAGES, so runtime dependencies | ||
| 421 | # can be be resolved (RDEPENDS, RRECOMMENDS etc.) | ||
| 422 | for package in packages: | ||
| 423 | cacheData.packages[package].append(file_name) | ||
| 424 | rprovides += (self.getVar("RPROVIDES_%s" % package, file_name, 1) or "").split() | ||
| 425 | |||
| 426 | for package in packages_dynamic: | ||
| 427 | cacheData.packages_dynamic[package].append(file_name) | ||
| 428 | |||
| 429 | for rprovide in rprovides: | ||
| 430 | cacheData.rproviders[rprovide].append(file_name) | ||
| 431 | |||
| 432 | # Build hash of runtime depends and rececommends | ||
| 433 | rdepends = bb.utils.explode_deps(self.getVar('RDEPENDS', file_name, True) or "") | ||
| 434 | rrecommends = bb.utils.explode_deps(self.getVar('RRECOMMENDS', file_name, True) or "") | ||
| 435 | for package in packages + [pn]: | ||
| 436 | rdeps_pkg = bb.utils.explode_deps(self.getVar('RDEPENDS_%s' % package, file_name, True) or "") | ||
| 437 | cacheData.rundeps[file_name][package] = rdepends + rdeps_pkg | ||
| 438 | rrecs_pkg = bb.utils.explode_deps(self.getVar('RDEPENDS_%s' % package, file_name, True) or "") | ||
| 439 | cacheData.runrecs[file_name][package] = rrecommends + rrecs_pkg | ||
| 440 | |||
| 441 | # Collect files we may need for possible world-dep | ||
| 442 | # calculations | ||
| 443 | if not self.getVar('BROKEN', file_name, True) and not self.getVar('EXCLUDE_FROM_WORLD', file_name, True): | ||
| 444 | cacheData.possible_world.append(file_name) | ||
| 445 | |||
| 446 | cacheData.hashfn[file_name] = self.getVar('BB_HASHFILENAME', file_name, True) | ||
| 447 | |||
| 448 | # Touch this to make sure its in the cache | ||
| 449 | self.getVar('__BB_DONT_CACHE', file_name, True) | ||
| 450 | self.getVar('__VARIANTS', file_name, True) | ||
| 451 | 419 | ||
| 452 | @staticmethod | 420 | @staticmethod | 
| 453 | def load_bbfile(bbfile, appends, config): | 421 | def load_bbfile(bbfile, appends, config): | 
| @@ -514,7 +482,6 @@ class CacheData(object): | |||
| 514 | def __init__(self): | 482 | def __init__(self): | 
| 515 | """ | 483 | """ | 
| 516 | Direct cache variables | 484 | Direct cache variables | 
| 517 | (from Cache.handle_data) | ||
| 518 | """ | 485 | """ | 
| 519 | self.providers = defaultdict(list) | 486 | self.providers = defaultdict(list) | 
| 520 | self.rproviders = defaultdict(list) | 487 | self.rproviders = defaultdict(list) | 
| @@ -547,3 +514,59 @@ class CacheData(object): | |||
| 547 | self.world_target = set() | 514 | self.world_target = set() | 
| 548 | self.bbfile_priority = {} | 515 | self.bbfile_priority = {} | 
| 549 | self.bbfile_config_priorities = [] | 516 | self.bbfile_config_priorities = [] | 
| 517 | |||
| 518 | def add_from_recipeinfo(self, fn, info): | ||
| 519 | self.task_deps[fn] = info.task_deps | ||
| 520 | self.pkg_fn[fn] = info.pn | ||
| 521 | self.pkg_pn[info.pn].append(fn) | ||
| 522 | self.pkg_pepvpr[fn] = (info.pe, info.pv, info.pr) | ||
| 523 | self.pkg_dp[fn] = info.defaultpref | ||
| 524 | self.stamp[fn] = info.stamp | ||
| 525 | |||
| 526 | provides = [info.pn] | ||
| 527 | for provide in info.provides: | ||
| 528 | if provide not in provides: | ||
| 529 | provides.append(provide) | ||
| 530 | self.fn_provides[fn] = provides | ||
| 531 | |||
| 532 | for provide in provides: | ||
| 533 | self.providers[provide].append(fn) | ||
| 534 | if provide not in self.pn_provides[info.pn]: | ||
| 535 | self.pn_provides[info.pn].append(provide) | ||
| 536 | |||
| 537 | for dep in info.depends: | ||
| 538 | if dep not in self.deps[fn]: | ||
| 539 | self.deps[fn].append(dep) | ||
| 540 | if dep not in self.all_depends: | ||
| 541 | self.all_depends.append(dep) | ||
| 542 | |||
| 543 | rprovides = info.rprovides | ||
| 544 | for package in info.packages: | ||
| 545 | self.packages[package].append(fn) | ||
| 546 | rprovides += info.rprovides_pkg[package] | ||
| 547 | |||
| 548 | for package in info.packages_dynamic: | ||
| 549 | self.packages_dynamic[package].append(fn) | ||
| 550 | |||
| 551 | for rprovide in rprovides: | ||
| 552 | self.rproviders[rprovide].append(fn) | ||
| 553 | |||
| 554 | # Build hash of runtime depends and rececommends | ||
| 555 | for package in info.packages + [info.pn]: | ||
| 556 | rundeps, runrecs = list(info.rdepends), list(info.rrecommends) | ||
| 557 | if package in info.packages: | ||
| 558 | rundeps += info.rdepends_pkg[package] | ||
| 559 | runrecs += info.rrecommends_pkg[package] | ||
| 560 | self.rundeps[fn][package] = rundeps | ||
| 561 | self.runrecs[fn][package] = runrecs | ||
| 562 | |||
| 563 | # Collect files we may need for possible world-dep | ||
| 564 | # calculations | ||
| 565 | if not info.broken and not info.not_world: | ||
| 566 | self.possible_world.append(fn) | ||
| 567 | |||
| 568 | self.hashfn[fn] = info.hashfilename | ||
| 569 | |||
| 570 | for task, taskhash in info.basetaskhashes.iteritems(): | ||
| 571 | identifier = '%s.%s' % (fn, task) | ||
| 572 | self.basetaskhash[identifier] = taskhash | ||
