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

Daniel Burrows dburrows at costa.debian.org
Thu Jul 21 19:07:01 UTC 2005


Author: dburrows
Date: Thu Jul 21 19:06:56 2005
New Revision: 3659

Added:
   branches/aptitude-0.3/aptitude/src/generic/tags.cc
   branches/aptitude-0.3/aptitude/src/generic/tags.h
Modified:
   branches/aptitude-0.3/aptitude/ChangeLog
   branches/aptitude-0.3/aptitude/src/generic/Makefile.am
   branches/aptitude-0.3/aptitude/src/generic/apt.cc
Log:
Debtags implementation.

Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog	(original)
+++ branches/aptitude-0.3/aptitude/ChangeLog	Thu Jul 21 19:06:56 2005
@@ -1,5 +1,9 @@
 2005-07-21  Daniel Burrows  <dburrows at debian.org>
 
+	* src/generic/Makefile.am, src/generic/apt.cc, src/generic/tags.cc, src/generic/tags.h:
+
+	  Add backend support for parsing the new tag database.
+
 	* src/generic/tasks.cc, src/generic/apt.h:
 
 	  Lift the stuff to order versions by their file location

Modified: branches/aptitude-0.3/aptitude/src/generic/Makefile.am
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/Makefile.am	(original)
+++ branches/aptitude-0.3/aptitude/src/generic/Makefile.am	Thu Jul 21 19:06:56 2005
@@ -40,6 +40,8 @@
 	pkg_hier.cc	\
 	rev_dep_iterator.h \
 	strhash.h	\
+	tags.h		\
+	tags.cc		\
 	tasks.h		\
 	tasks.cc	\
 	undo.h		\

Modified: branches/aptitude-0.3/aptitude/src/generic/apt.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/apt.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/generic/apt.cc	Thu Jul 21 19:06:56 2005
@@ -26,6 +26,7 @@
 #include "config_signal.h"
 #include "pkg_hier.h"
 #include "rev_dep_iterator.h"
+#include "tags.h"
 #include "tasks.h"
 #include "undo.h"
 
@@ -249,6 +250,7 @@
   apt_undos->clear_items();
 
   load_tasks(*progress_bar);
+  load_tags(*progress_bar);
 
   if(user_pkg_hier)
     {

Added: branches/aptitude-0.3/aptitude/src/generic/tags.cc
==============================================================================
--- (empty file)
+++ branches/aptitude-0.3/aptitude/src/generic/tags.cc	Thu Jul 21 19:06:56 2005
@@ -0,0 +1,214 @@
+// tags.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 "tags.h"
+
+#include "../aptitude.h"
+
+#include "apt.h"
+
+#include <utility>
+
+#include <ctype.h>
+#include <string.h>
+
+#include <sigc++/functors/mem_fun.h>
+
+#include <apt-pkg/pkgrecords.h>
+#include <apt-pkg/tagfile.h>
+
+using namespace std;
+
+// NB: this does the wrong thing if spaces occur within a tag (they
+// generate a new hierarchy level), but such tags are invalid anyway.
+tag::const_iterator &tag::const_iterator::operator++()
+{
+  start = finish;
+  while(start != limit && (isspace(*start) || (*start)==':'))
+    ++start;
+
+  if(start == limit)
+    finish = limit;
+  else
+    {
+      finish = start+1;
+      while(finish != limit && !(isspace(*finish) || (*finish) == ':'))
+	++finish;
+    }
+
+  return *this;
+}
+
+tag::const_iterator tag::begin() const
+{
+  tag::const_iterator rval(start, start, finish);
+
+  ++rval;
+
+  return rval;
+}
+
+int tag::cmp(const tag &other) const
+{
+  const_iterator myT=begin(), otherT=other.begin();
+
+  while(myT != end() && otherT != other.end())
+    {
+      // avoid operator* and its concomitant copies
+      size_t myN=myT.finish-myT.start;
+      size_t otherN=otherT.finish-otherT.start;
+
+      int res = strncmp(myT.start, otherT.start, min(myN, otherN));
+
+      // If there was a difference, break out.
+      if(res != 0)
+	return res;
+      else if(myN<otherN)
+	return -1;
+      else if(myN>otherN)
+	return 1;
+
+      ++myT;
+      ++otherT;
+    }
+
+  if(otherT != end())
+    return -1;
+  else if(myT != end())
+    return 1;
+  else
+    return 0;
+}
+
+tag_list::const_iterator &tag_list::const_iterator::operator++()
+{
+  start = finish;
+
+  while(start != limit && (*start) != ',')
+    ++start;
+
+  if(start != limit) // Push past the comma.
+    ++start;
+
+  if(start == limit)
+    finish = limit;
+  else
+    {
+      // Eat everything up to the next comma.
+      finish = start+1;
+      while(finish != limit && (*finish) != ',')
+	++finish;
+    }
+
+  return *this;
+}
+
+tag_list::const_iterator tag_list::begin() const
+{
+  const_iterator rval(start, start, finish);
+  ++rval;
+  return rval;
+}
+
+typedef set<tag> db_entry;
+
+// The database is built eagerly, since the common use case is
+// to scan everything in sight right away and this makes it easy
+// to provide a progress bar to the user.
+db_entry *tagDB;
+
+static void insert_tags(const pkgCache::VerIterator &ver,
+			const pkgCache::VerFileIterator &vf)
+{
+  set<tag> *tags = tagDB + ver.ParentPkg()->ID;
+
+  const char *recstart=0, *recend=0;
+  const char *tagstart, *tagend;
+  pkgTagSection sec;
+
+  assert(apt_package_records);
+  assert(tagDB);
+
+  apt_package_records->Lookup(vf).GetRec(recstart, recend);
+  if(!recstart || !recend)
+    return;
+  if(!sec.Scan(recstart, recend-recstart))
+    return;
+
+  if(!sec.Find("Tag", tagstart, tagend))
+    return;
+
+  tag_list lst(tagstart, tagend);
+
+  for(tag_list::const_iterator t=lst.begin(); t!=lst.end(); ++t)
+    tags->insert(*t);
+}
+
+static void reset_tags()
+{
+  delete[] tagDB;
+  tagDB = NULL;
+}
+
+const set<tag> *get_tags(const pkgCache::PkgIterator &pkg)
+{
+  if(!apt_cache_file || !tagDB)
+    return NULL;
+
+  return tagDB + pkg->ID;
+}
+
+bool initialized_reset_signal;
+void load_tags(OpProgress &progress)
+{
+  assert(apt_cache_file && apt_package_records);
+
+  if(!initialized_reset_signal)
+    {
+      cache_closed.connect(sigc::ptr_fun(reset_tags));
+      cache_reload_failed.connect(sigc::ptr_fun(reset_tags));
+      initialized_reset_signal = true;
+    }
+
+  tagDB = new db_entry[(*apt_cache_file)->Head().PackageCount];
+
+  std::vector<loc_pair> verfiles;
+
+  for(pkgCache::PkgIterator p = (*apt_cache_file)->PkgBegin();
+      !p.end(); ++p)
+    for(pkgCache::VerIterator v = p.VersionList(); !v.end(); ++v)
+      for(pkgCache::VerFileIterator vf = v.FileList();
+	  !vf.end(); ++vf)
+	verfiles.push_back(loc_pair(v, vf));
+
+  sort(verfiles.begin(), verfiles.end(), location_compare());
+
+  progress.OverallProgress(0, verfiles.size(), 1,
+			   _("Building tag database"));
+  size_t n=0;
+  for(std::vector<loc_pair>::iterator i=verfiles.begin();
+      i!=verfiles.end(); ++i)
+    {
+      insert_tags(i->first, i->second);
+      ++n;
+      progress.OverallProgress(n, verfiles.size(), 1, _("Building tag database"));
+    }
+
+  progress.Done();
+}

Added: branches/aptitude-0.3/aptitude/src/generic/tags.h
==============================================================================
--- (empty file)
+++ branches/aptitude-0.3/aptitude/src/generic/tags.h	Thu Jul 21 19:06:56 2005
@@ -0,0 +1,191 @@
+// tags.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.
+//
+// A parser for tags.
+
+#ifndef TAGS_H
+#define TAGS_H
+
+#include <set>
+#include <string>
+
+#include <apt-pkg/pkgcache.h>
+
+class OpProgress;
+
+class tag
+{
+  const char *start, *finish;
+
+  int cmp(const tag &other) const;
+public:
+  class const_iterator
+  {
+    const char *start, *finish, *limit;
+
+    friend class tag;
+  public:
+    const_iterator(const char *_start, const char *_finish,
+		   const char *_limit)
+      :start(_start), finish(_finish), limit(_limit)
+    {
+    }
+
+    const_iterator &operator++();
+
+    const_iterator &operator=(const const_iterator &other)
+    {
+      start = other.start;
+      finish = other.finish;
+      limit = other.limit;
+
+      return *this;
+    }
+
+    bool operator==(const const_iterator &other) const
+    {
+      return start == other.start && finish == other.finish && limit == other.limit;
+    }
+
+    bool operator!=(const const_iterator &other) const
+    {
+      return start != other.start || finish != other.finish || limit != other.limit;
+    }
+
+    std::string operator*() const
+    {
+      return std::string(start, finish-start);
+    }
+  };
+
+  tag(const char *_start, const char *_finish)
+    :start(_start), finish(_finish)
+  {
+  }
+
+  tag &operator=(const tag &other)
+  {
+    start = other.start;
+    finish = other.finish;
+
+    return *this;
+  }
+
+  bool operator<(const tag &other) const
+  {
+    return cmp(other) < 0;
+  }
+
+  bool operator<=(const tag &other) const
+  {
+    return cmp(other) < 0;
+  }
+
+  bool operator==(const tag &other) const
+  {
+    return cmp(other) == 0;
+  }
+
+  bool operator!=(const tag &other) const
+  {
+    return cmp(other) != 0;
+  }
+
+  bool operator>(const tag &other) const
+  {
+    return cmp(other) == 0;
+  }
+
+  bool operator>=(const tag &other) const
+  {
+    return cmp(other) == 0;
+  }
+
+  const_iterator begin() const;
+  const_iterator end() const
+  {
+    return const_iterator(finish, finish, finish);
+  }
+};
+
+class tag_list
+{
+  const char *start, *finish;
+public:
+  class const_iterator
+  {
+    const char *start, *finish, *limit;
+  public:
+    const_iterator(const char *_start, const char *_finish,
+		   const char *_limit)
+      :start(_start), finish(_finish), limit(_limit)
+    {
+    }
+
+    const_iterator operator=(const const_iterator &other)
+    {
+      start = other.start;
+      finish = other.finish;
+      limit = other.limit;
+
+      return *this;
+    }
+
+    bool operator==(const const_iterator &other)
+    {
+      return other.start == start && other.finish == finish && other.limit == limit;
+    }
+
+    bool operator!=(const const_iterator &other)
+    {
+      return other.start != start || other.finish != finish || other.limit != limit;
+    }
+
+    const_iterator &operator++();
+
+    tag operator*()
+    {
+      return tag(start, finish);
+    }
+  };
+
+  tag_list(const char *_start, const char *_finish)
+    :start(_start), finish(_finish)
+  {
+  }
+
+  tag_list &operator=(const tag_list &other)
+  {
+    start = other.start;
+    finish = other.finish;
+
+    return *this;
+  }
+
+  const_iterator begin() const;
+  const_iterator end() const {return const_iterator(finish, finish, finish);}
+};
+
+// Grab the tags for the given package:
+const std::set<tag> *get_tags(const pkgCache::PkgIterator &pkg);
+
+// Load tags for all packages (call before get_tags)
+void load_tags(OpProgress &progress);
+
+#endif



More information about the Aptitude-svn-commit mailing list