Merge lp:~stolowski/unity-scope-click/populate-departments-db into lp:unity-scope-click/devel
- populate-departments-db
- Merge into devel
Status: | Merged |
---|---|
Approved by: | Alejandro J. Cura |
Approved revision: | 326 |
Merged at revision: | 334 |
Proposed branch: | lp:~stolowski/unity-scope-click/populate-departments-db |
Merge into: | lp:unity-scope-click/devel |
Prerequisite: | lp:~stolowski/unity-scope-click/departments-db |
Diff against target: |
1444 lines (+616/-69) 26 files modified
CMakeLists.txt (+1/-0) libclickscope/click/departments-db.cpp (+51/-1) libclickscope/click/departments-db.h (+20/-13) libclickscope/click/departments.cpp (+2/-1) libclickscope/click/departments.h (+1/-0) libclickscope/click/interface.h (+1/-0) libclickscope/click/package.cpp (+9/-0) libclickscope/click/package.h (+2/-0) libclickscope/click/preview.cpp (+64/-20) libclickscope/click/preview.h (+26/-8) libclickscope/tests/CMakeLists.txt (+2/-1) libclickscope/tests/fake_json.cpp (+9/-2) libclickscope/tests/test_departments.cpp (+3/-3) libclickscope/tests/test_index.cpp (+4/-2) scope/clickapps/apps-scope.cpp (+1/-1) scope/clickstore/CMakeLists.txt (+2/-1) scope/clickstore/store-query.cpp (+31/-1) scope/clickstore/store-query.h (+3/-1) scope/clickstore/store-scope.cpp (+12/-2) scope/clickstore/store-scope.h (+2/-0) scope/tests/CMakeLists.txt (+3/-2) scope/tests/test_query.cpp (+61/-10) tools/CMakeLists.txt (+1/-0) tools/init-departments/CMakeLists.txt (+19/-0) tools/init-departments/README (+10/-0) tools/init-departments/init-departments.cpp (+276/-0) |
To merge this branch: | bzr merge lp:~stolowski/unity-scope-click/populate-departments-db |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alejandro J. Cura (community) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Review via email: mp+225434@code.launchpad.net |
Commit message
Populate departments database in the store scope. Use slugs for unique department ids when parsing. Implemented a tool that initializes or updates departments db.
Description of the change
Populate departments database in the store scope. Use slugs for unique department ids when parsing.
Implemented a tool that queries for locally installed packages, calls ubuntu store server for them and creates a sqlite db file with departments and package - department mapping data that will later be used by click apps scope.
Usage:
init-departments DBFILE LOCALE1 [LOCALE2 ...]
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:316
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:317
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:318
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
deb: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:319
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:320
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:322
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:323
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 325. By Paweł Stołowski
-
Merged departments init tool.
- 326. By Paweł Stołowski
-
Updated README.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:325
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:326
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alejandro J. Cura (alecu) wrote : | # |
Code looks good. I tested the debs from this and the following branches on the device, and it works beautifully.
One comment is that I would like to see tests for the init-departments tool, since it will be used to build images, and any problems there will lead to broken images. I propose to open a bug for that, and to work on such tests in an upcoming branch.
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2014-07-11 14:46:09 +0000 |
3 | +++ CMakeLists.txt 2014-07-15 14:51:22 +0000 |
4 | @@ -54,6 +54,7 @@ |
5 | add_subdirectory(scope) |
6 | add_subdirectory(data) |
7 | add_subdirectory(po) |
8 | +add_subdirectory(tools) |
9 | |
10 | include(EnableCoverageReport) # Using gcov CMake modules from https://code.cor-lab.org/projects/rsc |
11 | ##################################################################### |
12 | |
13 | === modified file 'libclickscope/click/departments-db.cpp' |
14 | --- libclickscope/click/departments-db.cpp 2014-07-02 13:18:32 +0000 |
15 | +++ libclickscope/click/departments-db.cpp 2014-07-15 14:51:22 +0000 |
16 | @@ -45,7 +45,7 @@ |
17 | if (!path.isEmpty()) |
18 | { |
19 | QDir("/").mkpath(path); |
20 | - const std::string dbpath = path.toStdString() + "/clickscope/click-departments.db"; |
21 | + const std::string dbpath = path.toStdString() + "/click-departments.db"; |
22 | return std::unique_ptr<DepartmentsDb>(new DepartmentsDb(dbpath)); |
23 | } |
24 | throw std::runtime_error("Cannot determine cache directory"); |
25 | @@ -56,6 +56,8 @@ |
26 | init_db(name); |
27 | |
28 | delete_pkgmap_query_.reset(new QSqlQuery(db_)); |
29 | + delete_depts_query_.reset(new QSqlQuery(db_)); |
30 | + delete_deptnames_query_.reset(new QSqlQuery(db_)); |
31 | insert_pkgmap_query_.reset(new QSqlQuery(db_)); |
32 | insert_dept_id_query_.reset(new QSqlQuery(db_)); |
33 | insert_dept_name_query_.reset(new QSqlQuery(db_)); |
34 | @@ -66,6 +68,8 @@ |
35 | select_dept_name_.reset(new QSqlQuery(db_)); |
36 | |
37 | delete_pkgmap_query_->prepare("DELETE FROM pkgmap WHERE pkgid=:pkgid"); |
38 | + delete_depts_query_->prepare("DELETE FROM depts"); |
39 | + delete_deptnames_query_->prepare("DELETE FROM deptnames WHERE locale=:locale"); |
40 | insert_pkgmap_query_->prepare("INSERT OR REPLACE INTO pkgmap (pkgid, deptid) VALUES (:pkgid, :deptid)"); |
41 | insert_dept_id_query_->prepare("INSERT OR REPLACE INTO depts (deptid, parentid) VALUES (:deptid, :parentid)"); |
42 | insert_dept_name_query_->prepare("INSERT OR REPLACE INTO deptnames (deptid, locale, name) VALUES (:deptid, :locale, :name)"); |
43 | @@ -76,6 +80,10 @@ |
44 | select_dept_name_->prepare("SELECT name FROM deptnames WHERE deptid=:deptid AND locale=:locale"); |
45 | } |
46 | |
47 | +DepartmentsDb::~DepartmentsDb() |
48 | +{ |
49 | +} |
50 | + |
51 | void DepartmentsDb::init_db(const std::string& name) |
52 | { |
53 | db_ = QSqlDatabase::addDatabase("QSQLITE"); |
54 | @@ -308,4 +316,46 @@ |
55 | return q.value(0).toInt(); |
56 | } |
57 | |
58 | +void DepartmentsDb::store_departments_(const click::DepartmentList& depts, const std::string& locale) |
59 | +{ |
60 | + for (auto const& dept: depts) |
61 | + { |
62 | + store_department_name(dept->id(), locale, dept->name()); |
63 | + for (auto const& subdep: dept->sub_departments()) |
64 | + { |
65 | + store_department_mapping(subdep->id(), dept->id()); |
66 | + } |
67 | + store_departments_(dept->sub_departments(), locale); |
68 | + } |
69 | +} |
70 | + |
71 | +void DepartmentsDb::store_departments(const click::DepartmentList& depts, const std::string& locale) |
72 | +{ |
73 | + if (!db_.transaction()) |
74 | + { |
75 | + std::cerr << "Failed to start transaction" << std::endl; |
76 | + } |
77 | + |
78 | + // |
79 | + // delete existing departments for given locale first |
80 | + delete_deptnames_query_->bindValue(":locale", QVariant(QString::fromStdString(locale))); |
81 | + if (!delete_deptnames_query_->exec()) |
82 | + { |
83 | + db_.rollback(); |
84 | + report_db_error(delete_deptnames_query_->lastError(), "Failed to delete from deptnames"); |
85 | + } |
86 | + if (!delete_depts_query_->exec()) |
87 | + { |
88 | + db_.rollback(); |
89 | + report_db_error(delete_depts_query_->lastError(), "Failed to delete from depts"); |
90 | + } |
91 | + |
92 | + store_departments_(depts, locale); |
93 | + |
94 | + if (!db_.commit()) |
95 | + { |
96 | + std::cerr << "Failed to commit transaction" << std::endl; |
97 | + } |
98 | +} |
99 | + |
100 | } |
101 | |
102 | === modified file 'libclickscope/click/departments-db.h' |
103 | --- libclickscope/click/departments-db.h 2014-07-02 13:14:36 +0000 |
104 | +++ libclickscope/click/departments-db.h 2014-07-15 14:51:22 +0000 |
105 | @@ -30,6 +30,7 @@ |
106 | #ifndef CLICK_DEPARTMENTS_DB_H |
107 | #define CLICK_DEPARTMENTS_DB_H |
108 | |
109 | +#include <click/departments.h> |
110 | #include <string> |
111 | #include <set> |
112 | #include <unordered_set> |
113 | @@ -43,7 +44,7 @@ |
114 | namespace click |
115 | { |
116 | |
117 | -class DepartmentsDb final |
118 | +class DepartmentsDb |
119 | { |
120 | public: |
121 | struct DepartmentInfo |
122 | @@ -61,29 +62,35 @@ |
123 | DepartmentsDb(const std::string& name); |
124 | DepartmentsDb(const DepartmentsDb& other) = delete; |
125 | DepartmentsDb& operator=(const DepartmentsDb&) = delete; |
126 | - |
127 | - std::string get_department_name(const std::string& department_id, const std::list<std::string>& locales); |
128 | - std::unordered_set<std::string> get_packages_for_department(const std::string& department_id, bool recursive = true); |
129 | - std::string get_parent_department_id(const std::string& department_id); |
130 | - std::list<DepartmentInfo> get_children_departments(const std::string& department_id); |
131 | - |
132 | - void store_package_mapping(const std::string& package_id, const std::string& department_id); |
133 | - void store_department_mapping(const std::string& department_id, const std::string& parent_department_id); |
134 | - void store_department_name(const std::string& department_id, const std::string& locale, const std::string& name); |
135 | + virtual ~DepartmentsDb(); |
136 | + |
137 | + virtual std::string get_department_name(const std::string& department_id, const std::list<std::string>& locales); |
138 | + virtual std::unordered_set<std::string> get_packages_for_department(const std::string& department_id, bool recursive = true); |
139 | + virtual std::string get_parent_department_id(const std::string& department_id); |
140 | + virtual std::list<DepartmentInfo> get_children_departments(const std::string& department_id); |
141 | + |
142 | + virtual void store_package_mapping(const std::string& package_id, const std::string& department_id); |
143 | + virtual void store_department_mapping(const std::string& department_id, const std::string& parent_department_id); |
144 | + virtual void store_department_name(const std::string& department_id, const std::string& locale, const std::string& name); |
145 | |
146 | // these methods are mostly for tests |
147 | - int department_mapping_count() const; |
148 | - int package_count() const; |
149 | - int department_name_count() const; |
150 | + virtual int department_mapping_count() const; |
151 | + virtual int package_count() const; |
152 | + virtual int department_name_count() const; |
153 | + |
154 | + void store_departments(const click::DepartmentList& depts, const std::string& locale); |
155 | |
156 | static std::unique_ptr<DepartmentsDb> create_db(); |
157 | |
158 | private: |
159 | void init_db(const std::string& name); |
160 | + void store_departments_(const click::DepartmentList& depts, const std::string& locale); |
161 | static void report_db_error(const QSqlError& error, const std::string& message); |
162 | |
163 | QSqlDatabase db_; |
164 | std::unique_ptr<QSqlQuery> delete_pkgmap_query_; |
165 | + std::unique_ptr<QSqlQuery> delete_depts_query_; |
166 | + std::unique_ptr<QSqlQuery> delete_deptnames_query_; |
167 | std::unique_ptr<QSqlQuery> insert_pkgmap_query_; |
168 | std::unique_ptr<QSqlQuery> insert_dept_id_query_; |
169 | std::unique_ptr<QSqlQuery> insert_dept_name_query_; |
170 | |
171 | === modified file 'libclickscope/click/departments.cpp' |
172 | --- libclickscope/click/departments.cpp 2014-06-23 10:12:52 +0000 |
173 | +++ libclickscope/click/departments.cpp 2014-07-15 14:51:22 +0000 |
174 | @@ -93,6 +93,7 @@ |
175 | { |
176 | auto const item = node[i]; |
177 | |
178 | + auto slug = check_mandatory_attribute(item, Department::JsonKeys::slug, Json::ValueType::stringValue).asString(); |
179 | auto name = check_mandatory_attribute(item, Department::JsonKeys::name, Json::ValueType::stringValue).asString(); |
180 | const bool has_children = item.isMember(Department::JsonKeys::has_children) ? item[Department::JsonKeys::has_children].asBool() : false; |
181 | |
182 | @@ -100,7 +101,7 @@ |
183 | auto const self = check_mandatory_attribute(links, Department::JsonKeys::self, Json::ValueType::objectValue); |
184 | auto const href = check_mandatory_attribute(self, Department::JsonKeys::href, Json::ValueType::stringValue).asString(); |
185 | |
186 | - auto dep = std::make_shared<Department>(name, name, href, has_children); //FIXME: id |
187 | + auto dep = std::make_shared<Department>(slug, name, href, has_children); |
188 | if (item.isObject() && item.isMember(Department::JsonKeys::embedded)) |
189 | { |
190 | auto const emb = item[Department::JsonKeys::embedded]; |
191 | |
192 | === modified file 'libclickscope/click/departments.h' |
193 | --- libclickscope/click/departments.h 2014-06-23 10:12:52 +0000 |
194 | +++ libclickscope/click/departments.h 2014-07-15 14:51:22 +0000 |
195 | @@ -47,6 +47,7 @@ |
196 | struct JsonKeys |
197 | { |
198 | JsonKeys() = delete; |
199 | + constexpr static const char* slug {"slug"}; |
200 | constexpr static const char* name {"name"}; |
201 | constexpr static const char* embedded {"_embedded"}; |
202 | constexpr static const char* department {"clickindex:department"}; |
203 | |
204 | === modified file 'libclickscope/click/interface.h' |
205 | --- libclickscope/click/interface.h 2014-06-16 15:38:49 +0000 |
206 | +++ libclickscope/click/interface.h 2014-07-15 14:51:22 +0000 |
207 | @@ -75,6 +75,7 @@ |
208 | |
209 | ManifestList manifest_list_from_json(const std::string& json); |
210 | Manifest manifest_from_json(const std::string& json); |
211 | +PackageSet package_names_from_stdout(const std::string& stdout_data); |
212 | |
213 | class Interface |
214 | { |
215 | |
216 | === modified file 'libclickscope/click/package.cpp' |
217 | --- libclickscope/click/package.cpp 2014-06-26 17:31:28 +0000 |
218 | +++ libclickscope/click/package.cpp 2014-07-15 14:51:22 +0000 |
219 | @@ -126,6 +126,15 @@ |
220 | details.download_url = root[JsonKeys::download_url].asString(); |
221 | details.license = root[JsonKeys::license].asString(); |
222 | |
223 | + if (root[JsonKeys::department].isArray()) |
224 | + { |
225 | + auto const dept_array = root[JsonKeys::department]; |
226 | + if (dept_array.size() > 0) |
227 | + { |
228 | + details.department = dept_array[dept_array.size() - 1].asString(); |
229 | + } |
230 | + } |
231 | + |
232 | // Optional details go here. |
233 | if (root[JsonKeys::version].isString()) |
234 | details.version = root[JsonKeys::version].asString(); |
235 | |
236 | === modified file 'libclickscope/click/package.h' |
237 | --- libclickscope/click/package.h 2014-06-26 17:31:28 +0000 |
238 | +++ libclickscope/click/package.h 2014-07-15 14:51:22 +0000 |
239 | @@ -126,6 +126,7 @@ |
240 | constexpr static const char* terms_of_service{"terms_of_service"}; |
241 | constexpr static const char* license{"license"}; |
242 | constexpr static const char* publisher{"publisher"}; |
243 | + constexpr static const char* department{"department"}; |
244 | constexpr static const char* main_screenshot_url{"screenshot_url"}; |
245 | constexpr static const char* more_screenshot_urls{"screenshot_urls"}; |
246 | constexpr static const char* binary_filesize{"binary_filesize"}; |
247 | @@ -149,6 +150,7 @@ |
248 | json::Value::UInt64 binary_filesize; |
249 | std::string version; |
250 | std::string framework; |
251 | + std::string department; |
252 | }; |
253 | |
254 | std::ostream& operator<<(std::ostream& out, const PackageDetails& details); |
255 | |
256 | === modified file 'libclickscope/click/preview.cpp' |
257 | --- libclickscope/click/preview.cpp 2014-07-11 08:31:53 +0000 |
258 | +++ libclickscope/click/preview.cpp 2014-07-15 14:51:22 +0000 |
259 | @@ -34,6 +34,7 @@ |
260 | #include <click/download-manager.h> |
261 | #include <click/launcher.h> |
262 | #include <click/dbus_constants.h> |
263 | +#include <click/departments-db.h> |
264 | |
265 | #include <boost/algorithm/string/replace.hpp> |
266 | |
267 | @@ -53,21 +54,56 @@ |
268 | |
269 | namespace click { |
270 | |
271 | +DepartmentUpdater::DepartmentUpdater(const std::shared_ptr<click::DepartmentsDb>& depts) |
272 | + : depts(depts) |
273 | +{ |
274 | +} |
275 | + |
276 | +void DepartmentUpdater::store_department(const PackageDetails& details) |
277 | +{ |
278 | + // |
279 | + // store package -> department mapping in sqlite db |
280 | + if (depts) |
281 | + { |
282 | + if (!details.department.empty()) |
283 | + { |
284 | + try |
285 | + { |
286 | + depts->store_package_mapping(details.package.name, details.department); |
287 | + qDebug() << "Storing mapping for" << QString::fromStdString(details.package.name) << ":" << QString::fromStdString(details.department); |
288 | + } |
289 | + catch (const std::exception& e) |
290 | + { |
291 | + qWarning() << "Failed to store package mapping for package '" |
292 | + << QString::fromStdString(details.package.name) |
293 | + << "', department '" << QString::fromStdString(details.department) |
294 | + << "':" << QString::fromStdString(e.what()); |
295 | + } |
296 | + } |
297 | + else |
298 | + { |
299 | + qWarning() << "Department is empty for package" << QString::fromStdString(details.package.name); |
300 | + } |
301 | + } |
302 | +} |
303 | + |
304 | // Preview base class |
305 | |
306 | Preview::Preview(const unity::scopes::Result& result, |
307 | const unity::scopes::ActionMetadata& metadata, |
308 | const QSharedPointer<click::web::Client>& client, |
309 | - const QSharedPointer<click::network::AccessManager>& nam) |
310 | + const QSharedPointer<click::network::AccessManager>& nam, |
311 | + std::shared_ptr<click::DepartmentsDb> depts) |
312 | : PreviewQueryBase(result, metadata) |
313 | { |
314 | - strategy.reset(choose_strategy(result, metadata, client, nam)); |
315 | + strategy.reset(choose_strategy(result, metadata, client, nam, depts)); |
316 | } |
317 | |
318 | PreviewStrategy* Preview::choose_strategy(const unity::scopes::Result &result, |
319 | const unity::scopes::ActionMetadata &metadata, |
320 | const QSharedPointer<web::Client> &client, |
321 | - const QSharedPointer<click::network::AccessManager>& nam) |
322 | + const QSharedPointer<click::network::AccessManager>& nam, |
323 | + std::shared_ptr<click::DepartmentsDb> depts) |
324 | { |
325 | if (metadata.scope_data().which() != scopes::Variant::Type::Null) { |
326 | auto metadict = metadata.scope_data().get_dict(); |
327 | @@ -81,26 +117,26 @@ |
328 | << " and close_preview=" |
329 | << metadict.count(click::Preview::Actions::CLOSE_PREVIEW); |
330 | |
331 | - return new InstalledPreview(result, metadata, client); |
332 | + return new InstalledPreview(result, metadata, client, depts); |
333 | } else if (metadict.count("action_id") != 0 && metadict.count("download_url") != 0) { |
334 | std::string action_id = metadict["action_id"].get_string(); |
335 | std::string download_url = metadict["download_url"].get_string(); |
336 | if (action_id == click::Preview::Actions::INSTALL_CLICK) { |
337 | - return new InstallingPreview(download_url, result, client, nam); |
338 | + return new InstallingPreview(download_url, result, client, nam, depts); |
339 | } else { |
340 | qWarning() << "unexpected action id " << QString::fromStdString(action_id) |
341 | << " given with download_url" << QString::fromStdString(download_url); |
342 | - return new UninstalledPreview(result, client); |
343 | + return new UninstalledPreview(result, client, depts); |
344 | } |
345 | } else if (metadict.count(click::Preview::Actions::UNINSTALL_CLICK) != 0) { |
346 | return new UninstallConfirmationPreview(result); |
347 | } else if (metadict.count(click::Preview::Actions::CONFIRM_UNINSTALL) != 0) { |
348 | return new UninstallingPreview(result, client); |
349 | } else if (metadict.count(click::Preview::Actions::RATED) != 0) { |
350 | - return new InstalledPreview(result, metadata, client); |
351 | + return new InstalledPreview(result, metadata, client, depts); |
352 | } else { |
353 | qWarning() << "preview() called with unexpected metadata. returning uninstalled preview"; |
354 | - return new UninstalledPreview(result, client); |
355 | + return new UninstalledPreview(result, client, depts); |
356 | } |
357 | } else { |
358 | // metadata.scope_data() is Null, so we return an appropriate "default" preview: |
359 | @@ -109,9 +145,9 @@ |
360 | return new InstalledScopePreview(result); |
361 | } |
362 | if (result["installed"].get_bool() == true) { |
363 | - return new InstalledPreview(result, metadata, client); |
364 | + return new InstalledPreview(result, metadata, client, depts); |
365 | } else { |
366 | - return new UninstalledPreview(result, client); |
367 | + return new UninstalledPreview(result, client, depts); |
368 | } |
369 | } |
370 | |
371 | @@ -340,15 +376,17 @@ |
372 | reply->push(downloadErrorWidgets()); |
373 | } |
374 | |
375 | - |
376 | // class InstallingPreview |
377 | |
378 | InstallingPreview::InstallingPreview(const std::string &download_url, |
379 | const unity::scopes::Result &result, |
380 | const QSharedPointer<click::web::Client>& client, |
381 | - const QSharedPointer<click::network::AccessManager> &nam) |
382 | - : PreviewStrategy(result, client), download_url(download_url), |
383 | - downloader(new click::Downloader(nam)) |
384 | + const QSharedPointer<click::network::AccessManager> &nam, |
385 | + std::shared_ptr<click::DepartmentsDb> depts) |
386 | + : PreviewStrategy(result, client), DepartmentUpdater(depts), |
387 | + download_url(download_url), |
388 | + downloader(new click::Downloader(nam)), |
389 | + depts_db(depts) |
390 | { |
391 | } |
392 | |
393 | @@ -383,7 +421,8 @@ |
394 | default: |
395 | std::string object_path = rc.first; |
396 | qDebug() << "Successfully created UDM Download."; |
397 | - populateDetails([this, reply, object_path](const PackageDetails &details){ |
398 | + populateDetails([this, reply, object_path](const PackageDetails &details) { |
399 | + store_department(details); |
400 | reply->push(headerWidgets(details)); |
401 | reply->push(progressBarWidget(object_path)); |
402 | reply->push(descriptionWidgets(details)); |
403 | @@ -416,13 +455,14 @@ |
404 | return widgets; |
405 | } |
406 | |
407 | - |
408 | // class InstalledPreview |
409 | |
410 | InstalledPreview::InstalledPreview(const unity::scopes::Result& result, |
411 | const unity::scopes::ActionMetadata& metadata, |
412 | - const QSharedPointer<click::web::Client>& client) |
413 | + const QSharedPointer<click::web::Client>& client, |
414 | + const std::shared_ptr<click::DepartmentsDb>& depts) |
415 | : PreviewStrategy(result, client), |
416 | + DepartmentUpdater(depts), |
417 | metadata(metadata) |
418 | { |
419 | } |
420 | @@ -485,6 +525,7 @@ |
421 | } |
422 | getApplicationUri(manifest, [this, reply, manifest, app_name, &review](const std::string& uri) { |
423 | populateDetails([this, reply, uri, manifest, app_name, &review](const PackageDetails &details){ |
424 | + store_department(details); |
425 | reply->push(headerWidgets(details)); |
426 | reply->push(createButtons(uri, manifest)); |
427 | reply->push(descriptionWidgets(details)); |
428 | @@ -685,8 +726,10 @@ |
429 | // class UninstalledPreview |
430 | |
431 | UninstalledPreview::UninstalledPreview(const unity::scopes::Result& result, |
432 | - const QSharedPointer<click::web::Client>& client) |
433 | - : PreviewStrategy(result, client) |
434 | + const QSharedPointer<click::web::Client>& client, |
435 | + const std::shared_ptr<click::DepartmentsDb>& depts) |
436 | + : PreviewStrategy(result, client), |
437 | + DepartmentUpdater(depts) |
438 | { |
439 | } |
440 | |
441 | @@ -699,6 +742,7 @@ |
442 | qDebug() << "in UninstalledPreview::run, about to populate details"; |
443 | |
444 | populateDetails([this, reply](const PackageDetails &details){ |
445 | + store_department(details); |
446 | reply->push(headerWidgets(details)); |
447 | reply->push(uninstalledActionButtonWidgets(details)); |
448 | reply->push(descriptionWidgets(details)); |
449 | @@ -748,7 +792,7 @@ |
450 | // TODO: this class should be removed once uninstall() is handled elsewhere. |
451 | UninstallingPreview::UninstallingPreview(const unity::scopes::Result& result, |
452 | const QSharedPointer<click::web::Client>& client) |
453 | - : UninstalledPreview(result, client) |
454 | + : UninstalledPreview(result, client, nullptr) |
455 | { |
456 | } |
457 | UninstallingPreview::~UninstallingPreview() |
458 | |
459 | === modified file 'libclickscope/click/preview.h' |
460 | --- libclickscope/click/preview.h 2014-06-18 04:39:23 +0000 |
461 | +++ libclickscope/click/preview.h 2014-07-15 14:51:22 +0000 |
462 | @@ -49,6 +49,18 @@ |
463 | |
464 | class Manifest; |
465 | class PreviewStrategy; |
466 | +class DepartmentsDb; |
467 | + |
468 | +class DepartmentUpdater |
469 | +{ |
470 | +protected: |
471 | + DepartmentUpdater(const std::shared_ptr<click::DepartmentsDb>& depts); |
472 | + virtual ~DepartmentUpdater() = default; |
473 | + void store_department(const PackageDetails& pkg); |
474 | + |
475 | +private: |
476 | + std::shared_ptr<click::DepartmentsDb> depts; |
477 | +}; |
478 | |
479 | class Preview : public unity::scopes::PreviewQueryBase |
480 | { |
481 | @@ -57,7 +69,8 @@ |
482 | PreviewStrategy* choose_strategy(const unity::scopes::Result& result, |
483 | const unity::scopes::ActionMetadata& metadata, |
484 | const QSharedPointer<web::Client> &client, |
485 | - const QSharedPointer<click::network::AccessManager>& nam); |
486 | + const QSharedPointer<click::network::AccessManager>& nam, |
487 | + std::shared_ptr<click::DepartmentsDb> depts); |
488 | public: |
489 | struct Actions |
490 | { |
491 | @@ -82,7 +95,8 @@ |
492 | Preview(const unity::scopes::Result& result, |
493 | const unity::scopes::ActionMetadata& metadata, |
494 | const QSharedPointer<click::web::Client>& client, |
495 | - const QSharedPointer<click::network::AccessManager>& nam); |
496 | + const QSharedPointer<click::network::AccessManager>& nam, |
497 | + std::shared_ptr<click::DepartmentsDb> depts); |
498 | // From unity::scopes::PreviewQuery |
499 | void cancelled() override; |
500 | virtual void run(unity::scopes::PreviewReplyProxy const& reply) override; |
501 | @@ -134,13 +148,14 @@ |
502 | void run(unity::scopes::PreviewReplyProxy const& reply) override; |
503 | }; |
504 | |
505 | -class InstallingPreview : public PreviewStrategy |
506 | +class InstallingPreview : public PreviewStrategy, public DepartmentUpdater |
507 | { |
508 | public: |
509 | InstallingPreview(std::string const& download_url, |
510 | const unity::scopes::Result& result, |
511 | const QSharedPointer<click::web::Client>& client, |
512 | - const QSharedPointer<click::network::AccessManager>& nam); |
513 | + const QSharedPointer<click::network::AccessManager>& nam, |
514 | + std::shared_ptr<click::DepartmentsDb> depts); |
515 | |
516 | virtual ~InstallingPreview(); |
517 | |
518 | @@ -150,15 +165,17 @@ |
519 | virtual scopes::PreviewWidgetList progressBarWidget(const std::string& object_path); |
520 | std::string download_url; |
521 | QSharedPointer<click::Downloader> downloader; |
522 | + std::shared_ptr<click::DepartmentsDb> depts_db; |
523 | void startLauncherAnimation(const PackageDetails& details); |
524 | }; |
525 | |
526 | -class InstalledPreview : public PreviewStrategy |
527 | +class InstalledPreview : public PreviewStrategy, public DepartmentUpdater |
528 | { |
529 | public: |
530 | InstalledPreview(const unity::scopes::Result& result, |
531 | const unity::scopes::ActionMetadata& metadata, |
532 | - const QSharedPointer<click::web::Client>& client); |
533 | + const QSharedPointer<click::web::Client>& client, |
534 | + const std::shared_ptr<click::DepartmentsDb>& depts); |
535 | |
536 | virtual ~InstalledPreview(); |
537 | |
538 | @@ -204,11 +221,12 @@ |
539 | |
540 | }; |
541 | |
542 | -class UninstalledPreview : public PreviewStrategy |
543 | +class UninstalledPreview : public PreviewStrategy, public DepartmentUpdater |
544 | { |
545 | public: |
546 | UninstalledPreview(const unity::scopes::Result& result, |
547 | - const QSharedPointer<click::web::Client>& client); |
548 | + const QSharedPointer<click::web::Client>& client, |
549 | + const std::shared_ptr<click::DepartmentsDb>& depts); |
550 | |
551 | virtual ~UninstalledPreview(); |
552 | |
553 | |
554 | === modified file 'libclickscope/tests/CMakeLists.txt' |
555 | --- libclickscope/tests/CMakeLists.txt 2014-07-11 21:56:59 +0000 |
556 | +++ libclickscope/tests/CMakeLists.txt 2014-07-15 14:51:22 +0000 |
557 | @@ -26,7 +26,6 @@ |
558 | test_bootstrap.cpp |
559 | test_configuration.cpp |
560 | test_departments.cpp |
561 | - test_departments-db.cpp |
562 | test_download_manager.cpp |
563 | test_index.cpp |
564 | test_interface.cpp |
565 | @@ -34,6 +33,8 @@ |
566 | test_reviews.cpp |
567 | test_smartconnect.cpp |
568 | test_webclient.cpp |
569 | + test_departments.cpp |
570 | + test_departments-db.cpp |
571 | |
572 | ${CMAKE_CURRENT_BINARY_DIR}/test_data.cpp |
573 | ) |
574 | |
575 | === modified file 'libclickscope/tests/fake_json.cpp' |
576 | --- libclickscope/tests/fake_json.cpp 2014-07-11 09:15:22 +0000 |
577 | +++ libclickscope/tests/fake_json.cpp 2014-07-15 14:51:22 +0000 |
578 | @@ -412,6 +412,7 @@ |
579 | "clickindex:department": [ |
580 | { |
581 | "name": "Games", |
582 | + "slug": "games", |
583 | "_links": { |
584 | "self": { |
585 | "href": "https://search.apps.ubuntu.com/api/v1/departments/Games" |
586 | @@ -421,6 +422,7 @@ |
587 | "clickindex:department": [ |
588 | { |
589 | "name": "Board Games", |
590 | + "slug": "board_games", |
591 | "_links": { |
592 | "self": { |
593 | "href": "https://search.apps.ubuntu.com/api/v1/departments/Games/Board+Games" |
594 | @@ -432,6 +434,7 @@ |
595 | }, |
596 | { |
597 | "name": "Graphics", |
598 | + "slug": "graphics", |
599 | "_links": { |
600 | "self": { |
601 | "href": "https://search.apps.ubuntu.com/api/v1/departments/Graphics" |
602 | @@ -441,6 +444,7 @@ |
603 | "clickindex:department": [ |
604 | { |
605 | "name": "Drawing", |
606 | + "slug": "graphics_drawing", |
607 | "_links": { |
608 | "self": { |
609 | "href": "https://search.apps.ubuntu.com/api/v1/departments/Graphics/Drawing" |
610 | @@ -452,6 +456,7 @@ |
611 | }, |
612 | { |
613 | "name": "Internet", |
614 | + "slug": "internet", |
615 | "_links": { |
616 | "self": { |
617 | "href": "https://search.apps.ubuntu.com/api/v1/departments/Internet" |
618 | @@ -461,6 +466,7 @@ |
619 | "clickindex:department": [ |
620 | { |
621 | "name": "Chat", |
622 | + "slug": "internet_chat", |
623 | "_links": { |
624 | "self": { |
625 | "href": "https://search.apps.ubuntu.com/api/v1/departments/Internet/Chat" |
626 | @@ -469,6 +475,7 @@ |
627 | }, |
628 | { |
629 | "name": "Mail", |
630 | + "slug": "internet_mail", |
631 | "_links": { |
632 | "self": { |
633 | "href": "https://search.apps.ubuntu.com/api/v1/departments/Internet/Mail" |
634 | @@ -477,6 +484,7 @@ |
635 | }, |
636 | { |
637 | "name": "Web Browsers", |
638 | + "slug": "internet_web", |
639 | "_links": { |
640 | "self": { |
641 | "href": "https://search.apps.ubuntu.com/api/v1/departments/Internet/Web+Browsers" |
642 | @@ -508,6 +516,7 @@ |
643 | "clickindex:department": [ |
644 | { |
645 | "name": "Games", |
646 | + "slug": "games", |
647 | "_links": { |
648 | "self": { |
649 | "href": "https://search.apps.ubuntu.com/api/v1/departments/Games" |
650 | @@ -622,5 +631,3 @@ |
651 | } |
652 | } |
653 | )foo"; |
654 | - |
655 | - |
656 | |
657 | === modified file 'libclickscope/tests/test_departments.cpp' |
658 | --- libclickscope/tests/test_departments.cpp 2014-06-23 11:33:55 +0000 |
659 | +++ libclickscope/tests/test_departments.cpp 2014-07-15 14:51:22 +0000 |
660 | @@ -40,7 +40,7 @@ |
661 | auto it = depts.cbegin(); |
662 | { |
663 | auto dep = *it; |
664 | - EXPECT_EQ("Games", dep->id()); |
665 | + EXPECT_EQ("games", dep->id()); |
666 | EXPECT_EQ("Games", dep->name()); |
667 | EXPECT_EQ("https://search.apps.ubuntu.com/api/v1/departments/Games", dep->href()); |
668 | EXPECT_FALSE(dep->has_children_flag()); |
669 | @@ -52,7 +52,7 @@ |
670 | { |
671 | ++it; |
672 | auto dep = *it; |
673 | - EXPECT_EQ("Graphics", dep->id()); |
674 | + EXPECT_EQ("graphics", dep->id()); |
675 | EXPECT_EQ("Graphics", dep->name()); |
676 | EXPECT_EQ("https://search.apps.ubuntu.com/api/v1/departments/Graphics", dep->href()); |
677 | EXPECT_FALSE(dep->has_children_flag()); |
678 | @@ -64,7 +64,7 @@ |
679 | { |
680 | ++it; |
681 | auto dep = *it; |
682 | - EXPECT_EQ("Internet", dep->id()); |
683 | + EXPECT_EQ("internet", dep->id()); |
684 | EXPECT_EQ("Internet", dep->name()); |
685 | EXPECT_EQ("https://search.apps.ubuntu.com/api/v1/departments/Internet", dep->href()); |
686 | EXPECT_FALSE(dep->has_children_flag()); |
687 | |
688 | === modified file 'libclickscope/tests/test_index.cpp' |
689 | --- libclickscope/tests/test_index.cpp 2014-06-26 18:57:08 +0000 |
690 | +++ libclickscope/tests/test_index.cpp 2014-07-15 14:51:22 +0000 |
691 | @@ -342,7 +342,8 @@ |
692 | {"sshot1", "sshot2"}, |
693 | 177582, |
694 | "0.2", |
695 | - "None" |
696 | + "None", |
697 | + "tools" |
698 | }; |
699 | EXPECT_CALL(*this, details_callback(fake_details, _)).Times(1); |
700 | response->replyFinished(); |
701 | @@ -389,7 +390,8 @@ |
702 | {"sshot1", "sshot2"}, |
703 | 177582, |
704 | "0.2", |
705 | - "None" |
706 | + "None", |
707 | + "tools" |
708 | }; |
709 | |
710 | EXPECT_CALL(*this, details_callback(fake_details, _)).Times(1); |
711 | |
712 | === modified file 'scope/clickapps/apps-scope.cpp' |
713 | --- scope/clickapps/apps-scope.cpp 2014-07-03 13:12:08 +0000 |
714 | +++ scope/clickapps/apps-scope.cpp 2014-07-15 14:51:22 +0000 |
715 | @@ -86,7 +86,7 @@ |
716 | unity::scopes::PreviewQueryBase::UPtr click::Scope::preview(const unity::scopes::Result& result, |
717 | const unity::scopes::ActionMetadata& metadata) { |
718 | qDebug() << "Scope::preview() called."; |
719 | - return scopes::PreviewQueryBase::UPtr{new click::Preview(result, metadata, client, nam)}; |
720 | + return scopes::PreviewQueryBase::UPtr{new click::Preview(result, metadata, client, nam, nullptr)}; |
721 | } |
722 | |
723 | |
724 | |
725 | === modified file 'scope/clickstore/CMakeLists.txt' |
726 | --- scope/clickstore/CMakeLists.txt 2014-06-23 15:00:28 +0000 |
727 | +++ scope/clickstore/CMakeLists.txt 2014-07-15 14:51:22 +0000 |
728 | @@ -1,6 +1,7 @@ |
729 | SET (CMAKE_INCLUDE_CURRENT_DIR ON) |
730 | SET (CMAKE_AUTOMOC ON) |
731 | find_package (Qt5Core REQUIRED) |
732 | +find_package (Qt5Sql REQUIRED) |
733 | pkg_check_modules(JSON_CPP REQUIRED jsoncpp) |
734 | |
735 | add_definitions( |
736 | @@ -19,7 +20,7 @@ |
737 | ${JSON_CPP_INCLUDE_DIRS} |
738 | ) |
739 | |
740 | -qt5_use_modules (${STORE_LIB_UNVERSIONED} Network) |
741 | +qt5_use_modules (${STORE_LIB_UNVERSIONED} Network Sql) |
742 | |
743 | target_link_libraries (${STORE_LIB_UNVERSIONED} |
744 | ${SCOPE_LIB_NAME} |
745 | |
746 | === modified file 'scope/clickstore/store-query.cpp' |
747 | --- scope/clickstore/store-query.cpp 2014-07-11 20:56:01 +0000 |
748 | +++ scope/clickstore/store-query.cpp 2014-07-15 14:51:22 +0000 |
749 | @@ -32,6 +32,7 @@ |
750 | #include "store-query.h" |
751 | #include "store-scope.h" |
752 | #include <click/qtbridge.h> |
753 | +#include <click/departments-db.h> |
754 | |
755 | #include <click/key_file_locator.h> |
756 | |
757 | @@ -114,25 +115,29 @@ |
758 | struct click::Query::Private |
759 | { |
760 | Private(click::Index& index, click::DepartmentLookup& depts, |
761 | + std::shared_ptr<click::DepartmentsDb> depts_db, |
762 | click::HighlightList& highlights, const scopes::SearchMetadata& metadata) |
763 | : index(index), |
764 | department_lookup(depts), |
765 | + depts_db(depts_db), |
766 | highlights(highlights), |
767 | meta(metadata) |
768 | { |
769 | } |
770 | click::Index& index; |
771 | click::DepartmentLookup& department_lookup; |
772 | + std::shared_ptr<click::DepartmentsDb> depts_db; |
773 | click::HighlightList& highlights; |
774 | scopes::SearchMetadata meta; |
775 | click::web::Cancellable search_operation; |
776 | }; |
777 | |
778 | click::Query::Query(unity::scopes::CannedQuery const& query, click::Index& index, click::DepartmentLookup& depts, |
779 | + std::shared_ptr<click::DepartmentsDb> depts_db, |
780 | click::HighlightList& highlights, |
781 | scopes::SearchMetadata const& metadata) |
782 | : unity::scopes::SearchQueryBase(query, metadata), |
783 | - impl(new Private(index, depts, highlights, metadata)) |
784 | + impl(new Private(index, depts, depts_db, highlights, metadata)) |
785 | { |
786 | } |
787 | |
788 | @@ -234,6 +239,21 @@ |
789 | root->set_subdepartments(departments); |
790 | } |
791 | |
792 | +// recursively store all departments in the departments database |
793 | +void click::Query::store_departments(const click::DepartmentList& depts) |
794 | +{ |
795 | + assert(impl->depts_db); |
796 | + |
797 | + try |
798 | + { |
799 | + impl->depts_db->store_departments(depts, search_metadata().locale()); |
800 | + } |
801 | + catch (const std::exception &e) |
802 | + { |
803 | + qWarning() << "Failed to update database: " << QString::fromStdString(e.what()); |
804 | + } |
805 | +} |
806 | + |
807 | void click::Query::push_package(const scopes::SearchReplyProxy& searchReply, scopes::Category::SCPtr category, const PackageSet &installedPackages, const Package& pkg) |
808 | { |
809 | qDebug() << "pushing result" << QString::fromStdString(pkg.name); |
810 | @@ -400,6 +420,16 @@ |
811 | impl->department_lookup.rebuild(rdeps); |
812 | impl->highlights = highlights; |
813 | qDebug() << "Total number of departments:" << impl->department_lookup.size() << ", highlights:" << highlights.size(); |
814 | + |
815 | + if (impl->depts_db) |
816 | + { |
817 | + qDebug() << "Storing departments in the database"; |
818 | + store_departments(deps); |
819 | + } |
820 | + else |
821 | + { |
822 | + qWarning() << "Departments db not available"; |
823 | + } |
824 | } |
825 | else |
826 | { |
827 | |
828 | === modified file 'scope/clickstore/store-query.h' |
829 | --- scope/clickstore/store-query.h 2014-06-18 09:01:20 +0000 |
830 | +++ scope/clickstore/store-query.h 2014-07-15 14:51:22 +0000 |
831 | @@ -50,6 +50,7 @@ |
832 | class Application; |
833 | class Index; |
834 | class DepartmentLookup; |
835 | +class DepartmentsDb; |
836 | |
837 | class Query : public scopes::SearchQueryBase |
838 | { |
839 | @@ -76,7 +77,7 @@ |
840 | constexpr static const char* VERSION{"version"}; |
841 | }; |
842 | |
843 | - Query(unity::scopes::CannedQuery const& query, click::Index& index, click::DepartmentLookup& dept_lookup, click::HighlightList& highlights, |
844 | + Query(unity::scopes::CannedQuery const& query, click::Index& index, click::DepartmentLookup& dept_lookup, std::shared_ptr<click::DepartmentsDb> depts_db, click::HighlightList& highlights, |
845 | scopes::SearchMetadata const& metadata); |
846 | virtual ~Query(); |
847 | |
848 | @@ -86,6 +87,7 @@ |
849 | |
850 | protected: |
851 | virtual void populate_departments(const click::DepartmentList& depts, const std::string& current_department_id, unity::scopes::Department::SPtr &root); |
852 | + virtual void store_departments(const click::DepartmentList& depts); |
853 | virtual void push_departments(const scopes::SearchReplyProxy& searchReply, const scopes::Department::SCPtr& root); |
854 | virtual void add_highlights(scopes::SearchReplyProxy const& searchReply, const PackageSet& installedPackages); |
855 | virtual void add_available_apps(const scopes::SearchReplyProxy &searchReply, const PackageSet &installedPackages, const std::string &category); |
856 | |
857 | === modified file 'scope/clickstore/store-scope.cpp' |
858 | --- scope/clickstore/store-scope.cpp 2014-06-23 15:00:28 +0000 |
859 | +++ scope/clickstore/store-scope.cpp 2014-07-15 14:51:22 +0000 |
860 | @@ -28,6 +28,7 @@ |
861 | */ |
862 | |
863 | #include <click/qtbridge.h> |
864 | +#include <click/departments-db.h> |
865 | #include <click/department-lookup.h> |
866 | #include "store-scope.h" |
867 | #include "store-query.h" |
868 | @@ -42,6 +43,7 @@ |
869 | #include <click/click-i18n.h> |
870 | |
871 | #include <logging.h> |
872 | +#include <iostream> |
873 | |
874 | bool click::Scope::old_api = false; |
875 | |
876 | @@ -52,6 +54,14 @@ |
877 | index.reset(new click::Index(client)); |
878 | depts.reset(new click::DepartmentLookup()); |
879 | highlights.reset(new click::HighlightList()); |
880 | + try |
881 | + { |
882 | + depts_db = click::DepartmentsDb::create_db(); |
883 | + } |
884 | + catch (const std::runtime_error& e) |
885 | + { |
886 | + std::cerr << "Failed to get cache directory" << std::endl; |
887 | + } |
888 | } |
889 | |
890 | click::Scope::~Scope() |
891 | @@ -94,14 +104,14 @@ |
892 | |
893 | scopes::SearchQueryBase::UPtr click::Scope::search(unity::scopes::CannedQuery const& q, scopes::SearchMetadata const& metadata) |
894 | { |
895 | - return scopes::SearchQueryBase::UPtr(new click::Query(q, *index, *depts, *highlights, metadata)); |
896 | + return scopes::SearchQueryBase::UPtr(new click::Query(q, *index, *depts, depts_db, *highlights, metadata)); |
897 | } |
898 | |
899 | |
900 | unity::scopes::PreviewQueryBase::UPtr click::Scope::preview(const unity::scopes::Result& result, |
901 | const unity::scopes::ActionMetadata& metadata) { |
902 | qDebug() << "Scope::preview() called."; |
903 | - return scopes::PreviewQueryBase::UPtr{new click::Preview(result, metadata, client, nam)}; |
904 | + return scopes::PreviewQueryBase::UPtr{new click::Preview(result, metadata, client, nam, depts_db)}; |
905 | } |
906 | |
907 | unity::scopes::ActivationQueryBase::UPtr click::Scope::perform_action(unity::scopes::Result const& result, unity::scopes::ActionMetadata const& metadata, |
908 | |
909 | === modified file 'scope/clickstore/store-scope.h' |
910 | --- scope/clickstore/store-scope.h 2014-06-18 18:07:39 +0000 |
911 | +++ scope/clickstore/store-scope.h 2014-07-15 14:51:22 +0000 |
912 | @@ -46,6 +46,7 @@ |
913 | { |
914 | |
915 | class DepartmentLookup; |
916 | +class DepartmentsDb; |
917 | |
918 | class Scope : public scopes::ScopeBase |
919 | { |
920 | @@ -73,6 +74,7 @@ |
921 | QSharedPointer<click::Index> index; |
922 | std::shared_ptr<click::DepartmentLookup> depts; |
923 | std::shared_ptr<click::HighlightList> highlights; |
924 | + std::shared_ptr<click::DepartmentsDb> depts_db; |
925 | |
926 | std::string installApplication(unity::scopes::Result const& result); |
927 | static bool old_api; |
928 | |
929 | === modified file 'scope/tests/CMakeLists.txt' |
930 | --- scope/tests/CMakeLists.txt 2014-07-03 13:12:08 +0000 |
931 | +++ scope/tests/CMakeLists.txt 2014-07-15 14:51:22 +0000 |
932 | @@ -7,6 +7,7 @@ |
933 | SET (CMAKE_AUTOMOC ON) |
934 | |
935 | find_package(Qt5Core REQUIRED) |
936 | +find_package(Qt5Sql REQUIRED) |
937 | |
938 | include_directories ( |
939 | ${CMAKE_SOURCE_DIR}/libclickscope |
940 | @@ -24,8 +25,8 @@ |
941 | test_apps_query.cpp |
942 | ) |
943 | |
944 | -qt5_use_modules(${CLICKSCOPE_TESTS_TARGET} Core DBus Network Test) |
945 | -qt5_use_modules(${APPS_SCOPE_TESTS_TARGET} Core DBus Network Test) |
946 | +qt5_use_modules(${CLICKSCOPE_TESTS_TARGET} Core DBus Network Test Sql) |
947 | +qt5_use_modules(${APPS_SCOPE_TESTS_TARGET} Core DBus Network Test Sql) |
948 | |
949 | target_link_libraries(${CLICKSCOPE_TESTS_TARGET} |
950 | ${STORE_LIB_UNVERSIONED} |
951 | |
952 | === modified file 'scope/tests/test_query.cpp' |
953 | --- scope/tests/test_query.cpp 2014-07-11 14:55:30 +0000 |
954 | +++ scope/tests/test_query.cpp 2014-07-15 14:51:22 +0000 |
955 | @@ -36,6 +36,7 @@ |
956 | #include "click/qtbridge.h" |
957 | #include "clickstore/store-query.h" |
958 | #include "click/application.h" |
959 | +#include "click/departments-db.h" |
960 | #include "test_helpers.h" |
961 | |
962 | #include <tests/mock_network_access_manager.h> |
963 | @@ -53,12 +54,27 @@ |
964 | |
965 | namespace |
966 | { |
967 | + |
968 | +class MockDepartmentsDb : public click::DepartmentsDb |
969 | +{ |
970 | +public: |
971 | + MockDepartmentsDb(const std::string& name) |
972 | + : click::DepartmentsDb(name) |
973 | + { |
974 | + } |
975 | + |
976 | + MOCK_METHOD2(store_package_mapping, void(const std::string&, const std::string&)); |
977 | + MOCK_METHOD2(store_department_mapping, void(const std::string&, const std::string&)); |
978 | + MOCK_METHOD3(store_department_name, void(const std::string&, const std::string&, const std::string&)); |
979 | +}; |
980 | + |
981 | class MockQueryBase : public click::Query { |
982 | public: |
983 | MockQueryBase(const unity::scopes::CannedQuery& query, click::Index& index, |
984 | click::DepartmentLookup& depts, |
985 | + std::shared_ptr<click::DepartmentsDb> depts_db, |
986 | click::HighlightList& highlights, |
987 | - scopes::SearchMetadata const& metadata) : click::Query(query, index, depts, highlights, metadata) |
988 | + scopes::SearchMetadata const& metadata) : click::Query(query, index, depts, depts_db, highlights, metadata) |
989 | { |
990 | |
991 | } |
992 | @@ -73,8 +89,9 @@ |
993 | public: |
994 | MockQuery(const unity::scopes::CannedQuery& query, click::Index& index, |
995 | click::DepartmentLookup& depts, |
996 | + std::shared_ptr<click::DepartmentsDb> depts_db, |
997 | click::HighlightList& highlights, |
998 | - scopes::SearchMetadata const& metadata) : MockQueryBase(query, index, depts, highlights, metadata) |
999 | + scopes::SearchMetadata const& metadata) : MockQueryBase(query, index, depts, depts_db, highlights, metadata) |
1000 | { |
1001 | |
1002 | } |
1003 | @@ -99,8 +116,9 @@ |
1004 | public: |
1005 | MockQueryRun(const unity::scopes::CannedQuery& query, click::Index& index, |
1006 | click::DepartmentLookup& depts, |
1007 | + std::shared_ptr<click::DepartmentsDb> depts_db, |
1008 | click::HighlightList& highlights, |
1009 | - scopes::SearchMetadata const& metadata) : MockQueryBase(query, index, depts, highlights, metadata) |
1010 | + scopes::SearchMetadata const& metadata) : MockQueryBase(query, index, depts, depts_db, highlights, metadata) |
1011 | { |
1012 | |
1013 | } |
1014 | @@ -123,7 +141,7 @@ |
1015 | scopes::SearchMetadata metadata("en_EN", "phone"); |
1016 | PackageSet no_installed_packages; |
1017 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1018 | - MockQuery q(query, mock_index, dept_lookup, highlights, metadata); |
1019 | + MockQuery q(query, mock_index, dept_lookup, nullptr, highlights, metadata); |
1020 | EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)).Times(1); |
1021 | |
1022 | scopes::testing::MockSearchReply mock_reply; |
1023 | @@ -148,7 +166,7 @@ |
1024 | scopes::SearchMetadata metadata("en_EN", "phone"); |
1025 | PackageSet no_installed_packages; |
1026 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1027 | - MockQuery q(query, mock_index, dept_lookup, highlights, metadata); |
1028 | + MockQuery q(query, mock_index, dept_lookup, nullptr, highlights, metadata); |
1029 | EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)); |
1030 | |
1031 | scopes::CategoryRenderer renderer("{}"); |
1032 | @@ -177,7 +195,7 @@ |
1033 | scopes::SearchMetadata metadata("en_EN", "phone"); |
1034 | PackageSet no_installed_packages; |
1035 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1036 | - MockQuery q(query, mock_index, dept_lookup, highlights, metadata); |
1037 | + MockQuery q(query, mock_index, dept_lookup, nullptr, highlights, metadata); |
1038 | EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)); |
1039 | |
1040 | scopes::CategoryRenderer renderer("{}"); |
1041 | @@ -201,7 +219,7 @@ |
1042 | scopes::SearchMetadata metadata("en_EN", "phone"); |
1043 | PackageSet no_installed_packages; |
1044 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1045 | - MockQueryRun q(query, mock_index, dept_lookup, highlights, metadata); |
1046 | + MockQueryRun q(query, mock_index, dept_lookup, nullptr, highlights, metadata); |
1047 | auto reply = scopes::SearchReplyProxy(); |
1048 | EXPECT_CALL(q, get_installed_packages()).WillOnce(Return(no_installed_packages)); |
1049 | EXPECT_CALL(q, add_available_apps(reply, no_installed_packages, _)); |
1050 | @@ -226,7 +244,7 @@ |
1051 | click::DepartmentLookup dept_lookup; |
1052 | click::HighlightList highlights; |
1053 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1054 | - MockQuery q(query, mock_index, dept_lookup, highlights, metadata); |
1055 | + MockQuery q(query, mock_index, dept_lookup, nullptr, highlights, metadata); |
1056 | EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)); |
1057 | |
1058 | scopes::CategoryRenderer renderer("{}"); |
1059 | @@ -256,7 +274,7 @@ |
1060 | click::DepartmentLookup dept_lookup; |
1061 | click::HighlightList highlights; |
1062 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1063 | - MockQuery q(query, mock_index, dept_lookup, highlights, metadata); |
1064 | + MockQuery q(query, mock_index, dept_lookup, nullptr, highlights, metadata); |
1065 | EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)); |
1066 | |
1067 | scopes::CategoryRenderer renderer("{}"); |
1068 | @@ -270,6 +288,39 @@ |
1069 | q.wrap_add_available_apps(reply, one_installed_package, FAKE_CATEGORY_TEMPLATE); |
1070 | } |
1071 | |
1072 | +TEST(QueryTest, testDepartmentsDbIsUpdated) |
1073 | +{ |
1074 | + auto dept1 = std::make_shared<click::Department>("1", "Department one", "http://one.com", true); |
1075 | + dept1->set_subdepartments({ |
1076 | + std::make_shared<click::Department>("1-1", "Department two", "http://two.com", false), |
1077 | + std::make_shared<click::Department>("1-2", "Department three", "http://three.com", false) |
1078 | + }); |
1079 | + DepartmentList init_departments({dept1}); |
1080 | + auto depts_db = std::make_shared<MockDepartmentsDb>("query-tests.db"); |
1081 | + |
1082 | + EXPECT_CALL(*depts_db, store_department_name(_, _, _)).Times(3); |
1083 | + EXPECT_CALL(*depts_db, store_department_mapping(_, _)).Times(2); |
1084 | + |
1085 | + MockIndex mock_index(click::Packages(), click::DepartmentList(), init_departments); |
1086 | + scopes::SearchMetadata metadata("en_EN", "phone"); |
1087 | + PackageSet one_installed_package { |
1088 | + {"org.example.app2", "0.2"} |
1089 | + }; |
1090 | + click::DepartmentLookup dept_lookup; |
1091 | + click::HighlightList highlights; |
1092 | + const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1093 | + MockQuery q(query, mock_index, dept_lookup, depts_db, highlights, metadata); |
1094 | + EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)); |
1095 | + |
1096 | + scopes::CategoryRenderer renderer("{}"); |
1097 | + auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer); |
1098 | + EXPECT_CALL(q, register_category(_, _, _, _, _)).Times(2).WillRepeatedly(Return(ptrCat)); |
1099 | + |
1100 | + scopes::testing::MockSearchReply mock_reply; |
1101 | + scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){}); |
1102 | + q.wrap_add_available_apps(reply, one_installed_package, FAKE_CATEGORY_TEMPLATE); |
1103 | +} |
1104 | + |
1105 | class FakeInterface : public click::Interface |
1106 | { |
1107 | public: |
1108 | @@ -286,7 +337,7 @@ |
1109 | click::DepartmentLookup dept_lookup; |
1110 | click::HighlightList highlights; |
1111 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1112 | - MockQuery q(query, mock_index, dept_lookup, highlights, metadata); |
1113 | + MockQuery q(query, mock_index, dept_lookup, nullptr, highlights, metadata); |
1114 | PackageSet installed_packages{{"package_1", "0.1"}}; |
1115 | |
1116 | FakeInterface fake_interface; |
1117 | |
1118 | === added directory 'tools' |
1119 | === added file 'tools/CMakeLists.txt' |
1120 | --- tools/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1121 | +++ tools/CMakeLists.txt 2014-07-15 14:51:22 +0000 |
1122 | @@ -0,0 +1,1 @@ |
1123 | +add_subdirectory(init-departments) |
1124 | |
1125 | === added directory 'tools/init-departments' |
1126 | === added file 'tools/init-departments/CMakeLists.txt' |
1127 | --- tools/init-departments/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1128 | +++ tools/init-departments/CMakeLists.txt 2014-07-15 14:51:22 +0000 |
1129 | @@ -0,0 +1,19 @@ |
1130 | +set (CMAKE_INCLUDE_CURRENT_DIR ON) |
1131 | +set (INITDEPTS init-departments) |
1132 | + |
1133 | +find_package (Qt5Core REQUIRED) |
1134 | + |
1135 | +include_directories ( |
1136 | + ${CMAKE_SOURCE_DIR}/libclickscope |
1137 | + ${JSON_CPP_INCLUDE_DIRS} |
1138 | + ) |
1139 | + |
1140 | +add_executable (${INITDEPTS} |
1141 | + init-departments.cpp |
1142 | + ) |
1143 | + |
1144 | +qt5_use_modules (${INITDEPTS} Network Sql) |
1145 | + |
1146 | +target_link_libraries(${INITDEPTS} |
1147 | + ${SCOPE_LIB_NAME} |
1148 | + ) |
1149 | |
1150 | === added file 'tools/init-departments/README' |
1151 | --- tools/init-departments/README 1970-01-01 00:00:00 +0000 |
1152 | +++ tools/init-departments/README 2014-07-15 14:51:22 +0000 |
1153 | @@ -0,0 +1,10 @@ |
1154 | +This tool creates/updates the list of departments and package:department mapping |
1155 | +for currently installed apps, and stores it in a sqlite database file. |
1156 | +This db should then be put in the unity-scope-click-departmentsdb package or manually |
1157 | +copied to the location where click scope expects it to be (~/.cache/click-departments.db). |
1158 | + |
1159 | +Usage: |
1160 | +init-departments DBFILE LOCALE1 [LOCALE2 ...] |
1161 | + |
1162 | +for example: |
1163 | +init-departments click-departments.db "" pl_PL de_DE |
1164 | |
1165 | === added file 'tools/init-departments/init-departments.cpp' |
1166 | --- tools/init-departments/init-departments.cpp 1970-01-01 00:00:00 +0000 |
1167 | +++ tools/init-departments/init-departments.cpp 2014-07-15 14:51:22 +0000 |
1168 | @@ -0,0 +1,276 @@ |
1169 | +/* |
1170 | + * Copyright (C) 2014 Canonical Ltd. |
1171 | + * |
1172 | + * This program is free software: you can redistribute it and/or modify it |
1173 | + * under the terms of the GNU General Public License version 3, as published |
1174 | + * by the Free Software Foundation. |
1175 | + * |
1176 | + * This program is distributed in the hope that it will be useful, but |
1177 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1178 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1179 | + * PURPOSE. See the GNU General Public License for more details. |
1180 | + * |
1181 | + * You should have received a copy of the GNU General Public License along |
1182 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1183 | + * |
1184 | + * In addition, as a special exception, the copyright holders give |
1185 | + * permission to link the code of portions of this program with the |
1186 | + * OpenSSL library under certain conditions as described in each |
1187 | + * individual source file, and distribute linked combinations |
1188 | + * including the two. |
1189 | + * You must obey the GNU General Public License in all respects |
1190 | + * for all of the code used other than OpenSSL. If you modify |
1191 | + * file(s) with this exception, you may extend this exception to your |
1192 | + * version of the file(s), but you are not obligated to do so. If you |
1193 | + * do not wish to do so, delete this exception statement from your |
1194 | + * version. If you delete this exception statement from all source |
1195 | + * files in the program, then also delete it here. |
1196 | + */ |
1197 | + |
1198 | +#include <click/interface.h> |
1199 | +#include <click/key_file_locator.h> |
1200 | +#include <click/index.h> |
1201 | +#include <click/webclient.h> |
1202 | +#include <click/network_access_manager.h> |
1203 | +#include <click/qtbridge.h> |
1204 | +#include <click/departments-db.h> |
1205 | +#include <future> |
1206 | +#include <iostream> |
1207 | +#include <QDebug> |
1208 | +#include <QtGlobal> |
1209 | + |
1210 | +enum |
1211 | +{ |
1212 | + // invalid arguments |
1213 | + DEPTS_ERROR_ARG = 1, |
1214 | + |
1215 | + // network request errors |
1216 | + DEPTS_ERROR_NETWORK = 2, |
1217 | + |
1218 | + // sqlite db errors |
1219 | + DEPTS_ERROR_DB = 5, |
1220 | + |
1221 | + // click errors |
1222 | + DEPTS_ERROR_CLICK_PARSE = 10, |
1223 | + DEPTS_ERROR_CLICK_CALL = 11, |
1224 | + DEPTS_ERROR_CLICK_UNKNOWN = 12 |
1225 | +}; |
1226 | + |
1227 | +std::list<std::pair<std::string, std::string>> NON_CLICK_APPS = { |
1228 | + {"address-book-app.desktop", "accessories"}, |
1229 | + {"dialer-app.desktop", "accessories"}, |
1230 | + {"mediaplayer-app.desktop", "sound-video"}, |
1231 | + {"messaging-app.desktop", "accessories"}, |
1232 | + {"ubuntu-system-settings.desktop", "accessories"}, |
1233 | + {"webbrowser-app.desktop", "web-browsers"} |
1234 | +}; |
1235 | + |
1236 | +QSharedPointer<click::KeyFileLocator> keyFileLocator(new click::KeyFileLocator()); |
1237 | +click::Interface iface(keyFileLocator); |
1238 | + |
1239 | +void noDebug(QtMsgType, const QMessageLogContext&, const QString&) {} |
1240 | + |
1241 | +int main(int argc, char **argv) |
1242 | +{ |
1243 | + if (argc < 3) |
1244 | + { |
1245 | + std::cerr << "Usage: " << argv[0] << " DBFILE LOCALE1 [LOCALE2 ...]" << std::endl; |
1246 | + return DEPTS_ERROR_ARG; |
1247 | + } |
1248 | + |
1249 | + const std::string dbfile(argv[1]); |
1250 | + const std::set<std::string> locales(argv + 2, argv + argc); |
1251 | + |
1252 | + if (!getenv("INIT_DEPARTMENTS_DEBUG")) |
1253 | + qInstallMessageHandler(noDebug); |
1254 | + |
1255 | + std::unique_ptr<click::DepartmentsDb> db; |
1256 | + try |
1257 | + { |
1258 | + db.reset(new click::DepartmentsDb(dbfile)); |
1259 | + } |
1260 | + catch (const std::exception &e) |
1261 | + { |
1262 | + std::cerr << "Failed to open departments database " << dbfile << std::endl; |
1263 | + return DEPTS_ERROR_DB; |
1264 | + } |
1265 | + |
1266 | + auto nam = QSharedPointer<click::network::AccessManager>(new click::network::AccessManager()); |
1267 | + auto client = QSharedPointer<click::web::Client>(new click::web::Client(nam)); |
1268 | + click::Index index(client); |
1269 | + std::vector<click::web::Cancellable> cnc; |
1270 | + |
1271 | + std::promise<void> qt_ready; |
1272 | + std::promise<void> bootstrap_ready; |
1273 | + std::promise<click::PackageSet> pkgs_ready; |
1274 | + auto qt_ready_ft = qt_ready.get_future(); |
1275 | + auto bootstrap_ft = bootstrap_ready.get_future(); |
1276 | + auto pkgs_ft = pkgs_ready.get_future(); |
1277 | + |
1278 | + std::atomic<int> return_val(0); |
1279 | + std::atomic<std::vector<std::string>::size_type> num_of_locales(locales.size()); |
1280 | + std::atomic<click::PackageSet::size_type> num_of_pkgs(0); |
1281 | + |
1282 | + // |
1283 | + // a thread that does bootstrap request |
1284 | + std::thread net_thread([&]() { |
1285 | + qt_ready_ft.get(); |
1286 | + |
1287 | + for (auto const locale: locales) |
1288 | + { |
1289 | + qt::core::world::enter_with_task([&return_val, &bootstrap_ready, &index, &cnc, &num_of_locales, &db, locale]() { |
1290 | + |
1291 | + std::cout << "Getting departments for locale '" << locale << "'" << std::endl; |
1292 | + cnc.push_back(index.bootstrap([&return_val, &bootstrap_ready, &num_of_locales, &db, locale](const click::DepartmentList& depts, const click::HighlightList&, click::Index::Error error, int) { |
1293 | + std::cout << "Bootstrap call for locale '" << locale << "' finished" << std::endl; |
1294 | + |
1295 | + if (error == click::Index::Error::NoError) |
1296 | + { |
1297 | + try |
1298 | + { |
1299 | + db->store_departments(depts, locale); |
1300 | + std::cout << "Stored departments for locale '" << locale << "'" << std::endl; |
1301 | + } |
1302 | + catch (const std::exception& e) |
1303 | + { |
1304 | + std::cerr << "Failed to update departments database: " << e.what() << std::endl; |
1305 | + return_val = DEPTS_ERROR_DB; |
1306 | + } |
1307 | + |
1308 | + if (--num_of_locales == 0) |
1309 | + { |
1310 | + std::cout << "All locales processed" << std::endl; |
1311 | + bootstrap_ready.set_value(); |
1312 | + } |
1313 | + } |
1314 | + else |
1315 | + { |
1316 | + std::cerr << "Network error" << std::endl; |
1317 | + return_val = DEPTS_ERROR_NETWORK; |
1318 | + bootstrap_ready.set_value(); |
1319 | + qt::core::world::destroy(); |
1320 | + return; |
1321 | + } |
1322 | + })); |
1323 | + }); |
1324 | + } |
1325 | + }); |
1326 | + |
1327 | + // |
1328 | + // a thread that iterates over all packages and performs details requests |
1329 | + // it initially blocks on bootstrap_ft and pkgs_ft future |
1330 | + // (waits until bootstrap finished and main thread gets all the click packages) |
1331 | + std::thread details_thread([&]() { |
1332 | + bootstrap_ft.get(); |
1333 | + auto const pkgs = pkgs_ft.get(); |
1334 | + |
1335 | + num_of_pkgs = pkgs.size(); |
1336 | + |
1337 | + // if click list failed or nothing to do, then end this thread and stop Qt bridge |
1338 | + if (return_val != 0 || num_of_pkgs == 0) |
1339 | + { |
1340 | + std::cerr << "No packages to process or an error occurred, not fetching departments" << std::endl; |
1341 | + qt::core::world::destroy(); |
1342 | + return; |
1343 | + } |
1344 | + |
1345 | + std::cout << "Getting package details for " << num_of_pkgs << " packages" << std::endl; |
1346 | + |
1347 | + // |
1348 | + // note: this queues requests for all the packages; the number of packages to process |
1349 | + // is kept in num_of_pkgs which gets decreased, the last processed package will stop Qt bridge. |
1350 | + for (auto const& pkg: pkgs) |
1351 | + { |
1352 | + auto const pkgname = pkg.name; |
1353 | + |
1354 | + qt::core::world::enter_with_task([&return_val, &index, &cnc, &num_of_pkgs, pkgname, &db]() { |
1355 | + |
1356 | + cnc.push_back(index.get_details(pkgname, [&return_val, &num_of_pkgs, pkgname, &db](const click::PackageDetails& details, click::Index::Error error) { |
1357 | + std::cout << "Details call for " << pkgname << " finished" << std::endl; |
1358 | + |
1359 | + if (error == click::Index::Error::NoError) |
1360 | + { |
1361 | + try |
1362 | + { |
1363 | + std::cout << "Storing package department for " << pkgname << ", " << details.department << std::endl; |
1364 | + db->store_package_mapping(pkgname, details.department); |
1365 | + } |
1366 | + catch (const std::exception& e) |
1367 | + { |
1368 | + std::cerr << "Failed to update departments database: " << e.what() << std::endl; |
1369 | + return_val = DEPTS_ERROR_DB; |
1370 | + } |
1371 | + } |
1372 | + else |
1373 | + { |
1374 | + std::cerr << "Network error" << std::endl; |
1375 | + return_val = DEPTS_ERROR_NETWORK; |
1376 | + } |
1377 | + if (--num_of_pkgs == 0) |
1378 | + { |
1379 | + std::cout << "All packages processed" << std::endl; |
1380 | + qt::core::world::destroy(); |
1381 | + } |
1382 | + })); |
1383 | + }); |
1384 | + } |
1385 | + }); |
1386 | + |
1387 | + // |
1388 | + // enter Qt world; this blocks until qt::core:;world::destroy() gets called |
1389 | + qt::core::world::build_and_run(argc, argv, [&pkgs_ready, &qt_ready, &return_val]() { |
1390 | + |
1391 | + qt::core::world::enter_with_task([&return_val, &pkgs_ready, &qt_ready]() { |
1392 | + std::cout << "Querying click for installed packages" << std::endl; |
1393 | + iface.get_installed_packages([&return_val, &pkgs_ready, &qt_ready](click::PackageSet pkgs, click::InterfaceError error) { |
1394 | + if (error == click::InterfaceError::NoError) |
1395 | + { |
1396 | + std::cout << "Found: " << pkgs.size() << " click packages" << std::endl; |
1397 | + } |
1398 | + else |
1399 | + { |
1400 | + if (error == click::InterfaceError::ParseError) |
1401 | + { |
1402 | + std::cerr << "Error parsing click output" << std::endl; |
1403 | + return_val = DEPTS_ERROR_CLICK_PARSE; |
1404 | + } |
1405 | + else if (error == click::InterfaceError::CallError) |
1406 | + { |
1407 | + std::cerr << "Error calling click command" << std::endl; |
1408 | + return_val = DEPTS_ERROR_CLICK_CALL; |
1409 | + } |
1410 | + else |
1411 | + { |
1412 | + std::cerr << "An unknown click error occured" << std::endl; |
1413 | + return_val = DEPTS_ERROR_CLICK_UNKNOWN; |
1414 | + } |
1415 | + } |
1416 | + qt_ready.set_value(); |
1417 | + pkgs_ready.set_value(pkgs); // this unblocks net_thread |
1418 | + }); |
1419 | + }); |
1420 | + }); |
1421 | + |
1422 | + net_thread.join(); |
1423 | + details_thread.join(); |
1424 | + |
1425 | + try |
1426 | + { |
1427 | + for (auto const& app: NON_CLICK_APPS) |
1428 | + { |
1429 | + db->store_package_mapping(app.first, app.second); |
1430 | + } |
1431 | + } |
1432 | + catch (const std::exception &e) |
1433 | + { |
1434 | + std::cerr << "Failed to insert non-click appsint database" << std::endl; |
1435 | + return DEPTS_ERROR_DB; |
1436 | + } |
1437 | + |
1438 | + std::cout << std::endl << "Summary:" << std::endl |
1439 | + << "Number of department mappings: " << db->department_mapping_count() << std::endl |
1440 | + << "Number of department names (all locales): " << db->department_name_count() << std::endl |
1441 | + << "Number of applications: " << db->package_count() << std::endl; |
1442 | + |
1443 | + return return_val; |
1444 | +} |
PASSED: Continuous integration, rev:315 jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- ci/161/ jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- utopic- amd64-ci/ 136 jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- utopic- armhf-ci/ 135 jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- utopic- armhf-ci/ 135/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- utopic- i386-ci/ 135
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity- team-unity- scope-click- devel-ci/ 161/rebuild
http://