diff options
author | Brian Harring <ferringb@chromium.org> | 2011-10-13 23:27:22 -0700 |
---|---|---|
committer | Zac Medico <zmedico@gentoo.org> | 2011-10-14 16:50:20 -0700 |
commit | 2ed1cb53cc4158af08c22d466b15b9a9a7767212 (patch) | |
tree | 9c2f87cfccd2f304baaece4b88db48a1f35db847 /pym/portage/eclass_cache.py | |
parent | cache.util: drop completely dead module/code (diff) | |
download | portage-2ed1cb53cc4158af08c22d466b15b9a9a7767212.tar.gz portage-2ed1cb53cc4158af08c22d466b15b9a9a7767212.tar.bz2 portage-2ed1cb53cc4158af08c22d466b15b9a9a7767212.zip |
cache: rewrite to support arbitrary validation method
Specifically, the cache can use any portage supported checksum method,
or use the standard mtime approach. In addition, support controlling
whether or not paths are stored, and generally try to restore some
of the centralization/encapsulation that was in place originally.
(cherry picked from commit bc1aed614fb588f0ade5bcb5d1265a8db0f8d247)
Change-Id: Ic38057e7dbb15063c64a93c99e66e113a7d4c70e
Diffstat (limited to 'pym/portage/eclass_cache.py')
-rw-r--r-- | pym/portage/eclass_cache.py | 66 |
1 files changed, 50 insertions, 16 deletions
diff --git a/pym/portage/eclass_cache.py b/pym/portage/eclass_cache.py index 1374f1d9b..fb187416d 100644 --- a/pym/portage/eclass_cache.py +++ b/pym/portage/eclass_cache.py @@ -6,21 +6,50 @@ __all__ = ["cache"] import stat import sys +import operator from portage.util import normalize_path import errno from portage.exception import PermissionDenied from portage import os +from portage import checksum if sys.hexversion >= 0x3000000: long = int + +class hashed_path(object): + + def __init__(self, location): + self.location = location + + def __getattr__(self, attr): + if attr == 'mtime': + # use stat.ST_MTIME; accessing .st_mtime gets you a float + # depending on the python version, and long(float) introduces + # some rounding issues that aren't present for people using + # the straight c api. + # thus use the defacto python compatibility work around; + # access via index, which gurantees you get the raw long. + self.mtime = obj = os.stat(self.location)[stat.ST_MTIME] + return obj + if not attr.islower(): + # we don't care to allow .mD5 as an alias for .md5 + raise AttributeError(attr) + try: + val = checksum.perform_checksum(self.location, attr.upper())[0] + except KeyError: + raise AttributeError(attr) + setattr(self, attr, val) + return val + + class cache(object): """ Maintains the cache information about eclasses used in ebuild. """ def __init__(self, porttree_root, overlays=[]): - self.eclasses = {} # {"Name": ("location","_mtime_")} + self.eclasses = {} # {"Name": hashed_path} self._eclass_locations = {} # screw with the porttree ordering, w/out having bash inherit match it, and I'll hurt you. @@ -80,14 +109,16 @@ class cache(object): for y in eclass_filenames: if not y.endswith(".eclass"): continue + obj = hashed_path(os.path.join(x, y)) + obj.eclass_dir = x try: - mtime = os.stat(os.path.join(x, y))[stat.ST_MTIME] + mtime = obj.mtime except OSError: continue ys=y[:-eclass_len] if x == self._master_eclass_root: master_eclasses[ys] = mtime - self.eclasses[ys] = (x, mtime) + self.eclasses[ys] = obj self._eclass_locations[ys] = x continue @@ -98,22 +129,25 @@ class cache(object): # so prefer the master entry. continue - self.eclasses[ys] = (x, mtime) + self.eclasses[ys] = obj self._eclass_locations[ys] = x - def is_eclass_data_valid(self, ec_dict): + def validate_and_rewrite_cache(self, ec_dict, chf_type, stores_paths): if not isinstance(ec_dict, dict): - return False - for eclass, tup in ec_dict.items(): - cached_data = self.eclasses.get(eclass, None) - """ Only use the mtime for validation since the probability of a - collision is small and, depending on the cache implementation, the - path may not be specified (cache from rsync mirrors, for example). - """ - if cached_data is None or tup[1] != cached_data[1]: - return False - - return True + return None + our_getter = operator.attrgetter(chf_type) + cache_getter = lambda x:x + if stores_paths: + key_getter = operator.itemgetter(1) + d = {} + for eclass, ec_data in ec_dict.items(): + cached_data = self.eclasses.get(eclass) + if cached_data is None: + return None + if cache_getter(ec_data) != our_getter(cached_data): + return None + d[eclass] = cached_data + return d def get_eclass_data(self, inherits): ec_dict = {} |