Merge lp:~jpakkane/unity-lens-applications/columbustestintegration into lp:unity-lens-applications
- columbustestintegration
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Paweł Stołowski | ||||
Approved revision: | 335 | ||||
Merged at revision: | 326 | ||||
Proposed branch: | lp:~jpakkane/unity-lens-applications/columbustestintegration | ||||
Merge into: | lp:unity-lens-applications | ||||
Diff against target: |
451 lines (+210/-42) 6 files modified
configure.ac (+2/-1) debian/control (+1/-0) src/Makefile.am (+2/-2) src/unity-package-search.cc (+162/-38) tests/manual/fuzzy-search-test.txt (+42/-0) tests/unit/Makefile.am (+1/-1) |
||||
To merge this branch: | bzr merge lp:~jpakkane/unity-lens-applications/columbustestintegration | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Paweł Stołowski (community) | Approve | ||
Review via email: mp+150007@code.launchpad.net |
Commit message
Add libcolumbus fuzzy matching.
Description of the change
Add libcolumbus fuzzy matching.
Jussi Pakkanen (jpakkane) wrote : | # |
The query string is of the type "xapian keyword stuff AND query text". If the query text is empty, the AND part is missing and strstr returns NULL. This is a Xapian keyword only search and thus we pass it to Xapian.
I renamed the variable so it is now clearer. Will contact didrocks about the changelog soon.
Jussi Pakkanen (jpakkane) wrote : | # |
All issues have been fixed. The correct way to populate the changelog is to use bugs and link them. This has now been done.
However libcolumbus is currently in universe so let's not merge this until it gets to main.
Michael Terry (mterry) wrote : | # |
libcolumbus's MIR is approved (bug 1122269). It's just waiting for something in main to depend on it before it gets promoted. If you want to be the first, go ahead and land this.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
- 334. By Jussi Pakkanen
-
Bump required libcolumbus version.
- 335. By Jussi Pakkanen
-
Add libcolumbus flags to test subdirectory too.
Preview Diff
1 | === modified file 'configure.ac' |
2 | --- configure.ac 2013-02-15 10:11:07 +0000 |
3 | +++ configure.ac 2013-03-01 15:43:20 +0000 |
4 | @@ -14,7 +14,7 @@ |
5 | ############################################# |
6 | # Init the other things we depend on |
7 | ############################################# |
8 | -AM_MAINTAINER_MODE |
9 | +AM_MAINTAINER_MODE([enable]) |
10 | AM_PROG_VALAC([0.18.0]) |
11 | AS_IF([test -z "$VALAC"], [AC_MSG_ERROR(["No valac compiler found."])]) |
12 | AC_PROG_CC |
13 | @@ -75,6 +75,7 @@ |
14 | gee-1.0 |
15 | dee-1.0 >= 0.5.16 |
16 | zeitgeist-1.0 >= 0.3.8 |
17 | + libcolumbus0 >= 0.4.0 |
18 | unity >= 6.7.0 |
19 | libgnome-menu-3.0 >= 3.6.0) |
20 | |
21 | |
22 | === modified file 'debian/control' |
23 | --- debian/control 2012-11-08 04:49:06 +0000 |
24 | +++ debian/control 2013-03-01 15:43:20 +0000 |
25 | @@ -16,6 +16,7 @@ |
26 | libxapian-dev, |
27 | libdb-dev, |
28 | libapt-pkg-dev, |
29 | + libcolumbus0-dev, |
30 | Standards-Version: 3.9.3 |
31 | Homepage: https://launchpad.net/unity-lens-applications |
32 | # If you aren't a member of ~unity-team but need to upload packaging changes, |
33 | |
34 | === modified file 'src/Makefile.am' |
35 | --- src/Makefile.am 2013-02-20 15:31:37 +0000 |
36 | +++ src/Makefile.am 2013-03-01 15:43:20 +0000 |
37 | @@ -1,7 +1,7 @@ |
38 | NULL = |
39 | BUILT_SOURCES = |
40 | CLEANFILES = |
41 | -EXTRA_DIST = |
42 | +EXTRA_DIST = |
43 | |
44 | DATADIR = $(datadir) |
45 | |
46 | @@ -75,7 +75,7 @@ |
47 | $(NULL) |
48 | |
49 | unity-package-search.o : $(srcdir)/unity-package-search.cc $(srcdir)/unity-package-search.h |
50 | - $(AM_V_GEN)$(CXX) $(COVERAGE_CFLAGS) -g $(unity_package_search_libs) -DGMENU_I_KNOW_THIS_IS_UNSTABLE `pkg-config --cflags --libs glib-2.0 libgnome-menu-3.0 unity gee-1.0` -c $(srcdir)/unity-package-search.cc |
51 | + $(AM_V_GEN)$(CXX) --std=c++11 $(COVERAGE_CFLAGS) -g $(unity_package_search_libs) -DGMENU_I_KNOW_THIS_IS_UNSTABLE `pkg-config --cflags --libs glib-2.0 libgnome-menu-3.0 unity gee-1.0 libcolumbus0` -c $(srcdir)/unity-package-search.cc |
52 | |
53 | unity-ratings-db.o : $(srcdir)/unity-ratings-db.c $(srcdir)/unity-ratings-db.h |
54 | $(AM_V_CC)$(CC) -g $(COVERAGE_CFLAGS) $(unity_ratings_db_libs) `pkg-config --cflags --libs glib-2.0` -c $(srcdir)/unity-ratings-db.c |
55 | |
56 | === modified file 'src/unity-package-search.cc' |
57 | --- src/unity-package-search.cc 2012-11-05 19:18:41 +0000 |
58 | +++ src/unity-package-search.cc 2013-03-01 15:43:20 +0000 |
59 | @@ -25,14 +25,15 @@ |
60 | * Xapian index of the menu contents. |
61 | */ |
62 | |
63 | -using namespace std; |
64 | - |
65 | #include <xapian.h> |
66 | #include <iostream> |
67 | #include <gmenu-tree.h> |
68 | #include <glib.h> |
69 | #include <unity.h> |
70 | #include <string.h> |
71 | +#include <vector> |
72 | + |
73 | +using namespace std; |
74 | |
75 | #define SOFTWARE_CENTER_INDEX "/var/cache/software-center/xapian" |
76 | #define QUERY_PARSER_EXACTSEARCH_FLAGS Xapian::QueryParser::FLAG_BOOLEAN|Xapian::QueryParser::FLAG_PHRASE|Xapian::QueryParser::FLAG_LOVEHATE |
77 | @@ -55,14 +56,11 @@ |
78 | #define XAPIAN_VALUE_SCREENSHOT_URLS 185 |
79 | #define XAPIAN_VALUE_DESCRIPTION 188 |
80 | #define XAPIAN_VALUE_VERSION_INFO 198 |
81 | +#define XAPIAN_VALUE_EXENAME 294 |
82 | #define XAPIAN_VALUE_CURRENCY 201 |
83 | |
84 | #include "unity-package-search.h" |
85 | - |
86 | -extern "C" |
87 | -{ |
88 | - extern gchar* unity_applications_lens_utils_preprocess_string (const gchar* input); |
89 | -} |
90 | +#include "columbus.hh" |
91 | |
92 | struct _UnityPackageSearcher |
93 | { |
94 | @@ -71,8 +69,58 @@ |
95 | Xapian::Enquire *enquire; |
96 | Xapian::QueryParser *query_parser; |
97 | GRand *random; |
98 | + Columbus::Matcher *matcher; |
99 | + vector<string> col_mapping; |
100 | + bool db_merged; |
101 | }; |
102 | |
103 | +static void buildMatcher(UnityPackageSearcher *searcher) { |
104 | + Columbus::Matcher *m = searcher->matcher; |
105 | + Xapian::Database *db = searcher->db; |
106 | + Columbus::Corpus c; |
107 | + Columbus::Word appnameField("appname"); |
108 | + Columbus::Word summaryField("summary"); |
109 | + Columbus::Word pkgnameField("pkgname"); |
110 | + Columbus::Word exenameField("exename"); |
111 | + |
112 | + for(Xapian::PostingIterator post = db->postlist_begin(""); post != db->postlist_end(""); post++) { |
113 | + Xapian::Document xdoc = db->get_document(*post); |
114 | + DocumentID id; |
115 | + if(searcher->db_merged) { |
116 | + searcher->col_mapping.push_back(xdoc.get_value(XAPIAN_VALUE_APPNAME)); |
117 | + id = searcher->col_mapping.size()-1; |
118 | + } else { |
119 | + id = xdoc.get_docid(); |
120 | + } |
121 | + Columbus::Document cdoc(id); |
122 | + std::string val; |
123 | + |
124 | + val = xdoc.get_value(XAPIAN_VALUE_APPNAME); |
125 | + if(!val.empty()) |
126 | + cdoc.addText(appnameField, val.c_str()); |
127 | + val = xdoc.get_value(XAPIAN_VALUE_SUMMARY); |
128 | + if(!val.empty()) |
129 | + cdoc.addText(summaryField, val.c_str()); |
130 | + val = xdoc.get_value(XAPIAN_VALUE_PKGNAME); |
131 | + if(!val.empty()) |
132 | + cdoc.addText(pkgnameField, val.c_str()); |
133 | + val = xdoc.get_value(XAPIAN_VALUE_EXENAME); |
134 | + if(!val.empty()) |
135 | + cdoc.addText(exenameField, val.c_str()); |
136 | + c.addDocument(cdoc); |
137 | + } |
138 | + m->index(c); |
139 | + m->getErrorValues().addStandardErrors(); |
140 | + m->getErrorValues().setSubstringMode(); |
141 | + m->getIndexWeights().setWeight(summaryField, 0.5); |
142 | +} |
143 | + |
144 | + |
145 | +extern "C" |
146 | +{ |
147 | + extern gchar* unity_applications_lens_utils_preprocess_string (const gchar* input); |
148 | +} |
149 | + |
150 | /* A Xapian::Sorter that respects the collation rules for the current locale */ |
151 | class LocaleKeyMaker : public Xapian::KeyMaker |
152 | { |
153 | @@ -264,6 +312,7 @@ |
154 | dum2 = strstr (dum1, " "); // const |
155 | dum2 == NULL ? : *dum2 = '\0'; // const |
156 | dum2 = g_path_get_basename (dum1); // alloc |
157 | + doc.add_value(XAPIAN_VALUE_EXENAME, dum2); |
158 | indexer->index_text (dum2, 2); |
159 | g_free (dum1); |
160 | dum1 = g_strdelimit (dum2, "-", '_'); // in place switch, dum1 own mem |
161 | @@ -299,7 +348,7 @@ |
162 | UnityPackageSearcher *searcher; |
163 | Xapian::WritableDatabase *db; |
164 | |
165 | - searcher = g_new0 (UnityPackageSearcher, 1); |
166 | + searcher = new UnityPackageSearcher; |
167 | db = new Xapian::WritableDatabase (); |
168 | searcher->db = db; |
169 | searcher->db->add_database (Xapian::InMemory::open ()); |
170 | @@ -307,11 +356,15 @@ |
171 | init_searcher (searcher); |
172 | |
173 | /* Index the menu recursively */ |
174 | + searcher->db_merged = false; |
175 | Xapian::TermGenerator *indexer = new Xapian::TermGenerator (); |
176 | index_menu_item (db, indexer, gmenu_tree_get_root_directory (menu)); |
177 | delete indexer; |
178 | db->flush (); |
179 | |
180 | + searcher->matcher = new Columbus::Matcher(); |
181 | + buildMatcher(searcher); |
182 | + |
183 | return searcher; |
184 | } |
185 | |
186 | @@ -323,7 +376,7 @@ |
187 | UnityPackageSearcher *searcher; |
188 | gchar *agent = NULL; |
189 | |
190 | - searcher = g_new0 (UnityPackageSearcher, 1); |
191 | + searcher = new UnityPackageSearcher; |
192 | |
193 | // Xapian initialization |
194 | try |
195 | @@ -351,6 +404,9 @@ |
196 | } |
197 | |
198 | init_searcher (searcher); |
199 | + searcher->db_merged = true; |
200 | + searcher->matcher = new Columbus::Matcher(); |
201 | + buildMatcher(searcher); |
202 | |
203 | return searcher; |
204 | } |
205 | @@ -364,8 +420,9 @@ |
206 | delete searcher->sorter; |
207 | delete searcher->enquire; |
208 | delete searcher->query_parser; |
209 | + delete searcher->matcher; |
210 | g_rand_free (searcher->random); |
211 | - g_free (searcher); |
212 | + delete searcher; |
213 | } |
214 | |
215 | static UnityPackageInfo* |
216 | @@ -425,20 +482,37 @@ |
217 | g_slice_free (UnityPackageInfo, pkginfo); |
218 | } |
219 | |
220 | -UnityPackageSearchResult* |
221 | -unity_package_searcher_search (UnityPackageSearcher *searcher, |
222 | - const gchar *search_string, |
223 | - guint max_hits, |
224 | - UnityPackageSearchType search_type, |
225 | - UnityPackageSort sort) |
226 | +Xapian::Document get_doc_from_col_match(UnityPackageSearcher *searcher, DocumentID id) { |
227 | + if(searcher->db_merged) { |
228 | + string name = searcher->col_mapping[id]; |
229 | + string query = "AA\""; |
230 | + query += name; |
231 | + query += "\""; |
232 | + Xapian::QueryParser p; |
233 | + Xapian::Query q; |
234 | + Xapian::Enquire e(*searcher->db); |
235 | + Xapian::MSet matches; |
236 | + p.set_database(*searcher->db); |
237 | + q = p.parse_query(query); |
238 | + e.set_query(q); |
239 | + matches = e.get_mset(0, 1); |
240 | + return matches.begin().get_document(); |
241 | + } else { |
242 | + return searcher->db->get_document(id); |
243 | + } |
244 | +} |
245 | + |
246 | +static UnityPackageSearchResult* |
247 | +xapian_search (UnityPackageSearcher *searcher, |
248 | + const gchar *search_string, |
249 | + guint max_hits, |
250 | + UnityPackageSearchType search_type, |
251 | + UnityPackageSort sort) |
252 | { |
253 | UnityPackageSearchResult* result; |
254 | - |
255 | - g_return_val_if_fail (searcher != NULL, NULL); |
256 | - g_return_val_if_fail (search_string != NULL, NULL); |
257 | - |
258 | string _search_string (search_string); |
259 | Xapian::Query query; |
260 | + |
261 | try |
262 | { |
263 | switch (search_type) |
264 | @@ -455,12 +529,11 @@ |
265 | break; |
266 | } |
267 | } |
268 | - catch (Xapian::Error e) |
269 | + catch (Xapian::Error &e) |
270 | { |
271 | g_warning ("Error parsing query '%s': %s", search_string, e.get_msg().c_str()); |
272 | return g_slice_new0 (UnityPackageSearchResult); |
273 | } |
274 | - //cout << "Performing query `" << query.get_description() << "'" << endl; |
275 | |
276 | switch (sort) |
277 | { |
278 | @@ -488,24 +561,26 @@ |
279 | // Retrieve the results, note that we build the result->results |
280 | // list in reverse order and then reverse it before we return it |
281 | result->num_hits = matches.get_matches_estimated (); |
282 | + |
283 | for (Xapian::MSetIterator i = matches.begin(); i != matches.end(); ++i) |
284 | - { |
285 | - try |
286 | - { |
287 | - Xapian::Document doc = i.get_document(); |
288 | - UnityPackageInfo *pkginfo = _pkginfo_from_document (doc); |
289 | - pkginfo->relevancy = i.get_percent (); |
290 | - result->results = g_slist_prepend (result->results, pkginfo); |
291 | - } |
292 | - catch (Xapian::Error e) |
293 | - { |
294 | - g_warning ("Unable to read document from result set: %s", e.get_msg().c_str()); |
295 | - } |
296 | - } |
297 | + { |
298 | + try |
299 | + { |
300 | + Xapian::Document doc = i.get_document(); |
301 | + UnityPackageInfo *pkginfo = _pkginfo_from_document (doc); |
302 | + pkginfo->relevancy = i.get_percent(); |
303 | + result->results = g_slist_prepend (result->results, pkginfo); |
304 | + } |
305 | + catch (Xapian::Error &e) |
306 | + { |
307 | + g_warning ("Unable to read document from result set: %s", |
308 | + e.get_msg().c_str()); |
309 | + } |
310 | + } |
311 | |
312 | result->results = g_slist_reverse (result->results); |
313 | } |
314 | - catch(const Xapian::Error e) |
315 | + catch(const Xapian::Error &e) |
316 | { |
317 | g_warning ("Error running query '%s': %s", search_string, e.get_msg().c_str()); |
318 | } |
319 | @@ -513,6 +588,55 @@ |
320 | return result; |
321 | } |
322 | |
323 | +static UnityPackageSearchResult* |
324 | +libcolumbus_search(UnityPackageSearcher *searcher, const char *str) { |
325 | + Columbus::MatchResults results; |
326 | + UnityPackageSearchResult* result; |
327 | + |
328 | + result = g_slice_new0 (UnityPackageSearchResult); |
329 | + searcher->matcher->match(str, results); |
330 | + for (size_t i = 0; i < results.size(); ++i) |
331 | + { |
332 | + try |
333 | + { |
334 | + Xapian::Document doc = get_doc_from_col_match(searcher, results.getDocumentID(i)); |
335 | + UnityPackageInfo *pkginfo = _pkginfo_from_document (doc); |
336 | + pkginfo->relevancy = results.getRelevancy(i); |
337 | + result->results = g_slist_prepend (result->results, pkginfo); |
338 | + } |
339 | + catch (Xapian::Error &e) |
340 | + { |
341 | + g_warning ("Unable to read document from result set: %s", |
342 | + e.get_msg().c_str()); |
343 | + } |
344 | + } |
345 | + |
346 | + result->results = g_slist_reverse (result->results); |
347 | + return result; |
348 | +} |
349 | + |
350 | +UnityPackageSearchResult* |
351 | +unity_package_searcher_search (UnityPackageSearcher *searcher, |
352 | + const gchar *search_string, |
353 | + guint max_hits, |
354 | + UnityPackageSearchType search_type, |
355 | + UnityPackageSort sort) |
356 | +{ |
357 | + |
358 | + g_return_val_if_fail (searcher != NULL, NULL); |
359 | + g_return_val_if_fail (search_string != NULL, NULL); |
360 | + |
361 | + bool has_category = strstr(search_string, "category:") != NULL; |
362 | + const char *col_query_str = strstr(search_string, "AND"); |
363 | + if(has_category || !col_query_str) { |
364 | + return xapian_search(searcher, search_string, max_hits, search_type, sort); |
365 | + } else { |
366 | + col_query_str += 3; |
367 | + return libcolumbus_search(searcher, col_query_str); |
368 | + } |
369 | +} |
370 | + |
371 | + |
372 | /** |
373 | * Get applications matching given xapian filter query and additionally filter results out |
374 | * using AppFilterCallback, until n_apps matching apps are found. |
375 | @@ -618,7 +742,7 @@ |
376 | n_unique++; |
377 | } |
378 | } |
379 | - catch (Xapian::Error e) |
380 | + catch (Xapian::Error &e) |
381 | { |
382 | g_warning ("Error getting random apps: %s", e.get_msg().c_str()); |
383 | continue; |
384 | @@ -653,7 +777,7 @@ |
385 | } |
386 | } |
387 | } |
388 | - catch (Xapian::Error e) |
389 | + catch (Xapian::Error &e) |
390 | { |
391 | g_debug ("Error getting random apps for query '%s': %s", filter_query, e.get_msg().c_str()); |
392 | return g_slice_new0 (UnityPackageSearchResult); |
393 | |
394 | === added file 'tests/manual/fuzzy-search-test.txt' |
395 | --- tests/manual/fuzzy-search-test.txt 1970-01-01 00:00:00 +0000 |
396 | +++ tests/manual/fuzzy-search-test.txt 2013-03-01 15:43:20 +0000 |
397 | @@ -0,0 +1,42 @@ |
398 | +Fuzzy searching in the Dash |
399 | +--------------------------- |
400 | + |
401 | +Tests that fuzzy matching works in the Dash. |
402 | + |
403 | +Actions: |
404 | + |
405 | +Tap super. |
406 | +Enter an application name that is slightly misspelled. Check that the Dash. |
407 | +returns valid replies. |
408 | + |
409 | +Examples: |
410 | + |
411 | + fimp -> Gimp |
412 | + fierfox -> Firefox |
413 | + sttings -> settings |
414 | + |
415 | +Fuzzy searching in the app lens |
416 | +------------------------------- |
417 | + |
418 | +Tests that fuzzy matching works in the app lens. |
419 | + |
420 | +Actions: |
421 | + |
422 | +Tap super. |
423 | +Select app lens. |
424 | +Do the same searches as in the previous test. Check that they return the |
425 | +same results. |
426 | + |
427 | + |
428 | +Searching with filters |
429 | +---------------------- |
430 | + |
431 | +When filters are enabled, the search falls back to non-fuzzy mode. |
432 | + |
433 | +Actions: |
434 | + |
435 | +Tap super. |
436 | +Select app lens. |
437 | +Enable filters, activate "graphics". |
438 | +Type "fimp" in search field, Gimp should not be show in the results. |
439 | +Type "gimp" in search field, Gimp should be shown in the results. |
440 | |
441 | === modified file 'tests/unit/Makefile.am' |
442 | --- tests/unit/Makefile.am 2013-02-20 16:09:23 +0000 |
443 | +++ tests/unit/Makefile.am 2013-03-01 15:43:20 +0000 |
444 | @@ -106,7 +106,7 @@ |
445 | nodist_test_software_center_details_SOURCES = $(test_software_center_details_VALASOURCES:.vala=.c) |
446 | |
447 | unity-package-search.o : $(top_srcdir)/src/unity-package-search.cc $(top_srcdir)/src/unity-package-search.h |
448 | - $(AM_V_GEN)$(CXX) -g $(COVERAGE_CFLAGS) $(UNITY_PACKAGE_SEARCH_LIBS) -DGMENU_I_KNOW_THIS_IS_UNSTABLE `pkg-config --cflags --libs glib-2.0 libgnome-menu-3.0 unity gee-1.0` -c $(top_srcdir)/src/unity-package-search.cc |
449 | + $(AM_V_GEN)$(CXX) --std=c++11 -g $(COVERAGE_CFLAGS) $(UNITY_PACKAGE_SEARCH_LIBS) -DGMENU_I_KNOW_THIS_IS_UNSTABLE `pkg-config --cflags --libs glib-2.0 libgnome-menu-3.0 unity gee-1.0 libcolumbus0` -c $(top_srcdir)/src/unity-package-search.cc |
450 | unity-ratings-db.o : $(top_srcdir)/src/unity-ratings-db.c $(top_srcdir)/src/unity-ratings-db.h |
451 | $(AM_V_CC)$(CC) -g $(COVERAGE_CFLAGS) $(unity_ratings_db_libs) `pkg-config --cflags --libs glib-2.0` -c $(top_srcdir)/src/unity-ratings-db.c |
452 |
325 + //cout << "Columbus matched " << results.size() << " documents." << endl;
Please remove.
357 + bool has_category = strstr( search_ string, "category:") != NULL; search_ string, "AND");
358 + const char *tmp = strstr(
359 + if(has_category || !tmp) {
Could you rename tmp? Shouldn't it actually say "tmp", not "!tmp" (we want complex queries to be handled by xapian search and only simple queries to be routed to columbus, right?). I don't quite understand what case we are trying to cover here and why - can you add a comment to this code?
Could you also add a manual tests to tests/manual/? Ideally it should fail completly if exectued on old app lens (without columbus); the test should cover cases with and without category filters.
Please check with didrocks if debian/changelog needs updating after chaning control.