Add REQUIRED_USE check as pre-merge check.
authorSebastian Luther <SebastianLuther@gmx.de>
Mon, 12 Apr 2010 19:41:33 +0000 (21:41 +0200)
committerZac Medico <zmedico@gentoo.org>
Wed, 11 Aug 2010 01:27:37 +0000 (18:27 -0700)
pym/_emerge/Scheduler.py

index c6af547f8b03b74f986eb075ec216f1d00f252f7..d5c152f153bea1b163a0c892e3eab593914acc97 100644 (file)
@@ -721,6 +721,63 @@ class Scheduler(PollScheduler):
                        return 1
                return os.EX_OK
 
+       def _check_required_use(self):
+               # Make sure all constraints expressed in REQUIRED_USE are satisfied
+
+               failures = 0
+               shown_verifying_msg = False
+               for x in self._mergelist:
+                       if not isinstance(x, Package):
+                               continue
+
+                       if x.operation == "uninstall":
+                               continue
+
+                       if x.metadata["EAPI"] in ("0", "1", "2", "3"):
+                               continue
+
+                       if not x.metadata["REQUIRED_USE"]:
+                               continue
+
+                       if not shown_verifying_msg:
+                               shown_verifying_msg = True
+                               self._status_msg("Verifying use flag constraints")
+
+                       required_use = x.metadata["REQUIRED_USE"]
+                       use = x.metadata["USE"].split()
+                       iuse = x.metadata["IUSE"].split()
+
+                       try:
+                               sat, unsat = portage.dep.check_required_use(required_use, use, iuse)
+                       except portage.exception.InvalidRequiredUseString as e:
+                               failures += 1
+                               portage.writemsg("!!! Invalid REQUIRED_USE specified by " + \
+                                       "'%s': %s\n" % (x.cpv, str(e)), noiselevel=-1)
+                               del e
+                               continue
+
+                       if unsat:
+                               failures += 1
+                               if sat:
+                                       #not all constraints are violated, display the them all to not annoy
+                                       #the user with another violated constraint after he fixed the first one
+                                       portage.writemsg(
+                                               "!!! Use flag constraints for '%s' not met.\n" % x.cpv + \
+                                               "!!! violated constraint(s): '%s'\n" % unsat + \
+                                               "!!! all constraint(s):      '%s'\n" % required_use, noiselevel=-1)
+                               else:
+                                       portage.writemsg(
+                                               "!!! Use flag constraints for '%s' not met.\n" % x.cpv + \
+                                               "!!! constraint(s): '%s'\n" % required_use, noiselevel=-1)
+               if failures:
+                       portage.writemsg("\n")
+                       portage.writemsg("Explanation: || ( a b c ): at least one of 'a', 'b' or 'c' must be enabled\n")
+                       portage.writemsg("Explanation: ^^ ( a b c ): exactly one of 'a', 'b' or 'c' must be enabled\n")
+                       portage.writemsg("Explanation: a? ( b ): b needs to be enabled if a is enabled\n")
+                       portage.writemsg("Explanation: '!'-prefix reverses the required state\n")
+                       return 1
+               return os.EX_OK
+
        def _add_prefetchers(self):
 
                if not self._parallel_fetch:
@@ -990,6 +1047,10 @@ class Scheduler(PollScheduler):
                if rval != os.EX_OK and not keep_going:
                        return rval
 
+               rval = self._check_required_use()
+               if rval != os.EX_OK:
+                       return rval
+
                rval = self._run_pkg_pretend()
                if rval != os.EX_OK:
                        return rval