summaryrefslogtreecommitdiffstats
path: root/pym/portage
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2012-06-22 02:59:53 -0700
committerZac Medico <zmedico@gentoo.org>2012-06-22 02:59:53 -0700
commite4ba8f36e6a4624f4fec61c7ce8bed0e3bd2fa01 (patch)
treebc90757f7887bf571d98617d1178ff2be3c90ff1 /pym/portage
parent19123d07f93bff6833848774812de882e7be9960 (diff)
downloadportage-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')
-rw-r--r--pym/portage/__init__.py2
-rw-r--r--pym/portage/dbapi/__init__.py4
-rw-r--r--pym/portage/dbapi/porttree.py4
-rw-r--r--pym/portage/dbapi/vartree.py5
-rw-r--r--pym/portage/dep/__init__.py126
-rw-r--r--pym/portage/dep/_slot_abi.py92
-rw-r--r--pym/portage/eapi.py6
-rw-r--r--pym/portage/package/ebuild/doebuild.py24
-rw-r--r--pym/portage/tests/dep/testAtom.py19
-rw-r--r--pym/portage/tests/dep/test_isvalidatom.py9
-rw-r--r--pym/portage/tests/dep/test_match_from_list.py19
-rw-r--r--pym/portage/tests/emerge/test_emerge_slot_abi.py198
-rw-r--r--pym/portage/tests/resolver/test_complete_graph.py4
-rw-r--r--pym/portage/tests/resolver/test_slot_abi.py376
-rw-r--r--pym/portage/versions.py15
15 files changed, 877 insertions, 26 deletions
diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py
index 84cac7411..46bdc961c 100644
--- a/pym/portage/__init__.py
+++ b/pym/portage/__init__.py
@@ -408,7 +408,7 @@ def abssymlink(symlink, target=None):
_doebuild_manifest_exempt_depend = 0
-_testing_eapis = frozenset(["4-python"])
+_testing_eapis = frozenset(["4-python", "4-slot-abi"])
_deprecated_eapis = frozenset(["4_pre1", "3_pre2", "3_pre1"])
def _eapi_is_deprecated(eapi):
diff --git a/pym/portage/dbapi/__init__.py b/pym/portage/dbapi/__init__.py
index 2ab7dc5b6..34b1d4705 100644
--- a/pym/portage/dbapi/__init__.py
+++ b/pym/portage/dbapi/__init__.py
@@ -8,7 +8,7 @@ import re
import portage
portage.proxy.lazyimport.lazyimport(globals(),
'portage.dbapi.dep_expand:dep_expand@_dep_expand',
- 'portage.dep:match_from_list',
+ 'portage.dep:match_from_list,_match_slot',
'portage.output:colorize',
'portage.util:cmp_sort_key,writemsg',
'portage.versions:catsplit,catpkgsplit,vercmp,_pkg_str',
@@ -173,7 +173,7 @@ class dbapi(object):
except (KeyError, InvalidData):
pass
else:
- if pkg_str.slot == atom.slot:
+ if _match_slot(atom, pkg_str):
yield pkg_str
def _iter_match_use(self, atom, cpv_iter):
diff --git a/pym/portage/dbapi/porttree.py b/pym/portage/dbapi/porttree.py
index df681152c..945c22c3d 100644
--- a/pym/portage/dbapi/porttree.py
+++ b/pym/portage/dbapi/porttree.py
@@ -10,7 +10,7 @@ portage.proxy.lazyimport.lazyimport(globals(),
'portage.checksum',
'portage.data:portage_gid,secpass',
'portage.dbapi.dep_expand:dep_expand',
- 'portage.dep:Atom,dep_getkey,match_from_list,use_reduce',
+ 'portage.dep:Atom,dep_getkey,match_from_list,use_reduce,_match_slot',
'portage.package.ebuild.doebuild:doebuild',
'portage.util:ensure_dirs,shlex_split,writemsg,writemsg_level',
'portage.util.listdir:listdir',
@@ -836,7 +836,7 @@ class portdbapi(dbapi):
continue
if mydep.slot is not None and \
- mydep.slot != pkg_str.slot:
+ not _match_slot(mydep, pkg_str):
continue
if mydep.unevaluated_atom.use is not None and \
diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
index 5448bd431..b8405d483 100644
--- a/pym/portage/dbapi/vartree.py
+++ b/pym/portage/dbapi/vartree.py
@@ -3465,6 +3465,11 @@ class dblink(object):
if not os.path.exists(self.dbcatdir):
ensure_dirs(self.dbcatdir)
+ try:
+ slot = self.mycpv.slot
+ except AttributeError:
+ # discard the sub-slot if necesssary
+ slot = _pkg_str(self.mycpv, slot=slot).slot
cp = self.mysplit[0]
slot_atom = "%s:%s" % (cp, slot)
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
diff --git a/pym/portage/eapi.py b/pym/portage/eapi.py
index e36567d16..8b03f830e 100644
--- a/pym/portage/eapi.py
+++ b/pym/portage/eapi.py
@@ -9,6 +9,9 @@ def eapi_has_iuse_defaults(eapi):
def eapi_has_slot_deps(eapi):
return eapi != "0"
+def eapi_has_slot_abi(eapi):
+ return eapi in ("4-slot-abi",)
+
def eapi_has_src_uri_arrows(eapi):
return eapi not in ("0", "1")
@@ -65,7 +68,7 @@ def eapi_allows_dots_in_use_flags(eapi):
_eapi_attrs = collections.namedtuple('_eapi_attrs',
'dots_in_PN dots_in_use_flags iuse_defaults '
- 'repo_deps required_use slot_deps '
+ 'repo_deps required_use slot_abi slot_deps '
'src_uri_arrows strong_blocks use_deps use_dep_defaults')
_eapi_attrs_cache = {}
@@ -86,6 +89,7 @@ def _get_eapi_attrs(eapi):
repo_deps = (eapi is None or eapi_has_repo_deps(eapi)),
required_use = (eapi is None or eapi_has_required_use(eapi)),
slot_deps = (eapi is None or eapi_has_slot_deps(eapi)),
+ slot_abi = (eapi is None or eapi_has_slot_abi(eapi)),
src_uri_arrows = (eapi is None or eapi_has_src_uri_arrows(eapi)),
strong_blocks = (eapi is None or eapi_has_strong_blocks(eapi)),
use_deps = (eapi is None or eapi_has_use_deps(eapi)),
diff --git a/pym/portage/package/ebuild/doebuild.py b/pym/portage/package/ebuild/doebuild.py
index edc5d0b6e..09062f9f3 100644
--- a/pym/portage/package/ebuild/doebuild.py
+++ b/pym/portage/package/ebuild/doebuild.py
@@ -25,6 +25,8 @@ portage.proxy.lazyimport.lazyimport(globals(),
'portage.package.ebuild.digestcheck:digestcheck',
'portage.package.ebuild.digestgen:digestgen',
'portage.package.ebuild.fetch:fetch',
+ 'portage.package.ebuild._ipc.QueryCommand:QueryCommand',
+ 'portage.dep._slot_abi:evaluate_slot_abi_equal_deps',
'portage.package.ebuild._spawn_nofetch:spawn_nofetch',
'portage.util.ExtractKernelVersion:ExtractKernelVersion'
)
@@ -43,7 +45,7 @@ from portage.dep import Atom, check_required_use, \
from portage.eapi import eapi_exports_KV, eapi_exports_merge_type, \
eapi_exports_replace_vars, eapi_exports_REPOSITORY, \
eapi_has_required_use, eapi_has_src_prepare_and_src_configure, \
- eapi_has_pkg_pretend
+ eapi_has_pkg_pretend, _get_eapi_attrs
from portage.elog import elog_process, _preload_elog_modules
from portage.elog.messages import eerror, eqawarn
from portage.exception import DigestException, FileNotFound, \
@@ -1631,6 +1633,8 @@ def _post_src_install_write_metadata(settings):
due to local environment settings like in bug #386829.
"""
+ eapi_attrs = _get_eapi_attrs(settings.configdict['pkg']['EAPI'])
+
build_info_dir = os.path.join(settings['PORTAGE_BUILDDIR'], 'build-info')
for k in ('IUSE',):
@@ -1664,6 +1668,8 @@ def _post_src_install_write_metadata(settings):
continue
if k.endswith('DEPEND'):
+ if eapi_attrs.slot_abi:
+ continue
token_class = Atom
else:
token_class = None
@@ -1682,6 +1688,22 @@ def _post_src_install_write_metadata(settings):
errors='strict') as f:
f.write(_unicode_decode(v + '\n'))
+ if eapi_attrs.slot_abi:
+ deps = evaluate_slot_abi_equal_deps(settings, use, QueryCommand.get_db())
+ for k, v in deps.items():
+ filename = os.path.join(build_info_dir, k)
+ if not v:
+ try:
+ os.unlink(filename)
+ except OSError:
+ pass
+ continue
+ with io.open(_unicode_encode(os.path.join(build_info_dir,
+ k), encoding=_encodings['fs'], errors='strict'),
+ mode='w', encoding=_encodings['repo.content'],
+ errors='strict') as f:
+ f.write(_unicode_decode(v + '\n'))
+
_vdb_use_conditional_keys = ('DEPEND', 'LICENSE', 'PDEPEND',
'PROPERTIES', 'PROVIDE', 'RDEPEND', 'RESTRICT',)
diff --git a/pym/portage/tests/dep/testAtom.py b/pym/portage/tests/dep/testAtom.py
index 092cacf84..e0cfaabcf 100644
--- a/pym/portage/tests/dep/testAtom.py
+++ b/pym/portage/tests/dep/testAtom.py
@@ -144,6 +144,25 @@ class TestAtom(TestCase):
self.assertRaisesMsg(atom, (InvalidAtom, TypeError), Atom, atom, \
allow_wildcard=allow_wildcard, allow_repo=allow_repo)
+ def testSlotAbiAtom(self):
+ tests = (
+ ("virtual/ffmpeg:0/53", "4-slot-abi", {"slot": "0", "slot_abi": "53", "slot_abi_op": None}),
+ ("virtual/ffmpeg:0/53=", "4-slot-abi", {"slot": "0", "slot_abi": "53", "slot_abi_op": "="}),
+ ("virtual/ffmpeg:=", "4-slot-abi", {"slot": None, "slot_abi": None, "slot_abi_op": "="}),
+ ("virtual/ffmpeg:0=", "4-slot-abi", {"slot": "0", "slot_abi": None, "slot_abi_op": "="}),
+ ("virtual/ffmpeg:*", "4-slot-abi", {"slot": None, "slot_abi": None, "slot_abi_op": "*"}),
+ ("virtual/ffmpeg:0*", "4-slot-abi", {"slot": "0", "slot_abi": None, "slot_abi_op": "*"}),
+ ("virtual/ffmpeg:0", "4-slot-abi", {"slot": "0", "slot_abi": None, "slot_abi_op": None}),
+ ("virtual/ffmpeg", "4-slot-abi", {"slot": None, "slot_abi": None, "slot_abi_op": None}),
+ )
+
+ for atom, eapi, parts in tests:
+ a = Atom(atom, eapi=eapi)
+ for k, v in parts.items():
+ self.assertEqual(v, getattr(a, k),
+ msg="Atom('%s').%s = %s == '%s'" %
+ (atom, k, getattr(a, k), v ))
+
def test_intersects(self):
test_cases = (
("dev-libs/A", "dev-libs/A", True),
diff --git a/pym/portage/tests/dep/test_isvalidatom.py b/pym/portage/tests/dep/test_isvalidatom.py
index 173ab0dec..abcec755e 100644
--- a/pym/portage/tests/dep/test_isvalidatom.py
+++ b/pym/portage/tests/dep/test_isvalidatom.py
@@ -134,6 +134,15 @@ class IsValidAtom(TestCase):
IsValidAtomTestCase("=sys-apps/portage-2.2*:foo::repo[bar?,!baz?,!doc=,build=]", False, allow_repo=False),
IsValidAtomTestCase("=sys-apps/portage-2.2*:foo::repo[doc?]", False, allow_repo=False),
IsValidAtomTestCase("null/portage::repo", False, allow_repo=False),
+
+ IsValidAtomTestCase("virtual/ffmpeg:0/53", True),
+ IsValidAtomTestCase("virtual/ffmpeg:0/53=", True),
+ IsValidAtomTestCase("virtual/ffmpeg:0/53*", False),
+ IsValidAtomTestCase("virtual/ffmpeg:=", True),
+ IsValidAtomTestCase("virtual/ffmpeg:0=", True),
+ IsValidAtomTestCase("virtual/ffmpeg:*", True),
+ IsValidAtomTestCase("virtual/ffmpeg:0*", True),
+ IsValidAtomTestCase("virtual/ffmpeg:0", True),
)
for test_case in test_cases:
diff --git a/pym/portage/tests/dep/test_match_from_list.py b/pym/portage/tests/dep/test_match_from_list.py
index fae473e20..d6649ad7f 100644
--- a/pym/portage/tests/dep/test_match_from_list.py
+++ b/pym/portage/tests/dep/test_match_from_list.py
@@ -16,9 +16,15 @@ class Package(object):
def __init__(self, atom):
atom = Atom(atom, allow_repo=True)
self.cp = atom.cp
- self.cpv = _pkg_str(atom.cpv, slot=(atom.slot or '0'), repo=atom.repo)
+ slot = atom.slot
+ if atom.slot_abi:
+ slot = "%s/%s" % (slot, atom.slot_abi)
+ if not slot:
+ slot = '0'
+ self.cpv = _pkg_str(atom.cpv, slot=slot, repo=atom.repo)
self.cpv_split = catpkgsplit(self.cpv)
- self.slot = atom.slot
+ self.slot = self.cpv.slot
+ self.slot_abi = self.cpv.slot_abi
self.repo = atom.repo
if atom.use:
self.use = self._use_class(atom.use.enabled)
@@ -93,6 +99,15 @@ class Test_match_from_list(TestCase):
("dev-libs/A::repo2[foo]", [Package("=dev-libs/A-1::repo1[-foo]"), Package("=dev-libs/A-1::repo2[foo]")], ["dev-libs/A-1::repo2"] ),
("dev-libs/A:1::repo2[foo]", [Package("=dev-libs/A-1:1::repo1"), Package("=dev-libs/A-1:2::repo2")], [] ),
("dev-libs/A:1::repo2[foo]", [Package("=dev-libs/A-1:2::repo1"), Package("=dev-libs/A-1:1::repo2[foo]")], ["dev-libs/A-1::repo2"] ),
+
+ ("virtual/ffmpeg:0/53", [Package("=virtual/ffmpeg-0.10.3:0/53")], ["virtual/ffmpeg-0.10.3"] ),
+ ("virtual/ffmpeg:0/53=", [Package("=virtual/ffmpeg-0.10.3:0/53")], ["virtual/ffmpeg-0.10.3"] ),
+ ("virtual/ffmpeg:0/52", [Package("=virtual/ffmpeg-0.10.3:0/53")], [] ),
+ ("virtual/ffmpeg:=", [Package("=virtual/ffmpeg-0.10.3:0/53")], ["virtual/ffmpeg-0.10.3"] ),
+ ("virtual/ffmpeg:0=", [Package("=virtual/ffmpeg-0.10.3:0/53")], ["virtual/ffmpeg-0.10.3"] ),
+ ("virtual/ffmpeg:*", [Package("=virtual/ffmpeg-0.10.3:0/53")], ["virtual/ffmpeg-0.10.3"] ),
+ ("virtual/ffmpeg:0*", [Package("=virtual/ffmpeg-0.10.3:0/53")], ["virtual/ffmpeg-0.10.3"] ),
+ ("virtual/ffmpeg:0", [Package("=virtual/ffmpeg-0.10.3:0/53")], ["virtual/ffmpeg-0.10.3"] ),
)
for atom, cpv_list, expected_result in tests:
diff --git a/pym/portage/tests/emerge/test_emerge_slot_abi.py b/pym/portage/tests/emerge/test_emerge_slot_abi.py
new file mode 100644
index 000000000..005c5d354
--- /dev/null
+++ b/pym/portage/tests/emerge/test_emerge_slot_abi.py
@@ -0,0 +1,198 @@
+# Copyright 2012 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+import subprocess
+import sys
+
+import portage
+from portage import os
+from portage import _unicode_decode
+from portage.const import (BASH_BINARY, PORTAGE_BIN_PATH,
+ PORTAGE_PYM_PATH, USER_CONFIG_PATH)
+from portage.process import find_binary
+from portage.tests import TestCase
+from portage.tests.resolver.ResolverPlayground import ResolverPlayground
+from portage.util import ensure_dirs
+
+class SlotAbiEmergeTestCase(TestCase):
+
+ def testSlotAbiEmerge(self):
+
+ debug = False
+
+ ebuilds = {
+ "dev-libs/glib-1.2.10" : {
+ "SLOT": "1"
+ },
+ "dev-libs/glib-2.30.2" : {
+ "EAPI": "4-slot-abi",
+ "SLOT": "2/2.30"
+ },
+ "dev-libs/glib-2.32.3" : {
+ "EAPI": "4-slot-abi",
+ "SLOT": "2/2.32"
+ },
+ "dev-libs/dbus-glib-0.98" : {
+ "EAPI": "4-slot-abi",
+ "DEPEND": "dev-libs/glib:2=",
+ "RDEPEND": "dev-libs/glib:2="
+ },
+ }
+ installed = {
+ "dev-libs/glib-1.2.10" : {
+ "EAPI": "4-slot-abi",
+ "SLOT": "1"
+ },
+ "dev-libs/glib-2.30.2" : {
+ "EAPI": "4-slot-abi",
+ "SLOT": "2/2.30"
+ },
+ "dev-libs/dbus-glib-0.98" : {
+ "EAPI": "4-slot-abi",
+ "DEPEND": "dev-libs/glib:2/2.30=",
+ "RDEPEND": "dev-libs/glib:2/2.30="
+ },
+ }
+
+ world = ["dev-libs/glib:1", "dev-libs/dbus-glib"]
+
+ playground = ResolverPlayground(ebuilds=ebuilds,
+ installed=installed, world=world, debug=debug)
+ settings = playground.settings
+ eprefix = settings["EPREFIX"]
+ eroot = settings["EROOT"]
+ trees = playground.trees
+ portdb = trees[eroot]["porttree"].dbapi
+ vardb = trees[eroot]["vartree"].dbapi
+ portdir = settings["PORTDIR"]
+ var_cache_edb = os.path.join(eprefix, "var", "cache", "edb")
+
+ portage_python = portage._python_interpreter
+ ebuild_cmd = (portage_python, "-Wd",
+ os.path.join(PORTAGE_BIN_PATH, "ebuild"))
+ emerge_cmd = (portage_python, "-Wd",
+ os.path.join(PORTAGE_BIN_PATH, "emerge"))
+
+ test_ebuild = portdb.findname("dev-libs/dbus-glib-0.98")
+ self.assertFalse(test_ebuild is None)
+
+ test_commands = (
+ emerge_cmd + ("--oneshot", "dev-libs/glib",),
+ (lambda: "dev-libs/glib:2/2.32=" in vardb.aux_get("dev-libs/dbus-glib-0.98", ["RDEPEND"])[0],),
+ emerge_cmd + ("--oneshot", "=dev-libs/glib-2.30.2", "--ignore-built-slot-abi-deps", "y"),
+ emerge_cmd + ("--oneshot", "dev-libs/dbus-glib"),
+ (lambda: "dev-libs/glib:2/2.30=" in vardb.aux_get("dev-libs/dbus-glib-0.98", ["RDEPEND"])[0],),
+ )
+
+ distdir = playground.distdir
+ pkgdir = playground.pkgdir
+ fake_bin = os.path.join(eprefix, "bin")
+ portage_tmpdir = os.path.join(eprefix, "var", "tmp", "portage")
+ profile_path = settings.profile_path
+ user_config_dir = os.path.join(os.sep, eprefix, USER_CONFIG_PATH)
+
+ features = []
+ if not portage.process.sandbox_capable or \
+ os.environ.get("SANDBOX_ON") == "1":
+ features.append("-sandbox")
+
+ make_conf = (
+ "FEATURES=\"%s\"\n" % (" ".join(features),),
+ "PORTDIR=\"%s\"\n" % (portdir,),
+ "PORTAGE_GRPNAME=\"%s\"\n" % (os.environ["PORTAGE_GRPNAME"],),
+ "PORTAGE_USERNAME=\"%s\"\n" % (os.environ["PORTAGE_USERNAME"],),
+ "PKGDIR=\"%s\"\n" % (pkgdir,),
+ "PORTAGE_INST_GID=%s\n" % (portage.data.portage_gid,),
+ "PORTAGE_INST_UID=%s\n" % (portage.data.portage_uid,),
+ "PORTAGE_TMPDIR=\"%s\"\n" % (portage_tmpdir,),
+ "CLEAN_DELAY=0\n",
+ "DISTDIR=\"%s\"\n" % (distdir,),
+ "EMERGE_WARNING_DELAY=0\n",
+ )
+
+ path = os.environ.get("PATH")
+ if path is not None and not path.strip():
+ path = None
+ if path is None:
+ path = ""
+ else:
+ path = ":" + path
+ path = fake_bin + path
+
+ pythonpath = os.environ.get("PYTHONPATH")
+ if pythonpath is not None and not pythonpath.strip():
+ pythonpath = None
+ if pythonpath is not None and \
+ pythonpath.split(":")[0] == PORTAGE_PYM_PATH:
+ pass
+ else:
+ if pythonpath is None:
+ pythonpath = ""
+ else:
+ pythonpath = ":" + pythonpath
+ pythonpath = PORTAGE_PYM_PATH + pythonpath
+
+ env = {
+ "PORTAGE_OVERRIDE_EPREFIX" : eprefix,
+ "PATH" : path,
+ "PORTAGE_PYTHON" : portage_python,
+ "PYTHONPATH" : pythonpath,
+ }
+
+ if "__PORTAGE_TEST_HARDLINK_LOCKS" in os.environ:
+ env["__PORTAGE_TEST_HARDLINK_LOCKS"] = \
+ os.environ["__PORTAGE_TEST_HARDLINK_LOCKS"]
+
+ dirs = [distdir, fake_bin, portage_tmpdir,
+ user_config_dir, var_cache_edb]
+ true_symlinks = ["chown", "chgrp"]
+ true_binary = find_binary("true")
+ self.assertEqual(true_binary is None, False,
+ "true command not found")
+ try:
+ for d in dirs:
+ ensure_dirs(d)
+ with open(os.path.join(user_config_dir, "make.conf"), 'w') as f:
+ for line in make_conf:
+ f.write(line)
+ for x in true_symlinks:
+ os.symlink(true_binary, os.path.join(fake_bin, x))
+ with open(os.path.join(var_cache_edb, "counter"), 'wb') as f:
+ f.write(b"100")
+ # non-empty system set keeps --depclean quiet
+ with open(os.path.join(profile_path, "packages"), 'w') as f:
+ f.write("*dev-libs/token-system-pkg")
+
+ if debug:
+ # The subprocess inherits both stdout and stderr, for
+ # debugging purposes.
+ stdout = None
+ else:
+ # The subprocess inherits stderr so that any warnings
+ # triggered by python -Wd will be visible.
+ stdout = subprocess.PIPE
+
+ for i, args in enumerate(test_commands):
+
+ if hasattr(args[0], '__call__'):
+ self.assertTrue(args[0](),
+ "callable at index %s failed" % (i,))
+ continue
+
+ proc = subprocess.Popen(args,
+ env=env, stdout=stdout)
+
+ if debug:
+ proc.wait()
+ else:
+ output = proc.stdout.readlines()
+ proc.wait()
+ proc.stdout.close()
+ if proc.returncode != os.EX_OK:
+ for line in output:
+ sys.stderr.write(_unicode_decode(line))
+
+ self.assertEqual(os.EX_OK, proc.returncode,
+ "emerge failed with args %s" % (args,))
+ finally:
+ playground.cleanup()
diff --git a/pym/portage/tests/resolver/test_complete_graph.py b/pym/portage/tests/resolver/test_complete_graph.py
index 07206430e..850b883b4 100644
--- a/pym/portage/tests/resolver/test_complete_graph.py
+++ b/pym/portage/tests/resolver/test_complete_graph.py
@@ -29,7 +29,7 @@ class CompleteGraphTestCase(TestCase):
test_cases = (
ResolverPlaygroundTestCase(
[">=sys-libs/x-2"],
- options = {"--complete-graph-if-new-ver" : "n"},
+ options = {"--complete-graph-if-new-ver" : "n", "--rebuild-if-new-slot-abi": "n"},
mergelist = ["sys-libs/x-2"],
success = True,
),
@@ -42,7 +42,7 @@ class CompleteGraphTestCase(TestCase):
),
ResolverPlaygroundTestCase(
["<sys-libs/x-1"],
- options = {"--complete-graph-if-new-ver" : "n"},
+ options = {"--complete-graph-if-new-ver" : "n", "--rebuild-if-new-slot-abi": "n"},
mergelist = ["sys-libs/x-0.1"],
success = True,
),
diff --git a/pym/portage/tests/resolver/test_slot_abi.py b/pym/portage/tests/resolver/test_slot_abi.py
new file mode 100644
index 000000000..46938347f
--- /dev/null
+++ b/pym/portage/tests/resolver/test_slot_abi.py
@@ -0,0 +1,376 @@
+# Copyright 2012 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+from portage.tests import TestCase
+from portage.tests.resolver.ResolverPlayground import (ResolverPlayground,
+ ResolverPlaygroundTestCase)
+
+class SlotAbiTestCase(TestCase):
+
+ def __init__(self, *args, **kwargs):
+ super(SlotAbiTestCase, self).__init__(*args, **kwargs)
+
+ def testSubSlot(self):
+ ebuilds = {
+ "dev-libs/icu-49" : {
+ "EAPI": "4-slot-abi",
+ "SLOT": "0/49"
+ },
+ "dev-libs/icu-4.8" : {
+ "EAPI": "4-slot-abi",
+ "SLOT": "0/48"
+ },
+ "dev-libs/libxml2-2.7.8" : {
+ "EAPI": "4-slot-abi",
+ "DEPEND": "dev-libs/icu:=",
+ "RDEPEND": "dev-libs/icu:="
+ },
+ }
+ binpkgs = {
+ "dev-libs/icu-49" : {
+ "EAPI": "4-slot-abi",
+ "SLOT": "0/49"
+ },
+ "dev-libs/icu-4.8" : {
+ "EAPI": "4-slot-abi",
+ "SLOT": "0/48"
+ },
+ "dev-libs/libxml2-2.7.8" : {
+ "EAPI": "4-slot-abi",
+ "DEPEND": "dev-libs/icu:0/48=",
+ "RDEPEND": "dev-libs/icu:0/48="
+ },
+ }
+ installed = {
+ "dev-libs/icu-4.8" : {
+ "EAPI": "4-slot-abi",
+ "SLOT": "0/48"
+ },
+ "dev-libs/libxml2-2.7.8" : {
+ "EAPI": "4-slot-abi",
+ "DEPEND": "dev-libs/icu:0/48=",
+ "RDEPEND": "dev-libs/icu:0/48="
+ },
+ }
+
+ world = ["dev-libs/libxml2"]
+
+ test_cases = (
+
+ ResolverPlaygroundTestCase(
+ ["dev-libs/icu"],
+ options = {"--oneshot": True},
+ success = True,
+ mergelist = ["dev-libs/icu-49", "dev-libs/libxml2-2.7.8" ]),
+
+ ResolverPlaygroundTestCase(
+ ["dev-libs/icu"],
+ options = {"--oneshot": True, "--ignore-built-slot-abi-deps": "y"},
+ success = True,
+ mergelist = ["dev-libs/icu-49"]),
+
+ ResolverPlaygroundTestCase(
+ ["dev-libs/icu"],
+ options = {"--oneshot": True, "--usepkg": True},
+ success = True,
+ mergelist = ["[binary]dev-libs/icu-49", "dev-libs/libxml2-2.7.8" ]),
+
+ ResolverPlaygroundTestCase(
+ ["dev-libs/icu"],
+ options = {"--oneshot": True, "--usepkgonly": True},
+ success = True,
+ mergelist = ["[binary]dev-libs/icu-4.8"]),
+
+ ResolverPlaygroundTestCase(
+ ["dev-libs/icu"],
+ options = {"--oneshot": True, "--usepkgonly": True, "--ignore-built-slot-abi-deps": "y"},
+ success = True,
+ mergelist = ["[binary]dev-libs/icu-49"]),
+
+ ResolverPlaygroundTestCase(
+ ["@world"],
+ options = {"--update": True, "--deep": True},
+ success = True,
+ mergelist = ["dev-libs/icu-49", "dev-libs/libxml2-2.7.8" ]),
+
+ ResolverPlaygroundTestCase(
+ ["@world"],
+ options = {"--update": True, "--deep": True, "--ignore-built-slot-abi-deps": "y"},
+ success = True,
+ mergelist = ["dev-libs/icu-49"]),
+
+ ResolverPlaygroundTestCase(
+ ["@world"],
+ options = {"--update": True, "--deep": True, "--usepkg": True},
+ success = True,
+ mergelist = ["[binary]dev-libs/icu-49", "dev-libs/libxml2-2.7.8" ]),
+
+ ResolverPlaygroundTestCase(
+ ["@world"],
+ options = {"--update": True, "--deep": True, "--usepkgonly": True},
+ success = True,
+ mergelist = []),
+
+ ResolverPlaygroundTestCase(
+ ["@world"],
+ options = {"--update": True, "--deep": True, "--usepkgonly": True, "--ignore-built-slot-abi-deps": "y"},
+ success = True,
+ mergelist = ["[binary]dev-libs/icu-49"]),
+
+ )
+
+ playground = ResolverPlayground(ebuilds=ebuilds, binpkgs=binpkgs,
+ installed=installed, world=world, debug=False)
+ try:
+ for test_case in test_cases:
+ playground.run_TestCase(test_case)
+ self.assertEqual(test_case.test_success, True, test_case.fail_msg)
+ finally:
+ playground.cleanup()
+
+ def testWholeSlot(self):
+ ebuilds = {
+ "sys-libs/db-4.8" : {
+ "SLOT": "4.8"
+ },
+ "sys-libs/db-4.7" : {
+ "SLOT": "4.7"
+ },
+ "app-office/libreoffice-3.5.4.2" : {
+ "EAPI": "4-slot-abi",
+ "DEPEND": ">=sys-libs/db-4:=",
+ "RDEPEND": ">=sys-libs/db-4:="
+ },
+ }
+ binpkgs = {
+ "sys-libs/db-4.8" : {
+ "SLOT": "4.8"
+ },
+ "sys-libs/db-4.7" : {
+ "SLOT": "4.7"
+ },
+ "app-office/libreoffice-3.5.4.2" : {
+ "EAPI": "4-slot-abi",
+ "DEPEND": ">=sys-libs/db-4:4.7/4.7=",
+ "RDEPEND": ">=sys-libs/db-4:4.7/4.7=="
+ },
+ }
+ installed = {
+ "sys-libs/db-4.7" : {
+ "SLOT": "4.7"
+ },
+ "app-office/libreoffice-3.5.4.2" : {
+ "EAPI": "4-slot-abi",
+ "DEPEND": ">=sys-libs/db-4:4.7/4.7=",
+ "RDEPEND": ">=sys-libs/db-4:4.7/4.7="
+ },
+ }
+
+ world = ["app-office/libreoffice"]
+
+ test_cases = (
+
+ ResolverPlaygroundTestCase(
+ ["sys-libs/db"],
+ options = {"--oneshot": True},
+ success = True,
+ mergelist = ["sys-libs/db-4.8", "app-office/libreoffice-3.5.4.2"]),
+
+ ResolverPlaygroundTestCase(
+ ["sys-libs/db"],
+ options = {"--oneshot": True, "--ignore-built-slot-abi-deps": "y"},
+ success = True,
+ mergelist = ["sys-libs/db-4.8"]),
+
+ ResolverPlaygroundTestCase(
+ ["sys-libs/db"],
+ options = {"--oneshot": True, "--usepkg": True},
+ success = True,
+ mergelist = ["[binary]sys-libs/db-4.8", "app-office/libreoffice-3.5.4.2"]),
+
+ ResolverPlaygroundTestCase(
+ ["sys-libs/db"],
+ options = {"--oneshot": True, "--usepkgonly": True},
+ success = True,
+ mergelist = ["[binary]sys-libs/db-4.8"]),
+
+ ResolverPlaygroundTestCase(
+ ["sys-libs/db"],
+ options = {"--oneshot": True, "--rebuild-if-new-slot-abi": "n"},
+ success = True,
+ mergelist = ["sys-libs/db-4.8"]),
+
+ ResolverPlaygroundTestCase(
+ ["@world"],
+ options = {"--update": True, "--deep": True},
+ success = True,
+ mergelist = ["sys-libs/db-4.8", "app-office/libreoffice-3.5.4.2"]),
+
+ ResolverPlaygroundTestCase(
+ ["@world"],
+ options = {"--update": True, "--deep": True, "--usepkg": True},
+ success = True,
+ mergelist = ["[binary]sys-libs/db-4.8", "app-office/libreoffice-3.5.4.2"]),
+
+ ResolverPlaygroundTestCase(
+ ["@world"],
+ options = {"--update": True, "--deep": True, "--usepkg": True, "--ignore-built-slot-abi-deps": "y"},
+ success = True,
+ mergelist = ["[binary]sys-libs/db-4.8"]),
+
+ ResolverPlaygroundTestCase(
+ ["@world"],
+ options = {"--update": True, "--deep": True, "--usepkgonly": True},
+ success = True,
+ mergelist = []),
+
+ ResolverPlaygroundTestCase(
+ ["@world"],
+ options = {"--update": True, "--deep": True, "--usepkgonly": True, "--ignore-built-slot-abi-deps": "y"},
+ success = True,
+ mergelist = ["[binary]sys-libs/db-4.8"]),
+
+ ResolverPlaygroundTestCase(
+ ["@world"],
+ options = {"--update": True, "--deep": True, "--rebuild-if-new-slot-abi": "n"},
+ success = True,
+ mergelist = []),
+
+ )
+
+ playground = ResolverPlayground(ebuilds=ebuilds, binpkgs=binpkgs,
+ installed=installed, world=world, debug=False)
+ try:
+ for test_case in test_cases:
+ playground.run_TestCase(test_case)
+ self.assertEqual(test_case.test_success, True, test_case.fail_msg)
+ finally:
+ playground.cleanup()
+
+ def testWholeSlotSubSlotMix(self):
+ ebuilds = {
+ "dev-libs/glib-1.2.10" : {
+ "SLOT": "1"
+ },
+ "dev-libs/glib-2.30.2" : {
+ "EAPI": "4-slot-abi",
+ "SLOT": "2/2.30"
+ },
+ "dev-libs/glib-2.32.3" : {
+ "EAPI": "4-slot-abi",
+ "SLOT": "2/2.32"
+ },
+ "dev-libs/dbus-glib-0.98" : {
+ "EAPI": "4-slot-abi",
+ "DEPEND": "dev-libs/glib:2=",
+ "RDEPEND": "dev-libs/glib:2="
+ },
+ }
+ binpkgs = {
+ "dev-libs/glib-1.2.10" : {
+ "SLOT": "1"
+ },
+ "dev-libs/glib-2.30.2" : {
+ "EAPI": "4-slot-abi",
+ "SLOT": "2/2.30"
+ },
+ "dev-libs/glib-2.32.3" : {
+ "EAPI": "4-slot-abi",
+ "SLOT": "2/2.32"
+ },
+ "dev-libs/dbus-glib-0.98" : {
+ "EAPI": "4-slot-abi",
+ "DEPEND": "dev-libs/glib:2/2.30=",
+ "RDEPEND": "dev-libs/glib:2/2.30="
+ },
+ }
+ installed = {
+ "dev-libs/glib-1.2.10" : {
+ "EAPI": "4-slot-abi",
+ "SLOT": "1"
+ },
+ "dev-libs/glib-2.30.2" : {
+ "EAPI": "4-slot-abi",
+ "SLOT": "2/2.30"
+ },
+ "dev-libs/dbus-glib-0.98" : {
+ "EAPI": "4-slot-abi",
+ "DEPEND": "dev-libs/glib:2/2.30=",
+ "RDEPEND": "dev-libs/glib:2/2.30="
+ },
+ }
+
+ world = ["dev-libs/glib:1", "dev-libs/dbus-glib"]
+
+ test_cases = (
+
+ ResolverPlaygroundTestCase(
+ ["dev-libs/glib"],
+ options = {"--oneshot": True},
+ success = True,
+ mergelist = ["dev-libs/glib-2.32.3", "dev-libs/dbus-glib-0.98" ]),
+
+ ResolverPlaygroundTestCase(
+ ["dev-libs/glib"],
+ options = {"--oneshot": True, "--ignore-built-slot-abi-deps": "y"},
+ success = True,
+ mergelist = ["dev-libs/glib-2.32.3"]),
+
+ ResolverPlaygroundTestCase(
+ ["dev-libs/glib"],
+ options = {"--oneshot": True, "--usepkg": True},
+ success = True,
+ mergelist = ["[binary]dev-libs/glib-2.32.3", "dev-libs/dbus-glib-0.98" ]),
+
+ ResolverPlaygroundTestCase(
+ ["dev-libs/glib"],
+ options = {"--oneshot": True, "--usepkgonly": True},
+ success = True,
+ mergelist = ["[binary]dev-libs/glib-2.30.2"]),
+
+ ResolverPlaygroundTestCase(
+ ["dev-libs/glib"],
+ options = {"--oneshot": True, "--usepkgonly": True, "--ignore-built-slot-abi-deps": "y"},
+ success = True,
+ mergelist = ["[binary]dev-libs/glib-2.32.3"]),
+
+ ResolverPlaygroundTestCase(
+ ["@world"],
+ options = {"--update": True, "--deep": True},
+ success = True,
+ mergelist = ["dev-libs/glib-2.32.3", "dev-libs/dbus-glib-0.98" ]),
+
+ ResolverPlaygroundTestCase(
+ ["@world"],
+ options = {"--update": True, "--deep": True, "--ignore-built-slot-abi-deps": "y"},
+ success = True,
+ mergelist = ["dev-libs/glib-2.32.3"]),
+
+ ResolverPlaygroundTestCase(
+ ["@world"],
+ options = {"--update": True, "--deep": True, "--usepkg": True},
+ success = True,
+ mergelist = ["[binary]dev-libs/glib-2.32.3", "dev-libs/dbus-glib-0.98" ]),
+
+ ResolverPlaygroundTestCase(
+ ["@world"],
+ options = {"--update": True, "--deep": True, "--usepkgonly": True},
+ success = True,
+ mergelist = []),
+
+ ResolverPlaygroundTestCase(
+ ["@world"],
+ options = {"--update": True, "--deep": True, "--usepkgonly": True, "--ignore-built-slot-abi-deps": "y"},
+ success = True,
+ mergelist = ["[binary]dev-libs/glib-2.32.3"]),
+
+ )
+
+ playground = ResolverPlayground(ebuilds=ebuilds, binpkgs=binpkgs,
+ installed=installed, world=world, debug=False)
+ try:
+ for test_case in test_cases:
+ playground.run_TestCase(test_case)
+ self.assertEqual(test_case.test_success, True, test_case.fail_msg)
+ finally:
+ playground.cleanup()
diff --git a/pym/portage/versions.py b/pym/portage/versions.py
index a1ded6771..5893096d1 100644
--- a/pym/portage/versions.py
+++ b/pym/portage/versions.py
@@ -356,13 +356,24 @@ class _pkg_str(_unicode):
# for match_from_list introspection
self.__dict__['cpv'] = self
if slot is not None:
- slot_match = _get_slot_re(_get_eapi_attrs(eapi)).match(slot)
+ eapi_attrs = _get_eapi_attrs(eapi)
+ slot_match = _get_slot_re(eapi_attrs).match(slot)
if slot_match is None:
# Avoid an InvalidAtom exception when creating SLOT atoms
self.__dict__['slot'] = '0'
+ self.__dict__['slot_abi'] = '0'
self.__dict__['slot_invalid'] = slot
else:
- self.__dict__['slot'] = slot
+ if eapi_attrs.slot_abi:
+ slot_split = slot.split("/")
+ self.__dict__['slot'] = slot_split[0]
+ if len(slot_split) > 1:
+ self.__dict__['slot_abi'] = slot_split[1]
+ else:
+ self.__dict__['slot_abi'] = slot_split[0]
+ else:
+ self.__dict__['slot'] = slot
+ self.__dict__['slot_abi'] = slot
if repo is not None:
repo = _gen_valid_repo(repo)