aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2015-02-17 18:31:28 -0800
committerZac Medico <zmedico@gentoo.org>2015-03-04 13:32:07 -0800
commitc6e3af2b1e419d70443a74575e9b762a101a3912 (patch)
tree1d11fb1778e2cb8bc812c12b7d7c6aa5281a2d96
parentbinpkg-multi-instance 6 of 7 (diff)
downloadportage-c6e3af2b1e419d70443a74575e9b762a101a3912.tar.gz
portage-c6e3af2b1e419d70443a74575e9b762a101a3912.tar.bz2
portage-c6e3af2b1e419d70443a74575e9b762a101a3912.zip
binpkg-multi-instance 7 of 7
Support "profile-formats = build-id" setting for layout.conf. When this is enabled in layout.conf of the containing repository, a dependency atom in the profile can refer to a specific build, using the build-id that is assigned when FEATURES=binpkg-multi-instance is enabled. A build-id atom is identical to a version-specific atom, except that the version is followed by a hyphen and an integer build-id. With the build-id profile format, it is possible to assemble a system using specific builds of binary packages, as users of "binary" distros might be accustomed to. For example, an atom in the "packages" file can pull a specific build of a package into the @system set, and an atom in the "package.keywords" file can be used to modify the effective KEYWORDS of a specific build of a package. Refering to specific builds can be useful for a number of reasons. For example, if a particular build needs to undergo a large amount of testing in a complex environment in order to verify reliability, then it can be useful to lock a profile to a specific build that has been thoroughly tested.
-rw-r--r--man/portage.58
-rw-r--r--pym/_emerge/is_valid_package_atom.py5
-rw-r--r--pym/portage/_sets/ProfilePackageSet.py3
-rw-r--r--pym/portage/_sets/profiles.py3
-rw-r--r--pym/portage/dep/__init__.py38
-rw-r--r--pym/portage/package/ebuild/_config/KeywordsManager.py3
-rw-r--r--pym/portage/package/ebuild/_config/LocationsManager.py8
-rw-r--r--pym/portage/package/ebuild/_config/MaskManager.py21
-rw-r--r--pym/portage/package/ebuild/_config/UseManager.py14
-rw-r--r--pym/portage/package/ebuild/config.py15
-rw-r--r--pym/portage/repository/config.py2
-rw-r--r--pym/portage/tests/dep/test_isvalidatom.py8
-rw-r--r--pym/portage/tests/resolver/binpkg_multi_instance/test_build_id_profile_format.py134
-rw-r--r--pym/portage/util/__init__.py13
14 files changed, 237 insertions, 38 deletions
diff --git a/man/portage.5 b/man/portage.5
index 3b099ff06..e77fc6ee8 100644
--- a/man/portage.5
+++ b/man/portage.5
@@ -1220,7 +1220,7 @@ and the newer/faster "md5-dict" format. Default is to detect dirs.
The EAPI to use for profiles when unspecified. This attribute is
supported only if profile-default-eapi is included in profile-formats.
.TP
-.BR profile\-formats " = [pms] [portage-1] [portage-2] [profile-bashrcs] [profile-set] [profile-default-eapi]"
+.BR profile\-formats " = [pms] [portage-1] [portage-2] [profile-bashrcs] [profile-set] [profile-default-eapi] [build-id]"
Control functionality available to profiles in this repo such as which files
may be dirs, or the syntax available in parent files. Use "portage-2" if you're
unsure. The default is "portage-1-compat" mode which is meant to be compatible
@@ -1230,7 +1230,11 @@ Setting profile-bashrcs will enable the per-profile bashrc mechanism
profile \fBpackages\fR file to add atoms to the @profile package set.
See the profile \fBpackages\fR section for more information.
Setting profile-default-eapi enables support for the
-profile_eapi_when_unspecified attribute.
+profile_eapi_when_unspecified attribute. Setting build\-id allows
+dependency atoms in the profile to refer to specific builds (see the
+binpkg\-multi\-instance FEATURES setting in \fBmake.conf\fR(5)). A
+build\-id atom is identical to a version-specific atom, except that the
+version is followed by a hyphen and an integer build\-id.
.RE
.RE
diff --git a/pym/_emerge/is_valid_package_atom.py b/pym/_emerge/is_valid_package_atom.py
index 112afc1ec..17f764266 100644
--- a/pym/_emerge/is_valid_package_atom.py
+++ b/pym/_emerge/is_valid_package_atom.py
@@ -14,9 +14,10 @@ def insert_category_into_atom(atom, category):
ret = None
return ret
-def is_valid_package_atom(x, allow_repo=False):
+def is_valid_package_atom(x, allow_repo=False, allow_build_id=True):
if "/" not in x.split(":")[0]:
x2 = insert_category_into_atom(x, 'cat')
if x2 != None:
x = x2
- return isvalidatom(x, allow_blockers=False, allow_repo=allow_repo)
+ return isvalidatom(x, allow_blockers=False, allow_repo=allow_repo,
+ allow_build_id=allow_build_id)
diff --git a/pym/portage/_sets/ProfilePackageSet.py b/pym/portage/_sets/ProfilePackageSet.py
index 2fcafb659..fec937391 100644
--- a/pym/portage/_sets/ProfilePackageSet.py
+++ b/pym/portage/_sets/ProfilePackageSet.py
@@ -23,7 +23,8 @@ class ProfilePackageSet(PackageSet):
def load(self):
self._setAtoms(x for x in stack_lists(
[grabfile_package(os.path.join(y.location, "packages"),
- verify_eapi=True, eapi=y.eapi, eapi_default=None)
+ verify_eapi=True, eapi=y.eapi, eapi_default=None,
+ allow_build_id=y.allow_build_id)
for y in self._profiles
if "profile-set" in y.profile_formats],
incremental=1) if x[:1] != "*")
diff --git a/pym/portage/_sets/profiles.py b/pym/portage/_sets/profiles.py
index ccb343210..bccc02e7c 100644
--- a/pym/portage/_sets/profiles.py
+++ b/pym/portage/_sets/profiles.py
@@ -34,7 +34,8 @@ class PackagesSystemSet(PackageSet):
(self._profiles,), level=logging.DEBUG, noiselevel=-1)
mylist = [grabfile_package(os.path.join(x.location, "packages"),
- verify_eapi=True, eapi=x.eapi, eapi_default=None)
+ verify_eapi=True, eapi=x.eapi, eapi_default=None,
+ allow_build_id=x.allow_build_id)
for x in self._profiles]
if debug:
diff --git a/pym/portage/dep/__init__.py b/pym/portage/dep/__init__.py
index a8c748dba..0a13d9f00 100644
--- a/pym/portage/dep/__init__.py
+++ b/pym/portage/dep/__init__.py
@@ -1193,11 +1193,11 @@ class Atom(_unicode):
self.overlap = self._overlap(forbid=forbid_overlap)
def __new__(cls, s, unevaluated_atom=None, allow_wildcard=False, allow_repo=None,
- _use=None, eapi=None, is_valid_flag=None):
+ _use=None, eapi=None, is_valid_flag=None, allow_build_id=None):
return _unicode.__new__(cls, s)
def __init__(self, s, unevaluated_atom=None, allow_wildcard=False, allow_repo=None,
- _use=None, eapi=None, is_valid_flag=None):
+ _use=None, eapi=None, is_valid_flag=None, allow_build_id=None):
if isinstance(s, Atom):
# This is an efficiency assertion, to ensure that the Atom
# constructor is not called redundantly.
@@ -1218,8 +1218,13 @@ class Atom(_unicode):
# Ignore allow_repo when eapi is specified.
allow_repo = eapi_attrs.repo_deps
else:
+ # These parameters have "smart" defaults that are only
+ # applied when the caller does not explicitly pass in a
+ # True or False value.
if allow_repo is None:
allow_repo = True
+ if allow_build_id is None:
+ allow_build_id = True
blocker_prefix = ""
if "!" == s[:1]:
@@ -1234,6 +1239,7 @@ class Atom(_unicode):
blocker = False
self.__dict__['blocker'] = blocker
m = atom_re.match(s)
+ build_id = None
extended_syntax = False
extended_version = None
if m is None:
@@ -1270,8 +1276,22 @@ class Atom(_unicode):
slot = m.group(atom_re.groups - 2)
repo = m.group(atom_re.groups - 1)
use_str = m.group(atom_re.groups)
- if m.group(base + 4) is not None:
- raise InvalidAtom(self)
+ version = m.group(base + 4)
+ if version is not None:
+ if allow_build_id:
+ cpv_build_id = cpv
+ cpv = cp
+ cp = cp[:-len(version)]
+ build_id = cpv_build_id[len(cpv)+1:]
+ if len(build_id) > 1 and build_id[:1] == "0":
+ # Leading zeros are not allowed.
+ raise InvalidAtom(self)
+ try:
+ build_id = int(build_id)
+ except ValueError:
+ raise InvalidAtom(self)
+ else:
+ raise InvalidAtom(self)
elif m.group('star') is not None:
base = atom_re.groupindex['star']
op = '=*'
@@ -1334,6 +1354,7 @@ class Atom(_unicode):
self.__dict__['slot_operator'] = None
self.__dict__['operator'] = op
self.__dict__['extended_syntax'] = extended_syntax
+ self.__dict__['build_id'] = build_id
if not (repo is None or allow_repo):
raise InvalidAtom(self)
@@ -1879,7 +1900,7 @@ def dep_getusedeps( depend ):
return tuple(use_list)
def isvalidatom(atom, allow_blockers=False, allow_wildcard=False,
- allow_repo=False, eapi=None):
+ allow_repo=False, eapi=None, allow_build_id=False):
"""
Check to see if a depend atom is valid
@@ -1904,7 +1925,8 @@ def isvalidatom(atom, allow_blockers=False, allow_wildcard=False,
try:
if not isinstance(atom, Atom):
atom = Atom(atom, allow_wildcard=allow_wildcard,
- allow_repo=allow_repo, eapi=eapi)
+ allow_repo=allow_repo, eapi=eapi,
+ allow_build_id=allow_build_id)
if not allow_blockers and atom.blocker:
return False
return True
@@ -2109,6 +2131,7 @@ def match_from_list(mydep, candidate_list):
mycpv = mydep.cpv
mycpv_cps = catpkgsplit(mycpv) # Can be None if not specific
slot = mydep.slot
+ build_id = mydep.build_id
if not mycpv_cps:
cat, pkg = catsplit(mycpv)
@@ -2183,6 +2206,9 @@ def match_from_list(mydep, candidate_list):
xcpv = remove_slot(x)
if not cpvequal(xcpv, mycpv):
continue
+ if (build_id is not None and
+ getattr(xcpv, "build_id", None) != build_id):
+ continue
mylist.append(x)
elif operator == "=*": # glob match
diff --git a/pym/portage/package/ebuild/_config/KeywordsManager.py b/pym/portage/package/ebuild/_config/KeywordsManager.py
index e1a8e2b5f..72e24b961 100644
--- a/pym/portage/package/ebuild/_config/KeywordsManager.py
+++ b/pym/portage/package/ebuild/_config/KeywordsManager.py
@@ -22,7 +22,8 @@ class KeywordsManager(object):
rawpkeywords = [grabdict_package(
os.path.join(x.location, "package.keywords"),
recursive=x.portage1_directories,
- verify_eapi=True, eapi=x.eapi, eapi_default=None)
+ verify_eapi=True, eapi=x.eapi, eapi_default=None,
+ allow_build_id=x.allow_build_id)
for x in profiles]
for pkeyworddict in rawpkeywords:
if not pkeyworddict:
diff --git a/pym/portage/package/ebuild/_config/LocationsManager.py b/pym/portage/package/ebuild/_config/LocationsManager.py
index 34b33e999..55b8c089a 100644
--- a/pym/portage/package/ebuild/_config/LocationsManager.py
+++ b/pym/portage/package/ebuild/_config/LocationsManager.py
@@ -31,7 +31,8 @@ _PORTAGE1_DIRECTORIES = frozenset([
'use.mask', 'use.force'])
_profile_node = collections.namedtuple('_profile_node',
- 'location portage1_directories user_config profile_formats eapi')
+ ('location', 'portage1_directories', 'user_config',
+ 'profile_formats', 'eapi', 'allow_build_id'))
_allow_parent_colon = frozenset(
["portage-2"])
@@ -142,7 +143,8 @@ class LocationsManager(object):
_profile_node(custom_prof, True, True,
('profile-bashrcs', 'profile-set'),
read_corresponding_eapi_file(
- custom_prof + os.sep, default=None)))
+ custom_prof + os.sep, default=None),
+ True))
del custom_prof
self.profiles = tuple(self.profiles)
@@ -253,7 +255,7 @@ class LocationsManager(object):
self.profiles.append(currentPath)
self.profiles_complex.append(
_profile_node(currentPath, allow_directories, False,
- current_formats, eapi))
+ current_formats, eapi, 'build-id' in current_formats))
def _expand_parent_colon(self, parentsFile, parentPath,
repo_loc, repositories):
diff --git a/pym/portage/package/ebuild/_config/MaskManager.py b/pym/portage/package/ebuild/_config/MaskManager.py
index 55c8c7a08..44aba23bb 100644
--- a/pym/portage/package/ebuild/_config/MaskManager.py
+++ b/pym/portage/package/ebuild/_config/MaskManager.py
@@ -40,7 +40,9 @@ class MaskManager(object):
pmask_cache[loc] = grabfile_package(path,
recursive=repo_config.portage1_profiles,
remember_source_file=True, verify_eapi=True,
- eapi_default=repo_config.eapi)
+ eapi_default=repo_config.eapi,
+ allow_build_id=("build-id"
+ in repo_config.profile_formats))
if repo_config.portage1_profiles_compat and os.path.isdir(path):
warnings.warn(_("Repository '%(repo_name)s' is implicitly using "
"'portage-1' profile format in its profiles/package.mask, but "
@@ -107,7 +109,8 @@ class MaskManager(object):
continue
repo_lines = grabfile_package(os.path.join(repo.location, "profiles", "package.unmask"), \
recursive=1, remember_source_file=True,
- verify_eapi=True, eapi_default=repo.eapi)
+ verify_eapi=True, eapi_default=repo.eapi,
+ allow_build_id=("build-id" in repo.profile_formats))
lines = stack_lists([repo_lines], incremental=1, \
remember_source_file=True, warn_for_unmatched_removal=True,
strict_warn_for_unmatched_removal=strict_umatched_removal)
@@ -122,13 +125,15 @@ class MaskManager(object):
os.path.join(x.location, "package.mask"),
recursive=x.portage1_directories,
remember_source_file=True, verify_eapi=True,
- eapi=x.eapi, eapi_default=None))
+ eapi=x.eapi, eapi_default=None,
+ allow_build_id=x.allow_build_id))
if x.portage1_directories:
profile_pkgunmasklines.append(grabfile_package(
os.path.join(x.location, "package.unmask"),
recursive=x.portage1_directories,
remember_source_file=True, verify_eapi=True,
- eapi=x.eapi, eapi_default=None))
+ eapi=x.eapi, eapi_default=None,
+ allow_build_id=x.allow_build_id))
profile_pkgmasklines = stack_lists(profile_pkgmasklines, incremental=1, \
remember_source_file=True, warn_for_unmatched_removal=True,
strict_warn_for_unmatched_removal=strict_umatched_removal)
@@ -143,10 +148,14 @@ class MaskManager(object):
if user_config:
user_pkgmasklines = grabfile_package(
os.path.join(abs_user_config, "package.mask"), recursive=1, \
- allow_wildcard=True, allow_repo=True, remember_source_file=True, verify_eapi=False)
+ allow_wildcard=True, allow_repo=True,
+ remember_source_file=True, verify_eapi=False,
+ allow_build_id=True)
user_pkgunmasklines = grabfile_package(
os.path.join(abs_user_config, "package.unmask"), recursive=1, \
- allow_wildcard=True, allow_repo=True, remember_source_file=True, verify_eapi=False)
+ allow_wildcard=True, allow_repo=True,
+ remember_source_file=True, verify_eapi=False,
+ allow_build_id=True)
#Stack everything together. At this point, only user_pkgmasklines may contain -atoms.
#Don't warn for unmatched -atoms here, since we don't do it for any other user config file.
diff --git a/pym/portage/package/ebuild/_config/UseManager.py b/pym/portage/package/ebuild/_config/UseManager.py
index 60d5f92f5..a93ea5c50 100644
--- a/pym/portage/package/ebuild/_config/UseManager.py
+++ b/pym/portage/package/ebuild/_config/UseManager.py
@@ -153,7 +153,8 @@ class UseManager(object):
return tuple(ret)
def _parse_file_to_dict(self, file_name, juststrings=False, recursive=True,
- eapi_filter=None, user_config=False, eapi=None, eapi_default="0"):
+ eapi_filter=None, user_config=False, eapi=None, eapi_default="0",
+ allow_build_id=False):
"""
@param file_name: input file name
@type file_name: str
@@ -176,6 +177,9 @@ class UseManager(object):
@param eapi_default: the default EAPI which applies if the
current profile node does not define a local EAPI
@type eapi_default: str
+ @param allow_build_id: allow atoms to specify a particular
+ build-id
+ @type allow_build_id: bool
@rtype: tuple
@return: collection of USE flags
"""
@@ -192,7 +196,7 @@ class UseManager(object):
file_dict = grabdict_package(file_name, recursive=recursive,
allow_wildcard=extended_syntax, allow_repo=extended_syntax,
verify_eapi=(not extended_syntax), eapi=eapi,
- eapi_default=eapi_default)
+ eapi_default=eapi_default, allow_build_id=allow_build_id)
if eapi is not None and eapi_filter is not None and not eapi_filter(eapi):
if file_dict:
writemsg(_("--- EAPI '%s' does not support '%s': '%s'\n") %
@@ -262,7 +266,8 @@ class UseManager(object):
for repo in repositories.repos_with_profiles():
ret[repo.name] = self._parse_file_to_dict(
os.path.join(repo.location, "profiles", file_name),
- eapi_filter=eapi_filter, eapi_default=repo.eapi)
+ eapi_filter=eapi_filter, eapi_default=repo.eapi,
+ allow_build_id=("build-id" in repo.profile_formats))
return ret
def _parse_profile_files_to_tuple_of_tuples(self, file_name, locations,
@@ -279,7 +284,8 @@ class UseManager(object):
os.path.join(profile.location, file_name), juststrings,
recursive=profile.portage1_directories, eapi_filter=eapi_filter,
user_config=profile.user_config, eapi=profile.eapi,
- eapi_default=None) for profile in locations)
+ eapi_default=None, allow_build_id=profile.allow_build_id)
+ for profile in locations)
def _parse_repository_usealiases(self, repositories):
ret = {}
diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py
index 3c0018f9e..3a4007bcb 100644
--- a/pym/portage/package/ebuild/config.py
+++ b/pym/portage/package/ebuild/config.py
@@ -570,7 +570,8 @@ class config(object):
try:
packages_list = [grabfile_package(
os.path.join(x.location, "packages"),
- verify_eapi=True, eapi=x.eapi, eapi_default=None)
+ verify_eapi=True, eapi=x.eapi, eapi_default=None,
+ allow_build_id=x.allow_build_id)
for x in profiles_complex]
except IOError as e:
if e.errno == IsADirectory.errno:
@@ -708,7 +709,8 @@ class config(object):
#package.properties
propdict = grabdict_package(os.path.join(
abs_user_config, "package.properties"), recursive=1, allow_wildcard=True, \
- allow_repo=True, verify_eapi=False)
+ allow_repo=True, verify_eapi=False,
+ allow_build_id=True)
v = propdict.pop("*/*", None)
if v is not None:
if "ACCEPT_PROPERTIES" in self.configdict["conf"]:
@@ -722,7 +724,8 @@ class config(object):
d = grabdict_package(os.path.join(
abs_user_config, "package.accept_restrict"),
recursive=True, allow_wildcard=True,
- allow_repo=True, verify_eapi=False)
+ allow_repo=True, verify_eapi=False,
+ allow_build_id=True)
v = d.pop("*/*", None)
if v is not None:
if "ACCEPT_RESTRICT" in self.configdict["conf"]:
@@ -735,7 +738,8 @@ class config(object):
#package.env
penvdict = grabdict_package(os.path.join(
abs_user_config, "package.env"), recursive=1, allow_wildcard=True, \
- allow_repo=True, verify_eapi=False)
+ allow_repo=True, verify_eapi=False,
+ allow_build_id=True)
v = penvdict.pop("*/*", None)
if v is not None:
global_wildcard_conf = {}
@@ -765,7 +769,8 @@ class config(object):
bashrc = grabdict_package(os.path.join(profile.location,
"package.bashrc"), recursive=1, allow_wildcard=True,
allow_repo=True, verify_eapi=True,
- eapi=profile.eapi, eapi_default=None)
+ eapi=profile.eapi, eapi_default=None,
+ allow_build_id=profile.allow_build_id)
if not bashrc:
continue
diff --git a/pym/portage/repository/config.py b/pym/portage/repository/config.py
index a884156ba..5da181040 100644
--- a/pym/portage/repository/config.py
+++ b/pym/portage/repository/config.py
@@ -42,7 +42,7 @@ _invalid_path_char_re = re.compile(r'[^a-zA-Z0-9._\-+:/]')
_valid_profile_formats = frozenset(
['pms', 'portage-1', 'portage-2', 'profile-bashrcs', 'profile-set',
- 'profile-default-eapi'])
+ 'profile-default-eapi', 'build-id'])
_portage1_profiles_allow_directories = frozenset(
["portage-1-compat", "portage-1", 'portage-2'])
diff --git a/pym/portage/tests/dep/test_isvalidatom.py b/pym/portage/tests/dep/test_isvalidatom.py
index 67ba60398..9d3367aab 100644
--- a/pym/portage/tests/dep/test_isvalidatom.py
+++ b/pym/portage/tests/dep/test_isvalidatom.py
@@ -5,11 +5,13 @@ from portage.tests import TestCase
from portage.dep import isvalidatom
class IsValidAtomTestCase(object):
- def __init__(self, atom, expected, allow_wildcard=False, allow_repo=False):
+ def __init__(self, atom, expected, allow_wildcard=False,
+ allow_repo=False, allow_build_id=False):
self.atom = atom
self.expected = expected
self.allow_wildcard = allow_wildcard
self.allow_repo = allow_repo
+ self.allow_build_id = allow_build_id
class IsValidAtom(TestCase):
@@ -154,5 +156,7 @@ class IsValidAtom(TestCase):
else:
atom_type = "invalid"
self.assertEqual(bool(isvalidatom(test_case.atom, allow_wildcard=test_case.allow_wildcard,
- allow_repo=test_case.allow_repo)), test_case.expected,
+ allow_repo=test_case.allow_repo,
+ allow_build_id=test_case.allow_build_id)),
+ test_case.expected,
msg="isvalidatom(%s) != %s" % (test_case.atom, test_case.expected))
diff --git a/pym/portage/tests/resolver/binpkg_multi_instance/test_build_id_profile_format.py b/pym/portage/tests/resolver/binpkg_multi_instance/test_build_id_profile_format.py
new file mode 100644
index 000000000..0397509f8
--- /dev/null
+++ b/pym/portage/tests/resolver/binpkg_multi_instance/test_build_id_profile_format.py
@@ -0,0 +1,134 @@
+# Copyright 2015 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 BuildIdProfileFormatTestCase(TestCase):
+
+ def testBuildIdProfileFormat(self):
+
+ profile = {
+ "packages": ("=app-misc/A-1-2",),
+ "package.provided": ("sys-libs/zlib-1.2.8-r1",),
+ }
+
+ repo_configs = {
+ "test_repo": {
+ "layout.conf": (
+ "profile-formats = build-id profile-set",
+ ),
+ }
+ }
+
+ user_config = {
+ "make.conf":
+ (
+ "FEATURES=\"binpkg-multi-instance\"",
+ ),
+ }
+
+ ebuilds = {
+ "app-misc/A-1" : {
+ "EAPI": "5",
+ "RDEPEND": "sys-libs/zlib dev-libs/B[foo]",
+ "DEPEND": "sys-libs/zlib dev-libs/B[foo]",
+ },
+ "dev-libs/B-1" : {
+ "EAPI": "5",
+ "IUSE": "foo",
+ },
+ }
+
+ binpkgs = (
+ ("app-misc/A-1", {
+ "EAPI": "5",
+ "BUILD_ID": "1",
+ "BUILD_TIME": "1",
+ "RDEPEND": "sys-libs/zlib dev-libs/B[foo]",
+ "DEPEND": "sys-libs/zlib dev-libs/B[foo]",
+ }),
+ ("app-misc/A-1", {
+ "EAPI": "5",
+ "BUILD_ID": "2",
+ "BUILD_TIME": "2",
+ "RDEPEND": "sys-libs/zlib dev-libs/B[foo]",
+ "DEPEND": "sys-libs/zlib dev-libs/B[foo]",
+ }),
+ ("app-misc/A-1", {
+ "EAPI": "5",
+ "BUILD_ID": "3",
+ "BUILD_TIME": "3",
+ "RDEPEND": "sys-libs/zlib dev-libs/B[foo]",
+ "DEPEND": "sys-libs/zlib dev-libs/B[foo]",
+ }),
+ ("dev-libs/B-1", {
+ "EAPI": "5",
+ "IUSE": "foo",
+ "USE": "",
+ "BUILD_ID": "1",
+ "BUILD_TIME": "1",
+ }),
+ ("dev-libs/B-1", {
+ "EAPI": "5",
+ "IUSE": "foo",
+ "USE": "foo",
+ "BUILD_ID": "2",
+ "BUILD_TIME": "2",
+ }),
+ ("dev-libs/B-1", {
+ "EAPI": "5",
+ "IUSE": "foo",
+ "USE": "",
+ "BUILD_ID": "3",
+ "BUILD_TIME": "3",
+ }),
+ )
+
+ installed = {
+ "app-misc/A-1" : {
+ "EAPI": "5",
+ "BUILD_ID": "1",
+ "BUILD_TIME": "1",
+ "RDEPEND": "sys-libs/zlib",
+ "DEPEND": "sys-libs/zlib",
+ },
+ "dev-libs/B-1" : {
+ "EAPI": "5",
+ "IUSE": "foo",
+ "USE": "foo",
+ "BUILD_ID": "2",
+ "BUILD_TIME": "2",
+ },
+ }
+
+ world = ()
+
+ test_cases = (
+
+ ResolverPlaygroundTestCase(
+ ["@world"],
+ options = {"--emptytree": True, "--usepkgonly": True},
+ success = True,
+ mergelist = [
+ "[binary]dev-libs/B-1-2",
+ "[binary]app-misc/A-1-2"
+ ]
+ ),
+
+ )
+
+ playground = ResolverPlayground(debug=False,
+ binpkgs=binpkgs, ebuilds=ebuilds, installed=installed,
+ repo_configs=repo_configs, profile=profile,
+ user_config=user_config, world=world)
+ try:
+ for test_case in test_cases:
+ playground.run_TestCase(test_case)
+ self.assertEqual(test_case.test_success, True,
+ test_case.fail_msg)
+ finally:
+ # Disable debug so that cleanup works.
+ #playground.debug = False
+ playground.cleanup()
diff --git a/pym/portage/util/__init__.py b/pym/portage/util/__init__.py
index b6f57873d..aeb951e26 100644
--- a/pym/portage/util/__init__.py
+++ b/pym/portage/util/__init__.py
@@ -424,7 +424,8 @@ def read_corresponding_eapi_file(filename, default="0"):
return default
return eapi
-def grabdict_package(myfilename, juststrings=0, recursive=0, allow_wildcard=False, allow_repo=False,
+def grabdict_package(myfilename, juststrings=0, recursive=0,
+ allow_wildcard=False, allow_repo=False, allow_build_id=False,
verify_eapi=False, eapi=None, eapi_default="0"):
""" Does the same thing as grabdict except it validates keys
with isvalidatom()"""
@@ -447,7 +448,8 @@ def grabdict_package(myfilename, juststrings=0, recursive=0, allow_wildcard=Fals
for k, v in d.items():
try:
k = Atom(k, allow_wildcard=allow_wildcard,
- allow_repo=allow_repo, eapi=eapi)
+ allow_repo=allow_repo,
+ allow_build_id=allow_build_id, eapi=eapi)
except InvalidAtom as e:
writemsg(_("--- Invalid atom in %s: %s\n") % (filename, e),
noiselevel=-1)
@@ -460,7 +462,8 @@ def grabdict_package(myfilename, juststrings=0, recursive=0, allow_wildcard=Fals
return atoms
-def grabfile_package(myfilename, compatlevel=0, recursive=0, allow_wildcard=False, allow_repo=False,
+def grabfile_package(myfilename, compatlevel=0, recursive=0,
+ allow_wildcard=False, allow_repo=False, allow_build_id=False,
remember_source_file=False, verify_eapi=False, eapi=None,
eapi_default="0"):
@@ -480,7 +483,9 @@ def grabfile_package(myfilename, compatlevel=0, recursive=0, allow_wildcard=Fals
if pkg[:1] == '*' and mybasename == 'packages':
pkg = pkg[1:]
try:
- pkg = Atom(pkg, allow_wildcard=allow_wildcard, allow_repo=allow_repo, eapi=eapi)
+ pkg = Atom(pkg, allow_wildcard=allow_wildcard,
+ allow_repo=allow_repo, allow_build_id=allow_build_id,
+ eapi=eapi)
except InvalidAtom as e:
writemsg(_("--- Invalid atom in %s: %s\n") % (source_file, e),
noiselevel=-1)