]> cygwin.com Git - cygwin-apps/setup.git/blobdiff - package_version.cc
2002-07-15 Robert Collins <rbtcollins@hotmail.com>
[cygwin-apps/setup.git] / package_version.cc
index 4c8fb59d1587e96e72ef313602332829bd8e5e5f..c40c50a6519ee92e6c46bcb2b88485b9746c3a40 100644 (file)
 static const char *cvsid =
   "\n%%% $Id$\n";
 #endif
+
+#include "package_version.h"
+#include "package_db.h"
+#include "package_meta.h"
+#include "state.h"
+#include "resource.h"
+#include <algorithm>
+
+/* a default class to avoid special casing empty packageversions */
+  
+/* TODO place into the class header */
+class _defaultversion : public _packageversion
+{
+public:
+  _defaultversion()
+    {
+      // never try to free me!
+      ++references;
+    }
+  String const Name(){return String();}
+  String const Vendor_version() {return String();}
+  String const Package_version() {return String();}
+  String const Canonical_version() {return String();}
+  void setCanonicalVersion (String const &) {}
+  package_status_t Status (){return package_notinstalled;}
+  package_type_t Type () {return package_binary;}
+  String const getfirstfile () {return String();}
+  String const getnextfile () {return String();}
+  String const SDesc () {return String();}
+  void set_sdesc (String const &) {}
+  String const LDesc () {return String();}
+  void set_ldesc (String const &) {}
+  void uninstall (){}
+};
+static _defaultversion defaultversion;
+
+/* the wrapper class */
+packageversion::packageversion() : data (&defaultversion)
+{
+  ++data->references;
+}
+
+/* Create from an actual package */
+packageversion::packageversion (_packageversion *pkg)
+{
+  if (pkg)
+    data = pkg;
+  else
+    data = &defaultversion;
+  ++data->references;
+}
+
+packageversion::packageversion (packageversion const &existing) : 
+data(existing.data)
+{
+  ++data->references;
+}
+
+packageversion::~packageversion() 
+{
+  if (--data->references == 0)
+    delete data;
+}
+
+packageversion &
+packageversion::operator= (packageversion const &rhs)
+{
+  ++rhs.data->references;
+  if (--data->references == 0)
+    delete data;
+  data = rhs.data;
+  return *this;
+}
+
+bool
+packageversion::operator ! () const
+{
+  return !data->Name().size();
+}
+
+packageversion::operator bool () const
+{
+  return data->Name().size();
+}
+
+bool
+packageversion::operator == (packageversion const &rhs) const
+{
+  if (this == &rhs || data == rhs.data)
+    return true;
+  else
+    return data->Name () == rhs.data->Name() && data->Canonical_version () == rhs.data->Canonical_version();
+}
+
+bool
+packageversion::operator != (packageversion const &rhs) const
+{
+  return ! (*this == rhs);
+}
+
+bool
+packageversion::operator < (packageversion const &rhs) const
+{
+  int t = data->Name ().casecompare (rhs.data->Name());
+  if (t < 0)
+    return true;
+  else if (t > 0)
+    return false;
+  else if (data->Canonical_version().casecompare (rhs.data->Canonical_version()) < 0)
+    return true;
+  return false;
+}
+
+String const 
+packageversion::Name () const
+{
+  return data->Name ();
+}
+
+String const
+packageversion::Canonical_version() const
+{
+  return data->Canonical_version();
+}
+
+void
+packageversion::setCanonicalVersion (String const &ver)
+{
+  data->setCanonicalVersion (ver);
+}
+
+String const
+packageversion::getfirstfile ()
+{
+  return data->getfirstfile ();
+}
+
+String const
+packageversion::getnextfile ()
+{
+  return data->getnextfile ();
+}
+
+String const
+packageversion::SDesc () const
+{
+  return data->SDesc ();
+}
+
+void
+packageversion::set_sdesc (String const &sdesc)
+{
+  data->set_sdesc (sdesc);
+}
+
+String const
+packageversion::LDesc () const
+{
+  return data->LDesc ();
+}
+
+void
+packageversion::set_ldesc (String const &ldesc)
+{
+  data->set_ldesc (ldesc);
+}
+
+packageversion
+packageversion::sourcePackage()
+{
+  return data->sourcePackage();
+}
+
+PackageSpecification &
+packageversion::sourcePackageSpecification ()
+{
+  return data->sourcePackageSpecification ();
+}
+
+void
+packageversion::setSourcePackageSpecification (PackageSpecification const &spec)
+{
+  data->setSourcePackageSpecification(spec);
+}
+
+vector <vector <PackageSpecification *> *> *
+packageversion::depends()
+{
+  return &data->depends;
+}
+
+vector <vector <PackageSpecification *> *> *
+packageversion::predepends()
+{
+      return &data->predepends;
+}
+
+vector <vector <PackageSpecification *> *> *
+packageversion::recommends()
+{
+      return &data->recommends;
+}
+
+vector <vector <PackageSpecification *> *> *
+packageversion::suggests()
+{
+      return &data->suggests;
+}
+
+vector <vector <PackageSpecification *> *> *
+packageversion::replaces()
+{
+      return &data->replaces;
+}
+
+vector <vector <PackageSpecification *> *> *
+packageversion::conflicts()
+{
+      return &data->conflicts;
+}
+
+vector <vector <PackageSpecification *> *> *
+packageversion::provides()
+{
+      return &data->provides;
+}
+
+vector <vector <PackageSpecification *> *> *
+packageversion::binaries()
+{
+      return &data->binaries;
+}
+
+bool
+packageversion::picked () const
+{
+  return data->picked;
+}
+
+void 
+packageversion::pick (bool aBool)
+{
+  data->picked = aBool;
+}
+
+bool
+packageversion::changeRequested () const
+{
+  return data->changeRequested ();
+}
+
+void
+packageversion::uninstall ()
+{
+ data->uninstall ();
+}
+
+packagesource *
+packageversion::source ()
+{
+  if (!data->sources.size())
+    data->sources.push_back (packagesource());
+  return &data->sources[0];
+}
+
+vector<packagesource> *
+packageversion::sources ()
+{
+  return &data->sources;
+}
+
+bool
+packageversion::accessible() const
+{
+  return data->accessible();
+}
+
+static bool
+checkForInstalled (PackageSpecification *spec)
+{
+  packagedb db;
+  packagemeta *required = db.findBinary (*spec);
+  if (!required)
+    return false;
+  if (spec->satisfies (required->installed)
+      && required->desired == required->installed )
+    /* done, found a satisfactory installed version that will remain
+       installed */
+    return true;
+  return false;
+}
+
+static bool
+checkForUpgradeable (PackageSpecification *spec)
+{
+  packagedb db;
+  packagemeta *required = db.findBinary (*spec);
+  if (!required || !required->installed)
+    return false;
+  for (set <packageversion>::iterator i = required->versions.begin();
+       i != required->versions.end(); ++i)
+    if (spec->satisfies (*i))
+      return true;
+  return false;
+}
+
+static bool
+checkForSatisfiable (PackageSpecification *spec)
+{
+  packagedb db;
+  packagemeta *required = db.findBinary (*spec);
+  if (!required)
+    return false;
+  for (set <packageversion>::iterator i = required->versions.begin();
+       i != required->versions.end(); ++i)
+    if (spec->satisfies (*i))
+      return true;
+  return false;
+}
+
+static int
+processOneDependency(trusts deftrust, size_t depth, PackageSpecification *spec)
+{
+  /* TODO: add this to a set of packages to be offered to meet the
+     requirement. For now, simply set the install to the first
+     satisfactory version. The user can step through the list if
+     desired */
+  packagedb db;
+  packagemeta *required = db.findBinary (*spec);
+  set <packageversion>::iterator v;
+  for (v = required->versions.begin();
+    v != required->versions.end() && !spec->satisfies (*v); ++v);
+  if (v != required->versions.end())
+    {
+      /* preserve source */
+      bool sourceticked = required->desired.sourcePackage().picked();
+      /* install this version */
+      required->desired = *v;
+      required->desired.pick (required->installed != required->desired);
+      required->desired.sourcePackage().pick (sourceticked);
+      /* does this requirement have requirements? */
+      return required->set_requirements (deftrust, depth + 1);
+    }
+  /* else assert !! */
+  return 0;
+}
+
+int
+packageversion::set_requirements (trusts deftrust = TRUST_CURR, size_t depth = 0)
+{
+  int changed = 0;
+  vector <vector <PackageSpecification *> *>::iterator dp = depends ()->begin();
+  /* cheap test for too much recursion */
+  if (depth > 5)
+    return changed;
+  /* walk through each and clause */
+  while (dp != depends ()->end())
+    {
+      /* three step:
+        1) is a satisfactory or clause installed?
+        2) is an unsatisfactory version of an or clause which has
+        a satisfactory version available installed?
+        3) is a satisfactory package available?
+        */
+      /* check each or clause for an installed match */
+      vector <PackageSpecification *>::iterator i =
+       find_if ((*dp)->begin(), (*dp)->end(), checkForInstalled);
+      if (i != (*dp)->end())
+       {
+         /* we found an installed ok package */
+         /* next and clause */
+         ++dp;
+         continue;
+       }
+      /* check each or clause for an upgradeable version */
+      i = find_if ((*dp)->begin(), (*dp)->end(), checkForUpgradeable);
+      if (i != (*dp)->end())
+       {
+         /* we found a package that can be up/downgraded to meet the
+            requirement. (*i is the packagespec that can be satisfied.)
+            */
+         ++dp;
+         changed += processOneDependency (deftrust, depth, *i) + 1;
+         continue;
+       }
+      /* check each or clause for an installable version */
+      i = find_if ((*dp)->begin(), (*dp)->end(), checkForSatisfiable);
+      if (i != (*dp)->end())
+       {
+         /* we found a package that can be installed to meet the requirement */
+         ++dp;
+         changed += processOneDependency (deftrust, depth, *i) + 1;
+         continue;
+       }
+      ++dp;
+    }
+  return changed;
+}
+
+/* the parent data class */
+  
+_packageversion::_packageversion ():picked (false), references (0)
+{
+}
+
+_packageversion::~_packageversion ()
+{
+}
+
+PackageSpecification &
+_packageversion::sourcePackageSpecification ()
+{
+  return _sourcePackage;
+}
+
+void
+_packageversion::setSourcePackageSpecification (PackageSpecification const &spec)
+{
+  _sourcePackage = spec;
+}
+
+packageversion
+_packageversion::sourcePackage ()
+{
+  if (!sourceVersion)
+    {
+      packagedb db;
+      packagemeta * pkg;
+      pkg = db.findSource (_sourcePackage);
+      /* no valid source meta available, just return the default
+        (blank) package version 
+        */
+      if (!pkg)
+       return sourceVersion;
+      set<packageversion>::iterator i=pkg->versions.begin();
+      while (i != pkg->versions.end())
+       {
+         packageversion const & ver = * i;
+          if (_sourcePackage.satisfies (ver))
+           sourceVersion = ver;
+          ++i;
+       }
+    }
+  return sourceVersion;
+}
+
+bool
+_packageversion::accessible() const
+{
+  bool cached = true;
+  for (vector<packagesource>::const_iterator i = sources.begin();
+       i!=sources.end(); ++i)
+    if (!i->Cached ())
+      cached = false;
+  if (cached) 
+    return true;
+  if (::source == IDC_SOURCE_CWD)
+    return false;
+  unsigned int retrievable = 0;
+  for (vector<packagesource>::const_iterator i = sources.begin();
+      i!=sources.end(); ++i)
+    if (i->sites.size() || i->Cached ())
+      retrievable += 1;
+  return retrievable == sources.size();
+}
+
+bool
+_packageversion::changeRequested ()
+{
+  return (picked || sourcePackage().picked());
+}
This page took 0.031445 seconds and 5 git commands to generate.