2
* Copyright (C) 2010 Canonical Ltd
4
* This program is free software: you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License version 3 as
6
* published by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
* Authored by Mikkel Kamstrup Erlandsen <mikkel.kamstrup@canonical.com>
21
* This file contains C bindings written in C++ to hook up with the
22
* Xapian indexes generated by Ubuntu Software Center and apt-xapian.
23
* It also hooks up to Apt's cache via libapt-pkg to check whether or not
24
* packages are installed.
26
* In the future we may be able to drop the depency on libapt-pkg if the Xapian
27
* indexes include some installation metadata.
32
#include <apt-pkg/pkgcachegen.h>
33
#include <apt-pkg/cachefile.h>
34
#include <apt-pkg/cacheiterators.h>
35
#include <apt-pkg/progress.h>
36
#include <apt-pkg/init.h>
41
#define SOFTWARE_CENTER_INDEX "/var/cache/software-center/xapian"
42
#define AXI_INDEX "/var/lib/apt-xapian-index/index"
43
#define QUERY_PARSER_FLAGS Xapian::QueryParser::FLAG_BOOLEAN|Xapian::QueryParser::FLAG_PHRASE|Xapian::QueryParser::FLAG_LOVEHATE|Xapian::QueryParser::FLAG_WILDCARD
45
// values used in the database
46
#define XAPIAN_VALUE_APPNAME 170
47
#define XAPIAN_VALUE_PKGNAME 171
48
#define XAPIAN_VALUE_ICON 172
49
#define XAPIAN_VALUE_GETTEXT_DOMAIN 173
50
#define XAPIAN_VALUE_ARCHIVE_SECTION 174
51
#define XAPIAN_VALUE_ARCHIVE_ARCH 175
52
#define XAPIAN_VALUE_POPCON 176
53
#define XAPIAN_VALUE_SUMMARY 177
54
#define XAPIAN_VALUE_ARCHIVE_CHANNEL 178
55
#define XAPIAN_VALUE_DESKTOP_FILE 179
59
struct _UnityPackageSearcher
63
Xapian::Enquire *enquire;
64
Xapian::QueryParser *query_parser;
68
unity_package_searcher_new ()
70
UnityPackageSearcher *searcher;
72
searcher = g_new0 (UnityPackageSearcher, 1);
74
// Xapian initialization
76
// Load the Xapian database
77
Xapian::Database *sc_db = new Xapian::Database (SOFTWARE_CENTER_INDEX);
78
Xapian::Database *axi_db = new Xapian::Database (AXI_INDEX);
79
sc_db->add_database (*axi_db);
83
// Start an enquire session
84
Xapian::Enquire *enquire = new Xapian::Enquire (*sc_db);
85
searcher->enquire = enquire;
87
// Create query parser
88
Xapian::QueryParser *query_parser = new Xapian::QueryParser ();
89
query_parser->add_prefix ("section", "AE");
90
query_parser->add_prefix ("type", "AT");
91
query_parser->add_prefix ("category", "AC");
92
query_parser->add_prefix ("name", "AA");
93
query_parser->add_prefix ("pkgname", "AP");
94
query_parser->set_default_op (Xapian::Query::OP_AND);
95
query_parser->set_database (*sc_db);
96
searcher->query_parser = query_parser;
97
} catch(const Xapian::Error &error) {
98
cerr << "Error loading package indexes: " << error.get_msg() << endl;
102
// AptPkg initialization
103
// FIXME: We should avoid calling the pkgInit* functions more than once
104
pkgInitConfig(*_config);
105
pkgInitSystem(*_config, _system);
109
OpTextProgress progress;
111
bool res = pkgMakeStatusCache(list, progress, &map, true);
113
pkgCache *cache = new pkgCache (map);
114
searcher->cache = cache;
120
unity_package_searcher_free (UnityPackageSearcher *searcher)
122
g_return_if_fail (searcher != NULL);
125
delete searcher->enquire;
126
delete searcher->query_parser;
127
delete searcher->cache;
131
UnityPackageSearchResult*
132
unity_package_searcher_search (UnityPackageSearcher *searcher,
133
const gchar *search_string)
135
UnityPackageSearchResult* result;
137
g_return_val_if_fail (searcher != NULL, NULL);
138
g_return_val_if_fail (search_string != NULL, NULL);
140
string _search_string (search_string);
141
Xapian::Query query = searcher->query_parser->parse_query (_search_string, QUERY_PARSER_FLAGS);
142
cout << "Performing query `" << query.get_description() << "'" << endl;
145
searcher->enquire->set_query(query);
146
Xapian::MSet matches =
147
searcher->enquire->get_mset(0, searcher->db->get_doccount ());
149
// Retrieve the results, note that we build the result->results
150
// list in reverse order and then reverse it before we return it
151
result = g_slice_new0 (UnityPackageSearchResult);
152
result->num_hits = matches.get_matches_estimated ();
153
for (Xapian::MSetIterator i = matches.begin();
157
UnityPackageInfo *pkginfo = g_slice_new0 (UnityPackageInfo);
158
Xapian::Document doc = i.get_document();
160
string pkgname = doc.get_value (XAPIAN_VALUE_PKGNAME);
161
pkginfo->package_name = g_strdup (pkgname.c_str ());
164
pkgCache::PkgIterator pkg = searcher->cache->FindPkg(pkgname);
166
if (!pkg.end() && pkg->CurrentState == pkgCache::State::Installed)
167
pkginfo->installed = TRUE;
169
pkginfo->installed = FALSE;
172
pkginfo->installed = FALSE;
174
string appname = doc.get_value (XAPIAN_VALUE_APPNAME);
175
pkginfo->application_name = g_strdup (appname.c_str ());
177
string desktop_file = doc.get_value (XAPIAN_VALUE_DESKTOP_FILE);
178
pkginfo->desktop_file = g_strdup (desktop_file.c_str ());
180
result->results = g_slist_prepend (result->results, pkginfo);
183
result->results = g_slist_reverse (result->results);
188
static void _free_package_info (gpointer pkg, gpointer data)
190
UnityPackageInfo pkginfo = (UnityPackageInfo*) pkg;
192
g_free (pkginfo->package_name);
193
g_free (pkginfo->application_name);
194
g_free (pkginfo->desktop_file);
196
g_slice_free (UnityPackageInfo, pkg);
200
unity_package_search_result_free (UnityPackageSearchResult *result)
202
g_return_if_fail (result != NULL);
204
g_slist_foreach (result->results, _free_package_info, NULL);
205
g_slist_free (result->results);
206
g_slice_free (UnityPackageSearchResult, result);