From ebf5d1a64a4a40a0efeba3b038122eef375ace94 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Fri, 24 Aug 2012 21:11:04 -0700 Subject: [PATCH] EAPI 5 stable use.mask/force for bug #431078 --- pym/_emerge/Package.py | 4 + .../package/ebuild/_config/KeywordsManager.py | 27 +++++++ .../package/ebuild/_config/UseManager.py | 79 +++++++++++++++++-- pym/portage/package/ebuild/config.py | 5 ++ pym/portage/versions.py | 14 ++++ 5 files changed, 122 insertions(+), 7 deletions(-) diff --git a/pym/_emerge/Package.py b/pym/_emerge/Package.py index c8a0c9042..85fc59773 100644 --- a/pym/_emerge/Package.py +++ b/pym/_emerge/Package.py @@ -127,6 +127,10 @@ class Package(Task): self._validate_deps() return self._validated_atoms + @property + def stable(self): + return self.cpv.stable + @classmethod def _gen_hash_key(cls, cpv=None, installed=None, onlydeps=None, operation=None, repo_name=None, root_config=None, diff --git a/pym/portage/package/ebuild/_config/KeywordsManager.py b/pym/portage/package/ebuild/_config/KeywordsManager.py index 74c7d0a2c..e42f490aa 100644 --- a/pym/portage/package/ebuild/_config/KeywordsManager.py +++ b/pym/portage/package/ebuild/_config/KeywordsManager.py @@ -93,6 +93,33 @@ class KeywordsManager(object): keywords.extend(pkg_keywords) return stack_lists(keywords, incremental=True) + def isStable(self, pkg, global_accept_keywords, backuped_accept_keywords): + mygroups = self.getKeywords(pkg, None, pkg._metadata["KEYWORDS"], None) + pgroups = global_accept_keywords.split() + + unmaskgroups = self.getPKeywords(pkg, None, None, + global_accept_keywords) + pgroups.extend(unmaskgroups) + + egroups = backuped_accept_keywords.split() + + if unmaskgroups or egroups: + pgroups = self._getEgroups(egroups, pgroups) + else: + pgroups = set(pgroups) + + if self._getMissingKeywords(pkg, pgroups, mygroups): + return False + + # If replacing all keywords with unstable variants would mask the + # package, then it's not considered stable. + unstable = [] + for kw in mygroups: + if kw[:1] != "~": + kw = "~" + kw + unstable.append(kw) + + return bool(self._getMissingKeywords(pkg, pgroups, set(unstable))) def getMissingKeywords(self, cpv, diff --git a/pym/portage/package/ebuild/_config/UseManager.py b/pym/portage/package/ebuild/_config/UseManager.py index e1ec7f4a0..94ff286c8 100644 --- a/pym/portage/package/ebuild/_config/UseManager.py +++ b/pym/portage/package/ebuild/_config/UseManager.py @@ -14,6 +14,9 @@ from portage.versions import cpv_getkey, _pkg_str from portage.package.ebuild._config.helper import ordered_by_atom_specificity +_no_stable_mask_eapis = frozenset( + ["0", "1", "2", "3", "4", "4-python", "4-slot-abi"]) + class UseManager(object): def __init__(self, repositories, profiles, abs_user_config, user_config=True): @@ -56,19 +59,41 @@ class UseManager(object): self._repo_puse_dict = self._parse_repository_files_to_dict_of_dicts("package.use", repositories) self._usemask_list = self._parse_profile_files_to_tuple_of_tuples("use.mask", profiles) + self._usestablemask_list = \ + self._parse_profile_files_to_tuple_of_tuples("use.stable.mask", + profiles, eapi_filter=self._stable_mask_eapi_filter) self._useforce_list = self._parse_profile_files_to_tuple_of_tuples("use.force", profiles) + self._usestableforce_list = \ + self._parse_profile_files_to_tuple_of_tuples("use.stable.force", + profiles, eapi_filter=self._stable_mask_eapi_filter) self._pusemask_list = self._parse_profile_files_to_tuple_of_dicts("package.use.mask", profiles) + self._pusestablemask_list = \ + self._parse_profile_files_to_tuple_of_dicts("package.use.stable.mask", + profiles, eapi_filter=self._stable_mask_eapi_filter) self._pkgprofileuse = self._parse_profile_files_to_tuple_of_dicts("package.use", profiles, juststrings=True) self._puseforce_list = self._parse_profile_files_to_tuple_of_dicts("package.use.force", profiles) + self._pusestableforce_list = \ + self._parse_profile_files_to_tuple_of_dicts("package.use.stable.force", + profiles, eapi_filter=self._stable_mask_eapi_filter) self._pusedict = self._parse_user_files_to_extatomdict("package.use", abs_user_config, user_config) self.repositories = repositories - - def _parse_file_to_tuple(self, file_name, recursive=True): + + @staticmethod + def _stable_mask_eapi_filter(eapi): + return eapi not in _no_stable_mask_eapis + + def _parse_file_to_tuple(self, file_name, recursive=True, eapi_filter=None): ret = [] lines = grabfile(file_name, recursive=recursive) eapi = read_corresponding_eapi_file(file_name) + if eapi_filter is not None and not eapi_filter(eapi): + if lines: + writemsg(_("--- EAPI '%s' does not support '%s': '%s'\n") % + (eapi, os.path.basename(file_name), file_name), + noiselevel=-1) + return () useflag_re = _get_useflag_re(eapi) for prefixed_useflag in lines: if prefixed_useflag[:1] == "-": @@ -82,11 +107,17 @@ class UseManager(object): ret.append(prefixed_useflag) return tuple(ret) - def _parse_file_to_dict(self, file_name, juststrings=False, recursive=True): + def _parse_file_to_dict(self, file_name, juststrings=False, recursive=True, eapi_filter=None): ret = {} location_dict = {} file_dict = grabdict_package(file_name, recursive=recursive, verify_eapi=True) eapi = read_corresponding_eapi_file(file_name) + if eapi_filter is not None and not eapi_filter(eapi): + if file_dict: + writemsg(_("--- EAPI '%s' does not support '%s': '%s'\n") % + (eapi, os.path.basename(file_name), file_name), + noiselevel=-1) + return ret useflag_re = _get_useflag_re(eapi) for k, v in file_dict.items(): useflags = [] @@ -131,16 +162,18 @@ class UseManager(object): ret[repo.name] = self._parse_file_to_dict(os.path.join(repo.location, "profiles", file_name)) return ret - def _parse_profile_files_to_tuple_of_tuples(self, file_name, locations): + def _parse_profile_files_to_tuple_of_tuples(self, file_name, locations, + eapi_filter=None): return tuple(self._parse_file_to_tuple( os.path.join(profile.location, file_name), - recursive=profile.portage1_directories) + recursive=profile.portage1_directories, eapi_filter=eapi_filter) for profile in locations) - def _parse_profile_files_to_tuple_of_dicts(self, file_name, locations, juststrings=False): + def _parse_profile_files_to_tuple_of_dicts(self, file_name, locations, + juststrings=False, eapi_filter=None): return tuple(self._parse_file_to_dict( os.path.join(profile.location, file_name), juststrings, - recursive=profile.portage1_directories) + recursive=profile.portage1_directories, eapi_filter=eapi_filter) for profile in locations) def getUseMask(self, pkg=None): @@ -171,14 +204,30 @@ class UseManager(object): pkg_usemask = ordered_by_atom_specificity(cpdict, pkg) if pkg_usemask: usemask.extend(pkg_usemask) + + try: + stable = pkg.stable + except AttributeError: + # KEYWORDS is unavailable (prior to "depend" phase) + stable = False + for i, pusemask_dict in enumerate(self._pusemask_list): if self._usemask_list[i]: usemask.append(self._usemask_list[i]) + if stable and self._usestablemask_list[i]: + usemask.append(self._usestablemask_list[i]) cpdict = pusemask_dict.get(cp) if cpdict: pkg_usemask = ordered_by_atom_specificity(cpdict, pkg) if pkg_usemask: usemask.extend(pkg_usemask) + if stable: + cpdict = self._pusestablemask_list[i].get(cp) + if cpdict: + pkg_usemask = ordered_by_atom_specificity(cpdict, pkg) + if pkg_usemask: + usemask.extend(pkg_usemask) + return frozenset(stack_lists(usemask, incremental=True)) def getUseForce(self, pkg=None): @@ -205,14 +254,30 @@ class UseManager(object): pkg_useforce = ordered_by_atom_specificity(cpdict, pkg) if pkg_useforce: useforce.extend(pkg_useforce) + + try: + stable = pkg.stable + except AttributeError: + # KEYWORDS is unavailable (prior to "depend" phase) + stable = False + for i, puseforce_dict in enumerate(self._puseforce_list): if self._useforce_list[i]: useforce.append(self._useforce_list[i]) + if stable and self._usestableforce_list[i]: + useforce.append(self._usestableforce_list[i]) cpdict = puseforce_dict.get(cp) if cpdict: pkg_useforce = ordered_by_atom_specificity(cpdict, pkg) if pkg_useforce: useforce.extend(pkg_useforce) + if stable: + cpdict = self._pusestableforce_list[i].get(cp) + if cpdict: + pkg_useforce = ordered_by_atom_specificity(cpdict, pkg) + if pkg_useforce: + useforce.extend(pkg_useforce) + return frozenset(stack_lists(useforce, incremental=True)) def getPUSE(self, pkg): diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py index 94c0bbc79..871831fb6 100644 --- a/pym/portage/package/ebuild/config.py +++ b/pym/portage/package/ebuild/config.py @@ -1653,6 +1653,11 @@ class config(object): return x return None + def _isStable(self, pkg): + return self._keywords_manager.isStable(pkg, + self.get("ACCEPT_KEYWORDS", ""), + self.configdict["backupenv"].get("ACCEPT_KEYWORDS", "")) + def _getKeywords(self, cpv, metadata): return self._keywords_manager.getKeywords(cpv, metadata["SLOT"], \ metadata.get("KEYWORDS", ""), metadata.get("repository")) diff --git a/pym/portage/versions.py b/pym/portage/versions.py index 36eb8ac21..692256b24 100644 --- a/pym/portage/versions.py +++ b/pym/portage/versions.py @@ -396,6 +396,20 @@ class _pkg_str(_unicode): raise AttributeError("_pkg_str instances are immutable", self.__class__, name, value) + @property + def stable(self): + try: + return self._stable + except AttributeError: + try: + metadata = self._metadata + settings = self._settings + except AttributeError: + raise AttributeError('stable') + stable = settings._isStable(self) + self.__dict__['_stable'] = stable + return stable + def pkgsplit(mypkg, silent=1, eapi=None): """ @param mypkg: either a pv or cpv -- 2.26.2