Merge lp:~townsend/libertine/0.99.12 into lp:libertine/trunk
- 0.99.12
- Merge into trunk
Proposed by
Christopher Townsend
Status: | Merged | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Approved by: | Stephen M. Webb | ||||||||||||
Approved revision: | 120 | ||||||||||||
Merged at revision: | 120 | ||||||||||||
Proposed branch: | lp:~townsend/libertine/0.99.12 | ||||||||||||
Merge into: | lp:libertine/trunk | ||||||||||||
Diff against target: |
1203 lines (+717/-77) 19 files modified
debian/changelog (+14/-0) libertine/ContainerArchivesList.cpp (+94/-0) libertine/ContainerArchivesList.h (+81/-0) libertine/ContainerConfig.cpp (+123/-17) libertine/ContainerConfig.h (+40/-14) libertine/ContainerConfigList.cpp (+15/-1) libertine/ContainerConfigList.h (+4/-0) libertine/ContainerManager.cpp (+10/-0) libertine/ContainerManager.h (+1/-0) libertine/libertine.cpp (+3/-0) libertine/libertine.h (+2/-0) libertine/qml/ConfigureContainer.qml (+34/-36) libertine/qml/ExtraArchivesView.qml (+167/-0) liblibertine/CMakeLists.txt (+1/-0) python/libertine/ChrootContainer.py (+12/-3) python/libertine/Libertine.py (+15/-4) python/libertine/LxcContainer.py (+2/-0) python/libertine/utils.py (+4/-0) tools/libertine-container-manager (+95/-2) |
||||||||||||
To merge this branch: | bzr merge lp:~townsend/libertine/0.99.12 | ||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Stephen M. Webb (community) | Approve | ||
Review via email:
|
Commit message
* Enable feature to add and remove extra archives in the container. This is for PPA's only right now.
* add multiarch support to chroot containers too.
* When killing processes in the container, need to wait() after terminating
processes and to actually terminate and wait() on the main process. Caused
app launching issues in LXC based containers.
Description of the change
To post a comment you must log in.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Stephen M. Webb (bregma) : | # |
review:
Approve
lp:~townsend/libertine/0.99.12
updated
- 121. By Christopher Townsend
-
When killing processes in the container, need to wait() after terminating
processes and to actually terminate and wait() on the main process. Caused
app launching issues in LXC based containers. (LP: #1558588)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'debian/changelog' |
2 | --- debian/changelog 2016-03-02 22:06:45 +0000 |
3 | +++ debian/changelog 2016-03-21 12:56:41 +0000 |
4 | @@ -1,3 +1,17 @@ |
5 | +libertine (0.99.12-0ubuntu1) UNRELEASED; urgency=medium |
6 | + |
7 | + [ Chris Townsend ] |
8 | + * Enable feature to add and remove extra archives in the container. This is |
9 | + for PPA's only right now. (LP: #1541901) |
10 | + * When killing processes in the container, need to wait() after terminating |
11 | + processes and to actually terminate and wait() on the main process. Caused |
12 | + app launching issues in LXC based containers. (LP: #1558588) |
13 | + |
14 | + [ Stephen M. Webb ] |
15 | + * add multiarch support to chroot containers too. (LP: #1556303) |
16 | + |
17 | + -- Chris Townsend <christopher.townsend@canonical.com> Wed, 16 Mar 2016 15:38:04 -0400 |
18 | + |
19 | libertine (0.99.11+16.04.20160302-0ubuntu1) xenial; urgency=medium |
20 | |
21 | [ Chris Townsend ] |
22 | |
23 | === added file 'libertine/ContainerArchivesList.cpp' |
24 | --- libertine/ContainerArchivesList.cpp 1970-01-01 00:00:00 +0000 |
25 | +++ libertine/ContainerArchivesList.cpp 2016-03-21 12:56:41 +0000 |
26 | @@ -0,0 +1,94 @@ |
27 | +/** |
28 | + * @file ContainerArchivesList.cpp |
29 | + * @brief Libertine Manager list of extra container archives, ie, PPAs |
30 | + */ |
31 | +/* |
32 | + * Copyright 2016 Canonical Ltd |
33 | + * |
34 | + * Libertine is free software: you can redistribute it and/or modify it under |
35 | + * the terms of the GNU General Public License, version 3, as published by the |
36 | + * Free Software Foundation. |
37 | + * |
38 | + * Libertine is distributed in the hope that it will be useful, but WITHOUT ANY |
39 | + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR |
40 | + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
41 | + * |
42 | + * You should have received a copy of the GNU General Public License |
43 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
44 | + */ |
45 | +#include "libertine/ContainerArchivesList.h" |
46 | +#include "libertine/ContainerConfigList.h" |
47 | + |
48 | +ContainerArchivesList:: |
49 | +ContainerArchivesList(ContainerConfigList* container_config_list, |
50 | + QObject* parent) |
51 | +: QAbstractListModel(parent) |
52 | +, container_config_list_(container_config_list) |
53 | +{ } |
54 | + |
55 | + |
56 | +ContainerArchivesList:: |
57 | +~ContainerArchivesList() |
58 | +{ } |
59 | + |
60 | + |
61 | +void ContainerArchivesList:: |
62 | +setContainerArchives(QString const& container_id) |
63 | +{ |
64 | + archives_ = container_config_list_->getArchivesForContainer(container_id); |
65 | + |
66 | + beginResetModel(); |
67 | + endResetModel(); |
68 | +} |
69 | + |
70 | + |
71 | +bool ContainerArchivesList:: |
72 | +empty() const noexcept |
73 | +{ return archives_->empty(); } |
74 | + |
75 | + |
76 | +ContainerArchivesList::size_type ContainerArchivesList:: |
77 | +size() const noexcept |
78 | +{ return archives_->count(); } |
79 | + |
80 | + |
81 | +int ContainerArchivesList:: |
82 | +rowCount(QModelIndex const&) const |
83 | +{ |
84 | + return this->size(); |
85 | +} |
86 | + |
87 | + |
88 | +QHash<int, QByteArray> ContainerArchivesList:: |
89 | +roleNames() const |
90 | +{ |
91 | + QHash<int, QByteArray> roles; |
92 | + roles[static_cast<int>(DataRole::ArchiveName)] = "archiveName"; |
93 | + roles[static_cast<int>(DataRole::ArchiveStatus)] = "archiveStatus"; |
94 | + |
95 | + return roles; |
96 | +} |
97 | + |
98 | + |
99 | +QVariant ContainerArchivesList:: |
100 | +data(QModelIndex const& index, int role) const |
101 | +{ |
102 | + QVariant result; |
103 | + |
104 | + if (index.isValid() && index.row() <= archives_->count()) |
105 | + { |
106 | + switch (static_cast<DataRole>(role)) |
107 | + { |
108 | + case DataRole::ArchiveName: |
109 | + result = (*archives_)[index.row()]->archive_name(); |
110 | + break; |
111 | + case DataRole::ArchiveStatus: |
112 | + result = (*archives_)[index.row()]->archive_status(); |
113 | + break; |
114 | + case DataRole::Error: |
115 | + break; |
116 | + } |
117 | + } |
118 | + |
119 | + return result; |
120 | +} |
121 | |
122 | === added file 'libertine/ContainerArchivesList.h' |
123 | --- libertine/ContainerArchivesList.h 1970-01-01 00:00:00 +0000 |
124 | +++ libertine/ContainerArchivesList.h 2016-03-21 12:56:41 +0000 |
125 | @@ -0,0 +1,81 @@ |
126 | +/** |
127 | + * @file ContainerArchivesList.h |
128 | + * @brief Libertine Manager list of extra container archives (PPAs) |
129 | + */ |
130 | +/* |
131 | + * Copyright 2016 Canonical Ltd |
132 | + * |
133 | + * Libertine is free software: you can redistribute it and/or modify it under |
134 | + * the terms of the GNU General Public License, version 3, as published by the |
135 | + * Free Software Foundation. |
136 | + * |
137 | + * Libertine is distributed in the hope that it will be useful, but WITHOUT ANY |
138 | + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR |
139 | + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
140 | + * |
141 | + * You should have received a copy of the GNU General Public License |
142 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
143 | + */ |
144 | +#ifndef _CONTAINER_ARCHIVES_LIST_H_ |
145 | +#define _CONTAINER_ARCHIVES_LIST_H_ |
146 | + |
147 | +#include "libertine/ContainerConfig.h" |
148 | + |
149 | +#include <QtCore/QAbstractListModel> |
150 | +#include <QtCore/QList> |
151 | +#include <QtCore/QObject> |
152 | +#include <QtCore/QString> |
153 | + |
154 | + |
155 | +class ContainerArchives; |
156 | +class ContainerConfigList; |
157 | + |
158 | +class ContainerArchivesList |
159 | +: public QAbstractListModel |
160 | +{ |
161 | + Q_OBJECT |
162 | + |
163 | +public: |
164 | + using ArchivesList = QList<ContainerArchives*>; |
165 | + using iterator = ArchivesList::iterator; |
166 | + using size_type = ArchivesList::size_type; |
167 | + |
168 | + enum class DataRole |
169 | + : int |
170 | + { |
171 | + ArchiveName = Qt::UserRole + 1, |
172 | + ArchiveStatus, |
173 | + Error |
174 | + }; |
175 | + |
176 | +public: |
177 | + explicit |
178 | + ContainerArchivesList(ContainerConfigList* container_config_list, |
179 | + QObject* parent = nullptr); |
180 | + |
181 | + ~ContainerArchivesList(); |
182 | + |
183 | + Q_INVOKABLE void |
184 | + setContainerArchives(QString const& container_id); |
185 | + |
186 | + Q_INVOKABLE bool |
187 | + empty() const noexcept; |
188 | + |
189 | + size_type |
190 | + size() const noexcept; |
191 | + |
192 | + int |
193 | + rowCount(QModelIndex const& parent = QModelIndex()) const; |
194 | + |
195 | + QHash<int, QByteArray> |
196 | + roleNames() const; |
197 | + |
198 | + QVariant |
199 | + data(QModelIndex const& index, int role = Qt::DisplayRole) const; |
200 | + |
201 | +private: |
202 | + ContainerConfigList* container_config_list_; |
203 | + ArchivesList* archives_; |
204 | +}; |
205 | + |
206 | +#endif /* _CONTAINER_ARCHIVES_LIST_H_ */ |
207 | |
208 | === modified file 'libertine/ContainerConfig.cpp' |
209 | --- libertine/ContainerConfig.cpp 2016-02-10 19:31:10 +0000 |
210 | +++ libertine/ContainerConfig.cpp 2016-03-21 12:56:41 +0000 |
211 | @@ -178,15 +178,15 @@ |
212 | return ContainerConfig::InstallStatus::New; |
213 | } |
214 | |
215 | - const static struct { QString string; ContainerApps::AppStatus enumeration; } app_status_names[] = |
216 | + const static struct { QString string; CurrentStatus enumeration; } status_names[] = |
217 | { |
218 | - { QObject::tr("new"), ContainerApps::AppStatus::New }, |
219 | - { QObject::tr("installing"), ContainerApps::AppStatus::Installing }, |
220 | - { QObject::tr("installed"), ContainerApps::AppStatus::Installed }, |
221 | - { QObject::tr("failed"), ContainerApps::AppStatus::Failed }, |
222 | - { QObject::tr("removing"), ContainerApps::AppStatus::Removing }, |
223 | - { QObject::tr("removed"), ContainerApps::AppStatus::Removed }, |
224 | - { QString(), ContainerApps::AppStatus::New } |
225 | + { QObject::tr("new"), CurrentStatus::New }, |
226 | + { QObject::tr("installing"), CurrentStatus::Installing }, |
227 | + { QObject::tr("installed"), CurrentStatus::Installed }, |
228 | + { QObject::tr("failed"), CurrentStatus::Failed }, |
229 | + { QObject::tr("removing"), CurrentStatus::Removing }, |
230 | + { QObject::tr("removed"), CurrentStatus::Removed }, |
231 | + { QString(), CurrentStatus::New } |
232 | }; |
233 | |
234 | QString |
235 | @@ -207,10 +207,10 @@ |
236 | return package_name; |
237 | } |
238 | |
239 | - ContainerApps::AppStatus |
240 | + CurrentStatus |
241 | extract_app_status_from_json(QJsonObject const& json_object) |
242 | { |
243 | - ContainerApps::AppStatus app_status = ContainerApps::AppStatus::New; |
244 | + CurrentStatus app_status = CurrentStatus::New; |
245 | |
246 | QJsonValue value = json_object["appStatus"]; |
247 | if (value != QJsonValue::Undefined) |
248 | @@ -221,7 +221,7 @@ |
249 | QString s = value.toString(); |
250 | if (s.length() > 0) |
251 | { |
252 | - for (auto const& name: app_status_names) |
253 | + for (auto const& name: status_names) |
254 | { |
255 | if (0 == s.compare(name.string, Qt::CaseInsensitive)) |
256 | { |
257 | @@ -241,7 +241,7 @@ |
258 | { |
259 | QList<ContainerApps*> container_apps; |
260 | QString package_name; |
261 | - ContainerApps::AppStatus app_status; |
262 | + CurrentStatus app_status; |
263 | |
264 | QJsonArray installed_apps = json_object["installedApps"].toArray(); |
265 | |
266 | @@ -255,12 +255,78 @@ |
267 | } |
268 | return container_apps; |
269 | } |
270 | + |
271 | + QString |
272 | + extract_archive_name_from_json(QJsonObject const& json_object) |
273 | + { |
274 | + QString archive_name; |
275 | + |
276 | + QJsonValue value = json_object["archiveName"]; |
277 | + if (value != QJsonValue::Undefined) |
278 | + { |
279 | + QJsonValue::Type value_type = value.type(); |
280 | + if (value_type == QJsonValue::String) |
281 | + { |
282 | + archive_name = value.toString(); |
283 | + } |
284 | + } |
285 | + |
286 | + return archive_name; |
287 | + } |
288 | + |
289 | + CurrentStatus |
290 | + extract_archive_status_from_json(QJsonObject const& json_object) |
291 | + { |
292 | + CurrentStatus archive_status = CurrentStatus::New; |
293 | + |
294 | + QJsonValue value = json_object["archiveStatus"]; |
295 | + if (value != QJsonValue::Undefined) |
296 | + { |
297 | + QJsonValue::Type value_type = value.type(); |
298 | + if (value_type == QJsonValue::String) |
299 | + { |
300 | + QString s = value.toString(); |
301 | + if (s.length() > 0) |
302 | + { |
303 | + for (auto const& name: status_names) |
304 | + { |
305 | + if (0 == s.compare(name.string, Qt::CaseInsensitive)) |
306 | + { |
307 | + archive_status = name.enumeration; |
308 | + break; |
309 | + } |
310 | + } |
311 | + } |
312 | + } |
313 | + } |
314 | + |
315 | + return archive_status; |
316 | + } |
317 | + |
318 | + QList<ContainerArchives*> |
319 | + extract_container_archives_from_json(QJsonObject const& json_object) |
320 | + { |
321 | + QList<ContainerArchives*> container_archives; |
322 | + QString archive_name; |
323 | + CurrentStatus archive_status; |
324 | + |
325 | + QJsonArray extra_archives = json_object["extraArchives"].toArray(); |
326 | + |
327 | + for (auto const& archive: extra_archives) |
328 | + { |
329 | + archive_name = extract_archive_name_from_json(archive.toObject()); |
330 | + archive_status = extract_archive_status_from_json(archive.toObject()); |
331 | + |
332 | + container_archives.append(new ContainerArchives(archive_name, archive_status)); |
333 | + } |
334 | + return container_archives; |
335 | + } |
336 | } // anonymous namespace |
337 | |
338 | |
339 | ContainerApps:: |
340 | ContainerApps(QString const& package_name, |
341 | - ContainerApps::AppStatus app_status, |
342 | + CurrentStatus app_status, |
343 | QObject* parent) |
344 | : QObject(parent) |
345 | , package_name_(package_name) |
346 | @@ -280,7 +346,32 @@ |
347 | |
348 | QString const& ContainerApps:: |
349 | app_status() const |
350 | -{ return app_status_names[(int)app_status_].string; } |
351 | +{ return status_names[(int)app_status_].string; } |
352 | + |
353 | + |
354 | +ContainerArchives:: |
355 | +ContainerArchives(QString const& archive_name, |
356 | + CurrentStatus archive_status, |
357 | + QObject* parent) |
358 | +: QObject(parent) |
359 | +, archive_name_(archive_name) |
360 | +, archive_status_(archive_status) |
361 | +{ } |
362 | + |
363 | + |
364 | +ContainerArchives:: |
365 | +~ContainerArchives() |
366 | +{ } |
367 | + |
368 | + |
369 | +QString const& ContainerArchives:: |
370 | +archive_name() const |
371 | +{ return archive_name_; } |
372 | + |
373 | + |
374 | +QString const& ContainerArchives:: |
375 | +archive_status() const |
376 | +{ return status_names[(int)archive_status_].string; } |
377 | |
378 | |
379 | ContainerConfig:: |
380 | @@ -316,6 +407,7 @@ |
381 | , multiarch_support_(extract_multiarch_support_from_json(json_object)) |
382 | , install_status_(extract_install_status_from_json(json_object)) |
383 | , container_apps_(extract_container_apps_from_json(json_object)) |
384 | +, container_archives_(extract_container_archives_from_json(json_object)) |
385 | { } |
386 | |
387 | |
388 | @@ -375,12 +467,19 @@ |
389 | { return container_apps_; } |
390 | |
391 | |
392 | +QList<ContainerArchives*> & ContainerConfig:: |
393 | +container_archives() |
394 | +{ return container_archives_; } |
395 | + |
396 | + |
397 | QJsonObject ContainerConfig:: |
398 | toJson() const |
399 | { |
400 | QJsonObject json_object, |
401 | - app_object; |
402 | - QJsonArray apps; |
403 | + app_object, |
404 | + archive_object; |
405 | + QJsonArray apps, |
406 | + archives; |
407 | |
408 | json_object["id"] = container_id_; |
409 | json_object["name"] = container_name_; |
410 | @@ -397,10 +496,17 @@ |
411 | for (auto const& container_app: container_apps_) |
412 | { |
413 | app_object["packageName"] = container_app->package_name(); |
414 | - app_object["appStatus"] = app_status_names[0].string; |
415 | + app_object["appStatus"] = status_names[0].string; |
416 | apps.append(app_object); |
417 | } |
418 | json_object["installedApps"] = apps; |
419 | |
420 | + for (auto const& container_archive: container_archives_) |
421 | + { |
422 | + archive_object["archiveName"] = container_archive->archive_name(); |
423 | + archives.append(archive_object); |
424 | + } |
425 | + json_object["extraArchives"] = archives; |
426 | + |
427 | return json_object; |
428 | } |
429 | |
430 | === modified file 'libertine/ContainerConfig.h' |
431 | --- libertine/ContainerConfig.h 2016-02-10 19:31:10 +0000 |
432 | +++ libertine/ContainerConfig.h 2016-03-21 12:56:41 +0000 |
433 | @@ -24,18 +24,17 @@ |
434 | #include <QtCore/QString> |
435 | |
436 | |
437 | +enum class CurrentStatus { New, Installing, Installed, Failed, Removing, Removed }; |
438 | + |
439 | + |
440 | class ContainerApps |
441 | : public QObject |
442 | { |
443 | Q_OBJECT |
444 | |
445 | public: |
446 | - enum class AppStatus |
447 | - { New, Installing, Installed, Failed, Removing, Removed }; |
448 | - |
449 | -public: |
450 | ContainerApps(QString const& package_name, |
451 | - AppStatus app_status, |
452 | + CurrentStatus app_status, |
453 | QObject* parent = nullptr); |
454 | ~ContainerApps(); |
455 | |
456 | @@ -46,8 +45,31 @@ |
457 | app_status() const; |
458 | |
459 | private: |
460 | - QString package_name_; |
461 | - AppStatus app_status_; |
462 | + QString package_name_; |
463 | + CurrentStatus app_status_; |
464 | +}; |
465 | + |
466 | + |
467 | +class ContainerArchives |
468 | +: public QObject |
469 | +{ |
470 | + Q_OBJECT |
471 | + |
472 | +public: |
473 | + ContainerArchives(QString const& archive_name, |
474 | + CurrentStatus archive_status, |
475 | + QObject* parent = nullptr); |
476 | + ~ContainerArchives(); |
477 | + |
478 | + QString const& |
479 | + archive_name() const; |
480 | + |
481 | + QString const& |
482 | + archive_status() const; |
483 | + |
484 | +private: |
485 | + QString archive_name_; |
486 | + CurrentStatus archive_status_; |
487 | }; |
488 | |
489 | |
490 | @@ -107,6 +129,9 @@ |
491 | QList<ContainerApps*> & |
492 | container_apps(); |
493 | |
494 | + QList<ContainerArchives*> & |
495 | + container_archives(); |
496 | + |
497 | QJsonObject |
498 | toJson() const; |
499 | |
500 | @@ -115,13 +140,14 @@ |
501 | void installStatusChanged(); |
502 | |
503 | private: |
504 | - QString container_id_; |
505 | - QString container_name_; |
506 | - QString container_type_; |
507 | - QString distro_series_; |
508 | - QString multiarch_support_; |
509 | - InstallStatus install_status_; |
510 | - QList<ContainerApps*> container_apps_; |
511 | + QString container_id_; |
512 | + QString container_name_; |
513 | + QString container_type_; |
514 | + QString distro_series_; |
515 | + QString multiarch_support_; |
516 | + InstallStatus install_status_; |
517 | + QList<ContainerApps*> container_apps_; |
518 | + QList<ContainerArchives*> container_archives_; |
519 | }; |
520 | |
521 | #endif /* CONTAINER_CONTAINERCONFIG_H */ |
522 | |
523 | === modified file 'libertine/ContainerConfigList.cpp' |
524 | --- libertine/ContainerConfigList.cpp 2016-02-11 15:25:09 +0000 |
525 | +++ libertine/ContainerConfigList.cpp 2016-03-21 12:56:41 +0000 |
526 | @@ -121,7 +121,7 @@ |
527 | { |
528 | if (config->container_id() == container_id) |
529 | { |
530 | - config->container_apps().append(new ContainerApps(package_name, ContainerApps::AppStatus::New, this)); |
531 | + config->container_apps().append(new ContainerApps(package_name, CurrentStatus::New, this)); |
532 | break; |
533 | } |
534 | } |
535 | @@ -193,6 +193,20 @@ |
536 | } |
537 | |
538 | |
539 | +QList<ContainerArchives*> * ContainerConfigList:: |
540 | +getArchivesForContainer(QString const& container_id) |
541 | +{ |
542 | + for (auto const& config: configs_) |
543 | + { |
544 | + if (config->container_id() == container_id) |
545 | + { |
546 | + return &(config->container_archives()); |
547 | + } |
548 | + } |
549 | + return nullptr; |
550 | +} |
551 | + |
552 | + |
553 | QString ContainerConfigList:: |
554 | getContainerType(QString const& container_id) |
555 | { |
556 | |
557 | === modified file 'libertine/ContainerConfigList.h' |
558 | --- libertine/ContainerConfigList.h 2016-02-11 15:25:09 +0000 |
559 | +++ libertine/ContainerConfigList.h 2016-03-21 12:56:41 +0000 |
560 | @@ -25,6 +25,7 @@ |
561 | |
562 | |
563 | class ContainerApps; |
564 | +class ContainerArchives; |
565 | class ContainerConfig; |
566 | class LibertineConfig; |
567 | |
568 | @@ -112,6 +113,9 @@ |
569 | Q_INVOKABLE QString |
570 | getAppVersion(QString const& app_info); |
571 | |
572 | + QList<ContainerArchives*> * |
573 | + getArchivesForContainer(QString const& container_id); |
574 | + |
575 | Q_INVOKABLE QString |
576 | getContainerType(QString const& container_id); |
577 | |
578 | |
579 | === modified file 'libertine/ContainerManager.cpp' |
580 | --- libertine/ContainerManager.cpp 2016-02-11 15:59:00 +0000 |
581 | +++ libertine/ContainerManager.cpp 2016-03-21 12:56:41 +0000 |
582 | @@ -395,6 +395,9 @@ |
583 | void ContainerManagerWorker:: |
584 | configureContainer(QStringList configure_command) |
585 | { |
586 | + QByteArray error_msg; |
587 | + bool result = true; |
588 | + |
589 | QProcess libertine_cli_tool; |
590 | QString exec_line = libertine_container_manager_tool; |
591 | QStringList args; |
592 | @@ -408,6 +411,13 @@ |
593 | |
594 | libertine_cli_tool.waitForFinished(-1); |
595 | |
596 | + if (libertine_cli_tool.exitCode() != 0) |
597 | + { |
598 | + error_msg = libertine_cli_tool.readAllStandardOutput(); |
599 | + result = false; |
600 | + } |
601 | + |
602 | + emit finishedConfigure(result, QString(error_msg)); |
603 | emit finished(); |
604 | quit(); |
605 | } |
606 | |
607 | === modified file 'libertine/ContainerManager.h' |
608 | --- libertine/ContainerManager.h 2016-02-11 16:25:49 +0000 |
609 | +++ libertine/ContainerManager.h 2016-03-21 12:56:41 +0000 |
610 | @@ -146,6 +146,7 @@ |
611 | void finishedRemove(bool result, QString const& error_msg); |
612 | void finishedSearch(bool result, QList<QString> packageList); |
613 | void finishedCommand(QString const& command_output); |
614 | + void finishedConfigure(bool result, QString const& error_msg); |
615 | }; |
616 | |
617 | #endif /* CONTAINER_CONTAINERMANAGER_H_ */ |
618 | |
619 | === modified file 'libertine/libertine.cpp' |
620 | --- libertine/libertine.cpp 2016-01-20 17:34:19 +0000 |
621 | +++ libertine/libertine.cpp 2016-03-21 12:56:41 +0000 |
622 | @@ -21,6 +21,7 @@ |
623 | #include <cstdlib> |
624 | #include "libertine/ContainerManager.h" |
625 | #include "libertine/ContainerAppsList.h" |
626 | +#include "libertine/ContainerArchivesList.h" |
627 | #include "libertine/ContainerConfig.h" |
628 | #include "libertine/ContainerConfigList.h" |
629 | #include "libertine/libertine.h" |
630 | @@ -105,6 +106,7 @@ |
631 | |
632 | containers_ = new ContainerConfigList(config_.data(), this); |
633 | container_apps_ = new ContainerAppsList(containers_, this); |
634 | + container_archives_ = new ContainerArchivesList(containers_, this); |
635 | password_helper_ = new PasswordHelper(); |
636 | |
637 | initialize_view(); |
638 | @@ -131,6 +133,7 @@ |
639 | QQmlContext* ctxt = view_.rootContext(); |
640 | ctxt->setContextProperty("containerConfigList", containers_); |
641 | ctxt->setContextProperty("containerAppsList", container_apps_); |
642 | + ctxt->setContextProperty("containerArchivesList", container_archives_); |
643 | ctxt->setContextProperty("passwordHelper", password_helper_); |
644 | |
645 | view_.setSource(QUrl::fromLocalFile(main_qml_source_file_)); |
646 | |
647 | === modified file 'libertine/libertine.h' |
648 | --- libertine/libertine.h 2016-01-20 17:34:19 +0000 |
649 | +++ libertine/libertine.h 2016-03-21 12:56:41 +0000 |
650 | @@ -30,6 +30,7 @@ |
651 | class LibertineConfig; |
652 | class PasswordHelper; |
653 | class ContainerAppsList; |
654 | +class ContainerArchivesList; |
655 | |
656 | |
657 | class Libertine |
658 | @@ -55,6 +56,7 @@ |
659 | QFileSystemWatcher watcher_; |
660 | ContainerConfigList* containers_; |
661 | ContainerAppsList* container_apps_; |
662 | + ContainerArchivesList* container_archives_; |
663 | PasswordHelper* password_helper_; |
664 | QQuickView view_; |
665 | }; |
666 | |
667 | === modified file 'libertine/qml/ConfigureContainer.qml' |
668 | --- libertine/qml/ConfigureContainer.qml 2016-02-11 15:25:09 +0000 |
669 | +++ libertine/qml/ConfigureContainer.qml 2016-03-21 12:56:41 +0000 |
670 | @@ -1,5 +1,5 @@ |
671 | /** |
672 | - * @file configureContainer.qml |
673 | + * @file ConfigureContainer.qml |
674 | * @brief Libertine configure container view |
675 | */ |
676 | /* |
677 | @@ -19,51 +19,49 @@ |
678 | import Libertine 1.0 |
679 | import QtQuick 2.4 |
680 | import Ubuntu.Components 1.2 |
681 | +import Ubuntu.Components.ListItems 1.2 as ListItem |
682 | |
683 | |
684 | Page { |
685 | id: configureView |
686 | title: i18n.tr("Configure ") + mainView.currentContainer |
687 | |
688 | - Item { |
689 | - visible: containerConfigList.getHostArchitecture() == 'x86_64' ? true : false |
690 | - CheckBox { |
691 | - id: multiarchCheckBox |
692 | - anchors { |
693 | - left: parent.left |
694 | - top: parent.top |
695 | - leftMargin: configureView.leftMargin |
696 | - } |
697 | - checked: containerConfigList.getContainerMultiarchSupport(mainView.currentContainer) == 'enabled' ? true : false |
698 | - onClicked: { |
699 | - var comp = Qt.createComponent("ContainerManager.qml") |
700 | - if (multiarchCheckBox.checked) { |
701 | - var worker = comp.createObject(mainView, {"containerAction": ContainerManagerWorker.Configure, |
702 | - "containerId": mainView.currentContainer, |
703 | - "containerType": containerConfigList.getContainerType(mainView.currentContainer), |
704 | - "data_list": ["--multiarch", "enable"]}) |
705 | - worker.start() |
706 | + Column { |
707 | + anchors.left: parent.left |
708 | + anchors.right: parent.right |
709 | + |
710 | + ListItem.Standard { |
711 | + visible: containerConfigList.getHostArchitecture() == 'x86_64' ? true : false |
712 | + control: CheckBox { |
713 | + checked: containerConfigList.getContainerMultiarchSupport(mainView.currentContainer) == 'enabled' ? true : false |
714 | + onClicked: { |
715 | + var comp = Qt.createComponent("ContainerManager.qml") |
716 | + if (multiarchCheckBox.checked) { |
717 | + var worker = comp.createObject(mainView, {"containerAction": ContainerManagerWorker.Configure, |
718 | + "containerId": mainView.currentContainer, |
719 | + "containerType": containerConfigList.getContainerType(mainView.currentContainer), |
720 | + "data_list": ["--multiarch", "enable"]}) |
721 | + worker.start() |
722 | + } |
723 | + else { |
724 | + var worker = comp.createObject(mainView, {"containerAction": ContainerManagerWorker.Configure, |
725 | + "containerId": mainView.currentContainer, |
726 | + "containerType": containerConfigList.getContainerType(mainView.currentContainer), |
727 | + "data_list": ["--multiarch", "disable"]}) |
728 | + worker.start() |
729 | + } |
730 | } |
731 | - else { |
732 | - var worker = comp.createObject(mainView, {"containerAction": ContainerManagerWorker.Configure, |
733 | - "containerId": mainView.currentContainer, |
734 | - "containerType": containerConfigList.getContainerType(mainView.currentContainer), |
735 | - "data_list": ["--multiarch", "disable"]}) |
736 | - worker.start() |
737 | - } |
738 | - } |
739 | - } |
740 | - Label { |
741 | - anchors { |
742 | - left: multiarchCheckBox.right |
743 | - right: parent.right |
744 | - top: parent.bottom |
745 | - verticalCenter: parent.verticalCenter |
746 | - leftMargin: units.gu(2) |
747 | - rightMargin: configureView.rightMargin |
748 | } |
749 | text: i18n.tr("i386 multiarch support") |
750 | } |
751 | |
752 | + ListItem.SingleValue { |
753 | + text: i18n.tr("Additional archives and PPAs") |
754 | + progression: true |
755 | + onClicked: { |
756 | + containerArchivesList.setContainerArchives(mainView.currentContainer) |
757 | + pageStack.push(Qt.resolvedUrl("ExtraArchivesView.qml")) |
758 | + } |
759 | + } |
760 | } |
761 | } |
762 | |
763 | === added file 'libertine/qml/ExtraArchivesView.qml' |
764 | --- libertine/qml/ExtraArchivesView.qml 1970-01-01 00:00:00 +0000 |
765 | +++ libertine/qml/ExtraArchivesView.qml 2016-03-21 12:56:41 +0000 |
766 | @@ -0,0 +1,167 @@ |
767 | +/** |
768 | + * @file ExtraArchiveView.qml |
769 | + * @brief Libertine container add archive view |
770 | + */ |
771 | +/* |
772 | + * Copyright 2016 Canonical Ltd |
773 | + * |
774 | + * Libertine is free software: you can redistribute it and/or modify it under |
775 | + * the terms of the GNU General Public License, version 3, as published by the |
776 | + * Free Software Foundation. |
777 | + * |
778 | + * Libertine is distributed in the hope that it will be useful, but WITHOUT ANY |
779 | + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR |
780 | + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
781 | + * |
782 | + * You should have received a copy of the GNU General Public License |
783 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
784 | + */ |
785 | +import Libertine 1.0 |
786 | +import QtQuick 2.4 |
787 | +import Ubuntu.Components 1.2 |
788 | +import Ubuntu.Components.Popups 1.2 |
789 | + |
790 | +Page { |
791 | + id: extraArchiveView |
792 | + title: i18n.tr("Additional Archives and PPAs") |
793 | + property var archive_name: null |
794 | + property var worker: null |
795 | + |
796 | + head.actions: [ |
797 | + Action { |
798 | + iconName: "add" |
799 | + text: i18n.tr("add") |
800 | + description: i18n.tr("Add a new PPA") |
801 | + onTriggered: PopupUtils.open(addArchivePopup) |
802 | + } |
803 | + ] |
804 | + |
805 | + Component { |
806 | + id: addArchivePopup |
807 | + Dialog { |
808 | + id: addArchiveDialog |
809 | + title: i18n.tr("Add additional PPA") |
810 | + text: i18n.tr("Enter name of PPA in the form ppa:user/ppa-name:") |
811 | + |
812 | + TextField { |
813 | + id: extraArchiveString |
814 | + onAccepted: { |
815 | + PopupUtils.close(addArchiveDialog) |
816 | + addArchive(text) |
817 | + } |
818 | + } |
819 | + Button { |
820 | + text: i18n.tr("OK") |
821 | + color: UbuntuColors.green |
822 | + onClicked: { |
823 | + PopupUtils.close(addArchiveDialog) |
824 | + addArchive(extraArchiveString.text) |
825 | + } |
826 | + } |
827 | + Button { |
828 | + text: i18n.tr("Cancel") |
829 | + color: UbuntuColors.red |
830 | + onClicked: PopupUtils.close(addArchiveDialog) |
831 | + } |
832 | + Component.onCompleted: { |
833 | + extraArchiveString.forceActiveFocus() |
834 | + } |
835 | + } |
836 | + } |
837 | + |
838 | + UbuntuListView { |
839 | + id: extraArchiveList |
840 | + anchors.fill: parent |
841 | + model: containerArchivesList |
842 | + delegate: ListItem { |
843 | + ActivityIndicator { |
844 | + id: extraArchiveActivity |
845 | + anchors.verticalCenter: parent.verticalCenter |
846 | + visible: (archiveStatus === i18n.tr("installing") || |
847 | + archiveStatus === i18n.tr("removing")) ? true : false |
848 | + running: extraArchiveActivity.visible |
849 | + } |
850 | + Label { |
851 | + anchors { |
852 | + verticalCenter: parent.verticalCenter |
853 | + left: extraArchiveActivity.running ? extraArchiveActivity.right : parent.left |
854 | + leftMargin: units.gu(2) |
855 | + } |
856 | + text: archiveName |
857 | + } |
858 | + leadingActions: ListItemActions { |
859 | + actions: [ |
860 | + Action { |
861 | + iconName: "delete" |
862 | + text: i18n.tr("remove") |
863 | + description: i18n.tr("Remove extra archive") |
864 | + onTriggered: { |
865 | + deleteArchive(archiveName) |
866 | + } |
867 | + } |
868 | + ] |
869 | + } |
870 | + } |
871 | + } |
872 | + |
873 | + function addArchive(archive) { |
874 | + var comp = Qt.createComponent("ContainerManager.qml") |
875 | + worker = comp.createObject(mainView, {"containerAction": ContainerManagerWorker.Configure, |
876 | + "containerId": mainView.currentContainer, |
877 | + "containerType": containerConfigList.getContainerType(mainView.currentContainer), |
878 | + "data_list": ["--add-archive", archive]}) |
879 | + worker.finishedConfigure.connect(finishedConfigure) |
880 | + worker.start() |
881 | + } |
882 | + |
883 | + function deleteArchive(archive) { |
884 | + var comp = Qt.createComponent("ContainerManager.qml") |
885 | + worker = comp.createObject(mainView, {"containerAction": ContainerManagerWorker.Configure, |
886 | + "containerId": mainView.currentContainer, |
887 | + "containerType": containerConfigList.getContainerType(mainView.currentContainer), |
888 | + "data_list": ["--delete-archive", archive]}) |
889 | + worker.finishedConfigure.connect(finishedConfigure) |
890 | + worker.start() |
891 | + } |
892 | + |
893 | + Component { |
894 | + id: addFailedPopup |
895 | + |
896 | + Dialog { |
897 | + property var error_msg: null |
898 | + id: addFailedDialog |
899 | + title: i18n.tr("Adding archive failed") |
900 | + text: error_msg |
901 | + |
902 | + Button { |
903 | + text: i18n.tr("Dismiss") |
904 | + onClicked: PopupUtils.close(addFailedDialog) |
905 | + } |
906 | + } |
907 | + } |
908 | + |
909 | + Component.onCompleted: { |
910 | + containerConfigList.configChanged.connect(reloadArchives) |
911 | + } |
912 | + |
913 | + Component.onDestruction: { |
914 | + containerConfigList.configChanged.disconnect(reloadArchives) |
915 | + |
916 | + if (worker) { |
917 | + worker.finishedConfigure.disconnect(finishedConfigure) |
918 | + } |
919 | + } |
920 | + |
921 | + function reloadArchives() { |
922 | + containerArchivesList.setContainerArchives(mainView.currentContainer) |
923 | + } |
924 | + |
925 | + function finishedConfigure(result, error_msg) { |
926 | + if (result) { |
927 | + containerArchivesList.setContainerArchives(mainView.currentContainer) |
928 | + } |
929 | + else { |
930 | + PopupUtils.open(addFailedPopup, null, {'error_msg': error_msg}) |
931 | + } |
932 | + } |
933 | +} |
934 | |
935 | === modified file 'liblibertine/CMakeLists.txt' |
936 | --- liblibertine/CMakeLists.txt 2015-10-07 18:59:50 +0000 |
937 | +++ liblibertine/CMakeLists.txt 2016-03-21 12:56:41 +0000 |
938 | @@ -11,6 +11,7 @@ |
939 | ${libertine_src}/ContainerConfig.cpp |
940 | ${libertine_src}/ContainerManager.cpp |
941 | ${libertine_src}/ContainerAppsList.cpp |
942 | + ${libertine_src}/ContainerArchivesList.cpp |
943 | ${libertine_src}/PasswordHelper.cpp |
944 | ) |
945 | set_target_properties(libertine-common PROPERTIES |
946 | |
947 | === modified file 'python/libertine/ChrootContainer.py' |
948 | --- python/libertine/ChrootContainer.py 2016-02-08 16:47:18 +0000 |
949 | +++ python/libertine/ChrootContainer.py 2016-03-21 12:56:41 +0000 |
950 | @@ -67,8 +67,9 @@ |
951 | def destroy_libertine_container(self): |
952 | shutil.rmtree(self.root_path) |
953 | |
954 | - def create_libertine_container(self, password=None, verbosity=1): |
955 | + def create_libertine_container(self, password=None, multiarch=False, verbosity=1): |
956 | installed_release = self.get_container_distro(self.container_id) |
957 | + architecture = utils.get_host_architecture() |
958 | |
959 | # Create the actual chroot |
960 | if installed_release == "trusty": |
961 | @@ -96,7 +97,7 @@ |
962 | fd.write("done\n") |
963 | os.fchmod(fd.fileno(), 0o755) |
964 | |
965 | - # Add universe and -updates to the chroot's sources.list |
966 | + # Add universe, multiverse, and -updates to the chroot's sources.list |
967 | if (utils.get_host_architecture() == 'armhf'): |
968 | archive = "deb http://ports.ubuntu.com/ubuntu-ports " |
969 | else: |
970 | @@ -105,9 +106,11 @@ |
971 | if verbosity == 1: |
972 | print("Updating chroot's sources.list entries...") |
973 | with open(os.path.join(self.root_path, 'etc', 'apt', 'sources.list'), 'a') as fd: |
974 | + fd.write(archive + installed_release + "-updates main\n") |
975 | fd.write(archive + installed_release + " universe\n") |
976 | - fd.write(archive + installed_release + "-updates main\n") |
977 | fd.write(archive + installed_release + "-updates universe\n") |
978 | + fd.write(archive + installed_release + " multiverse\n") |
979 | + fd.write(archive + installed_release + "-updates multiverse\n") |
980 | |
981 | utils.create_libertine_user_data_dir(self.container_id) |
982 | |
983 | @@ -151,10 +154,16 @@ |
984 | args = shlex.split(command_line) |
985 | cmd = subprocess.Popen(args).wait() |
986 | |
987 | + if multiarch and architecture == 'amd64': |
988 | + if verbosity == 1: |
989 | + print("Adding i386 multiarch support...") |
990 | + self.run_in_container("dpkg --add-architecture i386") |
991 | + |
992 | if verbosity == 1: |
993 | print("Updating the contents of the container after creation...") |
994 | self.update_packages(verbosity) |
995 | self.install_package("libnss-extrausers", verbosity) |
996 | + self.install_package("software-properties-common", verbosity) |
997 | |
998 | if verbosity == 1: |
999 | print("Installing Matchbox as the Xmir window manager...") |
1000 | |
1001 | === modified file 'python/libertine/Libertine.py' |
1002 | --- python/libertine/Libertine.py 2016-02-10 19:31:10 +0000 |
1003 | +++ python/libertine/Libertine.py 2016-03-21 12:56:41 +0000 |
1004 | @@ -18,6 +18,7 @@ |
1005 | import contextlib |
1006 | import json |
1007 | import libertine.utils |
1008 | +import os |
1009 | |
1010 | |
1011 | def get_container_type(container_id): |
1012 | @@ -133,10 +134,20 @@ |
1013 | """ |
1014 | if command == 'multiarch': |
1015 | if args[0] == 'enable': |
1016 | - self.run_in_container("dpkg --add-architecture i386") |
1017 | + return self.run_in_container("dpkg --add-architecture i386") |
1018 | else: |
1019 | self.run_in_container(apt_command_prefix(verbosity) + "purge \".*:i386\"") |
1020 | - self.run_in_container("dpkg --remove-architecture i386") |
1021 | + return self.run_in_container("dpkg --remove-architecture i386") |
1022 | + |
1023 | + elif command == 'add-archive': |
1024 | + if not os.path.exists(os.path.join(self.root_path, 'usr', 'bin', 'add-apt-repository')): |
1025 | + self.update_packages(verbosity) |
1026 | + self.install_package("software-properties-common", verbosity) |
1027 | + |
1028 | + return self.run_in_container("add-apt-repository -y " + args[0]) |
1029 | + |
1030 | + elif command == 'delete-archive': |
1031 | + return self.run_in_container("add-apt-repository -y -r " + args[0]) |
1032 | |
1033 | def get_container_distro(self, container_id): |
1034 | """ |
1035 | @@ -323,8 +334,8 @@ |
1036 | :rtype: The output of the given command. |
1037 | """ |
1038 | with ContainerRunning(self.container): |
1039 | - self.container.run_in_container(exec_line) |
1040 | + return self.container.run_in_container(exec_line) |
1041 | |
1042 | def configure_command(self, command, *args): |
1043 | with ContainerRunning(self.container): |
1044 | - self.container.configure_command(command, *args) |
1045 | + return self.container.configure_command(command, *args) |
1046 | |
1047 | === modified file 'python/libertine/LxcContainer.py' |
1048 | --- python/libertine/LxcContainer.py 2016-02-09 20:59:51 +0000 |
1049 | +++ python/libertine/LxcContainer.py 2016-03-21 12:56:41 +0000 |
1050 | @@ -189,6 +189,8 @@ |
1051 | print("Updating the contents of the container after creation...") |
1052 | self.update_packages(verbosity) |
1053 | |
1054 | + self.install_package("software-properties-common", verbosity) |
1055 | + |
1056 | if verbosity == 1: |
1057 | print("Installing Matchbox as the Xmir window manager...") |
1058 | self.install_package('matchbox', verbosity=verbosity) |
1059 | |
1060 | === modified file 'python/libertine/utils.py' |
1061 | --- python/libertine/utils.py 2015-12-23 02:34:16 +0000 |
1062 | +++ python/libertine/utils.py 2016-03-21 12:56:41 +0000 |
1063 | @@ -125,3 +125,7 @@ |
1064 | def terminate_window_manager(window_manager): |
1065 | for child in window_manager.children(): |
1066 | child.terminate() |
1067 | + child.wait() |
1068 | + |
1069 | + window_manager.terminate() |
1070 | + window_manager.wait() |
1071 | |
1072 | === modified file 'tools/libertine-container-manager' |
1073 | --- tools/libertine-container-manager 2016-02-10 19:31:10 +0000 |
1074 | +++ tools/libertine-container-manager 2016-03-21 12:56:41 +0000 |
1075 | @@ -127,6 +127,64 @@ |
1076 | return container['multiarch'] |
1077 | |
1078 | |
1079 | +def update_archive_install_status(container_id, archive_name, new_status): |
1080 | + container_list = read_container_config_file() |
1081 | + |
1082 | + for container in container_list['containerList']: |
1083 | + if container['id'] == container_id: |
1084 | + for archive in container['extraArchives']: |
1085 | + if archive['archiveName'] == archive_name: |
1086 | + archive['archiveStatus'] = new_status |
1087 | + write_container_config_file(container_list) |
1088 | + return |
1089 | + |
1090 | + |
1091 | +def add_container_archive(container_id, archive_name): |
1092 | + container_list = read_container_config_file() |
1093 | + |
1094 | + for container in container_list['containerList']: |
1095 | + if container['id'] == container_id: |
1096 | + archive_obj = {'archiveName': archive_name, 'archiveStatus': 'new'} |
1097 | + |
1098 | + if 'extraArchives' not in container: |
1099 | + container['extraArchives'] = [archive_obj] |
1100 | + else: |
1101 | + container['extraArchives'].append(archive_obj) |
1102 | + |
1103 | + write_container_config_file(container_list) |
1104 | + break |
1105 | + |
1106 | + |
1107 | +def delete_container_archive(container_id, archive_name): |
1108 | + container_list = read_container_config_file() |
1109 | + |
1110 | + for container in container_list['containerList']: |
1111 | + if container['id'] == container_id: |
1112 | + for archive in container['extraArchives']: |
1113 | + if archive['archiveName'] == archive_name: |
1114 | + container['extraArchives'].remove(archive) |
1115 | + write_container_config_file(container_list) |
1116 | + return |
1117 | + |
1118 | + print("%s does not exist." % archive_name) |
1119 | + sys.exit(1) |
1120 | + |
1121 | + |
1122 | +def archive_exists(container_id, archive_name): |
1123 | + container_list = read_container_config_file() |
1124 | + |
1125 | + for container in container_list['containerList']: |
1126 | + if container['id'] == container_id: |
1127 | + if 'extraArchives' not in container: |
1128 | + return False |
1129 | + else: |
1130 | + for archive in container['extraArchives']: |
1131 | + if archive['archiveName'] == archive_name: |
1132 | + return True |
1133 | + |
1134 | + return False |
1135 | + |
1136 | + |
1137 | def add_new_container(id, name, type, distro): |
1138 | if not os.path.exists(libertine.utils.get_libertine_database_dir_path()): |
1139 | os.makedirs(libertine.utils.get_libertine_database_dir_path()) |
1140 | @@ -379,7 +437,7 @@ |
1141 | |
1142 | container = LibertineContainer(args.id) |
1143 | |
1144 | - container.exec_command(args.command) |
1145 | + sys.exit(container.exec_command(args.command)) |
1146 | |
1147 | |
1148 | def configure(args): |
1149 | @@ -399,11 +457,36 @@ |
1150 | current_multiarch = get_container_multiarch_support(args.id) |
1151 | if current_multiarch == multiarch: |
1152 | print("i386 multiarch support is already %s" % multiarch) |
1153 | - sys.exit(0) |
1154 | + sys.exit(1) |
1155 | |
1156 | container.configure_command('multiarch', args.multiarch) |
1157 | update_container_multiarch_support(args.id, multiarch) |
1158 | |
1159 | + elif args.add_archive: |
1160 | + if archive_exists(args.id, args.add_archive): |
1161 | + print("%s already added in container." % args.add_archive) |
1162 | + sys.exit(1) |
1163 | + |
1164 | + add_container_archive(args.id, args.add_archive) |
1165 | + update_archive_install_status(args.id, args.add_archive, 'installing') |
1166 | + if container.configure_command('add-archive', args.add_archive) != 0: |
1167 | + delete_container_archive(args.id, args.add_archive) |
1168 | + sys.exit(1) |
1169 | + |
1170 | + update_archive_install_status(args.id, args.add_archive, 'installed') |
1171 | + |
1172 | + |
1173 | + elif args.delete_archive: |
1174 | + if not archive_exists(args.id, args.delete_archive): |
1175 | + print("%s is not added in container." % args.delete_archive) |
1176 | + sys.exit(1) |
1177 | + |
1178 | + update_archive_install_status(args.id, args.delete_archive, 'removing') |
1179 | + if container.configure_command('delete-archive', args.delete_archive) != 0: |
1180 | + sys.exit(1) |
1181 | + |
1182 | + delete_container_archive(args.id, args.delete_archive) |
1183 | + |
1184 | |
1185 | if __name__ == '__main__': |
1186 | parser = argparse.ArgumentParser(description="Legacy X application support for Unity 8") |
1187 | @@ -543,6 +626,16 @@ |
1188 | help=("Enables or disables i386 multiarch support for amd64 Libertine " |
1189 | "containers. This option has no effect when the Libertine " |
1190 | "container is i386.")) |
1191 | + parser_configure.add_argument( |
1192 | + '-a', '--add-archive', |
1193 | + metavar='Archive name', |
1194 | + help=("Adds an archive (PPA) in the specified Libertine container. Needs to be " |
1195 | + "in the form of \"ppa:user/ppa-name\".")) |
1196 | + parser_configure.add_argument( |
1197 | + '-d', '--delete-archive', |
1198 | + metavar='Archive name', |
1199 | + help=("Deletes an existing archive (PPA) in the specified Libertine container. " |
1200 | + "Needs to be in the form of \"ppa:user/ppa-name\".")) |
1201 | parser_configure.set_defaults(func=configure) |
1202 | |
1203 | # Actually parse the args |