Merge lp:~vorlon/ubuntu/quantal/aptdaemon/py3 into lp:ubuntu/quantal/aptdaemon
- Quantal (12.10)
- py3
- Merge into quantal
Proposed by
Steve Langasek
on 2012-06-13
| Status: | Merged |
|---|---|
| Merged at revision: | 105 |
| Proposed branch: | lp:~vorlon/ubuntu/quantal/aptdaemon/py3 |
| Merge into: | lp:ubuntu/quantal/aptdaemon |
| Diff against target: |
155465 lines (+83209/-31522) 152 files modified
.pc/.version (+1/-0) .pc/applied-patches (+2/-0) .pc/disable_simulate_test.patch/tests/test_simulate.py (+74/-0) .pc/test-suite-fixes/aptdaemon/test.py (+296/-0) .pc/test-suite-fixes/aptdaemon/worker.py (+1544/-0) NEWS (+31/-2) README.PackageKit (+4/-5) README.tests (+3/-2) aptd (+1/-1) aptdaemon/client.py (+17/-13) aptdaemon/config.py (+1/-1) aptdaemon/console.py (+50/-45) aptdaemon/core.py (+17/-17) aptdaemon/errors.py (+14/-7) aptdaemon/gtk3widgets.py (+3/-3) aptdaemon/gtkwidgets.py (+2/-2) aptdaemon/lock.py (+1/-1) aptdaemon/networking.py (+3/-2) aptdaemon/pkcompat.py (+105/-69) aptdaemon/pkenums.py (+326/-0) aptdaemon/policykit1.py (+2/-1) aptdaemon/progress.py (+132/-79) aptdaemon/test.py (+79/-20) aptdaemon/utils.py (+3/-3) aptdaemon/worker.py (+66/-65) aptdcon (+1/-1) debian/aptdaemon.install (+2/-2) debian/changelog (+39/-0) debian/control (+93/-49) debian/patches/disable_simulate_test.patch (+12/-0) debian/patches/series (+2/-0) debian/patches/test-suite-fixes (+53/-0) debian/python-aptdaemon.pkcompat.install (+2/-1) debian/python-aptdaemon.test.install (+1/-1) debian/python3-aptdaemon.gtk3widgets.examples (+1/-0) debian/python3-aptdaemon.gtk3widgets.install (+1/-0) debian/python3-aptdaemon.install (+16/-0) debian/python3-aptdaemon.pkcompat.docs (+1/-0) debian/python3-aptdaemon.pkcompat.install (+4/-0) debian/python3-aptdaemon.test.examples (+1/-0) debian/python3-aptdaemon.test.install (+18/-0) debian/rules (+24/-4) doc/source/aptdaemon.gtk3widgets.rst (+5/-0) doc/source/aptdaemon.gtkwidgets.rst (+0/-5) doc/source/index.rst (+1/-1) gtk-demo.py (+1/-1) gtk3-demo.py (+4/-7) po/af.po (+785/-415) po/am.po (+788/-375) po/ar.po (+772/-322) po/ast.po (+815/-452) po/az.po (+1362/-0) po/be.po (+1002/-574) po/bg.po (+817/-433) po/bn.po (+1001/-516) po/br.po (+785/-415) po/bs.po (+988/-482) po/ca.po (+903/-477) po/ca@valencia.po (+1450/-0) po/crh.po (+774/-324) po/cs.po (+927/-510) po/cy.po (+1364/-0) po/da.po (+812/-425) po/de.po (+888/-495) po/dv.po (+778/-337) po/el.po (+825/-434) po/en_AU.po (+957/-544) po/en_CA.po (+842/-470) po/en_GB.po (+867/-504) po/eo.po (+909/-496) po/es.po (+819/-457) po/et.po (+885/-470) po/eu.po (+885/-484) po/fa.po (+772/-322) po/fi.po (+825/-451) po/fil.po (+1362/-0) po/fo.po (+1362/-0) po/fr.po (+856/-484) po/gd.po (+1454/-0) po/gl.po (+814/-450) po/he.po (+800/-432) po/hi.po (+908/-499) po/hr.po (+772/-322) po/hu.po (+809/-444) po/hy.po (+1362/-0) po/id.po (+849/-455) po/is.po (+781/-336) po/it.po (+833/-446) po/ja.po (+824/-442) po/kk.po (+805/-432) po/km.po (+1434/-0) po/kn.po (+774/-324) po/ko.po (+917/-529) po/ku.po (+774/-353) po/ky.po (+1362/-0) po/ln.po (+1362/-0) po/lt.po (+913/-488) po/lv.po (+954/-521) po/ml.po (+809/-365) po/ms.po (+902/-488) po/my.po (+1362/-0) po/nb.po (+804/-450) po/nds.po (+777/-350) po/ne.po (+773/-361) po/nl.po (+825/-453) po/nn.po (+893/-418) po/oc.po (+898/-470) po/pl.po (+836/-441) po/pt.po (+969/-545) po/pt_BR.po (+831/-466) po/ro.po (+889/-490) po/ru.po (+866/-494) po/shn.po (+1362/-0) po/si.po (+812/-353) po/sk.po (+839/-440) po/sl.po (+842/-478) po/sq.po (+898/-476) po/sr.po (+989/-559) po/sv.po (+810/-445) po/ta.po (+840/-390) po/te.po (+1378/-0) po/th.po (+893/-462) po/tr.po (+817/-448) po/ug.po (+832/-405) po/uk.po (+911/-489) po/ur.po (+1362/-0) po/uz.po (+1362/-0) po/vi.po (+975/-564) po/zh_CN.po (+811/-442) po/zh_HK.po (+793/-406) po/zh_TW.po (+791/-425) setup.py (+6/-1) tests/_test_py2_string_handling.py (+94/-0) tests/fakeroot-apt-key (+2/-0) tests/repo/Packages (+147/-148) tests/repo/Release (+16/-4) tests/repo/Release.gpg (+8/-8) tests/repo/glatzor.gpg (+107/-51) tests/test_client.py (+31/-0) tests/test_configparser.py (+5/-0) tests/test_dbus_type.py (+6/-4) tests/test_debconf.py (+31/-26) tests/test_index.py (+2/-3) tests/test_lock.py (+7/-8) tests/test_lock_location.py (+6/-1) tests/test_pk.py (+157/-26) tests/test_progress.py (+5/-0) tests/test_py2_string_handling.py (+38/-0) tests/test_simulate.py (+1/-0) tests/test_unicodedecoding.py (+0/-94) tests/test_valid_package_names.py (+8/-3) tests/test_worker.py (+44/-21) |
| To merge this branch: | bzr merge lp:~vorlon/ubuntu/quantal/aptdaemon/py3 |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Canonical Foundations Team | 2012-06-13 | Pending | |
|
Review via email:
|
|||
Commit Message
Description of the Change
All ready for merge, passes the tests... feel free to upload if it checks
out in the morning and it's blocking anyone, otherwise I'll plan to upload
when I come online myself.
To post a comment you must log in.
lp:~vorlon/ubuntu/quantal/aptdaemon/py3
updated
on 2012-06-13
- 105. By Steve Langasek on 2012-06-13
-
test/test_pk.py: increase the sleep on startup, to allow longer for
fake-polkitd to start up.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
| 1 | === added directory '.pc' |
| 2 | === added file '.pc/.version' |
| 3 | --- .pc/.version 1970-01-01 00:00:00 +0000 |
| 4 | +++ .pc/.version 2012-06-13 16:29:18 +0000 |
| 5 | @@ -0,0 +1,1 @@ |
| 6 | +2 |
| 7 | |
| 8 | === added file '.pc/applied-patches' |
| 9 | --- .pc/applied-patches 1970-01-01 00:00:00 +0000 |
| 10 | +++ .pc/applied-patches 2012-06-13 16:29:18 +0000 |
| 11 | @@ -0,0 +1,2 @@ |
| 12 | +disable_simulate_test.patch |
| 13 | +test-suite-fixes |
| 14 | |
| 15 | === added directory '.pc/disable_simulate_test.patch' |
| 16 | === added directory '.pc/disable_simulate_test.patch/tests' |
| 17 | === added file '.pc/disable_simulate_test.patch/tests/test_simulate.py' |
| 18 | --- .pc/disable_simulate_test.patch/tests/test_simulate.py 1970-01-01 00:00:00 +0000 |
| 19 | +++ .pc/disable_simulate_test.patch/tests/test_simulate.py 2012-06-13 16:29:18 +0000 |
| 20 | @@ -0,0 +1,74 @@ |
| 21 | +#!/usr/bin/env python |
| 22 | +# -*- coding: utf-8 -*- |
| 23 | +"""Tests if the daemon forces a simualte during run.""" |
| 24 | + |
| 25 | +import logging |
| 26 | +import time |
| 27 | +import unittest |
| 28 | + |
| 29 | +from gi.repository import GObject |
| 30 | +import dbus |
| 31 | + |
| 32 | +import aptdaemon.client |
| 33 | +import aptdaemon.loop |
| 34 | +import aptdaemon.enums |
| 35 | + |
| 36 | +import aptdaemon.test |
| 37 | + |
| 38 | +DEBUG=True |
| 39 | + |
| 40 | + |
| 41 | +class DaemonTest(aptdaemon.test.AptDaemonTestCase): |
| 42 | + |
| 43 | + """Test the python client.""" |
| 44 | + |
| 45 | + def setUp(self): |
| 46 | + """Setup a chroot, run the aptdaemon and a fake PolicyKit daemon.""" |
| 47 | + # Setup chroot |
| 48 | + self.chroot = aptdaemon.test.Chroot() |
| 49 | + self.chroot.setup() |
| 50 | + self.addCleanup(self.chroot.remove) |
| 51 | + # Start aptdaemon with the chroot on the session bus |
| 52 | + self.start_dbus_daemon() |
| 53 | + self.bus = dbus.bus.BusConnection(self.dbus_address) |
| 54 | + self.start_session_aptd(self.chroot.path) |
| 55 | + # Start the fake PolikcyKit daemon |
| 56 | + self.start_fake_polkitd() |
| 57 | + time.sleep(1) |
| 58 | + |
| 59 | + def _on_finished(self, trans, exit): |
| 60 | + """Callback to stop the mainloop after a transaction is done.""" |
| 61 | + aptdaemon.loop.mainloop.quit() |
| 62 | + |
| 63 | + def test_detect_unauthenticated(self): |
| 64 | + """Test if the installation of an unauthenticated packages fails |
| 65 | + if simulate hasn't been called explicitly before. |
| 66 | + """ |
| 67 | + self.chroot.add_test_repository(copy_sig=False) |
| 68 | + self.client = aptdaemon.client.AptClient(self.bus) |
| 69 | + trans = self.client.install_packages(["silly-base"]) |
| 70 | + trans.connect("finished", self._on_finished) |
| 71 | + trans.run() |
| 72 | + aptdaemon.loop.mainloop.run() |
| 73 | + self.assertEqual(trans.exit, aptdaemon.enums.EXIT_FAILED) |
| 74 | + self.assertEqual(trans.error.code, |
| 75 | + aptdaemon.enums.ERROR_PACKAGE_UNAUTHENTICATED) |
| 76 | + self.assertEqual(trans.unauthenticated, ["silly-base"]) |
| 77 | + |
| 78 | + def test_environment(self): |
| 79 | + """Ensure that the test environment works.""" |
| 80 | + self.chroot.add_test_repository() |
| 81 | + self.client = aptdaemon.client.AptClient(self.bus) |
| 82 | + trans = self.client.install_packages(["silly-base"]) |
| 83 | + trans.connect("finished", self._on_finished) |
| 84 | + trans.run() |
| 85 | + aptdaemon.loop.mainloop.run() |
| 86 | + self.assertEqual(trans.exit, aptdaemon.enums.EXIT_SUCCESS) |
| 87 | + |
| 88 | + |
| 89 | +if __name__ == "__main__": |
| 90 | + if DEBUG: |
| 91 | + logging.basicConfig(level=logging.DEBUG) |
| 92 | + unittest.main() |
| 93 | + |
| 94 | +# vim: ts=4 et sts=4 |
| 95 | |
| 96 | === added directory '.pc/test-suite-fixes' |
| 97 | === added directory '.pc/test-suite-fixes/aptdaemon' |
| 98 | === added file '.pc/test-suite-fixes/aptdaemon/test.py' |
| 99 | --- .pc/test-suite-fixes/aptdaemon/test.py 1970-01-01 00:00:00 +0000 |
| 100 | +++ .pc/test-suite-fixes/aptdaemon/test.py 2012-06-13 16:29:18 +0000 |
| 101 | @@ -0,0 +1,296 @@ |
| 102 | +#!/usr/bin/env python |
| 103 | +# -*- coding: utf-8 -*- |
| 104 | +"""Small helpers for the test suite.""" |
| 105 | +# Copyright (C) 2011 Sebastian Heinlein <devel@glatzor.de> |
| 106 | +# |
| 107 | +# Licensed under the GNU General Public License Version 2 |
| 108 | +# |
| 109 | +# This program is free software; you can redistribute it and/or modify |
| 110 | +# it under the terms of the GNU General Public License as published by |
| 111 | +# the Free Software Foundation; either version 2 of the License, or |
| 112 | +# at your option) any later version. |
| 113 | +# |
| 114 | +# This program is distributed in the hope that it will be useful, |
| 115 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 116 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 117 | +# GNU General Public License for more details. |
| 118 | +# |
| 119 | +# You should have received a copy of the GNU General Public License |
| 120 | +# along with this program; if not, write to the Free Software |
| 121 | +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 122 | +# Licensed under the GNU General Public License Version 2 |
| 123 | + |
| 124 | +__author__ = "Sebastian Heinlein <devel@glatzor.de>" |
| 125 | +__all__ = ("get_tests_dir", "Chroot", "AptDaemonTestCase") |
| 126 | + |
| 127 | +import inspect |
| 128 | +import os |
| 129 | +import shutil |
| 130 | +import subprocess |
| 131 | +import sys |
| 132 | +import time |
| 133 | +import tempfile |
| 134 | +import unittest |
| 135 | + |
| 136 | +if sys.version_info.major > 2: |
| 137 | + from http.server import HTTPServer |
| 138 | + from http.server import SimpleHTTPRequestHandler as HTTPRequestHandler |
| 139 | +else: |
| 140 | + from BaseHTTPServer import HTTPServer |
| 141 | + from SimpleHTTPServer import SimpleHTTPRequestHandler as HTTPRequestHandler |
| 142 | + |
| 143 | +import apt_pkg |
| 144 | +import apt.auth |
| 145 | + |
| 146 | +PY3K = sys.version_info.major > 2 |
| 147 | + |
| 148 | + |
| 149 | +class Chroot(object): |
| 150 | + |
| 151 | + """Provides a chroot which can be used by APT.""" |
| 152 | + |
| 153 | + def __init__(self, prefix="tmp"): |
| 154 | + self.path = tempfile.mkdtemp(prefix) |
| 155 | + |
| 156 | + def setup(self): |
| 157 | + """Setup the chroot and modify the apt configuration.""" |
| 158 | + for subdir in ["alternatives", "info", "parts", "updates", "triggers"]: |
| 159 | + path = os.path.join(self.path, "var", "lib", "dpkg", subdir) |
| 160 | + os.makedirs(path) |
| 161 | + for fname in ["status", "available"]: |
| 162 | + with open(os.path.join(self.path, "var", "lib", "dpkg", fname), |
| 163 | + "w"): |
| 164 | + pass |
| 165 | + os.makedirs(os.path.join(self.path, "var/cache/apt/archives/partial")) |
| 166 | + os.makedirs(os.path.join(self.path, "var/lib/apt/lists")) |
| 167 | + os.makedirs(os.path.join(self.path, "var/lib/apt/lists/partial")) |
| 168 | + os.makedirs(os.path.join(self.path, "etc/apt/apt.conf.d")) |
| 169 | + os.makedirs(os.path.join(self.path, "etc/apt/sources.list.d")) |
| 170 | + os.makedirs(os.path.join(self.path, "etc/apt/preferences.d")) |
| 171 | + os.makedirs(os.path.join(self.path, "var/log")) |
| 172 | + os.makedirs(os.path.join(self.path, "media")) |
| 173 | + |
| 174 | + # Make apt use the new chroot |
| 175 | + dpkg_wrapper = os.path.join(get_tests_dir(), "dpkg-wrapper.sh") |
| 176 | + apt_key_wrapper = os.path.join(get_tests_dir(), "fakeroot-apt-key") |
| 177 | + config_path = os.path.join(self.path, "etc/apt/apt.conf.d/10chroot") |
| 178 | + with open(config_path, "w") as cnf: |
| 179 | + cnf.write("Dir::Bin::DPkg %s;" % dpkg_wrapper) |
| 180 | + cnf.write("Dir::Bin::Apt-Key %s;" % apt_key_wrapper) |
| 181 | + apt_pkg.read_config_file(apt_pkg.config, config_path) |
| 182 | + apt_pkg.init_system() |
| 183 | + |
| 184 | + def remove(self): |
| 185 | + """Remove the files of the chroot.""" |
| 186 | + apt_pkg.config.clear("Dir") |
| 187 | + apt_pkg.config.clear("Dir::State::Status") |
| 188 | + apt_pkg.init() |
| 189 | + shutil.rmtree(self.path) |
| 190 | + |
| 191 | + def add_trusted_key(self): |
| 192 | + """Add glatzor's key to the trusted ones.""" |
| 193 | + apt.auth.add_key_from_file(os.path.join(get_tests_dir(), |
| 194 | + "repo/glatzor.gpg")) |
| 195 | + |
| 196 | + def install_debfile(self, path, force_depends=False): |
| 197 | + """Install a package file into the chroot.""" |
| 198 | + cmd_list = ["fakeroot", "dpkg", "--root", self.path, |
| 199 | + "--log=%s/var/log/dpkg.log" % self.path] |
| 200 | + if force_depends: |
| 201 | + cmd_list.append("--force-depends") |
| 202 | + cmd_list.extend(["--install", path]) |
| 203 | + cmd = subprocess.Popen(cmd_list, |
| 204 | + env={"PATH": "/sbin:/bin:/usr/bin:/usr/sbin"}) |
| 205 | + cmd.communicate() |
| 206 | + |
| 207 | + def add_test_repository(self, copy_list=True, copy_sig=True): |
| 208 | + """Add the test repository to the to the chroot.""" |
| 209 | + return self.add_repository(os.path.join(get_tests_dir(), "repo"), |
| 210 | + copy_list, copy_sig) |
| 211 | + |
| 212 | + def add_cdrom_repository(self): |
| 213 | + """Emulate a repository on removable device.""" |
| 214 | + # Create the content of a fake cdrom |
| 215 | + media_path = os.path.join(self.path, "tmp/fake-cdrom") |
| 216 | + # The cdom gets identified by the info file |
| 217 | + os.makedirs(os.path.join(media_path, ".disk")) |
| 218 | + with open(os.path.join(media_path, ".disk/info"), "w") as info: |
| 219 | + info.write("This is a fake CDROM") |
| 220 | + # Copy the test repository "on" the cdrom |
| 221 | + shutil.copytree(os.path.join(get_tests_dir(), "repo"), |
| 222 | + os.path.join(media_path, "repo")) |
| 223 | + |
| 224 | + # Call apt-cdrom add |
| 225 | + mount_point = self.mount_cdrom() |
| 226 | + os.system("apt-cdrom add -m -d %s " |
| 227 | + "-o 'Debug::Acquire::cdrom'=True " |
| 228 | + "-o 'Acquire::cdrom::AutoDetect'=False " |
| 229 | + "-o 'Dir'=%s" % (mount_point, self.path)) |
| 230 | + self.unmount_cdrom() |
| 231 | + |
| 232 | + config_path = os.path.join(self.path, "etc/apt/apt.conf.d/11cdrom") |
| 233 | + with open(config_path, "w") as cnf: |
| 234 | + cnf.write('Debug::Acquire::cdrom True;\n' |
| 235 | + 'Acquire::cdrom::AutoDetect False;\n' |
| 236 | + 'Acquire::cdrom::NoMount True;\n' |
| 237 | + 'Acquire::cdrom::mount "%s";' % mount_point) |
| 238 | + |
| 239 | + def mount_cdrom(self): |
| 240 | + """Copy the repo information to the CDROM mount point.""" |
| 241 | + mount_point = os.path.join(self.path, "media/cdrom") |
| 242 | + os.symlink(os.path.join(self.path, "tmp/fake-cdrom"), mount_point) |
| 243 | + return mount_point |
| 244 | + |
| 245 | + def unmount_cdrom(self): |
| 246 | + """Remove all files from the mount point.""" |
| 247 | + os.unlink(os.path.join(self.path, "media/cdrom")) |
| 248 | + |
| 249 | + def add_repository(self, path, copy_list=True, copy_sig=True): |
| 250 | + """Add a sources.list entry to the chroot.""" |
| 251 | + # Add a sources list |
| 252 | + lst_path = os.path.join(self.path, "etc/apt/sources.list") |
| 253 | + with open(lst_path, "w") as lst_file: |
| 254 | + lst_file.write("deb file://%s ./ # Test repository" % path) |
| 255 | + if copy_list: |
| 256 | + filename = apt_pkg.uri_to_filename("file://%s/." % path) |
| 257 | + shutil.copy(os.path.join(path, "Packages"), |
| 258 | + "%s/var/lib/apt/lists/%s_Packages" % (self.path, |
| 259 | + filename)) |
| 260 | + if os.path.exists(os.path.join(path, "Release")): |
| 261 | + shutil.copy(os.path.join(path, "Release"), |
| 262 | + "%s/var/lib/apt/lists/%s_Release" % (self.path, |
| 263 | + filename)) |
| 264 | + if copy_sig and os.path.exists(os.path.join(path, "Release.gpg")): |
| 265 | + shutil.copy(os.path.join(path, "Release.gpg"), |
| 266 | + "%s/var/lib/apt/lists/%s_Release.gpg" % (self.path, |
| 267 | + filename)) |
| 268 | + |
| 269 | + |
| 270 | +class AptDaemonTestCase(unittest.TestCase): |
| 271 | + |
| 272 | + @classmethod |
| 273 | + def setupClass(cls): |
| 274 | + # Start with a clean APT configuration to remove changes |
| 275 | + # of previous tests |
| 276 | + for key in set([key.split("::")[0] for key in apt_pkg.config.keys()]): |
| 277 | + apt_pkg.config.clear(key) |
| 278 | + apt_pkg.init_config() |
| 279 | + |
| 280 | + def start_fake_polkitd(self, options="all"): |
| 281 | + """Start a fake PolicyKit daemon. |
| 282 | + |
| 283 | + :param allowed_actions: comma separated list of allowed actions. |
| 284 | + Defaults to all |
| 285 | + """ |
| 286 | + try: |
| 287 | + env = os.environ.copy() |
| 288 | + env["DBUS_SYSTEM_BUS_ADDRESS"] = self.dbus_address |
| 289 | + except AttributeError: |
| 290 | + env=None |
| 291 | + dir = get_tests_dir() |
| 292 | + proc = subprocess.Popen([os.path.join(dir, "fake-polkitd.py"), |
| 293 | + "--allowed-actions", options], |
| 294 | + env=env) |
| 295 | + self.addCleanup(self._kill_process, proc) |
| 296 | + return proc |
| 297 | + |
| 298 | + def start_session_aptd(self, chroot="/"): |
| 299 | + """Start an aptdaemon which listens on the session D-Bus. |
| 300 | + |
| 301 | + :param chroot: path to the chroot |
| 302 | + """ |
| 303 | + try: |
| 304 | + env = os.environ.copy() |
| 305 | + env["DBUS_SYSTEM_BUS_ADDRESS"] = self.dbus_address |
| 306 | + except AttributeError: |
| 307 | + env = None |
| 308 | + dir = get_tests_dir() |
| 309 | + if dir == "/usr/share/aptdaemon/tests": |
| 310 | + path = "/usr/sbin/aptd" |
| 311 | + else: |
| 312 | + path = os.path.join(dir, "../aptd") |
| 313 | + proc = subprocess.Popen(["python3", path, "--debug", |
| 314 | + "--disable-timeout", "--disable-plugins", |
| 315 | + "--chroot", chroot], |
| 316 | + env=env) |
| 317 | + self.addCleanup(self._kill_process, proc) |
| 318 | + return proc |
| 319 | + |
| 320 | + def start_dbus_daemon(self): |
| 321 | + """Start a private D-Bus daemon and return its process and address.""" |
| 322 | + proc, dbus_address = start_dbus_daemon() |
| 323 | + self.addCleanup(self._kill_process, proc) |
| 324 | + self.dbus_address = dbus_address |
| 325 | + |
| 326 | + def start_keyserver(self, filename=None): |
| 327 | + """Start a fake keyserver on hkp://localhost:19191 |
| 328 | + |
| 329 | + Keyword arguments: |
| 330 | + filename -- Optional path to a GnuPG pulic key file which should |
| 331 | + be returned by lookups. By default the key of the test repo |
| 332 | + is used. |
| 333 | + """ |
| 334 | + dir = tempfile.mkdtemp(prefix="keyserver-test-") |
| 335 | + self.addCleanup(shutil.rmtree, dir) |
| 336 | + os.mkdir(os.path.join(dir, "pks")) |
| 337 | + if filename is None: |
| 338 | + filename = os.path.join(get_tests_dir(), "repo/glatzor.gpg") |
| 339 | + shutil.copy(filename, os.path.join(dir, "pks", "lookup")) |
| 340 | + |
| 341 | + pid = os.fork() |
| 342 | + if pid == 0: |
| 343 | + # quiesce server log |
| 344 | + os.dup2(os.open('/dev/null', os.O_WRONLY), sys.stderr.fileno()) |
| 345 | + os.chdir(dir) |
| 346 | + httpd = HTTPServer(('localhost', 19191), HTTPRequestHandler) |
| 347 | + httpd.serve_forever() |
| 348 | + os._exit(0) |
| 349 | + else: |
| 350 | + self.addCleanup(self._kill_pid, pid) |
| 351 | + |
| 352 | + # wait a bit until server is ready |
| 353 | + time.sleep(0.5) |
| 354 | + |
| 355 | + def _kill_pid(self, pid): |
| 356 | + os.kill(pid, 15) |
| 357 | + os.wait() |
| 358 | + |
| 359 | + def _kill_process(self, proc): |
| 360 | + proc.kill() |
| 361 | + proc.wait() |
| 362 | + |
| 363 | + |
| 364 | +def get_tests_dir(): |
| 365 | + """Return the absolute path to the tests directory.""" |
| 366 | + # Try to detect a relative tests dir if we are running from the source |
| 367 | + # directory |
| 368 | + try: |
| 369 | + path = inspect.getsourcefile(sys.modules["aptdaemon.test"]) |
| 370 | + except KeyError as error: |
| 371 | + path = inspect.getsourcefile(inspect.currentframe()) |
| 372 | + path = os.path.realpath(path) |
| 373 | + relative_path = os.path.join(os.path.dirname(path), "../tests") |
| 374 | + if os.path.exists(os.path.join(relative_path, "repo/Packages")): |
| 375 | + return os.path.normpath(relative_path) |
| 376 | + # Fallback to an absolute path |
| 377 | + elif os.path.exists("/usr/share/aptdaemon/tests/repo/Packages"): |
| 378 | + return "/usr/share/aptdaemon/tests" |
| 379 | + else: |
| 380 | + raise Exception("Could not find tests direcotry") |
| 381 | + |
| 382 | +def start_dbus_daemon(): |
| 383 | + """Start a private D-Bus daemon and return its process and address.""" |
| 384 | + config_path = os.path.join(get_tests_dir(), "dbus.conf") |
| 385 | + proc = subprocess.Popen(["dbus-daemon", "--nofork", |
| 386 | + "--print-address", "--config-file", |
| 387 | + config_path], |
| 388 | + stdout=subprocess.PIPE) |
| 389 | + output = proc.stdout.readline().strip() |
| 390 | + if PY3K: |
| 391 | + dbus_address = output.decode() |
| 392 | + else: |
| 393 | + dbus_address = output |
| 394 | + return proc, dbus_address |
| 395 | + |
| 396 | + |
| 397 | +# vim: ts=4 et sts=4 |
| 398 | |
| 399 | === added file '.pc/test-suite-fixes/aptdaemon/worker.py' |
| 400 | --- .pc/test-suite-fixes/aptdaemon/worker.py 1970-01-01 00:00:00 +0000 |
| 401 | +++ .pc/test-suite-fixes/aptdaemon/worker.py 2012-06-13 16:29:18 +0000 |
| 402 | @@ -0,0 +1,1544 @@ |
| 403 | +#!/usr/bin/env python |
| 404 | +# -*- coding: utf-8 -*- |
| 405 | +"""Provides AptWorker which processes transactions.""" |
| 406 | +# Copyright (C) 2008-2009 Sebastian Heinlein <devel@glatzor.de> |
| 407 | +# |
| 408 | +# This program is free software; you can redistribute it and/or modify |
| 409 | +# it under the terms of the GNU General Public License as published by |
| 410 | +# the Free Software Foundation; either version 2 of the License, or |
| 411 | +# any later version. |
| 412 | +# |
| 413 | +# This program is distributed in the hope that it will be useful, |
| 414 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 415 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 416 | +# GNU General Public License for more details. |
| 417 | +# |
| 418 | +# You should have received a copy of the GNU General Public License along |
| 419 | +# with this program; if not, write to the Free Software Foundation, Inc., |
| 420 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| 421 | + |
| 422 | +__author__ = "Sebastian Heinlein <devel@glatzor.de>" |
| 423 | + |
| 424 | +__all__ = ("AptWorker", "DummyWorker") |
| 425 | + |
| 426 | +import contextlib |
| 427 | +import logging |
| 428 | +import os |
| 429 | +import platform |
| 430 | +import re |
| 431 | +import shutil |
| 432 | +import sys |
| 433 | +import tempfile |
| 434 | +import time |
| 435 | +import traceback |
| 436 | +from urllib.parse import urlsplit, urlunsplit |
| 437 | + |
| 438 | +import apt |
| 439 | +import apt.auth |
| 440 | +import apt.cache |
| 441 | +import apt.debfile |
| 442 | +import apt_pkg |
| 443 | +import aptsources |
| 444 | +import aptsources.distro |
| 445 | +from aptsources.sourceslist import SourcesList |
| 446 | +from gi.repository import GObject |
| 447 | +import pkg_resources |
| 448 | +import subprocess |
| 449 | + |
| 450 | +from .enums import * |
| 451 | +from .errors import * |
| 452 | +from . import lock |
| 453 | +from .loop import mainloop |
| 454 | +from .progress import DaemonOpenProgress, \ |
| 455 | + DaemonInstallProgress, \ |
| 456 | + DaemonAcquireProgress, \ |
| 457 | + DaemonAcquireRepoProgress, \ |
| 458 | + DaemonDpkgInstallProgress, \ |
| 459 | + DaemonDpkgReconfigureProgress, \ |
| 460 | + DaemonDpkgRecoverProgress, \ |
| 461 | + DaemonForkProgress |
| 462 | + |
| 463 | +log = logging.getLogger("AptDaemon.Worker") |
| 464 | + |
| 465 | +# Just required to detect translatable strings. The translation is done by |
| 466 | +# core.Transaction.gettext |
| 467 | +_ = lambda s: s |
| 468 | + |
| 469 | + |
| 470 | +class AptWorker(GObject.GObject): |
| 471 | + |
| 472 | + """Worker which processes transactions from the queue.""" |
| 473 | + |
| 474 | + __gsignals__ = {"transaction-done":(GObject.SignalFlags.RUN_FIRST, |
| 475 | + None, |
| 476 | + (GObject.TYPE_PYOBJECT,)), |
| 477 | + "transaction-simulated":(GObject.SignalFlags.RUN_FIRST, |
| 478 | + None, |
| 479 | + (GObject.TYPE_PYOBJECT,))} |
| 480 | + |
| 481 | + # the basedir under which license keys can be stored |
| 482 | + LICENSE_KEY_ROOTDIR = "/opt/" |
| 483 | + |
| 484 | + def __init__(self, chroot=None, load_plugins=True): |
| 485 | + """Initialize a new AptWorker instance.""" |
| 486 | + GObject.GObject.__init__(self) |
| 487 | + self.trans = None |
| 488 | + self.last_action_timestamp = time.time() |
| 489 | + self._cache = None |
| 490 | + # Store the the tid of the transaction whose changes are currently |
| 491 | + # marked in the cache |
| 492 | + self.marked_tid = None |
| 493 | + |
| 494 | + # Change to a given chroot |
| 495 | + if chroot: |
| 496 | + apt_conf_file = os.path.join(chroot, "etc/apt/apt.conf") |
| 497 | + if os.path.exists(apt_conf_file): |
| 498 | + apt_pkg.read_config_file(apt_pkg.config, apt_conf_file) |
| 499 | + apt_conf_dir = os.path.join(chroot, "etc/apt/apt.conf.d") |
| 500 | + if os.path.isdir(apt_conf_dir): |
| 501 | + apt_pkg.read_config_dir(apt_pkg.config, apt_conf_dir) |
| 502 | + apt_pkg.config["Dir"] = chroot |
| 503 | + apt_pkg.config["Dir::State::Status"] = os.path.join(chroot, |
| 504 | + "var/lib/dpkg/status") |
| 505 | + apt_pkg.config.clear("DPkg::Post-Invoke") |
| 506 | + apt_pkg.config.clear("DPkg::Options") |
| 507 | + apt_pkg.config["DPkg::Options::"] = "--root=%s" % chroot |
| 508 | + apt_pkg.config["DPkg::Options::"] = "--log=%s/var/log/dpkg.log" % \ |
| 509 | + chroot |
| 510 | + status_file = apt_pkg.config.find_file("Dir::State::status") |
| 511 | + lock.status_lock.path = os.path.join(os.path.dirname(status_file), |
| 512 | + "lock") |
| 513 | + archives_dir = apt_pkg.config.find_dir("Dir::Cache::Archives") |
| 514 | + lock.archive_lock.path = os.path.join(archives_dir, "lock") |
| 515 | + lists_dir = apt_pkg.config.find_dir("Dir::State::lists") |
| 516 | + lock.lists_lock.path = os.path.join(lists_dir, "lock") |
| 517 | + apt_pkg.init_system() |
| 518 | + |
| 519 | + self._status_orig = apt_pkg.config.find_file("Dir::State::status") |
| 520 | + self._status_frozen = None |
| 521 | + self.plugins = {} |
| 522 | + if load_plugins: |
| 523 | + self._load_plugins() |
| 524 | + |
| 525 | + def _load_plugins(self): |
| 526 | + """Load the plugins from setuptools' entry points.""" |
| 527 | + plugin_dirs = [os.path.join(os.path.dirname(__file__), "plugins")] |
| 528 | + env = pkg_resources.Environment(plugin_dirs) |
| 529 | + dists, errors = pkg_resources.working_set.find_plugins(env) |
| 530 | + for dist in dists: |
| 531 | + pkg_resources.working_set.add(dist) |
| 532 | + for name in ["modify_cache_after", "modify_cache_before", |
| 533 | + "get_license_key"]: |
| 534 | + for ept in pkg_resources.iter_entry_points("aptdaemon.plugins", |
| 535 | + name): |
| 536 | + try: |
| 537 | + self.plugins.setdefault(name, []).append(ept.load()) |
| 538 | + except: |
| 539 | + log.critical("Failed to load %s plugin: " |
| 540 | + "%s" % (name, ept.dist)) |
| 541 | + else: |
| 542 | + log.debug("Loaded %s plugin: %s", name, ept.dist) |
| 543 | + |
| 544 | + def _call_plugins(self, name, resolver=None): |
| 545 | + """Call all plugins of a given type.""" |
| 546 | + if not resolver: |
| 547 | + # If the resolver of the original task isn't available we create |
| 548 | + # a new one and protect the already marked changes |
| 549 | + resolver = apt.cache.ProblemResolver(self._cache) |
| 550 | + for pkg in self._cache.get_changes(): |
| 551 | + resolver.clear(pkg) |
| 552 | + resolver.protect(pkg) |
| 553 | + if pkg.marked_delete: |
| 554 | + resolver.remove(pkg) |
| 555 | + if not name in self.plugins: |
| 556 | + log.debug("There isn't any registered %s plugin" % name) |
| 557 | + return False |
| 558 | + for plugin in self.plugins[name]: |
| 559 | + log.debug("Calling %s plugin: %s", name, plugin) |
| 560 | + try: |
| 561 | + plugin(resolver, self._cache) |
| 562 | + except Exception as error: |
| 563 | + log.critical("Failed to call %s plugin:\n%s" % (plugin, error)) |
| 564 | + return True |
| 565 | + |
| 566 | + def run(self, transaction): |
| 567 | + """Process the given transaction in the background. |
| 568 | + |
| 569 | + Keyword argument: |
| 570 | + transaction -- core.Transcation instance to run |
| 571 | + """ |
| 572 | + log.info("Processing transaction %s", transaction.tid) |
| 573 | + if self.trans: |
| 574 | + raise Exception("There is already a running transaction") |
| 575 | + self.trans = transaction |
| 576 | + GObject.idle_add(self._process_transaction, transaction) |
| 577 | + |
| 578 | + def _emit_transaction_simulated(self, trans): |
| 579 | + """Emit the transaction-simulated signal. |
| 580 | + |
| 581 | + Keyword argument: |
| 582 | + trans -- the simulated transaction |
| 583 | + """ |
| 584 | + log.debug("Emitting transaction-simulated: %s", trans.tid) |
| 585 | + self.emit("transaction-simulated", trans) |
| 586 | + |
| 587 | + def _emit_transaction_done(self, trans): |
| 588 | + """Emit the transaction-done signal. |
| 589 | + |
| 590 | + Keyword argument: |
| 591 | + trans -- the finished transaction |
| 592 | + """ |
| 593 | + log.debug("Emitting transaction-done: %s", trans.tid) |
| 594 | + self.emit("transaction-done", trans) |
| 595 | + |
| 596 | + def _process_transaction(self, trans): |
| 597 | + """Run the worker""" |
| 598 | + self.last_action_timestamp = time.time() |
| 599 | + trans.status = STATUS_RUNNING |
| 600 | + trans.progress = 11 |
| 601 | + try: |
| 602 | + lock.wait_for_lock(trans) |
| 603 | + # Prepare the package cache |
| 604 | + if trans.role == ROLE_FIX_INCOMPLETE_INSTALL or \ |
| 605 | + not self.is_dpkg_journal_clean(): |
| 606 | + self.fix_incomplete_install(trans) |
| 607 | + # Process transaction which don't require a cache |
| 608 | + if trans.role == ROLE_ADD_VENDOR_KEY_FILE: |
| 609 | + self.add_vendor_key_from_file(trans, **trans.kwargs) |
| 610 | + elif trans.role == ROLE_ADD_VENDOR_KEY_FROM_KEYSERVER: |
| 611 | + self.add_vendor_key_from_keyserver(trans, **trans.kwargs) |
| 612 | + elif trans.role == ROLE_REMOVE_VENDOR_KEY: |
| 613 | + self.remove_vendor_key(trans, **trans.kwargs) |
| 614 | + elif trans.role == ROLE_ADD_REPOSITORY: |
| 615 | + self.add_repository(trans, **trans.kwargs) |
| 616 | + elif trans.role == ROLE_ENABLE_DISTRO_COMP: |
| 617 | + self.enable_distro_comp(trans, **trans.kwargs) |
| 618 | + elif trans.role == ROLE_RECONFIGURE: |
| 619 | + self.reconfigure(trans, trans.packages[PKGS_REINSTALL], |
| 620 | + **trans.kwargs) |
| 621 | + elif trans.role == ROLE_CLEAN: |
| 622 | + self.clean(trans) |
| 623 | + # Check if the transaction has been just simulated. So we could |
| 624 | + # skip marking the changes a second time. |
| 625 | + elif trans.role in (ROLE_REMOVE_PACKAGES, ROLE_INSTALL_PACKAGES, |
| 626 | + ROLE_UPGRADE_PACKAGES, ROLE_COMMIT_PACKAGES, |
| 627 | + ROLE_UPGRADE_SYSTEM, |
| 628 | + ROLE_FIX_BROKEN_DEPENDS) and \ |
| 629 | + self.marked_tid == trans.tid: |
| 630 | + self._apply_changes(trans) |
| 631 | + trans.exit = EXIT_SUCCESS |
| 632 | + return False |
| 633 | + else: |
| 634 | + self._open_cache(trans) |
| 635 | + # Process transaction which can handle a broken dep cache |
| 636 | + if trans.role == ROLE_FIX_BROKEN_DEPENDS: |
| 637 | + self.fix_broken_depends(trans) |
| 638 | + elif trans.role == ROLE_UPDATE_CACHE: |
| 639 | + self.update_cache(trans, **trans.kwargs) |
| 640 | + # Process the transactions which require a consistent cache |
| 641 | + elif trans.role == ROLE_ADD_LICENSE_KEY: |
| 642 | + self.add_license_key(trans, **trans.kwargs) |
| 643 | + elif self._cache and self._cache.broken_count: |
| 644 | + broken = [pkg.name for pkg in self._cache if pkg.is_now_broken] |
| 645 | + raise TransactionFailed(ERROR_CACHE_BROKEN, |
| 646 | + self._get_broken_details(trans)) |
| 647 | + if trans.role == ROLE_PK_QUERY: |
| 648 | + self.query(trans) |
| 649 | + elif trans.role == ROLE_INSTALL_FILE: |
| 650 | + self.install_file(trans, **trans.kwargs) |
| 651 | + elif trans.role in [ROLE_REMOVE_PACKAGES, ROLE_INSTALL_PACKAGES, |
| 652 | + ROLE_UPGRADE_PACKAGES, ROLE_COMMIT_PACKAGES]: |
| 653 | + self.commit_packages(trans, *trans.packages) |
| 654 | + elif trans.role == ROLE_UPGRADE_SYSTEM: |
| 655 | + self.upgrade_system(trans, **trans.kwargs) |
| 656 | + except TransactionCancelled: |
| 657 | + trans.exit = EXIT_CANCELLED |
| 658 | + except TransactionFailed as excep: |
| 659 | + trans.error = excep |
| 660 | + trans.exit = EXIT_FAILED |
| 661 | + except (KeyboardInterrupt, SystemExit): |
| 662 | + trans.exit = EXIT_CANCELLED |
| 663 | + except Exception as excep: |
| 664 | + tbk = traceback.format_exc() |
| 665 | + trans.error = TransactionFailed(ERROR_UNKNOWN, tbk) |
| 666 | + trans.exit = EXIT_FAILED |
| 667 | + try: |
| 668 | + from . import crash |
| 669 | + except ImportError: |
| 670 | + pass |
| 671 | + else: |
| 672 | + crash.create_report("%s: %s" % (type(excep), str(excep)), |
| 673 | + tbk, trans) |
| 674 | + else: |
| 675 | + trans.exit = EXIT_SUCCESS |
| 676 | + finally: |
| 677 | + trans.progress = 100 |
| 678 | + self.last_action_timestamp = time.time() |
| 679 | + tid = trans.tid[:] |
| 680 | + self.trans = None |
| 681 | + self.marked_tid = None |
| 682 | + self._emit_transaction_done(trans) |
| 683 | + lock.release() |
| 684 | + log.info("Finished transaction %s", tid) |
| 685 | + return False |
| 686 | + |
| 687 | + def commit_packages(self, trans, install, reinstall, remove, purge, upgrade, |
| 688 | + downgrade, simulate=False): |
| 689 | + """Perform a complex package operation. |
| 690 | + |
| 691 | + Keyword arguments: |
| 692 | + trans - the transaction |
| 693 | + install - list of package names to install |
| 694 | + reinstall - list of package names to reinstall |
| 695 | + remove - list of package names to remove |
| 696 | + purge - list of package names to purge including configuration files |
| 697 | + upgrade - list of package names to upgrade |
| 698 | + downgrade - list of package names to upgrade |
| 699 | + simulate -- if True the changes won't be applied |
| 700 | + """ |
| 701 | + log.info("Committing packages: %s, %s, %s, %s, %s, %s", |
| 702 | + install, reinstall, remove, purge, upgrade, downgrade) |
| 703 | + with self._cache.actiongroup(): |
| 704 | + resolver = apt.cache.ProblemResolver(self._cache) |
| 705 | + self._mark_packages_for_installation(install, resolver) |
| 706 | + self._mark_packages_for_installation(reinstall, resolver, |
| 707 | + reinstall=True) |
| 708 | + self._mark_packages_for_removal(remove, resolver) |
| 709 | + self._mark_packages_for_removal(purge, resolver, purge=True) |
| 710 | + self._mark_packages_for_upgrade(upgrade, resolver) |
| 711 | + self._mark_packages_for_downgrade(downgrade, resolver) |
| 712 | + self._resolve_depends(trans, resolver) |
| 713 | + self._check_obsoleted_dependencies(trans, resolver) |
| 714 | + if not simulate: |
| 715 | + self._apply_changes(trans) |
| 716 | + |
| 717 | + def _resolve_depends(self, trans, resolver): |
| 718 | + """Resolve the dependencies using the given ProblemResolver.""" |
| 719 | + self._call_plugins("modify_cache_before", resolver) |
| 720 | + resolver.install_protect() |
| 721 | + try: |
| 722 | + resolver.resolve() |
| 723 | + except SystemError: |
| 724 | + raise TransactionFailed(ERROR_DEP_RESOLUTION_FAILED, |
| 725 | + self._get_broken_details(trans, now=False)) |
| 726 | + if self._call_plugins("modify_cache_after", resolver): |
| 727 | + try: |
| 728 | + resolver.resolve() |
| 729 | + except SystemError: |
| 730 | + details = self._get_broken_details(trans, now=False) |
| 731 | + raise TransactionFailed(ERROR_DEP_RESOLUTION_FAILED, details) |
| 732 | + |
| 733 | + @staticmethod |
| 734 | + def _split_package_id(package): |
| 735 | + """Return the name, the version number and the release of the |
| 736 | + specified package.""" |
| 737 | + if "=" in package: |
| 738 | + name, version = package.split("=", 1) |
| 739 | + release = None |
| 740 | + elif "/" in package: |
| 741 | + name, release = package.split("/", 1) |
| 742 | + version = None |
| 743 | + else: |
| 744 | + name = package |
| 745 | + version = release = None |
| 746 | + return name, version, release |
| 747 | + |
| 748 | + def _get_unauthenticated(self): |
| 749 | + """Return a list of unauthenticated package names """ |
| 750 | + unauthenticated = [] |
| 751 | + for pkg in self._iterate_packages(): |
| 752 | + if (pkg.marked_install or |
| 753 | + pkg.marked_downgrade or |
| 754 | + pkg.marked_upgrade or |
| 755 | + pkg.marked_reinstall): |
| 756 | + trusted = False |
| 757 | + for origin in pkg.candidate.origins: |
| 758 | + trusted |= origin.trusted |
| 759 | + if not trusted: |
| 760 | + unauthenticated.append(pkg.name) |
| 761 | + return unauthenticated |
| 762 | + |
| 763 | + def _mark_packages_for_installation(self, packages, resolver, |
| 764 | + reinstall=False): |
| 765 | + """Mark packages for installation.""" |
| 766 | + for pkg_name, pkg_ver, pkg_rel in [self._split_package_id(pkg) |
| 767 | + for pkg in packages]: |
| 768 | + try: |
| 769 | + pkg = self._cache[pkg_name] |
| 770 | + except KeyError: |
| 771 | + raise TransactionFailed(ERROR_NO_PACKAGE, |
| 772 | + _("Package %s isn't available"), |
| 773 | + pkg_name) |
| 774 | + if reinstall: |
| 775 | + if not pkg.is_installed: |
| 776 | + raise TransactionFailed(ERROR_PACKAGE_NOT_INSTALLED, |
| 777 | + _("Package %s isn't installed"), |
| 778 | + pkg.name) |
| 779 | + if pkg_ver and pkg.installed.version != pkg_ver: |
| 780 | + raise TransactionFailed(ERROR_PACKAGE_NOT_INSTALLED, |
| 781 | + _("The version %s of %s isn't " |
| 782 | + "installed"), |
| 783 | + pkg_ver, pkg_name) |
| 784 | + else: |
| 785 | + # Fail if the user requests to install the same version |
| 786 | + # of an already installed package. |
| 787 | + if (pkg.is_installed and |
| 788 | + # Compare version numbers |
| 789 | + pkg_ver and pkg_ver == pkg.installed.version and |
| 790 | + # Optionally compare the origin if specified |
| 791 | + (not pkg_rel or |
| 792 | + pkg_rel in [origin.archive for |
| 793 | + origin in pkg.installed.origins])): |
| 794 | + raise TransactionFailed(ERROR_PACKAGE_ALREADY_INSTALLED, |
| 795 | + _("Package %s is already " |
| 796 | + "installed"), pkg_name) |
| 797 | + pkg.mark_install(False, True, True) |
| 798 | + resolver.clear(pkg) |
| 799 | + resolver.protect(pkg) |
| 800 | + if pkg_ver: |
| 801 | + try: |
| 802 | + pkg.candidate = pkg.versions[pkg_ver] |
| 803 | + except KeyError: |
| 804 | + raise TransactionFailed(ERROR_NO_PACKAGE, |
| 805 | + _("The version %s of %s isn't " |
| 806 | + "available."), pkg_ver, pkg_name) |
| 807 | + elif pkg_rel: |
| 808 | + self._set_candidate_release(pkg, pkg_rel) |
| 809 | + |
| 810 | + |
| 811 | + def enable_distro_comp(self, trans, component): |
| 812 | + """Enable given component in the sources list. |
| 813 | + |
| 814 | + Keyword arguments: |
| 815 | + trans -- the corresponding transaction |
| 816 | + component -- a component, e.g. main or universe |
| 817 | + """ |
| 818 | + trans.progress = 101 |
| 819 | + trans.status = STATUS_COMMITTING |
| 820 | + old_umask = os.umask(0o022) |
| 821 | + try: |
| 822 | + sourceslist = SourcesList() |
| 823 | + distro = aptsources.distro.get_distro() |
| 824 | + distro.get_sources(sourceslist) |
| 825 | + distro.enable_component(component) |
| 826 | + sourceslist.save() |
| 827 | + finally: |
| 828 | + os.umask(old_umask) |
| 829 | + |
| 830 | + def add_repository(self, trans, src_type, uri, dist, comps, comment, sourcesfile): |
| 831 | + """Add given repository to the sources list. |
| 832 | + |
| 833 | + Keyword arguments: |
| 834 | + trans -- the corresponding transaction |
| 835 | + src_type -- the type of the entry (deb, deb-src) |
| 836 | + uri -- the main repository uri (e.g. http://archive.ubuntu.com/ubuntu) |
| 837 | + dist -- the distribution to use (e.g. karmic, "/") |
| 838 | + comps -- a (possible empty) list of components (main, restricted) |
| 839 | + comment -- an (optional) comment |
| 840 | + sourcesfile -- an (optinal) filename in sources.list.d |
| 841 | + """ |
| 842 | + trans.progress = 101 |
| 843 | + trans.status = STATUS_COMMITTING |
| 844 | + |
| 845 | + if sourcesfile: |
| 846 | + if not sourcesfile.endswith(".list"): |
| 847 | + sourcesfile += ".list" |
| 848 | + dir = apt_pkg.config.find_dir("Dir::Etc::sourceparts") |
| 849 | + sourcesfile = os.path.join(dir, os.path.basename(sourcesfile)) |
| 850 | + else: |
| 851 | + sourcesfile = None |
| 852 | + # Store any private login information in a separate auth.conf file |
| 853 | + if re.match("(http|https|ftp)://\S+?:\S+?@\S+", uri): |
| 854 | + uri = self._store_and_strip_password_from_uri(uri) |
| 855 | + auth_conf_path = apt_pkg.config.find_file("Dir::etc::netrc") |
| 856 | + if not comment: |
| 857 | + comment = "credentials stored in %s" % auth_conf_path |
| 858 | + else: |
| 859 | + comment += "; credentials stored in %s" % auth_conf_path |
| 860 | + try: |
| 861 | + sources = SourcesList() |
| 862 | + entry = sources.add(src_type, uri, dist, comps, comment, |
| 863 | + file=sourcesfile) |
| 864 | + if entry.invalid: |
| 865 | + #FIXME: Introduce new error codes |
| 866 | + raise RepositoryInvalidError() |
| 867 | + except: |
| 868 | + log.exception("adding repository") |
| 869 | + raise |
| 870 | + else: |
| 871 | + sources.save() |
| 872 | + |
| 873 | + def _store_and_strip_password_from_uri(self, uri): |
| 874 | + """Extract the credentials from an URI. Store the password in |
| 875 | + auth.conf and return the URI without any password information. |
| 876 | + """ |
| 877 | + try: |
| 878 | + res = urlsplit(uri) |
| 879 | + except ValueError as error: |
| 880 | + log.warn("Failed to urlsplit '%s'", error) |
| 881 | + return uri |
| 882 | + netloc_public = res.netloc.replace("%s:%s@" % (res.username, |
| 883 | + res.password), |
| 884 | + "") |
| 885 | + |
| 886 | + # write auth.conf |
| 887 | + auth_conf_path = apt_pkg.config.find_file("Dir::etc::netrc") |
| 888 | + old_umask = os.umask(0o027) |
| 889 | + try: |
| 890 | + with open(auth_conf_path, "a") as auth_conf: |
| 891 | + auth_conf.write("""machine %s |
| 892 | +login %s |
| 893 | +password %s\n\n""" % (netloc_public + res.path, res.username, res.password)) |
| 894 | + except OSError as error: |
| 895 | + log.warn("Failed to write auth.conf: '%s'" % error) |
| 896 | + finally: |
| 897 | + os.umask(old_umask) |
| 898 | + |
| 899 | + # Return URI without user/pass |
| 900 | + return urlunsplit((res.scheme, netloc_public, res.path, res.query, |
| 901 | + res.fragment)) |
| 902 | + |
| 903 | + def add_vendor_key_from_keyserver(self, trans, keyid, keyserver): |
| 904 | + """Add the signing key from the given (keyid, keyserver) to the |
| 905 | + trusted vendors. |
| 906 | + |
| 907 | + Keyword argument: |
| 908 | + trans -- the corresponding transaction |
| 909 | + keyid - the keyid of the key (e.g. 0x0EB12F05) |
| 910 | + keyserver - the keyserver (e.g. keyserver.ubuntu.com) |
| 911 | + """ |
| 912 | + log.info("Adding vendor key from keyserver: %s %s", keyid, keyserver) |
| 913 | + # Perform some sanity checks |
| 914 | + try: |
| 915 | + res = urlsplit(keyserver) |
| 916 | + except ValueError: |
| 917 | + raise TransactionFailed(ERROR_KEY_NOT_INSTALLED, |
| 918 | + #TRANSLATORS: %s is the URL of GnuPG |
| 919 | + # keyserver |
| 920 | + _("The keyserver URL is invalid: %s"), |
| 921 | + keyserver) |
| 922 | + if res.scheme not in ["hkp", "ldap", "ldaps", "http", "https"]: |
| 923 | + raise TransactionFailed(ERROR_KEY_NOT_INSTALLED, |
| 924 | + #TRANSLATORS: %s is the URL of GnuPG |
| 925 | + # keyserver |
| 926 | + _("Invalid protocol of the server: %s"), |
| 927 | + keyserver) |
| 928 | + try: |
| 929 | + int(keyid, 16) |
| 930 | + except ValueError: |
| 931 | + raise TransactionFailed(ERROR_KEY_NOT_INSTALLED, |
| 932 | + #TRANSLATORS: %s is the id of a GnuPG key |
| 933 | + # e.g. E08ADE95 |
| 934 | + _("Invalid key id: %s"), keyid) |
| 935 | + trans.status = STATUS_DOWNLOADING |
| 936 | + trans.progress = 101 |
| 937 | + last_pulse = time.time() |
| 938 | + with DaemonForkProgress(trans) as progress: |
| 939 | + progress.run(apt.auth.add_key_from_keyserver, keyid, keyserver) |
| 940 | + if progress._child_exit != 0: |
| 941 | + #TRANSLATORS: The first %s is the key id and the second the server |
| 942 | + raise TransactionFailed(ERROR_KEY_NOT_INSTALLED, |
| 943 | + _("Failed to download and install the key " |
| 944 | + "%s from %s:\n%s"), |
| 945 | + keyid, keyserver, progress.output) |
| 946 | + |
| 947 | + def add_vendor_key_from_file(self, trans, path): |
| 948 | + """Add the signing key from the given file to the trusted vendors. |
| 949 | + |
| 950 | + Keyword argument: |
| 951 | + path -- absolute path to the key file |
| 952 | + """ |
| 953 | + log.info("Adding vendor key from file: %s", path) |
| 954 | + trans.progress = 101 |
| 955 | + trans.status = STATUS_COMMITTING |
| 956 | + with DaemonForkProgress(trans) as progress: |
| 957 | + progress.run(apt.auth.add_key_from_file, path) |
| 958 | + if progress._child_exit != 0: |
| 959 | + raise TransactionFailed(ERROR_KEY_NOT_INSTALLED, |
| 960 | + _("Key file %s couldn't be installed: %s"), |
| 961 | + path, progress.output) |
| 962 | + |
| 963 | + def remove_vendor_key(self, trans, fingerprint): |
| 964 | + """Remove repository key. |
| 965 | + |
| 966 | + Keyword argument: |
| 967 | + trans -- the corresponding transaction |
| 968 | + fingerprint -- fingerprint of the key to remove |
| 969 | + """ |
| 970 | + log.info("Removing vendor key: %s", fingerprint) |
| 971 | + trans.progress = 101 |
| 972 | + trans.status = STATUS_COMMITTING |
| 973 | + try: |
| 974 | + int(fingerprint, 16) |
| 975 | + except ValueError: |
| 976 | + raise TransactionFailed(ERROR_KEY_NOT_REMOVED, |
| 977 | + #TRANSLATORS: %s is the id of a GnuPG key |
| 978 | + # e.g. E08ADE95 |
| 979 | + _("Invalid key id: %s"), fingerprint) |
| 980 | + with DaemonForkProgress(trans) as progress: |
| 981 | + progress.run(apt.auth.remove_key, fingerprint) |
| 982 | + if progress._child_exit != 0: |
| 983 | + raise TransactionFailed(ERROR_KEY_NOT_REMOVED, |
| 984 | + _("Key with fingerprint %s couldn't be " |
| 985 | + "removed: %s"), fingerprint, |
| 986 | + progress.output) |
| 987 | + |
| 988 | + def install_file(self, trans, path, force, simulate=False): |
| 989 | + """Install local package file. |
| 990 | + |
| 991 | + Keyword argument: |
| 992 | + trans -- the corresponding transaction |
| 993 | + path -- absolute path to the package file |
| 994 | + force -- if installing an invalid package is allowed |
| 995 | + simulate -- if True the changes won't be committed but the debfile |
| 996 | + instance will be returned |
| 997 | + """ |
| 998 | + log.info("Installing local package file: %s", path) |
| 999 | + # Check if the dpkg can be installed at all |
| 1000 | + trans.status = STATUS_RESOLVING_DEP |
| 1001 | + deb = self._check_deb_file(path, force, trans.uid) |
| 1002 | + # Check for required changes and apply them before |
| 1003 | + (install, remove, unauth) = deb.required_changes |
| 1004 | + self._call_plugins("modify_cache_after") |
| 1005 | + if simulate: |
| 1006 | + return deb |
| 1007 | + with self._frozen_status(): |
| 1008 | + if len(install) > 0 or len(remove) > 0: |
| 1009 | + dpkg_range = (64, 99) |
| 1010 | + self._apply_changes(trans, fetch_range=(15, 33), |
| 1011 | + install_range=(34, 63)) |
| 1012 | + # Install the dpkg file |
| 1013 | + deb_progress = DaemonDpkgInstallProgress(trans, begin=64, end=95) |
| 1014 | + res = deb.install(deb_progress) |
| 1015 | + encoding = sys.getfilesystemencoding() |
| 1016 | + trans.output += deb_progress.output |
| 1017 | + if res: |
| 1018 | + raise TransactionFailed(ERROR_PACKAGE_MANAGER_FAILED, |
| 1019 | + trans.output) |
| 1020 | + |
| 1021 | + def _mark_packages_for_removal(self, packages, resolver, purge=False): |
| 1022 | + """Mark packages for installation.""" |
| 1023 | + for pkg_name, pkg_ver, pkg_rel in [self._split_package_id(pkg) |
| 1024 | + for pkg in packages]: |
| 1025 | + try: |
| 1026 | + pkg = self._cache[pkg_name] |
| 1027 | + except KeyError: |
| 1028 | + raise TransactionFailed(ERROR_NO_PACKAGE, |
| 1029 | + _("Package %s isn't available"), |
| 1030 | + pkg_name) |
| 1031 | + if not pkg.is_installed and not pkg.installed_files: |
| 1032 | + raise TransactionFailed(ERROR_PACKAGE_NOT_INSTALLED, |
| 1033 | + _("Package %s isn't installed"), |
| 1034 | + pkg_name) |
| 1035 | + if pkg.essential == True: |
| 1036 | + raise TransactionFailed(ERROR_NOT_REMOVE_ESSENTIAL_PACKAGE, |
| 1037 | + _("Package %s cannot be removed."), |
| 1038 | + pkg_name) |
| 1039 | + if pkg_ver and pkg.installed != pkg_ver: |
| 1040 | + raise TransactionFailed(ERROR_PACKAGE_NOT_INSTALLED, |
| 1041 | + _("The version %s of %s is not " |
| 1042 | + "installed"), pkg_ver, pkg_name) |
| 1043 | + pkg.mark_delete(False, purge) |
| 1044 | + resolver.clear(pkg) |
| 1045 | + resolver.protect(pkg) |
| 1046 | + resolver.remove(pkg) |
| 1047 | + |
| 1048 | + def _check_obsoleted_dependencies(self, trans, resolver=None): |
| 1049 | + """Mark obsoleted dependencies of to be removed packages for removal.""" |
| 1050 | + if not trans.remove_obsoleted_depends: |
| 1051 | + return |
| 1052 | + if not resolver: |
| 1053 | + resolver = apt.cache.ProblemResolver(self._cache) |
| 1054 | + installed_deps = set() |
| 1055 | + with self._cache.actiongroup(): |
| 1056 | + for pkg in self._iterate_packages(): |
| 1057 | + if pkg.marked_delete: |
| 1058 | + installed_deps = self._installed_dependencies(pkg.name, |
| 1059 | + installed_deps) |
| 1060 | + for dep_name in installed_deps: |
| 1061 | + if dep_name in self._cache: |
| 1062 | + pkg = self._cache[dep_name] |
| 1063 | + if pkg.is_installed and pkg.is_auto_removable: |
| 1064 | + pkg.mark_delete(False) |
| 1065 | + # do an additional resolver run to ensure that the autoremove |
| 1066 | + # never leaves the cache in an inconsistent state, see bug |
| 1067 | + # LP: #659111 for the rational, essentially this may happen |
| 1068 | + # if a package is marked install during problem resolving but |
| 1069 | + # is later no longer required. the resolver deals with that |
| 1070 | + self._resolve_depends(trans, resolver) |
| 1071 | + |
| 1072 | + def _installed_dependencies(self, pkg_name, all_deps=None): |
| 1073 | + """Recursively return all installed dependencies of a given package.""" |
| 1074 | + #FIXME: Should be part of python-apt, since it makes use of non-public |
| 1075 | + # API. Perhaps by adding a recursive argument to |
| 1076 | + # apt.package.Version.get_dependencies() |
| 1077 | + if not all_deps: |
| 1078 | + all_deps = set() |
| 1079 | + if not pkg_name in self._cache: |
| 1080 | + return all_deps |
| 1081 | + cur = self._cache[pkg_name]._pkg.current_ver |
| 1082 | + if not cur: |
| 1083 | + return all_deps |
| 1084 | + for sec in ("PreDepends", "Depends", "Recommends"): |
| 1085 | + try: |
| 1086 | + for dep in cur.depends_list[sec]: |
| 1087 | + dep_name = dep[0].target_pkg.name |
| 1088 | + if not dep_name in all_deps: |
| 1089 | + all_deps.add(dep_name) |
| 1090 | + all_deps |= self._installed_dependencies(dep_name, |
| 1091 | + all_deps) |
| 1092 | + except KeyError: |
| 1093 | + pass |
| 1094 | + return all_deps |
| 1095 | + |
| 1096 | + def _mark_packages_for_downgrade(self, packages, resolver): |
| 1097 | + """Mark packages for downgrade.""" |
| 1098 | + for pkg_name, pkg_ver, pkg_rel in [self._split_package_id(pkg) |
| 1099 | + for pkg in packages]: |
| 1100 | + try: |
| 1101 | + pkg = self._cache[pkg_name] |
| 1102 | + except KeyError: |
| 1103 | + raise TransactionFailed(ERROR_NO_PACKAGE, |
| 1104 | + _("Package %s isn't available"), |
| 1105 | + pkg_name) |
| 1106 | + if not pkg.is_installed: |
| 1107 | + raise TransactionFailed(ERROR_PACKAGE_NOT_INSTALLED, |
| 1108 | + _("Package %s isn't installed"), |
| 1109 | + pkg_name) |
| 1110 | + pkg.mark_install(False, True, pkg.is_auto_installed) |
| 1111 | + resolver.clear(pkg) |
| 1112 | + resolver.protect(pkg) |
| 1113 | + if pkg_ver: |
| 1114 | + if pkg.installed and pkg.installed.version < pkg_ver: |
| 1115 | + #FIXME: We need a new error enum |
| 1116 | + raise TransactionFailed(ERROR_NO_PACKAGE, |
| 1117 | + _("The former version %s of %s " \ |
| 1118 | + "is already installed"), |
| 1119 | + pkg.installed.version, pkg.name) |
| 1120 | + elif pkg.installed and pkg.installed.version == pkg_ver: |
| 1121 | + raise TransactionFailed(ERROR_PACKAGE_ALREADY_INSTALLED, |
| 1122 | + _("The version %s of %s " |
| 1123 | + "is already installed"), |
| 1124 | + pkg.installed.version, pkg.name) |
| 1125 | + try: |
| 1126 | + pkg.candidate = pkg.versions[pkg_ver] |
| 1127 | + except KeyError: |
| 1128 | + raise TransactionFailed(ERROR_NO_PACKAGE, |
| 1129 | + _("The version %s of %s isn't " |
| 1130 | + "available"), pkg_ver, pkg_name) |
| 1131 | + else: |
| 1132 | + raise TransactionFailed(ERROR_NO_PACKAGE, |
| 1133 | + _("You need to specify a version to " \ |
| 1134 | + "downgrade %s to"), pkg_name) |
| 1135 | + |
| 1136 | + |
| 1137 | + def _mark_packages_for_upgrade(self, packages, resolver): |
| 1138 | + """Mark packages for upgrade.""" |
| 1139 | + for pkg_name, pkg_ver, pkg_rel in [self._split_package_id(pkg) |
| 1140 | + for pkg in packages]: |
| 1141 | + try: |
| 1142 | + pkg = self._cache[pkg_name] |
| 1143 | + except KeyError: |
| 1144 | + raise TransactionFailed(ERROR_NO_PACKAGE, |
| 1145 | + _("Package %s isn't available"), |
| 1146 | + pkg_name) |
| 1147 | + if not pkg.is_installed: |
| 1148 | + raise TransactionFailed(ERROR_PACKAGE_NOT_INSTALLED, |
| 1149 | + _("Package %s isn't installed"), |
| 1150 | + pkg_name) |
| 1151 | + pkg.mark_install(False, True, pkg.is_auto_installed) |
| 1152 | + resolver.clear(pkg) |
| 1153 | + resolver.protect(pkg) |
| 1154 | + if pkg_ver: |
| 1155 | + if (pkg.installed and |
| 1156 | + apt_pkg.version_compare(pkg.installed.version, |
| 1157 | + pkg_ver) == 1): |
| 1158 | + raise TransactionFailed(ERROR_PACKAGE_UPTODATE, |
| 1159 | + _("The later version %s of %s " |
| 1160 | + "is already installed"), |
| 1161 | + pkg.installed.version, pkg.name) |
| 1162 | + elif (pkg.installed and |
| 1163 | + apt_pkg.version_compare(pkg.installed.version, |
| 1164 | + pkg_ver) == 0): |
| 1165 | + raise TransactionFailed(ERROR_PACKAGE_UPTODATE, |
| 1166 | + _("The version %s of %s " |
| 1167 | + "is already installed"), |
| 1168 | + pkg.installed.version, pkg.name) |
| 1169 | + try: |
| 1170 | + pkg.candidate = pkg.versions[pkg_ver] |
| 1171 | + except KeyError: |
| 1172 | + raise TransactionFailed(ERROR_NO_PACKAGE, |
| 1173 | + _("The version %s of %s isn't " |
| 1174 | + "available."), pkg_ver, pkg_name) |
| 1175 | + |
| 1176 | + elif pkg_rel: |
| 1177 | + self._set_candidate_release(pkg, pkg_rel) |
| 1178 | + |
| 1179 | + @staticmethod |
| 1180 | + def _set_candidate_release(pkg, release): |
| 1181 | + """Set the candidate of a package to the one from the given release.""" |
| 1182 | + #FIXME: Should be moved to python-apt |
| 1183 | + # Check if the package is provided in the release |
| 1184 | + for version in pkg.versions: |
| 1185 | + if [origin for origin in version.origins |
| 1186 | + if origin.archive == release]: |
| 1187 | + break |
| 1188 | + else: |
| 1189 | + raise TransactionFailed(ERROR_NO_PACKAGE, |
| 1190 | + _("The package %s isn't available in " |
| 1191 | + "the %s release."), pkg.name, release) |
| 1192 | + pkg._pcache.cache_pre_change() |
| 1193 | + pkg._pcache._depcache.set_candidate_release(pkg._pkg, version._cand, |
| 1194 | + release) |
| 1195 | + pkg._pcache.cache_post_change() |
| 1196 | + |
| 1197 | + def update_cache(self, trans, sources_list): |
| 1198 | + """Update the cache. |
| 1199 | + |
| 1200 | + Keyword arguments: |
| 1201 | + trans -- the corresponding transaction |
| 1202 | + sources_list -- only update the repositories found in the sources.list |
| 1203 | + snippet by the given file name. |
| 1204 | + """ |
| 1205 | + log.info("Updating cache") |
| 1206 | + def compare_pathes(first, second): |
| 1207 | + """Small helper to compare two pathes.""" |
| 1208 | + return os.path.normpath(first) == os.path.normpath(second) |
| 1209 | + progress = DaemonAcquireRepoProgress(trans, begin=10, end=90) |
| 1210 | + if sources_list and not sources_list.startswith("/"): |
| 1211 | + dir = apt_pkg.config.find_dir("Dir::Etc::sourceparts") |
| 1212 | + sources_list = os.path.join(dir, sources_list) |
| 1213 | + if sources_list: |
| 1214 | + # For security reasons (LP #722228) we only allow files inside |
| 1215 | + # sources.list.d as basedir |
| 1216 | + basedir = apt_pkg.config.find_dir("Dir::Etc::sourceparts") |
| 1217 | + system_sources = apt_pkg.config.find_file("Dir::Etc::sourcelist") |
| 1218 | + if "/" in sources_list: |
| 1219 | + sources_list = os.path.abspath(sources_list) |
| 1220 | + # Check if the sources_list snippet is in the sourceparts |
| 1221 | + # directory |
| 1222 | + common_prefix = os.path.commonprefix([sources_list, basedir]) |
| 1223 | + if not (compare_pathes(common_prefix, basedir) or |
| 1224 | + compare_pathes(sources_list, system_sources)): |
| 1225 | + raise AptDaemonError("Only alternative sources.list files " |
| 1226 | + "inside '%s' are allowed (not '%s')" \ |
| 1227 | + % (basedir, sources_list)) |
| 1228 | + else: |
| 1229 | + sources_list = os.path.join(basedir, sources_list) |
| 1230 | + try: |
| 1231 | + self._cache.update(progress, sources_list=sources_list) |
| 1232 | + except apt.cache.FetchFailedException as error: |
| 1233 | + # ListUpdate() method of apt handles a cancelled operation |
| 1234 | + # as a failed one, see LP #162441 |
| 1235 | + if trans.cancelled: |
| 1236 | + raise TransactionCancelled() |
| 1237 | + else: |
| 1238 | + raise TransactionFailed(ERROR_REPO_DOWNLOAD_FAILED, |
| 1239 | + str(error)) |
| 1240 | + except apt.cache.FetchCancelledException: |
| 1241 | + raise TransactionCancelled() |
| 1242 | + except apt.cache.LockFailedException: |
| 1243 | + raise TransactionFailed(ERROR_NO_LOCK) |
| 1244 | + self._open_cache(trans, begin=91, end=95) |
| 1245 | + |
| 1246 | + def upgrade_system(self, trans, safe_mode=True, simulate=False): |
| 1247 | + """Upgrade the system. |
| 1248 | + |
| 1249 | + Keyword argument: |
| 1250 | + trans -- the corresponding transaction |
| 1251 | + safe_mode -- if additional software should be installed or removed to |
| 1252 | + satisfy the dependencies the an updates |
| 1253 | + simulate -- if the changes should not be applied |
| 1254 | + """ |
| 1255 | + log.info("Upgrade system with safe mode: %s" % safe_mode) |
| 1256 | + trans.status = STATUS_RESOLVING_DEP |
| 1257 | + #FIXME: What to do if already uptotdate? Add error code? |
| 1258 | + self._call_plugins("modify_cache_before") |
| 1259 | + try: |
| 1260 | + self._cache.upgrade(dist_upgrade=not safe_mode) |
| 1261 | + except SystemError as excep: |
| 1262 | + raise TransactionFailed(ERROR_DEP_RESOLUTION_FAILED, str(excep)) |
| 1263 | + self._call_plugins("modify_cache_after") |
| 1264 | + self._check_obsoleted_dependencies(trans) |
| 1265 | + if not simulate: |
| 1266 | + self._apply_changes(trans) |
| 1267 | + |
| 1268 | + def fix_incomplete_install(self, trans): |
| 1269 | + """Run dpkg --configure -a to recover from a failed installation. |
| 1270 | + |
| 1271 | + Keyword arguments: |
| 1272 | + trans -- the corresponding transaction |
| 1273 | + """ |
| 1274 | + log.info("Fixing incomplete installs") |
| 1275 | + trans.status = STATUS_CLEANING_UP |
| 1276 | + with self._frozen_status(): |
| 1277 | + with DaemonDpkgRecoverProgress(trans) as progress: |
| 1278 | + progress.run() |
| 1279 | + trans.output += progress.output |
| 1280 | + if progress._child_exit != 0: |
| 1281 | + raise TransactionFailed(ERROR_PACKAGE_MANAGER_FAILED, |
| 1282 | + trans.output) |
| 1283 | + |
| 1284 | + def reconfigure(self, trans, packages, priority): |
| 1285 | + """Run dpkg-reconfigure to reconfigure installed packages. |
| 1286 | + |
| 1287 | + Keyword arguments: |
| 1288 | + trans -- the corresponding transaction |
| 1289 | + packages -- list of packages to reconfigure |
| 1290 | + priority -- the lowest priority of question which should be asked |
| 1291 | + """ |
| 1292 | + log.info("Reconfiguring packages") |
| 1293 | + with self._frozen_status(): |
| 1294 | + with DaemonDpkgReconfigureProgress(trans) as progress: |
| 1295 | + progress.run(packages, priority) |
| 1296 | + trans.output += progress.output |
| 1297 | + if progress._child_exit != 0: |
| 1298 | + raise TransactionFailed(ERROR_PACKAGE_MANAGER_FAILED, |
| 1299 | + trans.output) |
| 1300 | + |
| 1301 | + def fix_broken_depends(self, trans, simulate=False): |
| 1302 | + """Try to fix broken dependencies. |
| 1303 | + |
| 1304 | + Keyword arguments: |
| 1305 | + trans -- the corresponding transaction |
| 1306 | + simualte -- if the changes should not be applied |
| 1307 | + """ |
| 1308 | + log.info("Fixing broken depends") |
| 1309 | + trans.status = STATUS_RESOLVING_DEP |
| 1310 | + try: |
| 1311 | + self._cache._depcache.fix_broken() |
| 1312 | + except SystemError: |
| 1313 | + raise TransactionFailed(ERROR_DEP_RESOLUTION_FAILED, |
| 1314 | + self._get_broken_details(trans)) |
| 1315 | + if not simulate: |
| 1316 | + self._apply_changes(trans) |
| 1317 | + |
| 1318 | + def _open_cache(self, trans, begin=1, end=5, quiet=False, status=None): |
| 1319 | + """Open the APT cache. |
| 1320 | + |
| 1321 | + Keyword arguments: |
| 1322 | + trans -- the corresponding transaction |
| 1323 | + start -- the begin of the progress range |
| 1324 | + end -- the end of the the progress range |
| 1325 | + quiet -- if True do no report any progress |
| 1326 | + status -- an alternative dpkg status file |
| 1327 | + """ |
| 1328 | + self.marked_tid = None |
| 1329 | + trans.status = STATUS_LOADING_CACHE |
| 1330 | + if not status: |
| 1331 | + status = self._status_orig |
| 1332 | + apt_pkg.config.set("Dir::State::status", status) |
| 1333 | + apt_pkg.init_system() |
| 1334 | + progress = DaemonOpenProgress(trans, begin=begin, end=end, |
| 1335 | + quiet=quiet) |
| 1336 | + try: |
| 1337 | + if not isinstance(self._cache, apt.cache.Cache): |
| 1338 | + self._cache = apt.cache.Cache(progress) |
| 1339 | + else: |
| 1340 | + self._cache.open(progress) |
| 1341 | + except SystemError as excep: |
| 1342 | + raise TransactionFailed(ERROR_NO_CACHE, str(excep)) |
| 1343 | + |
| 1344 | + def is_dpkg_journal_clean(self): |
| 1345 | + """Return False if there are traces of incomplete dpkg status |
| 1346 | + updates.""" |
| 1347 | + status_updates = os.path.join(os.path.dirname(self._status_orig), |
| 1348 | + "updates/") |
| 1349 | + for dentry in os.listdir(status_updates): |
| 1350 | + if dentry.isdigit(): |
| 1351 | + return False |
| 1352 | + return True |
| 1353 | + |
| 1354 | + def _apply_changes(self, trans, fetch_range=(15, 50), |
| 1355 | + install_range=(50, 90)): |
| 1356 | + """Apply previously marked changes to the system. |
| 1357 | + |
| 1358 | + Keyword arguments: |
| 1359 | + trans -- the corresponding transaction |
| 1360 | + fetch_range -- tuple containing the start and end point of the |
| 1361 | + download progress |
| 1362 | + install_range -- tuple containing the start and end point of the |
| 1363 | + install progress |
| 1364 | + """ |
| 1365 | + changes = self._cache.get_changes() |
| 1366 | + if not changes: |
| 1367 | + return |
| 1368 | + # Do not allow to remove essential packages |
| 1369 | + for pkg in changes: |
| 1370 | + if pkg.marked_delete and (pkg.essential == True or \ |
| 1371 | + (pkg.installed and \ |
| 1372 | + pkg.installed.priority == "required") or\ |
| 1373 | + pkg.name == "aptdaemon"): |
| 1374 | + raise TransactionFailed(ERROR_NOT_REMOVE_ESSENTIAL_PACKAGE, |
| 1375 | + _("Package %s cannot be removed"), |
| 1376 | + pkg.name) |
| 1377 | + # Check if any of the cache changes get installed from an |
| 1378 | + # unauthenticated repository"" |
| 1379 | + if not trans.allow_unauthenticated and trans.unauthenticated: |
| 1380 | + raise TransactionFailed(ERROR_PACKAGE_UNAUTHENTICATED, |
| 1381 | + " ".join(sorted(trans.unauthenticated))) |
| 1382 | + if trans.cancelled: |
| 1383 | + raise TransactionCancelled() |
| 1384 | + trans.cancellable = False |
| 1385 | + fetch_progress = DaemonAcquireProgress(trans, begin=fetch_range[0], |
| 1386 | + end=fetch_range[1]) |
| 1387 | + inst_progress = DaemonInstallProgress(trans, begin=install_range[0], |
| 1388 | + end=install_range[1]) |
| 1389 | + with self._frozen_status(): |
| 1390 | + try: |
| 1391 | + self._cache.commit(fetch_progress, inst_progress) |
| 1392 | + except apt.cache.FetchFailedException as error: |
| 1393 | + raise TransactionFailed(ERROR_PACKAGE_DOWNLOAD_FAILED, |
| 1394 | + str(error)) |
| 1395 | + except apt.cache.FetchCancelledException: |
| 1396 | + raise TransactionCancelled() |
| 1397 | + except SystemError as excep: |
| 1398 | + # Run dpkg --configure -a to recover from a failed transaction |
| 1399 | + trans.status = STATUS_CLEANING_UP |
| 1400 | + with DaemonDpkgRecoverProgress(trans, begin=90, end=95) as pro: |
| 1401 | + pro.run() |
| 1402 | + output = inst_progress.output + pro.output |
| 1403 | + trans.output += output |
| 1404 | + raise TransactionFailed(ERROR_PACKAGE_MANAGER_FAILED, |
| 1405 | + "%s: %s" % (excep, trans.output)) |
| 1406 | + else: |
| 1407 | + enc = sys.getfilesystemencoding() |
| 1408 | + trans.output += inst_progress.output |
| 1409 | + |
| 1410 | + @contextlib.contextmanager |
| 1411 | + def _frozen_status(self): |
| 1412 | + """Freeze the status file to allow simulate operations during |
| 1413 | + a dpkg call.""" |
| 1414 | + frozen_dir = tempfile.mkdtemp(prefix="aptdaemon-frozen-status") |
| 1415 | + shutil.copy(self._status_orig, frozen_dir) |
| 1416 | + self._status_frozen = os.path.join(frozen_dir, "status") |
| 1417 | + try: |
| 1418 | + yield |
| 1419 | + finally: |
| 1420 | + shutil.rmtree(frozen_dir) |
| 1421 | + self._status_frozen = None |
| 1422 | + |
| 1423 | + def query(self, trans): |
| 1424 | + """Process a PackageKit query transaction.""" |
| 1425 | + raise NotImplementedError |
| 1426 | + |
| 1427 | + def simulate(self, trans): |
| 1428 | + """Return the dependencies which will be installed by the transaction, |
| 1429 | + the content of the dpkg status file after the transaction would have |
| 1430 | + been applied, the download size and the required disk space. |
| 1431 | + |
| 1432 | + Keyword arguments: |
| 1433 | + trans -- the transaction which should be simulated |
| 1434 | + """ |
| 1435 | + log.info("Simulating trans: %s" % trans.tid) |
| 1436 | + trans.status = STATUS_RESOLVING_DEP |
| 1437 | + GObject.idle_add(self._simulate, trans) |
| 1438 | + |
| 1439 | + def _simulate(self, trans): |
| 1440 | + try: |
| 1441 | + trans.depends, trans.download, trans.space, \ |
| 1442 | + trans.unauthenticated = self.__simulate(trans) |
| 1443 | + except TransactionFailed as excep: |
| 1444 | + trans.error = excep |
| 1445 | + trans.exit = EXIT_FAILED |
| 1446 | + except Exception as excep: |
| 1447 | + tbk = traceback.format_exc() |
| 1448 | + trans.error = TransactionFailed(ERROR_UNKNOWN, tbk) |
| 1449 | + try: |
| 1450 | + from . import crash |
| 1451 | + except ImportError: |
| 1452 | + pass |
| 1453 | + else: |
| 1454 | + crash.create_report("%s: %s" % (type(excep), str(excep)), |
| 1455 | + tbk, trans) |
| 1456 | + trans.exit = EXIT_FAILED |
| 1457 | + else: |
| 1458 | + trans.status = STATUS_SETTING_UP |
| 1459 | + trans.simulated = time.time() |
| 1460 | + self.marked_tid = trans.tid |
| 1461 | + finally: |
| 1462 | + self._emit_transaction_simulated(trans) |
| 1463 | + self.last_action_timestamp = time.time() |
| 1464 | + return False |
| 1465 | + |
| 1466 | + def __simulate(self, trans): |
| 1467 | + depends = [[], [], [], [], [], [], []] |
| 1468 | + unauthenticated = [] |
| 1469 | + skip_pkgs = [] |
| 1470 | + size = 0 |
| 1471 | + installs = reinstalls = removals = purges = upgrades = upgradables = \ |
| 1472 | + downgrades = [] |
| 1473 | + |
| 1474 | + # Only handle transaction which change packages |
| 1475 | + #FIXME: Add support for ROLE_FIX_INCOMPLETE_INSTALL |
| 1476 | + if trans.role not in [ROLE_INSTALL_PACKAGES, ROLE_UPGRADE_PACKAGES, |
| 1477 | + ROLE_UPGRADE_SYSTEM, ROLE_REMOVE_PACKAGES, |
| 1478 | + ROLE_COMMIT_PACKAGES, ROLE_INSTALL_FILE, |
| 1479 | + ROLE_FIX_BROKEN_DEPENDS]: |
| 1480 | + return depends, 0, 0, [] |
| 1481 | + |
| 1482 | + # If a transaction is currently running use the former status file |
| 1483 | + if self._status_frozen: |
| 1484 | + status_path = self._status_frozen |
| 1485 | + else: |
| 1486 | + status_path = self._status_orig |
| 1487 | + self._open_cache(trans, quiet=True, status=status_path) |
| 1488 | + if trans.role == ROLE_FIX_BROKEN_DEPENDS: |
| 1489 | + self.fix_broken_depends(trans, simulate=True) |
| 1490 | + elif self._cache.broken_count: |
| 1491 | + raise TransactionFailed(ERROR_CACHE_BROKEN, |
| 1492 | + self._get_broken_details(trans)) |
| 1493 | + elif trans.role == ROLE_UPGRADE_SYSTEM: |
| 1494 | + for pkg in self._iterate_packages(): |
| 1495 | + if pkg.is_upgradable: |
| 1496 | + upgradables.append(pkg) |
| 1497 | + self.upgrade_system(trans, simulate=True, **trans.kwargs) |
| 1498 | + elif trans.role == ROLE_INSTALL_FILE: |
| 1499 | + deb = self.install_file(trans, simulate=True, **trans.kwargs) |
| 1500 | + skip_pkgs.append(deb.pkgname) |
| 1501 | + try: |
| 1502 | + # Sometimes a thousands comma is used in packages |
| 1503 | + # See LP #656633 |
| 1504 | + size = int(deb["Installed-Size"].replace(",", "")) * 1024 |
| 1505 | + # Some packages ship really large install sizes e.g. |
| 1506 | + # openvpn access server, see LP #758837 |
| 1507 | + if size > sys.maxsize: |
| 1508 | + raise OverflowError("Size is too large: %s Bytes" % size) |
| 1509 | + except (KeyError, AttributeError, ValueError, OverflowError): |
| 1510 | + if not trans.kwargs["force"]: |
| 1511 | + msg = trans.gettext("The package doesn't provide a " |
| 1512 | + "valid Installed-Size control " |
| 1513 | + "field. See Debian Policy 5.6.20.") |
| 1514 | + raise TransactionFailed(ERROR_INVALID_PACKAGE_FILE, msg) |
| 1515 | + try: |
| 1516 | + pkg = self._cache[deb.pkgname] |
| 1517 | + except KeyError: |
| 1518 | + trans.packages = [[deb.pkgname], [], [], [], [], []] |
| 1519 | + else: |
| 1520 | + if pkg.is_installed: |
| 1521 | + # if we failed to get the size from the deb file do nor |
| 1522 | + # try to get the delta |
| 1523 | + if size != 0: |
| 1524 | + size -= pkg.installed.installed_size |
| 1525 | + trans.packages = [[], [deb.pkgname], [], [], [], []] |
| 1526 | + else: |
| 1527 | + trans.packages = [[deb.pkgname], [], [], [], [], []] |
| 1528 | + else: |
| 1529 | + #FIXME: ugly code to get the names of the packages |
| 1530 | + (installs, reinstalls, removals, purges, |
| 1531 | + upgrades, downgrades) = [[re.split("(=|/)", entry, 1)[0] \ |
| 1532 | + for entry in lst] \ |
| 1533 | + for lst in trans.packages] |
| 1534 | + self.commit_packages(trans, *trans.packages, simulate=True) |
| 1535 | + |
| 1536 | + changes = self._cache.get_changes() |
| 1537 | + changes_names = [] |
| 1538 | + # get the additional dependencies |
| 1539 | + for pkg in changes: |
| 1540 | + self._iterate_mainloop() |
| 1541 | + pkg_str = "%s=%s" % (pkg.name, pkg.candidate.version) |
| 1542 | + if pkg.marked_upgrade and pkg.is_installed and \ |
| 1543 | + not pkg.name in upgrades: |
| 1544 | + depends[PKGS_UPGRADE].append(pkg_str) |
| 1545 | + elif pkg.marked_reinstall and not pkg.name in reinstalls: |
| 1546 | + depends[PKGS_REINSTALL].append(pkg_str) |
| 1547 | + elif pkg.marked_downgrade and not pkg.name in downgrades: |
| 1548 | + depends[PKGS_DOWNGRADE].append(pkg_str) |
| 1549 | + elif pkg.marked_install and not pkg.name in installs: |
| 1550 | + depends[PKGS_INSTALL].append(pkg_str) |
| 1551 | + elif pkg.marked_delete and not pkg.name in removals: |
| 1552 | + pkg_str = "%s=%s" % (pkg.name, pkg.installed.version) |
| 1553 | + depends[PKGS_REMOVE].append(pkg_str) |
| 1554 | + #FIXME: add support for purges |
| 1555 | + changes_names.append(pkg.name) |
| 1556 | + # get the unauthenticated packages |
| 1557 | + unauthenticated = self._get_unauthenticated() |
| 1558 | + # Check for skipped upgrades |
| 1559 | + for pkg in upgradables: |
| 1560 | + if pkg.marked_keep: |
| 1561 | + pkg_str = "%s=%s" % (pkg.name, pkg.candidate.version) |
| 1562 | + depends[PKGS_KEEP].append(pkg_str) |
| 1563 | + |
| 1564 | + # apt.cache.Cache.required_download requires a clean cache. Under some |
| 1565 | + # strange circumstances it can fail (most likely an interrupted |
| 1566 | + # debconf question), see LP#659438 |
| 1567 | + # Running dpkg --configure -a fixes the situation |
| 1568 | + try: |
| 1569 | + required_download = self._cache.required_download |
| 1570 | + except SystemError as error: |
| 1571 | + raise TransactionFailed(ERROR_INCOMPLETE_INSTALL, str(error)) |
| 1572 | + |
| 1573 | + required_space = size + self._cache.required_space |
| 1574 | + |
| 1575 | + return depends, required_download, required_space, unauthenticated |
| 1576 | + |
| 1577 | + def _check_deb_file(self, path, force, uid): |
| 1578 | + """Perform some basic checks for the Debian package. |
| 1579 | + |
| 1580 | + :param trans: The transaction instance. |
| 1581 | + |
| 1582 | + :returns: An apt.debfile.Debfile instance. |
| 1583 | + """ |
| 1584 | + #FIXME: Unblock lintian call |
| 1585 | + if not os.path.isfile(path): |
| 1586 | + raise TransactionFailed(ERROR_UNREADABLE_PACKAGE_FILE, path) |
| 1587 | + if not force and os.path.isfile("/usr/bin/lintian"): |
| 1588 | + tags_dir = os.path.join(apt_pkg.config.find_dir("Dir"), |
| 1589 | + "usr", "share", "aptdaemon") |
| 1590 | + try: |
| 1591 | + distro = platform.dist()[0] |
| 1592 | + except KeyError: |
| 1593 | + distro = None |
| 1594 | + else: |
| 1595 | + tags_file = os.path.join(tags_dir, |
| 1596 | + "lintian-nonfatal.tags.%s" % distro) |
| 1597 | + tags_fatal_file = os.path.join(tags_dir, |
| 1598 | + "lintian-fatal.tags.%s" % distro) |
| 1599 | + if not distro or not os.path.exists(tags_file): |
| 1600 | + log.debug("Using default lintian tags file") |
| 1601 | + tags_file = os.path.join(tags_dir, "lintian-nonfatal.tags") |
| 1602 | + if not distro or not os.path.exists(tags_fatal_file): |
| 1603 | + log.debug("Using default lintian fatal tags file") |
| 1604 | + tags_fatal_file = os.path.join(tags_dir, "lintian-fatal.tags") |
| 1605 | + # Run linitan as the user who initiated the transaction |
| 1606 | + # Once with non fatal checks and a second time with the fatal |
| 1607 | + # checks which are not allowed to be overriden |
| 1608 | + nonfatal_args = ["/usr/bin/lintian", "--tags-from-file", |
| 1609 | + tags_file, path] |
| 1610 | + fatal_args = ["/usr/bin/lintian", "--tags-from-file", |
| 1611 | + tags_fatal_file, "--no-override", path] |
| 1612 | + for lintian_args in (nonfatal_args, fatal_args): |
| 1613 | + proc = subprocess.Popen(lintian_args, |
| 1614 | + stderr=subprocess.STDOUT, |
| 1615 | + stdout=subprocess.PIPE, close_fds=True, |
| 1616 | + preexec_fn=lambda: os.setuid(uid)) |
| 1617 | + while proc.poll() is None: |
| 1618 | + self._iterate_mainloop() |
| 1619 | + time.sleep(0.05) |
| 1620 | + #FIXME: Add an error to catch return state 2 (failure) |
| 1621 | + if proc.returncode == 1: |
| 1622 | + stdout = proc.stdout.read() |
| 1623 | + stdout.decode(sys.stdin.encoding or "UTF-8", |
| 1624 | + errors="replace") |
| 1625 | + raise TransactionFailed(ERROR_INVALID_PACKAGE_FILE, |
| 1626 | + "Lintian check results for %s:" |
| 1627 | + "\n%s" % (path, stdout)) |
| 1628 | + try: |
| 1629 | + deb = apt.debfile.DebPackage(path, self._cache) |
| 1630 | + except IOError: |
| 1631 | + raise TransactionFailed(ERROR_UNREADABLE_PACKAGE_FILE, path) |
| 1632 | + except Exception as error: |
| 1633 | + raise TransactionFailed(ERROR_INVALID_PACKAGE_FILE, str(error)) |
| 1634 | + try: |
| 1635 | + ret = deb.check() |
| 1636 | + except Exception as error: |
| 1637 | + raise TransactionFailed(ERROR_DEP_RESOLUTION_FAILED, str(error)) |
| 1638 | + if not ret: |
| 1639 | + raise TransactionFailed(ERROR_DEP_RESOLUTION_FAILED, |
| 1640 | + deb._failure_string) |
| 1641 | + return deb |
| 1642 | + |
| 1643 | + def clean(self, trans): |
| 1644 | + """Clean the download directories. |
| 1645 | + |
| 1646 | + Keyword arguments: |
| 1647 | + trans -- the corresponding transaction |
| 1648 | + """ |
| 1649 | + #FIXME: Use pkgAcquire.Clean(). Currently not part of python-apt. |
| 1650 | + trans.status = STATUS_CLEANING_UP |
| 1651 | + archive_path = apt_pkg.config.find_dir("Dir::Cache::archives") |
| 1652 | + for dir in [archive_path, os.path.join(archive_path, "partial")]: |
| 1653 | + for filename in os.listdir(dir): |
| 1654 | + if filename == "lock": |
| 1655 | + continue |
| 1656 | + path = os.path.join(dir, filename) |
| 1657 | + if os.path.isfile(path): |
| 1658 | + log.debug("Removing file %s", path) |
| 1659 | + os.remove(path) |
| 1660 | + |
| 1661 | + def add_license_key(self, trans, pkg_name, json_token, server_name): |
| 1662 | + """Add a license key data to the given package. |
| 1663 | + |
| 1664 | + Keyword arguemnts: |
| 1665 | + trans -- the coresponding transaction |
| 1666 | + pkg_name -- the name of the corresponding package |
| 1667 | + json_token -- the oauth token as json |
| 1668 | + server_name -- the server to use (ubuntu-production, ubuntu-staging) |
| 1669 | + """ |
| 1670 | + # set transaction state to downloading |
| 1671 | + trans.status = STATUS_DOWNLOADING |
| 1672 | + try: |
| 1673 | + license_key, license_key_path = \ |
| 1674 | + self.plugins["get_license_key"][0](trans.uid, pkg_name, |
| 1675 | + json_token, server_name) |
| 1676 | + except Exception as error: |
| 1677 | + logging.exception("get_license_key plugin failed") |
| 1678 | + raise TransactionFailed(ERROR_LICENSE_KEY_DOWNLOAD_FAILED, |
| 1679 | + str(error)) |
| 1680 | + # ensure stuff is good |
| 1681 | + if not license_key_path or not license_key: |
| 1682 | + raise TransactionFailed(ERROR_LICENSE_KEY_DOWNLOAD_FAILED, |
| 1683 | + _("The license key is empty")) |
| 1684 | + |
| 1685 | + # add license key if we have one |
| 1686 | + self._add_license_key_to_system(pkg_name, license_key, license_key_path) |
| 1687 | + |
| 1688 | + def _add_license_key_to_system(self, pkg_name, license_key, license_key_path): |
| 1689 | + # fixup path |
| 1690 | + license_key_path = os.path.join(apt_pkg.config.find_dir("Dir"), |
| 1691 | + license_key_path.lstrip("/")) |
| 1692 | + |
| 1693 | + # Check content of the key |
| 1694 | + if (license_key.strip().startswith("#!") or |
| 1695 | + license_key.startswith("\x7fELF")): |
| 1696 | + raise TransactionFailed(ERROR_LICENSE_KEY_INSTALL_FAILED, |
| 1697 | + _("The license key is not allowed to " |
| 1698 | + "contain executable code.")) |
| 1699 | + # Check the path of the license |
| 1700 | + license_key_path = os.path.normpath(license_key_path) |
| 1701 | + license_key_path_rootdir = os.path.join(apt_pkg.config["Dir"], |
| 1702 | + self.LICENSE_KEY_ROOTDIR.lstrip("/"), |
| 1703 | + pkg_name) |
| 1704 | + if not license_key_path.startswith(license_key_path_rootdir): |
| 1705 | + raise TransactionFailed(ERROR_LICENSE_KEY_INSTALL_FAILED, |
| 1706 | + _("The license key path %s is invalid"), |
| 1707 | + license_key_path) |
| 1708 | + if os.path.lexists(license_key_path): |
| 1709 | + raise TransactionFailed(ERROR_LICENSE_KEY_INSTALL_FAILED, |
| 1710 | + _("The license key already exists: %s"), |
| 1711 | + license_key_path) |
| 1712 | + # Symlink attacks! |
| 1713 | + if os.path.realpath(license_key_path) != license_key_path: |
| 1714 | + raise TransactionFailed(ERROR_LICENSE_KEY_INSTALL_FAILED, |
| 1715 | + _("The location of the license key is " |
| 1716 | + "unsecure since it contains symbolic " |
| 1717 | + "links. The path %s maps to %s"), |
| 1718 | + license_key_path, |
| 1719 | + os.path.realpath(license_key_path)) |
| 1720 | + # Check if the directory already exists |
| 1721 | + if not os.path.isdir(os.path.dirname(license_key_path)): |
| 1722 | + raise TransactionFailed(ERROR_LICENSE_KEY_INSTALL_FAILED, |
| 1723 | + _("The directory where to install the key " |
| 1724 | + "to doesn't exist yet: %s"), |
| 1725 | + license_key_path) |
| 1726 | + # write it |
| 1727 | + log.info("Writing license key to '%s'" % license_key_path) |
| 1728 | + old_umask = os.umask(18) |
| 1729 | + try: |
| 1730 | + with open(license_key_path, "w") as license_file: |
| 1731 | + license_file.write(license_key) |
| 1732 | + except IOError: |
| 1733 | + raise TransactionFailed(ERROR_LICENSE_KEY_INSTALL_FAILED, |
| 1734 | + _("Failed to write key file to: %s"), |
| 1735 | + license_key_path) |
| 1736 | + finally: |
| 1737 | + os.umask(old_umask) |
| 1738 | + |
| 1739 | + def _iterate_mainloop(self): |
| 1740 | + """Process pending actions on the main loop.""" |
| 1741 | + while GObject.main_context_default().pending(): |
| 1742 | + GObject.main_context_default().iteration() |
| 1743 | + |
| 1744 | + def _iterate_packages(self, interval=1000): |
| 1745 | + """Itarte von the packages of the cache and iterate on the |
| 1746 | + GObject main loop time for more responsiveness. |
| 1747 | + |
| 1748 | + Keyword arguments: |
| 1749 | + interval - the number of packages after which we iterate on the |
| 1750 | + mainloop |
| 1751 | + """ |
| 1752 | + for enum, pkg in enumerate(self._cache): |
| 1753 | + if not enum % interval: |
| 1754 | + self._iterate_mainloop() |
| 1755 | + yield pkg |
| 1756 | + |
| 1757 | + def _get_broken_details(self, trans, now=True): |
| 1758 | + """Return a message which provides debugging information about |
| 1759 | + broken packages. |
| 1760 | + |
| 1761 | + This method is basically a Python implementation of apt-get.cc's |
| 1762 | + ShowBroken. |
| 1763 | + |
| 1764 | + Keyword arguments: |
| 1765 | + trans -- the corresponding transaction |
| 1766 | + now -- if we check currently broken dependecies or the installation |
| 1767 | + candidate |
| 1768 | + """ |
| 1769 | + msg = trans.gettext("The following packages have unmet dependencies:") |
| 1770 | + msg += "\n\n" |
| 1771 | + for pkg in self._cache: |
| 1772 | + if not ((now and pkg.is_now_broken) or |
| 1773 | + (not now and pkg.is_inst_broken)): |
| 1774 | + continue |
| 1775 | + msg += "%s: " % pkg.name |
| 1776 | + if now: |
| 1777 | + version = pkg.installed |
| 1778 | + else: |
| 1779 | + version = pkg.candidate |
| 1780 | + indent = " " * (len(pkg.name) + 2) |
| 1781 | + dep_msg = "" |
| 1782 | + for dep in version.dependencies: |
| 1783 | + or_msg = "" |
| 1784 | + for base_dep in dep.or_dependencies: |
| 1785 | + if or_msg: |
| 1786 | + or_msg += "or\n" |
| 1787 | + or_msg += indent |
| 1788 | + # Check if it's an important dependency |
| 1789 | + # See apt-pkg/depcache.cc IsImportantDep |
| 1790 | + # See apt-pkg/pkgcache.cc IsCritical() |
| 1791 | + # FIXME: Add APT::Install-Recommends-Sections |
| 1792 | + if not (base_dep.rawtype in ["Depends", "PreDepends", |
| 1793 | + "Obsoletes", "DpkgBreaks", |
| 1794 | + "Conflicts"] or |
| 1795 | + (apt_pkg.config.find_b("APT::Install-Recommends", |
| 1796 | + False) and |
| 1797 | + base_dep.rawtype == "Recommends") or |
| 1798 | + (apt_pkg.config.find_b("APT::Install-Suggests", |
| 1799 | + False) and |
| 1800 | + base_dep.rawtype == "Suggests")): |
| 1801 | + continue |
| 1802 | + # Get the version of the target package |
| 1803 | + try: |
| 1804 | + pkg_dep = self._cache[base_dep.name] |
| 1805 | + except KeyError: |
| 1806 | + dep_version = None |
| 1807 | + else: |
| 1808 | + if now: |
| 1809 | + dep_version = pkg_dep.installed |
| 1810 | + else: |
| 1811 | + dep_version = pkg_dep.candidate |
| 1812 | + # We only want to display dependencies which cannot |
| 1813 | + # be satisfied |
| 1814 | + if dep_version and not apt_pkg.check_dep(base_dep.version, |
| 1815 | + base_dep.relation, |
| 1816 | + version.version): |
| 1817 | + break |
| 1818 | + or_msg = "%s: %s " % (base_dep.rawtype, base_dep.name) |
| 1819 | + if base_dep.version: |
| 1820 | + or_msg += "(%s %s) " % (base_dep.relation, |
| 1821 | + base_dep.version) |
| 1822 | + if self._cache.is_virtual_package(base_dep.name): |
| 1823 | + or_msg += trans.gettext("but it is a virtual package") |
| 1824 | + elif not dep_version: |
| 1825 | + if now: |
| 1826 | + or_msg += trans.gettext("but it is not installed") |
| 1827 | + else: |
| 1828 | + or_msg += trans.gettext("but it is not going to " |
| 1829 | + "be installed") |
| 1830 | + elif now: |
| 1831 | + #TRANSLATORS: %s is a version number |
| 1832 | + or_msg += trans.gettext("but %s is installed") % \ |
| 1833 | + dep_version.version |
| 1834 | + else: |
| 1835 | + #TRANSLATORS: %s is a version number |
| 1836 | + or_msg += trans.gettext("but %s is to be installed") % \ |
| 1837 | + dep_version.version |
| 1838 | + else: |
| 1839 | + # Only append an or-group if at least one of the |
| 1840 | + # dependencies cannot be satisfied |
| 1841 | + if dep_msg: |
| 1842 | + dep_msg += indent |
| 1843 | + dep_msg += or_msg |
| 1844 | + dep_msg += "\n" |
| 1845 | + msg += dep_msg |
| 1846 | + return msg |
| 1847 | + |
| 1848 | + def is_reboot_required(self): |
| 1849 | + """If a reboot is required to get all changes into effect.""" |
| 1850 | + return os.path.exists(os.path.join(apt_pkg.config.find_dir("Dir"), |
| 1851 | + "var/run/reboot-required")) |
| 1852 | + |
| 1853 | + |
| 1854 | +class DummyWorker(AptWorker): |
| 1855 | + |
| 1856 | + """Allows to test the daemon without making any changes to the system.""" |
| 1857 | + |
| 1858 | + def run(self, transaction): |
| 1859 | + """Process the given transaction in the background. |
| 1860 | + |
| 1861 | + Keyword argument: |
| 1862 | + transaction -- core.Transcation instance to run |
| 1863 | + """ |
| 1864 | + log.info("Processing transaction %s", transaction.tid) |
| 1865 | + if self.trans: |
| 1866 | + raise Exception("There is already a running transaction") |
| 1867 | + self.trans = transaction |
| 1868 | + self.last_action_timestamp = time.time() |
| 1869 | + self.trans.status = STATUS_RUNNING |
| 1870 | + self.trans.progress = 0 |
| 1871 | + self.trans.cancellable = True |
| 1872 | + GObject.timeout_add(200, self._process_transaction, transaction) |
| 1873 | + |
| 1874 | + def _process_transaction(self, trans): |
| 1875 | + """Run the worker""" |
| 1876 | + if trans.cancelled: |
| 1877 | + trans.exit = EXIT_CANCELLED |
| 1878 | + elif trans.progress == 100: |
| 1879 | + trans.exit = EXIT_SUCCESS |
| 1880 | + elif trans.role == ROLE_UPDATE_CACHE: |
| 1881 | + trans.exit = EXIT_FAILED |
| 1882 | + elif trans.role == ROLE_UPGRADE_PACKAGES: |
| 1883 | + trans.exit = EXIT_SUCCESS |
| 1884 | + elif trans.role == ROLE_UPGRADE_SYSTEM: |
| 1885 | + trans.exit = EXIT_CANCELLED |
| 1886 | + else: |
| 1887 | + if trans.role == ROLE_INSTALL_PACKAGES: |
| 1888 | + if trans.progress == 1: |
| 1889 | + trans.status = STATUS_RESOLVING_DEP |
| 1890 | + elif trans.progress == 5: |
| 1891 | + trans.status = STATUS_DOWNLOADING |
| 1892 | + elif trans.progress == 50: |
| 1893 | + trans.status = STATUS_COMMITTING |
| 1894 | + trans.status_details = "Heyas!" |
| 1895 | + elif trans.progress == 55: |
| 1896 | + trans.paused = True |
| 1897 | + trans.status = STATUS_WAITING_CONFIG_FILE_PROMPT |
| 1898 | + trans.config_file_conflict = "/etc/fstab", "/etc/mtab" |
| 1899 | + while trans.paused: |
| 1900 | + GObject.main_context_default().iteration() |
| 1901 | + trans.config_file_conflict_resolution = None |
| 1902 | + trans.config_file_conflict = None |
| 1903 | + trans.status = STATUS_COMMITTING |
| 1904 | + elif trans.progress == 60: |
| 1905 | + trans.required_medium = ("Debian Lenny 5.0 CD 1", |
| 1906 | + "USB CD-ROM") |
| 1907 | + trans.paused = True |
| 1908 | + trans.status = STATUS_WAITING_MEDIUM |
| 1909 | + while trans.paused: |
| 1910 | + GObject.main_context_default().iteration() |
| 1911 | + trans.status = STATUS_DOWNLOADING |
| 1912 | + elif trans.progress == 70: |
| 1913 | + trans.status_details = "Servus!" |
| 1914 | + elif trans.progress == 90: |
| 1915 | + trans.status_deatils = "" |
| 1916 | + trans.status = STATUS_CLEANING_UP |
| 1917 | + elif trans.role == ROLE_REMOVE_PACKAGES: |
| 1918 | + if trans.progress == 1: |
| 1919 | + trans.status = STATUS_RESOLVING_DEP |
| 1920 | + elif trans.progress == 5: |
| 1921 | + trans.status = STATUS_COMMITTING |
| 1922 | + trans.status_details = "Heyas!" |
| 1923 | + elif trans.progress == 50: |
| 1924 | + trans.status_details = "Hola!" |
| 1925 | + elif trans.progress == 70: |
| 1926 | + trans.status_details = "Servus!" |
| 1927 | + elif trans.progress == 90: |
| 1928 | + trans.status_deatils = "" |
| 1929 | + trans.status = STATUS_CLEANING_UP |
| 1930 | + trans.progress += 1 |
| 1931 | + return True |
| 1932 | + trans.status = STATUS_FINISHED |
| 1933 | + self.last_action_timestamp = time.time() |
| 1934 | + tid = self.trans.tid[:] |
| 1935 | + trans = self.trans |
| 1936 | + self.trans = None |
| 1937 | + self._emit_transaction_done(trans) |
| 1938 | + log.info("Finished transaction %s", tid) |
| 1939 | + return False |
| 1940 | + |
| 1941 | + def simulate(self, trans): |
| 1942 | + depends = [[], [], [], [], [], [], []] |
| 1943 | + return depends, 0, 0, [] |
| 1944 | + |
| 1945 | + |
| 1946 | +# vim:ts=4:sw=4:et |
| 1947 | |
| 1948 | === modified file 'NEWS' |
| 1949 | --- NEWS 2011-12-15 10:15:46 +0000 |
| 1950 | +++ NEWS 2012-06-13 16:29:18 +0000 |
| 1951 | @@ -1,4 +1,20 @@ |
| 1952 | -CHANGES (0.4x): |
| 1953 | +CHANGES (0.5x): |
| 1954 | + |
| 1955 | + * Enhancements: |
| 1956 | + |
| 1957 | + - Python3 support |
| 1958 | + |
| 1959 | + - Make use of apt.auth instead of softwareproperties.AptAuth |
| 1960 | + |
| 1961 | + - Support more PackageKit transactions (InstallSignature, RepoEnable) |
| 1962 | + |
| 1963 | + * API changes: |
| 1964 | + |
| 1965 | + - aptdaemon.test.TestCase has now a start_keyserver() method to fake |
| 1966 | + a GnuPG key server |
| 1967 | + |
| 1968 | + |
| 1969 | +CHANGES (0.45): |
| 1970 | |
| 1971 | * Enhancements: |
| 1972 | |
| 1973 | @@ -9,6 +25,8 @@ |
| 1974 | - Freeze (copy) the dpkg status file during a dpkg call to allow |
| 1975 | simulating other transactions with the frozen dpkg status |
| 1976 | |
| 1977 | + - Share WhatProvides plugins with the Python APT PackageKit backend |
| 1978 | + |
| 1979 | - Allow to install global license keys, see below |
| 1980 | |
| 1981 | - Add compatibilty for py-gobject 3.0 to the client module by switching |
| 1982 | @@ -35,6 +53,10 @@ |
| 1983 | |
| 1984 | * API changes: |
| 1985 | |
| 1986 | + - what-provides plugin: Share this plugin with the Python APT backend |
| 1987 | + of PackageKit to allow other packages to specify providers for |
| 1988 | + mod aliases, GStreamer codecs or language support |
| 1989 | + |
| 1990 | - get-license-key plugin: Add this new plugin which gets the uid, |
| 1991 | the package name, a json oauth token identifieng the customer |
| 1992 | and a server name to retrieve a license key and the path to store it to |
| 1993 | @@ -57,7 +79,9 @@ |
| 1994 | - org.freedesktop.PackageKit.transaction D-Bus interface: Initial |
| 1995 | implementaion |
| 1996 | |
| 1997 | - - aptdaemon.client: New AptClient.add_license_key method |
| 1998 | + - aptdaemon.client: |
| 1999 | + o New AptClient.add_license_key method |
| 2000 | + o Rename Transaction.disconnect() to Transaction._disconnect_from_dbus() |
| 2001 | |
| 2002 | - aptdaemon.enums: |
| 2003 | o Add enums for package states (e.g. PKG_INSTALLING or |
| 2004 | @@ -106,6 +130,11 @@ |
| 2005 | - Use apt_pkg.version_compare to detect already upt-to-date packages |
| 2006 | instead of simple string comparison |
| 2007 | - Fix --downgrade option of aptdcon |
| 2008 | + - Fix not supported errors in pkcompat |
| 2009 | + - Fix cancelling transactions |
| 2010 | + - Sync all properties of a transaction in the client before emitting |
| 2011 | + the finished signal (LP#747172) |
| 2012 | + - Fixes to piping the terminal (LP #733090) |
| 2013 | |
| 2014 | |
| 2015 | CHANGES (0.43) |
| 2016 | |
| 2017 | === modified file 'README.PackageKit' |
| 2018 | --- README.PackageKit 2012-03-09 09:02:40 +0000 |
| 2019 | +++ README.PackageKit 2012-06-13 16:29:18 +0000 |
| 2020 | @@ -50,20 +50,19 @@ |
| 2021 | - GetUpdateDetail |
| 2022 | - GetDistroUpgrades |
| 2023 | - UpgradeSystem |
| 2024 | + - WhatProvides (no builtin handling, only plugins) |
| 2025 | + - RepoEnable: (only enabling, not disabling) |
| 2026 | + - InstallSignature |
| 2027 | |
| 2028 | Not yet supported roles: |
| 2029 | |
| 2030 | - GetCategories: Curently groups are still used, would be nice to reuse the |
| 2031 | categories from software-center |
| 2032 | - GetRepoList: not implemented in the worker |
| 2033 | - - RepoEnable: not implemented in the worker) |
| 2034 | - - RepoSetData: not implemented in the worker) |
| 2035 | + - RepoSetData: not implemented in the worker |
| 2036 | - InstallFiles: not implemented in the worker |
| 2037 | - SimulateInstallFiles: not implemented in the worker |
| 2038 | - - WhatProvides: not implemented in the worker. We could reuse code from |
| 2039 | sessioninstaller. |
| 2040 | - - InstallSignature: not implemented in the worker. Could be mapped to |
| 2041 | - AddVendorKeyFromFile. |
| 2042 | |
| 2043 | Roles we won't support at all because of missing infrastructure in APT: |
| 2044 | |
| 2045 | |
| 2046 | === modified file 'README.tests' |
| 2047 | --- README.tests 2010-07-12 09:46:15 +0000 |
| 2048 | +++ README.tests 2012-06-13 16:29:18 +0000 |
| 2049 | @@ -1,3 +1,4 @@ |
| 2050 | -Tests are supported via nosetests from the python-nose package. |
| 2051 | +Tests are supported via nosetests3 from the python3-nose package. |
| 2052 | |
| 2053 | -Run them via nosetests. |
| 2054 | +To run the tests you can either use the "python3 setup.py test" or |
| 2055 | +the "nosetests3" command. |
| 2056 | |
| 2057 | === modified file 'aptd' |
| 2058 | --- aptd 2009-06-30 15:06:36 +0000 |
| 2059 | +++ aptd 2012-06-13 16:29:18 +0000 |
| 2060 | @@ -1,4 +1,4 @@ |
| 2061 | -#!/usr/bin/python |
| 2062 | +#!/usr/bin/python3 |
| 2063 | # -*- coding: utf-8 -*- |
| 2064 | """ |
| 2065 | aptd - apt daemon |
| 2066 | |
| 2067 | === modified file 'aptdaemon/client.py' |
| 2068 | --- aptdaemon/client.py 2012-04-09 20:48:44 +0000 |
| 2069 | +++ aptdaemon/client.py 2012-06-13 16:29:18 +0000 |
| 2070 | @@ -67,12 +67,16 @@ |
| 2071 | return value |
| 2072 | |
| 2073 | |
| 2074 | -class MemoizedMixIn(MemoizedTransaction, GObject.GObjectMeta): |
| 2075 | +class MemoizedMixInMeta(MemoizedTransaction, GObject.GObjectMeta): |
| 2076 | |
| 2077 | """Helper meta class for merging""" |
| 2078 | |
| 2079 | - |
| 2080 | -class AptTransaction(GObject.GObject): |
| 2081 | +# This code is used to make meta classes work with Python 2 and 3 at the same |
| 2082 | +# time, see http://mikewatkins.ca/2008/11/29/python-2-and-3-metaclasses/ |
| 2083 | +MemoizedMixIn = MemoizedMixInMeta("MemoizedMixIn", (GObject.GObject,), {}) |
| 2084 | + |
| 2085 | + |
| 2086 | +class AptTransaction(MemoizedMixIn): |
| 2087 | |
| 2088 | """Represents an aptdaemon transaction. |
| 2089 | |
| 2090 | @@ -410,7 +414,6 @@ |
| 2091 | dependencies before the transaction will be executed. |
| 2092 | """ |
| 2093 | |
| 2094 | - __metaclass__ = MemoizedMixIn |
| 2095 | |
| 2096 | __gsignals__ = {"finished": (GObject.SIGNAL_RUN_FIRST, |
| 2097 | GObject.TYPE_NONE, |
| 2098 | @@ -426,10 +429,10 @@ |
| 2099 | GObject.TYPE_PYOBJECT)), |
| 2100 | "download-changed": (GObject.SIGNAL_RUN_FIRST, |
| 2101 | GObject.TYPE_NONE, |
| 2102 | - (GObject.TYPE_INT,)), |
| 2103 | + (GObject.TYPE_INT64,)), |
| 2104 | "space-changed": (GObject.SIGNAL_RUN_FIRST, |
| 2105 | GObject.TYPE_NONE, |
| 2106 | - (GObject.TYPE_INT,)), |
| 2107 | + (GObject.TYPE_INT64,)), |
| 2108 | "error": (GObject.SIGNAL_RUN_FIRST, |
| 2109 | GObject.TYPE_NONE, |
| 2110 | (GObject.TYPE_STRING, GObject.TYPE_STRING)), |
| 2111 | @@ -457,15 +460,17 @@ |
| 2112 | "progress-details-changed": (GObject.SIGNAL_RUN_FIRST, |
| 2113 | GObject.TYPE_NONE, |
| 2114 | (GObject.TYPE_INT, GObject.TYPE_INT, |
| 2115 | - GObject.TYPE_INT, GObject.TYPE_INT, |
| 2116 | - GObject.TYPE_INT, GObject.TYPE_INT)), |
| 2117 | + GObject.TYPE_INT64, |
| 2118 | + GObject.TYPE_INT64, |
| 2119 | + GObject.TYPE_INT, |
| 2120 | + GObject.TYPE_INT64)), |
| 2121 | "progress-download-changed": (GObject.SIGNAL_RUN_FIRST, |
| 2122 | GObject.TYPE_NONE, |
| 2123 | (GObject.TYPE_STRING, |
| 2124 | GObject.TYPE_STRING, |
| 2125 | GObject.TYPE_STRING, |
| 2126 | - GObject.TYPE_INT, |
| 2127 | - GObject.TYPE_INT, |
| 2128 | + GObject.TYPE_INT64, |
| 2129 | + GObject.TYPE_INT64, |
| 2130 | GObject.TYPE_STRING)), |
| 2131 | "packages-changed": (GObject.SIGNAL_RUN_FIRST, |
| 2132 | GObject.TYPE_NONE, |
| 2133 | @@ -554,8 +559,7 @@ |
| 2134 | # main signals |
| 2135 | self._signal_matcher = \ |
| 2136 | self._iface.connect_to_signal("PropertyChanged", |
| 2137 | - self._on_property_changed, |
| 2138 | - utf8_strings=True) |
| 2139 | + self._on_property_changed) |
| 2140 | |
| 2141 | def _on_name_owner_changed(self, connection): |
| 2142 | """Fail the transaction if the daemon died.""" |
| 2143 | @@ -681,7 +685,7 @@ |
| 2144 | :raises: dbus.DBusException |
| 2145 | """ |
| 2146 | def sync_properties(prop_dict): |
| 2147 | - for property_name, value in prop_dict.iteritems(): |
| 2148 | + for property_name, value in prop_dict.items(): |
| 2149 | self._on_property_changed(property_name, value) |
| 2150 | if reply_handler: |
| 2151 | reply_handler(self) |
| 2152 | |
| 2153 | === modified file 'aptdaemon/config.py' |
| 2154 | --- aptdaemon/config.py 2012-02-03 06:37:42 +0000 |
| 2155 | +++ aptdaemon/config.py 2012-06-13 16:29:18 +0000 |
| 2156 | @@ -228,7 +228,7 @@ |
| 2157 | for filename in sorted(os.listdir("/etc/apt/apt.conf.d/")): |
| 2158 | lines = open("/etc/apt/apt.conf.d/%s" % filename).readlines() |
| 2159 | cw.parse(lines) |
| 2160 | - print(cw.set_value("huhu::abc", "lumpi", "10glatzor")) |
| 2161 | + print((cw.set_value("huhu::abc", "lumpi", "10glatzor"))) |
| 2162 | |
| 2163 | if __name__ == "__main__": |
| 2164 | main() |
| 2165 | |
| 2166 | === modified file 'aptdaemon/console.py' |
| 2167 | --- aptdaemon/console.py 2012-04-09 20:48:44 +0000 |
| 2168 | +++ aptdaemon/console.py 2012-06-13 16:29:18 +0000 |
| 2169 | @@ -53,6 +53,8 @@ |
| 2170 | ANSI_BOLD = chr(27) + "[1m" |
| 2171 | ANSI_RESET = chr(27) + "[0m" |
| 2172 | |
| 2173 | +PY3K = sys.version_info.major > 2 |
| 2174 | + |
| 2175 | |
| 2176 | class ConsoleClient: |
| 2177 | """ |
| 2178 | @@ -442,70 +444,73 @@ |
| 2179 | kepts = dep_kepts |
| 2180 | if installs: |
| 2181 | #TRANSLATORS: %s is the number of packages |
| 2182 | - print(ngettext("The following NEW package will be installed " |
| 2183 | + print((ngettext("The following NEW package will be installed " |
| 2184 | "(%(count)s):", |
| 2185 | "The following NEW packages will be installed " |
| 2186 | "(%(count)s):", |
| 2187 | - len(installs)) % {"count": len(installs)}) |
| 2188 | + len(installs)) % {"count": len(installs)})) |
| 2189 | show_packages(installs) |
| 2190 | if upgrades: |
| 2191 | #TRANSLATORS: %s is the number of packages |
| 2192 | - print(ngettext("The following package will be upgraded " |
| 2193 | + print((ngettext("The following package will be upgraded " |
| 2194 | "(%(count)s):", |
| 2195 | "The following packages will be upgraded " |
| 2196 | "(%(count)s):", |
| 2197 | - len(upgrades)) % {"count": len(upgrades)}) |
| 2198 | + len(upgrades)) % {"count": len(upgrades)})) |
| 2199 | show_packages(upgrades) |
| 2200 | if removals: |
| 2201 | #TRANSLATORS: %s is the number of packages |
| 2202 | - print(ngettext("The following package will be REMOVED " |
| 2203 | + print((ngettext("The following package will be REMOVED " |
| 2204 | "(%(count)s):", |
| 2205 | "The following packages will be REMOVED " |
| 2206 | "(%(count)s):", |
| 2207 | - len(removals)) % {"count": len(removals)}) |
| 2208 | + len(removals)) % {"count": len(removals)})) |
| 2209 | #FIXME: mark purges |
| 2210 | show_packages(removals) |
| 2211 | if downgrades: |
| 2212 | #TRANSLATORS: %s is the number of packages |
| 2213 | - print(ngettext("The following package will be DOWNGRADED " |
| 2214 | + print((ngettext("The following package will be DOWNGRADED " |
| 2215 | "(%(count)s):", |
| 2216 | "The following packages will be DOWNGRADED " |
| 2217 | "(%(count)s):", |
| 2218 | - len(downgrades)) % {"count": len(downgrades)}) |
| 2219 | + len(downgrades)) % {"count": len(downgrades)})) |
| 2220 | show_packages(downgrades) |
| 2221 | if reinstalls: |
| 2222 | #TRANSLATORS: %s is the number of packages |
| 2223 | - print(ngettext("The following package will be reinstalled " |
| 2224 | + print((ngettext("The following package will be reinstalled " |
| 2225 | "(%(count)s):", |
| 2226 | "The following packages will be reinstalled " |
| 2227 | "(%(count)s):", |
| 2228 | - len(reinstalls)) % {"count": len(reinstalls)}) |
| 2229 | + len(reinstalls)) % {"count": len(reinstalls)})) |
| 2230 | show_packages(reinstalls) |
| 2231 | if kepts: |
| 2232 | - print(ngettext("The following package has been kept back " |
| 2233 | + print((ngettext("The following package has been kept back " |
| 2234 | "(%(count)s):", |
| 2235 | "The following packages have been kept back " |
| 2236 | "(%(count)s):", |
| 2237 | - len(kepts)) % {"count": len(kepts)}) |
| 2238 | + len(kepts)) % {"count": len(kepts)})) |
| 2239 | show_packages(kepts) |
| 2240 | |
| 2241 | if self._transaction.download: |
| 2242 | - print(_("Need to get %sB of archives.") % \ |
| 2243 | - apt_pkg.size_to_str(self._transaction.download)) |
| 2244 | + print((_("Need to get %sB of archives.") % \ |
| 2245 | + apt_pkg.size_to_str(self._transaction.download))) |
| 2246 | if self._transaction.space > 0: |
| 2247 | - print(_("After this operation, %sB of additional disk space " |
| 2248 | + print((_("After this operation, %sB of additional disk space " |
| 2249 | "will be used.") % \ |
| 2250 | - apt_pkg.size_to_str(self._transaction.space)) |
| 2251 | + apt_pkg.size_to_str(self._transaction.space))) |
| 2252 | elif self._transaction.space < 0: |
| 2253 | - print(_("After this operation, %sB of additional disk space " |
| 2254 | + print((_("After this operation, %sB of additional disk space " |
| 2255 | "will be freed.") % \ |
| 2256 | - apt_pkg.size_to_str(self._transaction.space)) |
| 2257 | + apt_pkg.size_to_str(self._transaction.space))) |
| 2258 | if (not apt_pkg.config.find_b("APT::Get::Assume-Yes") and |
| 2259 | (self._transaction.space or self._transaction.download or |
| 2260 | installs or upgrades or downgrades or removals or kepts or |
| 2261 | reinstalls)): |
| 2262 | try: |
| 2263 | - cont = raw_input(_("Do you want to continue [Y/n]?")) |
| 2264 | + if PY3K: |
| 2265 | + cont = input(_("Do you want to continue [Y/n]?")) |
| 2266 | + else: |
| 2267 | + cont = raw_input(_("Do you want to continue [Y/n]?")) |
| 2268 | except EOFError: |
| 2269 | cont = "n" |
| 2270 | #FIXME: Listen to changed dependencies! |
| 2271 | @@ -532,100 +537,100 @@ |
| 2272 | |
| 2273 | epilog = _("To operate on more than one package put the package " |
| 2274 | "names in quotation marks:\naptdcon --install " |
| 2275 | - "\"foo bar\"").decode(enc) |
| 2276 | + "\"foo bar\"") |
| 2277 | parser = OptionParser(version=aptdaemon.__version__, epilog=epilog) |
| 2278 | parser.add_option("-c", "--refresh", default="", |
| 2279 | action="store_true", dest="refresh", |
| 2280 | - help=_("Refresh the cache").decode(enc)) |
| 2281 | + help=_("Refresh the cache")) |
| 2282 | parser.add_option("", "--fix-depends", default="", |
| 2283 | action="store_true", dest="fix_depends", |
| 2284 | help=_("Try to resolve broken dependencies. " |
| 2285 | "Potentially dangerous operation since it could " |
| 2286 | - "try to remove many packages.").decode(enc)) |
| 2287 | + "try to remove many packages.")) |
| 2288 | parser.add_option("", "--fix-install", default="", |
| 2289 | action="store_true", dest="fix_install", |
| 2290 | help=_("Try to finish a previous incompleted " |
| 2291 | - "installation").decode(enc)) |
| 2292 | + "installation")) |
| 2293 | parser.add_option("-i", "--install", default="", |
| 2294 | action="store", type="string", dest="install", |
| 2295 | - help=_("Install the given packages").decode(enc)) |
| 2296 | + help=_("Install the given packages")) |
| 2297 | parser.add_option("", "--reinstall", default="", |
| 2298 | action="store", type="string", dest="reinstall", |
| 2299 | - help=_("Reinstall the given packages").decode(enc)) |
| 2300 | + help=_("Reinstall the given packages")) |
| 2301 | parser.add_option("-r", "--remove", default="", |
| 2302 | action="store", type="string", dest="remove", |
| 2303 | - help=_("Remove the given packages").decode(enc)) |
| 2304 | + help=_("Remove the given packages")) |
| 2305 | parser.add_option("-p", "--purge", default="", |
| 2306 | action="store", type="string", dest="purge", |
| 2307 | help=_("Remove the given packages including " |
| 2308 | - "configuration files").decode(enc)) |
| 2309 | + "configuration files")) |
| 2310 | parser.add_option("-u", "--upgrade", default="", |
| 2311 | action="store", type="string", dest="upgrade", |
| 2312 | - help=_("Install the given packages").decode(enc)) |
| 2313 | + help=_("Install the given packages")) |
| 2314 | parser.add_option("", "--downgrade", default="", |
| 2315 | action="store", type="string", dest="downgrade", |
| 2316 | - help=_("Downgrade the given packages").decode(enc)) |
| 2317 | + help=_("Downgrade the given packages")) |
| 2318 | parser.add_option("", "--upgrade-system", |
| 2319 | action="store_true", dest="safe_upgrade", |
| 2320 | help=_("Deprecated: Please use " |
| 2321 | - "--safe-upgrade").decode(enc)) |
| 2322 | + "--safe-upgrade")) |
| 2323 | parser.add_option("", "--safe-upgrade", |
| 2324 | action="store_true", dest="safe_upgrade", |
| 2325 | - help=_("Upgrade the system in a safe way").decode(enc)) |
| 2326 | + help=_("Upgrade the system in a safe way")) |
| 2327 | parser.add_option("", "--full-upgrade", |
| 2328 | action="store_true", dest="full_upgrade", |
| 2329 | help=_("Upgrade the system, possibly installing and " |
| 2330 | - "removing packages").decode(enc)) |
| 2331 | + "removing packages")) |
| 2332 | parser.add_option("", "--add-vendor-key", default="", |
| 2333 | action="store", type="string", dest="add_vendor_key", |
| 2334 | - help=_("Add the vendor to the trusted ones").decode(enc)) |
| 2335 | + help=_("Add the vendor to the trusted ones")) |
| 2336 | parser.add_option("", "--add-vendor-key-from-keyserver", default="", |
| 2337 | action="store", type="string", |
| 2338 | help=_("Add the vendor keyid (also needs " |
| 2339 | - "--keyserver)").decode(enc)) |
| 2340 | + "--keyserver)")) |
| 2341 | parser.add_option("", "--keyserver", default="", |
| 2342 | action="store", type="string", |
| 2343 | help=_("Use the given keyserver for looking up " |
| 2344 | - "keys").decode(enc)) |
| 2345 | + "keys")) |
| 2346 | parser.add_option("", "--add-repository", default="", |
| 2347 | action="store", type="string", dest="add_repository", |
| 2348 | help=_("Add new repository from the given " |
| 2349 | - "deb-line").decode(enc)) |
| 2350 | + "deb-line")) |
| 2351 | parser.add_option("", "--sources-file", action="store", default="", |
| 2352 | type="string", dest="sources_file", |
| 2353 | help=_("Specify an alternative sources.list.d file to " |
| 2354 | - "which repositories should be added.").decode(enc)) |
| 2355 | + "which repositories should be added.")) |
| 2356 | parser.add_option("", "--list-trusted-vendors", default="", |
| 2357 | action="store_true", dest="list_trusted_vendor_keys", |
| 2358 | - help=_("List trusted vendor keys").decode(enc)) |
| 2359 | + help=_("List trusted vendor keys")) |
| 2360 | parser.add_option("", "--remove-vendor-key", default="", |
| 2361 | action="store", type="string", dest="remove_vendor_key", |
| 2362 | help=_("Remove the trusted key of the given " |
| 2363 | - "fingerprint").decode(enc)) |
| 2364 | + "fingerprint")) |
| 2365 | parser.add_option("", "--clean", |
| 2366 | action="store_true", dest="clean", |
| 2367 | - help=_("Remove downloaded package files").decode(enc)) |
| 2368 | + help=_("Remove downloaded package files")) |
| 2369 | parser.add_option("", "--reconfigure", default="", |
| 2370 | action="store", type="string", dest="reconfigure", |
| 2371 | help=_("Reconfigure installed packages. Optionally the " |
| 2372 | "minimum priority of questions can be " |
| 2373 | - "specified").decode(enc)) |
| 2374 | + "specified")) |
| 2375 | parser.add_option("", "--priority", default="default", |
| 2376 | action="store", type="string", dest="priority", |
| 2377 | help=_("The minimum debconf priority of question to " |
| 2378 | - "be displayed").decode(enc)) |
| 2379 | + "be displayed")) |
| 2380 | parser.add_option("", "--hide-terminal", |
| 2381 | action="store_true", dest="hide_terminal", |
| 2382 | - help=_("Do not attach to the apt terminal").decode(enc)) |
| 2383 | + help=_("Do not attach to the apt terminal")) |
| 2384 | parser.add_option("", "--allow-unauthenticated", |
| 2385 | action="store_true", dest="allow_unauthenticated", |
| 2386 | default=False, |
| 2387 | help=_("Allow packages from unauthenticated " |
| 2388 | - "sources").decode(enc)) |
| 2389 | + "sources")) |
| 2390 | parser.add_option("-d", "--show-details", |
| 2391 | action="store_true", dest="details", |
| 2392 | help=_("Show additional information about the packages. " |
| 2393 | - "Currently only the version number").decode(enc)) |
| 2394 | + "Currently only the version number")) |
| 2395 | (options, args) = parser.parse_args() |
| 2396 | con = ConsoleClient(show_terminal=not options.hide_terminal, |
| 2397 | allow_unauthenticated=options.allow_unauthenticated, |
| 2398 | |
| 2399 | === modified file 'aptdaemon/core.py' |
| 2400 | --- aptdaemon/core.py 2012-04-09 20:48:44 +0000 |
| 2401 | +++ aptdaemon/core.py 2012-06-13 16:29:18 +0000 |
| 2402 | @@ -54,8 +54,8 @@ |
| 2403 | import dbus.service |
| 2404 | import dbus.mainloop.glib |
| 2405 | import dbus.glib |
| 2406 | -from softwareproperties.AptAuth import AptAuth |
| 2407 | import apt_pkg |
| 2408 | +import apt.auth |
| 2409 | |
| 2410 | from .config import ConfigWriter |
| 2411 | from . import errors |
| 2412 | @@ -198,7 +198,7 @@ |
| 2413 | xml = ElementTree.fromstring(data) |
| 2414 | for iface in xml.findall("interface"): |
| 2415 | props = self._get_properties(iface.attrib["name"]) |
| 2416 | - for key, value in props.iteritems(): |
| 2417 | + for key, value in props.items(): |
| 2418 | attrib = {"name": key} |
| 2419 | if key in self.WRITABLE_PROPERTIES: |
| 2420 | attrib["access"] = "readwrite" |
| 2421 | @@ -346,7 +346,7 @@ |
| 2422 | bus -- the DBus connection which should be used (defaults to system bus) |
| 2423 | """ |
| 2424 | if tid is None: |
| 2425 | - tid = uuid.uuid4().get_hex() |
| 2426 | + tid = uuid.uuid4().hex |
| 2427 | self.tid = "/org/debian/apt/transaction/%s" % tid |
| 2428 | if connect == True: |
| 2429 | self.bus = bus |
| 2430 | @@ -380,9 +380,9 @@ |
| 2431 | self._role = dbus.String(role) |
| 2432 | self._progress = dbus.Int32(0) |
| 2433 | # items_done, total_items, bytes_done, total_bytes, speed, time |
| 2434 | - self._progress_details = dbus.Struct((0, 0, 0L, 0L, 0.0, 0L), |
| 2435 | + self._progress_details = dbus.Struct((0, 0, 0, 0, 0.0, 0), |
| 2436 | signature="iixxdx") |
| 2437 | - self._progress_download = dbus.Struct(("", "", "", 0L, 0L, ""), |
| 2438 | + self._progress_download = dbus.Struct(("", "", "", 0, 0, ""), |
| 2439 | signature="sssxxs") |
| 2440 | self._progress_package = dbus.Struct(("", ""), signature="ss") |
| 2441 | self._exit = dbus.String(enums.EXIT_UNFINISHED) |
| 2442 | @@ -485,7 +485,7 @@ |
| 2443 | if not data.signature.startswith("s"): |
| 2444 | raise errors.InvalidMetaDataError("Only strings are accepted " |
| 2445 | "as keys.") |
| 2446 | - for key, value in data.iteritems(): |
| 2447 | + for key, value in data.items(): |
| 2448 | if key in self._meta_data: |
| 2449 | raise errors.InvalidMetaDataError("The key %s already " |
| 2450 | "exists. It is not allowed " |
| 2451 | @@ -1471,7 +1471,7 @@ |
| 2452 | """Helper method which returns the tid of a new transaction.""" |
| 2453 | pid, uid, cmdline = \ |
| 2454 | yield policykit1.get_proc_info_from_dbus_name(sender, self.bus) |
| 2455 | - tid = uuid.uuid4().get_hex() |
| 2456 | + tid = uuid.uuid4().hex |
| 2457 | trans = Transaction(tid, role, self.queue, pid, uid, cmdline, sender, |
| 2458 | packages=packages, kwargs=kwargs, bus=self.bus) |
| 2459 | self.queue.limbo[trans.tid] = trans |
| 2460 | @@ -1926,11 +1926,11 @@ |
| 2461 | |
| 2462 | @inline_callbacks |
| 2463 | def _get_trusted_vendor_keys(self, sender): |
| 2464 | - aptauth = AptAuth() |
| 2465 | action = policykit1.PK_ACTION_GET_TRUSTED_VENDOR_KEYS |
| 2466 | yield policykit1.check_authorization_by_name(sender, action, |
| 2467 | bus=self.bus) |
| 2468 | - return_value([key.decode("utf-8", "ignore") for key in aptauth.list()]) |
| 2469 | + fingerprints = [key.keyid for key in apt.auth.list_keys()] |
| 2470 | + return_value(fingerprints) |
| 2471 | |
| 2472 | # pylint: disable-msg=C0103,C0322 |
| 2473 | @dbus.service.method(APTDAEMON_DBUS_INTERFACE, |
| 2474 | @@ -2144,40 +2144,40 @@ |
| 2475 | default=False, |
| 2476 | action="store_true", dest="disable_timeout", |
| 2477 | help=_("Do not shutdown the daemon because of " |
| 2478 | - "inactivity").decode(enc)) |
| 2479 | + "inactivity")) |
| 2480 | parser.add_option("", "--disable-plugins", |
| 2481 | default=False, |
| 2482 | action="store_true", dest="disable_plugins", |
| 2483 | - help=_("Do not load any plugins").decode(enc)) |
| 2484 | + help=_("Do not load any plugins")) |
| 2485 | parser.add_option("-d", "--debug", |
| 2486 | default=False, |
| 2487 | action="store_true", dest="debug", |
| 2488 | help=_("Show internal processing " |
| 2489 | - "information").decode(enc)) |
| 2490 | + "information")) |
| 2491 | parser.add_option("-r", "--replace", |
| 2492 | default=False, |
| 2493 | action="store_true", dest="replace", |
| 2494 | help=_("Quit and replace an already running " |
| 2495 | - "daemon").decode(enc)) |
| 2496 | + "daemon")) |
| 2497 | parser.add_option("", "--session-bus", |
| 2498 | default=False, |
| 2499 | action="store_true", dest="session_bus", |
| 2500 | help=_("Listen on the DBus session bus (Only required " |
| 2501 | - "for testing").decode(enc)) |
| 2502 | + "for testing")) |
| 2503 | parser.add_option("", "--chroot", default=None, |
| 2504 | action="store", type="string", dest="chroot", |
| 2505 | help=_("Perform operations in the given " |
| 2506 | - "chroot").decode(enc)) |
| 2507 | + "chroot")) |
| 2508 | parser.add_option("-p", "--profile", |
| 2509 | default=False, |
| 2510 | action="store", type="string", dest="profile", |
| 2511 | help=_("Store profile stats in the specified " |
| 2512 | - "file").decode(enc)) |
| 2513 | + "file")) |
| 2514 | parser.add_option("--dummy", |
| 2515 | default=False, |
| 2516 | action="store_true", dest="dummy", |
| 2517 | help=_("Do not make any changes to the system (Only " |
| 2518 | - "of use to developers)").decode(enc)) |
| 2519 | + "of use to developers)")) |
| 2520 | options, args = parser.parse_args() |
| 2521 | if options.debug == True: |
| 2522 | log.setLevel(logging.DEBUG) |
| 2523 | |
| 2524 | === modified file 'aptdaemon/errors.py' |
| 2525 | --- aptdaemon/errors.py 2012-02-03 06:37:42 +0000 |
| 2526 | +++ aptdaemon/errors.py 2012-06-13 16:29:18 +0000 |
| 2527 | @@ -28,11 +28,15 @@ |
| 2528 | "get_native_exception") |
| 2529 | |
| 2530 | import inspect |
| 2531 | +from functools import wraps |
| 2532 | +import sys |
| 2533 | + |
| 2534 | import dbus |
| 2535 | -from functools import wraps |
| 2536 | |
| 2537 | import aptdaemon.enums |
| 2538 | |
| 2539 | +PY3K = sys.version_info.major > 2 |
| 2540 | + |
| 2541 | |
| 2542 | class AptDaemonError(dbus.DBusException): |
| 2543 | |
| 2544 | @@ -49,7 +53,10 @@ |
| 2545 | """Overwrite the DBusException method, since it calls |
| 2546 | Exception.__str__() internally which doesn't support unicode or |
| 2547 | or non-ascii encodings.""" |
| 2548 | - return self._message.encode("UTF-8") |
| 2549 | + if PY3K: |
| 2550 | + return dbus.DBusException.get_dbus_message(self) |
| 2551 | + else: |
| 2552 | + return self._message.encode("UTF-8") |
| 2553 | |
| 2554 | |
| 2555 | class TransactionRoleAlreadySet(AptDaemonError): |
| 2556 | @@ -101,7 +108,7 @@ |
| 2557 | |
| 2558 | def __str__(self): |
| 2559 | return "Transaction failed: %s\n%s" % \ |
| 2560 | - (aptdaemon.enums.get_role_error_from_enum(self.code), |
| 2561 | + (aptdaemon.enums.get_error_string_from_enum(self.code), |
| 2562 | self.details) |
| 2563 | |
| 2564 | |
| 2565 | @@ -192,9 +199,7 @@ |
| 2566 | if not isinstance(error, dbus.DBusException): |
| 2567 | return error |
| 2568 | dbus_name = error.get_dbus_name() |
| 2569 | - # We have to use the deprecated message attribute to avoid encoding errors |
| 2570 | - # See LP #846044 |
| 2571 | - dbus_msg = error.message |
| 2572 | + dbus_msg = error.get_dbus_message() |
| 2573 | if dbus_name == TransactionFailed._dbus_error_name: |
| 2574 | return TransactionFailed(*dbus_msg.split(":", 1)) |
| 2575 | elif dbus_name == AuthorizationFailed._dbus_error_name: |
| 2576 | @@ -211,7 +216,9 @@ |
| 2577 | |
| 2578 | def _convert_unicode(text, encoding="UTF-8"): |
| 2579 | """Always return an unicode.""" |
| 2580 | - if not isinstance(text, unicode): |
| 2581 | + if PY3K and not isinstance(text, str): |
| 2582 | + text = str(text, encoding, errors="ignore") |
| 2583 | + elif not PY3K and not isinstance(text, unicode): |
| 2584 | text = unicode(text, encoding, errors="ignore") |
| 2585 | return text |
| 2586 | |
| 2587 | |
| 2588 | === modified file 'aptdaemon/gtk3widgets.py' |
| 2589 | --- aptdaemon/gtk3widgets.py 2012-03-14 13:26:31 +0000 |
| 2590 | +++ aptdaemon/gtk3widgets.py 2012-06-13 16:29:18 +0000 |
| 2591 | @@ -51,7 +51,7 @@ |
| 2592 | _ = lambda msg: gettext.dgettext("aptdaemon", msg) |
| 2593 | |
| 2594 | (COLUMN_ID, |
| 2595 | - COLUMN_PACKAGE) = range(2) |
| 2596 | + COLUMN_PACKAGE) = list(range(2)) |
| 2597 | |
| 2598 | |
| 2599 | class AptStatusIcon(Gtk.Image): |
| 2600 | @@ -446,7 +446,7 @@ |
| 2601 | of a transaction. |
| 2602 | """ |
| 2603 | |
| 2604 | - COL_TEXT, COL_PROGRESS, COL_URI = range(3) |
| 2605 | + COL_TEXT, COL_PROGRESS, COL_URI = list(range(3)) |
| 2606 | |
| 2607 | def __init__(self, transaction=None): |
| 2608 | Gtk.TreeView.__init__(self) |
| 2609 | @@ -484,7 +484,7 @@ |
| 2610 | downloaded, message): |
| 2611 | """Callback for a changed download progress.""" |
| 2612 | try: |
| 2613 | - progress = downloaded * 100 / full_size |
| 2614 | + progress = int(downloaded * 100 / full_size) |
| 2615 | except ZeroDivisionError: |
| 2616 | progress = -1 |
| 2617 | if status == DOWNLOAD_DONE: |
| 2618 | |
| 2619 | === modified file 'aptdaemon/gtkwidgets.py' |
| 2620 | --- aptdaemon/gtkwidgets.py 2012-02-03 06:37:42 +0000 |
| 2621 | +++ aptdaemon/gtkwidgets.py 2012-06-13 16:29:18 +0000 |
| 2622 | @@ -53,7 +53,7 @@ |
| 2623 | _ = lambda msg: gettext.dgettext("aptdaemon", msg) |
| 2624 | |
| 2625 | (COLUMN_ID, |
| 2626 | - COLUMN_PACKAGE) = range(2) |
| 2627 | + COLUMN_PACKAGE) = list(range(2)) |
| 2628 | |
| 2629 | |
| 2630 | class AptStatusIcon(gtk.Image): |
| 2631 | @@ -440,7 +440,7 @@ |
| 2632 | of a transaction. |
| 2633 | """ |
| 2634 | |
| 2635 | - COL_TEXT, COL_PROGRESS, COL_URI = range(3) |
| 2636 | + COL_TEXT, COL_PROGRESS, COL_URI = list(range(3)) |
| 2637 | |
| 2638 | def __init__(self, transaction=None): |
| 2639 | gtk.TreeView.__init__(self) |
| 2640 | |
| 2641 | === modified file 'aptdaemon/lock.py' |
| 2642 | --- aptdaemon/lock.py 2012-03-14 13:26:31 +0000 |
| 2643 | +++ aptdaemon/lock.py 2012-06-13 16:29:18 +0000 |
| 2644 | @@ -110,7 +110,7 @@ |
| 2645 | except IOError: |
| 2646 | return None |
| 2647 | finally: |
| 2648 | - fd_lock_read |
| 2649 | + fd_lock_read.close() |
| 2650 | return None |
| 2651 | |
| 2652 | apt_pkg.init() |
| 2653 | |
| 2654 | === modified file 'aptdaemon/networking.py' |
| 2655 | --- aptdaemon/networking.py 2012-05-11 15:56:04 +0000 |
| 2656 | +++ aptdaemon/networking.py 2012-06-13 16:29:18 +0000 |
| 2657 | @@ -33,7 +33,8 @@ |
| 2658 | DBusGMainLoop(set_as_default=True) |
| 2659 | import logging |
| 2660 | import os |
| 2661 | -import packagekit.enums as pk_enums |
| 2662 | + |
| 2663 | +from . import pkenums as pk_enums |
| 2664 | |
| 2665 | log = logging.getLogger("AptDaemon.NetMonitor") |
| 2666 | |
| 2667 | @@ -259,7 +260,7 @@ |
| 2668 | @inline_callbacks |
| 2669 | def _call_monitor(): |
| 2670 | state = yield monitor.get_network_state() |
| 2671 | - print("Initial network state: %s" % state) |
| 2672 | + print(("Initial network state: %s" % state)) |
| 2673 | log_handler = logging.StreamHandler() |
| 2674 | log.addHandler(log_handler) |
| 2675 | log.setLevel(logging.DEBUG) |
| 2676 | |
| 2677 | === modified file 'aptdaemon/pkcompat.py' |
| 2678 | --- aptdaemon/pkcompat.py 2012-05-11 15:56:04 +0000 |
| 2679 | +++ aptdaemon/pkcompat.py 2012-06-13 16:29:18 +0000 |
| 2680 | @@ -37,7 +37,6 @@ |
| 2681 | from defer.utils import dbus_deferred_method |
| 2682 | import dbus |
| 2683 | from gi.repository import GObject |
| 2684 | -import packagekit.enums as pk_enums |
| 2685 | |
| 2686 | # for optional plugin support |
| 2687 | try: |
| 2688 | @@ -45,14 +44,15 @@ |
| 2689 | except ImportError: |
| 2690 | pkg_resources = None |
| 2691 | |
| 2692 | -from aptdaemon import policykit1 |
| 2693 | -import aptdaemon.core |
| 2694 | -from aptdaemon.core import APTDAEMON_TRANSACTION_DBUS_INTERFACE |
| 2695 | -import aptdaemon.enums as aptd_enums |
| 2696 | -from aptdaemon.errors import TransactionFailed, TransactionCancelled |
| 2697 | -from aptdaemon.progress import DaemonAcquireProgress |
| 2698 | -import aptdaemon.worker |
| 2699 | -import aptdaemon.networking |
| 2700 | +from . import policykit1 |
| 2701 | +from . import core |
| 2702 | +from .core import APTDAEMON_TRANSACTION_DBUS_INTERFACE |
| 2703 | +from . import enums as aptd_enums |
| 2704 | +from .errors import TransactionFailed, TransactionCancelled |
| 2705 | +from .progress import DaemonAcquireProgress |
| 2706 | +from . import worker |
| 2707 | +from . import networking |
| 2708 | +from . import pkenums as pk_enums |
| 2709 | |
| 2710 | GObject.threads_init() |
| 2711 | |
| 2712 | @@ -239,7 +239,7 @@ |
| 2713 | } |
| 2714 | |
| 2715 | |
| 2716 | -class PackageKit(aptdaemon.core.DBusObject): |
| 2717 | +class PackageKit(core.DBusObject): |
| 2718 | |
| 2719 | """Provides a limited set of the PackageKit system D-Bus API.""" |
| 2720 | |
| 2721 | @@ -262,6 +262,8 @@ |
| 2722 | pk_enums.ROLE_SEARCH_GROUP, |
| 2723 | pk_enums.ROLE_SEARCH_FILE, |
| 2724 | pk_enums.ROLE_WHAT_PROVIDES, |
| 2725 | + pk_enums.ROLE_REPO_ENABLE, |
| 2726 | + pk_enums.ROLE_INSTALL_SIGNATURE, |
| 2727 | pk_enums.ROLE_DOWNLOAD_PACKAGES] |
| 2728 | if META_RELEASE_SUPPORT: |
| 2729 | SUPPORTED_ROLES.append(pk_enums.ROLE_GET_DISTRO_UPGRADES) |
| 2730 | @@ -294,14 +296,14 @@ |
| 2731 | self.bus = bus |
| 2732 | bus_path = PACKAGEKIT_DBUS_PATH |
| 2733 | bus_name = dbus.service.BusName(PACKAGEKIT_DBUS_SERVICE, self.bus) |
| 2734 | - aptdaemon.core.DBusObject.__init__(self, bus_name, bus_path) |
| 2735 | + core.DBusObject.__init__(self, bus_name, bus_path) |
| 2736 | self._updates_changed_timeout_id = None |
| 2737 | self._updates_changed = False |
| 2738 | self.queue = queue |
| 2739 | self.queue.worker.connect("transaction-done", self._on_transaction_done) |
| 2740 | self.queue.connect("queue-changed", self._on_queue_changed) |
| 2741 | self._distro_id = None |
| 2742 | - self.netmon = aptdaemon.networking.get_network_monitor() |
| 2743 | + self.netmon = networking.get_network_monitor() |
| 2744 | self.netmon.connect("network-state-changed", |
| 2745 | self._on_network_state_changed) |
| 2746 | self._get_network_state() |
| 2747 | @@ -430,15 +432,15 @@ |
| 2748 | def _get_properties(self, iface): |
| 2749 | """Helper to get the properties of a D-Bus interface.""" |
| 2750 | if iface == PACKAGEKIT_DBUS_INTERFACE: |
| 2751 | - return {# Claim that we are a stable version |
| 2752 | - "VersionMajor": dbus.UInt32(6), |
| 2753 | - "VersionMinor": dbus.UInt32(18), |
| 2754 | + return {# Claim that we are a current version |
| 2755 | + "VersionMajor": dbus.UInt32(7), |
| 2756 | + "VersionMinor": dbus.UInt32(4), |
| 2757 | "VersionMicro": dbus.UInt32(0), |
| 2758 | "BackendName": dbus.String("aptdaemon"), |
| 2759 | "BackendDescription": dbus.String("Compatibility layer"), |
| 2760 | "BackendAuthor": dbus.String(__author__), |
| 2761 | "Filters": dbus.String(";".join(self.SUPPORTED_FILTERS)), |
| 2762 | - "Groups": dbus.String(";".join(SECTION_GROUP_MAP.values())), |
| 2763 | + "Groups": dbus.String(";".join(list(SECTION_GROUP_MAP.values()))), |
| 2764 | "Roles": dbus.String(";".join(self.SUPPORTED_ROLES)), |
| 2765 | "Locked": dbus.Boolean(False), |
| 2766 | "NetworkState": dbus.String(self.netmon.state), |
| 2767 | @@ -460,7 +462,7 @@ |
| 2768 | def _on_network_state_changed(self, mon, state): |
| 2769 | self.Changed() |
| 2770 | self.PropertiesChanged(PACKAGEKIT_DBUS_INTERFACE, |
| 2771 | - {"Network": state}, []) |
| 2772 | + {"NetworkState": state}, []) |
| 2773 | |
| 2774 | def _on_queue_changed(self, queue): |
| 2775 | self.TransactionListChanged(self._get_transaction_list()) |
| 2776 | @@ -522,7 +524,7 @@ |
| 2777 | return False |
| 2778 | |
| 2779 | |
| 2780 | -class MergedTransaction(aptdaemon.core.Transaction): |
| 2781 | +class MergedTransaction(core.Transaction): |
| 2782 | |
| 2783 | """Overlay of an Aptdaemon transaction which also provides the |
| 2784 | PackageKit object and its interfaces. |
| 2785 | @@ -530,7 +532,7 @@ |
| 2786 | |
| 2787 | def __init__(self, pktrans, role, queue, connect=True, |
| 2788 | bus=None, packages=None, kwargs=None): |
| 2789 | - aptdaemon.core.Transaction.__init__(self, pktrans.tid[1:], role, queue, |
| 2790 | + core.Transaction.__init__(self, pktrans.tid[1:], role, queue, |
| 2791 | pktrans.pid, pktrans.uid, |
| 2792 | pktrans.cmdline, pktrans.sender, |
| 2793 | connect, bus, packages, kwargs) |
| 2794 | @@ -538,52 +540,52 @@ |
| 2795 | self.run_time = 0 |
| 2796 | |
| 2797 | def _set_status(self, enum): |
| 2798 | - aptdaemon.core.Transaction._set_status(self, enum) |
| 2799 | + core.Transaction._set_status(self, enum) |
| 2800 | self.pktrans.status = get_pk_status_enum(enum) |
| 2801 | |
| 2802 | - status = property(aptdaemon.core.Transaction._get_status, _set_status) |
| 2803 | + status = property(core.Transaction._get_status, _set_status) |
| 2804 | |
| 2805 | def _set_progress(self, percent): |
| 2806 | - aptdaemon.core.Transaction._set_progress(self, percent) |
| 2807 | + core.Transaction._set_progress(self, percent) |
| 2808 | self.pktrans.percentage = self._progress |
| 2809 | |
| 2810 | - progress = property(aptdaemon.core.Transaction._get_progress, _set_progress) |
| 2811 | + progress = property(core.Transaction._get_progress, _set_progress) |
| 2812 | |
| 2813 | def _set_progress_details(self, details): |
| 2814 | - aptdaemon.core.Transaction._set_progress_details(self, details) |
| 2815 | + core.Transaction._set_progress_details(self, details) |
| 2816 | self.pktrans.speed = int(details[4]) |
| 2817 | self.pktrans.remaining_time = int(details[5]) |
| 2818 | self.pktrans.elapsed_time = int(time.time() - self.pktrans.start_time) |
| 2819 | |
| 2820 | - progress_details = property(aptdaemon.core.Transaction._get_progress_details, |
| 2821 | + progress_details = property(core.Transaction._get_progress_details, |
| 2822 | _set_progress_details) |
| 2823 | |
| 2824 | def _set_progress_package(self, progress): |
| 2825 | - aptdaemon.core.Transaction._set_progress_package(self, progress) |
| 2826 | + core.Transaction._set_progress_package(self, progress) |
| 2827 | pkg_name, enum = progress |
| 2828 | self.emit_package(get_pk_package_enum(enum), |
| 2829 | get_pk_package_id(pkg_name), |
| 2830 | "") |
| 2831 | |
| 2832 | - progress_package = property(aptdaemon.core.Transaction._get_progress_package, |
| 2833 | + progress_package = property(core.Transaction._get_progress_package, |
| 2834 | _set_progress_package) |
| 2835 | |
| 2836 | |
| 2837 | def _set_exit(self, enum): |
| 2838 | - aptdaemon.core.Transaction._set_exit(self, enum) |
| 2839 | + core.Transaction._set_exit(self, enum) |
| 2840 | self.pktrans.exit = get_pk_exit_enum(enum) |
| 2841 | |
| 2842 | - exit = property(aptdaemon.core.Transaction._get_exit, _set_exit) |
| 2843 | + exit = property(core.Transaction._get_exit, _set_exit) |
| 2844 | |
| 2845 | def _set_error(self, excep): |
| 2846 | - aptdaemon.core.Transaction._set_error(self, excep) |
| 2847 | + core.Transaction._set_error(self, excep) |
| 2848 | self.pktrans.ErrorCode(get_pk_error_enum(excep.code), |
| 2849 | self._error_property[1]) |
| 2850 | |
| 2851 | - error = property(aptdaemon.core.Transaction._get_error, _set_error) |
| 2852 | + error = property(core.Transaction._get_error, _set_error) |
| 2853 | |
| 2854 | def _remove_from_connection_no_raise(self): |
| 2855 | - aptdaemon.core.Transaction._remove_from_connection_no_raise(self) |
| 2856 | + core.Transaction._remove_from_connection_no_raise(self) |
| 2857 | self.pktrans.Destroy() |
| 2858 | try: |
| 2859 | self.pktrans.remove_from_connection() |
| 2860 | @@ -613,7 +615,7 @@ |
| 2861 | changelog, state, issued, updated) |
| 2862 | |
| 2863 | |
| 2864 | -class PackageKitTransaction(aptdaemon.core.DBusObject): |
| 2865 | +class PackageKitTransaction(core.DBusObject): |
| 2866 | |
| 2867 | """Provides a PackageKit transaction object.""" |
| 2868 | |
| 2869 | @@ -622,14 +624,14 @@ |
| 2870 | pklog.info("Initializing PackageKit transaction") |
| 2871 | bus_name = None |
| 2872 | bus_path = None |
| 2873 | - self.tid = "/%s" % uuid.uuid4().get_hex() |
| 2874 | + self.tid = "/%s" % uuid.uuid4().hex |
| 2875 | if connect == True: |
| 2876 | if bus is None: |
| 2877 | bus = dbus.SystemBus() |
| 2878 | self.bus = bus |
| 2879 | bus_path = self.tid |
| 2880 | bus_name = dbus.service.BusName(PACKAGEKIT_DBUS_SERVICE, bus) |
| 2881 | - aptdaemon.core.DBusObject.__init__(self, bus_name, bus_path) |
| 2882 | + core.DBusObject.__init__(self, bus_name, bus_path) |
| 2883 | self.queue = queue |
| 2884 | self.hints = {} |
| 2885 | self.start_time = time.time() |
| 2886 | @@ -1745,9 +1747,9 @@ |
| 2887 | self.role = pk_enums.ROLE_INSTALL_FILES |
| 2888 | GObject.idle_add(self._fail_not_implemented) |
| 2889 | |
| 2890 | - @dbus.service.method(PACKAGEKIT_TRANS_DBUS_INTERFACE, |
| 2891 | - in_signature="sss", out_signature="", |
| 2892 | - sender_keyword="sender") |
| 2893 | + @dbus_deferred_method(PACKAGEKIT_TRANS_DBUS_INTERFACE, |
| 2894 | + in_signature="sss", out_signature="", |
| 2895 | + sender_keyword="sender") |
| 2896 | def InstallSignature(self, sig_type, key_id, package_id, sender): |
| 2897 | """This method allows us to install new security keys. |
| 2898 | |
| 2899 | @@ -1755,9 +1757,13 @@ |
| 2900 | :param key_id: A key ID, e.g. BB7576AC |
| 2901 | :param package_id: |
| 2902 | A PackageID for the package that the user is trying to install |
| 2903 | + (ignored) |
| 2904 | """ |
| 2905 | self.role = pk_enums.ROLE_INSTALL_SIGNATURE |
| 2906 | - GObject.idle_add(self._fail_not_implemented) |
| 2907 | + kwargs = {"sig_type": sig_type, |
| 2908 | + "key_id": key_id, |
| 2909 | + "package_id": package_id} |
| 2910 | + return self._run_query(kwargs, sender) |
| 2911 | |
| 2912 | @dbus.service.method(PACKAGEKIT_TRANS_DBUS_INTERFACE, |
| 2913 | in_signature="sss", out_signature="", |
| 2914 | @@ -1776,18 +1782,21 @@ |
| 2915 | self.role = pk_enums.ROLE_REPO_SET_DATA |
| 2916 | GObject.idle_add(self._fail_not_implemented) |
| 2917 | |
| 2918 | - @dbus.service.method(PACKAGEKIT_TRANS_DBUS_INTERFACE, |
| 2919 | - in_signature="sb", out_signature="", |
| 2920 | - sender_keyword="sender") |
| 2921 | + @dbus_deferred_method(PACKAGEKIT_TRANS_DBUS_INTERFACE, |
| 2922 | + in_signature="sb", out_signature="", |
| 2923 | + sender_keyword="sender") |
| 2924 | def RepoEnable(self, repo_id, enabled, sender): |
| 2925 | """This method enables the repository specified. |
| 2926 | |
| 2927 | :param repo_id: |
| 2928 | - A repository identifier, e.g. fedora-development-debuginfo |
| 2929 | + A repository identifier, e.g. fedora-development-debuginfo or an |
| 2930 | + apt source ("deb http://... unstable main") |
| 2931 | :param enabled: true if enabled, false if disabled. |
| 2932 | """ |
| 2933 | self.role = pk_enums.ROLE_REPO_ENABLE |
| 2934 | - GObject.idle_add(self._fail_not_implemented) |
| 2935 | + kwargs = {"repo_id": repo_id, |
| 2936 | + "enabled": enabled} |
| 2937 | + return self._run_query(kwargs, sender) |
| 2938 | |
| 2939 | @dbus.service.method(PACKAGEKIT_TRANS_DBUS_INTERFACE, |
| 2940 | in_signature="s", out_signature="", |
| 2941 | @@ -1889,7 +1898,7 @@ |
| 2942 | # HELPERS |
| 2943 | |
| 2944 | def _fail_not_implemented(self): |
| 2945 | - self.ErrorCode(pk_enums.ERROR_NOT_SUPPORTED, "") |
| 2946 | + self.ErrorCode(pk_enums.ERROR_NOT_SUPPORTED, "Unimplemented method") |
| 2947 | self.exit = pk_enums.EXIT_FAILED |
| 2948 | return False |
| 2949 | |
| 2950 | @@ -1941,7 +1950,7 @@ |
| 2951 | return trans |
| 2952 | |
| 2953 | |
| 2954 | -class PackageKitWorker(aptdaemon.worker.AptWorker): |
| 2955 | +class PackageKitWorker(worker.AptWorker): |
| 2956 | |
| 2957 | _plugins = None |
| 2958 | |
| 2959 | @@ -1981,6 +1990,10 @@ |
| 2960 | self.download_packages(trans, **trans.kwargs) |
| 2961 | elif trans.pktrans.role == pk_enums.ROLE_WHAT_PROVIDES: |
| 2962 | self.what_provides(trans, **trans.kwargs) |
| 2963 | + elif trans.pktrans.role == pk_enums.ROLE_REPO_ENABLE: |
| 2964 | + self.repo_enable(trans, **trans.kwargs) |
| 2965 | + elif trans.pktrans.role == pk_enums.ROLE_INSTALL_SIGNATURE: |
| 2966 | + self.install_signature(trans, **trans.kwargs) |
| 2967 | else: |
| 2968 | raise TransactionFailed(aptd_enums.ERROR_UNKNOWN, |
| 2969 | "Role %s isn't supported", |
| 2970 | @@ -2063,7 +2076,7 @@ |
| 2971 | pklog.info("Searching for package name: %s" % values) |
| 2972 | trans.progress = 101 |
| 2973 | |
| 2974 | - for pkg_name in self._cache.keys(): |
| 2975 | + for pkg_name in list(self._cache.keys()): |
| 2976 | if matches(values, pkg_name): |
| 2977 | self._emit_all_visible_pkg_versions(trans, filters, |
| 2978 | self._cache[pkg_name]) |
| 2979 | @@ -2082,7 +2095,7 @@ |
| 2980 | db = xapian.Database(XAPIAN_DB) |
| 2981 | parser = xapian.QueryParser() |
| 2982 | parser.set_default_op(xapian.Query.OP_AND) |
| 2983 | - query = parser.parse_query(u" ".join(values), search_flags) |
| 2984 | + query = parser.parse_query(" ".join(values), search_flags) |
| 2985 | enquire = xapian.Enquire(db) |
| 2986 | enquire.set_query(query) |
| 2987 | matches = enquire.get_mset(0, 1000) |
| 2988 | @@ -2212,8 +2225,7 @@ |
| 2989 | """ |
| 2990 | Create a list of urls pointing to cves referred in the changelog |
| 2991 | """ |
| 2992 | - return map(lambda c: HREF_CVE % c, |
| 2993 | - re.findall(MATCH_CVE, changelog, re.MULTILINE)) |
| 2994 | + return [HREF_CVE % c for c in re.findall(MATCH_CVE, changelog, re.MULTILINE)] |
| 2995 | |
| 2996 | pklog.info("Get update details of %s" % package_ids) |
| 2997 | trans.progress = 0 |
| 2998 | @@ -2239,7 +2251,7 @@ |
| 2999 | obsoletes = "" |
| 3000 | vendor_url = "" |
| 3001 | restart = "none" |
| 3002 | - update_text = u"" |
| 3003 | + update_text = "" |
| 3004 | state = "" |
| 3005 | issued = "" |
| 3006 | updated = "" |
| 3007 | @@ -2271,7 +2283,7 @@ |
| 3008 | changelog_raw = pkg.get_changelog() |
| 3009 | # The internal download error string of python-apt ist not |
| 3010 | # provided as unicode object |
| 3011 | - if not isinstance(changelog_raw, unicode): |
| 3012 | + if not isinstance(changelog_raw, str): |
| 3013 | changelog_raw = changelog_raw.decode("UTF-8") |
| 3014 | # Cache the fetched changelog |
| 3015 | if not os.path.exists(changelog_dir): |
| 3016 | @@ -2286,24 +2298,24 @@ |
| 3017 | finally: |
| 3018 | changelog_file.close() |
| 3019 | # Convert the changelog to markdown syntax |
| 3020 | - changelog = u"" |
| 3021 | + changelog = "" |
| 3022 | for line in changelog_raw.split("\n"): |
| 3023 | if line == "": |
| 3024 | changelog += " \n" |
| 3025 | else: |
| 3026 | - changelog += u" %s \n" % line |
| 3027 | + changelog += " %s \n" % line |
| 3028 | if line.startswith(pkg.candidate.source_name): |
| 3029 | match = re.match(r"(?P<source>.+) \((?P<version>.*)\) " |
| 3030 | "(?P<dist>.+); urgency=(?P<urgency>.+)", |
| 3031 | line) |
| 3032 | - update_text += u"%s\n%s\n\n" % (match.group("version"), |
| 3033 | + update_text += "%s\n%s\n\n" % (match.group("version"), |
| 3034 | "=" * \ |
| 3035 | len(match.group("version"))) |
| 3036 | elif line.startswith(" "): |
| 3037 | - update_text += u" %s \n" % line |
| 3038 | + update_text += " %s \n" % line |
| 3039 | elif line.startswith(" --"): |
| 3040 | #FIXME: Add %z for the time zone - requires Python 2.6 |
| 3041 | - update_text += u" \n" |
| 3042 | + update_text += " \n" |
| 3043 | match = re.match("^ -- (?P<maintainer>.+) (?P<mail><.+>) " |
| 3044 | "(?P<date>.+) (?P<offset>[-\+][0-9]+)$", |
| 3045 | line) |
| 3046 | @@ -2403,7 +2415,7 @@ |
| 3047 | if not self._is_package_visible(pkg, filters): |
| 3048 | return |
| 3049 | else: |
| 3050 | - summary = u"" |
| 3051 | + summary = "" |
| 3052 | if base_dependency.relation: |
| 3053 | version = "%s%s" % (base_dependency.relation, |
| 3054 | base_dependency.version) |
| 3055 | @@ -2557,10 +2569,7 @@ |
| 3056 | trans.emit_files(id, files) |
| 3057 | |
| 3058 | def what_provides(self, trans, filters, type, values): |
| 3059 | - """Emit all dependencies of the given package ids. |
| 3060 | - |
| 3061 | - Doesn't support recursive dependency resolution. |
| 3062 | - """ |
| 3063 | + """Emit all packages which provide the given type and search value.""" |
| 3064 | self._init_plugins() |
| 3065 | |
| 3066 | supported_type = False |
| 3067 | @@ -2581,6 +2590,34 @@ |
| 3068 | raise TransactionFailed(aptd_enums.ERROR_NOT_SUPPORTED, |
| 3069 | "Query type '%s' is not supported" % type) |
| 3070 | |
| 3071 | + def repo_enable(self, trans, repo_id, enabled): |
| 3072 | + """Enable or disable a repository.""" |
| 3073 | + |
| 3074 | + if not enabled: |
| 3075 | + raise TransactionFailed(aptd_enums.ERROR_NOT_SUPPORTED, |
| 3076 | + "Disabling repositories is not implemented") |
| 3077 | + |
| 3078 | + fields = repo_id.split() |
| 3079 | + if len(fields) < 3 or fields[0] not in ('deb', 'deb-src'): |
| 3080 | + raise TransactionFailed(aptd_enums.ERROR_NOT_SUPPORTED, |
| 3081 | + "Unknown repository ID format: %s" % repo_id) |
| 3082 | + |
| 3083 | + self.add_repository(trans, fields[0], fields[1], fields[2], |
| 3084 | + fields[3:], '', None) |
| 3085 | + |
| 3086 | + def install_signature(self, trans, sig_type, key_id, package_id): |
| 3087 | + """Install an archive key.""" |
| 3088 | + if sig_type != "gpg": |
| 3089 | + raise TransactionFailed(aptd_enums.ERROR_NOT_SUPPORTED, |
| 3090 | + "Type %s is not supported" % sig_type) |
| 3091 | + try: |
| 3092 | + keyserver = os.environ["APTDAEMON_KEYSERVER"] |
| 3093 | + except KeyError: |
| 3094 | + if platform.dist()[0] == "Ubuntu": |
| 3095 | + keyserver = "hkp://keyserver.ubuntu.com:80" |
| 3096 | + else: |
| 3097 | + keyserver = "hkp://keys.gnupg.net" |
| 3098 | + self.add_vendor_key_from_keyserver(trans, key_id, keyserver) |
| 3099 | |
| 3100 | # Helpers |
| 3101 | |
| 3102 | @@ -2662,7 +2699,7 @@ |
| 3103 | for name_raw in pkgs: |
| 3104 | #FIXME: Python-apt doesn't allow unicode as key. See #542965 |
| 3105 | name = str(name_raw) |
| 3106 | - if self._cache.has_key(name) and \ |
| 3107 | + if name in self._cache and \ |
| 3108 | self._is_package_visible(self._cache[name], filters): |
| 3109 | self._emit_package(trans, self._cache[name], info) |
| 3110 | |
| 3111 | @@ -2815,7 +2852,7 @@ |
| 3112 | Return the packagekit group corresponding to the package's section |
| 3113 | """ |
| 3114 | section = pkg.section.split("/")[-1] |
| 3115 | - if SECTION_GROUP_MAP.has_key(section): |
| 3116 | + if section in SECTION_GROUP_MAP: |
| 3117 | return SECTION_GROUP_MAP[section] |
| 3118 | else: |
| 3119 | pklog.debug("Unkown package section %s of %s" % (pkg.section, |
| 3120 | @@ -2855,9 +2892,9 @@ |
| 3121 | def _apply_changes(self, trans, fetch_range=(15, 50), |
| 3122 | install_range=(50, 90)): |
| 3123 | """Apply changes and emit RequireRestart accordingly.""" |
| 3124 | - aptdaemon.worker.AptWorker._apply_changes(self, trans, |
| 3125 | - fetch_range, |
| 3126 | - install_range) |
| 3127 | + worker.AptWorker._apply_changes(self, trans, |
| 3128 | + fetch_range, |
| 3129 | + install_range) |
| 3130 | if (hasattr(trans, "pktrans") and |
| 3131 | (trans.role == aptd_enums.ROLE_UPGRADE_SYSTEM or |
| 3132 | trans.packages[aptd_enums.PKGS_UPGRADE] or |
| 3133 | @@ -2923,8 +2960,7 @@ |
| 3134 | e.g. xterm:i368=235; to xterm;235;i386;installed |
| 3135 | """ |
| 3136 | #FIXME add arch support |
| 3137 | - name, version, release = \ |
| 3138 | - aptdaemon.worker.AptWorker._split_package_id(pk_id) |
| 3139 | + name, version, release = worker.AptWorker._split_package_id(pk_id) |
| 3140 | try: |
| 3141 | name, arch = name.split(":", 1) |
| 3142 | except ValueError: |
| 3143 | |
| 3144 | === added file 'aptdaemon/pkenums.py' |
| 3145 | --- aptdaemon/pkenums.py 1970-01-01 00:00:00 +0000 |
| 3146 | +++ aptdaemon/pkenums.py 2012-06-13 16:29:18 +0000 |
| 3147 | @@ -0,0 +1,326 @@ |
| 3148 | +# This file was autogenerated from ../../../lib/packagekit-glib2/pk-enum.c by enum-converter.py |
| 3149 | + |
| 3150 | +class PackageKitEnum: |
| 3151 | + exit = ( "unknown", "success", "failed", "cancelled", "key-required", "eula-required", "media-change-required", "killed", "need-untrusted", "cancelled-priority", "skip-transaction", "repair-required", ) |
| 3152 | + status = ( "unknown", "wait", "setup", "running", "query", "info", "refresh-cache", "remove", "download", "install", "update", "cleanup", "obsolete", "dep-resolve", "sig-check", "rollback", "test-commit", "commit", "request", "finished", "cancel", "download-repository", "download-packagelist", "download-filelist", "download-changelog", "download-group", "download-updateinfo", "repackaging", "loading-cache", "scan-applications", "generate-package-list", "waiting-for-lock", "waiting-for-auth", "scan-process-list", "check-executable-files", "check-libraries", "copy-files", ) |
| 3153 | + role = ( "unknown", "cancel", "get-depends", "get-details", "get-files", "get-packages", "get-repo-list", "get-requires", "get-update-detail", "get-updates", "install-files", "install-packages", "install-signature", "refresh-cache", "remove-packages", "repo-enable", "repo-set-data", "resolve", "rollback", "search-details", "search-file", "search-group", "search-name", "update-packages", "update-system", "what-provides", "accept-eula", "download-packages", "get-distro-upgrades", "get-categories", "get-old-transactions", "simulate-install-files", "simulate-install-packages", "simulate-remove-packages", "simulate-update-packages", "upgrade-system", "repair-system", "simulate-repair-system", ) |
| 3154 | + error = ( "unknown", "out-of-memory", "no-cache", "no-network", "not-supported", "internal-error", "gpg-failure", "filter-invalid", "package-id-invalid", "transaction-error", "transaction-cancelled", "package-not-installed", "package-not-found", "package-already-installed", "package-download-failed", "group-not-found", "group-list-invalid", "dep-resolution-failed", "create-thread-failed", "repo-not-found", "cannot-remove-system-package", "process-kill", "failed-initialization", "failed-finalise", "failed-config-parsing", "cannot-cancel", "cannot-get-lock", "no-packages-to-update", "cannot-write-repo-config", "local-install-failed", "bad-gpg-signature", "missing-gpg-signature", "cannot-install-source-package", "repo-configuration-error", "no-license-agreement", "file-conflicts", "package-conflicts", "repo-not-available", "invalid-package-file", "package-install-blocked", "package-corrupt", "all-packages-already-installed", "file-not-found", "no-more-mirrors-to-try", "no-distro-upgrade-data", "incompatible-architecture", "no-space-on-device", "media-change-required", "not-authorized", "update-not-found", "cannot-install-repo-unsigned", "cannot-update-repo-unsigned", "cannot-get-filelist", "cannot-get-requires", "cannot-disable-repository", "restricted-download", "package-failed-to-configure", "package-failed-to-build", "package-failed-to-install", "package-failed-to-remove", "failed-due-to-running-process", "package-database-changed", "provide-type-not-supported", "install-root-invalid", "cannot-fetch-sources", "cancelled-priority", "unfinished-transaction", ) |
| 3155 | + restart = ( "unknown", "none", "system", "session", "application", "security-system", "security-session", ) |
| 3156 | + message = ( "unknown", "broken-mirror", "connection-refused", "parameter-invalid", "priority-invalid", "backend-error", "daemon-error", "cache-being-rebuilt", "untrusted-package", "newer-package-exists", "could-not-find-package", "config-files-changed", "package-already-installed", "autoremove-ignored", "repo-metadata-download-failed", "repo-for-developers-only", "other-updates-held-back", ) |
| 3157 | + filter = ( "unknown", "none", "installed", "~installed", "devel", "~devel", "gui", "~gui", "free", "~free", "visible", "~visible", "supported", "~supported", "basename", "~basename", "newest", "~newest", "arch", "~arch", "source", "~source", "collections", "~collections", "application", "~application", ) |
| 3158 | + group = ( "unknown", "accessibility", "accessories", "education", "games", "graphics", "internet", "office", "other", "programming", "multimedia", "system", "desktop-gnome", "desktop-kde", "desktop-xfce", "desktop-other", "publishing", "servers", "fonts", "admin-tools", "legacy", "localization", "virtualization", "power-management", "security", "communication", "network", "maps", "repos", "science", "documentation", "electronics", "collections", "vendor", "newest", ) |
| 3159 | + update_state = ( "unknown", "testing", "unstable", "stable", ) |
| 3160 | + info = ( "unknown", "installed", "available", "low", "normal", "important", "security", "bugfix", "enhancement", "blocked", "downloading", "updating", "installing", "removing", "cleanup", "obsoleting", "collection-installed", "collection-available", "finished", "reinstalling", "downgrading", "preparing", "decompressing", "untrusted", "trusted", ) |
| 3161 | + sig_type = ( "unknown", "gpg", ) |
| 3162 | + upgrade = ( "unknown", "stable", "unstable", ) |
| 3163 | + provides = ( "unknown", "any", "modalias", "codec", "mimetype", "driver", "font", "postscript-driver", "plasma-service", "shared-library", "python-module", "language-support", ) |
| 3164 | + network = ( "unknown", "offline", "online", "wired", "wifi", "mobile", ) |
| 3165 | + media_type = ( "unknown", "cd", "dvd", "disc", ) |
| 3166 | + authorize_type = ( "unknown", "yes", "no", "interactive", ) |
| 3167 | + upgrade_kind = ( "unknown", "minimal", "default", "complete", ) |
| 3168 | + |
| 3169 | +# Constants |
| 3170 | + |
| 3171 | +AUTHORIZE_INTERACTIVE = "interactive" |
| 3172 | +AUTHORIZE_NO = "no" |
| 3173 | +AUTHORIZE_UNKNOWN = "unknown" |
| 3174 | +AUTHORIZE_YES = "yes" |
| 3175 | +DISTRO_UPGRADE_STABLE = "stable" |
| 3176 | +DISTRO_UPGRADE_UNKNOWN = "unknown" |
| 3177 | +DISTRO_UPGRADE_UNSTABLE = "unstable" |
| 3178 | +ERROR_ALL_PACKAGES_ALREADY_INSTALLED = "all-packages-already-installed" |
| 3179 | +ERROR_BAD_GPG_SIGNATURE = "bad-gpg-signature" |
| 3180 | +ERROR_CANCELLED_PRIORITY = "cancelled-priority" |
| 3181 | +ERROR_CANNOT_CANCEL = "cannot-cancel" |
| 3182 | +ERROR_CANNOT_DISABLE_REPOSITORY = "cannot-disable-repository" |
| 3183 | +ERROR_CANNOT_FETCH_SOURCES = "cannot-fetch-sources" |
| 3184 | +ERROR_CANNOT_GET_FILELIST = "cannot-get-filelist" |
| 3185 | +ERROR_CANNOT_GET_LOCK = "cannot-get-lock" |
| 3186 | +ERROR_CANNOT_GET_REQUIRES = "cannot-get-requires" |
| 3187 | +ERROR_CANNOT_INSTALL_REPO_UNSIGNED = "cannot-install-repo-unsigned" |
| 3188 | +ERROR_CANNOT_INSTALL_SOURCE_PACKAGE = "cannot-install-source-package" |
| 3189 | +ERROR_CANNOT_REMOVE_SYSTEM_PACKAGE = "cannot-remove-system-package" |
| 3190 | +ERROR_CANNOT_UPDATE_REPO_UNSIGNED = "cannot-update-repo-unsigned" |
| 3191 | +ERROR_CANNOT_WRITE_REPO_CONFIG = "cannot-write-repo-config" |
| 3192 | +ERROR_CREATE_THREAD_FAILED = "create-thread-failed" |
| 3193 | +ERROR_DEP_RESOLUTION_FAILED = "dep-resolution-failed" |
| 3194 | +ERROR_FAILED_CONFIG_PARSING = "failed-config-parsing" |
| 3195 | +ERROR_FAILED_FINALISE = "failed-finalise" |
| 3196 | +ERROR_FAILED_INITIALIZATION = "failed-initialization" |
| 3197 | +ERROR_FILE_CONFLICTS = "file-conflicts" |
| 3198 | +ERROR_FILE_NOT_FOUND = "file-not-found" |
| 3199 | +ERROR_FILTER_INVALID = "filter-invalid" |
| 3200 | +ERROR_GPG_FAILURE = "gpg-failure" |
| 3201 | +ERROR_GROUP_LIST_INVALID = "group-list-invalid" |
| 3202 | +ERROR_GROUP_NOT_FOUND = "group-not-found" |
| 3203 | +ERROR_INCOMPATIBLE_ARCHITECTURE = "incompatible-architecture" |
| 3204 | +ERROR_INSTALL_ROOT_INVALID = "install-root-invalid" |
| 3205 | +ERROR_INTERNAL_ERROR = "internal-error" |
| 3206 | +ERROR_INVALID_PACKAGE_FILE = "invalid-package-file" |
| 3207 | +ERROR_LOCAL_INSTALL_FAILED = "local-install-failed" |
| 3208 | +ERROR_MEDIA_CHANGE_REQUIRED = "media-change-required" |
| 3209 | +ERROR_MISSING_GPG_SIGNATURE = "missing-gpg-signature" |
| 3210 | +ERROR_NOT_AUTHORIZED = "not-authorized" |
| 3211 | +ERROR_NOT_SUPPORTED = "not-supported" |
| 3212 | +ERROR_NO_CACHE = "no-cache" |
| 3213 | +ERROR_NO_DISTRO_UPGRADE_DATA = "no-distro-upgrade-data" |
| 3214 | +ERROR_NO_LICENSE_AGREEMENT = "no-license-agreement" |
| 3215 | +ERROR_NO_MORE_MIRRORS_TO_TRY = "no-more-mirrors-to-try" |
| 3216 | +ERROR_NO_NETWORK = "no-network" |
| 3217 | +ERROR_NO_PACKAGES_TO_UPDATE = "no-packages-to-update" |
| 3218 | +ERROR_NO_SPACE_ON_DEVICE = "no-space-on-device" |
| 3219 | +ERROR_OOM = "out-of-memory" |
| 3220 | +ERROR_PACKAGE_ALREADY_INSTALLED = "package-already-installed" |
| 3221 | +ERROR_PACKAGE_CONFLICTS = "package-conflicts" |
| 3222 | +ERROR_PACKAGE_CORRUPT = "package-corrupt" |
| 3223 | +ERROR_PACKAGE_DATABASE_CHANGED = "package-database-changed" |
| 3224 | +ERROR_PACKAGE_DOWNLOAD_FAILED = "package-download-failed" |
| 3225 | +ERROR_PACKAGE_FAILED_TO_BUILD = "package-failed-to-build" |
| 3226 | +ERROR_PACKAGE_FAILED_TO_CONFIGURE = "package-failed-to-configure" |
| 3227 | +ERROR_PACKAGE_FAILED_TO_INSTALL = "package-failed-to-install" |
| 3228 | +ERROR_PACKAGE_FAILED_TO_REMOVE = "package-failed-to-remove" |
| 3229 | +ERROR_PACKAGE_ID_INVALID = "package-id-invalid" |
| 3230 | +ERROR_PACKAGE_INSTALL_BLOCKED = "package-install-blocked" |
| 3231 | +ERROR_PACKAGE_NOT_FOUND = "package-not-found" |
| 3232 | +ERROR_PACKAGE_NOT_INSTALLED = "package-not-installed" |
| 3233 | +ERROR_PROCESS_KILL = "process-kill" |
| 3234 | +ERROR_PROVIDE_TYPE_NOT_SUPPORTED = "provide-type-not-supported" |
| 3235 | +ERROR_REPO_CONFIGURATION_ERROR = "repo-configuration-error" |
| 3236 | +ERROR_REPO_NOT_AVAILABLE = "repo-not-available" |
| 3237 | +ERROR_REPO_NOT_FOUND = "repo-not-found" |
| 3238 | +ERROR_RESTRICTED_DOWNLOAD = "restricted-download" |
| 3239 | +ERROR_TRANSACTION_CANCELLED = "transaction-cancelled" |
| 3240 | +ERROR_TRANSACTION_ERROR = "transaction-error" |
| 3241 | +ERROR_UNFINISHED_TRANSACTION = "unfinished-transaction" |
| 3242 | +ERROR_UNKNOWN = "unknown" |
| 3243 | +ERROR_UPDATE_FAILED_DUE_TO_RUNNING_PROCESS = "failed-due-to-running-process" |
| 3244 | +ERROR_UPDATE_NOT_FOUND = "update-not-found" |
| 3245 | +EXIT_CANCELLED = "cancelled" |
| 3246 | +EXIT_CANCELLED_PRIORITY = "cancelled-priority" |
| 3247 | +EXIT_EULA_REQUIRED = "eula-required" |
| 3248 | +EXIT_FAILED = "failed" |
| 3249 | +EXIT_KEY_REQUIRED = "key-required" |
| 3250 | +EXIT_KILLED = "killed" |
| 3251 | +EXIT_MEDIA_CHANGE_REQUIRED = "media-change-required" |
| 3252 | +EXIT_NEED_UNTRUSTED = "need-untrusted" |
| 3253 | +EXIT_REPAIR_REQUIRED = "repair-required" |
| 3254 | +EXIT_SKIP_TRANSACTION = "skip-transaction" |
| 3255 | +EXIT_SUCCESS = "success" |
| 3256 | +EXIT_UNKNOWN = "unknown" |
| 3257 | +FILTER_APPLICATION = "application" |
| 3258 | +FILTER_ARCH = "arch" |
| 3259 | +FILTER_BASENAME = "basename" |
| 3260 | +FILTER_COLLECTIONS = "collections" |
| 3261 | +FILTER_DEVELOPMENT = "devel" |
| 3262 | +FILTER_FREE = "free" |
| 3263 | +FILTER_GUI = "gui" |
| 3264 | +FILTER_INSTALLED = "installed" |
| 3265 | +FILTER_NEWEST = "newest" |
| 3266 | +FILTER_NONE = "none" |
| 3267 | +FILTER_NOT_APPLICATION = "~application" |
| 3268 | +FILTER_NOT_ARCH = "~arch" |
| 3269 | +FILTER_NOT_BASENAME = "~basename" |
| 3270 | +FILTER_NOT_COLLECTIONS = "~collections" |
| 3271 | +FILTER_NOT_DEVELOPMENT = "~devel" |
| 3272 | +FILTER_NOT_FREE = "~free" |
| 3273 | +FILTER_NOT_GUI = "~gui" |
| 3274 | +FILTER_NOT_INSTALLED = "~installed" |
| 3275 | +FILTER_NOT_NEWEST = "~newest" |
| 3276 | +FILTER_NOT_SOURCE = "~source" |
| 3277 | +FILTER_NOT_SUPPORTED = "~supported" |
| 3278 | +FILTER_NOT_VISIBLE = "~visible" |
| 3279 | +FILTER_SOURCE = "source" |
| 3280 | +FILTER_SUPPORTED = "supported" |
| 3281 | +FILTER_UNKNOWN = "unknown" |
| 3282 | +FILTER_VISIBLE = "visible" |
| 3283 | +GROUP_ACCESSIBILITY = "accessibility" |
| 3284 | +GROUP_ACCESSORIES = "accessories" |
| 3285 | +GROUP_ADMIN_TOOLS = "admin-tools" |
| 3286 | +GROUP_COLLECTIONS = "collections" |
| 3287 | +GROUP_COMMUNICATION = "communication" |
| 3288 | +GROUP_DESKTOP_GNOME = "desktop-gnome" |
| 3289 | +GROUP_DESKTOP_KDE = "desktop-kde" |
| 3290 | +GROUP_DESKTOP_OTHER = "desktop-other" |
| 3291 | +GROUP_DESKTOP_XFCE = "desktop-xfce" |
| 3292 | +GROUP_DOCUMENTATION = "documentation" |
| 3293 | +GROUP_EDUCATION = "education" |
| 3294 | +GROUP_ELECTRONICS = "electronics" |
| 3295 | +GROUP_FONTS = "fonts" |
| 3296 | +GROUP_GAMES = "games" |
| 3297 | +GROUP_GRAPHICS = "graphics" |
| 3298 | +GROUP_INTERNET = "internet" |
| 3299 | +GROUP_LEGACY = "legacy" |
| 3300 | +GROUP_LOCALIZATION = "localization" |
| 3301 | +GROUP_MAPS = "maps" |
| 3302 | +GROUP_MULTIMEDIA = "multimedia" |
| 3303 | +GROUP_NETWORK = "network" |
| 3304 | +GROUP_NEWEST = "newest" |
| 3305 | +GROUP_OFFICE = "office" |
| 3306 | +GROUP_OTHER = "other" |
| 3307 | +GROUP_POWER_MANAGEMENT = "power-management" |
| 3308 | +GROUP_PROGRAMMING = "programming" |
| 3309 | +GROUP_PUBLISHING = "publishing" |
| 3310 | +GROUP_REPOS = "repos" |
| 3311 | +GROUP_SCIENCE = "science" |
| 3312 | +GROUP_SECURITY = "security" |
| 3313 | +GROUP_SERVERS = "servers" |
| 3314 | +GROUP_SYSTEM = "system" |
| 3315 | +GROUP_UNKNOWN = "unknown" |
| 3316 | +GROUP_VENDOR = "vendor" |
| 3317 | +GROUP_VIRTUALIZATION = "virtualization" |
| 3318 | +INFO_AVAILABLE = "available" |
| 3319 | +INFO_BLOCKED = "blocked" |
| 3320 | +INFO_BUGFIX = "bugfix" |
| 3321 | +INFO_CLEANUP = "cleanup" |
| 3322 | +INFO_COLLECTION_AVAILABLE = "collection-available" |
| 3323 | +INFO_COLLECTION_INSTALLED = "collection-installed" |
| 3324 | +INFO_DECOMPRESSING = "decompressing" |
| 3325 | +INFO_DOWNGRADING = "downgrading" |
| 3326 | +INFO_DOWNLOADING = "downloading" |
| 3327 | +INFO_ENHANCEMENT = "enhancement" |
| 3328 | +INFO_FINISHED = "finished" |
| 3329 | +INFO_IMPORTANT = "important" |
| 3330 | +INFO_INSTALLED = "installed" |
| 3331 | +INFO_INSTALLING = "installing" |
| 3332 | +INFO_LOW = "low" |
| 3333 | +INFO_NORMAL = "normal" |
| 3334 | +INFO_OBSOLETING = "obsoleting" |
| 3335 | +INFO_PREPARING = "preparing" |
| 3336 | +INFO_REINSTALLING = "reinstalling" |
| 3337 | +INFO_REMOVING = "removing" |
| 3338 | +INFO_SECURITY = "security" |
| 3339 | +INFO_TRUSTED = "trusted" |
| 3340 | +INFO_UNKNOWN = "unknown" |
| 3341 | +INFO_UNTRUSTED = "untrusted" |
| 3342 | +INFO_UPDATING = "updating" |
| 3343 | +MEDIA_TYPE_CD = "cd" |
| 3344 | +MEDIA_TYPE_DISC = "disc" |
| 3345 | +MEDIA_TYPE_DVD = "dvd" |
| 3346 | +MEDIA_TYPE_UNKNOWN = "unknown" |
| 3347 | +MESSAGE_AUTOREMOVE_IGNORED = "autoremove-ignored" |
| 3348 | +MESSAGE_BACKEND_ERROR = "backend-error" |
| 3349 | +MESSAGE_BROKEN_MIRROR = "broken-mirror" |
| 3350 | +MESSAGE_CACHE_BEING_REBUILT = "cache-being-rebuilt" |
| 3351 | +MESSAGE_CONFIG_FILES_CHANGED = "config-files-changed" |
| 3352 | +MESSAGE_CONNECTION_REFUSED = "connection-refused" |
| 3353 | +MESSAGE_COULD_NOT_FIND_PACKAGE = "could-not-find-package" |
| 3354 | +MESSAGE_DAEMON_ERROR = "daemon-error" |
| 3355 | +MESSAGE_NEWER_PACKAGE_EXISTS = "newer-package-exists" |
| 3356 | +MESSAGE_OTHER_UPDATES_HELD_BACK = "other-updates-held-back" |
| 3357 | +MESSAGE_PACKAGE_ALREADY_INSTALLED = "package-already-installed" |
| 3358 | +MESSAGE_PARAMETER_INVALID = "parameter-invalid" |
| 3359 | +MESSAGE_PRIORITY_INVALID = "priority-invalid" |
| 3360 | +MESSAGE_REPO_FOR_DEVELOPERS_ONLY = "repo-for-developers-only" |
| 3361 | +MESSAGE_REPO_METADATA_DOWNLOAD_FAILED = "repo-metadata-download-failed" |
| 3362 | +MESSAGE_UNKNOWN = "unknown" |
| 3363 | +MESSAGE_UNTRUSTED_PACKAGE = "untrusted-package" |
| 3364 | +NETWORK_MOBILE = "mobile" |
| 3365 | +NETWORK_OFFLINE = "offline" |
| 3366 | +NETWORK_ONLINE = "online" |
| 3367 | +NETWORK_UNKNOWN = "unknown" |
| 3368 | +NETWORK_WIFI = "wifi" |
| 3369 | +NETWORK_WIRED = "wired" |
| 3370 | +PROVIDES_ANY = "any" |
| 3371 | +PROVIDES_CODEC = "codec" |
| 3372 | +PROVIDES_FONT = "font" |
| 3373 | +PROVIDES_HARDWARE_DRIVER = "driver" |
| 3374 | +PROVIDES_LANGUAGE_SUPPORT = "language-support" |
| 3375 | +PROVIDES_MIMETYPE = "mimetype" |
| 3376 | +PROVIDES_MODALIAS = "modalias" |
| 3377 | +PROVIDES_PLASMA_SERVICE = "plasma-service" |
| 3378 | +PROVIDES_POSTSCRIPT_DRIVER = "postscript-driver" |
| 3379 | +PROVIDES_PYTHON = "python-module" |
| 3380 | +PROVIDES_SHARED_LIB = "shared-library" |
| 3381 | +PROVIDES_UNKNOWN = "unknown" |
| 3382 | +RESTART_APPLICATION = "application" |
| 3383 | +RESTART_NONE = "none" |
| 3384 | +RESTART_SECURITY_SESSION = "security-session" |
| 3385 | +RESTART_SECURITY_SYSTEM = "security-system" |
| 3386 | +RESTART_SESSION = "session" |
| 3387 | +RESTART_SYSTEM = "system" |
| 3388 | +RESTART_UNKNOWN = "unknown" |
| 3389 | +ROLE_ACCEPT_EULA = "accept-eula" |
| 3390 | +ROLE_CANCEL = "cancel" |
| 3391 | +ROLE_DOWNLOAD_PACKAGES = "download-packages" |
| 3392 | +ROLE_GET_CATEGORIES = "get-categories" |
| 3393 | +ROLE_GET_DEPENDS = "get-depends" |
| 3394 | +ROLE_GET_DETAILS = "get-details" |
| 3395 | +ROLE_GET_DISTRO_UPGRADES = "get-distro-upgrades" |
| 3396 | +ROLE_GET_FILES = "get-files" |
| 3397 | +ROLE_GET_OLD_TRANSACTIONS = "get-old-transactions" |
| 3398 | +ROLE_GET_PACKAGES = "get-packages" |
| 3399 | +ROLE_GET_REPO_LIST = "get-repo-list" |
| 3400 | +ROLE_GET_REQUIRES = "get-requires" |
| 3401 | +ROLE_GET_UPDATES = "get-updates" |
| 3402 | +ROLE_GET_UPDATE_DETAIL = "get-update-detail" |
| 3403 | +ROLE_INSTALL_FILES = "install-files" |
| 3404 | +ROLE_INSTALL_PACKAGES = "install-packages" |
| 3405 | +ROLE_INSTALL_SIGNATURE = "install-signature" |
| 3406 | +ROLE_REFRESH_CACHE = "refresh-cache" |
| 3407 | +ROLE_REMOVE_PACKAGES = "remove-packages" |
| 3408 | +ROLE_REPAIR_SYSTEM = "repair-system" |
| 3409 | +ROLE_REPO_ENABLE = "repo-enable" |
| 3410 | +ROLE_REPO_SET_DATA = "repo-set-data" |
| 3411 | +ROLE_RESOLVE = "resolve" |
| 3412 | +ROLE_ROLLBACK = "rollback" |
| 3413 | +ROLE_SEARCH_DETAILS = "search-details" |
| 3414 | +ROLE_SEARCH_FILE = "search-file" |
| 3415 | +ROLE_SEARCH_GROUP = "search-group" |
| 3416 | +ROLE_SEARCH_NAME = "search-name" |
| 3417 | +ROLE_SIMULATE_INSTALL_FILES = "simulate-install-files" |
| 3418 | +ROLE_SIMULATE_INSTALL_PACKAGES = "simulate-install-packages" |
| 3419 | +ROLE_SIMULATE_REMOVE_PACKAGES = "simulate-remove-packages" |
| 3420 | +ROLE_SIMULATE_REPAIR_SYSTEM = "simulate-repair-system" |
| 3421 | +ROLE_SIMULATE_UPDATE_PACKAGES = "simulate-update-packages" |
| 3422 | +ROLE_UNKNOWN = "unknown" |
| 3423 | +ROLE_UPDATE_PACKAGES = "update-packages" |
| 3424 | +ROLE_UPDATE_SYSTEM = "update-system" |
| 3425 | +ROLE_UPGRADE_SYSTEM = "upgrade-system" |
| 3426 | +ROLE_WHAT_PROVIDES = "what-provides" |
| 3427 | +SIGTYPE_GPG = "gpg" |
| 3428 | +SIGTYPE_UNKNOWN = "unknown" |
| 3429 | +STATUS_CANCEL = "cancel" |
| 3430 | +STATUS_CHECK_EXECUTABLE_FILES = "check-executable-files" |
| 3431 | +STATUS_CHECK_LIBRARIES = "check-libraries" |
| 3432 | +STATUS_CLEANUP = "cleanup" |
| 3433 | +STATUS_COMMIT = "commit" |
| 3434 | +STATUS_COPY_FILES = "copy-files" |
| 3435 | +STATUS_DEP_RESOLVE = "dep-resolve" |
| 3436 | +STATUS_DOWNLOAD = "download" |
| 3437 | +STATUS_DOWNLOAD_CHANGELOG = "download-changelog" |
| 3438 | +STATUS_DOWNLOAD_FILELIST = "download-filelist" |
| 3439 | +STATUS_DOWNLOAD_GROUP = "download-group" |
| 3440 | +STATUS_DOWNLOAD_PACKAGELIST = "download-packagelist" |
| 3441 | +STATUS_DOWNLOAD_REPOSITORY = "download-repository" |
| 3442 | +STATUS_DOWNLOAD_UPDATEINFO = "download-updateinfo" |
| 3443 | +STATUS_FINISHED = "finished" |
| 3444 | +STATUS_GENERATE_PACKAGE_LIST = "generate-package-list" |
| 3445 | +STATUS_INFO = "info" |
| 3446 | +STATUS_INSTALL = "install" |
| 3447 | +STATUS_LOADING_CACHE = "loading-cache" |
| 3448 | +STATUS_OBSOLETE = "obsolete" |
| 3449 | +STATUS_QUERY = "query" |
| 3450 | +STATUS_REFRESH_CACHE = "refresh-cache" |
| 3451 | +STATUS_REMOVE = "remove" |
| 3452 | +STATUS_REPACKAGING = "repackaging" |
| 3453 | +STATUS_REQUEST = "request" |
| 3454 | +STATUS_ROLLBACK = "rollback" |
| 3455 | +STATUS_RUNNING = "running" |
| 3456 | +STATUS_SCAN_APPLICATIONS = "scan-applications" |
| 3457 | +STATUS_SCAN_PROCESS_LIST = "scan-process-list" |
| 3458 | +STATUS_SETUP = "setup" |
| 3459 | +STATUS_SIG_CHECK = "sig-check" |
| 3460 | +STATUS_TEST_COMMIT = "test-commit" |
| 3461 | +STATUS_UNKNOWN = "unknown" |
| 3462 | +STATUS_UPDATE = "update" |
| 3463 | +STATUS_WAIT = "wait" |
| 3464 | +STATUS_WAITING_FOR_AUTH = "waiting-for-auth" |
| 3465 | +STATUS_WAITING_FOR_LOCK = "waiting-for-lock" |
| 3466 | +UPDATE_STATE_STABLE = "stable" |
| 3467 | +UPDATE_STATE_TESTING = "testing" |
| 3468 | +UPDATE_STATE_UNKNOWN = "unknown" |
| 3469 | +UPDATE_STATE_UNSTABLE = "unstable" |
| 3470 | +UPGRADE_KIND_COMPLETE = "complete" |
| 3471 | +UPGRADE_KIND_DEFAULT = "default" |
| 3472 | +UPGRADE_KIND_MINIMAL = "minimal" |
| 3473 | +UPGRADE_KIND_UNKNOWN = "unknown" |
| 3474 | |
| 3475 | === modified file 'aptdaemon/policykit1.py' |
| 3476 | --- aptdaemon/policykit1.py 2012-02-03 06:37:42 +0000 |
| 3477 | +++ aptdaemon/policykit1.py 2012-06-13 16:29:18 +0000 |
| 3478 | @@ -91,7 +91,8 @@ |
| 3479 | return _check_authorization(subject, action_id, timeout, bus, flags) |
| 3480 | |
| 3481 | def _check_authorization(subject, action_id, timeout, bus, flags=None): |
| 3482 | - def policykit_done((authorized, challenged, auth_details)): |
| 3483 | + def policykit_done(xxx_todo_changeme): |
| 3484 | + (authorized, challenged, auth_details) = xxx_todo_changeme |
| 3485 | if authorized: |
| 3486 | deferred.callback(auth_details) |
| 3487 | elif challenged: |
| 3488 | |
| 3489 | === modified file 'aptdaemon/progress.py' |
| 3490 | --- aptdaemon/progress.py 2012-04-09 20:48:44 +0000 |
| 3491 | +++ aptdaemon/progress.py 2012-06-13 16:29:18 +0000 |
| 3492 | @@ -231,7 +231,7 @@ |
| 3493 | |
| 3494 | def stop(self): |
| 3495 | """Callback at the end of the operation""" |
| 3496 | - self.transaction.progress_details = (0, 0, 0L, 0L, 0.0, 0L) |
| 3497 | + self.transaction.progress_details = (0, 0, 0, 0, 0.0, 0) |
| 3498 | self.transaction.progress = self.progress_end |
| 3499 | self.transaction.cancellable = False |
| 3500 | |
| 3501 | @@ -370,7 +370,16 @@ |
| 3502 | msg |
| 3503 | |
| 3504 | |
| 3505 | -class DaemonInstallProgress(object): |
| 3506 | +class DaemonForkProgress(object): |
| 3507 | + |
| 3508 | + """Forks and executes a given method in the child process while |
| 3509 | + monitoring the output and return state. |
| 3510 | + |
| 3511 | + During the run() call the mainloop will be iterated. |
| 3512 | + |
| 3513 | + Furthermore a status file descriptor is available to communicate |
| 3514 | + with the child process. |
| 3515 | + """ |
| 3516 | |
| 3517 | def __init__(self, transaction, begin=50, end=100): |
| 3518 | self.transaction = transaction |
| 3519 | @@ -385,9 +394,15 @@ |
| 3520 | self.output = "" |
| 3521 | self._line_buffer = "" |
| 3522 | |
| 3523 | + def __enter__(self): |
| 3524 | + self.start_update() |
| 3525 | + return self |
| 3526 | + |
| 3527 | + def __exit__(self, etype, evalue, etb): |
| 3528 | + self.finish_update() |
| 3529 | + |
| 3530 | def start_update(self): |
| 3531 | log.debug("Start update") |
| 3532 | - lock.status_lock.release() |
| 3533 | self.transaction.status = enums.STATUS_COMMITTING |
| 3534 | self.transaction.term_attached = True |
| 3535 | self.last_activity = time.time() |
| 3536 | @@ -396,17 +411,21 @@ |
| 3537 | def finish_update(self): |
| 3538 | """Callback at the end of the operation""" |
| 3539 | self.transaction.term_attached = False |
| 3540 | - lock.wait_for_lock(self.transaction, lock.status_lock) |
| 3541 | - |
| 3542 | - def _child(self, pm): |
| 3543 | - try: |
| 3544 | - res = pm.do_install(self.status_child_fd) |
| 3545 | - except: |
| 3546 | - os._exit(apt_pkg.PackageManager.RESULT_FAILED) |
| 3547 | - else: |
| 3548 | - os._exit(res) |
| 3549 | + |
| 3550 | + def _child(self, method, *args): |
| 3551 | + """Call the given method or function with the |
| 3552 | + corrsponding arguments in the child process. |
| 3553 | + |
| 3554 | + This method should be replace in subclasses. |
| 3555 | + """ |
| 3556 | + method(*args) |
| 3557 | + time.sleep(0.5) |
| 3558 | + os._exit(0) |
| 3559 | |
| 3560 | def run(self, *args, **kwargs): |
| 3561 | + """Setup monitoring, fork and call the self._child() method in the |
| 3562 | + child process with the given arguments. |
| 3563 | + """ |
| 3564 | log.debug("Run") |
| 3565 | terminal_fd = None |
| 3566 | if self.transaction.terminal: |
| 3567 | @@ -477,68 +496,14 @@ |
| 3568 | return False |
| 3569 | |
| 3570 | def _on_status_update(self, source, condition): |
| 3571 | - log.debug("UpdateInterface") |
| 3572 | - status_msg = "" |
| 3573 | - try: |
| 3574 | - while not status_msg.endswith("\n"): |
| 3575 | - self.last_activity = time.time() |
| 3576 | - status_msg += os.read(source, 1) |
| 3577 | - except: |
| 3578 | - return False |
| 3579 | - try: |
| 3580 | - (status, pkg, percent, message_raw) = status_msg.split(":", 3) |
| 3581 | - except ValueError: |
| 3582 | - # silently ignore lines that can't be parsed |
| 3583 | - return True |
| 3584 | - message = message_raw.strip() |
| 3585 | - #print "percent: %s %s" % (pkg, float(percent)/100.0) |
| 3586 | - if status == "pmerror": |
| 3587 | - self._error(pkg, message) |
| 3588 | - elif status == "pmconffile": |
| 3589 | - # we get a string like this: |
| 3590 | - # 'current-conffile' 'new-conffile' useredited distedited |
| 3591 | - match = re.match("\s*\'(.*)\'\s*\'(.*)\'.*", message_raw) |
| 3592 | - if match: |
| 3593 | - new, old = match.group(1), match.group(2) |
| 3594 | - self._conffile(new, old) |
| 3595 | - elif status == "pmstatus": |
| 3596 | - if message.startswith("Installing"): |
| 3597 | - status_enum = enums.PKG_INSTALLING |
| 3598 | - elif message.startswith("Installed"): |
| 3599 | - status_enum = enums.PKG_INSTALLED |
| 3600 | - elif message.startswith("Configuring"): |
| 3601 | - status_enum = enums.PKG_CONFIGURING |
| 3602 | - elif message.startswith("Preparing to configure"): |
| 3603 | - status_enum = enums.PKG_PREPARING_CONFIGURE |
| 3604 | - elif message.startswith("Preparing for removal of"): |
| 3605 | - status_enum = enums.PKG_PREPARING_REMOVE |
| 3606 | - elif message.startswith("Removing"): |
| 3607 | - status_enum = enums.PKG_REMOVING |
| 3608 | - elif message.startswith("Removed"): |
| 3609 | - status_enum = enums.PKG_REMOVED |
| 3610 | - elif message.startswith("Preparing to completely remove"): |
| 3611 | - status_enum = enums.PKG_PREPARING_PURGE |
| 3612 | - elif message.startswith("Completely removing"): |
| 3613 | - status_enum = enums.PKG_PURGING |
| 3614 | - elif message.startswith("Completely removed"): |
| 3615 | - status_enum = enums.PKG_PURGED |
| 3616 | - elif message.startswith("Unpacking"): |
| 3617 | - status_enum = enums.PKG_UNPACKING |
| 3618 | - elif message.startswith("Preparing"): |
| 3619 | - status_enum = enums.PKG_PREPARING_INSTALL |
| 3620 | - elif message.startswith("Noting disappearance of"): |
| 3621 | - status_enum = enums.PKG_DISAPPEARING |
| 3622 | - elif message.startswith("Running"): |
| 3623 | - status_enum = enums.PKG_RUNNING_TRIGGER |
| 3624 | - else: |
| 3625 | - status_enum = enums.PKG_UNKNOWN |
| 3626 | - self._status_changed(pkg, float(percent), status_enum) |
| 3627 | - # catch a time out by sending crtl+c |
| 3628 | - if self.last_activity + INSTALL_TIMEOUT < time.time() and \ |
| 3629 | - self.child_pid: |
| 3630 | - log.critical("Killing child since timeout of %s s", INSTALL_TIMEOUT) |
| 3631 | - os.kill(self.child_pid, 15) |
| 3632 | - return True |
| 3633 | + """Callback for changes on the status file descriptor. |
| 3634 | + |
| 3635 | + The method has to return True to keep the monitoring alive. If |
| 3636 | + it returns False the monitoring will stop. |
| 3637 | + |
| 3638 | + Replace this method in your subclass if you use the status fd. |
| 3639 | + """ |
| 3640 | + return False |
| 3641 | |
| 3642 | def _fork(self): |
| 3643 | """Fork and create a master/slave pty pair by which the forked process |
| 3644 | @@ -598,11 +563,12 @@ |
| 3645 | if condition == GObject.IO_IN: |
| 3646 | self.last_activity = time.time() |
| 3647 | try: |
| 3648 | - char = os.read(source, 1) |
| 3649 | + char_byte = os.read(source, 1) |
| 3650 | except OSError: |
| 3651 | log.debug("Faild to read from master") |
| 3652 | return True |
| 3653 | # Write all the output from dpkg to a log |
| 3654 | + char = char_byte.decode("UTF-8", "ignore") |
| 3655 | if char == "\n": |
| 3656 | # Skip ANSI characters from the console output |
| 3657 | line = re.sub(REGEX_ANSI_ESCAPE_CODE, "", self._line_buffer) |
| 3658 | @@ -614,7 +580,7 @@ |
| 3659 | self._line_buffer += char |
| 3660 | if target: |
| 3661 | try: |
| 3662 | - os.write(target, char) |
| 3663 | + os.write(target, char_byte) |
| 3664 | except OSError: |
| 3665 | log.debug("Failed to write to controlling terminal") |
| 3666 | return True |
| 3667 | @@ -642,6 +608,93 @@ |
| 3668 | os.close(source) |
| 3669 | return False |
| 3670 | |
| 3671 | + |
| 3672 | +class DaemonInstallProgress(DaemonForkProgress): |
| 3673 | + |
| 3674 | + """Progress to execute APT package operations in a child process.""" |
| 3675 | + |
| 3676 | + def start_update(self): |
| 3677 | + DaemonForkProgress.start_update(self) |
| 3678 | + lock.status_lock.release() |
| 3679 | + |
| 3680 | + def finish_update(self): |
| 3681 | + """Callback at the end of the operation""" |
| 3682 | + DaemonForkProgress.finish_update(self) |
| 3683 | + lock.wait_for_lock(self.transaction, lock.status_lock) |
| 3684 | + |
| 3685 | + def _child(self, pm): |
| 3686 | + try: |
| 3687 | + res = pm.do_install(self.status_child_fd) |
| 3688 | + except: |
| 3689 | + os._exit(apt_pkg.PackageManager.RESULT_FAILED) |
| 3690 | + else: |
| 3691 | + os._exit(res) |
| 3692 | + |
| 3693 | + def _on_status_update(self, source, condition): |
| 3694 | + """Parse messages from APT on the status fd.""" |
| 3695 | + log.debug("UpdateInterface") |
| 3696 | + status_msg = "" |
| 3697 | + try: |
| 3698 | + while not status_msg.endswith("\n"): |
| 3699 | + self.last_activity = time.time() |
| 3700 | + status_msg += os.read(source, 1).decode("UTF-8", "ignore") |
| 3701 | + except: |
| 3702 | + return False |
| 3703 | + try: |
| 3704 | + (status, pkg, percent, message_raw) = status_msg.split(":", 3) |
| 3705 | + except ValueError: |
| 3706 | + # silently ignore lines that can't be parsed |
| 3707 | + return True |
| 3708 | + message = message_raw.strip() |
| 3709 | + #print "percent: %s %s" % (pkg, float(percent)/100.0) |
| 3710 | + if status == "pmerror": |
| 3711 | + self._error(pkg, message) |
| 3712 | + elif status == "pmconffile": |
| 3713 | + # we get a string like this: |
| 3714 | + # 'current-conffile' 'new-conffile' useredited distedited |
| 3715 | + match = re.match("\s*\'(.*)\'\s*\'(.*)\'.*", message_raw) |
| 3716 | + if match: |
| 3717 | + new, old = match.group(1), match.group(2) |
| 3718 | + self._conffile(new, old) |
| 3719 | + elif status == "pmstatus": |
| 3720 | + if message.startswith("Installing"): |
| 3721 | + status_enum = enums.PKG_INSTALLING |
| 3722 | + elif message.startswith("Installed"): |
| 3723 | + status_enum = enums.PKG_INSTALLED |
| 3724 | + elif message.startswith("Configuring"): |
| 3725 | + status_enum = enums.PKG_CONFIGURING |
| 3726 | + elif message.startswith("Preparing to configure"): |
| 3727 | + status_enum = enums.PKG_PREPARING_CONFIGURE |
| 3728 | + elif message.startswith("Preparing for removal of"): |
| 3729 | + status_enum = enums.PKG_PREPARING_REMOVE |
| 3730 | + elif message.startswith("Removing"): |
| 3731 | + status_enum = enums.PKG_REMOVING |
| 3732 | + elif message.startswith("Removed"): |
| 3733 | + status_enum = enums.PKG_REMOVED |
| 3734 | + elif message.startswith("Preparing to completely remove"): |
| 3735 | + status_enum = enums.PKG_PREPARING_PURGE |
| 3736 | + elif message.startswith("Completely removing"): |
| 3737 | + status_enum = enums.PKG_PURGING |
| 3738 | + elif message.startswith("Completely removed"): |
| 3739 | + status_enum = enums.PKG_PURGED |
| 3740 | + elif message.startswith("Unpacking"): |
| 3741 | + status_enum = enums.PKG_UNPACKING |
| 3742 | + elif message.startswith("Preparing"): |
| 3743 | + status_enum = enums.PKG_PREPARING_INSTALL |
| 3744 | + elif message.startswith("Noting disappearance of"): |
| 3745 | + status_enum = enums.PKG_DISAPPEARING |
| 3746 | + elif message.startswith("Running"): |
| 3747 | + status_enum = enums.PKG_RUNNING_TRIGGER |
| 3748 | + else: |
| 3749 | + status_enum = enums.PKG_UNKNOWN |
| 3750 | + self._status_changed(pkg, float(percent), status_enum) |
| 3751 | + # catch a time out by sending crtl+c |
| 3752 | + if self.last_activity + INSTALL_TIMEOUT < time.time() and \ |
| 3753 | + self.child_pid: |
| 3754 | + log.critical("Killing child since timeout of %s s", INSTALL_TIMEOUT) |
| 3755 | + os.kill(self.child_pid, 15) |
| 3756 | + return True |
| 3757 | + |
| 3758 | def _status_changed(self, pkg, percent, status_enum): |
| 3759 | """Callback to update status information""" |
| 3760 | log.debug("APT status: %s, %s, %s", pkg, percent, status_enum) |
| 3761 | @@ -669,9 +722,9 @@ |
| 3762 | log.debug("Sending config file answer: %s", |
| 3763 | self.transaction.config_file_conflict_resolution) |
| 3764 | if self.transaction.config_file_conflict_resolution == "replace": |
| 3765 | - os.write(self.master_fd, "y\n") |
| 3766 | + os.write(self.master_fd, b"y\n") |
| 3767 | elif self.transaction.config_file_conflict_resolution == "keep": |
| 3768 | - os.write(self.master_fd, "n\n") |
| 3769 | + os.write(self.master_fd, b"n\n") |
| 3770 | self.transaction.config_file_conflict_resolution = None |
| 3771 | self.transaction.config_file_conflict = None |
| 3772 | self.transaction.status = enums.STATUS_COMMITTING |
| 3773 | @@ -703,7 +756,7 @@ |
| 3774 | status_raw = "" |
| 3775 | try: |
| 3776 | while not status_raw.endswith("\n"): |
| 3777 | - status_raw += os.read(source, 1) |
| 3778 | + status_raw += os.read(source, 1).decode("UTF-8", "ignore") |
| 3779 | except: |
| 3780 | return False |
| 3781 | try: |
| 3782 | |
| 3783 | === modified file 'aptdaemon/test.py' |
| 3784 | --- aptdaemon/test.py 2012-02-03 06:37:42 +0000 |
| 3785 | +++ aptdaemon/test.py 2012-06-13 16:29:18 +0000 |
| 3786 | @@ -28,10 +28,21 @@ |
| 3787 | import shutil |
| 3788 | import subprocess |
| 3789 | import sys |
| 3790 | +import time |
| 3791 | import tempfile |
| 3792 | import unittest |
| 3793 | |
| 3794 | +if sys.version_info.major > 2: |
| 3795 | + from http.server import HTTPServer |
| 3796 | + from http.server import SimpleHTTPRequestHandler as HTTPRequestHandler |
| 3797 | +else: |
| 3798 | + from BaseHTTPServer import HTTPServer |
| 3799 | + from SimpleHTTPServer import SimpleHTTPRequestHandler as HTTPRequestHandler |
| 3800 | + |
| 3801 | import apt_pkg |
| 3802 | +import apt.auth |
| 3803 | + |
| 3804 | +PY3K = sys.version_info.major > 2 |
| 3805 | |
| 3806 | |
| 3807 | class Chroot(object): |
| 3808 | @@ -55,16 +66,20 @@ |
| 3809 | os.makedirs(os.path.join(self.path, "var/lib/apt/lists/partial")) |
| 3810 | os.makedirs(os.path.join(self.path, "etc/apt/apt.conf.d")) |
| 3811 | os.makedirs(os.path.join(self.path, "etc/apt/sources.list.d")) |
| 3812 | + os.makedirs(os.path.join(self.path, "etc/apt/preferences.d")) |
| 3813 | os.makedirs(os.path.join(self.path, "var/log")) |
| 3814 | os.makedirs(os.path.join(self.path, "media")) |
| 3815 | |
| 3816 | # Make apt use the new chroot |
| 3817 | dpkg_wrapper = os.path.join(get_tests_dir(), "dpkg-wrapper.sh") |
| 3818 | + apt_key_wrapper = os.path.join(get_tests_dir(), "fakeroot-apt-key") |
| 3819 | config_path = os.path.join(self.path, "etc/apt/apt.conf.d/10chroot") |
| 3820 | with open(config_path, "w") as cnf: |
| 3821 | cnf.write("Dir::Bin::DPkg %s;" % dpkg_wrapper) |
| 3822 | + cnf.write("Dir::Bin::Apt-Key %s;" % apt_key_wrapper) |
| 3823 | apt_pkg.read_config_file(apt_pkg.config, config_path) |
| 3824 | apt_pkg.init_system() |
| 3825 | + apt_pkg.config["Dir"] = self.path |
| 3826 | |
| 3827 | def remove(self): |
| 3828 | """Remove the files of the chroot.""" |
| 3829 | @@ -75,16 +90,8 @@ |
| 3830 | |
| 3831 | def add_trusted_key(self): |
| 3832 | """Add glatzor's key to the trusted ones.""" |
| 3833 | - gpg_cmd = "gpg --ignore-time-conflict --no-options " \ |
| 3834 | - "--no-default-keyring --quiet " \ |
| 3835 | - "--secret-keyring %s/etc/apt/secring.gpg " \ |
| 3836 | - "--trustdb-name %s/etc/apt/trustdb.gpg " \ |
| 3837 | - "--primary-keyring %s/etc/apt/trusted.gpg " % \ |
| 3838 | - (self.path, self.path, self.path) |
| 3839 | - os.system("%s --import %s/repo/glatzor.gpg" % (gpg_cmd, |
| 3840 | - get_tests_dir())) |
| 3841 | - os.system("echo 'D0BF65B7DBE28DB62BEDBF1B683C53C7CF982D18:6:'| " |
| 3842 | - "%s --import-ownertrust " % gpg_cmd) |
| 3843 | + apt.auth.add_key_from_file(os.path.join(get_tests_dir(), |
| 3844 | + "repo/glatzor.gpg")) |
| 3845 | |
| 3846 | def install_debfile(self, path, force_depends=False): |
| 3847 | """Install a package file into the chroot.""" |
| 3848 | @@ -162,6 +169,14 @@ |
| 3849 | |
| 3850 | class AptDaemonTestCase(unittest.TestCase): |
| 3851 | |
| 3852 | + @classmethod |
| 3853 | + def setupClass(cls): |
| 3854 | + # Start with a clean APT configuration to remove changes |
| 3855 | + # of previous tests |
| 3856 | + for key in set([key.split("::")[0] for key in apt_pkg.config.keys()]): |
| 3857 | + apt_pkg.config.clear(key) |
| 3858 | + apt_pkg.init_config() |
| 3859 | + |
| 3860 | def start_fake_polkitd(self, options="all"): |
| 3861 | """Start a fake PolicyKit daemon. |
| 3862 | |
| 3863 | @@ -169,7 +184,8 @@ |
| 3864 | Defaults to all |
| 3865 | """ |
| 3866 | try: |
| 3867 | - env = {"DBUS_SYSTEM_BUS_ADDRESS": self.dbus_address} |
| 3868 | + env = os.environ.copy() |
| 3869 | + env["DBUS_SYSTEM_BUS_ADDRESS"] = self.dbus_address |
| 3870 | except AttributeError: |
| 3871 | env=None |
| 3872 | dir = get_tests_dir() |
| 3873 | @@ -185,7 +201,8 @@ |
| 3874 | :param chroot: path to the chroot |
| 3875 | """ |
| 3876 | try: |
| 3877 | - env = {"DBUS_SYSTEM_BUS_ADDRESS": self.dbus_address} |
| 3878 | + env = os.environ.copy() |
| 3879 | + env["DBUS_SYSTEM_BUS_ADDRESS"] = self.dbus_address |
| 3880 | except AttributeError: |
| 3881 | env = None |
| 3882 | dir = get_tests_dir() |
| 3883 | @@ -193,7 +210,7 @@ |
| 3884 | path = "/usr/sbin/aptd" |
| 3885 | else: |
| 3886 | path = os.path.join(dir, "../aptd") |
| 3887 | - proc = subprocess.Popen(["python", path, "--debug", |
| 3888 | + proc = subprocess.Popen(["python3", path, "--debug", |
| 3889 | "--disable-timeout", "--disable-plugins", |
| 3890 | "--chroot", chroot], |
| 3891 | env=env) |
| 3892 | @@ -202,14 +219,42 @@ |
| 3893 | |
| 3894 | def start_dbus_daemon(self): |
| 3895 | """Start a private D-Bus daemon and return its process and address.""" |
| 3896 | - config_path = os.path.join(get_tests_dir(), "dbus.conf") |
| 3897 | - proc = subprocess.Popen(["dbus-daemon", "--nofork", |
| 3898 | - "--print-address", "--config-file", |
| 3899 | - config_path], |
| 3900 | - stdout=subprocess.PIPE) |
| 3901 | + proc, dbus_address = start_dbus_daemon() |
| 3902 | self.addCleanup(self._kill_process, proc) |
| 3903 | - self.dbus_address = proc.stdout.readline().strip() |
| 3904 | - return proc, self.dbus_address |
| 3905 | + self.dbus_address = dbus_address |
| 3906 | + |
| 3907 | + def start_keyserver(self, filename=None): |
| 3908 | + """Start a fake keyserver on hkp://localhost:19191 |
| 3909 | + |
| 3910 | + Keyword arguments: |
| 3911 | + filename -- Optional path to a GnuPG pulic key file which should |
| 3912 | + be returned by lookups. By default the key of the test repo |
| 3913 | + is used. |
| 3914 | + """ |
| 3915 | + dir = tempfile.mkdtemp(prefix="keyserver-test-") |
| 3916 | + self.addCleanup(shutil.rmtree, dir) |
| 3917 | + os.mkdir(os.path.join(dir, "pks")) |
| 3918 | + if filename is None: |
| 3919 | + filename = os.path.join(get_tests_dir(), "repo/glatzor.gpg") |
| 3920 | + shutil.copy(filename, os.path.join(dir, "pks", "lookup")) |
| 3921 | + |
| 3922 | + pid = os.fork() |
| 3923 | + if pid == 0: |
| 3924 | + # quiesce server log |
| 3925 | + os.dup2(os.open('/dev/null', os.O_WRONLY), sys.stderr.fileno()) |
| 3926 | + os.chdir(dir) |
| 3927 | + httpd = HTTPServer(('localhost', 19191), HTTPRequestHandler) |
| 3928 | + httpd.serve_forever() |
| 3929 | + os._exit(0) |
| 3930 | + else: |
| 3931 | + self.addCleanup(self._kill_pid, pid) |
| 3932 | + |
| 3933 | + # wait a bit until server is ready |
| 3934 | + time.sleep(0.5) |
| 3935 | + |
| 3936 | + def _kill_pid(self, pid): |
| 3937 | + os.kill(pid, 15) |
| 3938 | + os.wait() |
| 3939 | |
| 3940 | def _kill_process(self, proc): |
| 3941 | proc.kill() |
| 3942 | @@ -234,5 +279,19 @@ |
| 3943 | else: |
| 3944 | raise Exception("Could not find tests direcotry") |
| 3945 | |
| 3946 | +def start_dbus_daemon(): |
| 3947 | + """Start a private D-Bus daemon and return its process and address.""" |
| 3948 | + config_path = os.path.join(get_tests_dir(), "dbus.conf") |
| 3949 | + proc = subprocess.Popen(["dbus-daemon", "--nofork", |
| 3950 | + "--print-address", "--config-file", |
| 3951 | + config_path], |
| 3952 | + stdout=subprocess.PIPE) |
| 3953 | + output = proc.stdout.readline().strip() |
| 3954 | + if PY3K: |
| 3955 | + dbus_address = output.decode() |
| 3956 | + else: |
| 3957 | + dbus_address = output |
| 3958 | + return proc, dbus_address |
| 3959 | + |
| 3960 | |
| 3961 | # vim: ts=4 et sts=4 |
| 3962 | |
| 3963 | === modified file 'aptdaemon/utils.py' |
| 3964 | --- aptdaemon/utils.py 2012-04-02 19:04:16 +0000 |
| 3965 | +++ aptdaemon/utils.py 2012-06-13 16:29:18 +0000 |
| 3966 | @@ -44,8 +44,8 @@ |
| 3967 | 'funcname': func.__name__, |
| 3968 | }, |
| 3969 | category=DeprecationWarning, |
| 3970 | - filename=func.func_code.co_filename, |
| 3971 | - lineno=func.func_code.co_firstlineno + 1 |
| 3972 | + filename=func.__code__.co_filename, |
| 3973 | + lineno=func.__code__.co_firstlineno + 1 |
| 3974 | ) |
| 3975 | return func(*args, **kwargs) |
| 3976 | return new_func |
| 3977 | @@ -62,7 +62,7 @@ |
| 3978 | et = ElementTree.ElementTree(file=filename) |
| 3979 | self._dict = {} |
| 3980 | self.norm = norm |
| 3981 | - for element in et.getiterator(): |
| 3982 | + for element in list(et.iter()): |
| 3983 | iso_code = element.get(tag) |
| 3984 | if not iso_code and fallback_tag: |
| 3985 | iso_code = element.get(fallback_tag) |
| 3986 | |
| 3987 | === modified file 'aptdaemon/worker.py' |
| 3988 | --- aptdaemon/worker.py 2012-05-11 15:56:04 +0000 |
| 3989 | +++ aptdaemon/worker.py 2012-06-13 16:29:18 +0000 |
| 3990 | @@ -31,8 +31,13 @@ |
| 3991 | import tempfile |
| 3992 | import time |
| 3993 | import traceback |
| 3994 | +try: |
| 3995 | + from urllib.parse import urlsplit, urlunsplit |
| 3996 | +except ImportError: |
| 3997 | + from urlparse import urlsplit, urlunsplit |
| 3998 | |
| 3999 | import apt |
| 4000 | +import apt.auth |
| 4001 | import apt.cache |
| 4002 | import apt.debfile |
| 4003 | import apt_pkg |
| 4004 | @@ -41,7 +46,6 @@ |
| 4005 | from aptsources.sourceslist import SourcesList |
| 4006 | from gi.repository import GObject |
| 4007 | import pkg_resources |
| 4008 | -from softwareproperties.AptAuth import AptAuth |
| 4009 | import subprocess |
| 4010 | |
| 4011 | from .enums import * |
| 4012 | @@ -54,7 +58,8 @@ |
| 4013 | DaemonAcquireRepoProgress, \ |
| 4014 | DaemonDpkgInstallProgress, \ |
| 4015 | DaemonDpkgReconfigureProgress, \ |
| 4016 | - DaemonDpkgRecoverProgress |
| 4017 | + DaemonDpkgRecoverProgress, \ |
| 4018 | + DaemonForkProgress |
| 4019 | |
| 4020 | log = logging.getLogger("AptDaemon.Worker") |
| 4021 | |
| 4022 | @@ -413,7 +418,7 @@ |
| 4023 | """ |
| 4024 | trans.progress = 101 |
| 4025 | trans.status = STATUS_COMMITTING |
| 4026 | - old_umask = os.umask(0022) |
| 4027 | + old_umask = os.umask(0o022) |
| 4028 | try: |
| 4029 | sourceslist = SourcesList() |
| 4030 | distro = aptsources.distro.get_distro() |
| 4031 | @@ -470,8 +475,6 @@ |
| 4032 | """Extract the credentials from an URI. Store the password in |
| 4033 | auth.conf and return the URI without any password information. |
| 4034 | """ |
| 4035 | - from urlparse import urlsplit, urlunsplit |
| 4036 | - |
| 4037 | try: |
| 4038 | res = urlsplit(uri) |
| 4039 | except ValueError as error: |
| 4040 | @@ -483,7 +486,7 @@ |
| 4041 | |
| 4042 | # write auth.conf |
| 4043 | auth_conf_path = apt_pkg.config.find_file("Dir::etc::netrc") |
| 4044 | - old_umask = os.umask(0027) |
| 4045 | + old_umask = os.umask(0o027) |
| 4046 | try: |
| 4047 | with open(auth_conf_path, "a") as auth_conf: |
| 4048 | auth_conf.write("""machine %s |
| 4049 | @@ -508,33 +511,39 @@ |
| 4050 | keyserver - the keyserver (e.g. keyserver.ubuntu.com) |
| 4051 | """ |
| 4052 | log.info("Adding vendor key from keyserver: %s %s", keyid, keyserver) |
| 4053 | + # Perform some sanity checks |
| 4054 | + try: |
| 4055 | + res = urlsplit(keyserver) |
| 4056 | + except ValueError: |
| 4057 | + raise TransactionFailed(ERROR_KEY_NOT_INSTALLED, |
| 4058 | + #TRANSLATORS: %s is the URL of GnuPG |
| 4059 | + # keyserver |
| 4060 | + _("The keyserver URL is invalid: %s"), |
| 4061 | + keyserver) |
| 4062 | + if res.scheme not in ["hkp", "ldap", "ldaps", "http", "https"]: |
| 4063 | + raise TransactionFailed(ERROR_KEY_NOT_INSTALLED, |
| 4064 | + #TRANSLATORS: %s is the URL of GnuPG |
| 4065 | + # keyserver |
| 4066 | + _("Invalid protocol of the server: %s"), |
| 4067 | + keyserver) |
| 4068 | + try: |
| 4069 | + int(keyid, 16) |
| 4070 | + except ValueError: |
| 4071 | + raise TransactionFailed(ERROR_KEY_NOT_INSTALLED, |
| 4072 | + #TRANSLATORS: %s is the id of a GnuPG key |
| 4073 | + # e.g. E08ADE95 |
| 4074 | + _("Invalid key id: %s"), keyid) |
| 4075 | trans.status = STATUS_DOWNLOADING |
| 4076 | trans.progress = 101 |
| 4077 | last_pulse = time.time() |
| 4078 | - #FIXME: Use GObject.spawn_async and deferreds in the worker |
| 4079 | - # Alternatively we could use python-pyme directly for a better |
| 4080 | - # error handling. Or the --status-fd of gpg |
| 4081 | - proc = subprocess.Popen(["/usr/bin/apt-key", "adv", |
| 4082 | - "--keyserver", keyserver, |
| 4083 | - "--recv", keyid], stderr=subprocess.STDOUT, |
| 4084 | - stdout=subprocess.PIPE, close_fds=True) |
| 4085 | - while proc.poll() is None: |
| 4086 | - self._iterate_mainloop() |
| 4087 | - time.sleep(0.05) |
| 4088 | - if time.time() - last_pulse > 0.3: |
| 4089 | - trans.progress = 101 |
| 4090 | - last_pulse = time.time() |
| 4091 | - if proc.returncode != 0: |
| 4092 | - stdout = unicode(proc.stdout.read(), |
| 4093 | - # that can return "None", in this case, just |
| 4094 | - # assume something |
| 4095 | - sys.stdin.encoding or "UTF-8", |
| 4096 | - errors="replace") |
| 4097 | + with DaemonForkProgress(trans) as progress: |
| 4098 | + progress.run(apt.auth.add_key_from_keyserver, keyid, keyserver) |
| 4099 | + if progress._child_exit != 0: |
| 4100 | #TRANSLATORS: The first %s is the key id and the second the server |
| 4101 | raise TransactionFailed(ERROR_KEY_NOT_INSTALLED, |
| 4102 | _("Failed to download and install the key " |
| 4103 | "%s from %s:\n%s"), |
| 4104 | - keyid, keyserver, stdout) |
| 4105 | + keyid, keyserver, progress.output) |
| 4106 | |
| 4107 | def add_vendor_key_from_file(self, trans, path): |
| 4108 | """Add the signing key from the given file to the trusted vendors. |
| 4109 | @@ -545,15 +554,12 @@ |
| 4110 | log.info("Adding vendor key from file: %s", path) |
| 4111 | trans.progress = 101 |
| 4112 | trans.status = STATUS_COMMITTING |
| 4113 | - try: |
| 4114 | - #FIXME: use GObject.spawn_async or reactor.spawn |
| 4115 | - #FIXME: use --dry-run before? |
| 4116 | - auth = AptAuth() |
| 4117 | - auth.add(os.path.expanduser(path)) |
| 4118 | - except Exception as error: |
| 4119 | + with DaemonForkProgress(trans) as progress: |
| 4120 | + progress.run(apt.auth.add_key_from_file, path) |
| 4121 | + if progress._child_exit != 0: |
| 4122 | raise TransactionFailed(ERROR_KEY_NOT_INSTALLED, |
| 4123 | _("Key file %s couldn't be installed: %s"), |
| 4124 | - path, error) |
| 4125 | + path, progress.output) |
| 4126 | |
| 4127 | def remove_vendor_key(self, trans, fingerprint): |
| 4128 | """Remove repository key. |
| 4129 | @@ -566,14 +572,19 @@ |
| 4130 | trans.progress = 101 |
| 4131 | trans.status = STATUS_COMMITTING |
| 4132 | try: |
| 4133 | - #FIXME: use GObject.spawn_async or reactor.spawn |
| 4134 | - #FIXME: use --dry-run before? |
| 4135 | - auth = AptAuth() |
| 4136 | - auth.rm(fingerprint) |
| 4137 | - except Exception as error: |
| 4138 | + int(fingerprint, 16) |
| 4139 | + except ValueError: |
| 4140 | + raise TransactionFailed(ERROR_KEY_NOT_REMOVED, |
| 4141 | + #TRANSLATORS: %s is the id of a GnuPG key |
| 4142 | + # e.g. E08ADE95 |
| 4143 | + _("Invalid key id: %s"), fingerprint) |
| 4144 | + with DaemonForkProgress(trans) as progress: |
| 4145 | + progress.run(apt.auth.remove_key, fingerprint) |
| 4146 | + if progress._child_exit != 0: |
| 4147 | raise TransactionFailed(ERROR_KEY_NOT_REMOVED, |
| 4148 | _("Key with fingerprint %s couldn't be " |
| 4149 | - "removed: %s"), fingerprint, error) |
| 4150 | + "removed: %s"), fingerprint, |
| 4151 | + progress.output) |
| 4152 | |
| 4153 | def install_file(self, trans, path, force, simulate=False): |
| 4154 | """Install local package file. |
| 4155 | @@ -603,7 +614,7 @@ |
| 4156 | deb_progress = DaemonDpkgInstallProgress(trans, begin=64, end=95) |
| 4157 | res = deb.install(deb_progress) |
| 4158 | encoding = sys.getfilesystemencoding() |
| 4159 | - trans.output += deb_progress.output.decode(encoding, "ignore") |
| 4160 | + trans.output += deb_progress.output |
| 4161 | if res: |
| 4162 | raise TransactionFailed(ERROR_PACKAGE_MANAGER_FAILED, |
| 4163 | trans.output) |
| 4164 | @@ -863,13 +874,10 @@ |
| 4165 | """ |
| 4166 | log.info("Fixing incomplete installs") |
| 4167 | trans.status = STATUS_CLEANING_UP |
| 4168 | - progress = DaemonDpkgRecoverProgress(trans) |
| 4169 | with self._frozen_status(): |
| 4170 | - progress.start_update() |
| 4171 | - progress.run() |
| 4172 | - progress.finish_update() |
| 4173 | - trans.output += progress.output.decode(sys.getfilesystemencoding(), |
| 4174 | - "ignore") |
| 4175 | + with DaemonDpkgRecoverProgress(trans) as progress: |
| 4176 | + progress.run() |
| 4177 | + trans.output += progress.output |
| 4178 | if progress._child_exit != 0: |
| 4179 | raise TransactionFailed(ERROR_PACKAGE_MANAGER_FAILED, |
| 4180 | trans.output) |
| 4181 | @@ -883,13 +891,10 @@ |
| 4182 | priority -- the lowest priority of question which should be asked |
| 4183 | """ |
| 4184 | log.info("Reconfiguring packages") |
| 4185 | - progress = DaemonDpkgReconfigureProgress(trans) |
| 4186 | with self._frozen_status(): |
| 4187 | - progress.start_update() |
| 4188 | - progress.run(packages, priority) |
| 4189 | - progress.finish_update() |
| 4190 | - trans.output += progress.output.decode(sys.getfilesystemencoding(), |
| 4191 | - "ignore") |
| 4192 | + with DaemonDpkgReconfigureProgress(trans) as progress: |
| 4193 | + progress.run(packages, priority) |
| 4194 | + trans.output += progress.output |
| 4195 | if progress._child_exit != 0: |
| 4196 | raise TransactionFailed(ERROR_PACKAGE_MANAGER_FAILED, |
| 4197 | trans.output) |
| 4198 | @@ -993,18 +998,15 @@ |
| 4199 | except SystemError as excep: |
| 4200 | # Run dpkg --configure -a to recover from a failed transaction |
| 4201 | trans.status = STATUS_CLEANING_UP |
| 4202 | - progress = DaemonDpkgRecoverProgress(trans, begin=90, end=95) |
| 4203 | - progress.start_update() |
| 4204 | - progress.run() |
| 4205 | - progress.finish_update() |
| 4206 | - output = inst_progress.output + progress.output |
| 4207 | - trans.output += output.decode(sys.getfilesystemencoding(), |
| 4208 | - "ignore") |
| 4209 | + with DaemonDpkgRecoverProgress(trans, begin=90, end=95) as pro: |
| 4210 | + pro.run() |
| 4211 | + output = inst_progress.output + pro.output |
| 4212 | + trans.output += output |
| 4213 | raise TransactionFailed(ERROR_PACKAGE_MANAGER_FAILED, |
| 4214 | "%s: %s" % (excep, trans.output)) |
| 4215 | else: |
| 4216 | enc = sys.getfilesystemencoding() |
| 4217 | - trans.output += inst_progress.output.decode(enc, "ignore") |
| 4218 | + trans.output += inst_progress.output |
| 4219 | |
| 4220 | @contextlib.contextmanager |
| 4221 | def _frozen_status(self): |
| 4222 | @@ -1103,7 +1105,7 @@ |
| 4223 | size = int(deb["Installed-Size"].replace(",", "")) * 1024 |
| 4224 | # Some packages ship really large install sizes e.g. |
| 4225 | # openvpn access server, see LP #758837 |
| 4226 | - if size > sys.maxint: |
| 4227 | + if size > sys.maxsize: |
| 4228 | raise OverflowError("Size is too large: %s Bytes" % size) |
| 4229 | except (KeyError, AttributeError, ValueError, OverflowError): |
| 4230 | if not trans.kwargs["force"]: |
| 4231 | @@ -1181,7 +1183,6 @@ |
| 4232 | :returns: An apt.debfile.Debfile instance. |
| 4233 | """ |
| 4234 | #FIXME: Unblock lintian call |
| 4235 | - path = path.encode("UTF-8") |
| 4236 | if not os.path.isfile(path): |
| 4237 | raise TransactionFailed(ERROR_UNREADABLE_PACKAGE_FILE, path) |
| 4238 | if not force and os.path.isfile("/usr/bin/lintian"): |
| 4239 | @@ -1219,9 +1220,9 @@ |
| 4240 | time.sleep(0.05) |
| 4241 | #FIXME: Add an error to catch return state 2 (failure) |
| 4242 | if proc.returncode == 1: |
| 4243 | - stdout = unicode(proc.stdout.read(), |
| 4244 | - sys.stdin.encoding or "UTF-8", |
| 4245 | - errors="replace") |
| 4246 | + stdout = proc.stdout.read() |
| 4247 | + stdout.decode(sys.stdin.encoding or "UTF-8", |
| 4248 | + errors="replace") |
| 4249 | raise TransactionFailed(ERROR_INVALID_PACKAGE_FILE, |
| 4250 | "Lintian check results for %s:" |
| 4251 | "\n%s" % (path, stdout)) |
| 4252 | |
| 4253 | === modified file 'aptdcon' |
| 4254 | --- aptdcon 2009-06-30 15:06:36 +0000 |
| 4255 | +++ aptdcon 2012-06-13 16:29:18 +0000 |
| 4256 | @@ -1,4 +1,4 @@ |
| 4257 | -#!/usr/bin/python |
| 4258 | +#!/usr/bin/python3 |
| 4259 | # -*- coding: utf-8 -*- |
| 4260 | """ |
| 4261 | aptdcon - command line interface client to aptdaemon |
| 4262 | |
| 4263 | === modified file 'debian/aptdaemon.install' |
| 4264 | --- debian/aptdaemon.install 2012-04-09 20:48:44 +0000 |
| 4265 | +++ debian/aptdaemon.install 2012-06-13 16:29:18 +0000 |
| 4266 | @@ -1,7 +1,7 @@ |
| 4267 | etc/apt/apt.conf.d/20dbus |
| 4268 | etc/dbus-1/system.d/org.debian.apt.conf |
| 4269 | -usr/bin/aptd /usr/sbin |
| 4270 | -usr/bin/aptdcon |
| 4271 | +../../build/scripts-3.*/aptd /usr/sbin |
| 4272 | +../../build/scripts-3.*/aptdcon /usr/bin |
| 4273 | usr/share/dbus-1/system-services/org.debian.apt.service |
| 4274 | usr/share/polkit-1/actions/org.debian.apt.policy |
| 4275 | usr/share/locale |
| 4276 | |
| 4277 | === modified file 'debian/changelog' |
| 4278 | --- debian/changelog 2012-05-23 12:53:16 +0000 |
| 4279 | +++ debian/changelog 2012-06-13 16:29:18 +0000 |
| 4280 | @@ -1,3 +1,42 @@ |
| 4281 | +aptdaemon (0.43+bzr838-0ubuntu1) UNRELEASED; urgency=low |
| 4282 | + |
| 4283 | + * Upload of the latest Python3 porting efforts from trunk |
| 4284 | + * debian/patches: |
| 4285 | + - Add disable_simulate_test: Fails on build bot for unknown reasons |
| 4286 | + * debian/control: |
| 4287 | + - Switch aptdaemon package to Python3 by default |
| 4288 | + - Add new python3-aptdaemon.gtk3widgets package |
| 4289 | + - Replace python-aptdaemon.test by python3-aptdaemon.test |
| 4290 | + - Replace python-aptdaemon.pkcompat by python3-aptdaemon.pkcompat |
| 4291 | + - python3-aptdaemon.pkcompat provides the new virtual package |
| 4292 | + packagekit-system-interface to obsolete the OR dependencies |
| 4293 | + with packagekit of PackageKit clients |
| 4294 | + - Remove policykit1 dependecy from the modules and add it to the server |
| 4295 | + package |
| 4296 | + - Remove not used shlibs macros |
| 4297 | + - Remove dependency to python-packagekit, since we ship the enums |
| 4298 | + in python3-aptdaemon.pkcompat |
| 4299 | + - Add build dependencies to run the test suite |
| 4300 | + * debian/rules: |
| 4301 | + - Build with Python2 and 3 |
| 4302 | + - Enable the test suite |
| 4303 | + * debian/*.(install|docs|examples): |
| 4304 | + - Adpat to above package changes |
| 4305 | + |
| 4306 | + [ Steve Langasek ] |
| 4307 | + * debian/control: |
| 4308 | + - Remove python-software-properties dependency in favor of new |
| 4309 | + python-apt with apt.auth module |
| 4310 | + * aptdaemon/test.py: explicitly set the chroot directory in the apt config |
| 4311 | + as part of the test setup, without which apt-key's chroot handling won't |
| 4312 | + work. |
| 4313 | + * test/test_pk.py: increase the sleep on startup, to allow longer for |
| 4314 | + fake-polkitd to start up. |
| 4315 | + * aptdaemon/worker.py: restore compatibility with python2, which doesn't |
| 4316 | + have urllib.parse. |
| 4317 | + |
| 4318 | + -- Sebastian Heinlein <glatzor@ubuntu.com> Fri, 11 May 2012 08:39:34 -0700 |
| 4319 | + |
| 4320 | aptdaemon (0.43+bzr810-0ubuntu3) quantal; urgency=low |
| 4321 | |
| 4322 | * debian/python-aptdaemon.test.install: Fix installation path of |
| 4323 | |
| 4324 | === modified file 'debian/control' |
| 4325 | --- debian/control 2012-05-22 11:01:33 +0000 |
| 4326 | +++ debian/control 2012-06-13 16:29:18 +0000 |
| 4327 | @@ -4,35 +4,50 @@ |
| 4328 | Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com> |
| 4329 | XSBC-Original-Maintainer: Julian Andres Klode <jak@debian.org> |
| 4330 | Build-Depends: debhelper (>= 7.3), |
| 4331 | + debconf-i18n, |
| 4332 | + dbus, |
| 4333 | + lintian, |
| 4334 | dh-translations, |
| 4335 | - dbus, |
| 4336 | - python, |
| 4337 | + python-all, |
| 4338 | python-setuptools, |
| 4339 | python-distutils-extra, |
| 4340 | - python-apt (>= 0.7.96.1ubuntu9), |
| 4341 | - python-debian, |
| 4342 | - python-defer, |
| 4343 | + python-nose, |
| 4344 | + python3-all, |
| 4345 | + python3-setuptools, |
| 4346 | + python3-distutils-extra, |
| 4347 | + python3-nose, |
| 4348 | + gir1.2-glib-2.0, |
| 4349 | + gir1.2-packagekitglib-1.0, |
| 4350 | + python3-apt (>= 0.8.5~ubuntu1), |
| 4351 | + python3-defer (>= 1.0.6), |
| 4352 | + python3-dbus, |
| 4353 | + python3-gi, |
| 4354 | + python3-mock, |
| 4355 | + python3-pkg-resources, |
| 4356 | + python-apt (>= 0.8.5~ubuntu1), |
| 4357 | + python-defer (>= 1.0.6), |
| 4358 | python-dbus, |
| 4359 | python-gi, |
| 4360 | - gir1.2-glib-2.0, |
| 4361 | - python-software-properties |
| 4362 | + python-mock, |
| 4363 | + python-pkg-resources, |
| 4364 | Standards-Version: 3.9.1 |
| 4365 | Homepage: https://launchpad.net/aptdaemon |
| 4366 | Vcs-Bzr: lp:~aptdaemon-developers/aptdaemon/ubuntu-quantal |
| 4367 | Vcs-Browser: https://code.launchpad.net/~aptdaemon-developers/aptdaemon/ubuntu-quantal |
| 4368 | XS-Original-Vcs-Bzr: nosmart+http://bzr.debian.org/bzr/apt/aptdaemon/debian-sid |
| 4369 | XS-Original-Vcs-Browser: http://bzr.debian.org/loggerhead/apt/aptdaemon/debian-sid |
| 4370 | -XS-Python-Version: >= 2.7 |
| 4371 | +X-Python-Version: >= 2.7 |
| 4372 | +X-Python3-Version: >= 3.2 |
| 4373 | |
| 4374 | Package: aptdaemon |
| 4375 | Architecture: all |
| 4376 | Depends: ${misc:Depends}, |
| 4377 | - ${python:Depends}, |
| 4378 | - python-aptdaemon (= ${binary:Version}), |
| 4379 | - python-gi, |
| 4380 | - gir1.2-glib-2.0 |
| 4381 | + ${python3:Depends}, |
| 4382 | + gir1.2-glib-2.0, |
| 4383 | + python3-aptdaemon (= ${binary:Version}), |
| 4384 | + python3-gi, |
| 4385 | + policykit-1, |
| 4386 | Recommends: lintian |
| 4387 | -XB-Python-Version: ${python:Versions} |
| 4388 | Breaks: software-center (<< 1.1.21) |
| 4389 | Description: transaction based package management service |
| 4390 | Aptdaemon allows normal users to perform package management tasks, e.g. |
| 4391 | @@ -54,39 +69,54 @@ |
| 4392 | the daemon. Moreover it contains the aptdcon script, which is a command |
| 4393 | line client for aptdaemon. The API is not stable yet. |
| 4394 | |
| 4395 | +Package: python3-aptdaemon |
| 4396 | +Architecture: all |
| 4397 | +Section: python |
| 4398 | +Depends: ${misc:Depends}, |
| 4399 | + ${python3:Depends}, |
| 4400 | + gir1.2-glib-2.0, |
| 4401 | + python3-apt (>= 0.8.5~ubuntu1), |
| 4402 | + python3-defer (>= 1.0.6), |
| 4403 | + python3-dbus, |
| 4404 | + python3-gi, |
| 4405 | + python3-pkg-resources, |
| 4406 | +Recommends: aptdaemon |
| 4407 | +Description: Python 3 module for the server and client of aptdaemon |
| 4408 | + Aptdaemon is a transaction based package management service. It allows |
| 4409 | + normal users to perform package management tasks, e.g. refreshing the |
| 4410 | + cache, upgrading the system, installing or removing software packages. |
| 4411 | + . |
| 4412 | + This package provides the Python 3 modules required to run aptdaemon |
| 4413 | + and to implement a client. The API is not stable yet. |
| 4414 | + |
| 4415 | + |
| 4416 | Package: python-aptdaemon |
| 4417 | Architecture: all |
| 4418 | Section: python |
| 4419 | -Depends: ${shlibs:Depends}, |
| 4420 | - ${misc:Depends}, |
| 4421 | +Depends: ${misc:Depends}, |
| 4422 | ${python:Depends}, |
| 4423 | - python-apt (>= 0.7.96.1ubuntu9), |
| 4424 | + python-apt (>= 0.8.5~ubuntu1), |
| 4425 | python-debian, |
| 4426 | python-defer, |
| 4427 | python-dbus, |
| 4428 | python-gi, |
| 4429 | gir1.2-glib-2.0, |
| 4430 | python-pkg-resources, |
| 4431 | - python-software-properties, |
| 4432 | - policykit-1 |
| 4433 | Recommends: aptdaemon |
| 4434 | -XB-Python-Version: ${python:Versions} |
| 4435 | -Description: Python module for the server and client of aptdaemon |
| 4436 | +Description: Python 2 module for the server and client of aptdaemon |
| 4437 | Aptdaemon is a transaction based package management service. It allows |
| 4438 | normal users to perform package management tasks, e.g. refreshing the |
| 4439 | cache, upgrading the system, installing or removing software packages. |
| 4440 | . |
| 4441 | - This package provides the Python modules required to run aptdaemon |
| 4442 | + This package provides the Python 2 modules required to run aptdaemon |
| 4443 | and to implement a client. The API is not stable yet. |
| 4444 | |
| 4445 | -Package: python-aptdaemon.test |
| 4446 | +Package: python3-aptdaemon.test |
| 4447 | Architecture: all |
| 4448 | Section: python |
| 4449 | -Depends: ${shlibs:Depends}, |
| 4450 | - ${misc:Depends}, |
| 4451 | - ${python:Depends}, |
| 4452 | - python-aptdaemon (= ${binary:Version}), |
| 4453 | -XB-Python-Version: ${python:Versions} |
| 4454 | +Depends: ${misc:Depends}, |
| 4455 | + ${python3:Depends}, |
| 4456 | + python3-aptdaemon (= ${binary:Version}), |
| 4457 | Description: Test environment for aptdaemon clients |
| 4458 | Aptdaemon is a transaction based package management daemon. It allows |
| 4459 | normal users to perform package management tasks, e.g. refreshing the |
| 4460 | @@ -98,8 +128,7 @@ |
| 4461 | |
| 4462 | Package: aptdaemon-data |
| 4463 | Architecture: all |
| 4464 | -Depends: ${shlibs:Depends}, |
| 4465 | - ${misc:Depends} |
| 4466 | +Depends: ${misc:Depends} |
| 4467 | Replaces: python-aptdaemon-gtk (<= 0.41+bzr580-0ubuntu1) |
| 4468 | Description: data files for clients |
| 4469 | Aptdaemon is a transaction based package management daemon. It allows |
| 4470 | @@ -112,12 +141,10 @@ |
| 4471 | Package: python-aptdaemon-gtk |
| 4472 | Architecture: all |
| 4473 | Section: python |
| 4474 | -Depends: ${shlibs:Depends}, |
| 4475 | - ${misc:Depends}, |
| 4476 | +Depends: ${misc:Depends}, |
| 4477 | ${python:Depends}, |
| 4478 | python-aptdaemon.gtkwidgets (= ${binary:Version}), |
| 4479 | python-aptdaemon.gtk3widgets (= ${binary:Version}) |
| 4480 | -XB-Python-Version: ${python:Versions} |
| 4481 | Description: Transitional dummy package |
| 4482 | Aptdaemon is a transaction based package management daemon. It allows |
| 4483 | normal users to perform package management tasks, e.g. refreshing the |
| 4484 | @@ -129,16 +156,16 @@ |
| 4485 | . |
| 4486 | You can remove it safely. |
| 4487 | |
| 4488 | -Package: python-aptdaemon.pkcompat |
| 4489 | +Package: python3-aptdaemon.pkcompat |
| 4490 | Architecture: all |
| 4491 | Section: python |
| 4492 | -Depends: ${shlibs:Depends}, |
| 4493 | - ${misc:Depends}, |
| 4494 | - ${python:Depends}, |
| 4495 | - python-aptdaemon (= ${binary:Version}), |
| 4496 | - python-packagekit, |
| 4497 | -Conflicts: packagekit |
| 4498 | -XB-Python-Version: ${python:Versions} |
| 4499 | +Depends: ${misc:Depends}, |
| 4500 | + ${python3:Depends}, |
| 4501 | + python3-aptdaemon (= ${binary:Version}), |
| 4502 | +Provides: packagekit-system-interface |
| 4503 | +Conflicts: packagekit, |
| 4504 | + python-aptdaemon.pkcompat, |
| 4505 | +Replaces: python-aptdaemon.pkcompat |
| 4506 | Description: PackageKit compatibilty for AptDaemon |
| 4507 | Aptdaemon is a transaction based package management daemon. It allows |
| 4508 | normal users to perform package management tasks, e.g. refreshing the |
| 4509 | @@ -149,8 +176,7 @@ |
| 4510 | Package: python-aptdaemon.gtkwidgets |
| 4511 | Architecture: all |
| 4512 | Section: python |
| 4513 | -Depends: ${shlibs:Depends}, |
| 4514 | - ${misc:Depends}, |
| 4515 | +Depends: ${misc:Depends}, |
| 4516 | ${python:Depends}, |
| 4517 | python-aptdaemon (= ${binary:Version}), |
| 4518 | python-gtk2, |
| 4519 | @@ -158,7 +184,6 @@ |
| 4520 | aptdaemon-data |
| 4521 | Conflicts: python-aptdaemon-gtk (<< 0.41+bzr582-0ubuntu1) |
| 4522 | Replaces: python-aptdaemon-gtk (<< 0.41+bzr582-0ubuntu1) |
| 4523 | -XB-Python-Version: ${python:Versions} |
| 4524 | Description: Python GTK+ 2 widgets to run an aptdaemon client |
| 4525 | Aptdaemon is a transaction based package management daemon. It allows |
| 4526 | normal users to perform package management tasks, e.g. refreshing the |
| 4527 | @@ -168,12 +193,32 @@ |
| 4528 | graphical client. The widgets can be used to initiate, to monitor and |
| 4529 | to control a transaction. The API is not stable yet. |
| 4530 | |
| 4531 | +Package: python3-aptdaemon.gtk3widgets |
| 4532 | +Architecture: all |
| 4533 | +Section: python |
| 4534 | +Depends: ${misc:Depends}, |
| 4535 | + ${python3:Depends}, |
| 4536 | + python3-aptdaemon (= ${binary:Version}), |
| 4537 | + python3-gi, |
| 4538 | + gir1.2-gtk-3.0, |
| 4539 | + gir1.2-vte-2.90, |
| 4540 | + aptdaemon-data |
| 4541 | +Conflicts: python-aptdaemon-gtk (<< 0.41+bzr582-0ubuntu1) |
| 4542 | +Replaces: python-aptdaemon-gtk (<< 0.41+bzr582-0ubuntu1) |
| 4543 | +Description: Python 3 GTK+ 3 widgets to run an aptdaemon client |
| 4544 | + Aptdaemon is a transaction based package management daemon. It allows |
| 4545 | + normal users to perform package management tasks, e.g. refreshing the |
| 4546 | + cache, upgrading the system, installing or removing software packages. |
| 4547 | + . |
| 4548 | + This package provides the Python 3 GTK+ 3 widgets to implement a fully |
| 4549 | + working graphical client. The widgets can be used to initiate, to |
| 4550 | + monitor and to control a transaction. The API is not stable yet. |
| 4551 | + |
| 4552 | Package: python-aptdaemon.gtk3widgets |
| 4553 | Architecture: all |
| 4554 | Section: python |
| 4555 | -Depends: ${shlibs:Depends}, |
| 4556 | - ${misc:Depends}, |
| 4557 | - ${python:Depends}, |
| 4558 | +Depends: ${misc:Depends}, |
| 4559 | + ${python3:Depends}, |
| 4560 | python-aptdaemon (= ${binary:Version}), |
| 4561 | python-gi, |
| 4562 | gir1.2-gtk-3.0, |
| 4563 | @@ -181,12 +226,11 @@ |
| 4564 | aptdaemon-data |
| 4565 | Conflicts: python-aptdaemon-gtk (<< 0.41+bzr582-0ubuntu1) |
| 4566 | Replaces: python-aptdaemon-gtk (<< 0.41+bzr582-0ubuntu1) |
| 4567 | -XB-Python-Version: ${python:Versions} |
| 4568 | -Description: Python GTK+ 3 widgets to run an aptdaemon client |
| 4569 | +Description: Python 2 GTK+ 3 widgets to run an aptdaemon client |
| 4570 | Aptdaemon is a transaction based package management daemon. It allows |
| 4571 | normal users to perform package management tasks, e.g. refreshing the |
| 4572 | cache, upgrading the system, installing or removing software packages. |
| 4573 | . |
| 4574 | - This package provides the Python GTK+ 3 widgets to implement a fully |
| 4575 | + This package provides the Python 2 GTK+ 3 widgets to implement a fully |
| 4576 | working graphical client. The widgets can be used to initiate, to |
| 4577 | monitor and to control a transaction. The API is not stable yet. |
| 4578 | |
| 4579 | === added file 'debian/patches/disable_simulate_test.patch' |
| 4580 | --- debian/patches/disable_simulate_test.patch 1970-01-01 00:00:00 +0000 |
| 4581 | +++ debian/patches/disable_simulate_test.patch 2012-06-13 16:29:18 +0000 |
| 4582 | @@ -0,0 +1,12 @@ |
| 4583 | +=== modified file 'tests/test_simulate.py' |
| 4584 | +--- old/tests/test_simulate.py 2012-03-19 07:58:34 +0000 |
| 4585 | ++++ new/tests/test_simulate.py 2012-06-04 11:06:46 +0000 |
| 4586 | +@@ -25,6 +25,7 @@ |
| 4587 | + def setUp(self): |
| 4588 | + """Setup a chroot, run the aptdaemon and a fake PolicyKit daemon.""" |
| 4589 | + # Setup chroot |
| 4590 | ++ self.skipTest("Temporarily disabled") |
| 4591 | + self.chroot = aptdaemon.test.Chroot() |
| 4592 | + self.chroot.setup() |
| 4593 | + self.addCleanup(self.chroot.remove) |
| 4594 | + |
| 4595 | |
| 4596 | === modified file 'debian/patches/series' |
| 4597 | --- debian/patches/series 2011-12-15 10:15:46 +0000 |
| 4598 | +++ debian/patches/series 2012-06-13 16:29:18 +0000 |
| 4599 | @@ -0,0 +1,2 @@ |
| 4600 | +disable_simulate_test.patch |
| 4601 | +test-suite-fixes |
| 4602 | |
| 4603 | === added file 'debian/patches/test-suite-fixes' |
| 4604 | --- debian/patches/test-suite-fixes 1970-01-01 00:00:00 +0000 |
| 4605 | +++ debian/patches/test-suite-fixes 2012-06-13 16:29:18 +0000 |
| 4606 | @@ -0,0 +1,53 @@ |
| 4607 | +Description: fixes for the test suite |
| 4608 | + fixes against upstream bzr to make the test suite work on quantal, with |
| 4609 | + python2+python3: |
| 4610 | + aptdaemon/test.py: explicitly set the chroot directory in the apt config |
| 4611 | + as part of the test setup, without which apt-key's chroot handling won't |
| 4612 | + work. |
| 4613 | + test/test_pk.py: increase the sleep on startup, to allow longer for |
| 4614 | + fake-polkitd to connect to dbus. |
| 4615 | + aptdaemon/worker.py: restore compatibility with python2, which doesn't |
| 4616 | + have urllib.parse. |
| 4617 | +Author: Steve Langasek <steve.langasek@ubuntu.com> |
| 4618 | + |
| 4619 | +Index: trunk/aptdaemon/test.py |
| 4620 | +=================================================================== |
| 4621 | +--- trunk.orig/aptdaemon/test.py |
| 4622 | ++++ trunk/aptdaemon/test.py |
| 4623 | +@@ -79,6 +79,7 @@ |
| 4624 | + cnf.write("Dir::Bin::Apt-Key %s;" % apt_key_wrapper) |
| 4625 | + apt_pkg.read_config_file(apt_pkg.config, config_path) |
| 4626 | + apt_pkg.init_system() |
| 4627 | ++ apt_pkg.config["Dir"] = self.path |
| 4628 | + |
| 4629 | + def remove(self): |
| 4630 | + """Remove the files of the chroot.""" |
| 4631 | +Index: trunk/aptdaemon/worker.py |
| 4632 | +=================================================================== |
| 4633 | +--- trunk.orig/aptdaemon/worker.py |
| 4634 | ++++ trunk/aptdaemon/worker.py |
| 4635 | +@@ -31,7 +31,10 @@ |
| 4636 | + import tempfile |
| 4637 | + import time |
| 4638 | + import traceback |
| 4639 | +-from urllib.parse import urlsplit, urlunsplit |
| 4640 | ++try: |
| 4641 | ++ from urllib.parse import urlsplit, urlunsplit |
| 4642 | ++except ImportError: |
| 4643 | ++ from urlparse import urlsplit, urlunsplit |
| 4644 | + |
| 4645 | + import apt |
| 4646 | + import apt.auth |
| 4647 | +Index: trunk/tests/test_pk.py |
| 4648 | +=================================================================== |
| 4649 | +--- trunk.orig/tests/test_pk.py |
| 4650 | ++++ trunk/tests/test_pk.py |
| 4651 | +@@ -66,7 +66,7 @@ |
| 4652 | + self.start_session_aptd(self.chroot.path) |
| 4653 | + # Start the fake PolikcyKit daemon |
| 4654 | + self.start_fake_polkitd() |
| 4655 | +- time.sleep(0.5) |
| 4656 | ++ time.sleep(2.5) |
| 4657 | + |
| 4658 | + def tearDown(self): |
| 4659 | + shutil.rmtree(self.workdir) |
| 4660 | |
| 4661 | === modified file 'debian/python-aptdaemon.pkcompat.install' |
| 4662 | --- debian/python-aptdaemon.pkcompat.install 2011-11-21 10:08:24 +0000 |
| 4663 | +++ debian/python-aptdaemon.pkcompat.install 2012-06-13 16:29:18 +0000 |
| 4664 | @@ -1,3 +1,4 @@ |
| 4665 | -usr/lib/python2.*/*-packages/aptdaemon/pkcompat.py |
| 4666 | +usr/lib/python3*/*-packages/aptdaemon/pkcompat.py |
| 4667 | +usr/lib/python3*/*-packages/aptdaemon/pkenums.py |
| 4668 | usr/share/dbus-1/system-services/org.freedesktop.PackageKit.service |
| 4669 | etc/dbus-1/system.d/org.freedesktop.PackageKit-aptd.conf |
| 4670 | |
| 4671 | === modified file 'debian/python-aptdaemon.test.install' |
| 4672 | --- debian/python-aptdaemon.test.install 2012-05-23 12:53:16 +0000 |
| 4673 | +++ debian/python-aptdaemon.test.install 2012-06-13 16:29:18 +0000 |
| 4674 | @@ -1,4 +1,4 @@ |
| 4675 | -usr/lib/python2.*/*-packages/aptdaemon/test.py |
| 4676 | +usr/lib/python3*/*-packages/aptdaemon/test.py |
| 4677 | tests/repo/glatzor.gpg /usr/share/aptdaemon/tests/repo/ |
| 4678 | tests/repo/gstreamer0.10-silly_0.1-0_all.deb /usr/share/aptdaemon/tests/repo/ |
| 4679 | tests/repo/Packages /usr/share/aptdaemon/tests/repo/ |
| 4680 | |
| 4681 | === added file 'debian/python3-aptdaemon.gtk3widgets.examples' |
| 4682 | --- debian/python3-aptdaemon.gtk3widgets.examples 1970-01-01 00:00:00 +0000 |
| 4683 | +++ debian/python3-aptdaemon.gtk3widgets.examples 2012-06-13 16:29:18 +0000 |
| 4684 | @@ -0,0 +1,1 @@ |
| 4685 | +gtk3-demo.py |
| 4686 | |
| 4687 | === added file 'debian/python3-aptdaemon.gtk3widgets.install' |
| 4688 | --- debian/python3-aptdaemon.gtk3widgets.install 1970-01-01 00:00:00 +0000 |
| 4689 | +++ debian/python3-aptdaemon.gtk3widgets.install 2012-06-13 16:29:18 +0000 |
| 4690 | @@ -0,0 +1,1 @@ |
| 4691 | +usr/lib/python3*/*-packages/aptdaemon/gtk3widgets.py |
| 4692 | |
| 4693 | === added file 'debian/python3-aptdaemon.install' |
| 4694 | --- debian/python3-aptdaemon.install 1970-01-01 00:00:00 +0000 |
| 4695 | +++ debian/python3-aptdaemon.install 2012-06-13 16:29:18 +0000 |
| 4696 | @@ -0,0 +1,16 @@ |
| 4697 | +usr/lib/python3*/*-packages/aptdaemon/__init__.py |
| 4698 | +usr/lib/python3*/*-packages/aptdaemon/client.py |
| 4699 | +usr/lib/python3*/*-packages/aptdaemon/config.py |
| 4700 | +usr/lib/python3*/*-packages/aptdaemon/console.py |
| 4701 | +usr/lib/python3*/*-packages/aptdaemon/core.py |
| 4702 | +usr/lib/python3*/*-packages/aptdaemon/crash.py |
| 4703 | +usr/lib/python3*/*-packages/aptdaemon/debconf.py |
| 4704 | +usr/lib/python3*/*-packages/aptdaemon/enums.py |
| 4705 | +usr/lib/python3*/*-packages/aptdaemon/errors.py |
| 4706 | +usr/lib/python3*/*-packages/aptdaemon/loop.py |
| 4707 | +usr/lib/python3*/*-packages/aptdaemon/lock.py |
| 4708 | +usr/lib/python3*/*-packages/aptdaemon/networking.py |
| 4709 | +usr/lib/python3*/*-packages/aptdaemon/policykit1.py |
| 4710 | +usr/lib/python3*/*-packages/aptdaemon/progress.py |
| 4711 | +usr/lib/python3*/*-packages/aptdaemon/utils.py |
| 4712 | +usr/lib/python3*/*-packages/aptdaemon/worker.py |
| 4713 | |
| 4714 | === added file 'debian/python3-aptdaemon.pkcompat.docs' |
| 4715 | --- debian/python3-aptdaemon.pkcompat.docs 1970-01-01 00:00:00 +0000 |
| 4716 | +++ debian/python3-aptdaemon.pkcompat.docs 2012-06-13 16:29:18 +0000 |
| 4717 | @@ -0,0 +1,1 @@ |
| 4718 | +README.PackageKit |
| 4719 | |
| 4720 | === added file 'debian/python3-aptdaemon.pkcompat.install' |
| 4721 | --- debian/python3-aptdaemon.pkcompat.install 1970-01-01 00:00:00 +0000 |
| 4722 | +++ debian/python3-aptdaemon.pkcompat.install 2012-06-13 16:29:18 +0000 |
| 4723 | @@ -0,0 +1,4 @@ |
| 4724 | +usr/lib/python3*/*-packages/aptdaemon/pkcompat.py |
| 4725 | +usr/lib/python3*/*-packages/aptdaemon/pkenums.py |
| 4726 | +usr/share/dbus-1/system-services/org.freedesktop.PackageKit.service |
| 4727 | +etc/dbus-1/system.d/org.freedesktop.PackageKit-aptd.conf |
| 4728 | |
| 4729 | === added file 'debian/python3-aptdaemon.test.examples' |
| 4730 | --- debian/python3-aptdaemon.test.examples 1970-01-01 00:00:00 +0000 |
| 4731 | +++ debian/python3-aptdaemon.test.examples 2012-06-13 16:29:18 +0000 |
| 4732 | @@ -0,0 +1,1 @@ |
| 4733 | +tests/test_client.py |
| 4734 | |
| 4735 | === added file 'debian/python3-aptdaemon.test.install' |
| 4736 | --- debian/python3-aptdaemon.test.install 1970-01-01 00:00:00 +0000 |
| 4737 | +++ debian/python3-aptdaemon.test.install 2012-06-13 16:29:18 +0000 |
| 4738 | @@ -0,0 +1,18 @@ |
| 4739 | +usr/lib/python3*/*-packages/aptdaemon/test.py |
| 4740 | +tests/repo/glatzor.gpg /usr/share/aptdaemon/tests/repo/ |
| 4741 | +tests/repo/gstreamer0.10-silly_0.1-0_all.deb /usr/share/aptdaemon/tests/repo/ |
| 4742 | +tests/repo/Packages /usr/share/aptdaemon/tests/repo/ |
| 4743 | +tests/repo/Release /usr/share/aptdaemon/tests/repo/ |
| 4744 | +tests/repo/Release.gpg /usr/share/aptdaemon/tests/repo/ |
| 4745 | +tests/repo/silly-base_0.1-0_all.deb /usr/share/aptdaemon/tests/repo/ |
| 4746 | +tests/repo/silly-base_0.1-0update1_all.deb /usr/share/aptdaemon/tests/repo/ |
| 4747 | +tests/repo/silly-broken_0.1-0_all.deb /usr/share/aptdaemon/tests/repo/ |
| 4748 | +tests/repo/silly-config_0.1-0_all.deb /usr/share/aptdaemon/tests/repo/ |
| 4749 | +tests/repo/silly-depend-base_0.1-0_all.deb /usr/share/aptdaemon/tests/repo/ |
| 4750 | +tests/repo/silly-essential_0.1-0_all.deb /usr/share/aptdaemon/tests/repo/ |
| 4751 | +tests/repo/silly-fail_0.1-0_all.deb /usr/share/aptdaemon/tests/repo/ |
| 4752 | +tests/repo/silly-important_0.1-0_all.deb /usr/share/aptdaemon/tests/repo/ |
| 4753 | +tests/repo/silly-postinst-input_0.1-0_all.deb /usr/share/aptdaemon/tests/repo/ |
| 4754 | +tests/dpkg-wrapper.sh /usr/share/aptdaemon/tests/ |
| 4755 | +tests/fake-polkitd.py /usr/share/aptdaemon/tests/ |
| 4756 | +tests/dbus.conf /usr/share/aptdaemon/tests/ |
| 4757 | |
| 4758 | === modified file 'debian/rules' |
| 4759 | --- debian/rules 2011-11-21 10:08:24 +0000 |
| 4760 | +++ debian/rules 2012-06-13 16:29:18 +0000 |
| 4761 | @@ -1,12 +1,32 @@ |
| 4762 | #!/usr/bin/make -f |
| 4763 | |
| 4764 | +#DH_VERBOSE=1 |
| 4765 | + |
| 4766 | +PYTHON2=$(shell pyversions -vr) |
| 4767 | +PYTHON3=$(shell py3versions -vr) |
| 4768 | + |
| 4769 | %: |
| 4770 | - dh --with=python2,translations $@ |
| 4771 | + dh $@ --with=python2,python3,translations |
| 4772 | + |
| 4773 | +build-python%: |
| 4774 | + python$* setup.py build |
| 4775 | + |
| 4776 | +override_dh_auto_build: $(PYTHON3:%=build-python%) |
| 4777 | + dh_auto_build |
| 4778 | + |
| 4779 | +install-python%: |
| 4780 | + python$* setup.py install --root=$(CURDIR)/debian/tmp --install-layout=deb |
| 4781 | + |
| 4782 | +override_dh_auto_install: $(PYTHON3:%=install-python%) |
| 4783 | + dh_auto_install |
| 4784 | |
| 4785 | override_dh_auto_clean: |
| 4786 | dh_auto_clean |
| 4787 | rm -rf build *.egg-info po/aptdaemon.pot |
| 4788 | |
| 4789 | -# mvo: disabled temporarely, see changelog for 0.41+bzr586-0ubuntu1 |
| 4790 | -#override_dh_auto_test: |
| 4791 | -# unit2 discover |
| 4792 | +ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS))) |
| 4793 | +test-python%: |
| 4794 | + python$* setup.py test -vv |
| 4795 | + |
| 4796 | +override_dh_auto_test: $(PYTHON3:%=test-python%) $(PYTHON2:%=test-python%) |
| 4797 | +endif |
| 4798 | |
| 4799 | === added file 'doc/source/aptdaemon.gtk3widgets.rst' |
| 4800 | --- doc/source/aptdaemon.gtk3widgets.rst 1970-01-01 00:00:00 +0000 |
| 4801 | +++ doc/source/aptdaemon.gtk3widgets.rst 2012-06-13 16:29:18 +0000 |
| 4802 | @@ -0,0 +1,5 @@ |
| 4803 | +:mod:`aptdaemon.gtk3widgets` --- The gtk3widgets module |
| 4804 | +===================================================== |
| 4805 | + |
| 4806 | +.. automodule:: aptdaemon.gtk3widgets |
| 4807 | + :members: |
| 4808 | |
| 4809 | === removed file 'doc/source/aptdaemon.gtkwidgets.rst' |
| 4810 | --- doc/source/aptdaemon.gtkwidgets.rst 2011-11-21 10:08:24 +0000 |
| 4811 | +++ doc/source/aptdaemon.gtkwidgets.rst 1970-01-01 00:00:00 +0000 |
| 4812 | @@ -1,5 +0,0 @@ |
| 4813 | -:mod:`aptdaemon.gtkwidgets` --- The gtkwidgets module |
| 4814 | -===================================================== |
| 4815 | - |
| 4816 | -.. automodule:: aptdaemon.gtkwidgets |
| 4817 | - :members: |
| 4818 | |
| 4819 | === modified file 'doc/source/index.rst' |
| 4820 | --- doc/source/index.rst 2011-11-21 10:08:24 +0000 |
| 4821 | +++ doc/source/index.rst 2012-06-13 16:29:18 +0000 |
| 4822 | @@ -8,7 +8,7 @@ |
| 4823 | |
| 4824 | aptdaemon.client |
| 4825 | aptdaemon.enums |
| 4826 | - aptdaemon.gtkwidgets |
| 4827 | + aptdaemon.gtk3widgets |
| 4828 | |
| 4829 | dbus |
| 4830 | plugins |
| 4831 | |
| 4832 | === modified file 'gtk-demo.py' |
| 4833 | --- gtk-demo.py 2011-12-01 14:40:52 +0000 |
| 4834 | +++ gtk-demo.py 2012-06-13 16:29:18 +0000 |
| 4835 | @@ -1,4 +1,4 @@ |
| 4836 | -#!/usr/bin/env python |
| 4837 | +#!/usr/bin/python |
| 4838 | # -*- coding: utf-8 -*- |
| 4839 | """ |
| 4840 | Provides a graphical demo application for aptdaemon |
| 4841 | |
| 4842 | === modified file 'gtk3-demo.py' |
| 4843 | --- gtk3-demo.py 2011-12-01 14:40:52 +0000 |
| 4844 | +++ gtk3-demo.py 2012-06-13 16:29:18 +0000 |
| 4845 | @@ -1,4 +1,4 @@ |
| 4846 | -#!/usr/bin/env python |
| 4847 | +#!/usr/bin/python3 |
| 4848 | # -*- coding: utf-8 -*- |
| 4849 | """ |
| 4850 | Provides a graphical demo application for aptdaemon |
| 4851 | @@ -66,14 +66,11 @@ |
| 4852 | self._run_transaction(trans) |
| 4853 | |
| 4854 | def _on_error(self, error): |
| 4855 | - try: |
| 4856 | - raise error |
| 4857 | - except aptdaemon.errors.NotAuthorizedError: |
| 4858 | + if isinstance(error, aptdaemon.errors.NotAuthorizedError): |
| 4859 | # Silently ignore auth failures |
| 4860 | return |
| 4861 | - except aptdaemon.errors.TransactionFailed as error: |
| 4862 | - pass |
| 4863 | - except Exception as error: |
| 4864 | + elif not isinstance(error, aptdaemon.errors.TransactionFailed): |
| 4865 | + # Catch internal errors of the client |
| 4866 | error = aptdaemon.errors.TransactionFailed(ERROR_UNKNOWN, |
| 4867 | str(error)) |
| 4868 | dia = AptErrorDialog(error) |
| 4869 | |
| 4870 | === modified file 'po/af.po' |
| 4871 | --- po/af.po 2011-11-21 10:08:24 +0000 |
| 4872 | +++ po/af.po 2012-06-13 16:29:18 +0000 |
| 4873 | @@ -7,499 +7,585 @@ |
| 4874 | msgstr "" |
| 4875 | "Project-Id-Version: aptdaemon\n" |
| 4876 | "Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" |
| 4877 | -"POT-Creation-Date: 2010-09-27 21:46+0000\n" |
| 4878 | -"PO-Revision-Date: 2010-07-26 09:31+0000\n" |
| 4879 | +"POT-Creation-Date: 2012-04-10 15:24+0000\n" |
| 4880 | +"PO-Revision-Date: 2011-01-16 11:40+0000\n" |
| 4881 | "Last-Translator: Michael Vogt <michael.vogt@ubuntu.com>\n" |
| 4882 | "Language-Team: Afrikaans <af@li.org>\n" |
| 4883 | "MIME-Version: 1.0\n" |
| 4884 | "Content-Type: text/plain; charset=UTF-8\n" |
| 4885 | "Content-Transfer-Encoding: 8bit\n" |
| 4886 | "Plural-Forms: nplurals=2; plural=n != 1;\n" |
| 4887 | -"X-Launchpad-Export-Date: 2010-09-28 16:44+0000\n" |
| 4888 | -"X-Generator: Launchpad (build Unknown)\n" |
| 4889 | - |
| 4890 | -#. This privilege allows to call AddRepository, UpdateCache(Partially) |
| 4891 | -#. and InstallPackages in a row and only authenticating once. |
| 4892 | -#. |
| 4893 | -#. The client has to authenticate for this privilege before calling |
| 4894 | -#. the aptdaemon methods. |
| 4895 | +"X-Launchpad-Export-Date: 2012-05-26 09:08+0000\n" |
| 4896 | +"X-Generator: Launchpad (build 15288)\n" |
| 4897 | + |
| 4898 | +#: ../data/org.debian.apt.policy.in.h:1 |
| 4899 | +msgid "List keys of trusted vendors" |
| 4900 | +msgstr "" |
| 4901 | + |
| 4902 | +#: ../data/org.debian.apt.policy.in.h:2 |
| 4903 | +msgid "To view the list of trusted keys, you need to authenticate." |
| 4904 | +msgstr "" |
| 4905 | + |
| 4906 | +#: ../data/org.debian.apt.policy.in.h:3 ../aptdaemon/console.py:607 |
| 4907 | +msgid "Remove downloaded package files" |
| 4908 | +msgstr "" |
| 4909 | + |
| 4910 | +#: ../data/org.debian.apt.policy.in.h:4 |
| 4911 | +msgid "To clean downloaded package files, you need to authenticate." |
| 4912 | +msgstr "" |
| 4913 | + |
| 4914 | +#: ../data/org.debian.apt.policy.in.h:5 |
| 4915 | +msgid "Change software configuration" |
| 4916 | +msgstr "" |
| 4917 | + |
| 4918 | #: ../data/org.debian.apt.policy.in.h:6 |
| 4919 | -msgid "Add a new repository and install packages from it" |
| 4920 | -msgstr "" |
| 4921 | - |
| 4922 | -#. This privilege allows to call AddRepository, UpdateCache(Partially) |
| 4923 | -#. and InstallPackages in a row and only authenticating once. |
| 4924 | -#. |
| 4925 | -#. The client has to authenticate for this privilege before calling |
| 4926 | -#. the aptdaemon methods. |
| 4927 | -#. |
| 4928 | -#. The only difference to install-packages-from-new-repo is the wording |
| 4929 | -#. of the message. It is required by Ubuntu's Software-Center. |
| 4930 | -#: ../data/org.debian.apt.policy.in.h:15 |
| 4931 | -msgid "" |
| 4932 | -"Add a new repository of purchased software and install packages from it" |
| 4933 | -msgstr "" |
| 4934 | - |
| 4935 | -#: ../data/org.debian.apt.policy.in.h:16 |
| 4936 | -msgid "Cancel the task of another user" |
| 4937 | -msgstr "Kanselleer die taak van 'n ander gebruiker" |
| 4938 | - |
| 4939 | -#: ../data/org.debian.apt.policy.in.h:17 |
| 4940 | +msgid "To change software settings, you need to authenticate." |
| 4941 | +msgstr "" |
| 4942 | + |
| 4943 | +#: ../data/org.debian.apt.policy.in.h:7 |
| 4944 | msgid "Change software repository" |
| 4945 | msgstr "" |
| 4946 | |
| 4947 | -#: ../data/org.debian.apt.policy.in.h:18 |
| 4948 | -msgid "Install or remove packages" |
| 4949 | +#: ../data/org.debian.apt.policy.in.h:8 |
| 4950 | +msgid "To change software repository settings, you need to authenticate." |
| 4951 | msgstr "" |
| 4952 | |
| 4953 | -#: ../data/org.debian.apt.policy.in.h:19 |
| 4954 | +#: ../data/org.debian.apt.policy.in.h:9 |
| 4955 | msgid "Install package file" |
| 4956 | msgstr "Installeer pakketlêer" |
| 4957 | |
| 4958 | +#: ../data/org.debian.apt.policy.in.h:10 |
| 4959 | +msgid "To install this package, you need to authenticate." |
| 4960 | +msgstr "" |
| 4961 | + |
| 4962 | +#: ../data/org.debian.apt.policy.in.h:11 |
| 4963 | +msgid "Update package information" |
| 4964 | +msgstr "Opdateer pakketinformasie" |
| 4965 | + |
| 4966 | +#: ../data/org.debian.apt.policy.in.h:12 |
| 4967 | +msgid "To update the software catalog, you need to authenticate." |
| 4968 | +msgstr "" |
| 4969 | + |
| 4970 | +#: ../data/org.debian.apt.policy.in.h:13 |
| 4971 | +msgid "Install or remove packages" |
| 4972 | +msgstr "" |
| 4973 | + |
| 4974 | +#: ../data/org.debian.apt.policy.in.h:14 |
| 4975 | +msgid "To install or remove software, you need to authenticate." |
| 4976 | +msgstr "" |
| 4977 | + |
| 4978 | +#. This privilege allows to call AddRepository, UpdateCache(Partially) |
| 4979 | +#. and InstallPackages in a row and only authenticating once. |
| 4980 | +#. |
| 4981 | +#. The client has to authenticate for this privilege before calling |
| 4982 | +#. the aptdaemon methods. |
| 4983 | #: ../data/org.debian.apt.policy.in.h:20 |
| 4984 | -msgid "List keys of trusted vendors" |
| 4985 | +msgid "Add a new repository and install packages from it" |
| 4986 | msgstr "" |
| 4987 | |
| 4988 | #: ../data/org.debian.apt.policy.in.h:21 |
| 4989 | -msgid "Set a proxy for software downloads" |
| 4990 | -msgstr "" |
| 4991 | - |
| 4992 | -#: ../data/org.debian.apt.policy.in.h:22 |
| 4993 | -msgid "To cancel someone else's software changes, you need to authenticate." |
| 4994 | -msgstr "" |
| 4995 | - |
| 4996 | -#: ../data/org.debian.apt.policy.in.h:23 |
| 4997 | -msgid "To change software repository settings, you need to authenticate." |
| 4998 | -msgstr "" |
| 4999 | - |
| 5000 | -#: ../data/org.debian.apt.policy.in.h:24 |
The diff has been truncated for viewing.

