Index: prereq.cc
===================================================================
RCS file: /cvs/cygwin-apps/setup/prereq.cc,v
retrieving revision 2.3
diff -u -r2.3 prereq.cc
--- prereq.cc	13 Dec 2009 19:23:43 -0000	2.3
+++ prereq.cc	7 Aug 2010 05:31:35 -0000
@@ -24,6 +24,7 @@
 #include <io.h>
 #include <ctype.h>
 #include <process.h>
+#include <queue>
 
 #include "prereq.h"
 #include "dialog.h"
@@ -150,47 +151,53 @@
 PrereqChecker::isMet ()
 {
   packagedb db;
-  bool foundUnmet = false;
 
   // unmet is static - clear it each time this is called
   unmet.clear ();
-  
-  // loop through each package
-  for (vector <packagemeta *>::iterator n = db.packages.begin ();
-        n != db.packages.end (); ++n)
+
+  // packages that need to be checked for dependencies
+  queue <packagemeta *> todo;
+
+  // go through all packages, adding desired ones to the initial work list
+  for (vector <packagemeta *>::iterator p = db.packages.begin ();
+        p != db.packages.end (); ++p)
+    {
+      if ((*p)->desired)
+        todo.push (*p);
+    }
+
+  // churn through the worklist
+  while (!todo.empty ())
     {
-      // if the package is installed or selected to be installed...
-      if ((*n)->desired)
+      packagemeta *pack = todo.front ();
+      todo.pop ();
+
+      // go throught the package's dependencies
+      for (vector <vector <PackageSpecification *> *>::iterator d = 
+            pack->curr.depends ()->begin ();
+            d != pack->curr.depends ()->end (); ++d)
         {
-          // loop through each dependency
-          for (vector <vector <PackageSpecification *> *>::iterator i = 
-                (*n)->desired.depends ()->begin ();
-                i != (*n)->desired.depends ()->end (); ++i)
+          // XXX: the following assumes that there is only a single
+          // node in each OR clause, which is currently the case.
+          // if setup is ever pushed to use AND/OR in "depends:"
+          // lines this will have to be updated
+          PackageSpecification *dep_spec = (*d)->at(0);
+          packagemeta *dep = db.findBinary (*dep_spec);
+          
+          if (dep && !(dep->desired && dep_spec->satisfies (dep->desired)))
             {
-              // XXX: the following assumes that there is only a single
-              // node in each OR clause, which is currently the case.
-              // if setup is ever pushed to use AND/OR in "depends:"
-              // lines this will have to be updated
-              PackageSpecification *spec = (*i)->at(0);
-                  
-              packagemeta *pack = db.findBinary (*spec);
-              if (!pack)
-                continue;  // asking for a package that doesn't exist - error?
-
-              if (pack->desired && spec->satisfies (pack->desired))
+              // we've got an unmet dependency
+              if (unmet.find(dep) == unmet.end())
                 {
-                  // dependency met
-                }
-              else
-                {                  
-                  foundUnmet = true;
-                  unmet[pack].push_back (*n);
+                  // newly found dependency: add to worklist
+                  todo.push(dep);
                 }
+              unmet[dep].push_back (pack);
             }
         }
     }
-    
-  return !foundUnmet;
+
+  return unmet.empty();
 }
 
 /* Formats 'unmet' as a string for display to the user.  */
