# 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()
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(" * ")
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()
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:
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):
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
EbuildAssignment, EbuildUselessDodoc,
EbuildUselessCdS, EbuildNestedDie,
EbuildPatches, EbuildQuotedA,
- IUseUndefined, InheritAutotools,
+ IUseUndefined, ImplicitRuntimeDeps, InheritAutotools,
EMakeParallelDisabled, DeprecatedBindnowFlags)))
def run_checks(contents, pkg):