Merged from trunk -r12528:12543
authorFabian Groffen <grobian@gentoo.org>
Fri, 30 Jan 2009 21:20:54 +0000 (21:20 -0000)
committerFabian Groffen <grobian@gentoo.org>
Fri, 30 Jan 2009 21:20:54 +0000 (21:20 -0000)
   | 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
man/repoman.1
pym/_emerge/__init__.py
pym/repoman/checks.py

index 7a4728e7e33e7d2bdf3de94daa1bdab6e4fe5e7f..ba7b3c2d35dbfb98e994108c737c75ad43563145 100755 (executable)
@@ -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",
index 754214049fd2710e1d1e198510677e4bde3410c1..5b5aec6ff8a7fc6f43ef8fde2a55d4dc27295249 100644 (file)
@@ -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
index 711418eb3a454df1ff2563439dd6f9441e363964..07026beb8a8e8b0547439257024d0d02a0ae8c03 100644 (file)
@@ -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):
index 7565039f274af031be89299a7336ae4e8034e35a..c9ef91cfc91d9df7a92259d2367e413bbabf2bfa 100644 (file)
@@ -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):