From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) by finch.gentoo.org (Postfix) with ESMTP id C87D3138CA3 for ; Wed, 4 Mar 2015 21:37:58 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id EB0C6E08EC; Wed, 4 Mar 2015 21:37:56 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 6269AE08CD for ; Wed, 4 Mar 2015 21:37:56 +0000 (UTC) Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 5ADB0340712 for ; Wed, 4 Mar 2015 21:37:55 +0000 (UTC) Received: from localhost.localdomain (localhost [127.0.0.1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 85E44130CB for ; Wed, 4 Mar 2015 21:37:52 +0000 (UTC) From: "Zac Medico" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Zac Medico" Message-ID: <1425504727.c6e3af2b1e419d70443a74575e9b762a101a3912.zmedico@gentoo> Subject: [gentoo-commits] proj/portage:master commit in: pym/portage/util/, pym/_emerge/, pym/portage/dep/, pym/portage/_sets/, ... X-VCS-Repository: proj/portage X-VCS-Files: man/portage.5 pym/_emerge/is_valid_package_atom.py pym/portage/_sets/ProfilePackageSet.py pym/portage/_sets/profiles.py pym/portage/dep/__init__.py pym/portage/package/ebuild/_config/KeywordsManager.py pym/portage/package/ebuild/_config/LocationsManager.py pym/portage/package/ebuild/_config/MaskManager.py pym/portage/package/ebuild/_config/UseManager.py pym/portage/package/ebuild/config.py pym/portage/repository/config.py pym/portage/tests/dep/test_isvalidatom.py pym/portage/tests/resolver/binpkg_multi_instance/test_build_id_profile_format.py pym/portage/util/__init__.py X-VCS-Directories: pym/portage/_sets/ pym/portage/dep/ pym/_emerge/ pym/portage/util/ man/ pym/portage/package/ebuild/ pym/portage/tests/resolver/binpkg_multi_instance/ pym/portage/tests/dep/ pym/portage/package/ebuild/_config/ pym/portage/repository/ X-VCS-Committer: zmedico X-VCS-Committer-Name: Zac Medico X-VCS-Revision: c6e3af2b1e419d70443a74575e9b762a101a3912 X-VCS-Branch: master Date: Wed, 4 Mar 2015 21:37:52 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Archives-Salt: 3f389598-5ae2-4425-80af-0d74fa0bc3b9 X-Archives-Hash: 5e78e540fa0fdfcbc53b515509539a16 commit: c6e3af2b1e419d70443a74575e9b762a101a3912 Author: Zac Medico gentoo org> AuthorDate: Wed Feb 18 02:31:28 2015 +0000 Commit: Zac Medico gentoo 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)