diff options
-rw-r--r-- | pym/_emerge/depgraph.py | 100 | ||||
-rw-r--r-- | pym/_emerge/resolver/backtracking.py | 7 | ||||
-rw-r--r-- | pym/portage/package/ebuild/getmaskingstatus.py | 2 | ||||
-rw-r--r-- | pym/portage/tests/resolver/ResolverPlayground.py | 10 | ||||
-rw-r--r-- | pym/portage/tests/resolver/test_autounmask.py | 24 |
5 files changed, 118 insertions, 25 deletions
diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 8558436bb..d095ce189 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -413,6 +413,7 @@ class _dynamic_depgraph_config(object): self._highest_pkg_cache = {} self._needed_unstable_keywords = backtrack_parameters.needed_unstable_keywords + self._needed_p_mask_changes = backtrack_parameters.needed_p_mask_changes self._needed_license_changes = backtrack_parameters.needed_license_changes self._needed_use_config_changes = backtrack_parameters.needed_use_config_changes self._runtime_pkg_mask = backtrack_parameters.runtime_pkg_mask @@ -2289,6 +2290,8 @@ class depgraph(object): if set(self._dynamic_config.digraph).intersection( \ self._dynamic_config._needed_unstable_keywords) or \ set(self._dynamic_config.digraph).intersection( \ + self._dynamic_config._needed_p_mask_changes) or \ + set(self._dynamic_config.digraph).intersection( \ self._dynamic_config._needed_use_config_changes) or \ set(self._dynamic_config.digraph).intersection( \ self._dynamic_config._needed_license_changes) : @@ -3278,17 +3281,22 @@ class depgraph(object): if pkg is not None: break - pkg, existing = \ - self._wrapped_select_pkg_highest_available_imp( - root, atom, onlydeps=onlydeps, - allow_use_changes=True, - allow_unstable_keywords=(not only_use_changes), - allow_license_changes=(not only_use_changes)) - - if pkg is not None and \ - pkg.installed and \ - not self._want_installed_pkg(pkg): - pkg = None + for allow_unmasks in (False, True): + if only_use_changes and allow_unmasks: + continue + + pkg, existing = \ + self._wrapped_select_pkg_highest_available_imp( + root, atom, onlydeps=onlydeps, + allow_use_changes=True, + allow_unstable_keywords=(not only_use_changes), + allow_license_changes=(not only_use_changes), + allow_unmasks=allow_unmasks) + + if pkg is not None and \ + pkg.installed and \ + not self._want_installed_pkg(pkg): + pkg = None if self._dynamic_config._need_restart: return None, None @@ -3300,7 +3308,7 @@ class depgraph(object): return pkg, existing - def _pkg_visibility_check(self, pkg, allow_unstable_keywords=False, allow_license_changes=False): + def _pkg_visibility_check(self, pkg, allow_unstable_keywords=False, allow_license_changes=False, allow_unmasks=False): if pkg.visible: return True @@ -3315,6 +3323,7 @@ class depgraph(object): masked_by_unstable_keywords = False missing_licenses = None masked_by_something_else = False + masked_by_p_mask = False for reason in mreasons: hint = reason.unmask_hint @@ -3323,6 +3332,8 @@ class depgraph(object): masked_by_something_else = True elif hint.key == "unstable keyword": masked_by_unstable_keywords = True + elif hint.key == "p_mask": + masked_by_p_mask = True elif hint.key == "license": missing_licenses = hint.value else: @@ -3335,15 +3346,20 @@ class depgraph(object): #If the package is already keyworded, remove the mask. masked_by_unstable_keywords = False + if pkg in self._dynamic_config._needed_p_mask_changes: + #If the package is already keyworded, remove the mask. + masked_by_p_mask = False + if missing_licenses: #If the needed licenses are already unmasked, remove the mask. missing_licenses.difference_update(self._dynamic_config._needed_license_changes.get(pkg, set())) - if not (masked_by_unstable_keywords or missing_licenses): + if not (masked_by_unstable_keywords or masked_by_p_mask or missing_licenses): #Package has already been unmasked. return True if (masked_by_unstable_keywords and not allow_unstable_keywords) or \ + (masked_by_p_mask and not allow_unmasks) or \ (missing_licenses and not allow_license_changes): #We are not allowed to do the needed changes. return False @@ -3354,7 +3370,13 @@ class depgraph(object): backtrack_infos.setdefault("config", {}) backtrack_infos["config"].setdefault("needed_unstable_keywords", set()) backtrack_infos["config"]["needed_unstable_keywords"].add(pkg) - + + if masked_by_p_mask: + self._dynamic_config._needed_p_mask_changes.add(pkg) + backtrack_infos = self._dynamic_config._backtrack_infos + backtrack_infos.setdefault("config", {}) + backtrack_infos["config"].setdefault("needed_p_mask_changes", set()) + backtrack_infos["config"]["needed_p_mask_changes"].add(pkg) if missing_licenses: self._dynamic_config._needed_license_changes.setdefault(pkg, set()).update(missing_licenses) @@ -3452,7 +3474,7 @@ class depgraph(object): return new_use def _wrapped_select_pkg_highest_available_imp(self, root, atom, onlydeps=False, \ - allow_use_changes=False, allow_unstable_keywords=False, allow_license_changes=False): + allow_use_changes=False, allow_unstable_keywords=False, allow_license_changes=False, allow_unmasks=False): root_config = self._frozen_config.roots[root] pkgsettings = self._frozen_config.pkgsettings[root] dbs = self._dynamic_config._filtered_trees[root]["dbs"] @@ -3588,7 +3610,8 @@ class depgraph(object): if not self._pkg_visibility_check(pkg, \ allow_unstable_keywords=allow_unstable_keywords, - allow_license_changes=allow_license_changes): + allow_license_changes=allow_license_changes, + allow_unmasks=allow_unmasks): continue # Enable upgrade or downgrade to a version @@ -3630,7 +3653,8 @@ class depgraph(object): "ebuild", Atom("=%s" % (pkg.cpv,))): if self._pkg_visibility_check(pkg_eb, \ allow_unstable_keywords=allow_unstable_keywords, - allow_license_changes=allow_license_changes): + allow_license_changes=allow_license_changes, + allow_unmasks=allow_unmasks): pkg_eb_visible = True break if not pkg_eb_visible: @@ -3638,7 +3662,8 @@ class depgraph(object): else: if not self._pkg_visibility_check(pkg_eb, \ allow_unstable_keywords=allow_unstable_keywords, - allow_license_changes=allow_license_changes): + allow_license_changes=allow_license_changes, + allow_unmasks=allow_unmasks): continue # Calculation of USE for unbuilt ebuilds is relatively @@ -3882,18 +3907,19 @@ class depgraph(object): for pkg in matched_packages: if pkg.installed and self._pkg_visibility_check(pkg, \ allow_unstable_keywords=allow_unstable_keywords, - allow_license_changes=allow_license_changes): + allow_license_changes=allow_license_changes, + allow_unmasks=allow_unmasks): return pkg, existing_node visible_matches = [] if matched_oldpkg: visible_matches = [pkg.cpv for pkg in matched_oldpkg \ if self._pkg_visibility_check(pkg, allow_unstable_keywords=allow_unstable_keywords, - allow_license_changes=allow_license_changes)] + allow_license_changes=allow_license_changes, allow_unmasks=allow_unmasks)] if not visible_matches: visible_matches = [pkg.cpv for pkg in matched_packages \ if self._pkg_visibility_check(pkg, allow_unstable_keywords=allow_unstable_keywords, - allow_license_changes=allow_license_changes)] + allow_license_changes=allow_license_changes, allow_unmasks=allow_unmasks)] if visible_matches: bestmatch = portage.best(visible_matches) else: @@ -5557,6 +5583,30 @@ class depgraph(object): else: unstable_keyword_msg[root].append("=%s %s\n" % (pkg.cpv, keyword)) + p_mask_change_msg = {} + for pkg in self._dynamic_config._needed_p_mask_changes: + self._show_merge_list() + if pkg in self._dynamic_config.digraph: + root = pkg.root + roots.add(root) + p_mask_change_msg.setdefault(root, []) + is_latest, is_latest_in_slot = check_if_latest(pkg) + pkgsettings = self._frozen_config.pkgsettings[pkg.root] + mreasons = _get_masking_status(pkg, pkgsettings, pkg.root_config, + use=self._pkg_use_enabled(pkg)) + for reason in mreasons: + if reason.unmask_hint and \ + reason.unmask_hint.key == 'p_mask': + keyword = reason.unmask_hint.value + + p_mask_change_msg[root].append(self._get_dep_chain_as_comment(pkg)) + if is_latest: + p_mask_change_msg[root].append(">=%s\n" % pkg.cpv) + elif is_latest_in_slot: + p_mask_change_msg[root].append(">=%s:%s\n" % (pkg.cpv, pkg.metadata["SLOT"])) + else: + p_mask_change_msg[root].append("=%s\n" % pkg.cpv) + use_changes_msg = {} for pkg, needed_use_config_change in self._dynamic_config._needed_use_config_changes.items(): self._show_merge_list() @@ -5633,6 +5683,10 @@ class depgraph(object): file_to_write_to[(abs_user_config, "package.keywords")] = \ find_config_file(abs_user_config, "package.keywords") + if root in p_mask_change_msg: + file_to_write_to[(abs_user_config, "package.unmask")] = \ + find_config_file(abs_user_config, "package.unmask") + if root in use_changes_msg: file_to_write_to[(abs_user_config, "package.use")] = \ find_config_file(abs_user_config, "package.use") @@ -5687,6 +5741,10 @@ class depgraph(object): write_changes(root, "keyword", unstable_keyword_msg[root], file_to_write_to.get((abs_user_config, "package.keywords"))) + if root in p_mask_change_msg: + write_changes(root, "mask", p_mask_change_msg[root], + file_to_write_to.get((abs_user_config, "package.unmask"))) + if root in use_changes_msg: write_changes(root, "USE", use_changes_msg[root], file_to_write_to.get((abs_user_config, "package.use"))) diff --git a/pym/_emerge/resolver/backtracking.py b/pym/_emerge/resolver/backtracking.py index 3c40bd8df..dcdaee0cb 100644 --- a/pym/_emerge/resolver/backtracking.py +++ b/pym/_emerge/resolver/backtracking.py @@ -7,11 +7,12 @@ class BacktrackParameter(object): __slots__ = ( "needed_unstable_keywords", "runtime_pkg_mask", "needed_use_config_changes", "needed_license_changes", - "rebuild_list", "reinstall_list" + "rebuild_list", "reinstall_list", "needed_p_mask_changes" ) def __init__(self): self.needed_unstable_keywords = set() + self.needed_p_mask_changes = set() self.runtime_pkg_mask = {} self.needed_use_config_changes = {} self.needed_license_changes = {} @@ -27,6 +28,7 @@ class BacktrackParameter(object): #Shallow copies are enough here, as we only need to ensure that nobody adds stuff #to our sets and dicts. The existing content is immutable. result.needed_unstable_keywords = copy.copy(self.needed_unstable_keywords) + result.needed_p_mask_changes = copy.copy(self.needed_p_mask_changes) result.runtime_pkg_mask = copy.copy(self.runtime_pkg_mask) result.needed_use_config_changes = copy.copy(self.needed_use_config_changes) result.needed_license_changes = copy.copy(self.needed_license_changes) @@ -37,6 +39,7 @@ class BacktrackParameter(object): def __eq__(self, other): return self.needed_unstable_keywords == other.needed_unstable_keywords and \ + self.needed_p_mask_changes == other.needed_p_mask_changes and \ self.runtime_pkg_mask == other.runtime_pkg_mask and \ self.needed_use_config_changes == other.needed_use_config_changes and \ self.needed_license_changes == other.needed_license_changes and \ @@ -138,6 +141,8 @@ class Backtracker(object): for change, data in changes.items(): if change == "needed_unstable_keywords": para.needed_unstable_keywords.update(data) + elif change == "needed_p_mask_changes": + para.needed_p_mask_changes.update(data) elif change == "needed_license_changes": for pkg, missing_licenses in data: para.needed_license_changes.setdefault(pkg, set()).update(missing_licenses) diff --git a/pym/portage/package/ebuild/getmaskingstatus.py b/pym/portage/package/ebuild/getmaskingstatus.py index a7d3c333f..e46f7886d 100644 --- a/pym/portage/package/ebuild/getmaskingstatus.py +++ b/pym/portage/package/ebuild/getmaskingstatus.py @@ -77,7 +77,7 @@ def _getmaskingstatus(mycpv, settings, portdb, myrepo=None): # package.mask checking if settings._getMaskAtom(mycpv, metadata): - rValue.append(_MaskReason("package.mask", "package.mask")) + rValue.append(_MaskReason("package.mask", "package.mask", _UnmaskHint("p_mask", None))) # keywords checking eapi = metadata["EAPI"] diff --git a/pym/portage/tests/resolver/ResolverPlayground.py b/pym/portage/tests/resolver/ResolverPlayground.py index c3540c939..f5bd77ff2 100644 --- a/pym/portage/tests/resolver/ResolverPlayground.py +++ b/pym/portage/tests/resolver/ResolverPlayground.py @@ -516,7 +516,7 @@ class ResolverPlaygroundTestCase(object): if self.ignore_mergelist_order and got is not None: got = set(got) expected = set(expected) - elif key == "unstable_keywords" and expected is not None: + elif key in ("unstable_keywords", "needed_p_mask_changes") and expected is not None: expected = set(expected) if got != expected: @@ -532,7 +532,7 @@ class ResolverPlaygroundResult(object): checks = ( "success", "mergelist", "use_changes", "license_changes", "unstable_keywords", "slot_collision_solutions", - "circular_dependency_solutions", + "circular_dependency_solutions", "needed_p_mask_changes", ) optional_checks = ( ) @@ -546,6 +546,7 @@ class ResolverPlaygroundResult(object): self.use_changes = None self.license_changes = None self.unstable_keywords = None + self.needed_p_mask_changes = None self.slot_collision_solutions = None self.circular_dependency_solutions = None @@ -572,6 +573,11 @@ class ResolverPlaygroundResult(object): for pkg in self.depgraph._dynamic_config._needed_unstable_keywords: self.unstable_keywords.add(pkg.cpv) + if self.depgraph._dynamic_config._needed_p_mask_changes: + self.needed_p_mask_changes = set() + for pkg in self.depgraph._dynamic_config._needed_p_mask_changes: + self.needed_p_mask_changes.add(pkg.cpv) + if self.depgraph._dynamic_config._needed_license_changes: self.license_changes = {} for pkg, missing_licenses in self.depgraph._dynamic_config._needed_license_changes.items(): diff --git a/pym/portage/tests/resolver/test_autounmask.py b/pym/portage/tests/resolver/test_autounmask.py index 027eb3326..62b152233 100644 --- a/pym/portage/tests/resolver/test_autounmask.py +++ b/pym/portage/tests/resolver/test_autounmask.py @@ -29,6 +29,10 @@ class AutounmaskTestCase(TestCase): "app-misc/W-2": { "KEYWORDS": "~x86" }, "app-misc/V-1": { "KEYWORDS": "~x86", "DEPEND": ">=app-misc/W-2"}, + #ebuilds to test mask and keyword changes + "app-text/A-1": {}, + "app-text/B-1": { "KEYWORDS": "~x86" }, + #ebuilds for mixed test for || dep handling "sci-libs/K-1": { "DEPEND": " || ( sci-libs/L[bar] || ( sci-libs/M sci-libs/P ) )", "EAPI": 2}, "sci-libs/K-2": { "DEPEND": " || ( sci-libs/L[bar] || ( sci-libs/P sci-libs/M ) )", "EAPI": 2}, @@ -203,6 +207,21 @@ class AutounmaskTestCase(TestCase): options = {"--autounmask": True}, use_changes = None, success = False), + + #Test mask and keyword changes. + ResolverPlaygroundTestCase( + ["app-text/A"], + options = {"--autounmask": True}, + success = False, + mergelist = ["app-text/A-1"], + needed_p_mask_changes = ["app-text/A-1"]), + ResolverPlaygroundTestCase( + ["app-text/B"], + options = {"--autounmask": True}, + success = False, + mergelist = ["app-text/B-1"], + unstable_keywords = ["app-text/B-1"], + needed_p_mask_changes = ["app-text/B-1"]), ) profile = { @@ -214,6 +233,11 @@ class AutounmaskTestCase(TestCase): ( "forced-flag", ), + "package.mask": + ( + "app-text/A", + "app-text/B", + ), } playground = ResolverPlayground(ebuilds=ebuilds, profile=profile) |