Merge lp:~larryprice/libertine/private-ppas into lp:libertine

Proposed by Larry Price
Status: Merged
Approved by: Christopher Townsend
Approved revision: 280
Merged at revision: 271
Proposed branch: lp:~larryprice/libertine/private-ppas
Merge into: lp:libertine
Diff against target: 637 lines (+294/-151)
8 files modified
libertine/ContainerManager.cpp (+24/-0)
libertine/ContainerManager.h (+1/-0)
libertine/qml/AddExtraArchiveView.qml (+117/-0)
libertine/qml/ExtraArchivesView.qml (+13/-68)
libertine/qml/ManageContainer.qml (+1/-1)
python/libertine/Libertine.py (+69/-33)
tools/libertine-container-manager (+56/-41)
tools/libertine-container-manager.1 (+13/-8)
To merge this branch: bzr merge lp:~larryprice/libertine/private-ppas
Reviewer Review Type Date Requested Status
Christopher Townsend Approve
Libertine CI Bot continuous-integration Approve
Review via email: mp+299838@code.launchpad.net

Commit message

Support adding private PPAs inside of a container.

Description of the change

Support adding private PPAs inside of a container.

Refactored `libertine-container-manager configure` to be slightly more consistent. Now use `l-c-m configure --archive {add,remove} --archive-name archive [--public-key-file keyfile]`.

Moved archive additions to new page with line items for archive URI and optional public signing key.

To post a comment you must log in.
Revision history for this message
Libertine CI Bot (libertine-ci-bot) wrote :

PASSED: Continuous integration, rev:279
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/52/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/libertine/job/build/174
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=default/135
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=default/135
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=default/135
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=vivid+overlay,testname=default/135
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=xenial+overlay,testname=default/135
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=yakkety,testname=default/135
    None: https://jenkins.canonical.com/libertine/job/lp-generic-update-mp/137/console
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/177
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=vivid+overlay/162
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=xenial+overlay/162
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=yakkety/162
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/155
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/155/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/155
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/155/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/155
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/155/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/155
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/155/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/155
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/155/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/155
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/155/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/52/rebuild

review: Approve (continuous-integration)
Revision history for this message
Christopher Townsend (townsend) wrote :

Very nice!

One general visual comment. When an archive with a long name is installing, the busy spinner is overlapping the text of the archive name. Is there any way to limit the right margin of the string to not overlap the spinner while the archive is being added? After the archive is successfully added, then I think it's ok to bring the right margin back over to where it is now.

review: Needs Information
280. By Larry Price

Remove unnecessary code and fix archive name length

Revision history for this message
Libertine CI Bot (libertine-ci-bot) wrote :

PASSED: Continuous integration, rev:280
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/53/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/libertine/job/build/176
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=vivid+overlay,testname=default/137
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=xenial+overlay,testname=default/137
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=amd64,release=yakkety,testname=default/137
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=vivid+overlay,testname=default/137
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=xenial+overlay,testname=default/137
    SUCCESS: https://jenkins.canonical.com/libertine/job/test-0-autopkgtest/label=i386,release=yakkety,testname=default/137
    None: https://jenkins.canonical.com/libertine/job/lp-generic-update-mp/139/console
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-0-fetch/179
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=vivid+overlay/164
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=xenial+overlay/164
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-1-sourcepkg/release=yakkety/164
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/157
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=vivid+overlay/157/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/157
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=xenial+overlay/157/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/157
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=amd64,release=yakkety/157/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/157
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=vivid+overlay/157/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/157
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=xenial+overlay/157/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/157
        deb: https://jenkins.canonical.com/libertine/job/build-2-binpkg/arch=i386,release=yakkety/157/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/libertine/job/lp-libertine-ci/53/rebuild

review: Approve (continuous-integration)
Revision history for this message
Christopher Townsend (townsend) wrote :

Ok, good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'libertine/ContainerManager.cpp'
2--- libertine/ContainerManager.cpp 2016-07-11 15:45:59 +0000
3+++ libertine/ContainerManager.cpp 2016-07-13 19:49:12 +0000
4@@ -17,6 +17,7 @@
5 * along with this program. If not, see <http://www.gnu.org/licenses/>.
6 */
7 #include "libertine/ContainerManager.h"
8+#include <QTemporaryFile>
9
10
11 namespace
12@@ -293,6 +294,29 @@
13
14
15 void ContainerManagerWorker::
16+addArchive(const QString& container_id, const QString& container_name, const QString& archive, const QByteArray& signing_key)
17+{
18+ QStringList command{"--archive", "add", "--archive-name", archive};
19+ if (!signing_key.isEmpty())
20+ {
21+ QTemporaryFile keyfile;
22+ if (!keyfile.open())
23+ {
24+ emit error(CONTAINER_CONFIGURE_FAILED.arg(container_name), keyfile.errorString());
25+ return;
26+ }
27+
28+ keyfile.setAutoRemove(false);
29+ keyfile.write(signing_key);
30+
31+ command << "--public-key-file" << keyfile.fileName();
32+ }
33+
34+ configureContainer(container_id, container_name, command);
35+}
36+
37+
38+void ContainerManagerWorker::
39 fixIntegrity()
40 {
41 process_.start(libertine_container_manager_tool, QStringList{"fix-integrity"});
42
43=== modified file 'libertine/ContainerManager.h'
44--- libertine/ContainerManager.h 2016-06-08 21:12:57 +0000
45+++ libertine/ContainerManager.h 2016-07-13 19:49:12 +0000
46@@ -42,6 +42,7 @@
47 Q_INVOKABLE void updateContainer(const QString& container_id, const QString& container_name);
48 Q_INVOKABLE void runCommand(const QString& container_id, const QString& container_name, const QString& command_line);
49 Q_INVOKABLE void configureContainer(const QString& container_id, const QString& container_name, const QStringList& configure_command);
50+ Q_INVOKABLE void addArchive(const QString& container_id, const QString& container_name, const QString& archive, const QByteArray& signing_key);
51 Q_INVOKABLE void fixIntegrity();
52 Q_INVOKABLE void setDefaultContainer(const QString& container_id, bool should_clear);
53
54
55=== added file 'libertine/qml/AddExtraArchiveView.qml'
56--- libertine/qml/AddExtraArchiveView.qml 1970-01-01 00:00:00 +0000
57+++ libertine/qml/AddExtraArchiveView.qml 2016-07-13 19:49:12 +0000
58@@ -0,0 +1,117 @@
59+/**
60+ * @file AddExtraArchiveView.qml
61+ * @brief Libertine container add archive view
62+ */
63+/*
64+ * Copyright 2016 Canonical Ltd
65+ *
66+ * Libertine is free software: you can redistribute it and/or modify it under
67+ * the terms of the GNU General Public License, version 3, as published by the
68+ * Free Software Foundation.
69+ *
70+ * Libertine is distributed in the hope that it will be useful, but WITHOUT ANY
71+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
72+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
73+ *
74+ * You should have received a copy of the GNU General Public License
75+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
76+ */
77+import Libertine 1.0
78+import QtQuick 2.4
79+import Ubuntu.Components 1.3
80+
81+Page {
82+ id: addExtraArchiveView
83+ header: PageHeader {
84+ id: pageHeader
85+ title: i18n.tr("Add Archive")
86+ }
87+ property string currentContainer: ""
88+
89+ Column {
90+ spacing: units.gu(2)
91+
92+ anchors {
93+ topMargin: pageHeader.height + units.gu(2)
94+ leftMargin: units.gu(2)
95+ rightMargin: units.gu(2)
96+ fill: parent
97+ }
98+
99+ Label {
100+ text: i18n.tr("New archive identifier, e.g.")
101+ anchors {
102+ left: parent.left
103+ right: parent.right
104+ }
105+ }
106+
107+ TextEdit {
108+ text: i18n.tr("multiverse\nppa:user/repository\ndeb http://myserver/repo stable repo")
109+ anchors {
110+ left: parent.left
111+ right: parent.right
112+ leftMargin: units.gu(4)
113+ }
114+
115+ readOnly: true
116+ color: UbuntuColors.darkGrey
117+ }
118+
119+ TextField {
120+ id: extraArchiveString
121+ anchors {
122+ left: parent.left
123+ right: parent.right
124+ }
125+ onAccepted: {
126+ addArchive()
127+ }
128+ }
129+
130+ Label {
131+ text: i18n.tr("(Optional) Public signing key for archive")
132+ anchors {
133+ left: parent.left
134+ right: parent.right
135+ }
136+ }
137+
138+ TextArea {
139+ id: publicSigningKey
140+ anchors {
141+ left: parent.left
142+ right: parent.right
143+ }
144+ height: Math.max(addExtraArchiveView.height/3, units.gu(6))
145+ }
146+
147+ Button {
148+ text: i18n.tr("Add")
149+ color: UbuntuColors.green
150+ onClicked: {
151+ addArchive()
152+ }
153+ }
154+ }
155+
156+ function addArchive() {
157+ var worker = Qt.createComponent("ContainerManager.qml").createObject(mainView)
158+ worker.finishedConfigure.connect(finishedConfigure)
159+ worker.error.connect(mainView.error)
160+ worker.addArchive(currentContainer, containerConfigList.getContainerName(currentContainer),
161+ extraArchiveString.text, publicSigningKey.text.trim())
162+
163+ pageStack.pop()
164+ }
165+
166+ Component.onCompleted: {
167+ extraArchiveString.forceActiveFocus()
168+ }
169+
170+ function finishedConfigure() {
171+ if (addExtraArchiveView) {
172+ containerArchivesList.setContainerArchives(currentContainer)
173+ }
174+ }
175+}
176
177=== modified file 'libertine/qml/ExtraArchivesView.qml'
178--- libertine/qml/ExtraArchivesView.qml 2016-07-11 17:06:17 +0000
179+++ libertine/qml/ExtraArchivesView.qml 2016-07-13 19:49:12 +0000
180@@ -1,6 +1,6 @@
181 /**
182 * @file ExtraArchiveView.qml
183- * @brief Libertine container add archive view
184+ * @brief Libertine container extra archive view
185 */
186 /*
187 * Copyright 2016 Canonical Ltd
188@@ -19,66 +19,25 @@
189 import Libertine 1.0
190 import QtQuick 2.4
191 import Ubuntu.Components 1.3
192-import Ubuntu.Components.Popups 1.3
193
194 Page {
195 id: extraArchiveView
196 header: PageHeader {
197 id: pageHeader
198- title: i18n.tr("Additional Archives and PPAs")
199+ title: i18n.tr("Additional Archives")
200 trailingActionBar.actions: [
201 Action {
202 iconName: "add"
203 text: i18n.tr("add")
204- description: i18n.tr("Add a new PPA")
205- onTriggered: PopupUtils.open(addArchivePopup)
206+ description: i18n.tr("Add a new archive")
207+ onTriggered: pageStack.push(Qt.resolvedUrl("AddExtraArchiveView.qml"), {currentContainer: currentContainer})
208 }
209 ]
210 }
211- property var archive_name: null
212- property var worker: null
213+ property string currentContainer: ""
214+
215 signal error(string description, string details)
216
217- Component {
218- id: addArchivePopup
219- Dialog {
220- id: addArchiveDialog
221- title: i18n.tr("Add additional archive")
222- text: i18n.tr("Enter new archive identifier, e.g.:")
223-
224- TextEdit {
225- text: i18n.tr("multiverse\nppa:user/repository\ndeb http://myserver/repo stable repo")
226- readOnly: true
227- color: UbuntuColors.darkGrey
228- }
229-
230- TextField {
231- id: extraArchiveString
232- placeholderText: i18n.tr("new archive name")
233- onAccepted: {
234- PopupUtils.close(addArchiveDialog)
235- addArchive(text)
236- }
237- }
238- Button {
239- text: i18n.tr("OK")
240- color: UbuntuColors.green
241- onClicked: {
242- PopupUtils.close(addArchiveDialog)
243- addArchive(extraArchiveString.text)
244- }
245- }
246- Button {
247- text: i18n.tr("Cancel")
248- color: UbuntuColors.red
249- onClicked: PopupUtils.close(addArchiveDialog)
250- }
251- Component.onCompleted: {
252- extraArchiveString.forceActiveFocus()
253- }
254- }
255- }
256-
257 UbuntuListView {
258 id: extraArchiveList
259 anchors {
260@@ -95,6 +54,8 @@
261 leftMargin: units.gu(2)
262 }
263 text: archiveName
264+ width: parent.width - units.gu(8)
265+ elide: Text.ElideMiddle
266 }
267 ActivityIndicator {
268 id: extraArchiveActivity
269@@ -132,18 +93,11 @@
270 text: i18n.tr("No additional archives and PPA's have been added")
271 }
272
273- function addArchive(archive) {
274- var worker = Qt.createComponent("ContainerManager.qml").createObject(mainView)
275- worker.finishedConfigure.connect(finishedConfigure)
276- worker.error.connect(sendAddError)
277- worker.configureContainer(mainView.currentContainer, containerConfigList.getContainerName(mainView.currentContainer), ["--add-archive", "\"" + archive + "\""])
278- }
279-
280 function deleteArchive(archive) {
281 var worker = Qt.createComponent("ContainerManager.qml").createObject(mainView)
282 worker.finishedConfigure.connect(finishedConfigure)
283 worker.error.connect(sendDeleteError)
284- worker.configureContainer(mainView.currentContainer, containerConfigList.getContainerName(mainView.currentContainer), ["--delete-archive", "\"" + archive + "\""])
285+ worker.configureContainer(currentContainer, containerConfigList.getContainerName(currentContainer), ["--archive", "remove", "--archive-name", "\"" + archive + "\""])
286 }
287
288 Component.onCompleted: {
289@@ -153,28 +107,19 @@
290
291 Component.onDestruction: {
292 containerConfigList.configChanged.disconnect(reloadArchives)
293-
294 error.disconnect(mainView.error)
295-
296- if (worker) {
297- worker.finishedConfigure.disconnect(finishedConfigure)
298- worker.error.disconnect(sendAddError)
299- worker.error.disconnect(sendDeleteError)
300- }
301 }
302
303 function reloadArchives() {
304- containerArchivesList.setContainerArchives(mainView.currentContainer)
305+ containerArchivesList.setContainerArchives(currentContainer)
306
307 extraArchiveList.visible = !containerArchivesList.empty() ? true : false
308 }
309
310 function finishedConfigure() {
311- containerArchivesList.setContainerArchives(mainView.currentContainer)
312- }
313-
314- function sendAddError(desc, details) {
315- error(i18n.tr("Adding archive failed"), details)
316+ if (extraArchiveView) {
317+ containerArchivesList.setContainerArchives(currentContainer)
318+ }
319 }
320
321 function sendDeleteError(desc, details) {
322
323=== modified file 'libertine/qml/ManageContainer.qml'
324--- libertine/qml/ManageContainer.qml 2016-06-08 21:56:53 +0000
325+++ libertine/qml/ManageContainer.qml 2016-07-13 19:49:12 +0000
326@@ -74,7 +74,7 @@
327 progression: true
328 onClicked: {
329 containerArchivesList.setContainerArchives(currentContainer)
330- pageStack.push(Qt.resolvedUrl("ExtraArchivesView.qml"))
331+ pageStack.push(Qt.resolvedUrl("ExtraArchivesView.qml"), {currentContainer: currentContainer})
332 }
333 }
334
335
336=== modified file 'python/libertine/Libertine.py'
337--- python/libertine/Libertine.py 2016-07-11 18:41:59 +0000
338+++ python/libertine/Libertine.py 2016-07-13 19:49:12 +0000
339@@ -162,32 +162,52 @@
340 os.environ['DEBIAN_FRONTEND'] = 'readline'
341 return self.run_in_container(apt_command_prefix(verbosity) + " install '" + package_name + "'") == 0
342
343- def configure_command(self, command, *args, verbosity=1):
344- """
345- Configures the container based on what the command is.
346-
347- :param command: The configuration command to run.
348- :param *args: List of arguments used for the given configuration command
349- """
350- if command == 'multiarch':
351- if args[0] == 'enable':
352- ret = self.run_in_container("dpkg --add-architecture i386")
353- if ret or ret == 0:
354- self.run_in_container(apt_command_prefix(verbosity) + '--force-yes update')
355- return ret
356- else:
357- self.run_in_container(apt_command_prefix(verbosity) + "purge \".*:i386\"")
358- return self.run_in_container("dpkg --remove-architecture i386")
359-
360- elif command == 'add-archive':
361- if not os.path.exists(os.path.join(self.root_path, 'usr', 'bin', 'add-apt-repository')):
362- self.update_packages(verbosity)
363- self.install_package("software-properties-common", verbosity)
364-
365- return self.run_in_container("add-apt-repository -y " + args[0])
366-
367- elif command == 'delete-archive':
368- return self.run_in_container("add-apt-repository -y -r " + args[0])
369+ def configure_multiarch(self, should_enable, verbosity=1):
370+ """
371+ Enables or disables multiarch repositories.
372+
373+ :param should_enable: Whether or not to enable multiarch support.
374+ :param verbosity: the chattiness of the output on a range from 0 to 2
375+ """
376+ if should_enable:
377+ ret = self.run_in_container("dpkg --add-architecture i386")
378+ if ret or ret == 0:
379+ self.run_in_container(apt_command_prefix(verbosity) + '--force-yes update')
380+ return ret
381+ else:
382+ self.run_in_container(apt_command_prefix(verbosity) + "purge \".*:i386\"")
383+ return self.run_in_container("dpkg --remove-architecture i386")
384+
385+ def configure_add_archive(self, archive, public_key_file, verbosity=1):
386+ """
387+ Adds the given archive. If this archive requires a key, prompt user.
388+
389+ :param archive: The configuration command to run.
390+ :param public_key_file: file containing the public key used to sign this archive
391+ :param verbosity: the chattiness of the output on a range from 0 to 2
392+ """
393+ if not os.path.exists(os.path.join(self.root_path, 'usr', 'bin', 'add-apt-repository')):
394+ self.update_packages(verbosity)
395+ self.install_package("software-properties-common", verbosity)
396+ if 'https://' in archive and not os.path.exists(os.path.join(self.root_path, 'usr', 'lib', 'apt', 'methods', 'https')):
397+ self.update_packages(verbosity)
398+ self.install_package("apt-transport-https", verbosity)
399+
400+ retcode = self.run_in_container("add-apt-repository -y " + archive)
401+ if retcode is 0 and public_key_file is not None:
402+ with open(public_key_file, 'r') as keyfile:
403+ return self.run_in_container("bash -c 'echo \"%s\" | apt-key add -'" % keyfile.read())
404+
405+ return retcode
406+
407+ def configure_remove_archive(self, archive, verbosity=1):
408+ """
409+ Removes the given archive.
410+
411+ :param archive: The configuration command to run.
412+ :param verbosity: the chattiness of the output on a range from 0 to 2
413+ """
414+ return self.run_in_container("add-apt-repository -y -r " + archive)
415
416 @property
417 def name(self):
418@@ -248,7 +268,9 @@
419 """
420 super().__init__()
421
422- container_type = ContainersConfig().get_container_type(container_id)
423+ self.containers_config = ContainersConfig()
424+
425+ container_type = self.containers_config.get_container_type(container_id)
426
427 if container_type == None or container_type == "lxc":
428 from libertine.LxcContainer import LibertineLXC
429@@ -288,7 +310,7 @@
430 Creates the container.
431 """
432 self.container.architecture = HostInfo().get_host_architecture()
433- self.container.installed_release = ContainersConfig().get_container_distro(self.container_id)
434+ self.container.installed_release = self.containers_config.get_container_distro(self.container_id)
435
436 return self.container.create_libertine_container(password, multiarch, verbosity)
437
438@@ -350,7 +372,7 @@
439 :param app_exec_line: the application exec line as passed in by
440 ubuntu-app-launch
441 """
442- if ContainersConfig().container_exists(self.container.container_id):
443+ if self.containers_config.container_exists(self.container.container_id):
444 # Update $PATH as necessary
445 if '/usr/games' not in os.environ['PATH']:
446 os.environ['PATH'] = os.environ['PATH'] + ":/usr/games"
447@@ -391,10 +413,24 @@
448 except RuntimeError as e:
449 return handle_runtime_error(e)
450
451- def configure_command(self, command, *args):
452- try:
453- with ContainerRunning(self.container):
454- return self.container.configure_command(command, *args)
455+ def configure_multiarch(self, should_enable, verbosity=1):
456+ try:
457+ with ContainerRunning(self.container):
458+ return self.container.configure_multiarch(should_enable, verbosity)
459+ except RuntimeError as e:
460+ return handle_runtime_error(e)
461+
462+ def configure_add_archive(self, archive, key, verbosity):
463+ try:
464+ with ContainerRunning(self.container):
465+ return self.container.configure_add_archive(archive, key, verbosity)
466+ except RuntimeError as e:
467+ return handle_runtime_error(e)
468+
469+ def configure_remove_archive(self, archive, verbosity):
470+ try:
471+ with ContainerRunning(self.container):
472+ return self.container.configure_remove_archive(archive, verbosity)
473 except RuntimeError as e:
474 return handle_runtime_error(e)
475
476
477=== modified file 'tools/libertine-container-manager'
478--- tools/libertine-container-manager 2016-07-11 18:41:59 +0000
479+++ tools/libertine-container-manager 2016-07-13 19:49:12 +0000
480@@ -206,11 +206,11 @@
481 if not container.exec_command(args.command):
482 sys.exit(1)
483
484- def delete_archive_by_name(self, container_id, archive_name):
485+ def delete_archive_by_name(self, container_id, archive_name, verbosity=1):
486 self.containers_config.update_archive_install_status(container_id, archive_name, 'removing')
487 if self.containers_config.get_archive_install_status(container_id, archive_name) == 'installed':
488 self.containers_config.update_archive_install_status(container_id, archive_name, 'removing')
489- if LibertineContainer(container_id).configure_command('delete-archive', "\"" + archive_name + "\"") is not 0:
490+ if LibertineContainer(container_id).configure_remove_archive("\"" + archive_name + "\"", verbosity) is not 0:
491 self.containers_config.update_archive_install_status(container_id, archive_name, 'installed')
492 return False
493
494@@ -232,36 +232,41 @@
495 print("i386 multiarch support is already %s" % multiarch)
496 sys.exit(1)
497
498- if container.configure_command('multiarch', args.multiarch) is not 0:
499+ if container.configure_multiarch(args.multiarch, args.verbosity) is not 0:
500 sys.exit(1)
501
502 self.containers_config.update_container_multiarch_support(container_id, multiarch)
503
504- elif args.add_archive:
505- archive_name = args.add_archive.strip("\'\"")
506+ elif args.archive is not None:
507+ archive_name = args.archive_name.strip("\'\"")
508 archive_name_esc = "\"" + archive_name + "\""
509
510- if self.containers_config.archive_exists(container_id, archive_name):
511- print("%s already added in container." % archive_name)
512- sys.exit(1)
513-
514- self.containers_config.add_container_archive(container_id, archive_name)
515- self.containers_config.update_archive_install_status(container_id, archive_name, 'installing')
516- if container.configure_command('add-archive', archive_name_esc) is not 0:
517- self.containers_config.delete_container_archive(container_id, archive_name)
518- sys.exit(1)
519-
520- self.containers_config.update_archive_install_status(container_id, archive_name, 'installed')
521-
522- elif args.delete_archive:
523- archive_name = args.delete_archive.strip("\'\"")
524- if not self.containers_config.archive_exists(container_id, archive_name):
525- print("%s is not added in container." % archive_name)
526- sys.exit(1)
527-
528- if not self.delete_archive_by_name(container_id, archive_name):
529- print("%s was not properly deleted." % archive_name)
530- sys.exit(1)
531+ if args.archive == 'add':
532+ if self.containers_config.archive_exists(container_id, archive_name):
533+ print("%s already added in container." % archive_name)
534+ sys.exit(1)
535+
536+ self.containers_config.add_container_archive(container_id, archive_name)
537+ self.containers_config.update_archive_install_status(container_id, archive_name, 'installing')
538+ if container.configure_add_archive(archive_name_esc, args.public_key_file, args.verbosity) is not 0:
539+ self.containers_config.delete_container_archive(container_id, archive_name)
540+ sys.exit(1)
541+
542+ self.containers_config.update_archive_install_status(container_id, archive_name, 'installed')
543+
544+ elif args.archive == 'remove':
545+ if not self.containers_config.archive_exists(container_id, archive_name):
546+ print("%s is not added in container." % archive_name)
547+ sys.exit(1)
548+
549+ if not self.delete_archive_by_name(container_id, archive_name):
550+ print("%s was not properly deleted." % archive_name)
551+ sys.exit(1)
552+
553+ else:
554+ print("Configure called with no subcommand. See configure --help for usage.")
555+ sys.exit(1)
556+
557
558 def merge(self, args):
559 self.containers_config.merge_container_config_files(args.file)
560@@ -444,21 +449,31 @@
561 parser_configure.add_argument(
562 '-i', '--id',
563 help=("Container identifier. Default container is used if omitted."))
564- parser_configure.add_argument(
565- '-m', '--multiarch',
566- choices=['enable', 'disable'],
567- help=("Enables or disables i386 multiarch support for amd64 Libertine "
568- "containers. This option has no effect when the Libertine "
569- "container is i386."))
570- parser_configure.add_argument(
571- '-a', '--add-archive',
572- metavar='Archive name',
573- help=("Adds an archive in the specified Libertine container. Examples: "
574- "'deb http://myserver/path/to/repo stable myrepo', ppa:user/repository, multiverse"))
575- parser_configure.add_argument(
576- '-d', '--delete-archive',
577- metavar='Archive name',
578- help=("Deletes an existing archive in the specified Libertine container."))
579+ multiarch_group = parser_configure.add_argument_group("Multiarch support",
580+ "Enable or disable multiarch support for a container.")
581+ multiarch_group.add_argument(
582+ '-m', '--multiarch',
583+ choices=['enable', 'disable'],
584+ help=("Enables or disables i386 multiarch support for amd64 Libertine "
585+ "containers. This option has no effect when the Libertine "
586+ "container is i386."))
587+
588+ archive_group = parser_configure.add_argument_group("Additional archive support",
589+ "Add or delete an additional archive (PPA).")
590+ archive_group.add_argument(
591+ '-a', '--archive',
592+ choices=['add', 'remove'],
593+ help=("Adds or removes an archive (PPA) in the specified Libertine container."))
594+ archive_group.add_argument(
595+ '-n', '--archive-name',
596+ metavar='Archive name',
597+ help=("Archive name to be added or removed."))
598+ archive_group.add_argument(
599+ '-k', '--public-key-file',
600+ metavar='Public key file',
601+ help=("File containing the key used to sign the given archive. "
602+ "Useful for third-party or private archives."))
603+
604 parser_configure.set_defaults(func=container_manager.configure)
605
606 # Handle merging another ContainersConfig.json file into the main ContainersConfig.json file
607
608=== modified file 'tools/libertine-container-manager.1'
609--- tools/libertine-container-manager.1 2016-07-07 18:54:59 +0000
610+++ tools/libertine-container-manager.1 2016-07-13 19:49:12 +0000
611@@ -265,14 +265,19 @@
612 Enable i386 support.
613 .RE
614 .IP
615-.BR \-a " ARCHIVE_NAME, " \-\-add-archive " ARCHIVE_NAME" ""
616-.RS 14
617-Adds an archive to the specified container. Examples: 'deb http://myserver/path/to/repo stable myrepo', ppa:user/repository, multiverse
618-.RE
619-.IP
620-.BR \-d " ARCHIVE_NAME, " \-\-delete-archive " ARCHIVE_NAME" ""
621-.RS 14
622-Deletes an archive to the specified container. Examples: 'deb http://myserver/path/to/repo stable myrepo', ppa:user/repository, multiverse
623+.BR \-a " {add,remove}, " \-\-archive "{add,remove}" ""
624+.RS 14
625+Adds or removes an archive in the specified container.
626+.RE
627+.IP
628+.BR \-n " ARCHIVE_NAME, " \-\-archive-name " ARCHIVE_NAME" ""
629+.RS 14
630+Archive to be added or removed. Examples: 'deb http://myserver/path/to/repo stable myrepo', ppa:user/repository, multiverse
631+.RE
632+.IP
633+.BR \-k " PUBLIC_KEY_FILE, " \-\-public-key-file " PUBLIC_KEY_FILE" ""
634+.RS 14
635+File containing public key used to sign new archive.
636 .RE
637 .TP
638

Subscribers

People subscribed via source and target branches