This is the mail archive of the cygwin-apps mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH setup 08/14] Change to using a libsolv pool for storing package information


Add class SolverVersion, a wrapper around a Solvable Id. The interface is
similar to class packageversion, the name change is just to make sure I've
got everything.

Place test packages into separate repos.

Expressing that curr: packages are preferred to prev: ones when that is not
the version number ordering should be done with epoch numbers.

Wire up various bits of data in packageversion to Solvable attributes,
including sourcepackage, stability, archive (packagesource) and depends.

Store sourcePackage() by the id rather than name, for much faster lookup.

SolverVersions for the same package can be ordered and compared by evr.

Factor out packagedb:addBinary() and also use it in IniDBBuilder, rather
that inlining the process of adding a package there. Add an analagous
packagedb:addSource() to do the same thing for source packages.

Change to reading installed.db after setup.ini's have been read, so we can
supplement the installed.db packages with information from setup.ini.

Make packagemeta::add_version() check for successful insertion of version.
Record the version at a stability level. The last version wins in setting
curr/test.

Use a Solver object inside packagedb

XXX: All SolvableVersion methods need to check for null solvable?
---
 IniDBBuilderPackage.cc  | 304 ++++++++++-----------------------
 IniDBBuilderPackage.h   |  28 +--
 Makefile.am             |   4 +-
 PackageSpecification.cc |  12 ++
 PackageSpecification.h  |   3 +
 configure.ac            |   1 +
 ini.cc                  |   5 +-
 libsolv.cc              | 443 ++++++++++++++++++++++++++++++++++++++++++++++++
 libsolv.h               | 146 ++++++++++++++++
 package_db.cc           |  90 ++++++++--
 package_db.h            |   6 +
 package_meta.cc         | 101 ++++++++---
 package_meta.h          |   6 +-
 13 files changed, 887 insertions(+), 262 deletions(-)
 create mode 100644 libsolv.cc
 create mode 100644 libsolv.h

diff --git a/IniDBBuilderPackage.cc b/IniDBBuilderPackage.cc
index fb200a8..b929c7e 100644
--- a/IniDBBuilderPackage.cc
+++ b/IniDBBuilderPackage.cc
@@ -22,8 +22,6 @@
 #include "IniParseFeedback.h"
 #include "package_db.h"
 #include "package_meta.h"
-#include "package_version.h"
-#include "cygpackage.h"
 #include "ini.h"
 // for strtoul
 #include <string.h>
@@ -34,7 +32,7 @@
 using namespace std;
 
 IniDBBuilderPackage::IniDBBuilderPackage (IniParseFeedback const &aFeedback) :
-cp (0), cbpv (), cspv (), currentSpec (0), _feedback (aFeedback){}
+currentSpec (0), _feedback (aFeedback){}
 
 IniDBBuilderPackage::~IniDBBuilderPackage()
 {
@@ -67,31 +65,28 @@ IniDBBuilderPackage::buildVersion (const std::string& aVersion)
 }
 
 void
-IniDBBuilderPackage::buildPackage (const std::string& name)
+IniDBBuilderPackage::buildPackage (const std::string& _name)
 {
-#if DEBUG
-  if (cp)
-    {
-      Log (LOG_BABBLE) << "Finished with package " << cp->name << endLog;
-      if (cbpv)
-	{
-	  Log (LOG_BABBLE) << "Version " << cbpv.Canonical_version() << endLog;
-	  Log (LOG_BABBLE) << "Depends:";
-	  dumpPackageDepends (cbpv.depends(), Log (LOG_BABBLE));
-	  Log (LOG_BABBLE) << endLog;
-	}
-    }
-#endif
-  packagedb db;
-  cp = db.findBinary (PackageSpecification(name));
-  if (!cp)
-    {
-      cp = new packagemeta (name);
-      db.packages.insert (packagedb::packagecollection::value_type(cp->name,cp));
-    }
-  cbpv = cygpackage::createInstance (name, package_binary);
-  cbpv.SetStability(TRUST_CURR);
-  cspv = packageversion ();
+  process();
+
+  /* Reset for next package */
+  name = _name;
+  message_id = "";
+  message_string = "";
+  categories.clear();
+
+  cbpv.reponame = release;
+  cbpv.version = "";
+  cbpv.vendor = release;
+  cbpv.sdesc = "";
+  cbpv.ldesc = "";
+  cbpv.stability = TRUST_CURR;
+  cbpv.type = package_binary;
+  cbpv.spkg = PackageSpecification();
+  cbpv.spkg_id = packageversion();
+  cbpv.requires = NULL;
+  cbpv.archive = packagesource();
+
   currentSpec = NULL;
   currentNodeList = PackageDepends();
 #if DEBUG
@@ -102,20 +97,19 @@ IniDBBuilderPackage::buildPackage (const std::string& name)
 void
 IniDBBuilderPackage::buildPackageVersion (const std::string& version)
 {
-  cbpv.setCanonicalVersion (version);
-  add_correct_version();
+  cbpv.version = version;
 }
 
 void
 IniDBBuilderPackage::buildPackageSDesc (const std::string& theDesc)
 {
-  cbpv.set_sdesc(theDesc);
+  cbpv.sdesc = theDesc;
 }
 
 void
 IniDBBuilderPackage::buildPackageLDesc (const std::string& theDesc)
 {
-  cbpv.set_ldesc(theDesc);
+  cbpv.ldesc = theDesc;
 }
 
 void
@@ -124,21 +118,23 @@ IniDBBuilderPackage::buildPackageInstall (const std::string& path,
                                           char *hash,
                                           hashType type)
 {
-  process_src (*cbpv.source(), path);
-  setSourceSize (*cbpv.source(), size);
+  // set archive path, size, mirror, hash
+  cbpv.archive.set_canonical(path.c_str());
+  cbpv.archive.size = atoi(size.c_str());
+  cbpv.archive.sites.push_back(site(parse_mirror));
 
   switch (type) {
   case hashType::sha512:
-    if (hash && !cbpv.source()->sha512_isSet)
+    if (hash && !cbpv.archive.sha512_isSet)
       {
-        memcpy (cbpv.source()->sha512sum, hash, sizeof(cbpv.source()->sha512sum));
-        cbpv.source()->sha512_isSet = true;
+        memcpy (cbpv.archive.sha512sum, hash, sizeof(cbpv.archive.sha512sum));
+        cbpv.archive.sha512_isSet = true;
       }
     break;
 
   case hashType::md5:
-    if (hash && !cbpv.source()->md5.isSet())
-      cbpv.source()->md5.set((unsigned char *)hash);
+    if (hash && !cbpv.archive.md5.isSet())
+      cbpv.archive.md5.set((unsigned char *)hash);
     break;
 
   case hashType::none:
@@ -152,79 +148,57 @@ IniDBBuilderPackage::buildPackageSource (const std::string& path,
                                          char *hash,
                                          hashType type)
 {
-  packagedb db;
-  /* get an appropriate metadata */
-  csp = db.findSource (PackageSpecification (cbpv.Name()));
-  if (!csp)
-    {
-      /* Copy the existing meta data to a new source package */
-      csp = new packagemeta (*cp);
-      /* delete versions information */
-      csp->versions.clear();
-      csp->desired = packageversion();
-      csp->installed = packageversion();
-      csp->curr = packageversion();
-      csp->exp = packageversion();
-      db.sourcePackages.insert (packagedb::packagecollection::value_type(csp->name,csp));
-    }
-  /* create a source packageversion */
-  cspv = cygpackage::createInstance (cbpv.Name(), package_source);
-  cspv.setCanonicalVersion (cbpv.Canonical_version());
-  set<packageversion>::iterator i=find (csp->versions.begin(),
-    csp->versions.end(), cspv);
-  if (i == csp->versions.end())
-    {
-      csp->add_version (cspv);
-    }
-  else
-    cspv = *i;
+  /* When there is a source: line, we invent a package to contain the source,
+     and make it the source package for this package. */
 
-  if (!cspv.source()->Canonical())
-    cspv.source()->set_canonical (path.c_str());
-  cspv.source()->sites.push_back(site(parse_mirror));
+  /* create a source package version */
+  SolverPool::addPackageData cspv = cbpv;
+  cspv.type = package_source;
+  cspv.requires = NULL;
 
-  /* creates the relationship between binary and source packageversions */
-  cbpv.setSourcePackageSpecification (PackageSpecification (cspv.Name()));
-  PackageSpecification &spec = cbpv.sourcePackageSpecification();
-  spec.setOperator (PackageSpecification::Equals);
-  spec.setVersion (cbpv.Canonical_version());
-
-  setSourceSize (*cspv.source(), size);
+  /* set archive path, size, mirror, hash */
+  cspv.archive = packagesource();
+  cspv.archive.set_canonical(path.c_str());
+  cspv.archive.size = atoi(size.c_str());
+  cspv.archive.sites.push_back(site(parse_mirror));
 
   switch (type) {
   case hashType::sha512:
-    if (hash && !cspv.source()->sha512_isSet)
+    if (hash && !cspv.archive.sha512_isSet)
       {
-        memcpy (cspv.source()->sha512sum, hash, sizeof(cspv.source()->sha512sum));
-        cspv.source()->sha512_isSet = true;
+        memcpy (cspv.archive.sha512sum, hash, sizeof(cspv.archive.sha512sum));
+        cspv.archive.sha512_isSet = true;
       }
     break;
 
   case hashType::md5:
-    if (hash && !cspv.source()->md5.isSet())
-      cspv.source()->md5.set((unsigned char *)hash);
+    if (hash && !cspv.archive.md5.isSet())
+      cspv.archive.md5.set((unsigned char *)hash);
     break;
 
   case hashType::none:
     break;
   }
+
+  packagedb db;
+  packageversion spkg_id = db.addSource (name + "-src", cspv);
+
+  /* create relationship between binary and source packageversions */
+  cbpv.spkg = PackageSpecification(name + "-src");
+  cbpv.spkg_id = spkg_id;
 }
 
 void
-IniDBBuilderPackage::buildPackageTrust (package_stability_t newtrust)
+IniDBBuilderPackage::buildPackageTrust (trusts newtrust)
 {
-  if (newtrust != TRUST_UNKNOWN)
-    {
-      cbpv = cygpackage::createInstance (cp->name, package_binary);
-      cbpv.SetStability(newtrust);
-      cspv = packageversion ();
-    }
+  process();
+  cbpv.stability = newtrust;
 }
 
 void
 IniDBBuilderPackage::buildPackageCategory (const std::string& name)
 {
-  cp->add_category (name);
+  categories.insert(name);
 }
 
 void
@@ -235,6 +209,7 @@ IniDBBuilderPackage::buildBeginDepends ()
 #endif
   currentSpec = NULL;
   currentNodeList = PackageDepends();
+  cbpv.requires = &currentNodeList;
 }
 
 void
@@ -244,42 +219,25 @@ IniDBBuilderPackage::buildBeginBuildDepends ()
   Log (LOG_BABBLE) << "Beginning of a Build-Depends statement" << endLog;
 #endif
   currentSpec = NULL;
-  currentNodeList = PackageDepends(); /* there is currently nowhere to store Build-Depends information */
+  currentNodeList = PackageDepends();
+  /* there is currently nowhere to store Build-Depends information */
 }
 
 void
-IniDBBuilderPackage::buildSourceName (const std::string& name)
+IniDBBuilderPackage::buildSourceName (const std::string& _name)
 {
-  if (cbpv)
-    {
-      cbpv.setSourcePackageSpecification (PackageSpecification (name));
+  // When there is a Source: line, that names a real source package
+  cbpv.spkg = PackageSpecification(name);
+  // XXX: set cbpv.spkg_id
 #if DEBUG
-      Log (LOG_BABBLE) << "\"" << cbpv.sourcePackageSpecification() <<
-	"\" is the source package for " << cp->name << "." << endLog;
+  Log (LOG_BABBLE) << "\"" << _name << "\" is the source package for " << name << "." << endLog;
 #endif
-    }
-  else
-      _feedback.warning ((std::string ("Attempt to set source for package")
-                          + std::string(cp->name)
-			  + "before creation of a version.").c_str());
 }
 
 void
 IniDBBuilderPackage::buildSourceNameVersion (const std::string& version)
 {
-  if (cbpv)
-    {
-      cbpv.sourcePackageSpecification().setOperator (PackageSpecification::Equals);
-      cbpv.sourcePackageSpecification().setVersion (version);
-#if DEBUG
-      Log (LOG_BABBLE) << "The source version needed for " << cp->name <<
-	" is " << version << "." << endLog;
-#endif
-    }
-  else
-      _feedback.warning ((std::string ("Attempt to set source version for package")
-                          + std::string(cp->name)
-			  + "before creation of a version.").c_str());
+  // XXX: should be stored as sourceevr
 }
 
 void
@@ -303,13 +261,8 @@ IniDBBuilderPackage::buildPackageListOperator (PackageSpecification::_operators
 	endLog;
 #endif
     }
-  else
-    _feedback.warning ((std::string ("Attempt to set an operator for package ")
-                        + std::string(cp->name)
-		       + " with no current specification.").c_str());
 }
 
-
 void
 IniDBBuilderPackage::buildPackageListOperatorVersion (const std::string& aVersion)
 {
@@ -321,111 +274,40 @@ IniDBBuilderPackage::buildPackageListOperatorVersion (const std::string& aVersio
 	endLog;
 #endif
     }
-  else
-      _feedback.warning ((std::string ("Attempt to set an operator version for package ")
-                          + std::string(cp->name)
-			  + " with no current specification.").c_str());
 }
 
-/* privates */
-
 void
-IniDBBuilderPackage::add_correct_version()
+IniDBBuilderPackage::buildMessage (const std::string& _message_id, const std::string& _message_string)
 {
-  cbpv.setDepends(currentNodeList);
+  message_id = _message_id;
+  message_string = _message_string;
+}
 
-  int merged = 0;
-  for (set<packageversion>::iterator n = cp->versions.begin();
-       !merged && n != cp->versions.end(); ++n)
-    if (*n == cbpv )
-      {
-	packageversion ver = *n;
-        /* ASSUMPTIONS:
-           categories and requires are consistent for the same version across
-           all mirrors
-           */
-        /*
-          XXX: if the versions are equal but the size/md5sum are different,
-          we should alert the user, as they may not be getting what they expect...
-        */
-        /* Copy the binary mirror across if this site claims to have an install */
-        if (cbpv.source()->sites.size() )
-          ver.source()->sites.push_back(site (cbpv.source()->sites.begin()->key));
-        /* Copy the descriptions across */
-        if (cbpv.SDesc ().size() && !n->SDesc ().size())
-          ver.set_sdesc (cbpv.SDesc ());
-        if (cbpv.LDesc ().size() && !n->LDesc ().size())
-          ver.set_ldesc (cbpv.LDesc ());
-	if (cbpv.depends().size() && !ver.depends().size())
-	  ver.setDepends(cbpv.depends());
-	/* TODO: other package lists */
-	/* Prevent dangling references */
-	currentNodeList = PackageDepends();
-	currentSpec = NULL;
-        cbpv = *n;
-        merged = 1;
-#if DEBUG
-        Log (LOG_BABBLE) << cp->name << " merged with an existing version " << cbpv.Canonical_version() << endLog;
-#endif
-      }
+/* privates */
+void
+IniDBBuilderPackage::process ()
+{
+  if (!name.size())
+    return;
 
-  if (!merged)
-    {
-      cp->add_version (cbpv);
 #if DEBUG
-      Log (LOG_BABBLE) << cp->name << " version " << cbpv.Canonical_version() << " added" << endLog;
+  Log (LOG_BABBLE) << "Finished with package " << name << endLog;
+  Log (LOG_BABBLE) << "Version " << cbpv.version << endLog;
 #endif
-    }
 
-  /*
-    Should this version be the one selected for this package at a given
-    stability/trust setting?  After merging potentially multiple package
-    databases, we should pick the one with the highest version number.
-  */
-  packageversion *v = NULL;
-  switch (cbpv.Stability())
-  {
-    case TRUST_CURR:
-      v = &(cp->curr);
-    break;
-    case TRUST_TEST:
-      v = &(cp->exp);
-    break;
-    default:
-    break;
-  }
+  /* Transfer the accumulated package information to packagedb */
+  packagedb db;
+  packagemeta *pkg = db.addBinary (name, cbpv);
 
-  if (v)
+  // For no good historical reason, some data lives in packagemeta rather than
+  // the packageversion
+  for (auto i = categories.begin(); i != categories.end(); i++)
     {
-      int comparison = packageversion::compareVersions(cbpv, *v);
-
-      if ((bool)(*v))
-        Log (LOG_BABBLE) << "package " << cp->name << " comparing versions " << cbpv.Canonical_version() << " and " << v->Canonical_version() << ", result was " << comparison << endLog;
-
-      if (comparison > 0)
-        {
-          *v = cbpv;
-        }
+      pkg->add_category(*i);
     }
-}
-
-void
-IniDBBuilderPackage::process_src (packagesource &src, const std::string& path)
-{
-  if (!src.Canonical())
-    src.set_canonical (path.c_str());
-  src.sites.push_back(site(parse_mirror));
-}
+  pkg->set_message(message_id, message_string);
 
-void
-IniDBBuilderPackage::setSourceSize (packagesource &src, const std::string& size)
-{
-  if (!src.size)
-    src.size = atoi(size.c_str());
-}
-
-void
-IniDBBuilderPackage::buildMessage (const std::string& message_id, const std::string& message)
-{
-  cp->set_message (message_id, message);
+  // Reset for next version
+  cbpv.spkg = PackageSpecification();
+  cbpv.spkg_id = packageversion();
 }
diff --git a/IniDBBuilderPackage.h b/IniDBBuilderPackage.h
index 8825add..307d2b5 100644
--- a/IniDBBuilderPackage.h
+++ b/IniDBBuilderPackage.h
@@ -17,11 +17,15 @@
 #define SETUP_INIDBBUILDERPACKAGE_H
 
 #include <vector>
-#include "package_version.h"
+#include <set>
+
+#include "package_message.h"
+#include "PackageTrust.h"
+#include "String++.h"
+#include "libsolv.h"
 
 class IniParseFeedback;
 class packagesource;
-class packagemeta;
 
 enum class hashType { none, md5, sha512 };
 
@@ -48,7 +52,7 @@ public:
   void buildPackageSource (const std::string& path, const std::string& size)
   { buildPackageSource(path, size, NULL, hashType::none); }
 
-  void buildPackageTrust (package_stability_t);
+  void buildPackageTrust (trusts);
   void buildPackageCategory (const std::string& );
 
   void buildBeginDepends ();
@@ -63,6 +67,7 @@ public:
   void set_arch (const std::string& a) { arch = a; }
   void set_release (const std::string& rel) { release = rel; }
 
+  // setup.ini header data
   unsigned int timestamp;
   std::string arch;
   std::string release;
@@ -70,16 +75,17 @@ public:
   std::string parse_mirror;
 
 private:
-  void add_correct_version();
-  void process_src (packagesource &src, const std::string& );
-  void setSourceSize (packagesource &src, const std::string& );
-
-  packagemeta *cp;
-  packageversion cbpv;
-  packagemeta *csp;
-  packageversion cspv;
+  void process ();
+
+  // package data
+  std::string name;
+  std::set <std::string, casecompare_lt_op> categories;
+  std::string message_id;
+  std::string message_string;
   PackageSpecification *currentSpec;
   PackageDepends currentNodeList;
+  SolverPool::addPackageData cbpv;
+
   IniParseFeedback const &_feedback;
 };
 
diff --git a/Makefile.am b/Makefile.am
index d4c8472..a8bfe4b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -100,7 +100,7 @@ inilint_SOURCES = \
 	String++.h
 
 @SETUP@_LDADD = \
-	libgetopt++/libgetopt++.la -lgcrypt -lgpg-error -llzma -lbz2 -lz \
+	libgetopt++/libgetopt++.la -lgcrypt -lgpg-error -llzma -lbz2 -lz -lsolv -lgnurx \
 	-lshlwapi -lcomctl32 -lole32 -lws2_32 -lpsapi -luuid -lntdll -lwininet -lmingw32
 @SETUP@_LDFLAGS = -mwindows -Wc,-static -static-libtool-libs
 @SETUP@_SOURCES = \
@@ -173,6 +173,8 @@ inilint_SOURCES = \
 	IOStreamProvider.h \
 	KeysSetting.cc \
 	KeysSetting.h \
+	libsolv.cc \
+	libsolv.h \
 	localdir.cc \
 	localdir.h \
 	LogFile.cc \
diff --git a/PackageSpecification.cc b/PackageSpecification.cc
index 247f3da..a2a3e48 100644
--- a/PackageSpecification.cc
+++ b/PackageSpecification.cc
@@ -28,6 +28,18 @@ PackageSpecification::packageName () const
   return _packageName;
 }
 
+const PackageSpecification::_operators
+PackageSpecification::op() const
+{
+  return _operator;
+}
+
+const std::string&
+PackageSpecification::version() const
+{
+  return _version;
+}
+
 void
 PackageSpecification::setOperator (_operators anOperator)
 {
diff --git a/PackageSpecification.h b/PackageSpecification.h
index 4c3ed6d..ef992fa 100644
--- a/PackageSpecification.h
+++ b/PackageSpecification.h
@@ -39,6 +39,9 @@ public:
   };
 
   const std::string& packageName() const;
+  const _operators op() const;
+  const std::string& version() const;
+
   void setOperator (_operators);
   void setVersion (const std::string& );
 
diff --git a/configure.ac b/configure.ac
index ab548c0..421b9b4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -60,6 +60,7 @@ AC_CHECK_HEADER(zlib.h, , missing_deps="$missing_deps zlib")
 AC_CHECK_HEADER(bzlib.h, , missing_deps="$missing_deps libbz2")
 AC_CHECK_HEADER(lzma.h, , missing_deps="$missing_deps liblzma")
 AC_CHECK_HEADER(gcrypt.h, , missing_deps="$missing_deps libgcrypt")
+AC_CHECK_HEADER(solv/pool.h, , missing_deps="$missing_deps libsolv")
 
 if test -n "$missing_deps"; then
 	AC_MSG_ERROR([missing prerequisites: $missing_deps])
diff --git a/ini.cc b/ini.cc
index 1162b91..b324e73 100644
--- a/ini.cc
+++ b/ini.cc
@@ -346,15 +346,14 @@ do_remote_ini (HWND owner)
 static bool
 do_ini_thread (HINSTANCE h, HWND owner)
 {
-  packagedb db;
-  db.read();
-
   size_t ini_count = 0;
   if (source == IDC_SOURCE_LOCALDIR)
     ini_count = do_local_ini (owner);
   else
     ini_count = do_remote_ini (owner);
 
+  packagedb db;
+  db.read();
   db.upgrade();
 
   if (ini_count == 0)
diff --git a/libsolv.cc b/libsolv.cc
new file mode 100644
index 0000000..67c68b5
--- /dev/null
+++ b/libsolv.cc
@@ -0,0 +1,443 @@
+/*
+ * Copyright (c) 2017 Jon Turney
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ */
+
+#include "libsolv.h"
+
+#include "solv/solver.h"
+#include "solv/solverdebug.h"
+#include "solv/evr.h"
+
+#include "LogSingleton.h"
+
+// ---------------------------------------------------------------------------
+// Utility functions for mapping between Operators and Relation Ids
+// ---------------------------------------------------------------------------
+
+static Id
+Operator2RelId(PackageSpecification::_operators op)
+{
+  switch (op)
+    {
+    case PackageSpecification::Equals:
+      return REL_EQ;
+    case PackageSpecification::LessThan:
+      return REL_LT;
+    case PackageSpecification::MoreThan:
+      return REL_GT;
+    case PackageSpecification::LessThanEquals:
+      return REL_LT | REL_EQ;
+    case PackageSpecification::MoreThanEquals:
+      return REL_GT | REL_EQ;
+    }
+
+  return 0;
+}
+
+static PackageSpecification::_operators
+RelId2Operator(Id id)
+{
+  switch (id)
+    {
+    case REL_EQ:
+      return PackageSpecification::Equals;
+    case REL_LT:
+      return PackageSpecification::LessThan;
+    case REL_GT:
+      return PackageSpecification::MoreThan;
+    case REL_LT | REL_EQ:
+      return PackageSpecification::LessThanEquals;
+    case REL_GT | REL_EQ:
+      return PackageSpecification::MoreThanEquals;
+    }
+
+  return PackageSpecification::Equals;
+}
+
+// ---------------------------------------------------------------------------
+// implements class SolvableVersion
+//
+// a wrapper around a libsolv Solvable
+// ---------------------------------------------------------------------------
+
+const std::string
+SolvableVersion::Name () const
+{
+  Solvable *solvable = pool_id2solvable(pool, id);
+  return std::string(pool_id2str(pool, solvable->name));
+}
+
+const std::string
+SolvableVersion::Canonical_version() const
+{
+  Solvable *solvable = pool_id2solvable(pool, id);
+  return std::string(pool_id2str(pool, solvable->evr));
+}
+
+package_type_t
+SolvableVersion::Type () const
+{
+  Solvable *solvable = pool_id2solvable(pool, id);
+  if (solvable->arch == ARCH_SRC)
+    return package_source;
+  else
+    return package_binary;
+}
+
+const PackageDepends
+SolvableVersion::depends() const
+{
+  Solvable *solvable = pool_id2solvable(pool, id);
+
+  Queue q;
+  queue_init(&q);
+
+  if (repo_lookup_idarray(solvable->repo, id, SOLVABLE_REQUIRES, &q))
+    {
+      // convert
+      PackageDepends dep;
+
+      for (int i = 0; i < q.count; i++)
+        {
+#ifdef DEBUG
+          Log (LOG_PLAIN) << "dep " << std::hex << q.elements[i] << ": " << pool_dep2str(pool, q.elements[i]) << endLog;
+#endif
+
+          const char *name = pool_id2str(pool, q.elements[i]);
+          PackageSpecification *spec = new PackageSpecification (name);
+
+          if (ISRELDEP(id))
+            {
+              Reldep *rd = GETRELDEP(pool, id);
+              spec->setOperator(RelId2Operator(rd->flags));
+              spec->setVersion(pool_id2str(pool, rd->evr));
+            }
+
+          dep.push_back (spec);
+        }
+
+      queue_empty(&q);
+
+      return dep;
+    }
+
+  // otherwise, return an empty depends list
+  static PackageDepends empty_package;
+  return empty_package;
+}
+
+const std::string
+SolvableVersion::SDesc () const
+{
+  Solvable *solvable = pool_id2solvable(pool, id);
+  const char *sdesc = repo_lookup_str(solvable->repo, id, SOLVABLE_SUMMARY);
+  return sdesc;
+}
+
+SolvableVersion
+SolvableVersion::sourcePackage () const
+{
+  if (!id)
+    return SolvableVersion();
+
+  // extract source package id
+  Solvable *solvable = pool_id2solvable(pool, id);
+  Id spkg_attr = pool_str2id(pool, "solvable:sourceid", 1);
+  Id spkg_id = repo_lookup_id(solvable->repo, id, spkg_attr);
+
+  // has no such attribute
+  if (!spkg_id)
+    return SolvableVersion();
+
+  return SolvableVersion(spkg_id, pool);
+}
+
+packagesource *
+SolvableVersion::source() const
+{
+  if (!id) {
+    static packagesource empty_source = packagesource();
+    return &empty_source;
+  }
+
+  Solvable *solvable = pool_id2solvable(pool, id);
+  Id psrc_attr = pool_str2id(pool, "solvable:packagesource", 1);
+  return (packagesource *)repo_lookup_num(solvable->repo, id, psrc_attr, 0);
+}
+
+bool
+SolvableVersion::accessible () const
+{
+  // XXX: accessible if archive is locally available, or we know a mirror
+  //
+  // (This seems utterly pointless.  Packages which aren't locally available are
+  // removed from the package list.  Packages we don't know a mirror for don't
+  // appear in the packagelist.)
+  return TRUE;
+}
+
+package_stability_t
+SolvableVersion::Stability () const
+{
+  Solvable *solvable = pool_id2solvable(pool, id);
+  Id stability_attr = pool_str2id(pool, "solvable:stability", 1);
+  return (package_stability_t)repo_lookup_num(solvable->repo, id, stability_attr, TRUST_UNKNOWN);
+}
+
+bool
+SolvableVersion::operator <(SolvableVersion const &rhs) const
+{
+  return (compareVersions(*this, rhs) < 0);
+}
+
+bool
+SolvableVersion::operator ==(SolvableVersion const &rhs) const
+{
+  return (compareVersions(*this, rhs) == 0);
+}
+
+bool
+SolvableVersion::operator !=(SolvableVersion const &rhs) const
+{
+  return (compareVersions(*this, rhs) != 0);
+}
+
+int
+SolvableVersion::compareVersions(const SolvableVersion &a,
+                                 const SolvableVersion &b)
+{
+  if (a.id == b.id)
+    return 0;
+
+  // if a and b are different, at least one of them has a pool
+  Pool *pool = a.pool ? a.pool : b.pool;
+
+  Solvable *sa = a.id ? pool_id2solvable(a.pool, a.id) : NULL;
+  Solvable *sb = b.id ? pool_id2solvable(b.pool, b.id) : NULL;
+
+  // empty versions compare as if their version is the empty string
+  Id evra = sa ? sa->evr : pool_str2id(pool, "", 1);
+  Id evrb = sb ? sb->evr : pool_str2id(pool, "", 1);
+
+  return pool_evrcmp(pool, evra, evrb, EVRCMP_COMPARE);
+}
+
+// ---------------------------------------------------------------------------
+// implements class SolverPool
+//
+// a simplified wrapper for libsolv
+// ---------------------------------------------------------------------------
+
+static
+void debug_callback(Pool *pool, void *data, int type, const char *str)
+{
+  if (type & (SOLV_FATAL|SOLV_ERROR))
+    LogPlainPrintf("libsolv: %s", str);
+  else
+    LogBabblePrintf("libsolv: %s", str);
+}
+
+SolverPool::SolverPool()
+{
+  /* create a pool */
+  pool = pool_create();
+
+  pool_setdebugcallback(pool, debug_callback, NULL);
+
+  int level = 1;
+#if DEBUG
+  level = 3;
+#endif
+  pool_setdebuglevel(pool, level);
+
+  /* create the repo to hold installed packages */
+  SolvRepo *installed = getRepo("_installed");
+  pool_set_installed(pool, installed->repo);
+}
+
+SolvRepo *
+SolverPool::getRepo(const std::string &name, bool test)
+{
+  RepoList::iterator i = repos.find(name);
+  if (i != repos.end())
+    return i->second;
+
+  /* create repo if not found */
+  SolvRepo *r = new(SolvRepo);
+  r->repo = repo_create(pool, name.c_str());
+
+  /* create attribute store, with no local pool */
+  r->data = repo_add_repodata(r->repo, 0);
+
+  /* remember if this is a test stability repo */
+  r->test = test;
+
+  repos[name] = r;
+
+  return r;
+}
+
+/*
+  Helper function to convert a PackageDepends list to libsolv dependencies.
+*/
+Id
+SolverPool::makedeps(Repo *repo, PackageDepends *requires)
+{
+  Id deps = 0;
+
+  for (PackageDepends::iterator i = requires->begin();
+       i != requires->end();
+       i++)
+    {
+      Id name = pool_str2id(pool, (*i)->packageName().c_str(), 1);
+
+      if ((*i)->version().size() == 0)
+        {
+          // no relation, so dependency is just on package name
+          deps = repo_addid_dep(repo, deps, name, 0);
+        }
+      else
+        {
+          // otherwise, dependency is on package name with a version condition
+          Id evr = pool_str2id(pool, (*i)->version().c_str(), 1);
+          int rel = pool_rel2id(pool, name, evr, Operator2RelId((*i)->op()), 1);
+
+          deps = repo_addid_dep(repo, deps, rel, 0);
+        }
+    }
+
+  return deps;
+}
+
+SolvableVersion
+SolverPool::addPackage(const std::string& pkgname, const addPackageData &pkgdata)
+{
+  std::string repoName = pkgdata.reponame;
+  bool test = false;
+
+  /* It's simplest to place test packages into a separate repo, and then
+     arrange for that repo to be disabled, if we don't want to consider
+     those packages */
+
+  if (pkgdata.stability == TRUST_TEST)
+    {
+      repoName = pkgdata.reponame + "_test_";
+      test = true;
+    }
+
+  SolvRepo *r = getRepo(repoName, test);
+  Repo *repo = r->repo;
+
+  /* create a solvable */
+  Id s = repo_add_solvable(repo);
+  Solvable *solvable = pool_id2solvable(pool, s);
+
+  /* initialize solvable for this packageo/version/etc.  */
+  solvable->name = pool_str2id(pool, pkgname.c_str(), 1);
+  solvable->arch = (pkgdata.type == package_binary) ? ARCH_ANY : ARCH_SRC;
+  solvable->evr = pool_str2id(repo->pool, pkgdata.version.c_str(), 1);
+  solvable->vendor = pool_str2id(repo->pool, pkgdata.vendor.c_str(), 1);
+  solvable->provides = repo_addid_dep(repo, solvable->provides, pool_rel2id(pool, solvable->name, solvable->evr, REL_EQ, 1), 0);
+  if (pkgdata.requires)
+    solvable->requires = makedeps(repo, pkgdata.requires);
+
+  /* a solvable can also store arbitrary attributes not needed for dependency
+     resolution, if we need them */
+
+  Repodata *data = r->data;
+  Id handle = s;
+#if DEBUG
+  Log (LOG_PLAIN) << "solvable " << s << " name " << pkgname << endLog;
+#endif
+
+  /* store short description attribute */
+  repodata_set_str(data, handle, SOLVABLE_SUMMARY, pkgdata.sdesc.c_str());
+  /* store long description attribute */
+  repodata_set_str(data, handle, SOLVABLE_DESCRIPTION, pkgdata.ldesc.c_str());
+
+  /* store source-package attribute */
+  const std::string sname = pkgdata.spkg.packageName();
+  if (!sname.empty())
+    repodata_set_id(data, handle, SOLVABLE_SOURCENAME, pool_str2id(pool, sname.c_str(), 1));
+  else
+    repodata_set_void(data, handle, SOLVABLE_SOURCENAME);
+  /* solvable:sourceevr may also be available from spkg but assumed to be same
+     as evr for the moment */
+
+  /* store source-package id */
+  /* XXX: this assumes we create install package after source package and so can
+     know that id */
+  Id spkg_attr = pool_str2id(pool, "solvable:sourceid", 1);
+  repodata_set_id(data, handle, spkg_attr, pkgdata.spkg_id.id);
+
+  /* we could store packagesource information as attributes ...
+
+     e.g.
+       size     SOLVABLE_DOWNLOADSIZE
+       pathname SOLVABLE_MEDIAFILE
+       site     SOLVABLE_MEDIABASE
+       checksum SOLVABLE_CHECKSUM
+
+     ... but for the moment, we just store a pointer to a packagesource object
+  */
+  Id psrc_attr = pool_str2id(pool, "solvable:packagesource", 1);
+  packagesource *psrc = new packagesource(pkgdata.archive);
+  repodata_set_num(data, handle, psrc_attr, (intptr_t)psrc);
+
+  /* store stability level attribute */
+  Id stability_attr = pool_str2id(pool, "solvable:stability", 1);
+  repodata_set_num(data, handle, stability_attr, pkgdata.stability);
+
+#if 0
+  repodata_internalize(data);
+
+  /* debug: verify the attributes we've just set get retrieved correctly */
+  SolvableVersion sv = SolvableVersion(s, pool);
+  const std::string check_sdesc = sv.SDesc();
+  if (pkgdata.sdesc.compare(check_sdesc) != 0) {
+    Log (LOG_PLAIN) << pkgname << " has sdesc mismatch: '" << pkgdata.sdesc << "' and '"
+                    << check_sdesc << "'" << endLog;
+  }
+  if (!sname.empty()) {
+    SolvableVersion check_spkg = sv.sourcePackage();
+    Solvable *check_spkg_solvable = pool_id2solvable(pool, check_spkg.id);
+    std::string check_sname = pool_id2str(pool, check_spkg_solvable->name);
+    if (sname.compare(check_sname) != 0) {
+      Log (LOG_PLAIN) << pkgname << " has spkg mismatch: '" << pkgdata.spkg.packageName()
+                      << "' and '" << check_sname << "'" << endLog;
+    }
+  }
+  packagesource *check_archive = sv.source();
+  if (check_archive != psrc)
+    Log (LOG_PLAIN) << pkgname << " has archive mismatch: " << psrc
+                    << " and " << check_archive << endLog;
+  package_stability_t check_stability = sv.Stability();
+  if (check_stability != pkgdata.stability) {
+    Log (LOG_PLAIN) << pkgname << " has stability mismatch: " << pkgdata.stability
+                    << " and " << check_stability << endLog;
+  }
+#endif
+
+  return SolvableVersion(s, pool);
+}
+
+void
+SolverPool::internalize()
+{
+  /* Make attribute data available to queries */
+  for (RepoList::iterator i = repos.begin();
+       i != repos.end();
+       i++)
+    {
+      repodata_internalize(i->second->data);
+    }
+}
diff --git a/libsolv.h b/libsolv.h
new file mode 100644
index 0000000..490da78
--- /dev/null
+++ b/libsolv.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2017 Jon Turney
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     A copy of the GNU General Public License can be found at
+ *     http://www.gnu.org/
+ *
+ */
+
+#ifndef LIBSOLV_H
+#define LIBSOLV_H
+
+#include "solv/pool.h"
+#include "solv/repo.h"
+#include "PackageSpecification.h"
+#include "PackageTrust.h"
+#include "package_source.h"
+#include "package_depends.h"
+#include <map>
+#include <vector>
+
+typedef trusts package_stability_t;
+
+typedef enum
+{
+  package_binary,
+  package_source
+}
+package_type_t;
+
+// ---------------------------------------------------------------------------
+// interface to class SolverVersion
+//
+// a wrapper around a libsolv Solvable
+// ---------------------------------------------------------------------------
+
+class SolverPool;
+
+class SolvableVersion
+{
+ public:
+  SolvableVersion() : id(0), pool(0) {};
+  SolvableVersion(Id _id, Pool *_pool) : id(_id), pool(_pool) {};
+
+  // converted to a bool, this is true if this isn't the result of the default
+  // constructor (an 'empty' version, in some sense)
+  explicit operator bool () const { return (id != 0); }
+
+  const std::string Name () const;
+  const std::string SDesc () const;
+  // In setup-speak, 'Canonical' version means 'e:v-r', the non-decomposed version
+  const std::string Canonical_version () const;
+  const PackageDepends depends() const;
+  bool accessible () const;
+  package_type_t Type () const;
+  package_stability_t Stability () const;
+
+  // the associated source package, if this is a binary package
+  SolvableVersion sourcePackage () const;
+
+  // where this package archive can be obtained from
+  packagesource *source() const;
+
+  // utility function to compare package versions
+  static int compareVersions(const SolvableVersion &a, const SolvableVersion &b);
+
+  // comparison operators
+
+  // these are somewhat necessary as otherwise we are compared as bool values
+  bool operator == (SolvableVersion const &) const;
+  bool operator != (SolvableVersion const &) const;
+
+  // these are only well defined for versions of the same package
+  bool operator < (SolvableVersion const &) const;
+  bool operator <= (SolvableVersion const &) const;
+  bool operator > (SolvableVersion const &) const;
+  bool operator >= (SolvableVersion const &) const;
+
+ private:
+  Id id;
+  Pool *pool;
+
+  friend SolverPool;
+};
+
+// ---------------------------------------------------------------------------
+// Helper class SolvRepo
+//
+// ---------------------------------------------------------------------------
+
+class SolvRepo
+{
+public:
+  Repo *repo;
+  Repodata *data;
+  bool test;
+};
+
+// ---------------------------------------------------------------------------
+// interface to class SolverPool
+//
+// a simplified wrapper for libsolv
+// ---------------------------------------------------------------------------
+
+class SolverPool
+{
+public:
+  SolverPool();
+  SolvRepo *getRepo(const std::string &name, bool test = false);
+
+  // Utility class for passing arguments to addPackage()
+  class addPackageData
+  {
+  public:
+    std::string reponame;
+    std::string version;
+    std::string vendor;
+    std::string sdesc;
+    std::string ldesc;
+    package_stability_t stability;
+    package_type_t type;
+    packagesource archive;
+    PackageSpecification spkg;
+    SolvableVersion spkg_id;
+    PackageDepends *requires;
+  };
+
+  SolvableVersion addPackage(const std::string& pkgname,
+                             const addPackageData &pkgdata);
+
+  void internalize(void);
+
+private:
+  Id makedeps(Repo *repo, PackageDepends *requires);
+  Pool *pool;
+
+  typedef std::map<std::string, SolvRepo *> RepoList;
+  RepoList repos;
+};
+
+
+#endif // LIBSOLV_H
diff --git a/package_db.cc b/package_db.cc
index 4e22953..c561089 100644
--- a/package_db.cc
+++ b/package_db.cc
@@ -40,6 +40,7 @@
 #include "Generic.h"
 #include "LogSingleton.h"
 #include "resource.h"
+#include "libsolv.h"
 
 using namespace std;
 
@@ -52,6 +53,8 @@ packagedb::read ()
 {
   if (!installeddbread)
     {
+      solver.internalize();
+
       /* Read in the local installation database. */
       io_stream *db = 0;
       db = io_stream::open ("cygfile:///etc/setup/installed.db", "rt", 0);
@@ -103,23 +106,37 @@ packagedb::read ()
 		  if (!parseable)
 		    continue;
 
-		  packagemeta *pkg = findBinary (PackageSpecification(pkgname));
-		  if (!pkg)
-		    {
-		      pkg = new packagemeta (pkgname);
-		      packages.insert (packagedb::packagecollection::value_type(pkgname, pkg));
-		    }
-
-		  packageversion binary = 
-		    cygpackage::createInstance (pkgname, f.ver,
-						package_binary);
-
-		  pkg->add_version (binary);
-		  pkg->set_installed (binary);
-		  pkg->desired = pkg->installed;
+                  SolverPool::addPackageData data;
+                  data.reponame = "_installed";
+                  data.version = f.ver;
+                  data.type = package_binary;
+
+                  // very limited information is available from installed.db, so
+                  // we put our best guesses here...
+                  data.vendor = "cygwin";
+                  data.requires = NULL;
+                  data.sdesc = "";
+                  data.ldesc = "";
+                  data.stability = TRUST_CURR; // XXX: would be nice to get this correct as it effects upgrade decisions...
+
+                  // supplement this with sdesc and source information from
+                  // setup.ini, if possible...
+                  packagemeta *pkgm = findBinary(PackageSpecification(pkgname));
+                  if (pkgm)
+                    {
+                      data.sdesc = pkgm->curr.SDesc();
+                      data.archive = *pkgm->curr.source();
+                      data.spkg = std::string(pkgname) + "-src";
+                      data.spkg_id = pkgm->curr.sourcePackage();
+                    }
+
+		  packagemeta *pkg = packagedb::addBinary (pkgname, data);
+
+		  pkg->set_installed_version (f.ver);
 
 		  if (dbver == 3)
 		    pkg->user_picked = (user_picked & 1);
+
 		}
 	      delete db;
 	      db = 0;
@@ -132,6 +149,50 @@ packagedb::read ()
 	  installeddbver = dbver;
 	}
     }
+  solver.internalize();
+}
+
+/* Add a package version to the packagedb */
+packagemeta *
+packagedb::addBinary (const std::string &pkgname,
+                      const SolverPool::addPackageData &pkgdata)
+{
+  /* If pkgname isn't already in packagedb, add a packagemeta */
+  packagemeta *pkg = findBinary (PackageSpecification(pkgname));
+  if (!pkg)
+    {
+      pkg = new packagemeta (pkgname);
+      packages.insert (packagedb::packagecollection::value_type(pkgname, pkg));
+    }
+
+  /* Create the SolvableVersion  */
+  SolvableVersion sv = solver.addPackage(pkgname, pkgdata);
+
+  /* Register it in packagemeta */
+  pkg->add_version (sv, pkgdata);
+
+  return pkg;
+}
+
+packageversion
+packagedb::addSource (const std::string &pkgname,
+                      const SolverPool::addPackageData &pkgdata)
+{
+  /* If pkgname isn't already in packagedb, add a packagemeta */
+  packagemeta *pkg = findSource (PackageSpecification(pkgname));
+  if (!pkg)
+    {
+      pkg = new packagemeta (pkgname);
+      sourcePackages.insert (packagedb::packagecollection::value_type(pkgname, pkg));
+    }
+
+  /* Create the SolvableVersion  */
+  SolvableVersion sv = solver.addPackage(pkgname, pkgdata);
+
+  /* Register it in packagemeta */
+  pkg->add_version (sv, pkgdata);
+
+  return sv;
 }
 
 int
@@ -230,6 +291,7 @@ packagedb::categoriesType packagedb::categories;
 packagedb::packagecollection packagedb::sourcePackages;
 PackageDBActions packagedb::task = PackageDB_Install;
 std::vector <packagemeta *> packagedb::dependencyOrderedPackages;
+SolverPool packagedb::solver;
 
 #include <stack>
 
diff --git a/package_db.h b/package_db.h
index d26f8ad..022358e 100644
--- a/package_db.h
+++ b/package_db.h
@@ -57,6 +57,7 @@ typedef std::vector <packagemeta *>::iterator PackageDBConnectedIterator;
 
 */
 
+#include "libsolv.h"
 #include <PackageTrust.h>
 
 class packagedb
@@ -69,6 +70,8 @@ public:
   void upgrade ();
   packagemeta * findBinary (PackageSpecification const &) const;
   packagemeta * findSource (PackageSpecification const &) const;
+  packagemeta * addBinary (const std::string &pkgname, const SolverPool::addPackageData &pkgdata);
+  packageversion addSource (const std::string &pkgname, const SolverPool::addPackageData &pkgdata);
   PackageDBConnectedIterator connectedBegin();
   PackageDBConnectedIterator connectedEnd();
   void fillMissingCategory();
@@ -83,6 +86,9 @@ public:
   typedef std::map <std::string, std::vector <packagemeta *>, casecompare_lt_op > categoriesType;
   static categoriesType categories;
   static PackageDBActions task;
+
+  static SolverPool solver;
+
 private:
   static int installeddbread;	/* do we have to reread this */
   static int installeddbver;
diff --git a/package_meta.cc b/package_meta.cc
index 425df59..c19eddf 100644
--- a/package_meta.cc
+++ b/package_meta.cc
@@ -128,19 +128,84 @@ packagemeta::~packagemeta()
 }
 
 void
-packagemeta::add_version (packageversion & thepkg)
+packagemeta::add_version (packageversion & thepkg, const SolverPool::addPackageData &pkgdata)
 {
-  /* todo: check return value */
-  versions.insert (thepkg);
+  /*
+    If a packageversion for the same version number is already present,allow
+    this version to replace it.
+
+    There is a problem where multiple repos provide a package.  It's never been
+    clear which repo should win.  With this implementation, the last one added
+    will win.
+
+    We rely on this by adding packages from installed.db last.
+   */
+
+  set <packageversion>::iterator i = versions.find(thepkg);
+  if (i != versions.end())
+    {
+      versions.erase(i);
+    }
+
+  /* Add the version */
+  std::pair<std::set <packageversion>::iterator, bool> result = versions.insert (thepkg);
+
+  if (!result.second)
+    Log (LOG_PLAIN) << "Failed to add version " << thepkg.Canonical_version() << " in package " << name << endLog;
+#ifdef DEBUG
+  else
+    Log (LOG_PLAIN) << "Added version " << thepkg.Canonical_version() << " in package " << name << endLog;
+#endif
+
+  /* Record the highest version at a given stability level */
+  /* (This has to be written somewhat carefully as attributes aren't
+     internalized yet so we can't look at them) */
+  packageversion *v = NULL;
+  switch (pkgdata.stability)
+    {
+    case TRUST_CURR:
+      v = &(this->curr);
+      break;
+    case TRUST_TEST:
+      v = &(this->exp);
+      break;
+    default:
+      break;
+    }
+
+  if (v)
+    {
+      /* Any version is always greater than no version */
+      int comparison = 1;
+      if (*v)
+        comparison = SolvableVersion::compareVersions(thepkg, *v);
+
+#ifdef DEBUG
+      if ((bool)(*v))
+        Log (LOG_BABBLE) << "package " << thepkg.Name() << " comparing versions " << thepkg.Canonical_version() << " and " << v->Canonical_version() << ", result was " << comparison << endLog;
+#endif
+
+      if (comparison >= 0)
+        {
+          *v = thepkg;
+        }
+    }
 }
 
-/* assumption: package thepkg is already in the metadata list. */
 void
-packagemeta::set_installed (packageversion & thepkg)
+packagemeta::set_installed_version (const std::string &version)
 {
-  set<packageversion>::const_iterator temp = versions.find (thepkg);
-  if (temp != versions.end())
-    installed = thepkg;
+  set<packageversion>::iterator i;
+  for (i = versions.begin(); i != versions.end(); i++)
+    {
+      if (version.compare(i->Canonical_version()) == 0)
+        {
+          installed = *i;
+
+          /* and mark as Keep */
+          desired = installed;
+        }
+    }
 }
 
 void
@@ -174,12 +239,6 @@ packagemeta::getReadableCategoryList () const
               ).visitor.result;
 }
 
-static bool
-hasSDesc(packageversion const &pkg)
-{
-  return pkg.SDesc().size();
-}
-
 static void
 parseNames (std::set<string> &parsed, std::string &option)
 {
@@ -304,11 +363,15 @@ bool packagemeta::isManuallyDeleted() const
 const std::string
 packagemeta::SDesc () const
 {
-  set<packageversion>::iterator i = find_if (versions.begin(), versions.end(), hasSDesc);
-  if (i == versions.end())
-    return std::string();
-  return i->SDesc ();
-};
+  set<packageversion>::iterator i;
+  for (i = versions.begin(); i != versions.end(); i++)
+    {
+      if (i->SDesc().size())
+        return i->SDesc ();
+    }
+
+  return std::string();
+}
 
 /* Return an appropriate caption given the current action. */
 std::string 
diff --git a/package_meta.h b/package_meta.h
index 8041aa1..421646a 100644
--- a/package_meta.h
+++ b/package_meta.h
@@ -28,7 +28,7 @@ class packagemeta;
 
 typedef std::pair<const std::string, std::vector<packagemeta *> > Category;
 
-/* NOTE: A packagemeta without 1 packageversion is invalid! */
+/* NOTE: A packagemeta without 1 version is invalid! */
 class packagemeta
 {
 public:
@@ -42,8 +42,8 @@ public:
 
   ~packagemeta ();
 
-  void add_version (packageversion &);
-  void set_installed (packageversion &);
+  void add_version (packageversion &, const SolverPool::addPackageData &);
+  void set_installed_version (const std::string &);
   void addToCategoryBase();
   bool hasNoCategories() const;
   void setDefaultCategories();
-- 
2.12.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]