public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/portage:master commit in: pym/portage/util/, pym/_emerge/, pym/portage/dep/, pym/portage/_sets/, ...
@ 2015-03-04 21:37 Zac Medico
  0 siblings, 0 replies; only message in thread
From: Zac Medico @ 2015-03-04 21:37 UTC (permalink / raw
  To: gentoo-commits

commit:     c6e3af2b1e419d70443a74575e9b762a101a3912
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Wed Feb 18 02:31:28 2015 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Wed Mar  4 21:32:07 2015 +0000
URL:        http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=c6e3af2b

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.

 man/portage.5                                      |   8 +-
 pym/_emerge/is_valid_package_atom.py               |   5 +-
 pym/portage/_sets/ProfilePackageSet.py             |   3 +-
 pym/portage/_sets/profiles.py                      |   3 +-
 pym/portage/dep/__init__.py                        |  38 +++++-
 .../package/ebuild/_config/KeywordsManager.py      |   3 +-
 .../package/ebuild/_config/LocationsManager.py     |   8 +-
 pym/portage/package/ebuild/_config/MaskManager.py  |  21 +++-
 pym/portage/package/ebuild/_config/UseManager.py   |  14 ++-
 pym/portage/package/ebuild/config.py               |  15 ++-
 pym/portage/repository/config.py                   |   2 +-
 pym/portage/tests/dep/test_isvalidatom.py          |   8 +-
 .../test_build_id_profile_format.py                | 134 +++++++++++++++++++++
 pym/portage/util/__init__.py                       |  13 +-
 14 files changed, 237 insertions(+), 38 deletions(-)

diff --git a/man/portage.5 b/man/portage.5
index 3b099ff..e77fc6e 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 112afc1..17f7642 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 2fcafb6..fec9373 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 ccb3432..bccc02e 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 a8c748d..0a13d9f 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 e1a8e2b..72e24b9 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 34b33e9..55b8c08 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 55c8c7a..44aba23 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 60d5f92..a93ea5c 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 3c0018f..3a4007b 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 a884156..5da1810 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 67ba603..9d3367a 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 0000000..0397509
--- /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 b6f5787..aeb951e 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)


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2015-03-04 21:37 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-03-04 21:37 [gentoo-commits] proj/portage:master commit in: pym/portage/util/, pym/_emerge/, pym/portage/dep/, pym/portage/_sets/, Zac Medico

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox