summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pym/_emerge/depgraph.py100
-rw-r--r--pym/_emerge/resolver/backtracking.py7
-rw-r--r--pym/portage/package/ebuild/getmaskingstatus.py2
-rw-r--r--pym/portage/tests/resolver/ResolverPlayground.py10
-rw-r--r--pym/portage/tests/resolver/test_autounmask.py24
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)