[Aptitude-devel] r3062 - in branches/aptitude-0.3/aptitude: . src

Daniel Burrows dburrows@costa.debian.org
Sat, 23 Apr 2005 02:04:20 +0000


Author: dburrows
Date: Sat Apr 23 02:04:17 2005
New Revision: 3062

Added:
   branches/aptitude-0.3/aptitude/src/solution_fragment.cc
   branches/aptitude-0.3/aptitude/src/solution_fragment.h
Modified:
   branches/aptitude-0.3/aptitude/ChangeLog
   branches/aptitude-0.3/aptitude/src/Makefile.am
   branches/aptitude-0.3/aptitude/src/ui.cc
Log:
Add basic support for displaying the current solution.

Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog	(original)
+++ branches/aptitude-0.3/aptitude/ChangeLog	Sat Apr 23 02:04:17 2005
@@ -1,5 +1,10 @@
 2005-04-22  Daniel Burrows  <dburrows@debian.org>
 
+	* src/solution_fragment.cc, src/solution_fragment.h, src/ui.cc:
+
+	  Add preliminary code to display a solution, and hook it up in
+	  the simplest possible way.
+
 	* src/broken_indicator.cc:
 
 	  Fix an assertion failure due to an incorrect assumption.

Modified: branches/aptitude-0.3/aptitude/src/Makefile.am
==============================================================================
--- branches/aptitude-0.3/aptitude/src/Makefile.am	(original)
+++ branches/aptitude-0.3/aptitude/src/Makefile.am	Sat Apr 23 02:04:17 2005
@@ -73,6 +73,8 @@
 	pkg_view.h	\
 	reason_fragment.cc\
 	reason_fragment.h\
+	solution_fragment.cc\
+	solution_fragment.h\
 	strhash.h	\
 	trust.h		\
 	trust.cc	\

Added: branches/aptitude-0.3/aptitude/src/solution_fragment.cc
==============================================================================
--- (empty file)
+++ branches/aptitude-0.3/aptitude/src/solution_fragment.cc	Sat Apr 23 02:04:17 2005
@@ -0,0 +1,206 @@
+// solution_fragment.cc
+//
+//
+//   Copyright (C) 2005 Daniel Burrows
+//
+//   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.
+//
+//   This program is distributed in the hope that it will be useful,
+//   but WITHOUT ANY WARRANTY; without even the implied warranty of
+//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//   General Public License for more details.
+//
+//   You should have received a copy of the GNU General Public License
+//   along with this program; see the file COPYING.  If not, write to
+//   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+//   Boston, MA 02111-1307, USA.
+
+#include "solution_fragment.h"
+
+#include <aptitude.h>
+
+#include <generic/aptitude_resolver.h>
+
+#include <vscreen/fragment.h>
+
+#include <vector>
+
+using namespace std;
+
+struct pkg_name_lt
+{
+public:
+  bool operator()(const pkgCache::PkgIterator &p1,
+		  const pkgCache::PkgIterator &p2) const
+  {
+    return strcmp(p1.Name(), p2.Name()) < 0;
+  }
+};
+
+struct ver_name_lt
+{
+public:
+  bool operator()(const pkgCache::VerIterator &v1,
+		  const pkgCache::VerIterator &v2) const
+  {
+    return strcmp(v1.ParentPkg().Name(), v2.ParentPkg().Name()) < 0;
+  }
+};
+
+/** \return a fragment listing the archives to which a version
+ *  belongs in the form "archive1,archive2,..."
+ */
+fragment *archives_fragment(const pkgCache::VerIterator &v)
+{
+  vector<fragment *> archive_fragments;
+
+  for(pkgCache::VerFileIterator vf=v.FileList(); !vf.end(); ++vf)
+    archive_fragments.push_back(text_fragment(vf.File().Archive()));
+
+  return join_fragments(archive_fragments, ",");
+}
+
+fragment *solution_fragment(const aptitude_resolver::solution &sol)
+{
+  // Bin packages according to what will happen to them.
+  vector<pkgCache::PkgIterator> remove_packages;
+  vector<pkgCache::VerIterator> keep_packages;
+  vector<pkgCache::VerIterator> install_packages;
+  vector<pkgCache::VerIterator> downgrade_packages;
+  vector<pkgCache::VerIterator> upgrade_packages;
+
+  sort(remove_packages.begin(), remove_packages.end(),
+       pkg_name_lt());
+
+  sort(keep_packages.begin(), keep_packages.end(),
+       ver_name_lt());
+  sort(install_packages.begin(), install_packages.end(),
+       ver_name_lt());
+  sort(downgrade_packages.begin(), downgrade_packages.end(),
+       ver_name_lt());
+  sort(upgrade_packages.begin(), upgrade_packages.end(),
+       ver_name_lt());
+
+  for(std::map<aptitude_resolver::package,
+	aptitude_resolver::action>::const_iterator i=sol.get_actions().begin();
+      i!=sol.get_actions().end(); ++i)
+    {
+      pkgCache::PkgIterator pkg=i->first.get_pkg();
+      pkgCache::VerIterator curver=pkg.CurrentVer();
+      pkgCache::VerIterator instver=(*apt_cache_file)[pkg].InstVerIter(*apt_cache_file);
+      pkgCache::VerIterator newver=i->second.ver.get_ver();
+
+      // If not, we have a problem.
+      assert(instver!=newver);
+
+      if(curver.end())
+	install_packages.push_back(newver);
+      else if(newver.end())
+	remove_packages.push_back(pkg);
+      else if(newver == curver)
+	keep_packages.push_back(curver);
+      else
+	{
+	  int cmp=_system->VS->CmpVersion(curver.VerStr(),
+					  newver.VerStr());
+
+	  // The versions shouldn't be equal -- otherwise
+	  // something is majorly wrong.
+	  // assert(cmp!=0);
+	  //
+	  // The above is not true: consider, eg, the case of a
+	  // locally compiled package and a standard package.
+
+	  /** \todo indicate "sidegrades" separately? */
+	  if(cmp<=0)
+	    upgrade_packages.push_back(newver);
+	  else if(cmp>0)
+	    downgrade_packages.push_back(newver);
+	}
+    }
+
+  vector<fragment *> fragments;
+  bool first=true;
+
+  if(!remove_packages.empty())
+    {
+      first=false;
+      fragments.push_back(fragf(_("%BRemove%b the following packages:%n")));
+      for(vector<pkgCache::PkgIterator>::const_iterator i=remove_packages.begin();
+	  i!=remove_packages.end(); ++i)
+	fragments.push_back(fragf("  %s%n", i->Name()));
+    }
+
+  if(!install_packages.empty())
+    {
+      if(!first)
+	fragments.push_back(newline_fragment());
+      else
+	first=false;
+
+      fragments.push_back(fragf(_("%BInstall%b the following packages:%n")));
+      for(vector<pkgCache::VerIterator>::const_iterator i=install_packages.begin();
+	  i!=install_packages.end(); ++i)
+	fragments.push_back(fragf(_("  %s [%s=%F]%n"),
+				  i->ParentPkg().Name(),
+				  i->VerStr(),
+				  archives_fragment(*i)));
+    }
+
+  if(!keep_packages.empty())
+    {
+      if(!first)
+	fragments.push_back(newline_fragment());
+      else
+	first=false;
+
+      fragments.push_back(fragf(_("%BKeep%b the following packages at their current version:")));
+      for(vector<pkgCache::VerIterator>::const_iterator i=keep_packages.begin();
+	  i!=keep_packages.end(); ++i)
+	fragments.push_back(fragf(_("  %s [%s=%F]%n"),
+				  i->ParentPkg().Name(),
+				  i->VerStr(),
+				  archives_fragment(*i)));
+    }
+
+  if(!upgrade_packages.empty())
+    {
+      if(!first)
+	fragments.push_back(newline_fragment());
+      else
+	first=false;
+
+      fragments.push_back(fragf(_("%BUpgrade%b the following packages:")));
+      for(vector<pkgCache::VerIterator>::const_iterator i=upgrade_packages.begin();
+	  i!=upgrade_packages.end(); ++i)
+	fragments.push_back(fragf(_("  %s [%s=%F -> %s=%F]%n"),
+				  i->ParentPkg().Name(),
+				  i->ParentPkg().CurrentVer().VerStr(),
+				  archives_fragment(i->ParentPkg().CurrentVer()),
+				  i->VerStr(),
+				  archives_fragment(*i)));
+    }
+
+  if(!downgrade_packages.empty())
+    {
+      if(!first)
+	fragments.push_back(newline_fragment());
+      else
+	first=false;
+
+      fragments.push_back(fragf(_("%BDowngrade%b the following packages:")));
+      for(vector<pkgCache::VerIterator>::const_iterator i=downgrade_packages.begin();
+	  i!=downgrade_packages.end(); ++i)
+	fragments.push_back(fragf(_("  %s [%s=%F -> %s=%F]%n"),
+				  i->ParentPkg().Name(),
+				  i->ParentPkg().CurrentVer().VerStr(),
+				  archives_fragment(i->ParentPkg().CurrentVer()),
+				  i->VerStr(),
+				  archives_fragment(*i)));
+    }
+
+  return flowbox(sequence_fragment(fragments));
+}

Added: branches/aptitude-0.3/aptitude/src/solution_fragment.h
==============================================================================
--- (empty file)
+++ branches/aptitude-0.3/aptitude/src/solution_fragment.h	Sat Apr 23 02:04:17 2005
@@ -0,0 +1,32 @@
+// solution_fragment.h            -*-c++-*-
+//
+//   Copyright (C) 2005 Daniel Burrows
+//
+//   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.
+//
+//   This program is distributed in the hope that it will be useful,
+//   but WITHOUT ANY WARRANTY; without even the implied warranty of
+//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//   General Public License for more details.
+//
+//   You should have received a copy of the GNU General Public License
+//   along with this program; see the file COPYING.  If not, write to
+//   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+//   Boston, MA 02111-1307, USA.
+//
+// Code to convert an aptitude resolver solution to a fragment.
+
+#ifndef SOLUTION_FRAGMENT_H
+#define SOLUTION_FRAGMENT_H
+
+class fragment;
+class aptitude_universe;
+template<class PackageUniverse>
+class generic_solution;
+
+fragment *solution_fragment(const generic_solution<aptitude_universe> &solution);
+
+#endif // SOLUTION_FRAGMENT_H

Modified: branches/aptitude-0.3/aptitude/src/ui.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/ui.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/ui.cc	Sat Apr 23 02:04:17 2005
@@ -49,6 +49,7 @@
 #include "load_config.h"
 #include "load_grouppolicy.h"
 #include "load_pkgview.h"
+#include "solution_fragment.h"
 
 #include <vscreen/curses++.h>
 #include <vscreen/fragment.h>
@@ -1228,7 +1229,27 @@
 
 static void do_examine_solution()
 {
-  show_message("This would be a truly fascinating and engaging dialog box...were it not for the fact that I have yet to write the code for it.  Please try again later.");
+  if(!apt_cache_file || !(*apt_cache_file)->resolver_exists())
+    return;
+  else
+    try
+      {
+	show_message(attr_fragment(solution_fragment((*apt_cache_file)->get_current_solution()),
+				   get_color("DefaultWidgetBackground")|A_REVERSE),
+		     NULL);
+      }
+    catch(NoMoreSolutions)
+      {
+	show_message(_("No solutions found."),
+		     NULL,
+		     get_color("Error"));
+      }
+    catch(NoMoreTime)
+      {
+	show_message(_("No solutions found before the time limit was exceeded."),
+		     NULL,
+		     get_color("Error"));
+      }
 }
 
 // NOTE ON TRANSLATIONS!