From 22b8c3bbe79a9fe23752375dadcf42b09c24b20c Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Wed, 1 May 2013 16:44:18 -0700 Subject: [PATCH] Support RESTRICT=preserve-libs, bug #364427 Note than when a package is merged, RESTRICT=preserve-libs applies if *either* the new instance or the old instance sets RESTRICT=preserve-libs. Also note that when the user has preserve-libs enabled, the --depclean-lib-check option may now kick in if one of the packages selected for unmerge sets RESTRICT=preserve-libs. --- bin/repoman | 2 +- man/ebuild.5 | 5 +++ man/emerge.1 | 9 ++--- pym/_emerge/actions.py | 24 +++++++++++--- pym/portage/dbapi/vartree.py | 64 ++++++++++++++++++++++++------------ 5 files changed, 74 insertions(+), 30 deletions(-) diff --git a/bin/repoman b/bin/repoman index a8293345a..a7bcbe1d1 100755 --- a/bin/repoman +++ b/bin/repoman @@ -450,7 +450,7 @@ for x in missingvars: qawarnings.add(x) valid_restrict = frozenset(["binchecks", "bindist", - "fetch", "installsources", "mirror", + "fetch", "installsources", "mirror", "preserve-libs", "primaryuri", "splitdebug", "strip", "test", "userpriv"]) live_eclasses = frozenset([ diff --git a/man/ebuild.5 b/man/ebuild.5 index 7ecb672e9..20e7b4b75 100644 --- a/man/ebuild.5 +++ b/man/ebuild.5 @@ -673,6 +673,11 @@ binaries that are not compatible with debugedit. .I mirror files in \fBSRC_URI\fR will not be downloaded from the \fBGENTOO_MIRRORS\fR. .TP +.I preserve\-libs +Disables preserve\-libs for specific packages. Note than when a package is +merged, RESTRICT=preserve\-libs applies if either the new instance or the +old instance sets RESTRICT=preserve\-libs. +.TP .I primaryuri fetch from URIs in \fBSRC_URI\fR before \fBGENTOO_MIRRORS\fR. .TP diff --git a/man/emerge.1 b/man/emerge.1 index 874d33380..15e8185fa 100644 --- a/man/emerge.1 +++ b/man/emerge.1 @@ -429,10 +429,11 @@ required. .BR "\-\-depclean\-lib\-check [ y | n ]" Account for library link-level dependencies during \fB\-\-depclean\fR and \fB\-\-prune\fR actions. -This option is enabled by default. This option is ignored -when FEATURES="preserve\-libs" is enabled in -\fBmake.conf\fR(5), since any libraries that have -consumers will simply be preserved. +This option is enabled by default. If FEATURES="preserve\-libs" is +enabled in \fBmake.conf\fR(5), and preserve\-libs is not restricted +for any of the packages selected for removal, then this option is +ignored because any libraries that have consumers will simply be +preserved. .TP .BR \-\-digest Prevent corruption from being noticed. The `repoman manifest` command is the diff --git a/pym/_emerge/actions.py b/pym/_emerge/actions.py index 2c5a1b383..3982eb363 100644 --- a/pym/_emerge/actions.py +++ b/pym/_emerge/actions.py @@ -987,10 +987,19 @@ def calc_depclean(settings, trees, ldpath_mtimes, cleanlist = create_cleanlist() clean_set = set(cleanlist) - if cleanlist and \ - real_vardb._linkmap is not None and \ - myopts.get("--depclean-lib-check", _DEPCLEAN_LIB_CHECK_DEFAULT) != "n" and \ - "preserve-libs" not in settings.features: + depclean_lib_check = cleanlist and real_vardb._linkmap is not None and \ + myopts.get("--depclean-lib-check", _DEPCLEAN_LIB_CHECK_DEFAULT) != "n" + preserve_libs = "preserve-libs" in settings.features + preserve_libs_restrict = False + + if depclean_lib_check and preserve_libs: + for pkg in cleanlist: + if "preserve-libs" in pkg.restrict: + preserve_libs_restrict = True + break + + if depclean_lib_check and \ + (preserve_libs_restrict or not preserve_libs): # Check if any of these packages are the sole providers of libraries # with consumers that have not been selected for removal. If so, these @@ -1003,6 +1012,13 @@ def calc_depclean(settings, trees, ldpath_mtimes, writemsg_level(">>> Checking for lib consumers...\n") for pkg in cleanlist: + + if preserve_libs and "preserve-libs" not in pkg.restrict: + # Any needed libraries will be preserved + # when this package is unmerged, so there's + # no need to account for it here. + continue + pkg_dblink = real_vardb._dblink(pkg.cpv) consumers = {} diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py index 0d4a75608..c6eaabfc0 100644 --- a/pym/portage/dbapi/vartree.py +++ b/pym/portage/dbapi/vartree.py @@ -1519,6 +1519,10 @@ class dblink(object): self._protect_obj = None self._pipe = pipe + # When necessary, this attribute is modified for + # compliance with RESTRICT=preserve-libs. + self._preserve_libs = "preserve-libs" in mysettings.features + def __hash__(self): return hash(self._hash_key) @@ -1895,6 +1899,10 @@ class dblink(object): except UnsupportedAPIException as e: eapi_unsupported = e + if self._preserve_libs and "preserve-libs" in \ + self.settings["PORTAGE_RESTRICT"].split(): + self._preserve_libs = False + builddir_lock = None scheduler = self._scheduler retval = os.EX_OK @@ -2879,7 +2887,7 @@ class dblink(object): self.vartree.dbapi._linkmap is None or \ self.vartree.dbapi._plib_registry is None or \ (not unmerge and self._installed_instance is None) or \ - "preserve-libs" not in self.settings.features: + not self._preserve_libs: return set() os = _os_merge @@ -3598,26 +3606,40 @@ class dblink(object): cp = self.mysplit[0] slot_atom = "%s:%s" % (cp, slot) - # filter any old-style virtual matches - slot_matches = [cpv for cpv in self.vartree.dbapi.match(slot_atom) \ - if cpv_getkey(cpv) == cp] - - if self.mycpv not in slot_matches and \ - self.vartree.dbapi.cpv_exists(self.mycpv): - # handle multislot or unapplied slotmove - slot_matches.append(self.mycpv) - - others_in_slot = [] - for cur_cpv in slot_matches: - # Clone the config in case one of these has to be unmerged since - # we need it to have private ${T} etc... for things like elog. - settings_clone = portage.config(clone=self.settings) - settings_clone.pop("PORTAGE_BUILDDIR_LOCKED", None) - settings_clone.reset() - others_in_slot.append(dblink(self.cat, catsplit(cur_cpv)[1], - settings=settings_clone, - vartree=self.vartree, treetype="vartree", - scheduler=self._scheduler, pipe=self._pipe)) + self.lockdb() + try: + # filter any old-style virtual matches + slot_matches = [cpv for cpv in self.vartree.dbapi.match(slot_atom) + if cpv_getkey(cpv) == cp] + + if self.mycpv not in slot_matches and \ + self.vartree.dbapi.cpv_exists(self.mycpv): + # handle multislot or unapplied slotmove + slot_matches.append(self.mycpv) + + others_in_slot = [] + for cur_cpv in slot_matches: + # Clone the config in case one of these has to be unmerged, + # since we need it to have private ${T} etc... for things + # like elog. + settings_clone = portage.config(clone=self.settings) + settings_clone.pop("PORTAGE_BUILDDIR_LOCKED", None) + settings_clone.setcpv(cur_cpv, mydb=self.vartree.dbapi) + if self._preserve_libs and "preserve-libs" in \ + settings_clone["PORTAGE_RESTRICT"].split(): + self._preserve_libs = False + others_in_slot.append(dblink(self.cat, catsplit(cur_cpv)[1], + settings=settings_clone, + vartree=self.vartree, treetype="vartree", + scheduler=self._scheduler, pipe=self._pipe)) + finally: + self.unlockdb() + + # If any instance has RESTRICT=preserve-libs, then + # restrict it for all instances. + if not self._preserve_libs: + for dblnk in others_in_slot: + dblnk._preserve_libs = False retval = self._security_check(others_in_slot) if retval: -- 2.26.2