diff options
author | Enrico Zini <enrico@enricozini.org> | 2010-05-10 18:58:02 +0100 |
---|---|---|
committer | Enrico Zini <enrico@enricozini.org> | 2010-05-10 18:58:02 +0100 |
commit | 16c7f645ed52eed014d4016fe6160c405e0f6787 (patch) | |
tree | b067ca7fcebd9d916f5b4d7b4475ec8884c7a656 /tools | |
parent | 1b5ac4e66699cacde7123da3b111a0a16ee55db4 (diff) | |
download | libept-16c7f645ed52eed014d4016fe6160c405e0f6787.tar.gz |
ept-cache superseded by axi-cache
Diffstat (limited to 'tools')
-rw-r--r-- | tools/CMakeLists.txt | 12 | ||||
-rw-r--r-- | tools/Environment.cc | 126 | ||||
-rw-r--r-- | tools/Environment.h | 136 | ||||
-rw-r--r-- | tools/EptCacheOptions.h | 293 | ||||
-rw-r--r-- | tools/ept-cache-man-hooks | 49 | ||||
-rw-r--r-- | tools/ept-cache.cc | 1060 | ||||
-rw-r--r-- | tools/filters.cc | 112 | ||||
-rw-r--r-- | tools/filters.h | 125 | ||||
-rw-r--r-- | tools/info.cc | 126 | ||||
-rw-r--r-- | tools/info.h | 79 | ||||
-rw-r--r-- | tools/manpage.cc | 62 | ||||
-rw-r--r-- | tools/utils.h | 72 |
12 files changed, 1 insertions, 2251 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index bd75e75..6ec14fe 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -4,18 +4,8 @@ link_libraries( ept ) add_executable( ept-cat ept-cat.cpp ) add_executable( pkglist pkglist.cpp ) -add_executable( manpage manpage.cc ) -add_executable( ept-cache - ept-cache.cc Environment.cc filters.cc info.cc ) set( bindir ${CMAKE_CURRENT_BINARY_DIR} ) set( srcdir ${CMAKE_CURRENT_SOURCE_DIR} ) -add_custom_command( - TARGET manpage - POST_BUILD - DEPENDS manpage - COMMAND LD_LIBRARY_PATH=${ept_BINARY_DIR} ${bindir}/manpage ept-cache ${srcdir}/ept-cache-man-hooks > ${bindir}/ept-cache.1 ) - -install( TARGETS ept-cache RUNTIME DESTINATION bin ) -install( FILES ${bindir}/ept-cache.1 DESTINATION share/man/man1 ) +install( PROGRAMS ept-cache DESTINATION bin ) diff --git a/tools/Environment.cc b/tools/Environment.cc deleted file mode 100644 index 2249591..0000000 --- a/tools/Environment.cc +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Common environment for many program parts - * - * Copyright (C) 2003 Enrico Zini <enrico@debian.org> - * - * 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 <ept/debtags/debtags.h> -#include <ept/debtags/vocabulary.h> -#include <ept/popcon/popcon.h> -#include <ept/popcon/local.h> -#include <ept/axi/axi.h> - -#include <stdio.h> -#include <stdarg.h> -#include <unistd.h> // isatty - -using namespace std; -using namespace ept; - -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), m_popcon(0), m_popconlocal(0), m_axi(0), _verbose(false), _debug(false) {} - -void Environment::init(bool editable) -{ - m_apt = new ept::apt::Apt; - m_debtags = new ept::debtags::Debtags(editable); - m_vocabulary = new ept::debtags::Vocabulary; - m_popcon = new ept::popcon::Popcon; - m_popconlocal = new ept::popcon::Local; - if (axi::timestamp() > 0) - m_axi = new Xapian::Database(axi::path_db()); - else - m_axi = new Xapian::Database; -} - -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: diff --git a/tools/Environment.h b/tools/Environment.h deleted file mode 100644 index d332da3..0000000 --- a/tools/Environment.h +++ /dev/null @@ -1,136 +0,0 @@ -#ifndef EPTCACHE_ENVIRONMENT_H -#define EPTCACHE_ENVIRONMENT_H - -/* - * Common environment for many program parts - * - * Copyright (C) 2007 Enrico Zini <enrico@debian.org> - * - * 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 <string> - -namespace Xapian { -class Database; -} - -namespace ept { -namespace apt { -class Apt; -} -namespace debtags { -class Debtags; -class Vocabulary; -} -namespace popcon { -class Popcon; -class Local; -} -} - -class Environment -{ -protected: - /// Apt data provider - ept::apt::Apt* m_apt; - - /// Debtags data provider - ept::debtags::Debtags* m_debtags; - - /// Debtags vocabulary data provider - ept::debtags::Vocabulary* m_vocabulary; - - /// Popcon data provider - ept::popcon::Popcon* m_popcon; - - /// Popcon local vote data provider - ept::popcon::Local* m_popconlocal; - - /// TextSearch data provider - Xapian::Database* m_axi; - - // 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_vocabulary; } - - /// Access the popcon data - ept::popcon::Popcon& popcon() { return *m_popcon; } - - /// Access the popcon data - ept::popcon::Local& popconLocal() { return *m_popconlocal; } - - /// Access the textsearch data - Xapian::Database& axi() { return *m_axi; } - - // 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 diff --git a/tools/EptCacheOptions.h b/tools/EptCacheOptions.h deleted file mode 100644 index f666e12..0000000 --- a/tools/EptCacheOptions.h +++ /dev/null @@ -1,293 +0,0 @@ -#ifndef EPTCACHE_OPTIONS_H -#define EPTCACHE_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 <ept/config.h> -#include <wibble/commandline/parser.h> - -namespace wibble { -namespace commandline { - -struct EptCacheOptions : public StandardParserWithMandatoryCommand -{ -public: - BoolOption* out_quiet; - BoolOption* out_verbose; - - BoolOption* out_debug; - BoolOption* out_names; - BoolOption* out_short; - BoolOption* out_full; - BoolOption* out_tagcoll; - IntOption* out_limit; - IntOption* out_cutoff; - StringOption* out_sort; - - StringOption* filter_tagexpr; - StringOption* filter_type; - -#if 0 - BoolOption* out_facets; - BoolOption* match_invert; - - BoolOption* misc_local; - BoolOption* misc_reindex; - IntOption* misc_distance; - StringOption* misc_vocfile; - - BoolOption* smse_reltags; - BoolOption* smse_disctags; - -#endif - Engine* show; - Engine* search; - Engine* dumpavail; - Engine* reindex; - Engine* info; - Engine* related; -#if 0 - Engine* update; - Engine* selfcheck; - Engine* check; - Engine* tagcat; - Engine* tagshow; - Engine* tagsearch; - Engine* cat; - Engine* grep; - Engine* install; - Engine* diff; - Engine* maintainers; - Engine* tag; - Engine* submit; - Engine* todo; - Engine* score; - Engine* stats; - Engine* todoreport; - Engine* smartsearch; - Engine* vocfilter; -#endif - - EptCacheOptions() - : StandardParserWithMandatoryCommand("ept-cache", VERSION, 1, "enrico@enricozini.org") - { - usage = "<command> [options and arguments]"; - description = "High-level tool to access package information"; - - // Output options - 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 package output group - OptionGroup* pkgOutputOpts = createGroup("Output options"); - out_names = pkgOutputOpts->add<BoolOption>("names", 0, "names", "", - "output only the names of the packages"); - out_quiet = pkgOutputOpts->add<BoolOption>("quiet", 'q', "quiet", "", - "do not write anything to standard output"); - 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"); - out_tagcoll = pkgOutputOpts->add<BoolOption>("tagcoll", 0, "tagcoll", "", - "tagcoll-style output"); - out_limit = pkgOutputOpts->add<IntOption>("limit", 0, "limit", "count", - "maximum number of packages to show"); - out_cutoff = pkgOutputOpts->add<IntOption>("cutoff", 0, "cutoff", "percent", - "do not show results that are this percent worse than the top result"); - out_sort = pkgOutputOpts->add<StringOption>("sort", 's', "sort", "method", - "sort order (use 'list' for a list of supported options)"); - - OptionGroup* filterOpts = createGroup("Filter options"); - filter_tagexpr = filterOpts->add<StringOption>("ftags", 0, "ftags", "tagexpr", - "only print packages matching this tag expression"); - filter_type = filterOpts->add<StringOption>("type", 't', "type", "name", - "only print packages of a given type (use 'list' for a list of supported types)"); - -#if 0 - // Create the collection output group - OptionGroup* collOutputOpts = createGroup("Options controlling transformations of tag data on output"); - out_facets = collOutputOpts->add<BoolOption>("facets", 0, "facets", "", - "output only the names of the facets (mainly used for computing statistics)"); - - // 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"); - - 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"); - - 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", - "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); -#endif - - show = addEngine("show", "<pkg>", - "show informations about a package, like apt-cache show does, but " - "adds new fields with all available extra metadata"); - show->add(pkgOutputOpts); - - search = addEngine("search", "[keywords]", - "output the names and descriptions of the packages that match" - " the given tag expression"); - search->add(pkgOutputOpts); - search->add(filterOpts); - - dumpavail = addEngine("dumpavail", "[keywords]", - "output the full package database, with all extra metadata"); - dumpavail->add(pkgOutputOpts); - dumpavail->add(filterOpts); - - reindex = addEngine("reindex", "", - "updates the various indexes managed by libept (requires root).\n" - "It needs to be run as root"); - reindex->add(out_quiet); - - info = addEngine("info", "", - "show information about the data providers.\n"); - - related = addEngine("related", "[pkgnames]", - "show packages similar to the given ones", - "Show packages similar to the given ones. Package similarity is " - " computed by how many common elements there are in their" - " descriptions and their tags"); - related->add(pkgOutputOpts); - related->add(filterOpts); - -#if 0 - 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"); -#endif - -#if 0 - 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", - "vocabulary file to use instead of the current debtags vocabulary"); -#endif - } -}; - -} -} - -// vim:set ts=4 sw=4: -#endif diff --git a/tools/ept-cache-man-hooks b/tools/ept-cache-man-hooks deleted file mode 100644 index 3563668..0000000 --- a/tools/ept-cache-man-hooks +++ /dev/null @@ -1,49 +0,0 @@ -DESCRIPTION end -|\fBept-cache\fP is a high-level tool to access package information. -|.P -|It can currently search and display data from four sources: the APT database, -|the Debtags tag information, Popcon package scores and a fast Xapian-based full -|text index on package descriptions. -|.P -|If the Xapian data source is enabled, output results are by default sorted by -|relevance order, with the best results first. If you are seeing strange -|results in the output, rerun the search with the \-\-full switch and look at -|the Search\-Score headers. - -OPTIONS end -|.SH EXAMPLES -|.P -|.nf -|# Output all the available information about apt -|ept-cache show apt -| -|# Keyword search -|ept-cache search image editor -| -|# Keyword search with simple tag filter -|ept-cache search -t gui image editor -| -|# More results -|ept-cache search -t gui --limit=300 image editor -| -|# Output full package records for grep-dctrl. -|# The records will contain improved Tag: headers, Popcon information and -|# any other information that is available through libept. -|ept-cache dumpavail -t gui image editor -| -|# Show packages similar to mutt -|ept-cache related mutt -| -|# Show packages somewhat inbetween mutt and iceweasel -|ept-cache related mutt iceweasel -| -|# Show what data sources are available -|ept-cache info -| -|# Build or update the indexes (needs root) -|ept-cache reindex -|.fi - -AUTHOR before -|.SH SEE ALSO -|\fBdebtags\fP (1), \fBapt-cache\fP (1) diff --git a/tools/ept-cache.cc b/tools/ept-cache.cc deleted file mode 100644 index bd3a8af..0000000 --- a/tools/ept-cache.cc +++ /dev/null @@ -1,1060 +0,0 @@ -/* - * ept-cache - Commandline interface to the ept library - * - * Copyright (C) 2007--2010 Enrico Zini <enrico@debian.org> - * - * 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 "EptCacheOptions.h" -#include "info.h" -#include "filters.h" -#include "utils.h" - -#include <ept/apt/apt.h> -#include <ept/apt/packagerecord.h> -#include <ept/debtags/debtags.h> -#include <ept/debtags/vocabulary.h> -#include <ept/popcon/popcon.h> -#include <ept/popcon/local.h> -#include <tagcoll/expression.h> -#include <ept/axi/axi.h> - -#include <wibble/regexp.h> -#include <wibble/string.h> - -#include <algorithm> -#include <iostream> -#include <sstream> - -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> - -/* - * * For packages - * - * Filters: - * + keyword search - * + tag expression - * - min/max popularity - * - installed status - * - * Sort orders - * + unsorted - * + alphabetical (?) - * + by popularity - * + by representativeness (only when installed) - * - by xapian score - * - * Show - * + Names only - * + Names and short descriptions - * + Full fields (dumpavail) - * + Nothing (return value à la grep) - * - * - * * For tags - * - * Filters - * - * - keyword search - * - relevance search - * - * Sort orders - * - * - alphabetic order - * - relevance order - * - xapian order (automatically given by the data source) - * - * Show - * - Names only - * - Names and short descriptions - * - Full fields (dumpavail) - * - Nothing (return value à la grep) - */ - -using namespace std; -using namespace tagcoll; -using namespace wibble; -using namespace ept; -using namespace ept::debtags; -using namespace ept::apt; - -static const int DEFAULT_QUALITY_CUTOFF = 50; - -// Database of expression macros -struct ExpressionMacros : public map<string, string> -{ - ExpressionMacros() { - insert(make_pair("gui", "role::program && (interface::x11 || interface::3d)")); - insert(make_pair("cmdline", "role::program && interface::commandline")); - insert(make_pair("game", "role::program && game::*")); - insert(make_pair("devel", "devel::* && !role::shared-lib")); - insert(make_pair("clean", "!role::shared-lib && !role::app-data")); - } -} expressionMacros; - -// Sorting infrastructure -template<typename SORTER> -struct Negator -{ - const SORTER& s; - - Negator(const SORTER& s) : s(s) {} - - bool operator()(const Info* a, const Info* b) const - { - return s(b, a); - } -}; -template<typename SORTER> -Negator<SORTER> negator(const SORTER& s) -{ - return Negator<SORTER>(s); -} -bool popularitySort(const Info* a, const Info* b) -{ - return a->popcon * a->xapian_score < b->popcon * b->xapian_score; -} -bool tfidfSort(const Info* a, const Info* b) -{ - return a->tfidf < b->tfidf; -} -bool nameSort(const Info* a, const Info* b) -{ - return a->name < b->name; -} -bool downloadSizeSort(const Info* a, const Info* b) -{ - return a->record->packageSize() < b->record->packageSize(); -} -bool installedSizeSort(const Info* a, const Info* b) -{ - return a->record->installedSize() < b->record->installedSize(); -} - -/// Consumer for package filters -struct Consumer -{ - size_t count; - int limit; - - Consumer() : count(0), limit(-1) {} - virtual ~Consumer() {} - - // Set the maximum number of items to consume from now on - void setLimit(int limit) { this->limit = limit; } - - // Set the maximum number of items to consume from now on to unlimited - void resetLimit() { limit = -1; } - - // Consume one Info item; returns true if it can consume more, false if - // production should stop for this consumer - virtual bool operator()(Info& i) - { - ++count; - if (limit == -1) - return true; - else if (limit > 0) - { - --limit; - return true; - } else - return false; - } - - // Signal that no more items will be produced - virtual void done() {} -}; - -struct Sorter : public Consumer -{ - vector<Info*> data; - bool reverse; - char sortType; - Consumer* out; - - Sorter(const std::string& stype, Consumer* out) - : reverse(false), sortType(0), out(out) - { - // Parse the sort type - for (string::const_iterator i = stype.begin(); - i != stype.end(); ++i) - switch (*i) - { - case '-': reverse = true; break; - default: if (!sortType) sortType = *i; break; - } - // Early warning to avoid complaining after generation was done - if (sortType != 'd' && sortType != 'i' && sortType != 'n' && sortType != 'p' && sortType != 't' && sortType != 'x') - throw wibble::exception::Consistency("parsing sort type", "invalid sort type (use 'list' for a list)"); - } - virtual ~Sorter() - { - if (out) delete out; - for (vector<Info*>::iterator i = data.begin(); - i != data.end(); ++i) - delete *i; - } - - /** - * Disconnect the chained consumer so that it will not be deallocated when - * the Sorter object is deleted. - * - * @returns The chained consumer - */ - Consumer* disconnectConsumer() - { - Consumer* res; - this->out = 0; - return res; - } - - virtual bool operator()(Info& i) - { - if (!Consumer::operator()(i)) - return false; - data.push_back(new Info(i)); - return true; - } - - virtual void done() - { - bool generateReversed = false; - - // Perform sorting - switch (sortType) - { - case 'd': - // Download size - for (vector<Info*>::iterator i = data.begin(); - i != data.end(); ++i) - (*i)->wantRecord(); - if (reverse) - std::sort(data.begin(), data.end(), negator(downloadSizeSort)); - else - std::sort(data.begin(), data.end(), downloadSizeSort); - break; - case 'i': - // Installed size - for (vector<Info*>::iterator i = data.begin(); - i != data.end(); ++i) - (*i)->wantRecord(); - if (reverse) - std::sort(data.begin(), data.end(), negator(installedSizeSort)); - else - std::sort(data.begin(), data.end(), installedSizeSort); - break; - case 'n': - // Alphabetical - if (reverse) - std::sort(data.begin(), data.end(), negator(nameSort)); - else - std::sort(data.begin(), data.end(), nameSort); - break; - case 'p': - // Popularity - for (vector<Info*>::iterator i = data.begin(); - i != data.end(); ++i) - (*i)->wantPopcon(); - if (reverse) - std::sort(data.begin(), data.end(), negator(popularitySort)); - else - std::sort(data.begin(), data.end(), popularitySort); - break; - case 't': - // TFIDF - for (vector<Info*>::iterator i = data.begin(); - i != data.end(); ++i) - (*i)->wantPopconLocal(); - if (reverse) - //std::sort(data.begin(), data.end(), negator(tfidfSort)); - std::sort(data.begin(), data.end(), negator(tfidfSort)); - else - std::sort(data.begin(), data.end(), tfidfSort); - break; - case 'x': - // Xapian score - - // We need to flip the other way round here, because xapian - // produces results in reverse score order - generateReversed = !reverse; - break; - default: - throw wibble::exception::Consistency("sorting", "invalid sort type (use 'list' for a list)"); - } - - if (generateReversed) - { - for (vector<Info*>::reverse_iterator i = data.rbegin(); - i != data.rend(); ++i) - if (!(*out)(**i)) - break; - } - else - { - for (vector<Info*>::iterator i = data.begin(); - i != data.end(); ++i) - if (!(*out)(**i)) - break; - } - } -}; - -struct NullPrinter : public Consumer -{ - virtual ~NullPrinter() {} -}; - -struct NamePrinter : public Consumer -{ - ostream& out; - NamePrinter(ostream& out) : out(out) {} - - virtual ~NamePrinter() {} - virtual bool operator()(Info& i) - { - if (!Consumer::operator()(i)) - return false; - out << i.name << endl; - return true; - } -}; - -struct ShortDescPrinter : public Consumer -{ - ostream& out; - ShortDescPrinter(ostream& out) : out(out) {} - virtual ~ShortDescPrinter() {} - virtual bool operator()(Info& i) - { - if (!Consumer::operator()(i)) - return false; - i.wantRecord(); - out << i.name << " - " << - i.record->shortDescription("(short description not available)") << endl; - return true; - } -}; - -struct TagcollPrinter : public Consumer -{ - ostream& out; - TagcollPrinter(ostream& out) : out(out) {} - virtual ~TagcollPrinter() {} - virtual bool operator()(Info& i) - { - if (!Consumer::operator()(i)) - return false; - i.wantTags(); - out << i.name << ": " << i.tags << endl; - return true; - } -}; - -struct FullRecordPrinter : public Consumer -{ - bool hasDebtags; - bool hasPopcon; - bool hasPopconLocal; - ostream& out; - FullRecordPrinter(ostream& out) : out(out) - { - hasDebtags = env().debtags().hasData(); - hasPopcon = env().popcon().hasData(); - hasPopconLocal = env().popconLocal().hasData(); - } - virtual ~FullRecordPrinter() {} - virtual bool operator()(Info& info) - { - if (!Consumer::operator()(info)) - return false; - info.wantRecord(); - info.wantTags(); - PackageRecord& record = *info.record; - bool tagsPrinted = false; - for (size_t i = 0; i < record.size(); ++i) - { - if (record.name(i) == "Tag") - { - tagsPrinted = true; - if (!info.tags.empty()) - out << "Tag: " << info.tags << std::endl; - } else { - out << record.field(i); - } - } - if (!tagsPrinted) - if (!info.tags.empty()) - out << "Tag: " << info.tags << std::endl; - if (hasPopcon) - { - info.wantPopcon(); - out << "Popcon: " << info.popcon << endl; - } - if (hasPopconLocal) - { - info.wantPopconLocal(); - out << "TFIDF: " << info.tfidf << endl; - } - if (info.has_xapian) - { - out << "Search-Score: " << info.xapian_score << endl; - } - out << std::endl; - return true; - } -}; - -/// Send a tag stream to an Info consumer -class OutputInfo : public wibble::mixin::OutputIterator<OutputInfo> -{ - const filter::Base& filter; - Consumer& out; - // When true, the consumer is ignoring the input - bool done; - -public: - OutputInfo(const filter::Base& filter, Consumer& out) - : filter(filter), out(out), done(false) {} - - template<typename ITEMS, typename TAGS> - OutputInfo& operator=(const std::pair<ITEMS, TAGS>& data) - { - if (done) return *this; - for (typename ITEMS::const_iterator i = data.first.begin(); - i != data.first.end(); ++i) - { - if (!env().apt().isValid(*i)) continue; - Info info(*i); - info.has_tags = true; - info.tags = data.second; - if (filter(info)) - if (!out(info)) - { - done = true; - break; - } - } - return *this; - } -}; - -/** - * Generate an Info stream and send it to a consumer. - * - * The sorting order will depend on what is the data provider that is chosen to - * initiate the stream, and is thus undefined. - */ -struct Generator -{ - filter::And filters; - - Xapian::QueryParser qp; - Xapian::Stem stem; - - Generator() : stem("en") - { - qp.set_default_op(Xapian::Query::OP_AND); - qp.set_database(env().axi()); - qp.set_stemmer(stem); - qp.set_stemming_strategy(Xapian::QueryParser::STEM_SOME); - qp.add_prefix("pkg", "XP"); - qp.add_boolean_prefix("tag", "XT"); - qp.add_boolean_prefix("sec", "XS"); - } - - Xapian::Query makeQuery(const vector<string>& keywords) - { - // Add prefixes to tag names - const Vocabulary& voc = env().voc(); - vector<string> kw; - for (vector<string>::const_iterator i = keywords.begin(); - i != keywords.end(); ++i) - { - if (voc.hasTag(*i)) - kw.push_back("tag:" + *i); - else - kw.push_back(*i); - } - return qp.parse_query(str::join(kw.begin(), kw.end(), " "), - Xapian::QueryParser::FLAG_BOOLEAN | - Xapian::QueryParser::FLAG_LOVEHATE | - Xapian::QueryParser::FLAG_BOOLEAN_ANY_CASE | - Xapian::QueryParser::FLAG_WILDCARD | - Xapian::QueryParser::FLAG_PURE_NOT | - Xapian::QueryParser::FLAG_SPELLING_CORRECTION); - } - - // Generate all the packages, without records - void generateNames(Consumer& out) - { - debug("Generate iterating names\n"); - for (Apt::iterator i = env().apt().begin(); - i != env().apt().end(); ++i) - { - Info info(*i); - if (filters(info)) - if (!out(info)) - break; - } - } - - // Generate all the packages, with records - void generateRecords(Consumer& out) - { - debug("Generate iterating records\n"); - PackageRecord rec; - for (Apt::record_iterator i = env().apt().recordBegin(); - i != env().apt().recordEnd(); ++i) - { - rec.scan(*i); - Info info(rec.package()); - info.record = &rec; - if (filters(info)) - if (!out(info)) - break; - } - } - - // Generate after a keyword search - void keywordXapianSearch(const vector<string>& keywords, Consumer& out, int qualityCutoff = DEFAULT_QUALITY_CUTOFF) - { - debug("Generate with xapian\n"); - Xapian::Enquire enquire(env().axi()); - - // Set up the base query - Xapian::Query query = makeQuery(keywords); - enquire.set_query(query); - debug("Xapian query: %s\n", query.get_description().c_str()); - -#if 0 - // Get a set of tags to expand the query - vector<string> expand = env().textsearch().expand(enquire); - - // Build the expanded query - Xapian::Query expansion(Xapian::Query::OP_OR, expand.begin(), expand.end()); - enquire.set_query(Xapian::Query(Xapian::Query::OP_OR, query, expansion)); - debug("Expanded Xapian query: %s\n", enquire.get_query().get_description().c_str()); -#endif - - //cerr << "Q: " << enquire.get_query().get_description() << endl; - fromXapianEnquire(enquire, out, qualityCutoff); - } - - void fromXapianEnquire(Xapian::Enquire& enquire, Consumer& out, int qualityCutoff = DEFAULT_QUALITY_CUTOFF, const Xapian::MatchDecider* md = 0) - { - // Retrieve the first result, to compute the cutoff score - Xapian::MSet first = enquire.get_mset(0, 1, 0, 0, md); - Xapian::MSetIterator ifirst = first.begin(); - if (ifirst == first.end()) - // If there are no results, quit now - return; - // Set a percentage cutoff based on the quality of the first results - debug(" Reference value for quality cutoff: %d%%\n", ifirst.get_percent()); - Xapian::percent cutoff = ifirst.get_percent() * qualityCutoff / 100; - debug(" Quality cutoff at: %d%%\n", cutoff); - enquire.set_cutoff(cutoff); - - bool done = false; - for (size_t pos = 0; !done; pos += 20) - { - // Limit to 1000 matches - Xapian::MSet matches = enquire.get_mset(pos, 20, 0, 0, md); - if (matches.size() < 20) - done = true; - for (Xapian::MSetIterator i = matches.begin(); i != matches.end(); ++i) - { - // Filter out results that apt doesn't know - if (!env().apt().isValid(i.get_document().get_data())) - { - debug(" Not in apt database: %s\n", i.get_document().get_data().c_str()); - continue; - } - // Create the info element - Info info(i.get_document().get_data()); - info.has_xapian = true; - info.xapian_score = i.get_percent(); - - debug(" Producing %s (%d%%)\n", info.name.c_str(), info.xapian_score); - - // Pass it on to the consumer - if (filters(info)) - if (!out(info)) - { - done = true; - break; - } - } - } - } - - void keywordAptSearch(const vector<string>& keywords, Consumer& out) - { - debug("Generate iterating records plus a keyword search\n"); - filters.acquire_front(new filter::Description(keywords)); - generateRecords(out); - } - - void debtagsSearch(const set<std::string>& wantedTags, Consumer& out) - { - debug("Generate by querying debtags\n"); - env().debtags().outputHavingTags(wantedTags, OutputInfo(filters, out)); - } -}; - - -/** - * Instantiate the consumer defined by the output options. - * - * If no output option has been specified, it returns the given default. - * Otherwise it creates a new default consumer and deletes the default one. - */ -Consumer* createPrinter(const wibble::commandline::EptCacheOptions& opts, Consumer* def) -{ - Consumer* res = 0; - if (opts.out_names->boolValue()) - res = new NamePrinter(cout); - else if (opts.out_short->boolValue()) - res = new ShortDescPrinter(cout); - else if (opts.out_full->boolValue()) - res = new FullRecordPrinter(cout); - else if (opts.out_quiet->boolValue()) - res = new NullPrinter(); - else if (opts.out_tagcoll->boolValue()) - res = new TagcollPrinter(cout); - else - res = def; - if (res != def) - delete def; - return res; -} - -bool usesXapian(wibble::commandline::EptCacheOptions& opts) -{ - return opts.hasNext() && axi::timestamp() > 0; -} - -void generate(wibble::commandline::EptCacheOptions& opts, Consumer& output, - int defaultXapianLimit = -1, int defaultXapianQualityCutoff = DEFAULT_QUALITY_CUTOFF) -{ - Generator gen; - - // Append filters - if (opts.filter_tagexpr->isSet()) - gen.filters.acquire(new filter::TagExpression(opts.filter_tagexpr->stringValue())); - - if (opts.filter_type->isSet()) - { - ExpressionMacros::const_iterator i = expressionMacros.find(opts.filter_type->stringValue()); - if (i == expressionMacros.end()) - throw wibble::exception::Consistency("parsing filter type", "invalid filter type (use 'list' for a list)"); - gen.filters.acquire(new filter::TagExpression(i->second)); - } - - // Configure the output consumer with sorters and limits - Consumer* cons = &output; - - // If we sort, we introduce an intermediate step - if (opts.out_sort->isSet()) - cons = new Sorter(opts.out_sort->stringValue(), cons); - - // Set the output limit where it's needed - bool xapian = usesXapian(opts); - if (xapian) - { - if (opts.out_sort->isSet()) - { - // If we use Xapian and we have a sorter, we need a cutoff - // at the quality score: since the sorter will scramble the - // xapian relevance scoring, we only need to feed good - // results to it - - // Keep the default Xapian quality cutoff set by the user, then - - // Set the match limit on the printer side - if (opts.out_limit->isSet()) - output.setLimit(opts.out_limit->intValue()); - } else { - // If we use Xapian and don't have a sorter, we can keep - // generating less relevant results as the xapian sorting - // order will help the user to make sense of the results - defaultXapianQualityCutoff = -1; - - // Set the match limit at the beginning of the output chain - if (opts.out_limit->isSet()) - cons->setLimit(opts.out_limit->intValue()); - else if (defaultXapianLimit != -1) - // Xapian shows the best matches first, so we can greatly - // reduce the limit - cons->setLimit(defaultXapianLimit); - } - } - else - { - // If we don't use Xapian, the packages arrive in undefined - // order, so we need to feed all of them to the sorter - // because we don't know when the top scored packages will - // be generated, or to the output - - // Set the match limit on the printer side - if (opts.out_limit->isSet()) - output.setLimit(opts.out_limit->intValue()); - } - - if (opts.out_cutoff->isSet()) - defaultXapianQualityCutoff = opts.out_cutoff->intValue(); - - if (opts.hasNext()) - { - // We have keywords - vector<string> keywords; - while (opts.hasNext()) - keywords.push_back(toLower(opts.next())); - if (axi::timestamp() > 0) - gen.keywordXapianSearch(keywords, *cons, defaultXapianQualityCutoff); - else - gen.keywordAptSearch(keywords, *cons); - } else { - // No keyword search - if (opts.out_names->boolValue()) - gen.generateNames(*cons); - else - gen.generateRecords(*cons); - } - - // Signal the end of input to the consumers - cons->done(); -} - -struct BlacklistDecider : public Xapian::MatchDecider -{ - std::set<std::string> blacklist; - BlacklistDecider() {} - BlacklistDecider(const std::set<std::string>& blacklist) : blacklist(blacklist) {} - - virtual bool operator()(const Xapian::Document& doc) const - { - return blacklist.find(doc.get_data()) == blacklist.end(); - } -}; - -Xapian::Query makeRelatedQuery(const std::string& pkgname) -{ - Xapian::Enquire enquire(env().axi()); - - // Retrieve the document for the given package - enquire.set_query(Xapian::Query("XP"+pkgname)); - Xapian::MSet matches = enquire.get_mset(0, 1); - Xapian::MSetIterator mi = matches.begin(); - if (mi == matches.end()) return Xapian::Query(); - Xapian::Document doc = mi.get_document(); - - // Return the query to get the list of similar documents - return Xapian::Query(Xapian::Query::OP_OR, doc.termlist_begin(), doc.termlist_end()); -} - -void generateRelated(wibble::commandline::EptCacheOptions& opts, Consumer& output, - int defaultXapianLimit = -1, int defaultXapianQualityCutoff = DEFAULT_QUALITY_CUTOFF) -{ - Generator gen; - - // Append filters - if (opts.filter_tagexpr->isSet()) - gen.filters.acquire(new filter::TagExpression(opts.filter_tagexpr->stringValue())); - - if (opts.filter_type->isSet()) - { - ExpressionMacros::const_iterator i = expressionMacros.find(opts.filter_type->stringValue()); - if (i == expressionMacros.end()) - throw wibble::exception::Consistency("parsing filter type", "invalid filter type (use 'list' for a list)"); - gen.filters.acquire(new filter::TagExpression(i->second)); - } - - // Configure the output consumer with sorters and limits - Consumer* cons = &output; - - // If we sort, we introduce an intermediate step - if (opts.out_sort->isSet()) - cons = new Sorter(opts.out_sort->stringValue(), cons); - - // Set the output limit where it's needed - if (opts.out_sort->isSet()) - { - // If we use Xapian and we have a sorter, we need a cutoff - // at the quality score: since the sorter will scramble the - // xapian relevance scoring, we only need to feed good - // results to it - - // Keep the default Xapian quality cutoff set by the user, then - - // Set the match limit on the printer side - if (opts.out_limit->isSet()) - output.setLimit(opts.out_limit->intValue()); - } else { - // If we use Xapian and don't have a sorter, we can keep - // generating less relevant results as the xapian sorting - // order will help the user to make sense of the results - defaultXapianQualityCutoff = -1; - - // Set the match limit at the beginning of the output chain - if (opts.out_limit->isSet()) - cons->setLimit(opts.out_limit->intValue()); - else if (defaultXapianLimit != -1) - // Xapian shows the best matches first, so we can greatly - // reduce the limit - cons->setLimit(defaultXapianLimit); - } - - if (opts.out_cutoff->isSet()) - defaultXapianQualityCutoff = opts.out_cutoff->intValue(); - - Xapian::Enquire enq(env().axi()); - string name = opts.next(); - Xapian::Query query = makeRelatedQuery(name); - BlacklistDecider blacklister; - debug("Excluding '%s' from the results\n", name.c_str()); - blacklister.blacklist.insert(name); - // We can even easily compute packages related to a list of packages - while (opts.hasNext()) - { - name = opts.next(); - debug("Excluding '%s' from the results\n", name.c_str()); - blacklister.blacklist.insert(name); - if (!env().apt().isValid(name)) - throw wibble::exception::Consistency("reading package names", "package "+name+" does not exist"); - query = Xapian::Query(Xapian::Query::OP_AND, query, makeRelatedQuery(name)); - } - //enq.register_match_decider("blacklist", &blacklister); - //gen.filters.acquire(new filter::Blacklist(seen)); - enq.set_query(query); - - // Generate from the Xapian enquire - //cerr << "Q: " << enq.get_query().get_description() << endl; - gen.fromXapianEnquire(enq, *cons, defaultXapianQualityCutoff, &blacklister); - - // Signal the end of input to the consumers - cons->done(); -} - -bool printOutOptionsHelpIfNeeded(wibble::commandline::EptCacheOptions& opts) -{ - if (opts.filter_type->isSet() && opts.filter_type->stringValue() == "list") - { - for (ExpressionMacros::const_iterator i = expressionMacros.begin(); - i != expressionMacros.end(); ++i) - cout << i->first << ": " << i->second << endl; - return true; - } - - if (opts.out_sort->isSet() && opts.out_sort->stringValue() == "list") - { - cout << "Available sort options:" << endl - << endl - << "download size - Sort by download size" << endl - << "installed size - Sort by installed size" << endl - << "name - Sort alphabetically by package name" << endl - << "popularity - Sort by popcon popularity" << endl - << "tfidf - Sort by how much a package makes a system unique" << endl - << "xapian - Sort by xapian relevance score" << endl - << endl - << "It is sufficient to provide a nonambiguous prefix of the sort type." << endl - << "Add a '-' to the begining or end to reverse the sort order." << endl - << "Example:" << endl - << " ept-cache search -s p- image editor" << endl; - return true; - } - return false; -} - -int success_if_had_output(Consumer* output) -{ - int count = output->count; - delete output; - return count > 0 ? 0 : 1; -} - -int main(int argc, const char* argv[]) -{ - wibble::commandline::EptCacheOptions opts; - bool warn_non_root_on_error = false; - - 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); - - // show <pkg> - // Similar to apt-cache show <pkg>, but add extra metadata to the output." - if (opts.foundCommand() == opts.show) - { - env().init(); - Consumer* output = createPrinter(opts, new FullRecordPrinter(cout)); - while (opts.hasNext()) - { - string name = opts.next(); - - if (env().apt().isValid(name)) - { - Info i(name); - (*output)(i); - } else { - verbose("Package %s not found", name.c_str()); - } - } - return success_if_had_output(output); - } - else if (opts.foundCommand() == opts.search) - { - if (printOutOptionsHelpIfNeeded(opts)) - return 1; - env().init(); - Consumer* output = createPrinter(opts, new ShortDescPrinter(cout)); - - // Generate the results - generate(opts, *output, 50, DEFAULT_QUALITY_CUTOFF); - - return success_if_had_output(output); - } - // dumpavail - // Output the full package database, with all the extra info available - else if (opts.foundCommand() == opts.dumpavail) - { - if (printOutOptionsHelpIfNeeded(opts)) - return 1; - env().init(); - Consumer* output = createPrinter(opts, new FullRecordPrinter(cout)); - - // Generate the results - generate(opts, *output, -1, -1); - - return success_if_had_output(output); - } - // related - // List packages related to the given one - else if (opts.foundCommand() == opts.related) - { - if (printOutOptionsHelpIfNeeded(opts)) - return 1; - env().init(); - Consumer* output = createPrinter(opts, new ShortDescPrinter(cout)); - - // Generate the results - generateRelated(opts, *output, 15, DEFAULT_QUALITY_CUTOFF); - - return success_if_had_output(output); - } - // reindex - // Rebuilds indexes (requires root) - else if (opts.foundCommand() == opts.reindex) - { - warn_non_root_on_error = true; - - mode_t prev_umask = umask(022); - - int exitcode; - if (opts.out_quiet->boolValue()) - exitcode = system("update-apt-xapian-index --quiet"); - else - exitcode = system("update-apt-xapian-index"); - if (exitcode != 0) - { - stringstream str; - str << "got an exit code of " << exitcode; - throw wibble::exception::Consistency("running update-apt-xapian-index", str.str()); - } - - // TODO: if verbose, print the various data files used - - umask(prev_umask); - } - // info - // Show information about the data providers - else if (opts.foundCommand() == opts.info) - { - env().init(); - if (env().debtags().hasData()) - cout << "Debtags: enabled." << endl; - else - cout << "Debtags: disabled. To enable it, run 'debtags update' as root." << endl; - - if (env().popcon().hasData()) - cout << "Popcon: enabled." << endl; - else - cout << "Popcon: disabled. To enable it, download http://popcon.debian.org/all-popcon-results.txt.gz" << endl - << " in /var/lib/popcon/ and run 'ept-cache reindex' as root" << endl; - - if (env().popconLocal().hasData()) - cout << "Popcon local scan: enabled." << endl; - else - cout << "Popcon local scan: disabled. To enable it, install the popularity-contest package and" << endl - << " enable it to run." << endl; - - time_t xts = axi::timestamp(); - if (xts > 0) - if (xts < env().apt().timestamp()) - cout << "Xapian: enabled but not up to date. To update it, run 'update-apt-xapian-index' as root." << endl; - else - cout << "Xapian: enabled and up to date." << endl; - else - cout << "Xapian: disabled. To enable it, run 'ept-cache reindex' as root" << endl; - - // TODO: if verbose, print the various data files used - } - 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; - if (warn_non_root_on_error && getuid() != 0) - cerr << "You may need to be root to perform this operation." << endl; - return 1; - } catch (Xapian::DatabaseVersionError& e) { - cerr << "Xapian " << e.get_type() << ": " << e.get_msg(); - if (!e.get_context().empty()) - cerr << ". Context: " << e.get_context(); - cerr << endl; - cerr << endl; - cerr << "Please recreate the database by removing /var/lib/apt-xapian and running ept-cache reindex as root." << endl; - } catch (Xapian::Error& e) { - cerr << "Xapian " << e.get_type() << ": " << e.get_msg(); - if (!e.get_context().empty()) - cerr << ". Context: " << e.get_context(); - cerr << endl; - if (warn_non_root_on_error && getuid() != 0) - cerr << "You may need to be root to perform this operation." << endl; - return 1; - } -} - -#include <ept/debtags/debtags.tcc> - -// vim:set ts=4 sw=4: diff --git a/tools/filters.cc b/tools/filters.cc deleted file mode 100644 index f4f21de..0000000 --- a/tools/filters.cc +++ /dev/null @@ -1,112 +0,0 @@ -/* - * ept-cache - Commandline interface to the ept library - * - * Copyright (C) 2007 Enrico Zini <enrico@debian.org> - * - * 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 "filters.h" -#include "info.h" -#include "utils.h" - -#include <ept/apt/packagerecord.h> - -#include <wibble/regexp.h> - -using namespace std; - -namespace filter { - -And::~And() -{ - for (iterator i = begin(); i != end(); ++i) - delete *i; -} -void And::acquire_front(Base* filter) -{ - insert(begin(), filter); -} -void And::acquire(Base* filter) -{ - push_back(filter); -} -bool And::operator()(Info& info) const -{ - if (empty()) - return true; - for (const_iterator i = begin(); i != end(); ++i) - if (!(**i)(info)) - return false; - return true; -} - -Or::~Or() -{ - for (iterator i = begin(); i != end(); ++i) - delete *i; -} -void Or::acquire_front(Base* filter) -{ - insert(begin(), filter); -} -void Or::acquire(Base* filter) -{ - push_back(filter); -} -bool Or::operator()(Info& info) const -{ - if (empty()) - return true; - for (const_iterator i = begin(); i != end(); ++i) - if ((**i)(info)) - return true; - return false; -} - -Description::Description(const std::string& str) -{ - wibble::Tokenizer tok(str, "[^[:blank:]]+", REG_EXTENDED); - for (wibble::Tokenizer::const_iterator i = tok.begin(); - i != tok.end(); ++i) - keywords.push_back(toLower(*i)); -} - -bool Description::operator()(Info& info) const -{ - info.wantRecord(); - string name = toLower(info.name); - string desc = toLower(info.record->description()); - for (std::vector<std::string>::const_iterator i = keywords.begin(); - i != keywords.end(); ++i) - if (name.find(*i) == string::npos && desc.find(*i) == string::npos) - return false; - return true; -} - -bool TagExpression::operator()(Info& info) const -{ - info.wantTags(); - return expr(info.tags); -} - -bool Blacklist::operator()(Info& info) const -{ - return blacklist.find(info.name) == blacklist.end(); -} - -} - -// vim:set ts=4 sw=4: diff --git a/tools/filters.h b/tools/filters.h deleted file mode 100644 index 050172a..0000000 --- a/tools/filters.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * ept-cache - Commandline interface to the ept library - * - * Copyright (C) 2007 Enrico Zini <enrico@debian.org> - * - * 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 EPTCACHE_FILTERS_H -#define EPTCACHE_FILTERS_H - -#include <vector> -#include <string> - -#include <tagcoll/expression.h> - -/* - * * For packages - * - * Filters: - * - keyword search - * - tag expression - * - min/max popularity - * - installed status - * - */ - -class Info; - -namespace filter { - -/// Interface for package filters -struct Base -{ - virtual ~Base() {} - virtual bool operator()(Info& i) const = 0; -}; - -/// ANDs a list of filters, with short-circuit semantics -struct And : public std::vector<Base*>, public Base -{ - virtual ~And(); - // Add a filter at the beginning of the list - void acquire_front(Base* filter); - // Add a filter at the end of the list - void acquire(Base* filter); - // Match the info if all filters match - virtual bool operator()(Info& info) const; -}; - -/// ORs a list of filters, with short-circuit semantics -struct Or : public std::vector<Base*>, public Base -{ - virtual ~Or(); - // Add a filter at the beginning of the list - void acquire_front(Base* filter); - // Add a filter at the end of the list - void acquire(Base* filter); - // Match the info if one of the filters match - virtual bool operator()(Info& info) const; -}; - -/// Negates a filter -struct Not : public Base -{ - Base* filter; - Not(Base* filter) : filter(filter) {} - virtual ~Not() { if (filter) delete filter; } - virtual bool operator()(Info& info) const - { - return ! (*filter)(info); - } -}; - -/// Text search on package name and description -struct Description : public Base -{ - std::vector<std::string> keywords; - - // Split up the string in keywords and lowercase them - Description(const std::string& str); - - // Assume split up, lowercased keywords - Description(const std::vector<std::string>& keywords) : keywords(keywords) {} - - virtual bool operator()(Info& info) const; -}; - -// Debtags expression filter -struct TagExpression : public Base -{ - tagcoll::Expression expr; - - TagExpression(const std::string& expr) : expr(expr) {} - TagExpression(const tagcoll::Expression& expr) : expr(expr) {} - - virtual bool operator()(Info& info) const; -}; - -// Blacklist filter -struct Blacklist : public Base -{ - std::set<std::string> blacklist; - - Blacklist(const std::set<std::string>& blacklist) : blacklist(blacklist) {} - - virtual bool operator()(Info& info) const; -}; - -} - -#endif -// vim:set ts=4 sw=4: diff --git a/tools/info.cc b/tools/info.cc deleted file mode 100644 index 2f7ba3e..0000000 --- a/tools/info.cc +++ /dev/null @@ -1,126 +0,0 @@ -/* - * ept-cache - Commandline interface to the ept library - * - * Copyright (C) 2007--2010 Enrico Zini <enrico@debian.org> - * - * 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 "info.h" - -#include "Environment.h" - -#include <ept/apt/apt.h> -#include <ept/apt/packagerecord.h> -#include <ept/debtags/debtags.h> -#include <ept/popcon/popcon.h> -#include <ept/popcon/local.h> - -using namespace std; -using namespace ept; -using namespace ept::debtags; -using namespace ept::apt; - -Info::Info(const std::string& name) - : name(name), has_xapian(false), xapian_score(100), deallocate_record(false), record(0), has_tags(false), has_popcon(false), has_local(false) {} - -Info::~Info() -{ - if (deallocate_record && record) - delete record; -} - -Info::Info(const Info& i) - : name(i.name), has_xapian(i.has_xapian), xapian_score(i.xapian_score), - has_tags(i.has_tags), tags(i.tags), has_popcon(i.has_popcon), - popcon(i.popcon), has_local(i.has_local), tfidf(i.tfidf) -{ - if (i.record) - { - deallocate_record = true; - record = new PackageRecord(*i.record); - } else { - deallocate_record = false; - record = 0; - } -} - -Info::Info& Info::operator=(const Info& i) -{ - name = i.name; - has_xapian = i.has_xapian; - xapian_score = i.xapian_score; - has_tags = i.has_tags; - tags = i.tags; - has_popcon = i.has_popcon; - popcon = i.popcon; - has_local = i.has_local; - tfidf = i.tfidf; - - if (i.record) - { - PackageRecord* newrec = new PackageRecord(*i.record); - if (record && deallocate_record) - delete record; - deallocate_record = true; - record = newrec; - } else { - if (record && deallocate_record) - delete record; - deallocate_record = false; - record = 0; - } - return *this; -} - -void Info::wantRecord() -{ - if (record) return; - record = new PackageRecord(env().apt().rawRecord(name)); - deallocate_record = true; -} - -void Info::wantTags() -{ - if (has_tags) return; - tags = env().debtags().getTagsOfItem(name); - if (tags.empty() && !env().debtags().hasData()) - { - wantRecord(); - set<string> stags = record->tag(); - for (set<string>::const_iterator i = stags.begin(); - i != stags.end(); ++i) - tags.insert(*i); - } - has_tags = true; -} - -void Info::wantPopcon() -{ - if (has_popcon) return; - popcon = env().popcon().score(name); - has_popcon = true; -} - -void Info::wantPopconLocal() -{ - if (has_local) return; - tfidf = env().popconLocal().tfidf(env().popcon(), name); - has_local = true; -} - -#include <ept/debtags/debtags.tcc> - -// vim:set ts=4 sw=4: diff --git a/tools/info.h b/tools/info.h deleted file mode 100644 index 7fe6d0b..0000000 --- a/tools/info.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * ept-cache - Commandline interface to the ept library - * - * Copyright (C) 2007--2010 Enrico Zini <enrico@debian.org> - * - * 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 EPTCACHE_INFO_H -#define EPTCACHE_INFO_H - -#include <string> -#include <set> - -namespace ept { -namespace apt { -class PackageRecord; -} -} - -/** - * Information about a package. - * - * This allows to have a stream of: - * \l names - * \l package records - * \l tags - * \l popcon scores - * \l xapian scores - * - * All optional and only retrieved on demand - */ -struct Info -{ - std::string name; - - // This is only available if the info stream is generated by a Xapian - // search. Therefore there is no wantXapian() method. - bool has_xapian; - int xapian_score; - - bool deallocate_record; - ept::apt::PackageRecord* record; - - bool has_tags; - std::set<std::string> tags; - - bool has_popcon; - float popcon; - - bool has_local; - float tfidf; - - Info(const std::string& name); - Info(const Info& i); - ~Info(); - - Info& operator=(const Info& i); - - void wantRecord(); - void wantTags(); - void wantPopcon(); - void wantPopconLocal(); -}; - -#endif -// vim:set ts=4 sw=4: diff --git a/tools/manpage.cc b/tools/manpage.cc deleted file mode 100644 index e4909ce..0000000 --- a/tools/manpage.cc +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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 <ept/config.h> -#include <wibble/commandline/doc.h> -#include "EptCacheOptions.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 == "ept-cache") - { - wibble::commandline::EptCacheOptions opts; - wibble::commandline::Manpage help("ept-cache", VERSION, 1, "enrico@enricozini.org"); - 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: ept-cache" << endl; - return 1; - } catch (std::exception& e) { - cerr << e.what() << endl; - return 1; - } -} - -#include <ept/debtags/debtags.tcc> - -// vim:set ts=4 sw=4: diff --git a/tools/utils.h b/tools/utils.h deleted file mode 100644 index d0e7034..0000000 --- a/tools/utils.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * ept-cache - Commandline interface to the ept library - * - * Copyright (C) 2007 Enrico Zini <enrico@debian.org> - * - * 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 EPTCACHE_UTILS_H -#define EPTCACHE_UTILS_H - -#include <string> -#include <ostream> - -#include <wibble/singleton.h> -#include <wibble/empty.h> - -namespace std { - -// Facilities for outputting a tag set -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; - else - out << ", " << *i; - return out; -} - -// Facilities for outputting a wibble::Singleton -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; -} - -// Facilities for outputting a wibble::Empty -template<typename TAG, typename _Traits> -basic_ostream<char, _Traits>& operator<<(basic_ostream<char, _Traits>& out, const wibble::Empty<TAG>&) -{ - return out; -} - -} - -// Convert a string to lower case -static inline std::string toLower(const std::string& s) -{ - std::string res; - for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) - res += tolower(*i); - return res; -} - -#endif -// vim:set ts=4 sw=4: |