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
=== modified file 'libertine/ContainerManager.cpp'
--- libertine/ContainerManager.cpp 2016-07-11 15:45:59 +0000
+++ libertine/ContainerManager.cpp 2016-07-13 19:49:12 +0000
@@ -17,6 +17,7 @@
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */18 */
19#include "libertine/ContainerManager.h"19#include "libertine/ContainerManager.h"
20#include <QTemporaryFile>
2021
2122
22namespace23namespace
@@ -293,6 +294,29 @@
293294
294295
295void ContainerManagerWorker::296void ContainerManagerWorker::
297addArchive(const QString& container_id, const QString& container_name, const QString& archive, const QByteArray& signing_key)
298{
299 QStringList command{"--archive", "add", "--archive-name", archive};
300 if (!signing_key.isEmpty())
301 {
302 QTemporaryFile keyfile;
303 if (!keyfile.open())
304 {
305 emit error(CONTAINER_CONFIGURE_FAILED.arg(container_name), keyfile.errorString());
306 return;
307 }
308
309 keyfile.setAutoRemove(false);
310 keyfile.write(signing_key);
311
312 command << "--public-key-file" << keyfile.fileName();
313 }
314
315 configureContainer(container_id, container_name, command);
316}
317
318
319void ContainerManagerWorker::
296fixIntegrity()320fixIntegrity()
297{321{
298 process_.start(libertine_container_manager_tool, QStringList{"fix-integrity"});322 process_.start(libertine_container_manager_tool, QStringList{"fix-integrity"});
299323
=== modified file 'libertine/ContainerManager.h'
--- libertine/ContainerManager.h 2016-06-08 21:12:57 +0000
+++ libertine/ContainerManager.h 2016-07-13 19:49:12 +0000
@@ -42,6 +42,7 @@
42 Q_INVOKABLE void updateContainer(const QString& container_id, const QString& container_name);42 Q_INVOKABLE void updateContainer(const QString& container_id, const QString& container_name);
43 Q_INVOKABLE void runCommand(const QString& container_id, const QString& container_name, const QString& command_line);43 Q_INVOKABLE void runCommand(const QString& container_id, const QString& container_name, const QString& command_line);
44 Q_INVOKABLE void configureContainer(const QString& container_id, const QString& container_name, const QStringList& configure_command);44 Q_INVOKABLE void configureContainer(const QString& container_id, const QString& container_name, const QStringList& configure_command);
45 Q_INVOKABLE void addArchive(const QString& container_id, const QString& container_name, const QString& archive, const QByteArray& signing_key);
45 Q_INVOKABLE void fixIntegrity();46 Q_INVOKABLE void fixIntegrity();
46 Q_INVOKABLE void setDefaultContainer(const QString& container_id, bool should_clear);47 Q_INVOKABLE void setDefaultContainer(const QString& container_id, bool should_clear);
4748
4849
=== added file 'libertine/qml/AddExtraArchiveView.qml'
--- libertine/qml/AddExtraArchiveView.qml 1970-01-01 00:00:00 +0000
+++ libertine/qml/AddExtraArchiveView.qml 2016-07-13 19:49:12 +0000
@@ -0,0 +1,117 @@
1/**
2 * @file AddExtraArchiveView.qml
3 * @brief Libertine container add archive view
4 */
5/*
6 * Copyright 2016 Canonical Ltd
7 *
8 * Libertine is free software: you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, version 3, as published by the
10 * Free Software Foundation.
11 *
12 * Libertine is distributed in the hope that it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19import Libertine 1.0
20import QtQuick 2.4
21import Ubuntu.Components 1.3
22
23Page {
24 id: addExtraArchiveView
25 header: PageHeader {
26 id: pageHeader
27 title: i18n.tr("Add Archive")
28 }
29 property string currentContainer: ""
30
31 Column {
32 spacing: units.gu(2)
33
34 anchors {
35 topMargin: pageHeader.height + units.gu(2)
36 leftMargin: units.gu(2)
37 rightMargin: units.gu(2)
38 fill: parent
39 }
40
41 Label {
42 text: i18n.tr("New archive identifier, e.g.")
43 anchors {
44 left: parent.left
45 right: parent.right
46 }
47 }
48
49 TextEdit {
50 text: i18n.tr("multiverse\nppa:user/repository\ndeb http://myserver/repo stable repo")
51 anchors {
52 left: parent.left
53 right: parent.right
54 leftMargin: units.gu(4)
55 }
56
57 readOnly: true
58 color: UbuntuColors.darkGrey
59 }
60
61 TextField {
62 id: extraArchiveString
63 anchors {
64 left: parent.left
65 right: parent.right
66 }
67 onAccepted: {
68 addArchive()
69 }
70 }
71
72 Label {
73 text: i18n.tr("(Optional) Public signing key for archive")
74 anchors {
75 left: parent.left
76 right: parent.right
77 }
78 }
79
80 TextArea {
81 id: publicSigningKey
82 anchors {
83 left: parent.left
84 right: parent.right
85 }
86 height: Math.max(addExtraArchiveView.height/3, units.gu(6))
87 }
88
89 Button {
90 text: i18n.tr("Add")
91 color: UbuntuColors.green
92 onClicked: {
93 addArchive()
94 }
95 }
96 }
97
98 function addArchive() {
99 var worker = Qt.createComponent("ContainerManager.qml").createObject(mainView)
100 worker.finishedConfigure.connect(finishedConfigure)
101 worker.error.connect(mainView.error)
102 worker.addArchive(currentContainer, containerConfigList.getContainerName(currentContainer),
103 extraArchiveString.text, publicSigningKey.text.trim())
104
105 pageStack.pop()
106 }
107
108 Component.onCompleted: {
109 extraArchiveString.forceActiveFocus()
110 }
111
112 function finishedConfigure() {
113 if (addExtraArchiveView) {
114 containerArchivesList.setContainerArchives(currentContainer)
115 }
116 }
117}
0118
=== modified file 'libertine/qml/ExtraArchivesView.qml'
--- libertine/qml/ExtraArchivesView.qml 2016-07-11 17:06:17 +0000
+++ libertine/qml/ExtraArchivesView.qml 2016-07-13 19:49:12 +0000
@@ -1,6 +1,6 @@
1/**1/**
2 * @file ExtraArchiveView.qml2 * @file ExtraArchiveView.qml
3 * @brief Libertine container add archive view3 * @brief Libertine container extra archive view
4 */4 */
5/*5/*
6 * Copyright 2016 Canonical Ltd6 * Copyright 2016 Canonical Ltd
@@ -19,66 +19,25 @@
19import Libertine 1.019import Libertine 1.0
20import QtQuick 2.420import QtQuick 2.4
21import Ubuntu.Components 1.321import Ubuntu.Components 1.3
22import Ubuntu.Components.Popups 1.3
2322
24Page {23Page {
25 id: extraArchiveView24 id: extraArchiveView
26 header: PageHeader {25 header: PageHeader {
27 id: pageHeader26 id: pageHeader
28 title: i18n.tr("Additional Archives and PPAs")27 title: i18n.tr("Additional Archives")
29 trailingActionBar.actions: [28 trailingActionBar.actions: [
30 Action {29 Action {
31 iconName: "add"30 iconName: "add"
32 text: i18n.tr("add")31 text: i18n.tr("add")
33 description: i18n.tr("Add a new PPA")32 description: i18n.tr("Add a new archive")
34 onTriggered: PopupUtils.open(addArchivePopup)33 onTriggered: pageStack.push(Qt.resolvedUrl("AddExtraArchiveView.qml"), {currentContainer: currentContainer})
35 }34 }
36 ]35 ]
37 }36 }
38 property var archive_name: null37 property string currentContainer: ""
39 property var worker: null38
40 signal error(string description, string details)39 signal error(string description, string details)
4140
42 Component {
43 id: addArchivePopup
44 Dialog {
45 id: addArchiveDialog
46 title: i18n.tr("Add additional archive")
47 text: i18n.tr("Enter new archive identifier, e.g.:")
48
49 TextEdit {
50 text: i18n.tr("multiverse\nppa:user/repository\ndeb http://myserver/repo stable repo")
51 readOnly: true
52 color: UbuntuColors.darkGrey
53 }
54
55 TextField {
56 id: extraArchiveString
57 placeholderText: i18n.tr("new archive name")
58 onAccepted: {
59 PopupUtils.close(addArchiveDialog)
60 addArchive(text)
61 }
62 }
63 Button {
64 text: i18n.tr("OK")
65 color: UbuntuColors.green
66 onClicked: {
67 PopupUtils.close(addArchiveDialog)
68 addArchive(extraArchiveString.text)
69 }
70 }
71 Button {
72 text: i18n.tr("Cancel")
73 color: UbuntuColors.red
74 onClicked: PopupUtils.close(addArchiveDialog)
75 }
76 Component.onCompleted: {
77 extraArchiveString.forceActiveFocus()
78 }
79 }
80 }
81
82 UbuntuListView {41 UbuntuListView {
83 id: extraArchiveList42 id: extraArchiveList
84 anchors {43 anchors {
@@ -95,6 +54,8 @@
95 leftMargin: units.gu(2)54 leftMargin: units.gu(2)
96 }55 }
97 text: archiveName56 text: archiveName
57 width: parent.width - units.gu(8)
58 elide: Text.ElideMiddle
98 }59 }
99 ActivityIndicator {60 ActivityIndicator {
100 id: extraArchiveActivity61 id: extraArchiveActivity
@@ -132,18 +93,11 @@
132 text: i18n.tr("No additional archives and PPA's have been added")93 text: i18n.tr("No additional archives and PPA's have been added")
133 }94 }
13495
135 function addArchive(archive) {
136 var worker = Qt.createComponent("ContainerManager.qml").createObject(mainView)
137 worker.finishedConfigure.connect(finishedConfigure)
138 worker.error.connect(sendAddError)
139 worker.configureContainer(mainView.currentContainer, containerConfigList.getContainerName(mainView.currentContainer), ["--add-archive", "\"" + archive + "\""])
140 }
141
142 function deleteArchive(archive) {96 function deleteArchive(archive) {
143 var worker = Qt.createComponent("ContainerManager.qml").createObject(mainView)97 var worker = Qt.createComponent("ContainerManager.qml").createObject(mainView)
144 worker.finishedConfigure.connect(finishedConfigure)98 worker.finishedConfigure.connect(finishedConfigure)
145 worker.error.connect(sendDeleteError)99 worker.error.connect(sendDeleteError)
146 worker.configureContainer(mainView.currentContainer, containerConfigList.getContainerName(mainView.currentContainer), ["--delete-archive", "\"" + archive + "\""])100 worker.configureContainer(currentContainer, containerConfigList.getContainerName(currentContainer), ["--archive", "remove", "--archive-name", "\"" + archive + "\""])
147 }101 }
148102
149 Component.onCompleted: {103 Component.onCompleted: {
@@ -153,28 +107,19 @@
153107
154 Component.onDestruction: {108 Component.onDestruction: {
155 containerConfigList.configChanged.disconnect(reloadArchives)109 containerConfigList.configChanged.disconnect(reloadArchives)
156
157 error.disconnect(mainView.error)110 error.disconnect(mainView.error)
158
159 if (worker) {
160 worker.finishedConfigure.disconnect(finishedConfigure)
161 worker.error.disconnect(sendAddError)
162 worker.error.disconnect(sendDeleteError)
163 }
164 }111 }
165112
166 function reloadArchives() {113 function reloadArchives() {
167 containerArchivesList.setContainerArchives(mainView.currentContainer)114 containerArchivesList.setContainerArchives(currentContainer)
168115
169 extraArchiveList.visible = !containerArchivesList.empty() ? true : false116 extraArchiveList.visible = !containerArchivesList.empty() ? true : false
170 }117 }
171118
172 function finishedConfigure() {119 function finishedConfigure() {
173 containerArchivesList.setContainerArchives(mainView.currentContainer)120 if (extraArchiveView) {
174 }121 containerArchivesList.setContainerArchives(currentContainer)
175122 }
176 function sendAddError(desc, details) {
177 error(i18n.tr("Adding archive failed"), details)
178 }123 }
179124
180 function sendDeleteError(desc, details) {125 function sendDeleteError(desc, details) {
181126
=== modified file 'libertine/qml/ManageContainer.qml'
--- libertine/qml/ManageContainer.qml 2016-06-08 21:56:53 +0000
+++ libertine/qml/ManageContainer.qml 2016-07-13 19:49:12 +0000
@@ -74,7 +74,7 @@
74 progression: true74 progression: true
75 onClicked: {75 onClicked: {
76 containerArchivesList.setContainerArchives(currentContainer)76 containerArchivesList.setContainerArchives(currentContainer)
77 pageStack.push(Qt.resolvedUrl("ExtraArchivesView.qml"))77 pageStack.push(Qt.resolvedUrl("ExtraArchivesView.qml"), {currentContainer: currentContainer})
78 }78 }
79 }79 }
8080
8181
=== modified file 'python/libertine/Libertine.py'
--- python/libertine/Libertine.py 2016-07-11 18:41:59 +0000
+++ python/libertine/Libertine.py 2016-07-13 19:49:12 +0000
@@ -162,32 +162,52 @@
162 os.environ['DEBIAN_FRONTEND'] = 'readline'162 os.environ['DEBIAN_FRONTEND'] = 'readline'
163 return self.run_in_container(apt_command_prefix(verbosity) + " install '" + package_name + "'") == 0163 return self.run_in_container(apt_command_prefix(verbosity) + " install '" + package_name + "'") == 0
164164
165 def configure_command(self, command, *args, verbosity=1):165 def configure_multiarch(self, should_enable, verbosity=1):
166 """166 """
167 Configures the container based on what the command is.167 Enables or disables multiarch repositories.
168168
169 :param command: The configuration command to run.169 :param should_enable: Whether or not to enable multiarch support.
170 :param *args: List of arguments used for the given configuration command170 :param verbosity: the chattiness of the output on a range from 0 to 2
171 """171 """
172 if command == 'multiarch':172 if should_enable:
173 if args[0] == 'enable':173 ret = self.run_in_container("dpkg --add-architecture i386")
174 ret = self.run_in_container("dpkg --add-architecture i386")174 if ret or ret == 0:
175 if ret or ret == 0:175 self.run_in_container(apt_command_prefix(verbosity) + '--force-yes update')
176 self.run_in_container(apt_command_prefix(verbosity) + '--force-yes update')176 return ret
177 return ret177 else:
178 else:178 self.run_in_container(apt_command_prefix(verbosity) + "purge \".*:i386\"")
179 self.run_in_container(apt_command_prefix(verbosity) + "purge \".*:i386\"")179 return self.run_in_container("dpkg --remove-architecture i386")
180 return self.run_in_container("dpkg --remove-architecture i386")180
181181 def configure_add_archive(self, archive, public_key_file, verbosity=1):
182 elif command == 'add-archive':182 """
183 if not os.path.exists(os.path.join(self.root_path, 'usr', 'bin', 'add-apt-repository')):183 Adds the given archive. If this archive requires a key, prompt user.
184 self.update_packages(verbosity)184
185 self.install_package("software-properties-common", verbosity)185 :param archive: The configuration command to run.
186186 :param public_key_file: file containing the public key used to sign this archive
187 return self.run_in_container("add-apt-repository -y " + args[0])187 :param verbosity: the chattiness of the output on a range from 0 to 2
188188 """
189 elif command == 'delete-archive':189 if not os.path.exists(os.path.join(self.root_path, 'usr', 'bin', 'add-apt-repository')):
190 return self.run_in_container("add-apt-repository -y -r " + args[0])190 self.update_packages(verbosity)
191 self.install_package("software-properties-common", verbosity)
192 if 'https://' in archive and not os.path.exists(os.path.join(self.root_path, 'usr', 'lib', 'apt', 'methods', 'https')):
193 self.update_packages(verbosity)
194 self.install_package("apt-transport-https", verbosity)
195
196 retcode = self.run_in_container("add-apt-repository -y " + archive)
197 if retcode is 0 and public_key_file is not None:
198 with open(public_key_file, 'r') as keyfile:
199 return self.run_in_container("bash -c 'echo \"%s\" | apt-key add -'" % keyfile.read())
200
201 return retcode
202
203 def configure_remove_archive(self, archive, verbosity=1):
204 """
205 Removes the given archive.
206
207 :param archive: The configuration command to run.
208 :param verbosity: the chattiness of the output on a range from 0 to 2
209 """
210 return self.run_in_container("add-apt-repository -y -r " + archive)
191211
192 @property212 @property
193 def name(self):213 def name(self):
@@ -248,7 +268,9 @@
248 """268 """
249 super().__init__()269 super().__init__()
250270
251 container_type = ContainersConfig().get_container_type(container_id)271 self.containers_config = ContainersConfig()
272
273 container_type = self.containers_config.get_container_type(container_id)
252274
253 if container_type == None or container_type == "lxc":275 if container_type == None or container_type == "lxc":
254 from libertine.LxcContainer import LibertineLXC276 from libertine.LxcContainer import LibertineLXC
@@ -288,7 +310,7 @@
288 Creates the container.310 Creates the container.
289 """311 """
290 self.container.architecture = HostInfo().get_host_architecture()312 self.container.architecture = HostInfo().get_host_architecture()
291 self.container.installed_release = ContainersConfig().get_container_distro(self.container_id)313 self.container.installed_release = self.containers_config.get_container_distro(self.container_id)
292314
293 return self.container.create_libertine_container(password, multiarch, verbosity)315 return self.container.create_libertine_container(password, multiarch, verbosity)
294316
@@ -350,7 +372,7 @@
350 :param app_exec_line: the application exec line as passed in by372 :param app_exec_line: the application exec line as passed in by
351 ubuntu-app-launch373 ubuntu-app-launch
352 """374 """
353 if ContainersConfig().container_exists(self.container.container_id):375 if self.containers_config.container_exists(self.container.container_id):
354 # Update $PATH as necessary376 # Update $PATH as necessary
355 if '/usr/games' not in os.environ['PATH']:377 if '/usr/games' not in os.environ['PATH']:
356 os.environ['PATH'] = os.environ['PATH'] + ":/usr/games"378 os.environ['PATH'] = os.environ['PATH'] + ":/usr/games"
@@ -391,10 +413,24 @@
391 except RuntimeError as e:413 except RuntimeError as e:
392 return handle_runtime_error(e)414 return handle_runtime_error(e)
393415
394 def configure_command(self, command, *args):416 def configure_multiarch(self, should_enable, verbosity=1):
395 try:417 try:
396 with ContainerRunning(self.container):418 with ContainerRunning(self.container):
397 return self.container.configure_command(command, *args)419 return self.container.configure_multiarch(should_enable, verbosity)
420 except RuntimeError as e:
421 return handle_runtime_error(e)
422
423 def configure_add_archive(self, archive, key, verbosity):
424 try:
425 with ContainerRunning(self.container):
426 return self.container.configure_add_archive(archive, key, verbosity)
427 except RuntimeError as e:
428 return handle_runtime_error(e)
429
430 def configure_remove_archive(self, archive, verbosity):
431 try:
432 with ContainerRunning(self.container):
433 return self.container.configure_remove_archive(archive, verbosity)
398 except RuntimeError as e:434 except RuntimeError as e:
399 return handle_runtime_error(e)435 return handle_runtime_error(e)
400436
401437
=== modified file 'tools/libertine-container-manager'
--- tools/libertine-container-manager 2016-07-11 18:41:59 +0000
+++ tools/libertine-container-manager 2016-07-13 19:49:12 +0000
@@ -206,11 +206,11 @@
206 if not container.exec_command(args.command):206 if not container.exec_command(args.command):
207 sys.exit(1)207 sys.exit(1)
208208
209 def delete_archive_by_name(self, container_id, archive_name):209 def delete_archive_by_name(self, container_id, archive_name, verbosity=1):
210 self.containers_config.update_archive_install_status(container_id, archive_name, 'removing')210 self.containers_config.update_archive_install_status(container_id, archive_name, 'removing')
211 if self.containers_config.get_archive_install_status(container_id, archive_name) == 'installed':211 if self.containers_config.get_archive_install_status(container_id, archive_name) == 'installed':
212 self.containers_config.update_archive_install_status(container_id, archive_name, 'removing')212 self.containers_config.update_archive_install_status(container_id, archive_name, 'removing')
213 if LibertineContainer(container_id).configure_command('delete-archive', "\"" + archive_name + "\"") is not 0:213 if LibertineContainer(container_id).configure_remove_archive("\"" + archive_name + "\"", verbosity) is not 0:
214 self.containers_config.update_archive_install_status(container_id, archive_name, 'installed')214 self.containers_config.update_archive_install_status(container_id, archive_name, 'installed')
215 return False215 return False
216216
@@ -232,36 +232,41 @@
232 print("i386 multiarch support is already %s" % multiarch)232 print("i386 multiarch support is already %s" % multiarch)
233 sys.exit(1)233 sys.exit(1)
234234
235 if container.configure_command('multiarch', args.multiarch) is not 0:235 if container.configure_multiarch(args.multiarch, args.verbosity) is not 0:
236 sys.exit(1)236 sys.exit(1)
237237
238 self.containers_config.update_container_multiarch_support(container_id, multiarch)238 self.containers_config.update_container_multiarch_support(container_id, multiarch)
239239
240 elif args.add_archive:240 elif args.archive is not None:
241 archive_name = args.add_archive.strip("\'\"")241 archive_name = args.archive_name.strip("\'\"")
242 archive_name_esc = "\"" + archive_name + "\""242 archive_name_esc = "\"" + archive_name + "\""
243243
244 if self.containers_config.archive_exists(container_id, archive_name):244 if args.archive == 'add':
245 print("%s already added in container." % archive_name)245 if self.containers_config.archive_exists(container_id, archive_name):
246 sys.exit(1)246 print("%s already added in container." % archive_name)
247247 sys.exit(1)
248 self.containers_config.add_container_archive(container_id, archive_name)248
249 self.containers_config.update_archive_install_status(container_id, archive_name, 'installing')249 self.containers_config.add_container_archive(container_id, archive_name)
250 if container.configure_command('add-archive', archive_name_esc) is not 0:250 self.containers_config.update_archive_install_status(container_id, archive_name, 'installing')
251 self.containers_config.delete_container_archive(container_id, archive_name)251 if container.configure_add_archive(archive_name_esc, args.public_key_file, args.verbosity) is not 0:
252 sys.exit(1)252 self.containers_config.delete_container_archive(container_id, archive_name)
253253 sys.exit(1)
254 self.containers_config.update_archive_install_status(container_id, archive_name, 'installed')254
255255 self.containers_config.update_archive_install_status(container_id, archive_name, 'installed')
256 elif args.delete_archive:256
257 archive_name = args.delete_archive.strip("\'\"")257 elif args.archive == 'remove':
258 if not self.containers_config.archive_exists(container_id, archive_name):258 if not self.containers_config.archive_exists(container_id, archive_name):
259 print("%s is not added in container." % archive_name)259 print("%s is not added in container." % archive_name)
260 sys.exit(1)260 sys.exit(1)
261261
262 if not self.delete_archive_by_name(container_id, archive_name):262 if not self.delete_archive_by_name(container_id, archive_name):
263 print("%s was not properly deleted." % archive_name)263 print("%s was not properly deleted." % archive_name)
264 sys.exit(1)264 sys.exit(1)
265
266 else:
267 print("Configure called with no subcommand. See configure --help for usage.")
268 sys.exit(1)
269
265270
266 def merge(self, args):271 def merge(self, args):
267 self.containers_config.merge_container_config_files(args.file)272 self.containers_config.merge_container_config_files(args.file)
@@ -444,21 +449,31 @@
444 parser_configure.add_argument(449 parser_configure.add_argument(
445 '-i', '--id',450 '-i', '--id',
446 help=("Container identifier. Default container is used if omitted."))451 help=("Container identifier. Default container is used if omitted."))
447 parser_configure.add_argument(452 multiarch_group = parser_configure.add_argument_group("Multiarch support",
448 '-m', '--multiarch',453 "Enable or disable multiarch support for a container.")
449 choices=['enable', 'disable'],454 multiarch_group.add_argument(
450 help=("Enables or disables i386 multiarch support for amd64 Libertine "455 '-m', '--multiarch',
451 "containers. This option has no effect when the Libertine "456 choices=['enable', 'disable'],
452 "container is i386."))457 help=("Enables or disables i386 multiarch support for amd64 Libertine "
453 parser_configure.add_argument(458 "containers. This option has no effect when the Libertine "
454 '-a', '--add-archive',459 "container is i386."))
455 metavar='Archive name',460
456 help=("Adds an archive in the specified Libertine container. Examples: "461 archive_group = parser_configure.add_argument_group("Additional archive support",
457 "'deb http://myserver/path/to/repo stable myrepo', ppa:user/repository, multiverse"))462 "Add or delete an additional archive (PPA).")
458 parser_configure.add_argument(463 archive_group.add_argument(
459 '-d', '--delete-archive',464 '-a', '--archive',
460 metavar='Archive name',465 choices=['add', 'remove'],
461 help=("Deletes an existing archive in the specified Libertine container."))466 help=("Adds or removes an archive (PPA) in the specified Libertine container."))
467 archive_group.add_argument(
468 '-n', '--archive-name',
469 metavar='Archive name',
470 help=("Archive name to be added or removed."))
471 archive_group.add_argument(
472 '-k', '--public-key-file',
473 metavar='Public key file',
474 help=("File containing the key used to sign the given archive. "
475 "Useful for third-party or private archives."))
476
462 parser_configure.set_defaults(func=container_manager.configure)477 parser_configure.set_defaults(func=container_manager.configure)
463478
464 # Handle merging another ContainersConfig.json file into the main ContainersConfig.json file479 # Handle merging another ContainersConfig.json file into the main ContainersConfig.json file
465480
=== modified file 'tools/libertine-container-manager.1'
--- tools/libertine-container-manager.1 2016-07-07 18:54:59 +0000
+++ tools/libertine-container-manager.1 2016-07-13 19:49:12 +0000
@@ -265,14 +265,19 @@
265Enable i386 support.265Enable i386 support.
266.RE266.RE
267.IP267.IP
268.BR \-a " ARCHIVE_NAME, " \-\-add-archive " ARCHIVE_NAME" ""268.BR \-a " {add,remove}, " \-\-archive "{add,remove}" ""
269.RS 14269.RS 14
270Adds an archive to the specified container. Examples: 'deb http://myserver/path/to/repo stable myrepo', ppa:user/repository, multiverse270Adds or removes an archive in the specified container.
271.RE271.RE
272.IP272.IP
273.BR \-d " ARCHIVE_NAME, " \-\-delete-archive " ARCHIVE_NAME" ""273.BR \-n " ARCHIVE_NAME, " \-\-archive-name " ARCHIVE_NAME" ""
274.RS 14274.RS 14
275Deletes an archive to the specified container. Examples: 'deb http://myserver/path/to/repo stable myrepo', ppa:user/repository, multiverse275Archive to be added or removed. Examples: 'deb http://myserver/path/to/repo stable myrepo', ppa:user/repository, multiverse
276.RE
277.IP
278.BR \-k " PUBLIC_KEY_FILE, " \-\-public-key-file " PUBLIC_KEY_FILE" ""
279.RS 14
280File containing public key used to sign new archive.
276.RE281.RE
277.TP282.TP
278283

Subscribers

People subscribed via source and target branches