[Aptitude-svn-commit] r3671 - in branches/aptitude-0.3/aptitude: .
doc/en src src/generic
Daniel Burrows
dburrows at costa.debian.org
Mon Jul 25 17:37:27 UTC 2005
Author: dburrows
Date: Mon Jul 25 17:37:23 2005
New Revision: 3671
Added:
branches/aptitude-0.3/aptitude/src/generic/util.cc
branches/aptitude-0.3/aptitude/src/generic/util.h
Modified:
branches/aptitude-0.3/aptitude/ChangeLog
branches/aptitude-0.3/aptitude/doc/en/aptitude.xml
branches/aptitude-0.3/aptitude/src/generic/Makefile.am
branches/aptitude-0.3/aptitude/src/load_grouppolicy.cc
branches/aptitude-0.3/aptitude/src/pkg_grouppolicy.cc
branches/aptitude-0.3/aptitude/src/pkg_grouppolicy.h
Log:
Implement generic grouping policy magic (first cut).
Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog (original)
+++ branches/aptitude-0.3/aptitude/ChangeLog Mon Jul 25 17:37:23 2005
@@ -1,5 +1,11 @@
2005-07-25 Daniel Burrows <dburrows at debian.org>
+ * doc/en/aptitude.xml, src/load_grouppolicy.cc, src/pkg_grouppolicy.cc, src/pkg_grouppolicy.h, src/generic/Makefile.am, src/generic/util.cc, src/generic/util.h:
+
+ Add a "patterns" grouping policy and start a long-overdue
+ collection of generic utility routines to kill off some of my
+ duplication of code. (Closes: #156065)
+
* src/generic/matchers.cc:
Match anything with an empty pattern.
Modified: branches/aptitude-0.3/aptitude/doc/en/aptitude.xml
==============================================================================
--- branches/aptitude-0.3/aptitude/doc/en/aptitude.xml (original)
+++ branches/aptitude-0.3/aptitude/doc/en/aptitude.xml Mon Jul 25 17:37:23 2005
@@ -4295,6 +4295,42 @@
</varlistentry>
<varlistentry>
+ <term><synopsis>pattern(<replaceable>pattern</replaceable> <optional>=> <replaceable>title</replaceable></optional><optional>, ...</optional>)</synopsis></term>
+
+ <listitem>
+ <para>
+ A customizable grouping policy. Each version of
+ every package is matched against the given
+ <replaceable>pattern</replaceable>s. The first
+ match found is used to assign a
+ <replaceable>title</replaceable> to the package;
+ packages are then grouped by their
+ <replaceable>title</replaceable>. Strings of the
+ form <literal>\N</literal> that occur in
+ <replaceable>title</replaceable> will be replaced by
+ the Nth result of the match. If
+ <replaceable>title</replaceable> is not present, it
+ is assumed to be <literal>\1</literal>.
+ </para>
+
+ <para>
+ For instance, <literal>pattern(~m => \1)</literal>
+ will group packages according to their Maintainer
+ field. The policy <literal>pattern(~m)</literal>
+ will do the same thing, as the absent
+ <replaceable>title</replaceable> defaults to
+ <literal>\1</literal>.
+ </para>
+
+ <para>
+ See the section <xref linkend='secSearchPatterns'/>
+ for more information on the format of
+ <replaceable>pattern</replaceable>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><synopsis>priority</synopsis></term>
<listitem>
@@ -4305,7 +4341,7 @@
</varlistentry>
<varlistentry>
- <term><synopsis>section[(<replaceable>mode</replaceable>[,passthrough])]</synopsis></term>
+ <term><synopsis>section<optional>(<replaceable>mode</replaceable><optional>,passthrough</optional>)</optional></synopsis></term>
<listitem>
<para>
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 Mon Jul 25 17:37:23 2005
@@ -45,7 +45,9 @@
tasks.h \
tasks.cc \
undo.h \
- undo.cc
+ undo.cc \
+ util.h \
+ util.cc
pkg_hier_dump_SOURCES= \
pkg_hier_dump.cc
Added: branches/aptitude-0.3/aptitude/src/generic/util.cc
==============================================================================
--- (empty file)
+++ branches/aptitude-0.3/aptitude/src/generic/util.cc Mon Jul 25 17:37:23 2005
@@ -0,0 +1,41 @@
+// util.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 "util.h"
+
+#include <ctype.h>
+
+using namespace std;
+
+void stripws(string &s)
+{
+ size_t start = 0;
+ while(start < s.size() && isspace(s[start]))
+ ++start;
+
+ size_t end = s.size();
+ while(end > 0 && isspace(s[end-1]))
+ --end;
+
+ if(start >= end)
+ s.clear();
+ else
+ s.assign(s, start, end-start);
+}
+
Added: branches/aptitude-0.3/aptitude/src/generic/util.h
==============================================================================
--- (empty file)
+++ branches/aptitude-0.3/aptitude/src/generic/util.h Mon Jul 25 17:37:23 2005
@@ -0,0 +1,28 @@
+// Random utility functions that have nothing to do with apt. -*-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.
+
+#ifndef UTIL_H
+#define UTIL_H
+
+#include <string>
+
+// Strip whitespace from the beginning and end of a string.
+void stripws(std::string &s);
+
+#endif
Modified: branches/aptitude-0.3/aptitude/src/load_grouppolicy.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/load_grouppolicy.cc (original)
+++ branches/aptitude-0.3/aptitude/src/load_grouppolicy.cc Mon Jul 25 17:37:23 2005
@@ -9,11 +9,11 @@
// The parsers take an arglist and a chain argument, and return either a
// new pkg_grouppolicy_factory, or (if an error was encountered) NULL.
// (note: the chain argument will be NULL if the policy is the tail of a list)
-// Yes, I don't believe in C++ exceptions.
#include "load_grouppolicy.h"
#include <generic/pkg_hier.h>
+#include <generic/util.h>
#include "aptitude.h"
@@ -237,6 +237,86 @@
return new pkg_grouppolicy_task_factory(chain);
}
+static pkg_grouppolicy_factory *parse_matchers_policy(const arglist &args,
+ pkg_grouppolicy_factory *chain)
+{
+ if(args.size() == 0)
+ {
+ _error->Error(_("Match-based grouping policies require at least one parameter"));
+ return NULL;
+ }
+
+ vector<pkg_grouppolicy_matchers_factory :: match_pair> subgroups;
+
+ for(arglist::const_iterator i = args.begin();
+ i != args.end(); ++i)
+ {
+ // Split each argument at the first occurance of "=>".
+ string matcher, format="\\1";
+ bool in_matcher=true;
+
+ string::const_iterator j = i->begin();
+
+ while(j != i->end() && in_matcher)
+ {
+ while(j != i->end() && *j != '=')
+ {
+ matcher+=*j;
+ ++j;
+ }
+
+ if(j != i->end())
+ {
+ assert((*j) == '=');
+
+ ++j;
+
+ if(j == i->end() || *j != '>')
+ matcher += '=';
+ else
+ {
+ ++j;
+ in_matcher = false;
+ }
+ }
+ }
+
+ if(!in_matcher)
+ {
+ format.clear();
+
+ while(j != i->end())
+ {
+ format += *j;
+ ++j;
+ }
+ }
+
+ assert(j == i->end());
+
+ stripws(format);
+ stripws(matcher);
+
+ pkg_matcher *m = parse_pattern(matcher);
+
+ if(m == NULL)
+ {
+ for(vector<pkg_grouppolicy_matchers_factory :: match_pair> :: const_iterator i = subgroups.begin();
+ i != subgroups.end(); ++i)
+ delete i->matcher;
+
+ return NULL;
+ }
+
+ subgroups.push_back(pkg_grouppolicy_matchers_factory :: match_pair(m, transcode(format)));
+ }
+
+ if(!chain)
+ chain = new pkg_grouppolicy_end_factory;
+
+ return new pkg_grouppolicy_matchers_factory(chain, subgroups);
+}
+
static parser_map parse_types;
static void init_parse_types()
@@ -257,6 +337,8 @@
parse_types["hier"]=parse_hier_policy;
parse_types["task"]=parse_task_policy;
+ parse_types["pattern"]=parse_matchers_policy;
+
initted_parse_types=true;
}
}
@@ -307,8 +389,6 @@
}
parsed.push_back(current);
- // Ew, takes kinda long. Probably not an issue now, but creating current
- // as a new item in parsed would be faster.
if(i<s.size() && s[i]==',')
i++; // Clear out trailing commas.
Modified: branches/aptitude-0.3/aptitude/src/pkg_grouppolicy.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/pkg_grouppolicy.cc (original)
+++ branches/aptitude-0.3/aptitude/src/pkg_grouppolicy.cc Mon Jul 25 17:37:23 2005
@@ -28,6 +28,7 @@
#include <vscreen/transcode.h>
#include "generic/apt.h"
+#include "generic/matchers.h"
#include "generic/pkg_hier.h"
#include "generic/tasks.h"
@@ -999,3 +1000,170 @@
{
delete chain;
}
+
+
+class pkg_grouppolicy_matchers : public pkg_grouppolicy
+{
+public:
+ typedef pkg_grouppolicy_matchers_factory::match_pair match_pair;
+
+ struct subtree_pair
+ {
+ pkg_grouppolicy *policy;
+ pkg_subtree *tree;
+
+ subtree_pair():policy(NULL), tree(NULL)
+ {
+ }
+
+ subtree_pair(pkg_grouppolicy *_policy, pkg_subtree *_tree)
+ :policy(_policy), tree(_tree)
+ {
+ }
+ };
+private:
+ pkg_grouppolicy_factory *chain;
+ const vector<match_pair> &subgroups;
+ typedef map<wstring, subtree_pair> subtree_map;
+ subtree_map subtrees;
+
+ wstring substitute(const wstring &s,
+ pkg_match_result *res)
+ {
+ wstring rval;
+
+ wstring::const_iterator i = s.begin();
+ while(i != s.end())
+ {
+ while(i != s.end() && *i != L'\\')
+ {
+ rval += *i;
+ ++i;
+ }
+
+ if(i != s.end())
+ {
+ ++i;
+ if(i == s.end())
+ rval += L'\\';
+ else if(*i == L'\\')
+ {
+ rval += L'\\';
+ ++i;
+ }
+ else if(iswdigit(*i))
+ {
+ wstring tocvt;
+
+ while(i != s.end() && iswdigit(*i))
+ {
+ tocvt += *i;
+ ++i;
+ }
+
+ wchar_t *endptr = NULL;
+ unsigned long val = wcstoul(tocvt.c_str(), &endptr, 0);
+
+ if(endptr && (*endptr) != L'\0')
+ {
+ wchar_t buf[512];
+
+ swprintf(buf, 512, transcode(_("Bad number in format string: %ls")).c_str(),
+ tocvt.c_str());
+
+ return buf;
+ }
+
+ if(val < 1)
+ {
+ wchar_t buf[512];
+ swprintf(buf, 512, transcode(_("Match indices must be 1 or greater, not \"%s\"")).c_str(),
+ tocvt.c_str());
+ return buf;
+ }
+
+ --val;
+
+ if(val >= res->num_groups())
+ {
+ string group_values;
+ for(unsigned int i = 0; i<res->num_groups(); ++i)
+ {
+ if(i > 0)
+ group_values += ",";
+ group_values += res->group(i);
+ }
+
+ wchar_t buf[1024];
+ swprintf(buf, 1024, transcode(_("Match index %ls is too large; available groups are (%s)")).c_str(),
+ tocvt.c_str(), group_values.c_str());
+
+ return buf;
+ }
+
+ rval += transcode(res->group(val));
+ }
+ }
+ }
+
+ return rval;
+ }
+public:
+ pkg_grouppolicy_matchers(pkg_grouppolicy_factory *_chain,
+ pkg_signal *_sig, desc_signal *_desc_sig,
+ const vector<match_pair> &_subgroups)
+ :pkg_grouppolicy(_sig, _desc_sig),
+ chain(_chain), subgroups(_subgroups)
+ {
+ }
+
+ ~pkg_grouppolicy_matchers()
+ {
+ for(subtree_map::const_iterator i = subtrees.begin();
+ i != subtrees.end(); ++i)
+ delete i->second.policy;
+ }
+
+ void add_package(const pkgCache::PkgIterator &pkg,
+ pkg_subtree *root)
+ {
+ for(vector<match_pair>::const_iterator i = subgroups.begin();
+ i != subgroups.end(); ++i)
+ for(pkgCache::VerIterator ver = pkg.VersionList(); !ver.end();
+ ++ver)
+ {
+ pkg_match_result *res = i->matcher->get_match(pkg, ver);
+ if(res != NULL)
+ {
+ wstring title = substitute(i->tree_name, res);
+ delete res;
+
+ subtree_map::const_iterator found =
+ subtrees.find(title);
+
+ if(found != subtrees.end())
+ found->second.policy->add_package(pkg, found->second.tree);
+ else
+ {
+ pkg_subtree *tree = new pkg_subtree(title);
+ pkg_grouppolicy *policy = chain->instantiate(get_sig(),
+ get_desc_sig());
+ root->add_child(tree);
+
+ subtrees[title]=subtree_pair(policy, tree);
+ }
+ }
+ }
+ }
+};
+
+pkg_grouppolicy *pkg_grouppolicy_matchers_factory :: instantiate(pkg_signal *sig,
+ desc_signal *_desc_sig)
+{
+ return new pkg_grouppolicy_matchers(chain, sig, _desc_sig, subgroups);
+}
+
+pkg_grouppolicy_matchers_factory :: ~pkg_grouppolicy_matchers_factory()
+{
+ delete chain;
+}
Modified: branches/aptitude-0.3/aptitude/src/pkg_grouppolicy.h
==============================================================================
--- branches/aptitude-0.3/aptitude/src/pkg_grouppolicy.h (original)
+++ branches/aptitude-0.3/aptitude/src/pkg_grouppolicy.h Mon Jul 25 17:37:23 2005
@@ -50,6 +50,8 @@
#include <apt-pkg/pkgcache.h>
#include <sigc++/signal.h>
+#include <vector>
+
// Used to set the visible status if a package is available.
typedef sigc::signal2<void,
const pkgCache::PkgIterator &,
@@ -258,4 +260,40 @@
virtual ~pkg_grouppolicy_task_factory();
};
+class pkg_matcher;
+
+// Groups packages using the given list of matchers/tree names. Match
+// results can be substituted into tree names using \N notation.
+class pkg_grouppolicy_matchers_factory:public pkg_grouppolicy_factory
+{
+public:
+ struct match_pair
+ {
+ pkg_matcher *matcher;
+ std::wstring tree_name;
+
+ match_pair(pkg_matcher *_matcher, const std::wstring &_tree_name)
+ :matcher(_matcher), tree_name(_tree_name)
+ {
+ }
+ };
+
+private:
+ pkg_grouppolicy_factory *chain;
+
+ std::vector<match_pair> subgroups;
+public:
+
+ pkg_grouppolicy_matchers_factory(pkg_grouppolicy_factory *_chain,
+ const std::vector<match_pair> &_subgroups)
+ :chain(_chain), subgroups(_subgroups)
+ {
+ }
+
+ pkg_grouppolicy *instantiate(pkg_signal *sig,
+ desc_signal *_desc_sig);
+
+ ~pkg_grouppolicy_matchers_factory();
+};
+
#endif
More information about the Aptitude-svn-commit
mailing list