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	6 Aug 2010 21:29:19 -0000
@@ -24,6 +24,8 @@
 #include <io.h>
 #include <ctype.h>
 #include <process.h>
+#include <list>
+#include <queue>
 
 #include "prereq.h"
 #include "dialog.h"
@@ -150,47 +152,56 @@
 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)
+
+  queue <packagemeta *> todo;
+  set <packagemeta *> known;
+
+  // 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 the package is installed or selected to be installed...
-      if ((*n)->desired)
+      if ((*p)->desired)
         {
-          // loop through each dependency
-          for (vector <vector <PackageSpecification *> *>::iterator i = 
-                (*n)->desired.depends ()->begin ();
-                i != (*n)->desired.depends ()->end (); ++i)
+          todo.push (*p);
+          known.insert (*p);
+        }
+    }
+
+  while (!todo.empty ())
+    {
+      packagemeta *pack = todo.front ();
+      todo.pop ();
+      for (vector <vector <PackageSpecification *> *>::iterator d = 
+            pack->curr.depends ()->begin ();
+            d != pack->curr.depends ()->end (); ++d)
+        {
+          // 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) 
+            continue;  // asking for a package that doesn't exist - ignore
+          
+          if (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))
-                {
-                  // dependency met
-                }
-              else
-                {                  
-                  foundUnmet = true;
-                  unmet[pack].push_back (*n);
-                }
+              // dependency met
+            }
+          else
+            {
+              unmet[dep].push_back (pack);
+              bool unknown = known.insert (dep).second;
+              if (unknown)
+                todo.push (dep);
             }
         }
     }
-    
-  return !foundUnmet;
+
+  return unmet.empty();
 }
 
 /* Formats 'unmet' as a string for display to the user.  */
