From f02a0fcfa9160fb4ad7a61c3106d90363cccfb69 Mon Sep 17 00:00:00 2001 From: Fabian Groffen Date: Fri, 30 Jan 2009 21:20:54 +0000 Subject: [PATCH] Merged from trunk -r12528:12543 | 12529 | Bug #255358 - Add new RDEPEND.implicit warning to detect the | | zmedico | caes where DEPEND is set and RDEPEND is unset in the ebuild, | | | since this triggers implicit RDEPEND=$DEPEND assignment. | | 12540 | When in --keep-going mode, don't suppress the list of failed | | zmedico | packages display at the end when there is only one failure, | | | since the failure may have occurred much earlier and the | | | related output may not be visible any longer. | | 12541 | Inside depgraph.loadResumeCommand(), ignore unsatisified | | zmedico | dependencies that are pulled in by installed packages. This | | | is needed in order to avoid having --keep-going bail out | | | needlessly when one of a group of circularly dependent | | | packages fails to install after one or more of the group | | | have already been installed. TODO: Add sanity checks to make | | | sure that it's really safe to ignore all the deps that can | | | be ignored by this code. | | 12542 | In depgraph.loadResumeCommand(), account for unsatisfied | | zmedico | dependencies of installed packages if they are in the | | | subgraph of dependencies of a package which is scheduled to | | | be installed. | | 12543 | Bug #199408 - Always enable the skip_masked and | | zmedico | skip_unsatisfied for the resume_depgraph() function. This | | | will cause emerge --resume to automatically drop masked | | | packages (without the need to specify --skipfirst). | svn path=/main/branches/prefix/; revision=12561 --- bin/repoman | 2 ++ man/repoman.1 | 4 ++++ pym/_emerge/__init__.py | 49 ++++++++++++++++++++++++++++++++--------- pym/repoman/checks.py | 29 +++++++++++++++++++++++- 4 files changed, 73 insertions(+), 11 deletions(-) diff --git a/bin/repoman b/bin/repoman index 7a4728e7e..ba7b3c2d3 100755 --- a/bin/repoman +++ b/bin/repoman @@ -303,6 +303,7 @@ qahelp={ "IUSE.undefined":"This ebuild does not define IUSE (style guideline says to define IUSE even when empty)", "LICENSE.invalid":"This ebuild is listing a license that doesnt exist in portages license/ dir.", "KEYWORDS.invalid":"This ebuild contains KEYWORDS that are not listed in profiles/arch.list or for which no valid profile was found", + "RDEPEND.implicit":"RDEPEND is unset in the ebuild which triggers implicit RDEPEND=$DEPEND assignment", "RDEPEND.suspect":"RDEPEND contains a package that usually only belongs in DEPEND.", "RESTRICT.invalid":"This ebuild contains invalid RESTRICT values.", "digestentry.unused":"Some files listed in the Manifest aren't referenced in SRC_URI", @@ -343,6 +344,7 @@ qawarnings = set(( "KEYWORDS.missing", "IUSE.invalid", "IUSE.undefined", +"RDEPEND.implicit", "RDEPEND.suspect", "RESTRICT.invalid", "SRC_URI.mirror", diff --git a/man/repoman.1 b/man/repoman.1 index 754214049..5b5aec6ff 100644 --- a/man/repoman.1 +++ b/man/repoman.1 @@ -168,6 +168,10 @@ Masked ebuilds with RDEPEND settings (matched against *all* ebuilds) .B RDEPEND.badmaskedindev Masked ebuilds with RDEPEND settings (matched against *all* ebuilds) in developing arch .TP +.B RDEPEND.implicit +RDEPEND is unset in the ebuild which triggers implicit RDEPEND=$DEPEND +assignment +.TP .B RDEPEND.suspect RDEPEND contains a package that usually only belongs in DEPEND .TP diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py index 711418eb3..07026beb8 100644 --- a/pym/_emerge/__init__.py +++ b/pym/_emerge/__init__.py @@ -8550,13 +8550,43 @@ class depgraph(object): # masked. if not self._create_graph(allow_unsatisfied=True): return False - if masked_tasks or self._unsatisfied_deps: + + unsatisfied_deps = [] + for dep in self._unsatisfied_deps: + if not isinstance(dep.parent, Package): + continue + if dep.parent.operation == "merge": + unsatisfied_deps.append(dep) + continue + + # For unsatisfied deps of installed packages, only account for + # them if they are in the subgraph of dependencies of a package + # which is scheduled to be installed. + unsatisfied_install = False + traversed = set() + dep_stack = self.digraph.parent_nodes(dep.parent) + while dep_stack: + node = dep_stack.pop() + if not isinstance(node, Package): + continue + if node.operation == "merge": + unsatisfied_install = True + break + if node in traversed: + continue + traversed.add(node) + dep_stack.extend(self.digraph.parent_nodes(node)) + + if unsatisfied_install: + unsatisfied_deps.append(dep) + + if masked_tasks or unsatisfied_deps: # This probably means that a required package # was dropped via --skipfirst. It makes the # resume list invalid, so convert it to a # UnsatisfiedResumeDep exception. raise self.UnsatisfiedResumeDep(self, - masked_tasks + self._unsatisfied_deps) + masked_tasks + unsatisfied_deps) self._serialized_tasks_cache = None try: self.altlist() @@ -10399,7 +10429,8 @@ class Scheduler(PollScheduler): for msg in self._post_mod_echo_msgs: msg() - if len(self._failed_pkgs_all) > 1: + if len(self._failed_pkgs_all) > 1 or \ + (self._failed_pkgs_all and "--keep-going" in self.myopts): msg = "The following packages have " + \ "failed to build or install:" prefix = bad(" * ") @@ -10878,7 +10909,7 @@ class Scheduler(PollScheduler): try: success, mydepgraph, dropped_tasks = resume_depgraph( self.settings, self.trees, self._mtimedb, self.myopts, - myparams, self._spinner, skip_unsatisfied=True) + myparams, self._spinner) except depgraph.UnsatisfiedResumeDep, e: mydepgraph = e.depgraph dropped_tasks = set() @@ -13719,14 +13750,15 @@ def action_depclean(settings, trees, ldpath_mtimes, else: print "Number removed: "+str(len(cleanlist)) -def resume_depgraph(settings, trees, mtimedb, myopts, myparams, spinner, - skip_masked=False, skip_unsatisfied=False): +def resume_depgraph(settings, trees, mtimedb, myopts, myparams, spinner): """ Construct a depgraph for the given resume list. This will raise PackageNotFound or depgraph.UnsatisfiedResumeDep when necessary. @rtype: tuple @returns: (success, depgraph, dropped_tasks) """ + skip_masked = True + skip_unsatisfied = True mergelist = mtimedb["resume"]["mergelist"] dropped_tasks = set() while True: @@ -13929,14 +13961,11 @@ def action_build(settings, trees, mtimedb, del mergelist[i] break - skip_masked = "--skipfirst" in myopts - skip_unsatisfied = "--skipfirst" in myopts success = False mydepgraph = None try: success, mydepgraph, dropped_tasks = resume_depgraph( - settings, trees, mtimedb, myopts, myparams, spinner, - skip_masked=skip_masked, skip_unsatisfied=skip_unsatisfied) + settings, trees, mtimedb, myopts, myparams, spinner) except (portage.exception.PackageNotFound, depgraph.UnsatisfiedResumeDep), e: if isinstance(e, depgraph.UnsatisfiedResumeDep): diff --git a/pym/repoman/checks.py b/pym/repoman/checks.py index 7565039f2..c9ef91cfc 100644 --- a/pym/repoman/checks.py +++ b/pym/repoman/checks.py @@ -230,6 +230,33 @@ class EbuildQuotedA(LineCheck): if match: return "Quoted \"${A}\" on line: %d" +class ImplicitRuntimeDeps(LineCheck): + """ + Detect the case where DEPEND is set and RDEPEND is unset in the ebuild, + since this triggers implicit RDEPEND=$DEPEND assignment. + """ + + repoman_check_name = 'RDEPEND.implicit' + _assignment_re = re.compile(r'^\s*(R?DEPEND)=') + + def new(self, pkg): + self._rdepend = False + self._depend = False + + def check(self, num, line): + if not self._rdepend: + m = self._assignment_re.match(line) + if m is None: + pass + elif m.group(1) == "RDEPEND": + self._rdepend = True + elif m.group(1) == "DEPEND": + self._depend = True + + def end(self): + if self._depend and not self._rdepend: + yield 'RDEPEND is not explicitly assigned' + class InheritAutotools(LineCheck): """ Make sure appropriate functions are called in @@ -306,7 +333,7 @@ _constant_checks = tuple((c() for c in ( EbuildAssignment, EbuildUselessDodoc, EbuildUselessCdS, EbuildNestedDie, EbuildPatches, EbuildQuotedA, - IUseUndefined, InheritAutotools, + IUseUndefined, ImplicitRuntimeDeps, InheritAutotools, EMakeParallelDisabled, DeprecatedBindnowFlags))) def run_checks(contents, pkg): -- 2.26.2