Merge lp:~larryprice/libertine/bind-mount-gui into lp:libertine
- bind-mount-gui
- Merge into devel
Status: | Merged |
---|---|
Approved by: | Larry Price |
Approved revision: | 399 |
Merged at revision: | 411 |
Proposed branch: | lp:~larryprice/libertine/bind-mount-gui |
Merge into: | lp:libertine |
Diff against target: |
698 lines (+387/-18) 18 files modified
common/CMakeLists.txt (+1/-0) common/ContainerArchivesList.cpp (+1/-0) common/ContainerArchivesList.h (+3/-4) common/ContainerBindMountsList.cpp (+87/-0) common/ContainerBindMountsList.h (+76/-0) common/ContainerConfigList.cpp (+8/-1) common/ContainerConfigList.h (+10/-8) common/ContainersConfig.cpp (+25/-1) common/ContainersConfig.h (+14/-0) debian/control (+1/-0) libertine/CMakeLists.txt (+1/-3) libertine/libertine.cpp (+3/-0) libertine/libertine.h (+2/-0) qml/common/AddBindMountDialog.qml (+27/-0) qml/common/ExtraBindMountsView.qml (+110/-0) qml/common/ManageContainer.qml (+9/-0) tests/unit/ContainersConfigTests.cpp (+8/-0) tools/libertine-container-manager (+1/-1) |
To merge this branch: | bzr merge lp:~larryprice/libertine/bind-mount-gui |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Libertine CI Bot | continuous-integration | Approve | |
Christopher Townsend | Approve | ||
Review via email: mp+317546@code.launchpad.net |
Commit message
Implement GUI for adding and removing bind-mounts in containers.
Description of the change
Implement GUI for adding and removing bind-mounts to containers.
Libertine CI Bot (libertine-ci-bot) wrote : | # |
Libertine CI Bot (libertine-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:396
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Libertine CI Bot (libertine-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:397
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Libertine CI Bot (libertine-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:398
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Libertine CI Bot (libertine-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:398
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Christopher Townsend (townsend) wrote : | # |
As mentioned on irc, the FileDialog pops up as a very small horizontal line and I happened to resize it by chance. If there is a way to try to set a default size for the dialog, that would be great.
Also, a couple of code style nitpicks inline.
Libertine CI Bot (libertine-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:399
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Christopher Townsend (townsend) wrote : | # |
Ok, +1.
I will note that there isn't any way to protect against the weird horizontal line FileDialog I saw, so we'll leave it as is and hope I'm the outlier.
Libertine CI Bot (libertine-ci-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Libertine CI Bot (libertine-ci-bot) : | # |
Preview Diff
1 | === modified file 'common/CMakeLists.txt' |
2 | --- common/CMakeLists.txt 2017-02-08 14:09:03 +0000 |
3 | +++ common/CMakeLists.txt 2017-02-22 20:19:40 +0000 |
4 | @@ -1,6 +1,7 @@ |
5 | add_library(${LIBERTINE_COMMON} |
6 | ContainerAppsList.cpp |
7 | ContainerArchivesList.cpp |
8 | + ContainerBindMountsList.cpp |
9 | ContainersConfig.cpp |
10 | ContainerConfigList.cpp |
11 | ContainerManager.cpp |
12 | |
13 | === modified file 'common/ContainerArchivesList.cpp' |
14 | --- common/ContainerArchivesList.cpp 2017-02-08 14:57:34 +0000 |
15 | +++ common/ContainerArchivesList.cpp 2017-02-22 20:19:40 +0000 |
16 | @@ -20,6 +20,7 @@ |
17 | |
18 | #include "common/ContainerConfigList.h" |
19 | |
20 | + |
21 | ContainerArchivesList:: |
22 | ContainerArchivesList(ContainerConfigList* container_config_list, |
23 | QObject* parent) |
24 | |
25 | === modified file 'common/ContainerArchivesList.h' |
26 | --- common/ContainerArchivesList.h 2017-02-08 13:10:10 +0000 |
27 | +++ common/ContainerArchivesList.h 2017-02-22 20:19:40 +0000 |
28 | @@ -18,14 +18,13 @@ |
29 | */ |
30 | #pragma once |
31 | |
32 | +#include "common/ContainersConfig.h" |
33 | #include <QtCore/QAbstractListModel> |
34 | #include <QtCore/QList> |
35 | #include <QtCore/QObject> |
36 | #include <QtCore/QString> |
37 | -#include "common/ContainersConfig.h" |
38 | - |
39 | - |
40 | -class ContainerArchives; |
41 | + |
42 | + |
43 | class ContainerConfigList; |
44 | |
45 | class ContainerArchivesList |
46 | |
47 | === added file 'common/ContainerBindMountsList.cpp' |
48 | --- common/ContainerBindMountsList.cpp 1970-01-01 00:00:00 +0000 |
49 | +++ common/ContainerBindMountsList.cpp 2017-02-22 20:19:40 +0000 |
50 | @@ -0,0 +1,87 @@ |
51 | +/** |
52 | + * @file ContainerBindMountsList.cpp |
53 | + * @brief Libertine Manager list of all mapped directories |
54 | + */ |
55 | +/* |
56 | + * Copyright 2017 Canonical Ltd |
57 | + * |
58 | + * Libertine is free software: you can redistribute it and/or modify it under |
59 | + * the terms of the GNU General Public License, version 3, as published by the |
60 | + * Free Software Foundation. |
61 | + * |
62 | + * Libertine is distributed in the hope that it will be useful, but WITHOUT ANY |
63 | + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR |
64 | + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
65 | + * |
66 | + * You should have received a copy of the GNU General Public License |
67 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
68 | + */ |
69 | +#include "common/ContainerBindMountsList.h" |
70 | + |
71 | +#include "common/ContainerConfigList.h" |
72 | + |
73 | + |
74 | +ContainerBindMountsList:: |
75 | +ContainerBindMountsList(ContainerConfigList* container_config_list, |
76 | + QObject* parent) |
77 | +: QAbstractListModel(parent) |
78 | +, container_config_list_(container_config_list) |
79 | +{ } |
80 | + |
81 | + |
82 | +void ContainerBindMountsList:: |
83 | +setContainerBindMounts(QString const& container_id) |
84 | +{ |
85 | + mounts_ = container_config_list_->getBindMountsForContainer(container_id); |
86 | + |
87 | + beginResetModel(); |
88 | + endResetModel(); |
89 | +} |
90 | + |
91 | + |
92 | +bool ContainerBindMountsList:: |
93 | +empty() const noexcept |
94 | +{ return mounts_.empty(); } |
95 | + |
96 | + |
97 | +ContainerBindMountsList::size_type ContainerBindMountsList:: |
98 | +size() const noexcept |
99 | +{ return mounts_.count(); } |
100 | + |
101 | + |
102 | +int ContainerBindMountsList:: |
103 | +rowCount(QModelIndex const&) const |
104 | +{ |
105 | + return this->size(); |
106 | +} |
107 | + |
108 | + |
109 | +QHash<int, QByteArray> ContainerBindMountsList:: |
110 | +roleNames() const |
111 | +{ |
112 | + QHash<int, QByteArray> roles; |
113 | + roles[static_cast<int>(DataRole::BindMountPath)] = "path"; |
114 | + |
115 | + return roles; |
116 | +} |
117 | + |
118 | + |
119 | +QVariant ContainerBindMountsList:: |
120 | +data(QModelIndex const& index, int role) const |
121 | +{ |
122 | + QVariant result; |
123 | + |
124 | + if (index.isValid() && index.row() <= mounts_.count()) |
125 | + { |
126 | + switch (static_cast<DataRole>(role)) |
127 | + { |
128 | + case DataRole::BindMountPath: |
129 | + result = mounts_[index.row()].path; |
130 | + break; |
131 | + case DataRole::Error: |
132 | + break; |
133 | + } |
134 | + } |
135 | + |
136 | + return result; |
137 | +} |
138 | |
139 | === added file 'common/ContainerBindMountsList.h' |
140 | --- common/ContainerBindMountsList.h 1970-01-01 00:00:00 +0000 |
141 | +++ common/ContainerBindMountsList.h 2017-02-22 20:19:40 +0000 |
142 | @@ -0,0 +1,76 @@ |
143 | +/** |
144 | + * @file ContainerBindMountsList.h |
145 | + * @brief Libertine Manager list of extra container archives (PPAs) |
146 | + */ |
147 | +/* |
148 | + * Copyright 2017 Canonical Ltd |
149 | + * |
150 | + * Libertine is free software: you can redistribute it and/or modify it under |
151 | + * the terms of the GNU General Public License, version 3, as published by the |
152 | + * Free Software Foundation. |
153 | + * |
154 | + * Libertine is distributed in the hope that it will be useful, but WITHOUT ANY |
155 | + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR |
156 | + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
157 | + * |
158 | + * You should have received a copy of the GNU General Public License |
159 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
160 | + */ |
161 | +#pragma once |
162 | + |
163 | +#include "common/ContainersConfig.h" |
164 | +#include <QtCore/QAbstractListModel> |
165 | +#include <QtCore/QList> |
166 | +#include <QtCore/QObject> |
167 | +#include <QtCore/QString> |
168 | + |
169 | + |
170 | +class ContainerConfigList; |
171 | + |
172 | +class ContainerBindMountsList |
173 | +: public QAbstractListModel |
174 | +{ |
175 | + Q_OBJECT |
176 | + |
177 | +public: |
178 | + using BindMountsList = QList<ContainersConfig::Container::BindMount>; |
179 | + using iterator = BindMountsList::iterator; |
180 | + using size_type = BindMountsList::size_type; |
181 | + |
182 | + enum class DataRole |
183 | + : int |
184 | + { |
185 | + BindMountPath = Qt::UserRole + 1, |
186 | + Error |
187 | + }; |
188 | + |
189 | +public: |
190 | + explicit |
191 | + ContainerBindMountsList(ContainerConfigList* container_config_list, |
192 | + QObject* parent = nullptr); |
193 | + |
194 | + virtual |
195 | + ~ContainerBindMountsList() = default; |
196 | + |
197 | + Q_INVOKABLE void |
198 | + setContainerBindMounts(QString const& container_id); |
199 | + |
200 | + Q_INVOKABLE bool |
201 | + empty() const noexcept; |
202 | + |
203 | + size_type |
204 | + size() const noexcept; |
205 | + |
206 | + int |
207 | + rowCount(QModelIndex const& parent = QModelIndex()) const; |
208 | + |
209 | + QHash<int, QByteArray> |
210 | + roleNames() const; |
211 | + |
212 | + QVariant |
213 | + data(QModelIndex const& index, int role = Qt::DisplayRole) const; |
214 | + |
215 | +private: |
216 | + ContainerConfigList* container_config_list_; |
217 | + BindMountsList mounts_; |
218 | +}; |
219 | |
220 | === modified file 'common/ContainerConfigList.cpp' |
221 | --- common/ContainerConfigList.cpp 2017-02-08 15:08:24 +0000 |
222 | +++ common/ContainerConfigList.cpp 2017-02-22 20:19:40 +0000 |
223 | @@ -34,9 +34,9 @@ |
224 | #include <QtCore/QStandardPaths> |
225 | #include <QtCore/QString> |
226 | #include <QtCore/QSysInfo> |
227 | - |
228 | #include <sys/file.h> |
229 | |
230 | + |
231 | namespace |
232 | { |
233 | static constexpr auto POLICY_INSTALLED_VERSION_LINE = 1; |
234 | @@ -235,6 +235,13 @@ |
235 | } |
236 | |
237 | |
238 | +QList<ContainersConfig::Container::BindMount> ContainerConfigList:: |
239 | +getBindMountsForContainer(QString const& container_id) |
240 | +{ |
241 | + return find_container_by_id(containers_config_->containers, container_id).mounts; |
242 | +} |
243 | + |
244 | + |
245 | QString ContainerConfigList:: |
246 | getContainerType(QString const& container_id) |
247 | { |
248 | |
249 | === modified file 'common/ContainerConfigList.h' |
250 | --- common/ContainerConfigList.h 2017-02-13 20:57:03 +0000 |
251 | +++ common/ContainerConfigList.h 2017-02-22 20:19:40 +0000 |
252 | @@ -18,15 +18,15 @@ |
253 | */ |
254 | #pragma once |
255 | |
256 | + |
257 | +#include "common/ContainersConfig.h" |
258 | +#include <memory> |
259 | #include <QtCore/QAbstractListModel> |
260 | #include <QtCore/QJsonObject> |
261 | #include <QtCore/QList> |
262 | -#include <memory> |
263 | -#include "common/ContainersConfig.h" |
264 | + |
265 | |
266 | class ContainerApps; |
267 | -class ContainerArchives; |
268 | -class ContainerConfig; |
269 | class LibertineConfig; |
270 | |
271 | |
272 | @@ -44,9 +44,7 @@ |
273 | NOTIFY defaultContainerChanged) |
274 | |
275 | public: |
276 | - using ConfigList = QList<ContainerConfig*>; |
277 | - using iterator = ConfigList::iterator; |
278 | - using size_type = ConfigList::size_type; |
279 | + using size_type = QList<ContainersConfig::Container>::size_type; |
280 | |
281 | static const QString Json_container_list; |
282 | static const QString Json_default_container; |
283 | @@ -74,12 +72,14 @@ |
284 | /** |
285 | * Constructs a container config list from a container config. |
286 | */ |
287 | + explicit |
288 | ContainerConfigList(LibertineConfig const* config, |
289 | QObject* parent = nullptr); |
290 | |
291 | /** |
292 | * Constructs a container config list from a raw json string |
293 | */ |
294 | + explicit |
295 | ContainerConfigList(QJsonObject const& json_object, |
296 | QObject* parent = nullptr); |
297 | |
298 | @@ -127,6 +127,9 @@ |
299 | QList<ContainersConfig::Container::Archive> |
300 | getArchivesForContainer(QString const& container_id); |
301 | |
302 | + QList<ContainersConfig::Container::BindMount> |
303 | + getBindMountsForContainer(QString const& container_id); |
304 | + |
305 | Q_INVOKABLE QString |
306 | getContainerType(QString const& container_id); |
307 | |
308 | @@ -228,7 +231,6 @@ |
309 | |
310 | private: |
311 | LibertineConfig const* config_; |
312 | - ConfigList configs_; |
313 | QString default_container_id_; |
314 | std::unique_ptr<ContainersConfig> containers_config_; |
315 | }; |
316 | |
317 | === modified file 'common/ContainersConfig.cpp' |
318 | --- common/ContainersConfig.cpp 2017-02-13 22:18:18 +0000 |
319 | +++ common/ContainersConfig.cpp 2017-02-22 20:19:40 +0000 |
320 | @@ -12,7 +12,6 @@ |
321 | * You should have received a copy of the GNU General Public License |
322 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
323 | */ |
324 | - |
325 | #include "ContainersConfig.h" |
326 | |
327 | #include <QJsonArray> |
328 | @@ -63,6 +62,19 @@ |
329 | } |
330 | |
331 | |
332 | +ContainersConfig::Container::BindMount:: |
333 | +BindMount(QString const& json) |
334 | +: path(json) |
335 | +{ } |
336 | + |
337 | + |
338 | +QString ContainersConfig::Container::BindMount:: |
339 | +dump() const |
340 | +{ |
341 | + return path; |
342 | +} |
343 | + |
344 | + |
345 | ContainersConfig::Container::InstalledApp:: |
346 | InstalledApp(QJsonObject const& json) |
347 | : status_(try_get_string(json, "appStatus")) |
348 | @@ -110,6 +122,11 @@ |
349 | { |
350 | installed_apps.append(InstalledApp(app.toObject())); |
351 | } |
352 | + |
353 | + for (auto const& mount: json["bindMounts"].toArray()) |
354 | + { |
355 | + mounts.append(BindMount(mount.toString())); |
356 | + } |
357 | } |
358 | |
359 | |
360 | @@ -138,6 +155,13 @@ |
361 | } |
362 | object["installedApps"] = installed_apps_list; |
363 | |
364 | + QJsonArray mounts_list; |
365 | + for (auto const& mount: mounts) |
366 | + { |
367 | + mounts_list.append(mount.dump()); |
368 | + } |
369 | + object["bindMounts"] = mounts_list; |
370 | + |
371 | return object; |
372 | } |
373 | |
374 | |
375 | === modified file 'common/ContainersConfig.h' |
376 | --- common/ContainersConfig.h 2017-02-13 22:18:18 +0000 |
377 | +++ common/ContainersConfig.h 2017-02-22 20:19:40 +0000 |
378 | @@ -73,6 +73,19 @@ |
379 | QString status; |
380 | }; |
381 | |
382 | + |
383 | + class BindMount |
384 | + { |
385 | + public: |
386 | + explicit BindMount(QString const& json); |
387 | + virtual ~BindMount() = default; |
388 | + |
389 | + QString dump() const; |
390 | + |
391 | + public: |
392 | + QString path; |
393 | + }; |
394 | + |
395 | private: |
396 | QString status_; // untranslated |
397 | |
398 | @@ -84,6 +97,7 @@ |
399 | QString type; |
400 | QString multiarch; |
401 | QList<Archive> archives; |
402 | + QList<BindMount> mounts; |
403 | QList<InstalledApp> installed_apps; |
404 | }; |
405 | |
406 | |
407 | === modified file 'debian/control' |
408 | --- debian/control 2017-02-16 14:05:23 +0000 |
409 | +++ debian/control 2017-02-22 20:19:40 +0000 |
410 | @@ -73,6 +73,7 @@ |
411 | Package: libertine-qt-common |
412 | Architecture: any |
413 | Depends: qml-module-qtquick2, |
414 | + qml-module-qtquick-dialogs, |
415 | qtdeclarative5-ubuntu-ui-toolkit-plugin, |
416 | ${misc:Depends}, |
417 | ${shlibs:Depends} |
418 | |
419 | === modified file 'libertine/CMakeLists.txt' |
420 | --- libertine/CMakeLists.txt 2016-10-07 21:04:06 +0000 |
421 | +++ libertine/CMakeLists.txt 2017-02-22 20:19:40 +0000 |
422 | @@ -12,8 +12,6 @@ |
423 | ) |
424 | |
425 | add_executable(${LIBERTINE_EXE_NAME} ${libertine_SRC}) |
426 | -target_link_libraries(${LIBERTINE_EXE_NAME} ${LIBERTINE_COMMON} ${LIBERTINE_CORE} Qt5::Core Qt5::Quick Qt5::Gui) |
427 | - |
428 | -install(DIRECTORY qml DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${CMAKE_PROJECT_NAME}) |
429 | +target_link_libraries(${LIBERTINE_EXE_NAME} ${LIBERTINE_COMMON} Qt5::Core Qt5::Quick Qt5::Gui) |
430 | |
431 | install(TARGETS ${LIBERTINE_EXE_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) |
432 | |
433 | === modified file 'libertine/libertine.cpp' |
434 | --- libertine/libertine.cpp 2017-02-08 14:23:49 +0000 |
435 | +++ libertine/libertine.cpp 2017-02-22 20:19:40 +0000 |
436 | @@ -21,6 +21,7 @@ |
437 | #include "common/ContainerManager.h" |
438 | #include "common/ContainerAppsList.h" |
439 | #include "common/ContainerArchivesList.h" |
440 | +#include "common/ContainerBindMountsList.h" |
441 | #include "common/ContainerConfigList.h" |
442 | #include "common/LibertineConfig.h" |
443 | #include "common/PackageOperationDetails.h" |
444 | @@ -114,6 +115,7 @@ |
445 | containers_ = new ContainerConfigList(config_.data(), this); |
446 | container_apps_ = new ContainerAppsList(containers_, this); |
447 | container_archives_ = new ContainerArchivesList(containers_, this); |
448 | + container_bind_mounts_ = new ContainerBindMountsList(containers_, this); |
449 | package_operation_details_ = new PackageOperationDetails(this); |
450 | |
451 | initialize_view(); |
452 | @@ -141,6 +143,7 @@ |
453 | ctxt->setContextProperty("containerConfigList", containers_); |
454 | ctxt->setContextProperty("containerAppsList", container_apps_); |
455 | ctxt->setContextProperty("containerArchivesList", container_archives_); |
456 | + ctxt->setContextProperty("containerBindMountsList", container_bind_mounts_); |
457 | ctxt->setContextProperty("packageOperationDetails", package_operation_details_); |
458 | |
459 | view_.setSource(QUrl::fromLocalFile(main_qml_source_file_)); |
460 | |
461 | === modified file 'libertine/libertine.h' |
462 | --- libertine/libertine.h 2016-10-03 20:30:29 +0000 |
463 | +++ libertine/libertine.h 2017-02-22 20:19:40 +0000 |
464 | @@ -30,6 +30,7 @@ |
465 | class LibertineConfig; |
466 | class ContainerAppsList; |
467 | class ContainerArchivesList; |
468 | +class ContainerBindMountsList; |
469 | class PackageOperationDetails; |
470 | |
471 | |
472 | @@ -57,6 +58,7 @@ |
473 | ContainerConfigList* containers_; |
474 | ContainerAppsList* container_apps_; |
475 | ContainerArchivesList* container_archives_; |
476 | + ContainerBindMountsList* container_bind_mounts_; |
477 | PackageOperationDetails* package_operation_details_; |
478 | QQuickView view_; |
479 | }; |
480 | |
481 | === removed directory 'libertine/qml' |
482 | === added file 'qml/common/AddBindMountDialog.qml' |
483 | --- qml/common/AddBindMountDialog.qml 1970-01-01 00:00:00 +0000 |
484 | +++ qml/common/AddBindMountDialog.qml 2017-02-22 20:19:40 +0000 |
485 | @@ -0,0 +1,27 @@ |
486 | +/* |
487 | + * Copyright 2017 Canonical Ltd |
488 | + * |
489 | + * Libertine is free software: you can redistribute it and/or modify it under |
490 | + * the terms of the GNU General Public License, version 3, as published by the |
491 | + * Free Software Foundation. |
492 | + * |
493 | + * Libertine is distributed in the hope that it will be useful, but WITHOUT ANY |
494 | + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR |
495 | + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
496 | + * |
497 | + * You should have received a copy of the GNU General Public License |
498 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
499 | + */ |
500 | +import QtQuick 2.4 |
501 | +import QtQuick.Dialogs 1.0 |
502 | + |
503 | +FileDialog { |
504 | + id: addBindMountDialog |
505 | + title: "Choose directory to bind-mount" |
506 | + selectFolder: true |
507 | + onAccepted: { |
508 | + if (addBindMountDialog.fileUrl) { |
509 | + extraBindMountsView.addBindMount(addBindMountDialog.fileUrl.toString().replace("file:///", "/")) |
510 | + } |
511 | + } |
512 | +} |
513 | |
514 | === added file 'qml/common/ExtraBindMountsView.qml' |
515 | --- qml/common/ExtraBindMountsView.qml 1970-01-01 00:00:00 +0000 |
516 | +++ qml/common/ExtraBindMountsView.qml 2017-02-22 20:19:40 +0000 |
517 | @@ -0,0 +1,110 @@ |
518 | +/* |
519 | + * Copyright 2017 Canonical Ltd |
520 | + * |
521 | + * Libertine is free software: you can redistribute it and/or modify it under |
522 | + * the terms of the GNU General Public License, version 3, as published by the |
523 | + * Free Software Foundation. |
524 | + * |
525 | + * Libertine is distributed in the hope that it will be useful, but WITHOUT ANY |
526 | + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR |
527 | + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
528 | + * |
529 | + * You should have received a copy of the GNU General Public License |
530 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
531 | + */ |
532 | +import Libertine 1.0 |
533 | +import QtQuick 2.4 |
534 | +import Ubuntu.Components 1.3 |
535 | + |
536 | +Page { |
537 | + id: extraBindMountsView |
538 | + clip: true |
539 | + header: PageHeader { |
540 | + id: pageHeader |
541 | + title: i18n.tr("Mapped Directories") |
542 | + trailingActionBar.actions: [ |
543 | + Action { |
544 | + iconName: "add" |
545 | + text: i18n.tr("add") |
546 | + description: i18n.tr("Add a new bind-mount") |
547 | + onTriggered: { |
548 | + var fileDialog = Qt.createComponent("AddBindMountDialog.qml").createObject(extraBindMountsView) |
549 | + fileDialog.open() |
550 | + } |
551 | + } |
552 | + ] |
553 | + } |
554 | + property string currentContainer: "" |
555 | + |
556 | + signal error(string description, string details) |
557 | + |
558 | + UbuntuListView { |
559 | + id: bindMountsListView |
560 | + anchors { |
561 | + topMargin: pageHeader.height |
562 | + fill: parent |
563 | + } |
564 | + model: containerBindMountsList |
565 | + visible: !containerBindMountsList.empty() |
566 | + delegate: ListItem { |
567 | + Label { |
568 | + anchors { |
569 | + verticalCenter: parent.verticalCenter |
570 | + left: parent.left |
571 | + leftMargin: units.gu(2) |
572 | + } |
573 | + text: path |
574 | + width: parent.width - units.gu(8) |
575 | + elide: Text.ElideMiddle |
576 | + } |
577 | + leadingActions: ListItemActions { |
578 | + actions: [ |
579 | + Action { |
580 | + iconName: "delete" |
581 | + text: i18n.tr("remove") |
582 | + description: i18n.tr("Remove mapped directory") |
583 | + onTriggered: { |
584 | + deleteBindMount(path) |
585 | + } |
586 | + } |
587 | + ] |
588 | + } |
589 | + } |
590 | + } |
591 | + |
592 | + Label { |
593 | + id: emptyLabel |
594 | + anchors.centerIn: parent |
595 | + visible: !bindMountsListView.visible |
596 | + wrapMode: Text.Wrap |
597 | + width: parent.width |
598 | + horizontalAlignment: Text.AlignHCenter |
599 | + text: i18n.tr("No custom bind-mounts have been added to this container.\n" + |
600 | + "Adding a directory here will allow you to modify its contents within this container.") |
601 | + } |
602 | + |
603 | + function deleteBindMount(mount) { |
604 | + var worker = Qt.createComponent("ContainerManager.qml").createObject(mainView) |
605 | + worker.error.connect(packageOperationDetails.error) |
606 | + worker.configureContainer(currentContainer, containerConfigList.getContainerName(currentContainer), ["--bind-mount", "remove", "--mount-path", "\"" + mount + "\""]) |
607 | + } |
608 | + |
609 | + function addBindMount(mount) { |
610 | + var worker = Qt.createComponent("ContainerManager.qml").createObject(mainView) |
611 | + worker.error.connect(packageOperationDetails.error) |
612 | + worker.configureContainer(currentContainer, containerConfigList.getContainerName(currentContainer), ["--bind-mount", "add", "--mount-path", "\"" + mount + "\""]) |
613 | + } |
614 | + |
615 | + Component.onCompleted: { |
616 | + containerConfigList.configChanged.connect(reloadMounts) |
617 | + } |
618 | + |
619 | + Component.onDestruction: { |
620 | + containerConfigList.configChanged.disconnect(reloadMounts) |
621 | + } |
622 | + |
623 | + function reloadMounts() { |
624 | + containerBindMountsList.setContainerBindMounts(currentContainer) |
625 | + bindMountsListView.visible = !containerBindMountsList.empty() |
626 | + } |
627 | +} |
628 | |
629 | === modified file 'qml/common/ManageContainer.qml' |
630 | --- qml/common/ManageContainer.qml 2017-02-06 16:35:18 +0000 |
631 | +++ qml/common/ManageContainer.qml 2017-02-22 20:19:40 +0000 |
632 | @@ -78,6 +78,15 @@ |
633 | } |
634 | } |
635 | |
636 | + ListItem.SingleValue { |
637 | + text: i18n.tr("Additional bind-mounts") |
638 | + progression: true |
639 | + onClicked: { |
640 | + containerBindMountsList.setContainerBindMounts(currentContainer) |
641 | + pageStack.addPageToNextColumn(manageView, Qt.resolvedUrl("ExtraBindMountsView.qml"), {currentContainer: currentContainer}) |
642 | + } |
643 | + } |
644 | + |
645 | ListItem.Standard { |
646 | control: Button { |
647 | id: updateButton |
648 | |
649 | === modified file 'tests/unit/ContainersConfigTests.cpp' |
650 | --- tests/unit/ContainersConfigTests.cpp 2017-02-13 22:18:18 +0000 |
651 | +++ tests/unit/ContainersConfigTests.cpp 2017-02-22 20:19:40 +0000 |
652 | @@ -48,6 +48,9 @@ |
653 | "archiveName": "ppa:some/archive", |
654 | "archiveStatus": "installed" |
655 | } |
656 | + ], |
657 | + "bindMounts": [ |
658 | + "/media/lrp/PEPPER" |
659 | ] |
660 | }, |
661 | { |
662 | @@ -107,6 +110,9 @@ |
663 | ASSERT_EQ(config.containers[0].archives.size(), 1); |
664 | EXPECT_EQ(config.containers[0].archives[0].status, "installed"); |
665 | EXPECT_EQ(config.containers[0].archives[0].name, "ppa:some/archive"); |
666 | + |
667 | + ASSERT_EQ(config.containers[0].mounts.size(), 1); |
668 | + EXPECT_EQ(config.containers[0].mounts[0].path, "/media/lrp/PEPPER"); |
669 | } |
670 | |
671 | |
672 | @@ -124,6 +130,7 @@ |
673 | auto zesty = json["containerList"].toArray()[1].toObject(); |
674 | zesty["installedApps"] = QJsonArray(); |
675 | zesty["extraArchives"] = QJsonArray(); |
676 | + zesty["bindMounts"] = QJsonArray(); |
677 | json["containerList"] = QJsonArray{xenial, zesty}; |
678 | |
679 | EXPECT_EQ(json, actual); |
680 | @@ -141,4 +148,5 @@ |
681 | EXPECT_EQ(container.status, "unknown"); |
682 | EXPECT_TRUE(container.archives.isEmpty()); |
683 | EXPECT_TRUE(container.installed_apps.isEmpty()); |
684 | + EXPECT_TRUE(container.mounts.isEmpty()); |
685 | } |
686 | |
687 | === modified file 'tools/libertine-container-manager' |
688 | --- tools/libertine-container-manager 2017-02-14 20:26:49 +0000 |
689 | +++ tools/libertine-container-manager 2017-02-22 20:19:40 +0000 |
690 | @@ -307,7 +307,7 @@ |
691 | libertine.utils.get_logger().error("Configure bind-mounts called without mount path. See configure --help for usage") |
692 | sys.exit(1) |
693 | |
694 | - mount_path = args.mount_path.rstrip('/') |
695 | + mount_path = args.mount_path.rstrip('/').strip('"') |
696 | |
697 | # validate bind-mount |
698 | if not mount_path.startswith(os.environ['HOME']) and not mount_path.startswith('/media/%s' % os.environ['USER']): |
FAILED: Continuous integration, rev:395 /jenkins. canonical. com/libertine/ job/lp- libertine- ci/388/ /jenkins. canonical. com/libertine/ job/build/ 742/console /jenkins. canonical. com/libertine/ job/build- 0-fetch/ 752 /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=amd64, release= xenial+ overlay/ 733/console /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=amd64, release= zesty/733/ console /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=i386, release= xenial+ overlay/ 733/console /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=i386, release= zesty/733/ console
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild: /jenkins. canonical. com/libertine/ job/lp- libertine- ci/388/ rebuild
https:/