[Aptitude-svn-commit] r3870 - in branches/aptitude-0.3/aptitude: . src/generic

Daniel Burrows dburrows at costa.debian.org
Tue Aug 16 20:41:31 UTC 2005


Author: dburrows
Date: Tue Aug 16 20:41:28 2005
New Revision: 3870

Modified:
   branches/aptitude-0.3/aptitude/ChangeLog
   branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver_universe.cc
Log:
Introduce restrictions on which recommendations are considered 'interesting'.

Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog	(original)
+++ branches/aptitude-0.3/aptitude/ChangeLog	Tue Aug 16 20:41:28 2005
@@ -1,5 +1,12 @@
 2005-08-16  Daniel Burrows  <dburrows at debian.org>
 
+	* src/generic/aptitude_resolver_universe.cc:
+
+	  Redefine is_interesting_dep in terms of "subsumption": a
+	  recommendation is now considered "interesting" iff it covers
+	  neither a subset nor a superset of the version space covered by
+	  a recommendation of the current version.
+
 	* src/generic/aptitude_resolver_universe.cc, src/generic/aptitude_resolver_universe.h:
 
 	  Make the is_interesting_dep function really be a static member

Modified: branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver_universe.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver_universe.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver_universe.cc	Tue Aug 16 20:41:28 2005
@@ -6,12 +6,193 @@
 
 using namespace std;
 
+/** \return \b true if d1 subsumes d2; that is, if one of the
+ *  following holds:
+ *
+ *  (a) d1 and d2 target the same package and are unversioned.
+ *
+ *  (b) d1 and d2 are unversioned and some version of d2's target
+ *      provides the target package of d1.
+ *
+ *  (c) d1 and d2 target the same package, d1 is unversioned, and d2
+ *      is versioned.
+ *
+ *  (c) d1 and d2 target the same package and are versioned
+ *     (with op1 ver1 and op2 ver2 being the operations and versions)
+ *     and:
+ *
+ *       - op1 is >=, op2 is >>, >=, or =, and ver1 <= ver2; or
+ *       - op1 is <=, op2 is <<, <=, or =, and ver1 >= ver2; or
+ *       - op1 is >>, op2 is >>, and ver1 <= ver2; or
+ *       - op1 is >>, op2 is =, and ver1 < ver2; or
+ *       - op1 is <<, op2 is <<, and ver1 >= ver2; or
+ *       - op1 is <<, op2 is =, and ver1 > ver2; or
+ *       - op1 is =, op2 is =, and ver1 = ver2; or
+ *       - op1 is !=, op2 is !=, and ver1 = ver2.
+ */
+static bool subsumes(const pkgCache::DepIterator &d1,
+		     const pkgCache::DepIterator &d2)
+{
+  pkgCache::PkgIterator target1 = const_cast<pkgCache::DepIterator &>(d1).TargetPkg();
+  pkgCache::PkgIterator target2 = const_cast<pkgCache::DepIterator &>(d2).TargetPkg();
+
+  if(!d1.TargetVer())
+    {
+      if(target1 == target2)
+	return true;
+
+      if(d2.TargetVer())
+	return false;
+
+      for(pkgCache::PrvIterator p = target1.ProvidesList();
+	  !p.end(); ++p)
+	if(p.OwnerPkg() == target2)
+	  return true;
+
+      return false;
+    }
+  else
+    {
+      if(target1 != target2)
+	return false;
+
+      if(!d2.TargetVer())
+	return false;
+
+      pkgCache::Dep::DepCompareOp t1 = (pkgCache::Dep::DepCompareOp) (d1->CompareOp &~ pkgCache::Dep::Or);
+      pkgCache::Dep::DepCompareOp t2 = (pkgCache::Dep::DepCompareOp) (d2->CompareOp &~ pkgCache::Dep::Or);
+
+      int cmpresult = _system->VS->DoCmpVersion(d1.TargetVer(), d1.TargetVer()+strlen(d1.TargetVer()),
+						d2.TargetVer(), d2.TargetVer()+strlen(d2.TargetVer()));
+
+      switch(t1)
+	{
+	case pkgCache::Dep::LessEq:
+	  return
+	    (t2 == pkgCache::Dep::Less ||
+	     t2 == pkgCache::Dep::LessEq ||
+	     t2 == pkgCache::Dep::Equals) &&
+	    cmpresult >= 0;
+	case pkgCache::Dep::GreaterEq:
+	  return
+	    (t2 == pkgCache::Dep::Greater ||
+	     t2 == pkgCache::Dep::LessEq ||
+	     t2 == pkgCache::Dep::Equals) &&
+	    cmpresult <= 0;
+	case pkgCache::Dep::Less:
+	  return
+	    (t2 == pkgCache::Dep::Less && cmpresult >= 0) ||
+	    (t2 == pkgCache::Dep::Equals && cmpresult > 0);
+	case pkgCache::Dep::Greater:
+	  return
+	    (t2 == pkgCache::Dep::Greater && cmpresult <= 0) ||
+	    (t2 == pkgCache::Dep::Equals && cmpresult < 0);
+	case pkgCache::Dep::Equals:
+	  return
+	    (t2 == pkgCache::Dep::Equals && cmpresult == 0);
+	case pkgCache::Dep::NotEquals:
+	  return
+	    (t2 == pkgCache::Dep::NotEquals && cmpresult == 0);
+
+	  // These shouldn't happen:
+	case pkgCache::Dep::NoOp:
+	default:
+	  abort();
+	}
+    }
+}
+
+/** \return \b true if the OR group of d1 subsumes the OR group of d2:
+ *  that is, if every member of the OR group containing d2 has a
+ *  subsuming element in the OR group containing d1.
+ */
+static bool or_group_subsumes(const pkgCache::DepIterator &d1,
+			      const pkgCache::DepIterator &d2)
+{
+  pkgCache::DepIterator start1, end1, start2, end2;
+
+  surrounding_or(d1, start1, end1);
+  surrounding_or(d2, start2, end2);
+
+  for(pkgCache::DepIterator i = d1; i != end1; ++i)
+    {
+      bool found = false;
+
+      for(pkgCache::DepIterator j = d2; j != end2; ++j)
+	if(subsumes(i, j))
+	  {
+	    found = true;
+	    break;
+	  }
+
+      if(!found)
+	return false;
+    }
+
+  return true;
+}
+
 // This should be a static member of the universe object, but it's
 // rather awkward to put it there right now.
+//
+// Interesting deps are:
+//
+//   - All critical deps
+//   - All recommendations that are currently satisfied
+//   - All recommendations that are unrelated under subsumption to
+//     each recommendation of the current package version.
 inline bool aptitude_universe::is_interesting_dep(const pkgCache::DepIterator &d)
 {
-  return const_cast<pkgCache::DepIterator &>(d).IsCritical() ||
-    d->Type == pkgCache::Dep::Recommends;
+  if(const_cast<pkgCache::DepIterator &>(d).IsCritical())
+    return true;
+  else if(d->Type != pkgCache::Dep::Recommends)
+    return false;
+  else
+    {
+      pkgCache::DepIterator dtmp = d;
+      while(!dtmp.end() && dtmp->CompareOp & pkgCache::Dep::Or)
+	++dtmp;
+      if((*apt_cache_file)[d] & pkgDepCache::DepGNow)
+	return true;
+
+      pkgCache::VerIterator currver = const_cast<pkgCache::DepIterator &>(d).ParentPkg().CurrentVer();
+      pkgCache::VerIterator parver = const_cast<pkgCache::DepIterator &>(d).ParentVer();
+
+      if(currver == parver)
+	return false;
+      else if(currver.end())
+	return true;
+      else
+	// Check whether the current version of this package has a dep
+	// that either subsumes _or is subsumed by_ this
+	// recommendation.  (for mathematical "correctness" we'd only
+	// check the first direction, but the goal is to not annoy the
+	// user unnecessarily; losing a few new recommendations is OK)
+	//
+	// NB: full correctness without annoyance means actually
+	// TRIMMING DOWN the target set of a recommendation by
+	// subtracting elements that are in the current version's
+	// recommendation list.  Needless to say, I'm ignoring this
+	// for now.
+	{
+	  pkgCache::DepIterator d2 = currver.DependsList();
+
+	  while(!d2.end())
+	    {
+	      if(d2->Type == pkgCache::Dep::Recommends &&
+		 or_group_subsumes(d2, d) || or_group_subsumes(d, d2))
+		return false;
+
+	      while(!d2.end() && ((d2->CompareOp & pkgCache::Dep::Or) != 0))
+		++d2;
+
+	      if(!d2.end())
+		++d2;
+	    }
+
+	  return true;
+	}
+    }
 }
 
 string aptitude_resolver_version::get_name() const



More information about the Aptitude-svn-commit mailing list