Author: enrico
Date: 2007-06-20 11:18:50 +0000 (Wed, 20 Jun 2007)
New Revision: 3004

Added:
   software/ui/Makefile.am
   software/ui/configure.ac
   software/ui/src/
   software/ui/src/Environment.cc
   software/ui/src/Environment.h
   software/ui/src/Environment.tcc
   software/ui/src/GamessOptions.h
   software/ui/src/Makefile.am
   software/ui/src/games.cc
   software/ui/src/manpage.cc
Log:
initial structure

Added: software/ui/Makefile.am
===================================================================
--- software/ui/Makefile.am                             (rev 0)
+++ software/ui/Makefile.am     2007-06-20 11:18:50 UTC (rev 3004)
@@ -0,0 +1,10 @@
+## Process this file with automake to produce Makefile.in
+
+SUBDIRS = src .
+
+man_MANS = games.1
+
+games.1: src/manpage
+       tools/manpage gamse > $@ || rm $@
+
+EXTRA_DIST = $(man_MANS)

Added: software/ui/configure.ac
===================================================================
--- software/ui/configure.ac                            (rev 0)
+++ software/ui/configure.ac    2007-06-20 11:18:50 UTC (rev 3004)
@@ -0,0 +1,36 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(games, 0.1, [EMAIL PROTECTED],[EMAIL PROTECTED])
+AC_CONFIG_SRCDIR([configure.ac])
+AM_CONFIG_HEADER(config.h)
+AM_INIT_AUTOMAKE([foreign])
+
+dnl To use subdirs
+AC_PROG_MAKE_SET
+
+AC_LANG(C++)
+
+AC_GNU_SOURCE
+dnl AC_ISC_POSIX
+AC_PROG_CXX()
+AC_PROG_CXXCPP
+AM_PROG_CC_STDC
+AC_HEADER_STDC
+
+dnl Use libtool
+AM_PROG_LIBTOOL
+
+dnl Use wibble, tagcoll2 and pkg
+LIBWIBBLE_DEFS
+LIBTAGCOLL2_DEFS
+LIBEPT_DEFS
+
+dnl Look for apt-get
+AC_PATH_PROG(APTGET, apt-get, /usr/bin/apt-get)
+AC_SUBST(APTGET)
+AC_DEFINE_UNQUOTED(APTGET, "$APTGET", [Location of apt-get program])
+
+AC_CONFIG_FILES([
+Makefile
+src/Makefile
+])
+AC_OUTPUT

Added: software/ui/src/Environment.cc
===================================================================
--- software/ui/src/Environment.cc                              (rev 0)
+++ software/ui/src/Environment.cc      2007-06-20 11:18:50 UTC (rev 3004)
@@ -0,0 +1,115 @@
+/*
+ * Common environment for many program parts
+ *
+ * Copyright (C) 2003--2007  Enrico Zini <[EMAIL PROTECTED]>
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "Environment.h"
+
+#include <ept/apt/apt.h>
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>    // isatty
+
+#include <cstdlib>
+
+using namespace std;
+
+static Environment* instance = 0;
+
+Environment& Environment::get() throw ()
+{
+       if (instance == 0)
+               instance = new Environment;
+
+       return *instance;
+}
+
+// Initialize the environment with default values
+Environment::Environment() throw ()
+       : m_apt(0), m_debtags(0), _verbose(false), _debug(false) {}
+
+void Environment::init(bool editable)
+{
+       m_apt = new ept::apt::Apt;
+       m_debtags = new ept::debtags::Debtags(editable);
+}
+
+void fatal_error(const char* fmt, ...) throw() ATTR_PRINTF(1, 2)
+{
+       fprintf(stderr, "debtags: ");
+       va_list ap;
+       va_start(ap, fmt);
+       vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       fprintf(stderr, "\n");
+       exit(1);
+}
+
+void error(const char* fmt, ...) throw() ATTR_PRINTF(1, 2)
+{
+       va_list ap;
+       va_start(ap, fmt);
+       vfprintf(stderr, fmt, ap);
+       va_end(ap);
+}
+
+void warning(const char* fmt, ...) throw() ATTR_PRINTF(1, 2)
+{
+       va_list ap;
+       va_start(ap, fmt);
+       vfprintf(stderr, fmt, ap);
+       va_end(ap);
+}
+
+void verbose(const char* fmt, ...) throw() ATTR_PRINTF(1, 2)
+{
+       if (Environment::get().verbose())
+       {
+               va_list ap;
+               va_start(ap, fmt);
+               vfprintf(stderr, fmt, ap);
+               va_end(ap);
+       }
+}
+
+void debug(const char* fmt, ...) throw() ATTR_PRINTF(1, 2)
+{
+       if (Environment::get().debug())
+       {
+               va_list ap;
+               va_start(ap, fmt);
+               vfprintf(stderr, fmt, ap);
+               va_end(ap);
+       }
+}
+
+void feedback(const char* fmt, ...) throw() ATTR_PRINTF(1, 2)
+{
+       if (isatty(1))
+       {
+               va_list ap;
+               va_start(ap, fmt);
+               vfprintf(stdout, fmt, ap);
+               va_end(ap);
+       }
+}
+
+
+
+// vim:set ts=4 sw=4:

Added: software/ui/src/Environment.h
===================================================================
--- software/ui/src/Environment.h                               (rev 0)
+++ software/ui/src/Environment.h       2007-06-20 11:18:50 UTC (rev 3004)
@@ -0,0 +1,104 @@
+#ifndef DEBTAGS_ENVIRONMENT_H
+#define DEBTAGS_ENVIRONMENT_H
+
+/*
+ * Common environment for many program parts
+ *
+ * Copyright (C) 2003--2007  Enrico Zini <[EMAIL PROTECTED]>
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <ept/debtags/debtags.h>
+#include <string>
+
+namespace ept {
+namespace apt {
+class Apt;
+}
+}
+
+class Environment
+{
+protected:
+       /// Apt data provider
+       ept::apt::Apt* m_apt;
+
+       /// Debtags data provider
+       ept::debtags::Debtags* m_debtags;
+
+       // True when operations should be verbose
+       bool _verbose;
+
+       // True when operations should be very verbose
+       bool _debug;
+
+       Environment() throw ();
+               
+public:
+       static Environment& get() throw ();
+
+       /**
+        * Initialise the data providers.
+        *
+        * This method must be called before they can be accessed.
+        */
+       void init(bool editable = false);
+
+       /// Access the apt data provider
+       ept::apt::Apt& apt() { return *m_apt; }
+
+       /// Access the debtags data provider
+       ept::debtags::Debtags& debtags() { return *m_debtags; }
+
+       /// Access the tag vocabulary
+       ept::debtags::Vocabulary& voc() { return m_debtags->vocabulary(); }
+
+       // Accessor methods
+
+       bool verbose() const throw () { return _verbose; }
+       bool verbose(bool verbose) throw () { return _verbose = verbose; }
+
+       bool debug() const throw () { return _debug; }
+       bool debug(bool debug) throw ()
+       {
+               // Debug implies verbose
+               if (debug)
+                       _verbose = true;
+               return _debug = debug;
+       }
+};
+
+// Commodity output functions
+
+#ifndef ATTR_PRINTF
+ #ifdef GCC
+  #define ATTR_PRINTF(string, first) __attribute__((format (printf, string, 
first)))
+ #else
+  #define ATTR_PRINTF(string, first)
+ #endif
+#endif
+
+void fatal_error(const char* fmt, ...) throw() ATTR_PRINTF(1, 2);
+void error(const char* fmt, ...) throw() ATTR_PRINTF(1, 2);
+void warning(const char* fmt, ...) throw() ATTR_PRINTF(1, 2);
+void verbose(const char* fmt, ...) throw() ATTR_PRINTF(1, 2);
+void debug(const char* fmt, ...) throw() ATTR_PRINTF(1, 2);
+void feedback(const char* fmt, ...) throw() ATTR_PRINTF(1, 2);
+
+static inline Environment& env() { return Environment::get(); }
+
+// vim:set ts=4 sw=4:
+#endif

Added: software/ui/src/Environment.tcc
===================================================================
--- software/ui/src/Environment.tcc                             (rev 0)
+++ software/ui/src/Environment.tcc     2007-06-20 11:18:50 UTC (rev 3004)
@@ -0,0 +1,67 @@
+/*
+ * debtags - Implement package tags support for Debian
+ *
+ * Copyright (C) 2003--2007  Enrico Zini <[EMAIL PROTECTED]>
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef DEBTAGS_ENVIRONMENT_TCC
+#define DEBTAGS_ENVIRONMENT_TCC
+
+#include "Environment.h"
+
+#include <pkg/debtags/maint/serializer.h>
+
+#include <tagcoll/input/stdio.h>
+#include <tagcoll/TextFormat.h>
+
+
+template<typename OUT>
+void Environment::readCollection(const string& file, const OUT& out)
+{
+       if (file == "-")
+       {
+               input::Stdio input(stdin, "<stdin>");
+               textformat::parse(input,
+                               pkg::debtags::stringToInt(pkgid, voc(),
+                                       pkg::debtags::intToPkg(pkgid, voc(), 
out)));
+       }
+       else
+       {
+               input::Stdio input(file);
+               textformat::parse(input,
+                               pkg::debtags::stringToInt(pkgid, voc(),
+                                       pkg::debtags::intToPkg(pkgid, voc(), 
out)));
+       }
+}
+
+template<typename OUT>
+void Environment::readCollectionRaw(const string& file, const OUT& out)
+{
+       if (file == "-")
+       {
+               input::Stdio input(stdin, "<stdin>");
+               textformat::parse(input, out);
+       }
+       else
+       {
+               input::Stdio input(file);
+               textformat::parse(input, out);
+       }
+}
+
+#endif
+// vim:set ts=4 sw=4:

Added: software/ui/src/GamessOptions.h
===================================================================
--- software/ui/src/GamessOptions.h                             (rev 0)
+++ software/ui/src/GamessOptions.h     2007-06-20 11:18:50 UTC (rev 3004)
@@ -0,0 +1,243 @@
+#ifndef DEBTAGS_OPTIONS_H
+#define DEBTAGS_OPTIONS_H
+
+/*
+ * Commandline parser for tagcoll
+ *
+ * Copyright (C) 2003,2004,2005,2006  Enrico Zini
+ * 
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <wibble/commandline/parser.h>
+
+namespace wibble {
+namespace commandline {
+
+struct DebtagsOptions : public StandardParserWithMandatoryCommand
+{
+public:
+       BoolOption* out_quiet;
+       BoolOption* out_verbose;
+
+       BoolOption* out_names;
+       BoolOption* out_debug;
+       BoolOption* out_facets;
+       BoolOption* out_short;
+       BoolOption* out_full;
+
+       BoolOption* match_invert;
+
+       BoolOption* misc_local;
+       BoolOption* misc_reindex;
+       IntOption* misc_distance;
+       StringOption* misc_vocfile;
+
+       BoolOption* smse_reltags;
+       BoolOption* smse_disctags;
+
+       Engine* update;
+       Engine* selfcheck;
+       Engine* check;
+       Engine* tagcat;
+       Engine* tagshow;
+       Engine* tagsearch;
+       Engine* show;
+       Engine* related;
+       Engine* cat;
+       Engine* dumpavail;
+       Engine* search;
+       Engine* grep;
+       Engine* install;
+       Engine* diff;
+       Engine* maintainers;
+       Engine* tag;
+       Engine* submit;
+       Engine* todo;
+       Engine* score;
+       Engine* stats;
+       Engine* todoreport;
+       Engine* smartsearch;
+       Engine* vocfilter;
+
+       DebtagsOptions() 
+               : StandardParserWithMandatoryCommand("debtags", VERSION, 1, 
"[EMAIL PROTECTED]")
+       {
+               usage = "<command> [options and arguments]";
+               description = "Commandline interface to access and manipulate 
Debian Package Tags";
+
+               out_verbose = add<BoolOption>("verbose", 'v', "verbose", "",
+                                               "enable verbose output");
+               out_debug = add<BoolOption>("debug", 0, "debug", "",
+                                               "enable debugging output 
(including verbose output)");
+
+               // Create the collection output group
+               OptionGroup* collOutputOpts = createGroup("Options controlling 
transformations of tag data on output");
+               out_names = collOutputOpts->add<BoolOption>("names", 0, 
"names", "",
+                                               "output only the names of the 
packages");
+               out_quiet = collOutputOpts->add<BoolOption>("quiet", 'q', 
"quiet", "",
+                                               "do not write anything to 
standard output");
+               out_facets = collOutputOpts->add<BoolOption>("facets", 0, 
"facets", "",
+                                               "output only the names of the 
facets (mainly used for computing statistics)");
+
+               // Create the package output group
+               OptionGroup* pkgOutputOpts = createGroup("Options controlling 
transformations of package data on output");
+               pkgOutputOpts->add(out_names);
+               pkgOutputOpts->add(out_quiet);
+               out_short = pkgOutputOpts->add<BoolOption>("short", 0, "short", 
"",
+                                               "output the names of the 
packages, plus a short description");
+               out_full = pkgOutputOpts->add<BoolOption>("full", 0, "full", "",
+                                               "output the full record of 
package data");
+
+               // Create the matching options group
+               OptionGroup* matchOpts = createGroup("Options controlling 
matching of packages");
+               match_invert = matchOpts->add<BoolOption>("invert", 'i', 
"invert", "",
+                               "invert the match, selecting non-matching 
items");
+
+               update = addEngine("update", "",
+                       "updates the package tag database (requires root)",
+                       "Collect package tag data from the sources listed in "
+                       "/etc/debtags/sources.list, then regenerate the debtags 
"
+                       "tag database and main index.\n"
+                       "It needs to be run as root");
+               misc_local = update->add<BoolOption>("local", 0, "local", "",
+                       "do not download files when performing an update");
+               misc_reindex = update->add<BoolOption>("reindex", 0, "reindex", 
"",
+                       "do not download any file, just do reindexing if 
needed");
+
+               selfcheck = addEngine("selfcheck", "",
+                       "perform a series of internal self checks using the 
current tag data");
+
+               check = addEngine("check", "<file>", 
+                       "check that all the tags in the given tagged collection 
are present "
+                       "in the tag vocabulary.  Checks the main database if no 
file is "
+                       "specified");
+
+               tagcat = addEngine("tagcat", "", "output the tag vocabulary");
+
+               tagshow = addEngine("tagshow", "", 
+                       "show the vocabulary informations about a tag");
+
+               tagsearch = addEngine("tagsearch", "<string [string [string 
...]]>",
+                       "show a summary of all tags whose data contains the 
given strings");
+
+               show = addEngine("show", "<pkg>",
+                       "show informations about a package, like apt-cache show 
does, but "
+                       "adding the tag informations from the debtags index");
+
+               related = addEngine("related", "<pkg1[,pkg2[,pkg3...]]>",
+                       "show packages related to the given one(s)",
+                       "Output a list of the packages that are related to the 
given package or list of packages.  "
+                       "If more than one package are to be specified, separate 
them with commas.\n"
+                       "The --distance option can be used to control how 
closely related the output "
+                       "packages should be from the package(s) specified.");
+               related->examples = "debtags related mutt,mozilla-browser";
+               misc_distance = related->add<IntOption>("distance", 'd', 
"distance", "distance",
+                       "set the maximum distance to use for the \"related\" 
command (defaults to 0)");
+                       
+               cat = addEngine("cat", "", "output the full package tag 
database");
+               cat->add(matchOpts);
+               cat->add(collOutputOpts);
+
+               dumpavail = addEngine("dumpavail", "[tag expression]",
+                       "output the full package database");
+               dumpavail->add(matchOpts);
+               dumpavail->add(pkgOutputOpts);
+
+               search = addEngine("search", "<tag expression>",
+                       "output the names and descriptions of the packages that 
match"
+                       " the given tag expression");
+               search->add(matchOpts);
+               search->add(pkgOutputOpts);
+
+               grep = addEngine("grep", "<tag expression>",
+                       "output the lines of the full package tag database that 
match"
+                       " the given tag expression");
+               grep->add(matchOpts);
+               grep->add(collOutputOpts);
+
+               install = addEngine("install", "<tag expression>",
+                       "apt-get install the packages that match the given tag 
expression",
+                       "Invokes apt-get install with the names of the packages 
matched "
+                       "by the given tag expression.  If you want to see what 
packages "
+                       "would be installed you can use debtags search, as "
+                       "debtags install just calls apt-get install on all "
+                       "the results of an equivalent debtags search.  Please 
note "
+                       "that debtags install is just a prototype feature 
useful "
+                       "for experimenting in some environments like Custom 
Debian "
+                       "Distributions.  For this reason it is suggested that 
you "
+                       "use debtags just as a way to find packages, and "
+                       "proper package managers as the way to install them");
+               install->add(matchOpts);
+
+               diff = addEngine("diff", "[filename]",
+                       "create a tag patch between the current tag database 
and the tag"
+                       "collection [filename].  Standard input is used if 
filename is not specified");
+               diff->aliases.push_back("mkpatch");
+
+               maintainers = addEngine("maintainers", "", 
+                       "create a tagged collection of maintainers and the tags 
of the"
+                       "packages they maintain");
+               maintainers->add(collOutputOpts);
+
+               tag = addEngine("tag", "{add|rm|ls} <package> [tags...]",
+                       "view and edit the tags for a package",
+                       "General manipulation of tags, useful for automation in 
scripts.\n"
+                       "It can be used in three ways:\n"
+                       "tag add <package> <tags...> will add the tags to the 
given package\n"
+                       "tag rm <package> <tags...> will remove the tags from 
the given package\n"
+                       "tag ls <package> will output the names of the tags of 
the given package");
+
+               submit = addEngine("submit", "[patch]",
+                       "mail the given patch file to the central tag 
repository."
+                       "If [patch] is omitted, mail the local tag 
modifications.");
+
+               todo = addEngine("todo", "", 
+                       "print a list of the installed packages that are not 
yet tagged");
+               todo->add(pkgOutputOpts);
+
+               score = addEngine("score", "", 
+                       "score uninstalled packages according to how often 
their tags "
+                       "appear in the packages that are installed already");
+
+               stats = addEngine("stats", "",
+                       "print statistics about Debtags");
+
+               todoreport = addEngine("todoreport", "", 
+                       "print a report of packages needing work");
+
+               smartsearch = addEngine("smartsearch", "<word [word1 [+tag 
[-tag1 ...]]]>",
+                       "Perform a keyword search integrated with related 
packages.\n"
+                       "A + prefix indicates a wanted tag.  A - prefix 
indicates "
+                       "an unwanted tag.  Other words indicate keywords to 
search.\n"
+                       "Remember to use '--' before unwanted tags to avoid to 
have "
+                       "them interpreted as commandline switches.\n");
+               smse_reltags = smartsearch->add<BoolOption>("relevant", 0, 
"relevant", "",
+                       "only print the tag names sorted by increasing 
relevance");
+               smse_disctags = smartsearch->add<BoolOption>("discriminant", 0, 
"discriminant", "",
+                       "only print the tag names sorted by increasing 
discriminance");
+
+               vocfilter = addEngine("vocfilter", "tagfile", 
+                       "filter out the tags that are not found in the given 
vocabulary file");
+               misc_vocfile = vocfilter->add<StringOption>("vocabulary", 0, 
"vocabulary", "file",
+                       "vocabulary file to use instead of the current debtags 
vocabulary");
+       }
+};
+
+}
+}
+
+// vim:set ts=4 sw=4:
+#endif

Added: software/ui/src/Makefile.am
===================================================================
--- software/ui/src/Makefile.am                         (rev 0)
+++ software/ui/src/Makefile.am 2007-06-20 11:18:50 UTC (rev 3004)
@@ -0,0 +1,16 @@
+## Process this file with automake to produce Makefile.in
+
+bin_PROGRAMS = games
+noinst_PROGRAMS = manpage
+
+games_SOURCES = \
+       Environment.cc \
+       games.cc
+games_LDADD = $(LIBEPT_LIBS)
+
+manpage_SOURCES = manpage.cc
+manpage_LDADD = $(LIBEPT_LIBS)
+
+INCLUDES = -I.. $(LIBEPT_CFLAGS)
+
+EXTRA_DIST = GamesOptions.h Environment.h

Added: software/ui/src/games.cc
===================================================================
--- software/ui/src/games.cc                            (rev 0)
+++ software/ui/src/games.cc    2007-06-20 11:18:50 UTC (rev 3004)
@@ -0,0 +1,821 @@
+/*
+ * debtags - Implement package tags support for Debian
+ *
+ * Copyright (C) 2003--2006  Enrico Zini <[EMAIL PROTECTED]>
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#define APPNAME PACKAGE_NAME
+#else
+#warning No config.h found: using fallback values
+#define APPNAME __FILE__
+#define PACKAGE_VERSION "unknown"
+#endif
+
+#include <tagcoll/input/stdio.h>
+#include <tagcoll/stream/filters.h>
+#include <tagcoll/expression.h>
+#include <tagcoll/TextFormat.h>
+#include <tagcoll/SmartHierarchy.h>
+#include <tagcoll/coll/simple.h>
+#include <tagcoll/utils/set.h>
+//#include <tagcoll/experiments.h>
+
+#include "Environment.h"
+#include "DebtagsOptions.h"
+#include "Printer.h"
+#include "nullstream.h"
+//#include "Ept.h"
+#include "SmartSearcher.h"
+
+#include <ept/apt/packagerecord.h>
+#include <ept/debtags/expression.h>
+#include <ept/debtags/maint/vocabularymerger.h>
+#include <ept/debtags/maint/path.h>
+#include <ept/debtags/maint/vocabularyindexer.h>
+#include <ept/debtags/maint/debtagsindexer.h>
+#if 0
+#include <ept/cache/debtags/update.h>
+//#include <apt-pkg/configuration.h>
+#endif
+
+#include <wibble/sys/fs.h>
+
+#include <errno.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/types.h> // umask
+#include <sys/stat.h>  // umask
+
+namespace std {
+
+template<typename TAG, typename _Traits>
+basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>& out, 
const std::set<TAG>& tags)
+{
+       for (typename std::set<TAG>::const_iterator i = tags.begin();
+                       i != tags.end(); i++)
+               if (i == tags.begin())
+                       out << i->fullname();
+               else
+                       out << ", " << i->fullname();
+       return out;
+}
+
+template<typename TAG, typename _Traits>
+basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>& out, 
const wibble::Singleton<TAG>& tags)
+{
+       out << *tags.begin();
+       return out;
+}
+
+template<typename TAG, typename _Traits>
+basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>& out, 
const wibble::Empty<TAG>&)
+{
+       return out;
+}
+
+}
+
+using namespace std;
+using namespace ept;
+using namespace ept::debtags;
+using namespace ept::apt;
+using namespace ept::textsearch;
+
+int main(int argc, const char* argv[])
+{
+       wibble::commandline::DebtagsOptions opts;
+
+       try {
+               // Install the handler for unexpected exceptions
+               wibble::exception::InstallUnexpected installUnexpected;
+
+               if (opts.parse(argc, argv))
+                       return 0;
+
+               if (opts.out_verbose->boolValue())
+                       ::Environment::get().verbose(true);
+
+               if (opts.out_debug->boolValue())
+                       ::Environment::get().debug(true);
+
+               if (opts.foundCommand() == opts.selfcheck)
+               {
+                       env().init();
+                       Vocabulary& voc = env().voc();
+                       Apt& apt = env().apt();
+
+                       // ensure that all facets are readable
+                       std::set<Facet> facets = voc.facets();
+                       for (std::set<Facet>::const_iterator i = 
facets.begin(); i != facets.end(); i++)
+                       {
+                               cout << "Checking facet " << 
i->name(string("<invalid name>")) << "..." << endl;
+                               i->name(string("foo"));
+                               i->shortDescription(string("foo"));
+                               i->longDescription(string("foo"));
+                               i->tags();
+                       }
+
+                       // ensure that all tags are readable
+                       std::set<Tag> tags = voc.tags();
+                       for (std::set<Tag>::const_iterator i = tags.begin(); i 
!= tags.end(); i++)
+                       {
+                               cout << "Checking tag " << 
i->fullname(string("<invalid name>")) << "..." << endl;
+                               i->name(string("foo"));
+                               i->fullname(string("foo"));
+                               i->shortDescription(string("foo"));
+                               i->longDescription(string("foo"));
+                       }
+
+                       // ensure that all packages that declare they are 
readable, are readable
+                       for (Apt::iterator i = apt.begin(); i != apt.end(); ++i)
+                       {
+                               cout << "Checking package " << *i << "..." << 
endl;
+                               //if (i->isValid())
+                               //{
+                               //      i->shortDescription(string("foo"));
+                               //      i->longDescription(string("foo"));
+                               //      //i->tags(std::set<Tag>());
+                               //}
+                       }
+                       
+                       for (std::set<Facet>::const_iterator i = facets.begin();
+                                       i != facets.end(); i++)
+                       {
+                               if (!voc.hasFacet(i->name()))
+                                       cerr << "Vocabulary is not sure about 
having facet " << i->name() << endl;
+
+                               std::set<Tag> tags = i->tags();
+                               for (std::set<Tag>::const_iterator j = 
tags.begin();
+                                               j != tags.end(); j++)
+                                       if (!voc.hasTag(j->fullname()))
+                                               cerr << "Vocabulary is not sure 
about having tag " << j->fullname() << endl;
+                       }
+                       return 0;
+               }
+               // Output the full package tag database
+               else if (opts.foundCommand() == opts.cat)
+               {
+                       env().init();
+                       Debtags& debtags = env().debtags();
+                       int count = 0;
+
+                       auto_ptr<CollPrinter> printer;
+
+                       if (opts.out_names->boolValue())
+                               printer.reset(new 
CollPrinter(CollPrinter::NAME, count));
+                       else if (opts.out_facets->boolValue())
+                               printer.reset(new 
CollPrinter(CollPrinter::FACETS, count));
+                       else if (opts.out_quiet->boolValue())
+                               printer.reset(new 
CollPrinter(CollPrinter::QUIET, count));
+                       else 
+                               printer.reset(new 
CollPrinter(CollPrinter::TAGS, count));
+
+                       if (opts.hasNext())
+                       {
+                               debtags.output(expressionFilter(opts.next(), 
opts.match_invert->boolValue(), *printer));
+                       } else
+                               debtags.output(*printer);
+
+                       return count > 0 ? 0 : 1;
+               }
+               // Output the full package database
+               else if (opts.foundCommand() == opts.dumpavail)
+               {
+                       env().init();
+                       int count = 0;
+
+                       auto_ptr<PackagePrinter> printer;
+                       if (opts.out_names->boolValue())
+                               printer.reset(new 
PackagePrinter(PackagePrinter::NAME, count));
+                       else if (opts.out_short->boolValue())
+                               printer.reset(new 
PackagePrinter(PackagePrinter::SHORT, count));
+                       else if (opts.out_quiet->boolValue())
+                               printer.reset(new 
PackagePrinter(PackagePrinter::QUIET, count));
+                       else 
+                               printer.reset(new 
PackagePrinter(PackagePrinter::FULL, count));
+
+                       if (opts.hasNext())
+                       {
+                               
env().debtags().output(expressionFilter(opts.next(), 
opts.match_invert->boolValue(), *printer));
+                       } else {
+                               // If there is no expression filter, dump from 
the Apt database
+                               Apt& apt = env().apt();
+                               PackageRecord record;
+                               for (Apt::record_iterator i = apt.recordBegin();
+                                               i != apt.recordEnd(); ++i)
+                               {
+                                       record.scan(*i);
+                                       *printer = record;
+                               }
+                       }
+
+                       return count > 0 ? 0 : 1;
+               }
+               // search [-v] <tag expression>\n"
+               // Output the names and description of the packages that 
match\n"
+               // the given tag expression\n"
+               else if (opts.foundCommand() == opts.search)
+               {
+                       env().init();
+                       // TODO: complain if no expression found
+                       int count = 0;
+
+                       auto_ptr<PackagePrinter> printer;
+                       if (opts.out_names->boolValue())
+                               printer.reset(new 
PackagePrinter(PackagePrinter::NAME, count));
+                       else if (opts.out_full->boolValue())
+                               printer.reset(new 
PackagePrinter(PackagePrinter::FULL, count));
+                       else if (opts.out_quiet->boolValue())
+                               printer.reset(new 
PackagePrinter(PackagePrinter::QUIET, count));
+                       else 
+                               printer.reset(new 
PackagePrinter(PackagePrinter::SHORT, count));
+
+                       if (opts.hasNext())
+                       {
+                               
env().debtags().output(expressionFilter(opts.next(), 
opts.match_invert->boolValue(), *printer));
+                       } else
+                               env().debtags().output(*printer);
+
+                       return count > 0 ? 0 : 1;
+               }
+               // grep [-v] [-q] <tag expression>
+               // Output the lines of the full package tag database that match 
the
+               // given tag expression
+               else if (opts.foundCommand() == opts.grep)
+               {
+                       env().init();
+                       // TODO: complain if no expression found
+                       Debtags& debtags = env().debtags();
+                       int count = 0;
+
+                       auto_ptr<CollPrinter> printer;
+
+                       if (opts.out_names->boolValue())
+                               printer.reset(new 
CollPrinter(CollPrinter::NAME, count));
+                       else if (opts.out_facets->boolValue())
+                               printer.reset(new 
CollPrinter(CollPrinter::FACETS, count));
+                       else if (opts.out_quiet->boolValue())
+                               printer.reset(new 
CollPrinter(CollPrinter::QUIET, count));
+                       else 
+                               printer.reset(new 
CollPrinter(CollPrinter::TAGS, count));
+
+                       if (opts.hasNext())
+                       {
+                               debtags.output(expressionFilter(opts.next(), 
opts.match_invert->boolValue(), *printer));
+                       } else
+                               debtags.output(*printer);
+
+                       return count > 0 ? 0 : 1;
+               }
+               // tagcat
+               // Output the entire tag vocabulary
+               else if (opts.foundCommand() == opts.tagcat)
+               {
+                       env().init();
+                       Vocabulary& voc = env().voc();
+
+                       std::set<Facet> facets = voc.facets();
+                       for (std::set<Facet>::const_iterator i = facets.begin();
+                                       i != facets.end(); i++)
+                       {
+                               printVocabularyItem(*i);
+
+                               std::set<Tag> tags = i->tags();
+                               for (std::set<Tag>::const_iterator j = 
tags.begin();
+                                               j != tags.end(); j++)
+                                       printVocabularyItem(*j);
+                       }
+                       return 0;
+               }
+               // tagshow <tag>
+               // Show the vocabulary informations about a tag
+               else if (opts.foundCommand() == opts.tagshow)
+               {
+                       env().init();
+                       string tag = opts.next();
+
+                       Tag t = env().voc().tagByName(tag);
+                       if (!t.valid())
+                       {
+                               verbose("Tag `%s' was not found in tag 
vocabulary\n", tag.c_str());
+                               return 1;
+                       }
+                       else
+                       {
+                               printVocabularyItem(t);
+                               return 0;
+                       }
+               }
+               // tagsearch <pattern [pattern [pattern [...]]]>
+               // Show a summary of all tags matching the given patterns
+               else if (opts.foundCommand() == opts.tagsearch)
+               {
+                       env().init();
+                       SubstringTagMatcher match;
+
+                       // Get the patterns to be matched
+                       bool empty;
+                       while (opts.hasNext())
+                       {
+                               string pattern = opts.next();
+                               match.add(pattern);
+                               empty = false;
+                       }
+
+                       if (empty)
+                       {
+                               error("No patterns given in commandline\n");
+                               return 1;
+                       }
+
+                       int matched = 0;
+
+                       std::set<Facet> facets = env().voc().facets();
+                       for (std::set<Facet>::const_iterator i = facets.begin();
+                                       i != facets.end(); i++)
+                       {
+                               if (match(*i))
+                               {
+                                       matched++;
+                                       printShortVocabularyItem(*i);
+                               }
+
+                               std::set<Tag> tags = i->tags();
+                               for (std::set<Tag>::const_iterator j = 
tags.begin();
+                                               j != tags.end(); j++)
+                                       if (match(*j))
+                                       {
+                                               matched++;
+                                               printShortVocabularyItem(*j);
+                                       }
+                       }
+
+                       return matched > 0 ? 0 : 1;
+               }
+               // show <pkg>
+               // Call apt-cache show <pkg>, but add tag informations to the 
output.\n"
+               else if (opts.foundCommand() == opts.show)
+               {
+                       env().init();
+                       while (opts.hasNext())
+                       {
+                               string name = opts.next();
+
+                               if (env().apt().isValid(name))
+                               {
+                                       PackagePrinter 
printer(PackagePrinter::FULL);
+                                       printer = name;
+                                       return 0;
+                               } else {
+                                       verbose("Package %s not found", 
name.c_str());
+                                       return 1;
+                               }
+                       }
+               }
+               // related <pkg1[,pkg2[,pkg2,[...]]]>
+               // Show packages related to the specified ones
+               else if (opts.foundCommand() == opts.related)
+               {
+                       env().init();
+                       using namespace wibble::operators;
+
+                       int maxdist = 0;
+                       if (opts.misc_distance->boolValue())
+                               maxdist = opts.misc_distance->intValue();
+                       string pkg = opts.next();
+
+                       // Split the items on commas
+                       string splititem;
+                       std::set<string> splititems;
+                       for (string::const_iterator c = pkg.begin(); c != 
pkg.end(); c++)
+                               if (*c == ',')
+                               {
+                                       if (env().apt().isValid(splititem))
+                                       {
+                                               splititems.insert(splititem);
+                                       } else {
+                                               error("Item \"%s\" does not 
exist in the collection\n", splititem.c_str());
+                                               return 1;
+                                       }
+                                       splititem = string();
+                               } else
+                                       splititem += *c;
+                       if (env().apt().isValid(splititem))
+                       {
+                               splititems.insert(splititem);
+                       } else {
+                               error("Item \"%s\" does not exist in the 
collection\n", splititem.c_str());
+                               return 1;
+                       }
+
+                       // Get the tagset as the intersection of the tagsets of 
all input items
+                       std::set<string>::const_iterator i = splititems.begin();
+                       std::set<Tag> ts = env().debtags().getTagsOfItem(*i);
+                       for (++i; i != splititems.end(); i++)
+                               ts &= env().debtags().getTagsOfItem(*i);
+
+                       if (ts.empty())
+                       {
+                               if (splititems.size() > 1)
+                                       fprintf(stderr, "The packages %s are 
unrelated: cannot find a barycenter to start computing relationships from.\n", 
pkg.c_str());
+                               else
+                                       fprintf(stderr, "The package %s has no 
tags attached.\n", pkg.c_str());
+                               return 1;
+                       }
+
+                       std::set<string> 
related(env().debtags().getRelatedItems(ts, maxdist) - splititems);
+
+                       int count = 0;
+
+                       auto_ptr<PackagePrinter> printer;
+                       if (opts.out_names->boolValue())
+                               printer.reset(new 
PackagePrinter(PackagePrinter::NAME, count));
+                       else if (opts.out_full->boolValue())
+                               printer.reset(new 
PackagePrinter(PackagePrinter::FULL, count));
+                       else if (opts.out_quiet->boolValue())
+                               printer.reset(new 
PackagePrinter(PackagePrinter::QUIET, count));
+                       else 
+                               printer.reset(new 
PackagePrinter(PackagePrinter::SHORT, count));
+
+                       for (std::set<string>::const_iterator i = 
related.begin();
+                                       i != related.end(); ++i)
+                       {
+                               **printer = *i;
+                               ++*printer;
+                       }
+
+                       if (count > 50 && maxdist == 0 && isatty(1))
+                       {
+                               string tags;
+                               for (std::set<Tag>::const_iterator i = 
ts.begin();
+                                               i != ts.end(); i++)
+                                       if (i == ts.begin())
+                                               tags += i->fullname();
+                                       else
+                                               tags += "%2C" + i->fullname();
+                               feedback("\nIt seems that this set of packages 
lacks tag information that could help to better distinguish package 
similarities.\nYou can help providing better tagging: just point your browser 
to http://debian.vitavonni.de/packagebrowser/?tags=%s\n";, tags.c_str());
+                       }
+                       return 0;
+               }
+               // maintainers
+               // Create a tagged collection of maintainers and the tags of the
+               // packages they maintain
+               else if (opts.foundCommand() == opts.maintainers)
+               {
+                       env().init();
+                       // Gather maintainer informations
+                       coll::Simple<string, string> maints;
+                       
env().debtags().output(packageToMaint(inserter(maints)));
+
+                       // Print them out
+                       maints.output(textformat::StdioWriter(stdout));
+               }
+               // tag
+               //   tag [add <package> <tags...>\n"
+               //   tag [rm  <package> <tags...>\n"
+               //   tag [ls  <package>\n"
+               //                View and edit the tags for a package\n");
+               else if (opts.foundCommand() == opts.tag)
+               {
+                       std::string cmd = opts.next();
+
+                       if (cmd == "add" || cmd == "rm")
+                       {
+                               env().init(true);
+
+                               string pkg = opts.next();
+                               if (!env().apt().isValid(pkg))
+                               {
+                                       error("Package %s not found\n", 
pkg.c_str());
+                                       return 1;
+                               }
+
+                               std::set<Tag> tagset;
+                               while (opts.hasNext())
+                               {
+                                       string tag = opts.next();
+                                       Tag t = env().voc().tagByName(tag);
+                                       if (t)
+                                               tagset.insert(t);
+                                       else
+                                               error("Tag '%s' not found: 
ignored\n", tag.c_str());
+                               }
+
+                               if (!tagset.empty())
+                               {
+                                       PatchList<string, Tag> change;
+                                       if (cmd == "add")
+                                               change.addPatch(Patch<string, 
Tag>(pkg, tagset, std::set<Tag>()));
+                                       else
+                                               change.addPatch(Patch<string, 
Tag>(pkg, std::set<Tag>(), tagset));
+                                       env().debtags().applyChange(change);
+                                       env().debtags().savePatch();
+                               } else
+                                       verbose("No tags to add\n");
+                       }
+                       else if (cmd == "ls")
+                       {
+                               env().init();
+                               string pkg = opts.next();
+                               if (env().apt().isValid(pkg))
+                               {
+                                       std::set<Tag> ts = 
env().debtags().getTagsOfItem(pkg);
+                                       for (std::set<Tag>::const_iterator i = 
ts.begin();
+                                                       i != ts.end(); i++)
+                                               cout << i->fullname() << endl;
+                                       return 0;
+                               } else {
+                                       verbose("Package %s not found", 
pkg.c_str());
+                                       return 1;
+                               }
+                       }
+                       else
+                               throw wibble::exception::Consistency("parsing 
the 'tag' subcommand", "command " + cmd + " is not valid working with tags");
+               }
+               // submit
+               // Mail the local updates to the tag database to the central tag
+               // repository
+               else if (opts.foundCommand() == opts.submit)
+               {
+                       env().init();
+                       if (opts.hasNext())
+                       {
+                               input::Stdio in(opts.next());
+                               PatchList<string, string> patch;
+                               textformat::parsePatch(in, inserter(patch));
+                               env().debtags().sendPatch(patch);
+                       }
+                       else
+                               env().debtags().sendPatch();
+               }
+               // todo
+               // Print a list of the installed packages that are not yet 
tagged
+               else if (opts.foundCommand() == opts.todo)
+               {
+                       env().init();
+                       int count = 0;
+
+                       auto_ptr<PackagePrinter> printer;
+                       if (opts.out_names->boolValue())
+                               printer.reset(new 
PackagePrinter(PackagePrinter::NAME, count));
+                       else if (opts.out_full->boolValue())
+                               printer.reset(new 
PackagePrinter(PackagePrinter::FULL, count));
+                       else if (opts.out_quiet->boolValue())
+                               printer.reset(new 
PackagePrinter(PackagePrinter::QUIET, count));
+                       else 
+                               printer.reset(new 
PackagePrinter(PackagePrinter::SHORT, count));
+
+                       env().debtags().output(todoFilter(*printer));
+
+                       return count > 0 ? 0 : 1;
+               }
+               // stats
+               // Print statistics about Debtags
+               else if (opts.foundCommand() == opts.stats)
+               {
+                       env().init();
+                       int pkgCount = env().apt().size();
+                       printf("Total count of packages: %d\n", pkgCount);
+
+                       Stats stats;
+                       env().debtags().outputPatched(StatsCollector(stats));
+
+                       printf("Total count of packages (according to APT): 
%d\n", pkgCount);
+                       printf("Total count of packages (according to Debtags): 
%d\n", stats.seen);
+
+                       printf("Number of facets: %zi\n", 
env().voc().facets().size());
+                       printf("Number of tags: %zi\n", 
env().voc().tags().size());
+
+#if 0
+                       // Copied from Debtags class: compute the toplevel 
facets
+                       // TODO: use Debtags instead of Environment throughout 
all Debtags
+                       CardinalityStore<entity::Package, Facet> coll;
+                       TagToFacet<entity::Package> tagStripper(coll);
+                       debtags.outputPatched(tagStripper);
+                       Facet f;
+                       SmartHierarchyNode<entity::Package, Facet> node(f, 
coll, 0);
+                       printf("Number of automatically computed toplevel 
facets: %d\n", node.size());
+#endif
+
+//                     printf("Number of packages with 
special::completely-tagged tags: %d (%.1f%%)\n",
+//                                     stats.complete, 
(float)stats.complete*100/stats.seen);
+                       printf("Number of packages with tags, but no 
special::not-yet-tagged tags: %d (%.1f%%)\n",
+                                       stats.tagged, 
(float)stats.tagged*100/stats.seen);
+                       printf("Number of packages with special::not-yet-tagged 
tags: %d (%.1f%%)\n",
+                                       stats.nyt, 
(float)stats.nyt*100/stats.seen);
+                       printf("Number of packages with only 
special::not-yet-tagged tags: %d (%.1f%%)\n",
+                                       stats.onlynyt, 
(float)stats.onlynyt*100/stats.seen);
+                       printf("Number of packages with no tags: %d (%.1f%%)\n",
+                                       stats.notags, 
(float)stats.notags*100/stats.seen);
+
+               }
+               // check <file>
+               // Check that all the tags in the given tagged collection are
+               // present in the tag vocabulary.  Checks the main database if 
no
+               // file is specified
+               else if (opts.foundCommand() == opts.check)
+               {
+                       env().init();
+                       if (!opts.hasNext())
+                               throw wibble::exception::BadOption("you should 
specify the file with the collection to check");
+
+                       string file = opts.next();
+
+                       VocabularyCheck results;
+                       readCollection(file, VocabularyChecker(env().voc(), 
results));
+
+                       if (results.missing_count > 0)
+                       {
+                               results.report(cout);
+                               return 1;
+                       }
+                       else
+                               return 0;
+               }
+               // score
+               // Score uninstalled packages according to how often their tags
+               // appear in the packages that are installed already
+               else if (opts.foundCommand() == opts.score)
+               {
+                       env().init();
+                       // Compute package scores
+                       PackageScore score;
+                       env().debtags().outputPatched(PackageScorer(score));
+
+                       // Print the results
+                       score.output(env().debtags(), cout);
+               }
+               // mkpatch [filename]
+               // Create a tag patch between the current tag database and the 
tag
+               // collection [filename]
+               else if (opts.foundCommand() == opts.diff)
+               {
+                       env().init();
+                       string file = opts.next();
+
+                       coll::Simple<string, Tag> coll;
+                       env().debtags().outputSystem(file, inserter(coll));
+
+                       PatchList<string, Tag> newpatches;
+                       newpatches.addPatch(env().debtags(), coll);
+
+                       textformat::outputPatch(serPackage, serTag, newpatches, 
stdout);
+               }
+               // ssearch <word [word1 [word2 ...]]>
+               // Perform a keyword search integrated with related packages
+               else if (opts.foundCommand() == opts.smartsearch)
+               {
+                       env().init();
+                       if (!opts.hasNext())
+                               throw wibble::exception::BadOption("you should 
specify one pattern to search");
+
+                       string keywords;
+                       while (opts.hasNext())
+                               if (keywords.empty())
+                                       keywords = opts.next();
+                               else
+                                       keywords += " " + opts.next();
+
+                       SmartSearcher searcher(keywords);
+
+                       if (opts.smse_reltags->boolValue())
+                               searcher.outputRelevantTags();
+                       else if (opts.smse_disctags->boolValue())
+                               searcher.outputDiscriminantTags();
+                       else {
+                               searcher.interact();
+                       }
+               }
+               // update
+               // Updates the package tag database (requires root)
+               else if (opts.foundCommand() == opts.update)
+               {
+                       using namespace wibble::sys;
+
+                       verbose("System source directory: %s\n", 
Path::debtagsSourceDir().c_str());
+                       verbose("User source directory: %s\n", 
Path::debtagsUserSourceDir().c_str());
+
+                       if (!opts.misc_reindex->boolValue())
+                       {
+                               // Run the fetcher to acquire new data
+                               string fetcher = SCRIPTDIR "/fetch";
+                               if (!fs::access(fetcher, X_OK))
+                                       warning("Fetch script %s does not exist 
or is not executable: skipping acquiring of new data\n", fetcher.c_str());
+                               else {
+                                       if (opts.out_verbose->boolValue())
+                                               fetcher += " --verbose";
+                                       if (opts.misc_local->boolValue())
+                                               fetcher += " --local";
+                                       if (system(fetcher.c_str()) != 0)
+                                               throw 
wibble::exception::Consistency("acquiring new data", "fetcher command " + 
fetcher + " failed");
+                               }
+                       }
+
+
+                       // Access the indexes to trigger a rebuild
+                       //typedef ept::t::cache::debtags::IndexManager<> 
IndexManager;
+                       std::string a, b;
+
+                       //auto_ptr<Ept> ept = debtagsInit();
+                       env().init();
+
+                       VocabularyIndexer::obtainWorkingVocabulary(a, b);
+                       verbose("Vocabulary: %s\n", a.c_str());
+                       verbose("Vocabulary index: %s\n", b.c_str());
+
+                       DebtagsIndexer::obtainWorkingDebtags(env().voc(), a, b);
+                       verbose("Tag database: %s\n", a.c_str());
+                       verbose("Tag database index: %s\n", b.c_str());
+
+                       //mode_t prev_umask = umask(022);
+                       //umask(prev_umask);
+               }
+               else if (opts.foundCommand() == opts.vocfilter)
+               {
+                       env().init();
+                       if (!opts.hasNext())
+                               throw wibble::exception::BadOption("you should 
specify the file with the collection to check");
+
+                       string file = opts.next();
+
+                       if (opts.misc_vocfile->boolValue())
+                       {
+                               VocabularyMerger vm;
+                               input::Stdio 
input(opts.misc_vocfile->stringValue());
+                               vm.read(input);
+                               readCollection(file, vocabularyFilter(vm, 
textformat::OstreamWriter(cout)));
+                       }
+                       else
+                               readCollection(file, 
vocabularyFilter(env().voc(), textformat::OstreamWriter(cout)));
+               }
+#if 0
+               // todoreport
+               // Print a report of packages needing work
+               else if (opts.foundCommand() == opts.todoreport)
+               {
+                       debtagsInit();
+                       wantTagDatabase();
+
+                       unsigned int itemsPerGroup = 0;
+                       if (opts.hasNext())
+                               itemsPerGroup = atoi(opts.next().c_str());
+
+                       ReportMaker rm(itemsPerGroup);
+                       rm.printReport();
+
+               }
+#endif
+#if 0
+               // install [-v] [-q] <tag expression>
+               // apt-get install the packages that match the given tag 
expression
+               else if (opts.foundCommand() == opts.install)
+               {
+                       component::PackageTags& debtags = debtagsInit();
+                       wantTagDatabase();
+                       Installer installer;
+
+                       Searcher searcher(debtags, &installer);
+                       string expression = opts.next();
+
+                       searcher.output(expression, 
opts.matchGroup.invert->boolValue());
+
+                       return 1;
+               }
+#endif
+               else
+                       throw wibble::exception::BadOption(string("unhandled 
command ") +
+                                               (opts.foundCommand() ? 
opts.foundCommand()->name() : "(null)"));
+
+               return 0;
+       } catch (wibble::exception::BadOption& e) {
+               cerr << e.desc() << endl;
+               opts.outputHelp(cerr);
+               return 1;
+       } catch (std::exception& e) {
+               cerr << e.what() << endl;
+               return 1;
+       }
+}
+
+#include <ept/debtags/debtags.tcc>
+#include <tagcoll/coll/simple.tcc>
+#include <tagcoll/coll/fast.tcc>
+#include <tagcoll/TextFormat.tcc>
+
+// vim:set ts=4 sw=4:

Added: software/ui/src/manpage.cc
===================================================================
--- software/ui/src/manpage.cc                          (rev 0)
+++ software/ui/src/manpage.cc  2007-06-20 11:18:50 UTC (rev 3004)
@@ -0,0 +1,60 @@
+/*
+ * tagged collection - Experimental programs to test and study tagged 
collections
+ *
+ * Copyright (C) 2003,2004,2005,2006  Enrico Zini
+ * 
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <config.h>
+#include <wibble/commandline/doc.h>
+#include "DebtagsOptions.h"
+#include <iostream>
+
+using namespace std;
+
+int main(int argc, const char* argv[])
+{
+       try {
+               if (argc == 1)
+                       throw wibble::exception::BadOption("no arguments 
provided");
+
+               string cmd(argv[1]);
+               string hooks(argc > 2 ? argv[2] : "");
+
+               if (cmd == "debtags")
+               {
+                       wibble::commandline::DebtagsOptions opts;
+                       wibble::commandline::Manpage help("debtags", VERSION, 
1, "[EMAIL PROTECTED]");
+                       if (!hooks.empty())
+                               help.readHooks(hooks);
+                       help.output(cout, opts);
+               }
+               else
+                       throw wibble::exception::BadOption("unknown command " + 
cmd);
+
+               return 0;
+       } catch (wibble::exception::BadOption& e) {
+               cerr << e.desc() << endl << endl;
+               cerr << "Usage: manpage <command>" << endl << endl;
+               cerr << "Supported commands are: debtags" << endl;
+               return 1;
+       } catch (std::exception& e) {
+               cerr << e.what() << endl;
+               return 1;
+       }
+}
+
+// vim:set ts=4 sw=4:


_______________________________________________
Pkg-games-commits mailing list
[email protected]
http://lists.alioth.debian.org/mailman/listinfo/pkg-games-commits

Reply via email to