diff options
author | Zac Medico <zmedico@gentoo.org> | 2012-06-22 02:59:53 -0700 |
---|---|---|
committer | Zac Medico <zmedico@gentoo.org> | 2012-06-22 02:59:53 -0700 |
commit | e4ba8f36e6a4624f4fec61c7ce8bed0e3bd2fa01 (patch) | |
tree | bc90757f7887bf571d98617d1178ff2be3c90ff1 /pym/portage/dep | |
parent | fakedbapi: use _pkg_str more (diff) | |
download | portage-e4ba8f36e6a4624f4fec61c7ce8bed0e3bd2fa01.tar.gz portage-e4ba8f36e6a4624f4fec61c7ce8bed0e3bd2fa01.tar.bz2 portage-e4ba8f36e6a4624f4fec61c7ce8bed0e3bd2fa01.zip |
Add experimental EAPI 4-slot-abi support.
Refer to 4-slot-abi.docbook for a full description.
Diffstat (limited to 'pym/portage/dep')
-rw-r--r-- | pym/portage/dep/__init__.py | 126 | ||||
-rw-r--r-- | pym/portage/dep/_slot_abi.py | 92 |
2 files changed, 205 insertions, 13 deletions
diff --git a/pym/portage/dep/__init__.py b/pym/portage/dep/__init__.py index 23bafa892..557c92b42 100644 --- a/pym/portage/dep/__init__.py +++ b/pym/portage/dep/__init__.py @@ -47,7 +47,8 @@ _internal_warnings = False # It must not begin with a hyphen or a dot. _slot_separator = ":" _slot = r'([\w+][\w+.-]*)' -_slot_re = re.compile('^' + _slot + '$', re.VERBOSE) +# loosly match SLOT, which may have an optional ABI part +_slot_loose = r'([\w+./*=-]+)' _use = r'\[.*\]' _op = r'([=~]|[><]=?)' @@ -58,8 +59,49 @@ _repo = r'(?:' + _repo_separator + '(' + _repo_name + ')' + ')?' _extended_cat = r'[\w+*][\w+.*-]*' +_slot_re_cache = {} + def _get_slot_re(eapi_attrs): - return _slot_re + cache_key = eapi_attrs.slot_abi + slot_re = _slot_re_cache.get(cache_key) + if slot_re is not None: + return slot_re + + if eapi_attrs.slot_abi: + slot_re = _slot + r'(/' + _slot + r'=?)?' + else: + slot_re = _slot + + slot_re = re.compile('^' + slot_re + '$', re.VERBOSE) + + _slot_re_cache[cache_key] = slot_re + return slot_re + +_slot_dep_re_cache = {} + +def _get_slot_dep_re(eapi_attrs): + cache_key = eapi_attrs.slot_abi + slot_re = _slot_dep_re_cache.get(cache_key) + if slot_re is not None: + return slot_re + + if eapi_attrs.slot_abi: + slot_re = _slot + r'?(\*|=|/' + _slot + r'=?)?' + else: + slot_re = _slot + + slot_re = re.compile('^' + slot_re + '$', re.VERBOSE) + + _slot_dep_re_cache[cache_key] = slot_re + return slot_re + +def _match_slot(atom, pkg): + if pkg.slot == atom.slot: + if not atom.slot_abi: + return True + elif atom.slot_abi == pkg.slot_abi: + return True + return False _atom_re_cache = {} @@ -80,7 +122,7 @@ def _get_atom_re(eapi_attrs): '(?P<op>' + _op + cpv_re + ')|' + '(?P<star>=' + cpv_re + r'\*)|' + '(?P<simple>' + cp_re + '))' + - '(' + _slot_separator + _slot + ')?' + + '(' + _slot_separator + _slot_loose + ')?' + _repo + ')(' + _use + ')?$', re.VERBOSE) _atom_re_cache[cache_key] = atom_re @@ -101,7 +143,7 @@ def _get_atom_wildcard_re(eapi_attrs): atom_re = re.compile(r'(?P<simple>(' + _extended_cat + r')/(' + pkg_re + - r'))(:(?P<slot>' + _slot + r'))?(' + + r'))(:(?P<slot>' + _slot_loose + r'))?(' + _repo_separator + r'(?P<repo>' + _repo_name + r'))?$') _atom_wildcard_re_cache[cache_key] = atom_re @@ -1256,7 +1298,34 @@ class Atom(_unicode): self.__dict__['cpv'] = cpv self.__dict__['version'] = None self.__dict__['repo'] = repo - self.__dict__['slot'] = slot + if slot is None: + self.__dict__['slot'] = None + self.__dict__['slot_abi'] = None + self.__dict__['slot_abi_op'] = None + else: + slot_re = _get_slot_dep_re(eapi_attrs) + slot_match = slot_re.match(slot) + if slot_match is None: + raise InvalidAtom(self) + if eapi_attrs.slot_abi: + self.__dict__['slot'] = slot_match.group(1) + slot_abi = slot_match.group(2) + if slot_abi is not None: + slot_abi = slot_abi.lstrip("/") + if slot_abi in ("*", "="): + self.__dict__['slot_abi'] = None + self.__dict__['slot_abi_op'] = slot_abi + else: + slot_abi_op = None + if slot_abi is not None and slot_abi[-1:] == "=": + slot_abi_op = slot_abi[-1:] + slot_abi = slot_abi[:-1] + self.__dict__['slot_abi'] = slot_abi + self.__dict__['slot_abi_op'] = slot_abi_op + else: + self.__dict__['slot'] = slot + self.__dict__['slot_abi'] = None + self.__dict__['slot_abi_op'] = None self.__dict__['operator'] = op self.__dict__['extended_syntax'] = extended_syntax @@ -1330,6 +1399,15 @@ class Atom(_unicode): % (eapi, self), category='EAPI.incompatible') @property + def slot_abi_built(self): + """ + Returns True if slot_abi_op == "=" and slot_abi is not None. + NOTE: foo/bar:2= is unbuilt and returns False, whereas foo/bar:2/2= + is built and returns True. + """ + return self.slot_abi_op == "=" and self.slot_abi is not None + + @property def without_repo(self): if self.repo is None: return self @@ -1338,9 +1416,14 @@ class Atom(_unicode): @property def without_slot(self): - if self.slot is None: + if self.slot is None and self.slot_abi_op is None: return self - return Atom(self.replace(_slot_separator + self.slot, '', 1), + atom = remove_slot(self) + if self.repo is not None: + atom += _repo_separator + self.repo + if self.use is not None: + atom += _unicode(self.use) + return Atom(atom, allow_repo=True, allow_wildcard=True) def with_repo(self, repo): @@ -2077,16 +2160,33 @@ def match_from_list(mydep, candidate_list): else: raise KeyError(_("Unknown operator: %s") % mydep) - if slot is not None and not mydep.extended_syntax: + if mydep.slot is not None and not mydep.extended_syntax: candidate_list = mylist mylist = [] for x in candidate_list: - xslot = getattr(x, "slot", False) - if xslot is False: + x_pkg = None + try: + x.cpv + except AttributeError: xslot = dep_getslot(x) - if xslot is not None and xslot != slot: - continue - mylist.append(x) + if xslot is not None: + try: + x_pkg = _pkg_str(remove_slot(x), slot=xslot) + except InvalidData: + continue + else: + x_pkg = x + + if x_pkg is None: + mylist.append(x) + else: + try: + x_pkg.slot + except AttributeError: + mylist.append(x) + else: + if _match_slot(mydep, x_pkg): + mylist.append(x) if mydep.unevaluated_atom.use: candidate_list = mylist diff --git a/pym/portage/dep/_slot_abi.py b/pym/portage/dep/_slot_abi.py new file mode 100644 index 000000000..3282cafc3 --- /dev/null +++ b/pym/portage/dep/_slot_abi.py @@ -0,0 +1,92 @@ +# Copyright 2012 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from portage.dep import Atom, paren_enclose, use_reduce +from portage.exception import InvalidData + +_dep_keys = ('DEPEND', 'PDEPEND', 'RDEPEND') +_runtime_keys = ('PDEPEND', 'RDEPEND') + +def find_built_slot_abi_atoms(pkg): + atoms = {} + for k in _dep_keys: + atom_list = list(_find_built_slot_abi_op(use_reduce(pkg.metadata[k], + uselist=pkg.use.enabled, eapi=pkg.metadata['EAPI'], + token_class=Atom))) + if atom_list: + atoms[k] = atom_list + return atoms + +def _find_built_slot_abi_op(dep_struct): + for x in dep_struct: + if isinstance(x, list): + for atom in _find_slot_abi_equal_op(x): + yield atom + elif isinstance(x, Atom) and x.slot_abi_built: + yield x + +def ignore_built_slot_abi_deps(dep_struct): + for i, x in enumerate(dep_struct): + if isinstance(x, list): + ignore_slot_abi_equal_deps(x) + elif isinstance(x, Atom) and x.slot_abi_built: + # There's no way of knowing here whether the SLOT + # part of the SLOT/ABI pair should be kept, so we + # ignore both parts. + dep_struct[i] = x.without_slot + +def evaluate_slot_abi_equal_deps(settings, use, trees): + + metadata = settings.configdict['pkg'] + eapi = metadata['EAPI'] + running_vardb = trees[trees._running_eroot]["vartree"].dbapi + target_vardb = trees[trees._target_eroot]["vartree"].dbapi + vardbs = [target_vardb] + deps = {} + for k in _dep_keys: + deps[k] = use_reduce(metadata[k], + uselist=use, eapi=eapi, token_class=Atom) + + for k in _runtime_keys: + _eval_deps(deps[k], vardbs) + + if running_vardb is not target_vardb: + vardbs.append(running_vardb) + + _eval_deps(deps["DEPEND"], vardbs) + + result = {} + for k, v in deps.items(): + result[k] = paren_enclose(v) + + return result + +def _eval_deps(dep_struct, vardbs): + for i, x in enumerate(dep_struct): + if isinstance(x, list): + _eval_deps(x, vardbs) + elif isinstance(x, Atom) and x.slot_abi_op == "=": + for vardb in vardbs: + best_version = vardb.match(x) + if best_version: + best_version = best_version[-1] + try: + best_version = \ + vardb._pkg_str(best_version, None) + except (KeyError, InvalidData): + pass + else: + slot_part = "%s/%s=" % \ + (best_version.slot, best_version.slot_abi) + x = x.with_slot(slot_part) + dep_struct[i] = x + break + else: + # this dep could not be resolved, so remove the operator + # (user may be using package.provided and managing rebuilds + # manually) + if x.slot: + x = x.with_slot(x.slot) + else: + x = x.without_slot + dep_struct[i] = x |