summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 18:07:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 18:07:41 +0000
commit76926159194e180003aa78de97e5f287bf4325a5 (patch)
tree2cea7245cdc3f66355900c820c145eba90598766
parentInitial commit. (diff)
downloadpython-apt-76926159194e180003aa78de97e5f287bf4325a5.tar.xz
python-apt-76926159194e180003aa78de97e5f287bf4325a5.zip
Adding upstream version 2.7.6.upstream/2.7.6
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
-rw-r--r--.gitlab-ci.yml25
-rw-r--r--.pre-commit-config.yaml25
-rw-r--r--AUTHORS7
-rw-r--r--COPYING.GPL340
-rw-r--r--Dockerfile11
-rw-r--r--README.md49
-rw-r--r--TODO4
-rw-r--r--apt/__init__.py40
-rw-r--r--apt/auth.py311
-rw-r--r--apt/cache.py1004
-rw-r--r--apt/cdrom.py91
-rw-r--r--apt/debfile.py861
-rw-r--r--apt/package.py1559
-rw-r--r--apt/progress/__init__.py28
-rw-r--r--apt/progress/base.py332
-rw-r--r--apt/progress/text.py294
-rw-r--r--apt/py.typed0
-rw-r--r--apt/utils.py100
-rw-r--r--aptsources/__init__.py6
-rw-r--r--aptsources/_deb822.py144
-rw-r--r--aptsources/distinfo.py415
-rw-r--r--aptsources/distro.py648
-rw-r--r--aptsources/sourceslist.py1083
-rw-r--r--data/templates/Blankon.info.in370
-rw-r--r--data/templates/Blankon.mirrors17
-rw-r--r--data/templates/Debian.info.in119
-rw-r--r--data/templates/Debian.mirrors394
-rw-r--r--data/templates/Kali.info.in32
-rw-r--r--data/templates/Kali.mirrors2
-rw-r--r--data/templates/README.templates59
-rw-r--r--data/templates/Tanglu.info.in42
-rw-r--r--data/templates/Tanglu.mirrors3
-rw-r--r--data/templates/Ubuntu.info.in223
-rw-r--r--data/templates/Ubuntu.mirrors665
-rw-r--r--data/templates/gNewSense.info.in55
-rw-r--r--data/templates/gNewSense.mirrors489
-rw-r--r--doc/Makefile79
-rw-r--r--doc/client-example.cc68
-rw-r--r--doc/examples/acquire.py80
-rw-r--r--doc/examples/action.py116
-rw-r--r--doc/examples/all_deps.py37
-rw-r--r--doc/examples/architecture.py12
-rwxr-xr-xdoc/examples/build-deps-old.py74
-rwxr-xr-xdoc/examples/build-deps.py58
-rw-r--r--doc/examples/cdrom.py24
-rwxr-xr-xdoc/examples/checkstate.py37
-rwxr-xr-xdoc/examples/config.py60
-rwxr-xr-xdoc/examples/configisc.py49
-rwxr-xr-xdoc/examples/deb_inspect.py61
-rw-r--r--doc/examples/depcache.py109
-rwxr-xr-xdoc/examples/dependant-pkgs.py38
-rw-r--r--doc/examples/desc.py25
-rw-r--r--doc/examples/indexfile.py22
-rw-r--r--doc/examples/inst.py47
-rw-r--r--doc/examples/metaindex.py16
-rwxr-xr-xdoc/examples/print_uris.py10
-rw-r--r--doc/examples/progress.py118
-rwxr-xr-xdoc/examples/recommends.py37
-rwxr-xr-xdoc/examples/records.py16
-rw-r--r--doc/examples/sources.py21
-rwxr-xr-xdoc/examples/tagfile.py8
-rwxr-xr-xdoc/examples/update.py14
-rwxr-xr-xdoc/examples/versiontest.py54
-rw-r--r--doc/source/c++/api.rst858
-rw-r--r--doc/source/c++/embedding.rst34
-rw-r--r--doc/source/c++/index.rst8
-rw-r--r--doc/source/conf.py245
-rw-r--r--doc/source/contents.rst19
-rw-r--r--doc/source/examples/apt-cdrom.py79
-rwxr-xr-xdoc/source/examples/cache-packages.py23
-rwxr-xr-xdoc/source/examples/cache-pkgfile.py30
-rwxr-xr-xdoc/source/examples/dpkg-contents.py68
-rwxr-xr-xdoc/source/examples/dpkg-extract.py27
-rwxr-xr-xdoc/source/examples/dpkg-info.py22
-rwxr-xr-xdoc/source/examples/missing-deps.py59
-rwxr-xr-xdoc/source/examples/update-print-uris.py24
-rw-r--r--doc/source/library/apt.cache.rst83
-rw-r--r--doc/source/library/apt.cdrom.rst7
-rw-r--r--doc/source/library/apt.debfile.rst39
-rw-r--r--doc/source/library/apt.package.rst122
-rw-r--r--doc/source/library/apt.progress.base.rst335
-rw-r--r--doc/source/library/apt.progress.text.rst21
-rw-r--r--doc/source/library/apt_inst.rst323
-rw-r--r--doc/source/library/apt_pkg.rst2904
-rw-r--r--doc/source/library/aptsources.distinfo.rst11
-rw-r--r--doc/source/library/aptsources.distro.rst11
-rw-r--r--doc/source/library/aptsources.sourceslist.rst11
-rw-r--r--doc/source/library/index.rst35
-rw-r--r--doc/source/templates/indexcontent.html50
-rw-r--r--doc/source/templates/layout.html4
-rw-r--r--doc/source/tutorials/apt-cdrom.rst156
-rw-r--r--doc/source/tutorials/apt-get.rst46
-rw-r--r--doc/source/tutorials/contributing.rst315
-rw-r--r--doc/source/tutorials/index.rst8
-rw-r--r--doc/source/whatsnew/0.7.100.rst211
-rw-r--r--doc/source/whatsnew/0.8.0.rst38
-rw-r--r--doc/source/whatsnew/0.9.4.rst17
-rw-r--r--doc/source/whatsnew/1.0.rst75
-rw-r--r--doc/source/whatsnew/1.1.rst28
-rw-r--r--doc/source/whatsnew/1.4.rst16
-rw-r--r--doc/source/whatsnew/1.6.rst26
-rw-r--r--doc/source/whatsnew/1.7.rst42
-rw-r--r--doc/source/whatsnew/1.8.rst8
-rw-r--r--doc/source/whatsnew/2.0.rst37
-rw-r--r--doc/source/whatsnew/2.1.rst7
-rw-r--r--doc/source/whatsnew/index.rst9
-rw-r--r--mypy.ini2
-rw-r--r--po/POTFILES.in8
-rw-r--r--po/ar.po622
-rw-r--r--po/be.po638
-rw-r--r--po/bg.po680
-rw-r--r--po/bn.po671
-rw-r--r--po/ca.po679
-rw-r--r--po/cs.po660
-rw-r--r--po/csb.po621
-rw-r--r--po/da.po637
-rw-r--r--po/de.po645
-rw-r--r--po/el.po638
-rw-r--r--po/en_AU.po660
-rw-r--r--po/en_CA.po681
-rw-r--r--po/eo.po649
-rw-r--r--po/es.po663
-rw-r--r--po/fi.po639
-rw-r--r--po/fr.po652
-rw-r--r--po/gl.po661
-rw-r--r--po/he.po667
-rw-r--r--po/hr.po660
-rw-r--r--po/hu.po647
-rw-r--r--po/id.po638
-rw-r--r--po/it.po662
-rw-r--r--po/ja.po640
-rw-r--r--po/ka.po661
-rw-r--r--po/ko.po659
-rw-r--r--po/ku.po660
-rw-r--r--po/lt.po664
-rw-r--r--po/lv.po627
-rw-r--r--po/mk.po681
-rw-r--r--po/nb.po683
-rw-r--r--po/ne.po682
-rw-r--r--po/nl.po639
-rw-r--r--po/oc.po661
-rw-r--r--po/pl.po644
-rw-r--r--po/pt.po657
-rw-r--r--po/pt_BR.po648
-rw-r--r--po/python-apt.pot365
-rw-r--r--po/ro.po663
-rw-r--r--po/ru.po665
-rw-r--r--po/sk.po638
-rw-r--r--po/sl.po649
-rw-r--r--po/sq.po623
-rw-r--r--po/sr.po648
-rw-r--r--po/sv.po662
-rw-r--r--po/th.po659
-rw-r--r--po/tl.po639
-rw-r--r--po/tr.po659
-rw-r--r--po/uk.po635
-rw-r--r--po/vi.po683
-rw-r--r--po/zh_CN.po656
-rw-r--r--po/zh_HK.po633
-rw-r--r--po/zh_TW.po653
-rwxr-xr-xpre-build.sh18
-rw-r--r--python/acquire-item.cc356
-rw-r--r--python/acquire.cc424
-rw-r--r--python/apt_instmodule.cc87
-rw-r--r--python/apt_instmodule.h29
-rw-r--r--python/apt_pkgmodule.cc1117
-rw-r--r--python/apt_pkgmodule.h214
-rw-r--r--python/arfile.cc744
-rw-r--r--python/cache.cc1600
-rw-r--r--python/cachegroup.cc188
-rw-r--r--python/cdrom.cc139
-rw-r--r--python/configuration.cc613
-rw-r--r--python/depcache.cc1169
-rw-r--r--python/generic.cc122
-rw-r--r--python/generic.h336
-rw-r--r--python/hashes.cc135
-rw-r--r--python/hashstring.cc182
-rw-r--r--python/hashstringlist.cc220
-rw-r--r--python/indexfile.cc130
-rw-r--r--python/lock.cc268
-rw-r--r--python/metaindex.cc117
-rw-r--r--python/orderlist.cc317
-rw-r--r--python/pkgmanager.cc375
-rw-r--r--python/pkgrecords.cc280
-rw-r--r--python/pkgrecords.h10
-rw-r--r--python/pkgsrcrecords.cc438
-rw-r--r--python/policy.cc243
-rw-r--r--python/progress.cc473
-rw-r--r--python/progress.h120
-rw-r--r--python/python-apt-helpers.cc69
-rw-r--r--python/python-apt.h368
-rw-r--r--python/sourcelist.cc170
-rw-r--r--python/string.cc142
-rw-r--r--python/tag.cc1063
-rw-r--r--python/tarfile.cc521
-rw-r--r--setup.cfg5
-rw-r--r--setup.py159
-rw-r--r--tests/__init__.py1
-rw-r--r--tests/data/aptsources/lsb-release4
-rw-r--r--tests/data/aptsources/os-release10
-rw-r--r--tests/data/aptsources/sources.list10
-rw-r--r--tests/data/aptsources/sources.list.d.testDistribution/main.sources74
-rw-r--r--tests/data/aptsources/sources.list.d.testDuplication/main.sources10
-rw-r--r--tests/data/aptsources/sources.list.d/main.sources32
-rw-r--r--tests/data/aptsources/sources.list.testDistribution14
-rw-r--r--tests/data/aptsources/sources.list.testDuplication2
-rw-r--r--tests/data/aptsources_ports/sources.list52
-rw-r--r--tests/data/fake-packages/Packages21
-rw-r--r--tests/data/fake-packages/Packages.gzbin0 -> 555 bytes
-rw-r--r--tests/data/hashsums/hashsum_test.data1
-rw-r--r--tests/data/hashsums/hashsum_test_with_zero.databin0 -> 7 bytes
-rw-r--r--tests/data/misc/foo_Release492
-rw-r--r--tests/data/tagfile/history.1.log.gzbin0 -> 270 bytes
-rw-r--r--tests/data/tagfile/history.log15
-rw-r--r--tests/data/test-provides/etc/apt/sources.list1
-rw-r--r--tests/data/test-provides/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_oneiric_main_binary-i386_Packages75
-rw-r--r--tests/data/test-provides/var/lib/dpkg/status0
-rw-r--r--tests/data/test-repo/Packages.gzbin0 -> 675 bytes
-rw-r--r--tests/data/test-repo2/Packages.gzbin0 -> 675 bytes
-rw-r--r--tests/data/test-signed-usable-repo/key.gpg.base6462
-rw-r--r--tests/data/test-signed-usable-repo/seckey.asc158
-rw-r--r--tests/data/test-signed-usable-repo/signed/Packages26
-rw-r--r--tests/data/test-signed-usable-repo/signed/Release17
-rw-r--r--tests/data/test-signed-usable-repo/signed/Release.gpg14
-rw-r--r--tests/data/test-signed-usable-repo/signed/Sources21
-rw-r--r--tests/data/test-signed-usable-repo/signed/signed-not-usable_1.0.dsc11
-rw-r--r--tests/data/test-signed-usable-repo/signed/signed-not-usable_1.0_all.deb1
-rw-r--r--tests/data/test-signed-usable-repo/signed/signed-usable_1.0.dsc11
-rw-r--r--tests/data/test-signed-usable-repo/signed/signed-usable_1.0_all.deb1
-rw-r--r--tests/data/test-signed-usable-repo/unsigned/Packages26
-rw-r--r--tests/data/test-signed-usable-repo/unsigned/Release17
-rw-r--r--tests/data/test-signed-usable-repo/unsigned/Sources22
-rw-r--r--tests/data/test-signed-usable-repo/unsigned/unsigned-not-usable_1.0.dsc11
-rw-r--r--tests/data/test-signed-usable-repo/unsigned/unsigned-unusable_1.0_all.deb1
-rw-r--r--tests/data/test-signed-usable-repo/unsigned/unsigned-usable_1.0.dsc11
-rw-r--r--tests/data/test-signed-usable-repo/unsigned/unsigned-usable_1.0_all.deb1
-rw-r--r--tests/data/test-source-repo/Sources25
-rw-r--r--tests/data/test_debs/data-tar-broken.debbin0 -> 626 bytes
-rw-r--r--tests/data/test_debs/data-tar-xz.debbin0 -> 680 bytes
-rw-r--r--tests/data/test_debs/data-tar.debbin0 -> 20672 bytes
-rw-r--r--tests/data/test_debs/etc/apt/sources.list1
-rw-r--r--tests/data/test_debs/gdebi-test1.debbin0 -> 934 bytes
-rw-r--r--tests/data/test_debs/gdebi-test10.debbin0 -> 614 bytes
-rw-r--r--tests/data/test_debs/gdebi-test11.debbin0 -> 634 bytes
-rw-r--r--tests/data/test_debs/gdebi-test12.debbin0 -> 966 bytes
-rw-r--r--tests/data/test_debs/gdebi-test13.debbin0 -> 720 bytes
-rw-r--r--tests/data/test_debs/gdebi-test2.debbin0 -> 554 bytes
-rw-r--r--tests/data/test_debs/gdebi-test3.debbin0 -> 570 bytes
-rw-r--r--tests/data/test_debs/gdebi-test4.debbin0 -> 2306 bytes
-rw-r--r--tests/data/test_debs/gdebi-test5.debbin0 -> 2306 bytes
-rw-r--r--tests/data/test_debs/gdebi-test6.debbin0 -> 600 bytes
-rw-r--r--tests/data/test_debs/gdebi-test7.debbin0 -> 578 bytes
-rw-r--r--tests/data/test_debs/gdebi-test8.debbin0 -> 598 bytes
-rw-r--r--tests/data/test_debs/gdebi-test9.debbin0 -> 586 bytes
-rw-r--r--tests/data/test_debs/hello_2.5-1.dsc34
-rw-r--r--tests/data/test_debs/impossible-build-depends_2.5-1.dsc33
-rw-r--r--tests/data/test_debs/large-package-content_1.0_all.debbin0 -> 781546 bytes
-rw-r--r--tests/data/test_debs/multiarch-test1_i386.debbin0 -> 978 bytes
-rw-r--r--tests/data/test_debs/testdep-allowed-any_1.0-1_i386.debbin0 -> 1128 bytes
-rw-r--r--tests/data/test_debs/testdep-same-arch_1.0-1_i386.debbin0 -> 1236 bytes
-rw-r--r--tests/data/test_debs/utf8-package_1.0-1_all.debbin0 -> 1150 bytes
-rw-r--r--tests/data/test_debs/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_maverick_main_binary-i386_Packages31
-rw-r--r--tests/data/test_debs/var/lib/dpkg/status92
-rwxr-xr-xtests/fakeroot-apt-key2
-rwxr-xr-xtests/helper_install_progress_run.py15
-rw-r--r--tests/old/__init__.py11
-rw-r--r--tests/old/apt-test.py27
-rw-r--r--tests/old/cache.py51
-rw-r--r--tests/old/depcache.py57
-rw-r--r--tests/old/lock.py47
-rw-r--r--tests/old/memleak.py45
-rw-r--r--tests/old/pkgproblemresolver.py71
-rw-r--r--tests/old/pkgrecords.py41
-rw-r--r--tests/old/pkgsrcrecords.py31
-rwxr-xr-xtests/old/refcount.py54
-rw-r--r--tests/old/test_enhances.py16
-rw-r--r--tests/test_all.py63
-rw-r--r--tests/test_apt_cache.py400
-rw-r--r--tests/test_aptsources.py1573
-rwxr-xr-xtests/test_aptsources_deb822.py63
-rw-r--r--tests/test_aptsources_ports.py41
-rw-r--r--tests/test_auth.py314
-rw-r--r--tests/test_cache_invocation.py31
-rw-r--r--tests/test_configuration.py31
-rw-r--r--tests/test_cve_2020_27351.py149
-rw-r--r--tests/test_debfile.py192
-rw-r--r--tests/test_debfile_multiarch.py63
-rw-r--r--tests/test_deps.py142
-rw-r--r--tests/test_group.py31
-rw-r--r--tests/test_hashes.py206
-rw-r--r--tests/test_hashsums.py106
-rw-r--r--tests/test_install_progress_exec.py43
-rw-r--r--tests/test_large_file.py25
-rw-r--r--tests/test_lfs.py19
-rw-r--r--tests/test_lp659438.py80
-rw-r--r--tests/test_paths.py158
-rw-r--r--tests/test_pep484.py28
-rw-r--r--tests/test_policy.py70
-rw-r--r--tests/test_progress.py56
-rw-r--r--tests/test_pyflakes.py43
-rw-r--r--tests/test_signed_usable.py403
-rw-r--r--tests/test_size_to_str.py104
-rw-r--r--tests/test_sourcerecords.py129
-rw-r--r--tests/test_tagfile.py186
-rw-r--r--tests/test_utils.py74
-rw-r--r--tests/testcommon.py30
-rw-r--r--typehinting/apt_inst.pyi37
-rw-r--r--typehinting/apt_pkg.pyi390
-rwxr-xr-xutils/expand_info.py11
-rwxr-xr-xutils/get_debian_mirrors.py47
-rwxr-xr-xutils/get_ubuntu_mirrors_from_lp.py56
-rwxr-xr-xutils/mirrortest108
312 files changed, 71716 insertions, 0 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..876e324
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,25 @@
+image: debian:unstable
+variables:
+ DEBIAN_FRONTEND: noninteractive
+pre-commit:
+ script:
+ - apt update
+ - apt install -q -y pre-commit git
+ - pre-commit run -a --show-diff-on-failure
+test:
+ script:
+ - apt update
+ - apt build-dep -q -y ./
+ - dpkg-buildpackage
+ artifacts:
+ paths:
+ - build/sphinx/html/
+pages:
+ stage: deploy
+ script:
+ - mv build/sphinx/html/ public
+ artifacts:
+ paths:
+ - public
+ rules:
+ - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..ddd6c4b
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,25 @@
+repos:
+ - repo: https://github.com/asottile/pyupgrade
+ rev: v3.15.0
+ hooks:
+ - id: pyupgrade
+ args: [--py311-plus]
+ - repo: https://github.com/pycqa/isort
+ rev: 5.13.2
+ hooks:
+ - id: isort
+ args: ["--profile", "black", "--filter-files"]
+ - repo: https://github.com/PyCQA/autoflake
+ rev: v2.2.1
+ hooks:
+ - id: autoflake
+ - repo: https://github.com/psf/black
+ rev: 23.12.1
+ hooks:
+ - id: black
+ - repo: https://github.com/pre-commit/mirrors-mypy
+ rev: 'v1.8.0'
+ hooks:
+ - id: mypy
+ args: [--strict]
+ exclude: tests/|aptsources/(distro.py|sourceslist.py)|doc/|utils/|setup.py
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..1ed949c
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,7 @@
+jgg Jason Gunthorpe <jgg@debian.org>
+mdz Matt Zimmerman <mdz@debian.org>
+mvo Michael Vogt <mvo@debian.org>
+Michiel Sikkes <michiel@eyesopened.nl>
+Sebastian Heinlein <glatzor@ubuntu.com>
+Sean Wheller <sean@inwords.co.za>
+Julian Andres Klode <jak@debian.org>
diff --git a/COPYING.GPL b/COPYING.GPL
new file mode 100644
index 0000000..60549be
--- /dev/null
+++ b/COPYING.GPL
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..53b9b3c
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,11 @@
+FROM debian:testing
+COPY . /tmp
+WORKDIR /tmp
+RUN sed -i s#://deb.debian.org#://cdn-fastly.deb.debian.org# /etc/apt/sources.list \
+ && apt-get update \
+ && adduser --home /home/travis travis --quiet --disabled-login --gecos "" --uid 1000 \
+ && env DEBIAN_FRONTEND=noninteractive apt-get build-dep -y /tmp \
+ && env DEBIAN_FRONTEND=noninteractive apt-get install -y ccache python3-pip \
+ && python3 -m pip install -U mypy \
+ && rm -r /tmp/* \
+ && apt-get clean
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a3ea8aa
--- /dev/null
+++ b/README.md
@@ -0,0 +1,49 @@
+# Python-apt is a wrapper to use features of apt from python.
+
+It contains the following modules:
+
+## C++ Wrapper:
+
+* apt_pkg - access to libapt-pkg (wrapper to the lowlevel c++ code)
+* apt_inst - access to libapt-inst (wrapper to the lowlevel c++ code)
+
+## Python module:
+
+* apt - high level python interface build on top of apt_pkg, apt_inst
+* aptsources - high level manipulation of sources.list
+
+
+# Development
+
+## Building
+
+To build python-apt run:
+```
+$ python setup.py build
+```
+You may need to install the build-dependencies via:
+```
+$ sudo apt build-dep ./
+```
+first.
+
+## Running the tests
+
+Run the tests with:
+```
+$ python tests/test_all.py
+$ python3 tests/test_all.py
+```
+
+## Running mypy:
+
+To check if the "apt" python module is mypy clean, run:
+```
+$ MYPYPATH=./typehinting/ mypy ./apt
+```
+
+To use the annotation with your source code, run:
+```
+$ MYPYPATH=/usr/lib/python3/dist-packages/apt mypy ./my-program
+```
+(adjust from python3 to python2.7 if you run there).
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..a08a28a
--- /dev/null
+++ b/TODO
@@ -0,0 +1,4 @@
+* aptsources:
+ - make the distro detection in sources.list more clever by using the
+ origin informaton to avoid adding full uris to (unofficial/internal)
+ mirrors
diff --git a/apt/__init__.py b/apt/__init__.py
new file mode 100644
index 0000000..f22c9a0
--- /dev/null
+++ b/apt/__init__.py
@@ -0,0 +1,40 @@
+# Copyright (c) 2005-2009 Canonical
+#
+# Author: Michael Vogt <michael.vogt@ubuntu.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+# import the core of apt_pkg
+"""High-Level Interface for working with apt."""
+import apt_pkg
+
+from apt.cache import Cache as Cache
+from apt.cache import ProblemResolver as ProblemResolver
+
+# import some fancy classes
+from apt.package import Package as Package
+from apt.package import Version as Version
+
+Cache # pyflakes
+ProblemResolver # pyflakes
+Version # pyflakes
+from apt.cdrom import Cdrom as Cdrom
+
+# init the package system, but do not re-initialize config
+if "APT" not in apt_pkg.config:
+ apt_pkg.init_config()
+apt_pkg.init_system()
+
+__all__ = ["Cache", "Cdrom", "Package"]
diff --git a/apt/auth.py b/apt/auth.py
new file mode 100644
index 0000000..6d50616
--- /dev/null
+++ b/apt/auth.py
@@ -0,0 +1,311 @@
+#!/usr/bin/python3
+# auth - authentication key management
+#
+# Copyright (c) 2004 Canonical
+# Copyright (c) 2012 Sebastian Heinlein
+#
+# Author: Michael Vogt <mvo@debian.org>
+# Sebastian Heinlein <devel@glatzor.de>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+"""Handle GnuPG keys used to trust signed repositories."""
+
+import errno
+import os
+import os.path
+import shutil
+import subprocess
+import sys
+import tempfile
+
+import apt_pkg
+from apt_pkg import gettext as _
+
+
+class AptKeyError(Exception):
+ pass
+
+
+class AptKeyIDTooShortError(AptKeyError):
+ """Internal class do not rely on it."""
+
+
+class TrustedKey:
+
+ """Represents a trusted key."""
+
+ def __init__(self, name: str, keyid: str, date: str) -> None:
+ self.raw_name = name
+ # Allow to translated some known keys
+ self.name = _(name)
+ self.keyid = keyid
+ self.date = date
+
+ def __str__(self) -> str:
+ return f"{self.name}\n{self.keyid} {self.date}"
+
+
+def _call_apt_key_script(*args: str, **kwargs: str | None) -> str:
+ """Run the apt-key script with the given arguments."""
+ conf = None
+ cmd = [apt_pkg.config.find_file("Dir::Bin::Apt-Key", "/usr/bin/apt-key")]
+ cmd.extend(args)
+ env = os.environ.copy()
+ env["LANG"] = "C"
+ env["APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE"] = "1"
+ try:
+ if apt_pkg.config.find_dir("Dir") != "/":
+ # If the key is to be installed into a chroot we have to export the
+ # configuration from the chroot to the apt-key script by using
+ # a temporary APT_CONFIG file. The apt-key script uses apt-config
+ # shell internally
+ conf = tempfile.NamedTemporaryFile(prefix="apt-key", suffix=".conf")
+ conf.write(apt_pkg.config.dump().encode("UTF-8"))
+ conf.flush()
+ env["APT_CONFIG"] = conf.name
+ proc = subprocess.Popen(
+ cmd,
+ env=env,
+ universal_newlines=True,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
+
+ stdin = kwargs.get("stdin", None)
+
+ output, stderr = proc.communicate(stdin) # type: str, str
+
+ if proc.returncode:
+ raise AptKeyError(
+ "The apt-key script failed with return code %s:\n"
+ "%s\n"
+ "stdout: %s\n"
+ "stderr: %s" % (proc.returncode, " ".join(cmd), output, stderr)
+ )
+ elif stderr:
+ sys.stderr.write(stderr) # Forward stderr
+
+ return output.strip()
+ finally:
+ if conf is not None:
+ conf.close()
+
+
+def add_key_from_file(filename: str) -> None:
+ """Import a GnuPG key file to trust repositores signed by it.
+
+ Keyword arguments:
+ filename -- the absolute path to the public GnuPG key file
+ """
+ if not os.path.abspath(filename):
+ raise AptKeyError("An absolute path is required: %s" % filename)
+ if not os.access(filename, os.R_OK):
+ raise AptKeyError("Key file cannot be accessed: %s" % filename)
+ _call_apt_key_script("add", filename)
+
+
+def add_key_from_keyserver(keyid: str, keyserver: str) -> None:
+ """Import a GnuPG key file to trust repositores signed by it.
+
+ Keyword arguments:
+ keyid -- the long keyid (fingerprint) of the key, e.g.
+ A1BD8E9D78F7FE5C3E65D8AF8B48AD6246925553
+ keyserver -- the URL or hostname of the key server
+ """
+ tmp_keyring_dir = tempfile.mkdtemp()
+ try:
+ _add_key_from_keyserver(keyid, keyserver, tmp_keyring_dir)
+ except Exception:
+ raise
+ finally:
+ # We are racing with gpg when removing sockets, so ignore
+ # failure to delete non-existing files.
+ def onerror(
+ func: object, path: str, exc_info: tuple[type, Exception, object]
+ ) -> None:
+ if isinstance(exc_info[1], OSError) and exc_info[1].errno == errno.ENOENT:
+ return
+ raise
+
+ shutil.rmtree(tmp_keyring_dir, onerror=onerror)
+
+
+def _add_key_from_keyserver(keyid: str, keyserver: str, tmp_keyring_dir: str) -> None:
+ if len(keyid.replace(" ", "").replace("0x", "")) < (160 / 4):
+ raise AptKeyIDTooShortError("Only fingerprints (v4, 160bit) are supported")
+ # create a temp keyring dir
+ tmp_secret_keyring = os.path.join(tmp_keyring_dir, "secring.gpg")
+ tmp_keyring = os.path.join(tmp_keyring_dir, "pubring.gpg")
+ # default options for gpg
+ gpg_default_options = [
+ "gpg",
+ "--no-default-keyring",
+ "--no-options",
+ "--homedir",
+ tmp_keyring_dir,
+ ]
+ # download the key to a temp keyring first
+ res = subprocess.call(
+ gpg_default_options
+ + [
+ "--secret-keyring",
+ tmp_secret_keyring,
+ "--keyring",
+ tmp_keyring,
+ "--keyserver",
+ keyserver,
+ "--recv",
+ keyid,
+ ]
+ )
+ if res != 0:
+ raise AptKeyError(f"recv from '{keyserver}' failed for '{keyid}'")
+ # FIXME:
+ # - with gnupg 1.4.18 the downloaded key is actually checked(!),
+ # i.e. gnupg will not import anything that the server sends
+ # into the keyring, so the below checks are now redundant *if*
+ # gnupg 1.4.18 is used
+
+ # now export again using the long key id (to ensure that there is
+ # really only this one key in our keyring) and not someone MITM us
+ tmp_export_keyring = os.path.join(tmp_keyring_dir, "export-keyring.gpg")
+ res = subprocess.call(
+ gpg_default_options
+ + [
+ "--keyring",
+ tmp_keyring,
+ "--output",
+ tmp_export_keyring,
+ "--export",
+ keyid,
+ ]
+ )
+ if res != 0:
+ raise AptKeyError("export of '%s' failed", keyid)
+ # now verify the fingerprint, this is probably redundant as we
+ # exported by the fingerprint in the previous command but its
+ # still good paranoia
+ output = subprocess.Popen(
+ gpg_default_options
+ + [
+ "--keyring",
+ tmp_export_keyring,
+ "--fingerprint",
+ "--batch",
+ "--fixed-list-mode",
+ "--with-colons",
+ ],
+ stdout=subprocess.PIPE,
+ universal_newlines=True,
+ ).communicate()[0]
+ got_fingerprint = None
+ for line in output.splitlines():
+ if line.startswith("fpr:"):
+ got_fingerprint = line.split(":")[9]
+ # stop after the first to ensure no subkey trickery
+ break
+ # strip the leading "0x" is there is one and uppercase (as this is
+ # what gnupg is using)
+ signing_key_fingerprint = keyid.replace("0x", "").upper()
+ if got_fingerprint != signing_key_fingerprint:
+ # make the error match what gnupg >= 1.4.18 will output when
+ # it checks the key itself before importing it
+ raise AptKeyError(
+ f"recv from '{keyserver}' failed for '{signing_key_fingerprint}'"
+ )
+ # finally add it
+ add_key_from_file(tmp_export_keyring)
+
+
+def add_key(content: str) -> None:
+ """Import a GnuPG key to trust repositores signed by it.
+
+ Keyword arguments:
+ content -- the content of the GnuPG public key
+ """
+ _call_apt_key_script("adv", "--quiet", "--batch", "--import", "-", stdin=content)
+
+
+def remove_key(fingerprint: str) -> None:
+ """Remove a GnuPG key to no longer trust repositores signed by it.
+
+ Keyword arguments:
+ fingerprint -- the fingerprint identifying the key
+ """
+ _call_apt_key_script("rm", fingerprint)
+
+
+def export_key(fingerprint: str) -> str:
+ """Return the GnuPG key in text format.
+
+ Keyword arguments:
+ fingerprint -- the fingerprint identifying the key
+ """
+ return _call_apt_key_script("export", fingerprint)
+
+
+def update() -> str:
+ """Update the local keyring with the archive keyring and remove from
+ the local keyring the archive keys which are no longer valid. The
+ archive keyring is shipped in the archive-keyring package of your
+ distribution, e.g. the debian-archive-keyring package in Debian.
+ """
+ return _call_apt_key_script("update")
+
+
+def net_update() -> str:
+ """Work similar to the update command above, but get the archive
+ keyring from an URI instead and validate it against a master key.
+ This requires an installed wget(1) and an APT build configured to
+ have a server to fetch from and a master keyring to validate. APT
+ in Debian does not support this command and relies on update
+ instead, but Ubuntu's APT does.
+ """
+ return _call_apt_key_script("net-update")
+
+
+def list_keys() -> list[TrustedKey]:
+ """Returns a list of TrustedKey instances for each key which is
+ used to trust repositories.
+ """
+ # The output of `apt-key list` is difficult to parse since the
+ # --with-colons parameter isn't user
+ output = _call_apt_key_script(
+ "adv", "--with-colons", "--batch", "--fixed-list-mode", "--list-keys"
+ )
+ res = []
+ for line in output.split("\n"):
+ fields = line.split(":")
+ if fields[0] == "pub":
+ keyid = fields[4]
+ if fields[0] == "uid":
+ uid = fields[9]
+ creation_date = fields[5]
+ key = TrustedKey(uid, keyid, creation_date)
+ res.append(key)
+ return res
+
+
+if __name__ == "__main__":
+ # Add some known keys we would like to see translated so that they get
+ # picked up by gettext
+ lambda: _("Ubuntu Archive Automatic Signing Key <ftpmaster@ubuntu.com>")
+ lambda: _("Ubuntu CD Image Automatic Signing Key <cdimage@ubuntu.com>")
+
+ apt_pkg.init()
+ for trusted_key in list_keys():
+ print(trusted_key)
diff --git a/apt/cache.py b/apt/cache.py
new file mode 100644
index 0000000..cf78026
--- /dev/null
+++ b/apt/cache.py
@@ -0,0 +1,1004 @@
+# cache.py - apt cache abstraction
+#
+# Copyright (c) 2005-2009 Canonical
+#
+# Author: Michael Vogt <michael.vogt@ubuntu.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
+from __future__ import annotations
+
+import fnmatch
+import os
+import warnings
+import weakref
+from collections.abc import Callable, Iterator, KeysView
+from typing import Any, cast
+
+import apt_pkg
+
+import apt.progress.text
+from apt.package import Package, Version
+from apt.progress.base import AcquireProgress, InstallProgress, OpProgress
+
+
+class FetchCancelledException(IOError):
+ """Exception that is thrown when the user cancels a fetch operation."""
+
+
+class FetchFailedException(IOError):
+ """Exception that is thrown when fetching fails."""
+
+
+class UntrustedException(FetchFailedException):
+ """Exception that is thrown when fetching fails for trust reasons"""
+
+
+class LockFailedException(IOError):
+ """Exception that is thrown when locking fails."""
+
+
+class CacheClosedException(Exception):
+ """Exception that is thrown when the cache is used after close()."""
+
+
+class _WrappedLock:
+ """Wraps an apt_pkg.FileLock to raise LockFailedException.
+
+ Initialized using a directory path."""
+
+ def __init__(self, path: str) -> None:
+ self._path = path
+ self._lock = apt_pkg.FileLock(os.path.join(path, "lock"))
+
+ def __enter__(self) -> None:
+ try:
+ return self._lock.__enter__()
+ except apt_pkg.Error as e:
+ raise LockFailedException(
+ ("Failed to lock directory %s: %s") % (self._path, e)
+ )
+
+ def __exit__(self, typ: object, value: object, traceback: object) -> None:
+ return self._lock.__exit__(typ, value, traceback)
+
+
+class Cache:
+ """Dictionary-like package cache.
+
+ The APT cache file contains a hash table mapping names of binary
+ packages to their metadata. A Cache object is the in-core
+ representation of the same. It provides access to APTs idea of the
+ list of available packages.
+
+ The cache can be used like a mapping from package names to Package
+ objects (although only getting items is supported).
+
+ Keyword arguments:
+ progress -- a OpProgress object,
+ rootdir -- an alternative root directory. if that is given the system
+ sources.list and system lists/files are not read, only file relative
+ to the given rootdir,
+ memonly -- build the cache in memory only.
+
+
+ .. versionchanged:: 1.0
+
+ The cache now supports package names with special architecture
+ qualifiers such as :all and :native. It does not export them
+ in :meth:`keys()`, though, to keep :meth:`keys()` a unique set.
+ """
+
+ def __init__(
+ self,
+ progress: OpProgress | None = None,
+ rootdir: str | None = None,
+ memonly: bool = False,
+ ) -> None:
+ self._cache: apt_pkg.Cache = cast(apt_pkg.Cache, None)
+ self._depcache: apt_pkg.DepCache = cast(apt_pkg.DepCache, None)
+ self._records: apt_pkg.PackageRecords = cast(
+ apt_pkg.PackageRecords, None
+ ) # noqa
+ self._list: apt_pkg.SourceList = cast(apt_pkg.SourceList, None)
+ self._callbacks: dict[str, list[Callable[..., None] | str]] = {} # noqa
+ self._callbacks2: dict[
+ str, list[tuple[Callable[..., Any], tuple[Any, ...], dict[Any, Any]]]
+ ] = {} # noqa
+ self._weakref: weakref.WeakValueDictionary[
+ str, apt.Package
+ ] = weakref.WeakValueDictionary() # noqa
+ self._weakversions: weakref.WeakSet[Version] = weakref.WeakSet() # noqa
+ self._changes_count = -1
+ self._sorted_set: list[str] | None = None
+
+ self.connect("cache_post_open", "_inc_changes_count")
+ self.connect("cache_post_change", "_inc_changes_count")
+ if memonly:
+ # force apt to build its caches in memory
+ apt_pkg.config.set("Dir::Cache::pkgcache", "")
+ if rootdir:
+ rootdir = os.path.abspath(rootdir)
+ if os.path.exists(rootdir + "/etc/apt/apt.conf"):
+ apt_pkg.read_config_file(apt_pkg.config, rootdir + "/etc/apt/apt.conf")
+ if os.path.isdir(rootdir + "/etc/apt/apt.conf.d"):
+ apt_pkg.read_config_dir(apt_pkg.config, rootdir + "/etc/apt/apt.conf.d")
+ apt_pkg.config.set("Dir", rootdir)
+ apt_pkg.config.set("Dir::State::status", rootdir + "/var/lib/dpkg/status")
+ # also set dpkg to the rootdir path so that its called for the
+ # --print-foreign-architectures call
+ apt_pkg.config.set(
+ "Dir::bin::dpkg", os.path.join(rootdir, "usr", "bin", "dpkg")
+ )
+ # create required dirs/files when run with special rootdir
+ # automatically
+ self._check_and_create_required_dirs(rootdir)
+ # Call InitSystem so the change to Dir::State::Status is actually
+ # recognized (LP: #320665)
+ apt_pkg.init_system()
+
+ # Prepare a lock object (context manager for archive lock)
+ archive_dir = apt_pkg.config.find_dir("Dir::Cache::Archives")
+ self._archive_lock = _WrappedLock(archive_dir)
+
+ self.open(progress)
+
+ def fix_broken(self) -> None:
+ """Fix broken packages."""
+ self._depcache.fix_broken()
+
+ def _inc_changes_count(self) -> None:
+ """Increase the number of changes"""
+ self._changes_count += 1
+
+ def _check_and_create_required_dirs(self, rootdir: str) -> None:
+ """
+ check if the required apt directories/files are there and if
+ not create them
+ """
+ files = [
+ "/var/lib/dpkg/status",
+ "/etc/apt/sources.list",
+ ]
+ dirs = [
+ "/var/lib/dpkg",
+ "/etc/apt/",
+ "/var/cache/apt/archives/partial",
+ "/var/lib/apt/lists/partial",
+ ]
+ for d in dirs:
+ if not os.path.exists(rootdir + d):
+ # print "creating: ", rootdir + d
+ os.makedirs(rootdir + d)
+ for f in files:
+ if not os.path.exists(rootdir + f):
+ open(rootdir + f, "w").close()
+
+ def _run_callbacks(self, name: str) -> None:
+ """internal helper to run a callback"""
+ if name in self._callbacks:
+ for callback in self._callbacks[name]:
+ if callback == "_inc_changes_count":
+ self._inc_changes_count()
+ else:
+ callback() # type: ignore
+
+ if name in self._callbacks2:
+ for callback, args, kwds in self._callbacks2[name]:
+ callback(self, *args, **kwds)
+
+ def open(self, progress: OpProgress | None = None) -> None:
+ """Open the package cache, after that it can be used like
+ a dictionary
+ """
+ if progress is None:
+ progress = apt.progress.base.OpProgress()
+ # close old cache on (re)open
+ self.close()
+ self.op_progress = progress
+ self._run_callbacks("cache_pre_open")
+
+ self._cache = apt_pkg.Cache(progress)
+ self._depcache = apt_pkg.DepCache(self._cache)
+ self._records = apt_pkg.PackageRecords(self._cache)
+ self._list = apt_pkg.SourceList()
+ self._list.read_main_list()
+ self._sorted_set = None
+ self.__remap()
+
+ self._have_multi_arch = len(apt_pkg.get_architectures()) > 1
+
+ progress.done()
+ self._run_callbacks("cache_post_open")
+
+ def __remap(self) -> None:
+ """Called after cache reopen() to relocate to new cache.
+
+ Relocate objects like packages and versions from the old
+ underlying cache to the new one.
+ """
+ for key in list(self._weakref.keys()):
+ try:
+ pkg = self._weakref[key]
+ except KeyError:
+ continue
+
+ try:
+ pkg._pkg = self._cache[pkg._pkg.name, pkg._pkg.architecture]
+ except LookupError:
+ del self._weakref[key]
+
+ for ver in list(self._weakversions):
+ # Package has been reseated above, reseat version
+ for v in ver.package._pkg.version_list:
+ # Requirements as in debListParser::SameVersion
+ if (
+ v.hash == ver._cand.hash
+ and (v.size == 0 or ver._cand.size == 0 or v.size == ver._cand.size)
+ and v.multi_arch == ver._cand.multi_arch
+ and v.ver_str == ver._cand.ver_str
+ ):
+ ver._cand = v
+ break
+ else:
+ self._weakversions.remove(ver)
+
+ def close(self) -> None:
+ """Close the package cache"""
+ # explicitely free the FDs that _records has open
+ del self._records
+ self._records = cast(apt_pkg.PackageRecords, None)
+
+ def __enter__(self) -> Cache:
+ """Enter the with statement"""
+ return self
+
+ def __exit__(self, exc_type: object, exc_value: object, traceback: object) -> None:
+ """Exit the with statement"""
+ self.close()
+
+ def __getitem__(self, key: object) -> Package:
+ """look like a dictionary (get key)"""
+ try:
+ key = str(key)
+ rawpkg = self._cache[key]
+ except KeyError:
+ raise KeyError("The cache has no package named %r" % key)
+
+ # It might be excluded due to not having a version or something
+ if not self.__is_real_pkg(rawpkg):
+ raise KeyError("The cache has no package named %r" % key)
+
+ pkg = self._rawpkg_to_pkg(rawpkg)
+
+ return pkg
+
+ def get(self, key: object, default: object = None) -> Any:
+ """Return *self*[*key*] or *default* if *key* not in *self*.
+
+ .. versionadded:: 1.1
+ """
+ try:
+ return self[key]
+ except KeyError:
+ return default
+
+ def _rawpkg_to_pkg(self, rawpkg: apt_pkg.Package) -> Package:
+ """Returns the apt.Package object for an apt_pkg.Package object.
+
+ .. versionadded:: 1.0.0
+ """
+ fullname = rawpkg.get_fullname(pretty=True)
+
+ return self._weakref.setdefault(fullname, Package(self, rawpkg))
+
+ def __iter__(self) -> Iterator[Package]:
+ # We iterate sorted over package names here. With this we read the
+ # package lists linearly if we need to access the package records,
+ # instead of having to do thousands of random seeks; the latter
+ # is disastrous if we use compressed package indexes, and slower than
+ # necessary for uncompressed indexes.
+ for pkgname in self.keys():
+ pkg = Package(self, self._cache[pkgname])
+ yield self._weakref.setdefault(pkgname, pkg)
+
+ def __is_real_pkg(self, rawpkg: apt_pkg.Package) -> bool:
+ """Check if the apt_pkg.Package provided is a real package."""
+ return rawpkg.has_versions
+
+ def has_key(self, key: object) -> bool:
+ return key in self
+
+ def __contains__(self, key: object) -> bool:
+ try:
+ return self.__is_real_pkg(self._cache[str(key)])
+ except KeyError:
+ return False
+
+ def __len__(self) -> int:
+ return len(self.keys())
+
+ def keys(self) -> list[str]:
+ if self._sorted_set is None:
+ self._sorted_set = sorted(
+ p.get_fullname(pretty=True)
+ for p in self._cache.packages
+ if self.__is_real_pkg(p)
+ )
+ return list(self._sorted_set) # We need a copy here, caller may modify
+
+ def get_changes(self) -> list[Package]:
+ """Get the marked changes"""
+ changes = []
+ marked_keep = self._depcache.marked_keep
+ for rawpkg in self._cache.packages:
+ if not marked_keep(rawpkg):
+ changes.append(self._rawpkg_to_pkg(rawpkg))
+ return changes
+
+ def upgrade(self, dist_upgrade: bool = False) -> None:
+ """Upgrade all packages.
+
+ If the parameter *dist_upgrade* is True, new dependencies will be
+ installed as well (and conflicting packages may be removed). The
+ default value is False.
+ """
+ self.cache_pre_change()
+ self._depcache.upgrade(dist_upgrade)
+ self.cache_post_change()
+
+ @property
+ def required_download(self) -> int:
+ """Get the size of the packages that are required to download."""
+ if self._records is None:
+ raise CacheClosedException("Cache object used after close() called")
+ pm = apt_pkg.PackageManager(self._depcache)
+ fetcher = apt_pkg.Acquire()
+ pm.get_archives(fetcher, self._list, self._records)
+ return fetcher.fetch_needed
+
+ @property
+ def required_space(self) -> int:
+ """Get the size of the additional required space on the fs."""
+ return self._depcache.usr_size
+
+ @property
+ def req_reinstall_pkgs(self) -> set[str]:
+ """Return the packages not downloadable packages in reqreinst state."""
+ reqreinst = set()
+ get_candidate_ver = self._depcache.get_candidate_ver
+ states = frozenset(
+ (apt_pkg.INSTSTATE_REINSTREQ, apt_pkg.INSTSTATE_HOLD_REINSTREQ)
+ )
+ for pkg in self._cache.packages:
+ cand = get_candidate_ver(pkg)
+ if cand and not cand.downloadable and pkg.inst_state in states:
+ reqreinst.add(pkg.get_fullname(pretty=True))
+ return reqreinst
+
+ def _run_fetcher(
+ self, fetcher: apt_pkg.Acquire, allow_unauthenticated: bool | None
+ ) -> int:
+ if allow_unauthenticated is None:
+ allow_unauthenticated = apt_pkg.config.find_b(
+ "APT::Get::" "AllowUnauthenticated", False
+ )
+
+ untrusted = [item for item in fetcher.items if not item.is_trusted]
+ if untrusted and not allow_unauthenticated:
+ raise UntrustedException(
+ "Untrusted packages:\n%s" % "\n".join(i.desc_uri for i in untrusted)
+ )
+
+ # do the actual fetching
+ res = fetcher.run()
+
+ # now check the result (this is the code from apt-get.cc)
+ failed = False
+ err_msg = ""
+ for item in fetcher.items:
+ if item.status == item.STAT_DONE:
+ continue
+ if item.STAT_IDLE:
+ continue
+ err_msg += f"Failed to fetch {item.desc_uri} {item.error_text}\n"
+ failed = True
+
+ # we raise a exception if the download failed or it was cancelt
+ if res == fetcher.RESULT_CANCELLED:
+ raise FetchCancelledException(err_msg)
+ elif failed:
+ raise FetchFailedException(err_msg)
+ return res
+
+ def _fetch_archives(
+ self,
+ fetcher: apt_pkg.Acquire,
+ pm: apt_pkg.PackageManager,
+ allow_unauthenticated: bool | None = None,
+ ) -> int:
+ """fetch the needed archives"""
+ if self._records is None:
+ raise CacheClosedException("Cache object used after close() called")
+
+ # this may as well throw a SystemError exception
+ if not pm.get_archives(fetcher, self._list, self._records):
+ return False
+
+ # now run the fetcher, throw exception if something fails to be
+ # fetched
+ return self._run_fetcher(fetcher, allow_unauthenticated)
+
+ def fetch_archives(
+ self,
+ progress: AcquireProgress | None = None,
+ fetcher: apt_pkg.Acquire | None = None,
+ allow_unauthenticated: bool | None = None,
+ ) -> int:
+ """Fetch the archives for all packages marked for install/upgrade.
+
+ You can specify either an :class:`apt.progress.base.AcquireProgress()`
+ object for the parameter *progress*, or specify an already
+ existing :class:`apt_pkg.Acquire` object for the parameter *fetcher*.
+
+ The return value of the function is undefined. If an error occurred,
+ an exception of type :class:`FetchFailedException` or
+ :class:`FetchCancelledException` is raised.
+
+ The keyword-only parameter *allow_unauthenticated* specifies whether
+ to allow unauthenticated downloads. If not specified, it defaults to
+ the configuration option `APT::Get::AllowUnauthenticated`.
+
+ .. versionadded:: 0.8.0
+ """
+ if progress is not None and fetcher is not None:
+ raise ValueError("Takes a progress or a an Acquire object")
+ if progress is None:
+ progress = apt.progress.text.AcquireProgress()
+ if fetcher is None:
+ fetcher = apt_pkg.Acquire(progress)
+
+ with self._archive_lock:
+ return self._fetch_archives(
+ fetcher, apt_pkg.PackageManager(self._depcache), allow_unauthenticated
+ )
+
+ def is_virtual_package(self, pkgname: str) -> bool:
+ """Return whether the package is a virtual package."""
+ try:
+ pkg = self._cache[pkgname]
+ except KeyError:
+ return False
+ else:
+ return bool(pkg.has_provides and not pkg.has_versions)
+
+ def get_providing_packages(
+ self,
+ pkgname: str,
+ candidate_only: bool = True,
+ include_nonvirtual: bool = False,
+ ) -> list[Package]:
+ """Return a list of all packages providing a package.
+
+ Return a list of packages which provide the virtual package of the
+ specified name.
+
+ If 'candidate_only' is False, return all packages with at
+ least one version providing the virtual package. Otherwise,
+ return only those packages where the candidate version
+ provides the virtual package.
+
+ If 'include_nonvirtual' is True then it will search for all
+ packages providing pkgname, even if pkgname is not itself
+ a virtual pkg.
+ """
+
+ providers: set[Package] = set()
+ get_candidate_ver = self._depcache.get_candidate_ver
+ try:
+ vp = self._cache[pkgname]
+ if vp.has_versions and not include_nonvirtual:
+ return list(providers)
+ except KeyError:
+ return list(providers)
+
+ for provides, providesver, version in vp.provides_list:
+ rawpkg = version.parent_pkg
+ if not candidate_only or (version == get_candidate_ver(rawpkg)):
+ providers.add(self._rawpkg_to_pkg(rawpkg))
+ return list(providers)
+
+ def update(
+ self,
+ fetch_progress: AcquireProgress | None = None,
+ pulse_interval: int = 0,
+ raise_on_error: bool = True,
+ sources_list: str | None = None,
+ ) -> int:
+ """Run the equivalent of apt-get update.
+
+ You probably want to call open() afterwards, in order to utilise the
+ new cache. Otherwise, the old cache will be used which can lead to
+ strange bugs.
+
+ The first parameter *fetch_progress* may be set to an instance of
+ apt.progress.FetchProgress, the default is apt.progress.FetchProgress()
+ .
+ sources_list -- Update a alternative sources.list than the default.
+ Note that the sources.list.d directory is ignored in this case
+ """
+ with _WrappedLock(apt_pkg.config.find_dir("Dir::State::Lists")):
+ if sources_list:
+ old_sources_list = apt_pkg.config.find("Dir::Etc::sourcelist")
+ old_sources_list_d = apt_pkg.config.find("Dir::Etc::sourceparts")
+ old_cleanup = apt_pkg.config.find("APT::List-Cleanup")
+ apt_pkg.config.set(
+ "Dir::Etc::sourcelist", os.path.abspath(sources_list)
+ )
+ apt_pkg.config.set("Dir::Etc::sourceparts", "xxx")
+ apt_pkg.config.set("APT::List-Cleanup", "0")
+ slist = apt_pkg.SourceList()
+ slist.read_main_list()
+ else:
+ slist = self._list
+
+ try:
+ if fetch_progress is None:
+ fetch_progress = apt.progress.base.AcquireProgress()
+ try:
+ res = self._cache.update(fetch_progress, slist, pulse_interval)
+ except SystemError as e:
+ raise FetchFailedException(e)
+ if not res and raise_on_error:
+ raise FetchFailedException()
+ else:
+ return res
+ finally:
+ if sources_list:
+ apt_pkg.config.set("Dir::Etc::sourcelist", old_sources_list)
+ apt_pkg.config.set("Dir::Etc::sourceparts", old_sources_list_d)
+ apt_pkg.config.set("APT::List-Cleanup", old_cleanup)
+
+ def install_archives(
+ self, pm: apt_pkg.PackageManager, install_progress: InstallProgress
+ ) -> int:
+ """
+ The first parameter *pm* refers to an object returned by
+ apt_pkg.PackageManager().
+
+ The second parameter *install_progress* refers to an InstallProgress()
+ object of the module apt.progress.
+
+ This releases a system lock in newer versions, if there is any,
+ and reestablishes it afterwards.
+ """
+ # compat with older API
+ try:
+ install_progress.startUpdate() # type: ignore
+ except AttributeError:
+ install_progress.start_update()
+
+ did_unlock = apt_pkg.pkgsystem_is_locked()
+ if did_unlock:
+ apt_pkg.pkgsystem_unlock_inner()
+
+ try:
+ res = install_progress.run(pm)
+ finally:
+ if did_unlock:
+ apt_pkg.pkgsystem_lock_inner()
+
+ try:
+ install_progress.finishUpdate() # type: ignore
+ except AttributeError:
+ install_progress.finish_update()
+ return res
+
+ def commit(
+ self,
+ fetch_progress: AcquireProgress | None = None,
+ install_progress: InstallProgress | None = None,
+ allow_unauthenticated: bool | None = None,
+ ) -> bool:
+ """Apply the marked changes to the cache.
+
+ The first parameter, *fetch_progress*, refers to a FetchProgress()
+ object as found in apt.progress, the default being
+ apt.progress.FetchProgress().
+
+ The second parameter, *install_progress*, is a
+ apt.progress.InstallProgress() object.
+
+ The keyword-only parameter *allow_unauthenticated* specifies whether
+ to allow unauthenticated downloads. If not specified, it defaults to
+ the configuration option `APT::Get::AllowUnauthenticated`.
+ """
+ # FIXME:
+ # use the new acquire/pkgmanager interface here,
+ # raise exceptions when a download or install fails
+ # and send proper error strings to the application.
+ # Current a failed download will just display "error"
+ # which is less than optimal!
+
+ if fetch_progress is None:
+ fetch_progress = apt.progress.base.AcquireProgress()
+ if install_progress is None:
+ install_progress = apt.progress.base.InstallProgress()
+
+ assert install_progress is not None
+
+ with apt_pkg.SystemLock():
+ pm = apt_pkg.PackageManager(self._depcache)
+ fetcher = apt_pkg.Acquire(fetch_progress)
+ with self._archive_lock:
+ while True:
+ # fetch archives first
+ res = self._fetch_archives(fetcher, pm, allow_unauthenticated)
+
+ # then install
+ res = self.install_archives(pm, install_progress)
+ if res == pm.RESULT_COMPLETED:
+ break
+ elif res == pm.RESULT_FAILED:
+ raise SystemError("installArchives() failed")
+ elif res == pm.RESULT_INCOMPLETE:
+ pass
+ else:
+ raise SystemError(
+ "internal-error: unknown result "
+ "code from InstallArchives: %s" % res
+ )
+ # reload the fetcher for media swaping
+ fetcher.shutdown()
+ return res == pm.RESULT_COMPLETED
+
+ def clear(self) -> None:
+ """Unmark all changes"""
+ self._depcache.init()
+
+ # cache changes
+
+ def cache_post_change(self) -> None:
+ "called internally if the cache has changed, emit a signal then"
+ self._run_callbacks("cache_post_change")
+
+ def cache_pre_change(self) -> None:
+ """called internally if the cache is about to change, emit
+ a signal then"""
+ self._run_callbacks("cache_pre_change")
+
+ def connect(self, name: str, callback: Callable[..., None] | str) -> None:
+ """Connect to a signal.
+
+ .. deprecated:: 1.0
+
+ Please use connect2() instead, as this function is very
+ likely to cause a memory leak.
+ """
+ if callback != "_inc_changes_count":
+ warnings.warn(
+ "connect() likely causes a reference" " cycle, use connect2() instead",
+ RuntimeWarning,
+ 2,
+ )
+ if name not in self._callbacks:
+ self._callbacks[name] = []
+ self._callbacks[name].append(callback)
+
+ def connect2(
+ self, name: str, callback: Callable[..., Any], *args: object, **kwds: object
+ ) -> None:
+ """Connect to a signal.
+
+ The callback will be passed the cache as an argument, and
+ any arguments passed to this function. Make sure that, if you
+ pass a method of a class as your callback, your class does not
+ contain a reference to the cache.
+
+ Cyclic references to the cache can cause issues if the Cache object
+ is replaced by a new one, because the cache keeps a lot of objects and
+ tens of open file descriptors.
+
+ currently only used for cache_{post,pre}_{changed,open}.
+
+ .. versionadded:: 1.0
+ """
+ if name not in self._callbacks2:
+ self._callbacks2[name] = []
+ self._callbacks2[name].append((callback, args, kwds))
+
+ def actiongroup(self) -> apt_pkg.ActionGroup:
+ """Return an `ActionGroup` object for the current cache.
+
+ Action groups can be used to speedup actions. The action group is
+ active as soon as it is created, and disabled when the object is
+ deleted or when release() is called.
+
+ You can use the action group as a context manager, this is the
+ recommended way::
+
+ with cache.actiongroup():
+ for package in my_selected_packages:
+ package.mark_install()
+
+ This way, the action group is automatically released as soon as the
+ with statement block is left. It also has the benefit of making it
+ clear which parts of the code run with a action group and which
+ don't.
+ """
+ return apt_pkg.ActionGroup(self._depcache)
+
+ @property
+ def dpkg_journal_dirty(self) -> bool:
+ """Return True if the dpkg was interrupted
+
+ All dpkg operations will fail until this is fixed, the action to
+ fix the system if dpkg got interrupted is to run
+ 'dpkg --configure -a' as root.
+ """
+ dpkg_status_dir = os.path.dirname(
+ apt_pkg.config.find_file("Dir::State::status")
+ )
+ for f in os.listdir(os.path.join(dpkg_status_dir, "updates")):
+ if fnmatch.fnmatch(f, "[0-9]*"):
+ return True
+ return False
+
+ @property
+ def broken_count(self) -> int:
+ """Return the number of packages with broken dependencies."""
+ return self._depcache.broken_count
+
+ @property
+ def delete_count(self) -> int:
+ """Return the number of packages marked for deletion."""
+ return self._depcache.del_count
+
+ @property
+ def install_count(self) -> int:
+ """Return the number of packages marked for installation."""
+ return self._depcache.inst_count
+
+ @property
+ def keep_count(self) -> int:
+ """Return the number of packages marked as keep."""
+ return self._depcache.keep_count
+
+
+class ProblemResolver:
+ """Resolve problems due to dependencies and conflicts.
+
+ The first argument 'cache' is an instance of apt.Cache.
+ """
+
+ def __init__(self, cache: Cache) -> None:
+ self._resolver = apt_pkg.ProblemResolver(cache._depcache)
+ self._cache = cache
+
+ def clear(self, package: Package) -> None:
+ """Reset the package to the default state."""
+ self._resolver.clear(package._pkg)
+
+ def protect(self, package: Package) -> None:
+ """Protect a package so it won't be removed."""
+ self._resolver.protect(package._pkg)
+
+ def remove(self, package: Package) -> None:
+ """Mark a package for removal."""
+ self._resolver.remove(package._pkg)
+
+ def resolve(self) -> None:
+ """Resolve dependencies, try to remove packages where needed."""
+ self._cache.cache_pre_change()
+ self._resolver.resolve()
+ self._cache.cache_post_change()
+
+ def resolve_by_keep(self) -> None:
+ """Resolve dependencies, do not try to remove packages."""
+ self._cache.cache_pre_change()
+ self._resolver.resolve_by_keep()
+ self._cache.cache_post_change()
+
+ def keep_phased_updates(self) -> None:
+ """Keep back phased updates."""
+ self._cache.cache_pre_change()
+ self._resolver.keep_phased_updates()
+ self._cache.cache_post_change()
+
+
+# ----------------------------- experimental interface
+
+
+class Filter:
+ """Filter base class"""
+
+ def apply(self, pkg: Package) -> bool:
+ """Filter function, return True if the package matchs a
+ filter criteria and False otherwise
+ """
+ return True
+
+
+class MarkedChangesFilter(Filter):
+ """Filter that returns all marked changes"""
+
+ def apply(self, pkg: Package) -> bool:
+ if pkg.marked_install or pkg.marked_delete or pkg.marked_upgrade:
+ return True
+ else:
+ return False
+
+
+class InstalledFilter(Filter):
+ """Filter that returns all installed packages.
+
+ .. versionadded:: 1.0.0
+ """
+
+ def apply(self, pkg: Package) -> bool:
+ return pkg.is_installed
+
+
+class _FilteredCacheHelper:
+ """Helper class for FilteredCache to break a reference cycle."""
+
+ def __init__(self, cache: Cache) -> None:
+ # Do not keep a reference to the cache, or you have a cycle!
+
+ self._filtered: dict[str, bool] = {}
+ self._filters: list[Filter] = []
+ cache.connect2("cache_post_change", self.filter_cache_post_change)
+ cache.connect2("cache_post_open", self.filter_cache_post_change)
+
+ def _reapply_filter(self, cache: Cache) -> None:
+ "internal helper to refilter"
+ # Do not keep a reference to the cache, or you have a cycle!
+ self._filtered = {}
+ for pkg in cache:
+ for f in self._filters:
+ if f.apply(pkg):
+ self._filtered[pkg.name] = True
+ break
+
+ def set_filter(self, filter: Filter) -> None:
+ """Set the current active filter."""
+ self._filters = []
+ self._filters.append(filter)
+
+ def filter_cache_post_change(self, cache: Cache) -> None:
+ """Called internally if the cache changes, emit a signal then."""
+ # Do not keep a reference to the cache, or you have a cycle!
+ self._reapply_filter(cache)
+
+
+class FilteredCache:
+ """A package cache that is filtered.
+
+ Can work on a existing cache or create a new one
+ """
+
+ def __init__(
+ self, cache: Cache | None = None, progress: OpProgress | None = None
+ ) -> None:
+ if cache is None:
+ self.cache = Cache(progress)
+ else:
+ self.cache = cache
+ self._helper = _FilteredCacheHelper(self.cache)
+
+ def __len__(self) -> int:
+ return len(self._helper._filtered)
+
+ def __getitem__(self, key: str) -> Package:
+ return self.cache[key]
+
+ def __iter__(self) -> Iterator[Package]:
+ for pkgname in self._helper._filtered:
+ yield self.cache[pkgname]
+
+ def keys(self) -> KeysView[str]:
+ return self._helper._filtered.keys()
+
+ def has_key(self, key: object) -> bool:
+ return key in self
+
+ def __contains__(self, key: object) -> bool:
+ try:
+ # Normalize package name for multi arch
+ return self.cache[key].name in self._helper._filtered
+ except KeyError:
+ return False
+
+ def set_filter(self, filter: Filter) -> None:
+ """Set the current active filter."""
+ self._helper.set_filter(filter)
+ self.cache.cache_post_change()
+
+ def filter_cache_post_change(self) -> None:
+ """Called internally if the cache changes, emit a signal then."""
+ self._helper.filter_cache_post_change(self.cache)
+
+ def __getattr__(self, key: str) -> Any:
+ """we try to look exactly like a real cache."""
+ return getattr(self.cache, key)
+
+
+def cache_pre_changed(cache: Cache) -> None:
+ print("cache pre changed")
+
+
+def cache_post_changed(cache: Cache) -> None:
+ print("cache post changed")
+
+
+def _test() -> None:
+ """Internal test code."""
+ print("Cache self test")
+ apt_pkg.init()
+ cache = Cache(apt.progress.text.OpProgress())
+ cache.connect2("cache_pre_change", cache_pre_changed)
+ cache.connect2("cache_post_change", cache_post_changed)
+ print("aptitude" in cache)
+ pkg = cache["aptitude"]
+ print(pkg.name)
+ print(len(cache))
+
+ for pkgname in cache.keys():
+ assert cache[pkgname].name == pkgname
+
+ cache.upgrade()
+ changes = cache.get_changes()
+ print(len(changes))
+ for pkg in changes:
+ assert pkg.name
+
+ # see if fetching works
+ for dirname in ["/tmp/pytest", "/tmp/pytest/partial"]:
+ if not os.path.exists(dirname):
+ os.mkdir(dirname)
+ apt_pkg.config.set("Dir::Cache::Archives", "/tmp/pytest")
+ pm = apt_pkg.PackageManager(cache._depcache)
+ fetcher = apt_pkg.Acquire(apt.progress.text.AcquireProgress())
+ cache._fetch_archives(fetcher, pm, None)
+ # sys.exit(1)
+
+ print("Testing filtered cache (argument is old cache)")
+ filtered = FilteredCache(cache)
+ filtered.cache.connect2("cache_pre_change", cache_pre_changed)
+ filtered.cache.connect2("cache_post_change", cache_post_changed)
+ filtered.cache.upgrade()
+ filtered.set_filter(MarkedChangesFilter())
+ print(len(filtered))
+ for pkgname in filtered.keys():
+ assert pkgname == filtered[pkgname].name
+
+ print(len(filtered))
+
+ print("Testing filtered cache (no argument)")
+ filtered = FilteredCache(progress=apt.progress.base.OpProgress())
+ filtered.cache.connect2("cache_pre_change", cache_pre_changed)
+ filtered.cache.connect2("cache_post_change", cache_post_changed)
+ filtered.cache.upgrade()
+ filtered.set_filter(MarkedChangesFilter())
+ print(len(filtered))
+ for pkgname in filtered.keys():
+ assert pkgname == filtered[pkgname].name
+
+ print(len(filtered))
+
+
+if __name__ == "__main__":
+ _test()
diff --git a/apt/cdrom.py b/apt/cdrom.py
new file mode 100644
index 0000000..dc15c5b
--- /dev/null
+++ b/apt/cdrom.py
@@ -0,0 +1,91 @@
+# cdrom.py - CDROM handling
+#
+# Copyright (c) 2005-2009 Canonical
+# Copyright (c) 2009 Julian Andres Klode <jak@debian.org>
+#
+# Author: Michael Vogt <michael.vogt@ubuntu.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+"""Classes related to cdrom handling."""
+import glob
+
+import apt_pkg
+
+from apt.progress.base import CdromProgress
+
+
+class Cdrom(apt_pkg.Cdrom):
+ """Support for apt-cdrom like features.
+
+ This class has several optional parameters for initialisation, which may
+ be used to influence the behaviour of the object:
+
+ The optional parameter `progress` is a CdromProgress() subclass, which will
+ ask for the correct cdrom, etc. If not specified or None, a CdromProgress()
+ object will be used.
+
+ The optional parameter `mountpoint` may be used to specify an alternative
+ mountpoint.
+
+ If the optional parameter `nomount` is True, the cdroms will not be
+ mounted. This is the default behaviour.
+ """
+
+ def __init__(
+ self,
+ progress: CdromProgress | None = None,
+ mountpoint: str | None = None,
+ nomount: bool = True,
+ ) -> None:
+ apt_pkg.Cdrom.__init__(self)
+ if progress is None:
+ self._progress = CdromProgress()
+ else:
+ self._progress = progress
+ # see if we have a alternative mountpoint
+ if mountpoint is not None:
+ apt_pkg.config.set("Acquire::cdrom::mount", mountpoint)
+ # do not mess with mount points by default
+ if nomount:
+ apt_pkg.config.set("APT::CDROM::NoMount", "true")
+ else:
+ apt_pkg.config.set("APT::CDROM::NoMount", "false")
+
+ def add(self, progress: CdromProgress | None = None) -> bool:
+ """Add cdrom to the sources.list."""
+ return apt_pkg.Cdrom.add(self, progress or self._progress)
+
+ def ident(self, progress: CdromProgress | None = None) -> str:
+ """Identify the cdrom."""
+ return apt_pkg.Cdrom.ident(self, progress or self._progress)
+
+ @property
+ def in_sources_list(self) -> bool:
+ """Check if the cdrom is already in the current sources.list."""
+ cd_id = self.ident()
+ if cd_id is None:
+ # FIXME: throw exception instead
+ return False
+ # Get a list of files
+ src = glob.glob(apt_pkg.config.find_dir("Dir::Etc::sourceparts") + "*")
+ src.append(apt_pkg.config.find_file("Dir::Etc::sourcelist"))
+ # Check each file
+ for fname in src:
+ with open(fname) as fobj:
+ for line in fobj:
+ if not line.lstrip().startswith("#") and cd_id in line:
+ return True
+ return False
diff --git a/apt/debfile.py b/apt/debfile.py
new file mode 100644
index 0000000..b3ef733
--- /dev/null
+++ b/apt/debfile.py
@@ -0,0 +1,861 @@
+# Copyright (c) 2005-2010 Canonical
+#
+# Author: Michael Vogt <michael.vogt@ubuntu.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+"""Classes for working with locally available Debian packages."""
+
+import gzip
+import os
+import sys
+from collections.abc import Iterable
+from io import BytesIO
+from typing import cast
+
+import apt_inst
+import apt_pkg
+from apt_pkg import gettext as _
+
+import apt
+
+
+class NoDebArchiveException(IOError):
+ """Exception which is raised if a file is no Debian archive."""
+
+
+class DebPackage:
+ """A Debian Package (.deb file)."""
+
+ # Constants for comparing the local package file with the version
+ # in the cache
+ (VERSION_NONE, VERSION_OUTDATED, VERSION_SAME, VERSION_NEWER) = range(4)
+
+ debug = 0
+
+ def __init__(
+ self, filename: str | None = None, cache: apt.Cache | None = None
+ ) -> None:
+ if cache is None:
+ cache = apt.Cache()
+ self._cache = cache
+ self._debfile = cast(apt_inst.DebFile, None)
+ self.pkgname = ""
+ self.filename: str | None = None
+ self._sections: dict[str, str] | apt_pkg.TagSection[str] = {} # noqa
+ self._need_pkgs: list[str] = []
+ self._check_was_run = False
+ self._failure_string = ""
+ self._multiarch: str | None = None
+ if filename:
+ self.open(filename)
+
+ def open(self, filename: str) -> None:
+ """open given debfile"""
+ self._dbg(3, "open '%s'" % filename)
+ self._need_pkgs = []
+ self._installed_conflicts: set[str] = set()
+ self._failure_string = ""
+ self.filename = filename
+ self._debfile = apt_inst.DebFile(self.filename)
+ control = self._debfile.control.extractdata("control")
+ self._sections = apt_pkg.TagSection(control)
+ self.pkgname = self._sections["Package"]
+ self._check_was_run = False
+
+ def __getitem__(self, key: str) -> str:
+ return self._sections[key]
+
+ def __contains__(self, key: str) -> bool:
+ return key in self._sections
+
+ @property
+ def filelist(self) -> list[str]:
+ """return the list of files in the deb."""
+ files = []
+ try:
+ self._debfile.data.go(lambda item, data: files.append(item.name))
+ except SystemError:
+ return [_("List of files for '%s' could not be read") % self.filename]
+ return files
+
+ @property
+ def control_filelist(self) -> list[str]:
+ """return the list of files in control.tar.gz"""
+ control = []
+ try:
+ self._debfile.control.go(lambda item, data: control.append(item.name))
+ except SystemError:
+ return [
+ _("List of control files for '%s' could not be read") % self.filename
+ ]
+ return sorted(control)
+
+ # helper that will return a pkgname with a multiarch suffix if needed
+ def _maybe_append_multiarch_suffix(
+ self, pkgname: str, in_conflict_checking: bool = False
+ ) -> str:
+ # trivial cases
+ if ":" in pkgname:
+ return pkgname
+ if not self._multiarch:
+ return pkgname
+ elif self._cache.is_virtual_package(pkgname):
+ return pkgname
+ elif (
+ pkgname in self._cache
+ and self._cache[pkgname].candidate is not None
+ and cast(apt.package.Version, self._cache[pkgname].candidate).architecture
+ == "all"
+ ):
+ return pkgname
+ # now do the real multiarch checking
+ multiarch_pkgname = f"{pkgname}:{self._multiarch}"
+ # the upper layers will handle this
+ if multiarch_pkgname not in self._cache:
+ return multiarch_pkgname
+ multiarch_pkg = self._cache[multiarch_pkgname]
+ if multiarch_pkg.candidate is None:
+ return multiarch_pkgname
+ # now check the multiarch state
+ cand = multiarch_pkg.candidate._cand
+ # print pkgname, multiarch_pkgname, cand.multi_arch
+ # the default is to add the suffix, unless its a pkg that can satify
+ # foreign dependencies
+ if cand.multi_arch & cand.MULTI_ARCH_FOREIGN:
+ return pkgname
+ # for conflicts we need a special case here, any not multiarch enabled
+ # package has a implicit conflict
+ if in_conflict_checking and not (cand.multi_arch & cand.MULTI_ARCH_SAME):
+ return pkgname
+ return multiarch_pkgname
+
+ def _is_or_group_satisfied(self, or_group: list[tuple[str, str, str]]) -> bool:
+ """Return True if at least one dependency of the or-group is satisfied.
+
+ This method gets an 'or_group' and analyzes if at least one dependency
+ of this group is already satisfied.
+ """
+ self._dbg(2, "_checkOrGroup(): %s " % (or_group))
+
+ for dep in or_group:
+ depname = dep[0]
+ ver = dep[1]
+ oper = dep[2]
+
+ # multiarch
+ depname = self._maybe_append_multiarch_suffix(depname)
+
+ # check for virtual pkgs
+ if depname not in self._cache:
+ if self._cache.is_virtual_package(depname):
+ self._dbg(
+ 3, "_is_or_group_satisfied(): %s is virtual dep" % depname
+ )
+ for pkg in self._cache.get_providing_packages(depname):
+ if pkg.is_installed:
+ return True
+ continue
+ # check real dependency
+ inst = self._cache[depname].installed
+ if inst is not None and apt_pkg.check_dep(inst.version, oper, ver):
+ return True
+
+ # if no real dependency is installed, check if there is
+ # a package installed that provides this dependency
+ # (e.g. scrollkeeper dependecies are provided by rarian-compat)
+ # but only do that if there is no version required in the
+ # dependency (we do not supprot versionized dependencies)
+ if not oper:
+ for ppkg in self._cache.get_providing_packages(
+ depname, include_nonvirtual=True
+ ):
+ if ppkg.is_installed:
+ self._dbg(
+ 3,
+ "found installed '%s' that provides '%s'"
+ % (ppkg.name, depname),
+ )
+ return True
+ return False
+
+ def _satisfy_or_group(self, or_group: list[tuple[str, str, str]]) -> bool:
+ """Try to satisfy the or_group."""
+ for dep in or_group:
+ depname, ver, oper = dep
+
+ # multiarch
+ depname = self._maybe_append_multiarch_suffix(depname)
+
+ # if we don't have it in the cache, it may be virtual
+ if depname not in self._cache:
+ if not self._cache.is_virtual_package(depname):
+ continue
+ providers = self._cache.get_providing_packages(depname)
+ # if a package just has a single virtual provider, we
+ # just pick that (just like apt)
+ if len(providers) != 1:
+ continue
+ depname = providers[0].name
+
+ # now check if we can satisfy the deps with the candidate(s)
+ # in the cache
+ pkg = self._cache[depname]
+ cand = self._cache._depcache.get_candidate_ver(pkg._pkg)
+ if not cand:
+ continue
+ if not apt_pkg.check_dep(cand.ver_str, oper, ver):
+ continue
+
+ # check if we need to install it
+ self._dbg(2, "Need to get: %s" % depname)
+ self._need_pkgs.append(depname)
+ return True
+
+ # if we reach this point, we failed
+ or_str = ""
+ for dep in or_group:
+ or_str += dep[0]
+ if ver and oper:
+ or_str += f" ({dep[2]} {dep[1]})"
+ if dep != or_group[len(or_group) - 1]:
+ or_str += "|"
+ self._failure_string += _("Dependency is not satisfiable: %s\n") % or_str
+ return False
+
+ def _check_single_pkg_conflict(self, pkgname: str, ver: str, oper: str) -> bool:
+ """Return True if a pkg conflicts with a real installed/marked pkg."""
+ # FIXME: deal with conflicts against its own provides
+ # (e.g. Provides: ftp-server, Conflicts: ftp-server)
+ self._dbg(
+ 3,
+ "_check_single_pkg_conflict() pkg='%s' ver='%s' oper='%s'"
+ % (pkgname, ver, oper),
+ )
+ pkg = self._cache[pkgname]
+ if pkg.is_installed:
+ assert pkg.installed is not None
+ pkgver = pkg.installed.version
+ elif pkg.marked_install:
+ assert pkg.candidate is not None
+ pkgver = pkg.candidate.version
+ else:
+ return False
+ # print "pkg: %s" % pkgname
+ # print "ver: %s" % ver
+ # print "pkgver: %s " % pkgver
+ # print "oper: %s " % oper
+ if apt_pkg.check_dep(pkgver, oper, ver) and not self.replaces_real_pkg(
+ pkgname, oper, ver
+ ):
+ self._failure_string += (
+ _("Conflicts with the installed package " "'%s'") % pkg.name
+ )
+ self._dbg(3, "conflicts with installed pkg '%s'" % pkg.name)
+ return True
+ return False
+
+ def _check_conflicts_or_group(self, or_group: list[tuple[str, str, str]]) -> bool:
+ """Check the or-group for conflicts with installed pkgs."""
+ self._dbg(2, "_check_conflicts_or_group(): %s " % (or_group))
+ for dep in or_group:
+ depname = dep[0]
+ ver = dep[1]
+ oper = dep[2]
+
+ # FIXME: is this good enough? i.e. will apt always populate
+ # the cache with conflicting pkgnames for our arch?
+ depname = self._maybe_append_multiarch_suffix(
+ depname, in_conflict_checking=True
+ )
+
+ # check conflicts with virtual pkgs
+ if depname not in self._cache:
+ # FIXME: we have to check for virtual replaces here as
+ # well (to pass tests/gdebi-test8.deb)
+ if self._cache.is_virtual_package(depname):
+ for pkg in self._cache.get_providing_packages(depname):
+ self._dbg(3, "conflicts virtual check: %s" % pkg.name)
+ # P/C/R on virtal pkg, e.g. ftpd
+ if self.pkgname == pkg.name:
+ self._dbg(3, "conflict on self, ignoring")
+ continue
+ if self._check_single_pkg_conflict(pkg.name, ver, oper):
+ self._installed_conflicts.add(pkg.name)
+ continue
+ if self._check_single_pkg_conflict(depname, ver, oper):
+ self._installed_conflicts.add(depname)
+ return bool(self._installed_conflicts)
+
+ @property
+ def conflicts(self) -> list[list[tuple[str, str, str]]]:
+ """List of packages conflicting with this package."""
+ key = "Conflicts"
+ try:
+ return apt_pkg.parse_depends(self._sections[key], False)
+ except KeyError:
+ return []
+
+ @property
+ def depends(self) -> list[list[tuple[str, str, str]]]:
+ """List of packages on which this package depends on."""
+ depends = []
+ # find depends
+ for key in "Depends", "Pre-Depends":
+ try:
+ depends.extend(apt_pkg.parse_depends(self._sections[key], False))
+ except KeyError:
+ pass
+ return depends
+
+ @property
+ def provides(self) -> list[list[tuple[str, str, str]]]:
+ """List of virtual packages which are provided by this package."""
+ key = "Provides"
+ try:
+ return apt_pkg.parse_depends(self._sections[key], False)
+ except KeyError:
+ return []
+
+ @property
+ def replaces(self) -> list[list[tuple[str, str, str]]]:
+ """List of packages which are replaced by this package."""
+ key = "Replaces"
+ try:
+ return apt_pkg.parse_depends(self._sections[key], False)
+ except KeyError:
+ return []
+
+ def replaces_real_pkg(self, pkgname: str, oper: str, ver: str) -> bool:
+ """Return True if a given non-virtual package is replaced.
+
+ Return True if the deb packages replaces a real (not virtual)
+ packages named (pkgname, oper, ver).
+ """
+ self._dbg(3, f"replaces_real_pkg() {pkgname} {oper} {ver}")
+ pkg = self._cache[pkgname]
+ pkgver: str | None = None
+ if pkg.is_installed:
+ assert pkg.installed is not None
+ pkgver = pkg.installed.version
+ elif pkg.marked_install:
+ assert pkg.candidate is not None
+ pkgver = pkg.candidate.version
+ else:
+ pkgver = None
+ for or_group in self.replaces:
+ for name, ver, oper in or_group:
+ if name == pkgname and (
+ pkgver is None or apt_pkg.check_dep(pkgver, oper, ver)
+ ):
+ self._dbg(
+ 3,
+ "we have a replaces in our package for the "
+ "conflict against '%s'" % (pkgname),
+ )
+ return True
+ return False
+
+ def check_conflicts(self) -> bool:
+ """Check if there are conflicts with existing or selected packages.
+
+ Check if the package conflicts with a existing or to be installed
+ package. Return True if the pkg is OK.
+ """
+ res = True
+ for or_group in self.conflicts:
+ if self._check_conflicts_or_group(or_group):
+ # print "Conflicts with a exisiting pkg!"
+ # self._failure_string = "Conflicts with a exisiting pkg!"
+ res = False
+ return res
+
+ def check_breaks_existing_packages(self) -> bool:
+ """
+ check if installing the package would break exsisting
+ package on the system, e.g. system has:
+ smc depends on smc-data (= 1.4)
+ and user tries to installs smc-data 1.6
+ """
+ # show progress information as this step may take some time
+ size = float(len(self._cache))
+ steps = max(int(size / 50), 1)
+ debver = self._sections["Version"]
+ debarch = self._sections["Architecture"]
+ # store what we provide so that we can later check against that
+ provides = [x[0][0] for x in self.provides]
+ for i, pkg in enumerate(self._cache):
+ if i % steps == 0:
+ self._cache.op_progress.update(float(i) / size * 100.0)
+ if not pkg.is_installed:
+ continue
+ assert pkg.installed is not None
+ # check if the exising dependencies are still satisfied
+ # with the package
+ ver = pkg._pkg.current_ver
+ for dep_or in pkg.installed.dependencies:
+ for dep in dep_or.or_dependencies:
+ if dep.name == self.pkgname:
+ if not apt_pkg.check_dep(debver, dep.relation, dep.version):
+ self._dbg(2, "would break (depends) %s" % pkg.name)
+ # TRANSLATORS: the first '%s' is the package that
+ # breaks, the second the dependency that makes it
+ # break, the third the relation (e.g. >=) and the
+ # latest the version for the releation
+ self._failure_string += _(
+ "Breaks existing package '%(pkgname)s' "
+ "dependency %(depname)s "
+ "(%(deprelation)s %(depversion)s)"
+ ) % {
+ "pkgname": pkg.name,
+ "depname": dep.name,
+ "deprelation": dep.relation,
+ "depversion": dep.version,
+ }
+ self._cache.op_progress.done()
+ return False
+ # now check if there are conflicts against this package on
+ # the existing system
+ if "Conflicts" in ver.depends_list:
+ for conflicts_ver_list in ver.depends_list["Conflicts"]:
+ for c_or in conflicts_ver_list:
+ if (
+ c_or.target_pkg.name == self.pkgname
+ and c_or.target_pkg.architecture == debarch
+ ):
+ if apt_pkg.check_dep(
+ debver, c_or.comp_type, c_or.target_ver
+ ):
+ self._dbg(2, "would break (conflicts) %s" % pkg.name)
+ # TRANSLATORS: the first '%s' is the package
+ # that conflicts, the second the packagename
+ # that it conflicts with (so the name of the
+ # deb the user tries to install), the third is
+ # the relation (e.g. >=) and the last is the
+ # version for the relation
+ self._failure_string += _(
+ "Breaks existing package '%(pkgname)s' "
+ "conflict: %(targetpkg)s "
+ "(%(comptype)s %(targetver)s)"
+ ) % {
+ "pkgname": pkg.name,
+ "targetpkg": c_or.target_pkg.name,
+ "comptype": c_or.comp_type,
+ "targetver": c_or.target_ver,
+ }
+ self._cache.op_progress.done()
+ return False
+ if (
+ c_or.target_pkg.name in provides
+ and self.pkgname != pkg.name
+ ):
+ self._dbg(2, "would break (conflicts) %s" % provides)
+ self._failure_string += _(
+ "Breaks existing package '%(pkgname)s' "
+ "that conflict: '%(targetpkg)s'. But the "
+ "'%(debfile)s' provides it via: "
+ "'%(provides)s'"
+ ) % {
+ "provides": ",".join(provides),
+ "debfile": self.filename,
+ "targetpkg": c_or.target_pkg.name,
+ "pkgname": pkg.name,
+ }
+ self._cache.op_progress.done()
+ return False
+ self._cache.op_progress.done()
+ return True
+
+ def compare_to_version_in_cache(self, use_installed: bool = True) -> int:
+ """Compare the package to the version available in the cache.
+
+ Checks if the package is already installed or availabe in the cache
+ and if so in what version, returns one of (VERSION_NONE,
+ VERSION_OUTDATED, VERSION_SAME, VERSION_NEWER).
+ """
+ self._dbg(3, "compare_to_version_in_cache")
+ pkgname = self._sections["Package"]
+ architecture = self._sections["Architecture"]
+
+ # Arch qualify the package name
+ pkgname = ":".join([pkgname, architecture])
+
+ debver = self._sections["Version"]
+ self._dbg(1, "debver: %s" % debver)
+ if pkgname in self._cache:
+ pkg = self._cache[pkgname]
+ if use_installed and pkg.installed is not None:
+ cachever = pkg.installed.version
+ elif not use_installed and pkg.candidate is not None:
+ cachever = pkg.candidate.version
+ else:
+ return self.VERSION_NONE
+ if cachever is not None:
+ cmp = apt_pkg.version_compare(cachever, debver)
+ self._dbg(1, "CompareVersion(debver,instver): %s" % cmp)
+ if cmp == 0:
+ return self.VERSION_SAME
+ elif cmp < 0:
+ return self.VERSION_NEWER
+ elif cmp > 0:
+ return self.VERSION_OUTDATED
+ return self.VERSION_NONE
+
+ def check(self, allow_downgrade: bool = False) -> bool:
+ """Check if the package is installable."""
+ self._dbg(3, "check")
+
+ self._check_was_run = True
+
+ # check arch
+ if "Architecture" not in self._sections:
+ self._dbg(1, "ERROR: no architecture field")
+ self._failure_string = _("No Architecture field in the package")
+ return False
+ arch = self._sections["Architecture"]
+ if arch != "all" and arch != apt_pkg.config.find("APT::Architecture"):
+ if arch in apt_pkg.get_architectures():
+ self._multiarch = arch
+ self.pkgname = f"{self.pkgname}:{self._multiarch}"
+ self._dbg(1, "Found multiarch arch: '%s'" % arch)
+ else:
+ self._dbg(1, "ERROR: Wrong architecture dude!")
+ self._failure_string = (
+ _(
+ "Wrong architecture '%s' "
+ "-- Run dpkg --add-architecture to "
+ "add it and update afterwards"
+ )
+ % arch
+ )
+ return False
+
+ # check version
+ if (
+ not allow_downgrade
+ and self.compare_to_version_in_cache() == self.VERSION_OUTDATED
+ ):
+ if self._cache[self.pkgname].installed:
+ # the deb is older than the installed
+ self._failure_string = _("A later version is already installed")
+ return False
+
+ # FIXME: this sort of error handling sux
+ self._failure_string = ""
+
+ # check conflicts
+ if not self.check_conflicts():
+ return False
+
+ # check if installing it would break anything on the
+ # current system
+ if not self.check_breaks_existing_packages():
+ return False
+
+ # try to satisfy the dependencies
+ if not self._satisfy_depends(self.depends):
+ return False
+
+ # check for conflicts again (this time with the packages that are
+ # makeed for install)
+ if not self.check_conflicts():
+ return False
+
+ if self._cache._depcache.broken_count > 0:
+ self._failure_string = _(
+ "Failed to satisfy all dependencies " "(broken cache)"
+ )
+ # clean the cache again
+ self._cache.clear()
+ return False
+ return True
+
+ def satisfy_depends_str(self, dependsstr: str) -> bool:
+ """Satisfy the dependencies in the given string."""
+ return self._satisfy_depends(apt_pkg.parse_depends(dependsstr, False))
+
+ def _satisfy_depends(self, depends: list[list[tuple[str, str, str]]]) -> bool:
+ """Satisfy the dependencies."""
+ # turn off MarkAndSweep via a action group (if available)
+ try:
+ _actiongroup = apt_pkg.ActionGroup(self._cache._depcache)
+ _actiongroup # pyflakes
+ except AttributeError:
+ pass
+ # check depends
+ for or_group in depends:
+ if not self._is_or_group_satisfied(or_group):
+ if not self._satisfy_or_group(or_group):
+ return False
+ # now try it out in the cache
+ for pkg in self._need_pkgs:
+ try:
+ self._cache[pkg].mark_install(from_user=False)
+ except SystemError:
+ self._failure_string = _("Cannot install '%s'") % pkg
+ self._cache.clear()
+ return False
+ return True
+
+ @property
+ def missing_deps(self) -> list[str]:
+ """Return missing dependencies."""
+ self._dbg(1, "Installing: %s" % self._need_pkgs)
+ if not self._check_was_run:
+ raise AttributeError("property only available after check() was run")
+ return self._need_pkgs
+
+ @property
+ def required_changes(self) -> tuple[list[str], list[str], list[str]]:
+ """Get the changes required to satisfy the dependencies.
+
+ Returns: a tuple with (install, remove, unauthenticated)
+ """
+ install = []
+ remove = []
+ unauthenticated = []
+ if not self._check_was_run:
+ raise AttributeError("property only available after check() was run")
+ for pkg in self._cache:
+ if pkg.marked_install or pkg.marked_upgrade:
+ assert pkg.candidate is not None
+ install.append(pkg.name)
+ # check authentication, one authenticated origin is enough
+ # libapt will skip non-authenticated origins then
+ authenticated = False
+ for origin in pkg.candidate.origins:
+ authenticated |= origin.trusted
+ if not authenticated:
+ unauthenticated.append(pkg.name)
+ if pkg.marked_delete:
+ remove.append(pkg.name)
+ return (install, remove, unauthenticated)
+
+ @staticmethod
+ def to_hex(in_data: str) -> str:
+ hex = ""
+ for i, c in enumerate(in_data):
+ if i % 80 == 0:
+ hex += "\n"
+ hex += "%2.2x " % ord(c)
+ return hex
+
+ @staticmethod
+ def to_strish(in_data: str | Iterable[int]) -> str:
+ s = ""
+ # py2 compat, in_data is type string
+ if isinstance(in_data, str):
+ for c in in_data:
+ if ord(c) < 10 or ord(c) > 127:
+ s += " "
+ else:
+ s += c
+ # py3 compat, in_data is type bytes
+ else:
+ for b in in_data:
+ if b < 10 or b > 127:
+ s += " "
+ else:
+ s += chr(b)
+ return s
+
+ def _get_content(
+ self,
+ part: apt_inst.TarFile,
+ name: str,
+ auto_decompress: bool = True,
+ auto_hex: bool = True,
+ ) -> str:
+ if name.startswith("./"):
+ name = name[2:]
+ data = part.extractdata(name)
+ # check for zip content
+ if name.endswith(".gz") and auto_decompress:
+ io = BytesIO(data)
+ gz = gzip.GzipFile(fileobj=io)
+ data = _("Automatically decompressed:\n\n").encode("utf-8")
+ data += gz.read()
+ # auto-convert to hex
+ try:
+ return data.decode("utf-8")
+ except Exception:
+ new_data = _("Automatically converted to printable ascii:\n")
+ new_data += self.to_strish(data)
+ return new_data
+
+ def control_content(self, name: str) -> str:
+ """return the content of a specific control.tar.gz file"""
+ try:
+ return self._get_content(self._debfile.control, name)
+ except LookupError:
+ return ""
+
+ def data_content(self, name: str) -> str:
+ """return the content of a specific control.tar.gz file"""
+ try:
+ return self._get_content(self._debfile.data, name)
+ except LookupError:
+ return ""
+
+ def _dbg(self, level: int, msg: str) -> None:
+ """Write debugging output to sys.stderr."""
+ if level <= self.debug:
+ print(msg, file=sys.stderr)
+
+ def install(
+ self, install_progress: apt.progress.base.InstallProgress | None = None
+ ) -> int:
+ """Install the package."""
+ if self.filename is None:
+ raise apt_pkg.Error("No filename specified")
+ if install_progress is None:
+ return os.spawnlp(os.P_WAIT, "dpkg", "dpkg", "-i", self.filename)
+ else:
+ try:
+ install_progress.start_update()
+ except AttributeError:
+ install_progress.startUpdate() # type: ignore
+ res = install_progress.run(self.filename)
+ try:
+ install_progress.finish_update()
+ except AttributeError:
+ install_progress.finishUpdate() # type: ignore
+ return res
+
+
+class DscSrcPackage(DebPackage):
+ """A locally available source package."""
+
+ def __init__(
+ self, filename: str | None = None, cache: apt.Cache | None = None
+ ) -> None:
+ DebPackage.__init__(self, None, cache)
+ self.filename: str | None = filename
+ self._depends: list[list[tuple[str, str, str]]] = []
+ self._conflicts: list[list[tuple[str, str, str]]] = []
+ self._installed_conflicts: set[str] = set()
+ self.pkgname = ""
+ self.binaries: list[str] = []
+ self._sections: dict[str, str] = {}
+ if self.filename is not None:
+ self.open(self.filename)
+
+ @property
+ def depends(self) -> list[list[tuple[str, str, str]]]:
+ """Return the dependencies of the package"""
+ return self._depends
+
+ @property
+ def conflicts(self) -> list[list[tuple[str, str, str]]]:
+ """Return the dependencies of the package"""
+ return self._conflicts
+
+ @property
+ def filelist(self) -> list[str]:
+ """Return the list of files associated with this dsc file"""
+ # Files stanza looks like (hash, size, filename, ...)
+ return self._sections["Files"].split()[2::3]
+
+ def open(self, file: str) -> None:
+ """Open the package."""
+ depends_tags = ["Build-Depends", "Build-Depends-Indep"]
+ conflicts_tags = ["Build-Conflicts", "Build-Conflicts-Indep"]
+ fd = apt_pkg.open_maybe_clear_signed_file(file)
+ fobj = os.fdopen(fd)
+ tagfile = apt_pkg.TagFile(fobj)
+ try:
+ for sec in tagfile:
+ for tag in depends_tags:
+ if tag not in sec:
+ continue
+ self._depends.extend(apt_pkg.parse_src_depends(sec[tag]))
+ for tag in conflicts_tags:
+ if tag not in sec:
+ continue
+ self._conflicts.extend(apt_pkg.parse_src_depends(sec[tag]))
+ if "Source" in sec:
+ self.pkgname = sec["Source"]
+ if "Binary" in sec:
+ self.binaries = [b.strip() for b in sec["Binary"].split(",")]
+ for tag in sec.keys():
+ if tag in sec:
+ self._sections[tag] = sec[tag]
+ finally:
+ del tagfile
+ fobj.close()
+
+ s = _(
+ "Install Build-Dependencies for " "source package '%s' that builds %s\n"
+ ) % (self.pkgname, " ".join(self.binaries))
+ self._sections["Description"] = s
+ self._check_was_run = False
+
+ def check(self, allow_downgrade: bool = False) -> bool:
+ """Check if the package is installable.
+
+ The second parameter is ignored and only exists for compatibility
+ with parent type."""
+ if not self.check_conflicts():
+ for pkgname in self._installed_conflicts:
+ if self._cache[pkgname]._pkg.essential:
+ raise Exception(_("An essential package would be removed"))
+ self._cache[pkgname].mark_delete()
+ # properties are ok now
+ self._check_was_run = True
+ # FIXME: a additional run of the check_conflicts()
+ # after _satisfy_depends() should probably be done
+ return self._satisfy_depends(self.depends)
+
+
+def _test() -> None:
+ """Test function"""
+ from apt.cache import Cache
+ from apt.progress.base import InstallProgress
+
+ cache = Cache()
+
+ vp = "www-browser"
+ print(f"{vp} virtual: {cache.is_virtual_package(vp)}")
+ providers = cache.get_providing_packages(vp)
+ print("Providers for %s :" % vp)
+ for pkg in providers:
+ print(" %s" % pkg.name)
+
+ d = DebPackage(sys.argv[1], cache)
+ print("Deb: %s" % d.pkgname)
+ if not d.check():
+ print("can't be satified")
+ print(d._failure_string)
+ print("missing deps: %s" % d.missing_deps)
+ print(d.required_changes)
+
+ print(d.filelist)
+
+ print("Installing ...")
+ ret = d.install(InstallProgress())
+ print(ret)
+
+ # s = DscSrcPackage(cache, "../tests/3ddesktop_0.2.9-6.dsc")
+ # s.check_dep()
+ # print "Missing deps: ",s.missingDeps
+ # print "Print required changes: ", s.requiredChanges
+
+ s = DscSrcPackage(cache=cache)
+ ds = "libc6 (>= 2.3.2), libaio (>= 0.3.96) | libaio1 (>= 0.3.96)"
+ print(s._satisfy_depends(apt_pkg.parse_depends(ds, False)))
+
+
+if __name__ == "__main__":
+ _test()
diff --git a/apt/package.py b/apt/package.py
new file mode 100644
index 0000000..50ed6d1
--- /dev/null
+++ b/apt/package.py
@@ -0,0 +1,1559 @@
+# package.py - apt package abstraction
+#
+# Copyright (c) 2005-2009 Canonical
+#
+# Author: Michael Vogt <michael.vogt@ubuntu.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+"""Functionality related to packages."""
+from __future__ import annotations
+
+import logging
+import os
+import re
+import socket
+import subprocess
+import sys
+import threading
+from collections.abc import Iterable, Iterator, Mapping, Sequence
+from http.client import BadStatusLine
+from typing import Any, no_type_check
+from urllib.error import HTTPError
+from urllib.request import urlopen
+
+import apt_pkg
+from apt_pkg import gettext as _
+
+import apt.progress.text
+from apt.progress.base import AcquireProgress, InstallProgress
+
+__all__ = (
+ "BaseDependency",
+ "Dependency",
+ "Origin",
+ "Package",
+ "Record",
+ "Version",
+ "VersionList",
+)
+
+
+def _file_is_same(path: str, size: int, hashes: apt_pkg.HashStringList) -> bool:
+ """Return ``True`` if the file is the same."""
+ if os.path.exists(path) and os.path.getsize(path) == size:
+ with open(path) as fobj:
+ return apt_pkg.Hashes(fobj).hashes == hashes
+ return False
+
+
+class FetchError(Exception):
+ """Raised when a file could not be fetched."""
+
+
+class UntrustedError(FetchError):
+ """Raised when a file did not have a trusted hash."""
+
+
+class BaseDependency:
+ """A single dependency."""
+
+ class __dstr(str):
+ """Compare helper for compatibility with old third-party code.
+
+ Old third-party code might still compare the relation with the
+ previously used relations (<<,<=,==,!=,>=,>>,) instead of the curently
+ used ones (<,<=,=,!=,>=,>,). This compare helper lets < match to <<,
+ > match to >> and = match to ==.
+ """
+
+ def __eq__(self, other: object) -> bool:
+ if str.__eq__(self, other):
+ return True
+ elif str.__eq__(self, "<"):
+ return str.__eq__("<<", other)
+ elif str.__eq__(self, ">"):
+ return str.__eq__(">>", other)
+ elif str.__eq__(self, "="):
+ return str.__eq__("==", other)
+ else:
+ return False
+
+ def __ne__(self, other: object) -> bool:
+ return not self.__eq__(other)
+
+ def __init__(self, version: Version, dep: apt_pkg.Dependency) -> None:
+ self._version = version # apt.package.Version
+ self._dep = dep # apt_pkg.Dependency
+
+ def __str__(self) -> str:
+ return f"{self.rawtype}: {self.rawstr}"
+
+ def __repr__(self) -> str:
+ return "<BaseDependency: name:{!r} relation:{!r} version:{!r} rawtype:{!r}>".format(
+ self.name,
+ self.relation,
+ self.version,
+ self.rawtype,
+ )
+
+ @property
+ def name(self) -> str:
+ """The name of the target package."""
+ return self._dep.target_pkg.name
+
+ @property
+ def relation(self) -> str:
+ """The relation (<, <=, =, !=, >=, >, '') in mathematical notation.
+
+ The empty string will be returned in case of an unversioned dependency.
+ """
+ return self.__dstr(self._dep.comp_type)
+
+ @property
+ def relation_deb(self) -> str:
+ """The relation (<<, <=, =, !=, >=, >>, '') in Debian notation.
+
+ The empty string will be returned in case of an unversioned dependency.
+ For more details see the Debian Policy Manual on the syntax of
+ relationship fields:
+ https://www.debian.org/doc/debian-policy/ch-relationships.html#s-depsyntax # noqa
+
+ .. versionadded:: 1.0.0
+ """
+ return self._dep.comp_type_deb
+
+ @property
+ def version(self) -> str:
+ """The target version or an empty string.
+
+ Note that the version is only an empty string in case of an unversioned
+ dependency. In this case the relation is also an empty string.
+ """
+ return self._dep.target_ver
+
+ @property
+ def target_versions(self) -> list[Version]:
+ """A list of all Version objects which satisfy this dependency.
+
+ .. versionadded:: 1.0.0
+ """
+ tvers = []
+ _tvers: list[apt_pkg.Version] = self._dep.all_targets()
+ for _tver in _tvers: # type: apt_pkg.Version
+ _pkg: apt_pkg.Package = _tver.parent_pkg
+ cache = self._version.package._pcache # apt.cache.Cache
+ pkg = cache._rawpkg_to_pkg(_pkg) # apt.package.Package
+ tver = Version(pkg, _tver) # apt.package.Version
+ tvers.append(tver)
+ return tvers
+
+ @property
+ def installed_target_versions(self) -> list[Version]:
+ """A list of all installed Version objects which satisfy this dep.
+
+ .. versionadded:: 1.0.0
+ """
+ return [tver for tver in self.target_versions if tver.is_installed]
+
+ @property
+ def rawstr(self) -> str:
+ """String represenation of the dependency.
+
+ Returns the string representation of the dependency as it would be
+ written in the debian/control file. The string representation does not
+ include the type of the dependency.
+
+ Example for an unversioned dependency:
+ python3
+
+ Example for a versioned dependency:
+ python3 >= 3.2
+
+ .. versionadded:: 1.0.0
+ """
+ if self.version:
+ return f"{self.name} {self.relation_deb} {self.version}"
+ else:
+ return self.name
+
+ @property
+ def rawtype(self) -> str:
+ """Type of the dependency.
+
+ This should be one of 'Breaks', 'Conflicts', 'Depends', 'Enhances',
+ 'PreDepends', 'Recommends', 'Replaces', 'Suggests'.
+
+ Additional types might be added in the future.
+ """
+ return self._dep.dep_type_untranslated
+
+ @property
+ def pre_depend(self) -> bool:
+ """Whether this is a PreDepends."""
+ return self._dep.dep_type_untranslated == "PreDepends"
+
+
+class Dependency(list[BaseDependency]):
+ """Represent an Or-group of dependencies.
+
+ Attributes defined here:
+ or_dependencies - The possible choices
+ rawstr - String represenation of the Or-group of dependencies
+ rawtype - The type of the dependencies in the Or-group
+ target_version - A list of Versions which satisfy this Or-group of deps
+ """
+
+ def __init__(
+ self, version: Version, base_deps: list[BaseDependency], rawtype: str
+ ) -> None:
+ super().__init__(base_deps)
+ self._version = version # apt.package.Version
+ self._rawtype = rawtype
+
+ def __str__(self) -> str:
+ return f"{self.rawtype}: {self.rawstr}"
+
+ def __repr__(self) -> str:
+ return "<Dependency: [%s]>" % (", ".join(repr(bd) for bd in self))
+
+ @property
+ def or_dependencies(self) -> Dependency:
+ return self
+
+ @property
+ def rawstr(self) -> str:
+ """String represenation of the Or-group of dependencies.
+
+ Returns the string representation of the Or-group of dependencies as it
+ would be written in the debian/control file. The string representation
+ does not include the type of the Or-group of dependencies.
+
+ Example:
+ python2 >= 2.7 | python3
+
+ .. versionadded:: 1.0.0
+ """
+ return " | ".join(bd.rawstr for bd in self)
+
+ @property
+ def rawtype(self) -> str:
+ """Type of the Or-group of dependency.
+
+ This should be one of 'Breaks', 'Conflicts', 'Depends', 'Enhances',
+ 'PreDepends', 'Recommends', 'Replaces', 'Suggests'.
+
+ Additional types might be added in the future.
+
+ .. versionadded:: 1.0.0
+ """
+ return self._rawtype
+
+ @property
+ def target_versions(self) -> list[Version]:
+ """A list of all Version objects which satisfy this Or-group of deps.
+
+ .. versionadded:: 1.0.0
+ """
+ tvers: list[Version] = []
+ for bd in self: # apt.package.Dependency
+ for tver in bd.target_versions: # apt.package.Version
+ if tver not in tvers:
+ tvers.append(tver)
+ return tvers
+
+ @property
+ def installed_target_versions(self) -> list[Version]:
+ """A list of all installed Version objects which satisfy this dep.
+
+ .. versionadded:: 1.0.0
+ """
+ return [tver for tver in self.target_versions if tver.is_installed]
+
+
+class Origin:
+ """The origin of a version.
+
+ Attributes defined here:
+ archive - The archive (eg. unstable)
+ component - The component (eg. main)
+ label - The Label, as set in the Release file
+ origin - The Origin, as set in the Release file
+ codename - The Codename, as set in the Release file
+ site - The hostname of the site.
+ trusted - Boolean value whether this is trustworthy.
+ """
+
+ def __init__(self, pkg: Package, packagefile: apt_pkg.PackageFile) -> None:
+ self.archive = packagefile.archive
+ self.component = packagefile.component
+ self.label = packagefile.label
+ self.origin = packagefile.origin
+ self.codename = packagefile.codename
+ self.site = packagefile.site
+ self.not_automatic = packagefile.not_automatic
+ # check the trust
+ indexfile = pkg._pcache._list.find_index(packagefile)
+ if indexfile and indexfile.is_trusted:
+ self.trusted = True
+ else:
+ self.trusted = False
+
+ def __repr__(self) -> str:
+ return (
+ "<Origin component:%r archive:%r origin:%r label:%r "
+ "site:%r isTrusted:%r>"
+ ) % (
+ self.component,
+ self.archive,
+ self.origin,
+ self.label,
+ self.site,
+ self.trusted,
+ )
+
+
+class Record(Mapping[Any, Any]):
+ """Record in a Packages file
+
+ Represent a record as stored in a Packages file. You can use this like
+ a dictionary mapping the field names of the record to their values::
+
+ >>> record = Record("Package: python-apt\\nVersion: 0.8.0\\n\\n")
+ >>> record["Package"]
+ 'python-apt'
+ >>> record["Version"]
+ '0.8.0'
+
+ For example, to get the tasks of a package from a cache, you could do::
+
+ package.candidate.record["Tasks"].split()
+
+ Of course, you can also use the :attr:`Version.tasks` property.
+
+ """
+
+ def __init__(self, record_str: str) -> None:
+ self._rec = apt_pkg.TagSection(record_str)
+
+ def __hash__(self) -> int:
+ return hash(self._rec)
+
+ def __str__(self) -> str:
+ return str(self._rec)
+
+ def __getitem__(self, key: str) -> str:
+ return self._rec[key]
+
+ def __contains__(self, key: object) -> bool:
+ return key in self._rec
+
+ def __iter__(self) -> Iterator[str]:
+ return iter(self._rec.keys())
+
+ def iteritems(self) -> Iterable[tuple[object, str]]:
+ """An iterator over the (key, value) items of the record."""
+ for key in self._rec.keys():
+ yield key, self._rec[key]
+
+ def get(self, key: str, default: object = None) -> object:
+ """Return record[key] if key in record, else *default*.
+
+ The parameter *default* must be either a string or None.
+ """
+ return self._rec.get(key, default)
+
+ def has_key(self, key: str) -> bool:
+ """deprecated form of ``key in x``."""
+ return key in self._rec
+
+ def __len__(self) -> int:
+ return len(self._rec)
+
+
+class Version:
+ """Representation of a package version.
+
+ The Version class contains all information related to a
+ specific package version.
+
+ .. versionadded:: 0.7.9
+ """
+
+ def __init__(self, package: Package, cand: apt_pkg.Version) -> None:
+ self.package = package
+ self._cand = cand
+ self.package._pcache._weakversions.add(self)
+
+ def _cmp(self, other: Any) -> int | Any:
+ """Compares against another apt.Version object or a version string.
+
+ This method behaves like Python 2's cmp builtin and returns an integer
+ according to the outcome. The return value is negative in case of
+ self < other, zero if self == other and positive if self > other.
+
+ The comparison includes the package name and architecture if other is
+ an apt.Version object. If other isn't an apt.Version object it'll be
+ assumed that other is a version string (without package name/arch).
+
+ .. versionchanged:: 1.0.0
+ """
+ # Assume that other is an apt.Version object.
+ try:
+ self_name = self.package.fullname
+ other_name = other.package.fullname
+ if self_name < other_name:
+ return -1
+ elif self_name > other_name:
+ return 1
+ return apt_pkg.version_compare(self._cand.ver_str, other.version)
+ except AttributeError:
+ # Assume that other is a string that only contains the version.
+ try:
+ return apt_pkg.version_compare(self._cand.ver_str, other)
+ except TypeError:
+ return NotImplemented
+
+ def __eq__(self, other: object) -> bool:
+ return self._cmp(other) == 0
+
+ def __ge__(self, other: Version) -> bool:
+ return self._cmp(other) >= 0
+
+ def __gt__(self, other: Version) -> bool:
+ return self._cmp(other) > 0
+
+ def __le__(self, other: Version) -> bool:
+ return self._cmp(other) <= 0
+
+ def __lt__(self, other: Version) -> bool:
+ return self._cmp(other) < 0
+
+ def __ne__(self, other: object) -> bool | Any:
+ try:
+ return self._cmp(other) != 0
+ except TypeError:
+ return NotImplemented
+
+ def __hash__(self) -> int:
+ return self._cand.hash
+
+ def __str__(self) -> str:
+ return f"{self.package.name}={self.version}"
+
+ def __repr__(self) -> str:
+ return f"<Version: package:{self.package.name!r} version:{self.version!r}>"
+
+ @property
+ def _records(self) -> apt_pkg.PackageRecords:
+ """Internal helper that moves the Records to the right position."""
+ # If changing lookup, change fetch_binary() as well
+ if not self.package._pcache._records.lookup(self._cand.file_list[0]):
+ raise LookupError("Could not lookup record")
+
+ return self.package._pcache._records
+
+ @property
+ def _translated_records(self) -> apt_pkg.PackageRecords | None:
+ """Internal helper to get the translated description."""
+ desc_iter = self._cand.translated_description
+ if self.package._pcache._records.lookup(desc_iter.file_list.pop(0)):
+ return self.package._pcache._records
+ return None
+
+ @property
+ def is_security_update(self) -> bool:
+ """Return whether this version is a security update."""
+ return bool(self._cand.is_security_update)
+
+ @property
+ def installed_size(self) -> int:
+ """Return the size of the package when installed."""
+ return self._cand.installed_size
+
+ @property
+ def homepage(self) -> str:
+ """Return the homepage for the package."""
+ return self._records.homepage
+
+ @property
+ def size(self) -> int:
+ """Return the size of the package."""
+ return self._cand.size
+
+ @property
+ def architecture(self) -> str:
+ """Return the architecture of the package version."""
+ return self._cand.arch
+
+ @property
+ def downloadable(self) -> bool:
+ """Return whether the version of the package is downloadable."""
+ return bool(self._cand.downloadable)
+
+ @property
+ def is_installed(self) -> bool:
+ """Return wether this version of the package is currently installed.
+
+ .. versionadded:: 1.0.0
+ """
+ inst_ver = self.package.installed
+ return inst_ver is not None and inst_ver._cand.id == self._cand.id
+
+ @property
+ def version(self) -> str:
+ """Return the version as a string."""
+ return self._cand.ver_str
+
+ @property
+ def summary(self) -> str | None:
+ """Return the short description (one line summary)."""
+ records = self._translated_records
+ return records.short_desc if records is not None else None
+
+ @property
+ def raw_description(self) -> str:
+ """return the long description (raw)."""
+ return self._records.long_desc
+
+ @property
+ def section(self) -> str:
+ """Return the section of the package."""
+ return self._cand.section
+
+ @property
+ def description(self) -> str:
+ """Return the formatted long description.
+
+ Return the formatted long description according to the Debian policy
+ (Chapter 5.6.13).
+ See http://www.debian.org/doc/debian-policy/ch-controlfields.html
+ for more information.
+ """
+ desc = ""
+ records = self._translated_records
+ dsc = records.long_desc if records is not None else None
+
+ if not dsc:
+ return _("Missing description for '%s'." "Please report.") % (
+ self.package.name
+ )
+
+ try:
+ if not isinstance(dsc, str):
+ # Only convert where needed (i.e. Python 2.X)
+ dsc = dsc.decode("utf-8")
+ except UnicodeDecodeError as err:
+ return _(
+ "Invalid unicode in description for '%s' (%s). " "Please report."
+ ) % (self.package.name, err)
+
+ lines = iter(dsc.split("\n"))
+ # Skip the first line, since its a duplication of the summary
+ next(lines)
+ for raw_line in lines:
+ if raw_line.strip() == ".":
+ # The line is just line break
+ if not desc.endswith("\n"):
+ desc += "\n\n"
+ continue
+ if raw_line.startswith(" "):
+ # The line should be displayed verbatim without word wrapping
+ if not desc.endswith("\n"):
+ line = "\n%s\n" % raw_line[2:]
+ else:
+ line = "%s\n" % raw_line[2:]
+ elif raw_line.startswith(" "):
+ # The line is part of a paragraph.
+ if desc.endswith("\n") or desc == "":
+ # Skip the leading white space
+ line = raw_line[1:]
+ else:
+ line = raw_line
+ else:
+ line = raw_line
+ # Add current line to the description
+ desc += line
+ return desc
+
+ @property
+ def source_name(self) -> str:
+ """Return the name of the source package."""
+ try:
+ return self._records.source_pkg or self.package.shortname
+ except IndexError:
+ return self.package.shortname
+
+ @property
+ def source_version(self) -> str:
+ """Return the version of the source package."""
+ try:
+ return self._records.source_ver or self._cand.ver_str
+ except IndexError:
+ return self._cand.ver_str
+
+ @property
+ def priority(self) -> str:
+ """Return the priority of the package, as string."""
+ return self._cand.priority_str
+
+ @property
+ def policy_priority(self) -> int:
+ """Return the internal policy priority as a number.
+ See apt_preferences(5) for more information about what it means.
+ """
+ return self.package._pcache._depcache.policy.get_priority(self._cand)
+
+ @property
+ def record(self) -> Record:
+ """Return a Record() object for this version.
+
+ Return a Record() object for this version which provides access
+ to the raw attributes of the candidate version
+ """
+ return Record(self._records.record)
+
+ def get_dependencies(self, *types: str) -> list[Dependency]:
+ """Return a list of Dependency objects for the given types.
+
+ Multiple types can be specified. Possible types are:
+ 'Breaks', 'Conflicts', 'Depends', 'Enhances', 'PreDepends',
+ 'Recommends', 'Replaces', 'Suggests'
+
+ Additional types might be added in the future.
+ """
+ depends_list = []
+ depends = self._cand.depends_list
+ for type_ in types:
+ try:
+ for dep_ver_list in depends[type_]:
+ base_deps = []
+ for dep_or in dep_ver_list:
+ base_deps.append(BaseDependency(self, dep_or))
+ depends_list.append(Dependency(self, base_deps, type_))
+ except KeyError:
+ pass
+ return depends_list
+
+ @property
+ def provides(self) -> list[str]:
+ """Return a list of names that this version provides."""
+ return [p[0] for p in self._cand.provides_list]
+
+ @property
+ def enhances(self) -> list[Dependency]:
+ """Return the list of enhances for the package version."""
+ return self.get_dependencies("Enhances")
+
+ @property
+ def dependencies(self) -> list[Dependency]:
+ """Return the dependencies of the package version."""
+ return self.get_dependencies("PreDepends", "Depends")
+
+ @property
+ def recommends(self) -> list[Dependency]:
+ """Return the recommends of the package version."""
+ return self.get_dependencies("Recommends")
+
+ @property
+ def suggests(self) -> list[Dependency]:
+ """Return the suggests of the package version."""
+ return self.get_dependencies("Suggests")
+
+ @property
+ def origins(self) -> list[Origin]:
+ """Return a list of origins for the package version."""
+ origins = []
+ for packagefile, _unused in self._cand.file_list:
+ origins.append(Origin(self.package, packagefile))
+ return origins
+
+ @property
+ def filename(self) -> str:
+ """Return the path to the file inside the archive.
+
+ .. versionadded:: 0.7.10
+ """
+ return self._records.filename
+
+ @property
+ def md5(self) -> str:
+ """Return the md5sum of the binary.
+
+ .. versionadded:: 0.7.10
+ """
+ return self._records.md5_hash
+
+ @property
+ def sha1(self) -> str:
+ """Return the sha1sum of the binary.
+
+ .. versionadded:: 0.7.10
+ """
+ return self._records.sha1_hash
+
+ @property
+ def sha256(self) -> str:
+ """Return the sha256sum of the binary.
+
+ .. versionadded:: 0.7.10
+ """
+ return self._records.sha256_hash
+
+ @property
+ def tasks(self) -> set[str]:
+ """Get the tasks of the package.
+
+ A set of the names of the tasks this package belongs to.
+
+ .. versionadded:: 0.8.0
+ """
+ return set(self.record["Task"].split())
+
+ def _uris(self) -> Iterator[str]:
+ """Return an iterator over all available urls.
+
+ .. versionadded:: 0.7.10
+ """
+ for packagefile, _unused in self._cand.file_list:
+ indexfile = self.package._pcache._list.find_index(packagefile)
+ if indexfile:
+ yield indexfile.archive_uri(self._records.filename)
+
+ @property
+ def uris(self) -> list[str]:
+ """Return a list of all available uris for the binary.
+
+ .. versionadded:: 0.7.10
+ """
+ return list(self._uris())
+
+ @property
+ def uri(self) -> str | None:
+ """Return a single URI for the binary.
+
+ .. versionadded:: 0.7.10
+ """
+ try:
+ return next(iter(self._uris()))
+ except StopIteration:
+ return None
+
+ def fetch_binary(
+ self,
+ destdir: str = "",
+ progress: AcquireProgress | None = None,
+ allow_unauthenticated: bool | None = None,
+ ) -> str:
+ """Fetch the binary version of the package.
+
+ The parameter *destdir* specifies the directory where the package will
+ be fetched to.
+
+ The parameter *progress* may refer to an apt_pkg.AcquireProgress()
+ object. If not specified or None, apt.progress.text.AcquireProgress()
+ is used.
+
+ The keyword-only parameter *allow_unauthenticated* specifies whether
+ to allow unauthenticated downloads. If not specified, it defaults to
+ the configuration option `APT::Get::AllowUnauthenticated`.
+
+ .. versionadded:: 0.7.10
+ """
+ if allow_unauthenticated is None:
+ allow_unauthenticated = apt_pkg.config.find_b(
+ "APT::Get::" "AllowUnauthenticated", False
+ )
+ base = os.path.basename(self._records.filename)
+ destfile = os.path.join(destdir, base)
+ if _file_is_same(destfile, self.size, self._records.hashes):
+ logging.debug("Ignoring already existing file: %s" % destfile)
+ return os.path.abspath(destfile)
+
+ # Verify that the index is actually trusted
+ pfile, offset = self._cand.file_list[0]
+ index = self.package._pcache._list.find_index(pfile)
+
+ if not (allow_unauthenticated or (index and index.is_trusted)):
+ raise UntrustedError(
+ "Could not fetch %s %s source package: "
+ "Source %r is not trusted"
+ % (
+ self.package.name,
+ self.version,
+ getattr(index, "describe", "<unknown>"),
+ )
+ )
+ if not self.uri:
+ raise ValueError("No URI for this binary.")
+ hashes = self._records.hashes
+ if not (allow_unauthenticated or hashes.usable):
+ raise UntrustedError(
+ "The item %r could not be fetched: " "No trusted hash found." % destfile
+ )
+ acq = apt_pkg.Acquire(progress or apt.progress.text.AcquireProgress())
+ acqfile = apt_pkg.AcquireFile(
+ acq, self.uri, hashes, self.size, base, destfile=destfile
+ )
+ acq.run()
+
+ if acqfile.status != acqfile.STAT_DONE:
+ raise FetchError(
+ "The item %r could not be fetched: %s"
+ % (acqfile.destfile, acqfile.error_text)
+ )
+
+ return os.path.abspath(destfile)
+
+ def fetch_source(
+ self,
+ destdir: str = "",
+ progress: AcquireProgress | None = None,
+ unpack: bool = True,
+ allow_unauthenticated: bool | None = None,
+ ) -> str:
+ """Get the source code of a package.
+
+ The parameter *destdir* specifies the directory where the source will
+ be fetched to.
+
+ The parameter *progress* may refer to an apt_pkg.AcquireProgress()
+ object. If not specified or None, apt.progress.text.AcquireProgress()
+ is used.
+
+ The parameter *unpack* describes whether the source should be unpacked
+ (``True``) or not (``False``). By default, it is unpacked.
+
+ If *unpack* is ``True``, the path to the extracted directory is
+ returned. Otherwise, the path to the .dsc file is returned.
+
+ The keyword-only parameter *allow_unauthenticated* specifies whether
+ to allow unauthenticated downloads. If not specified, it defaults to
+ the configuration option `APT::Get::AllowUnauthenticated`.
+ """
+ if allow_unauthenticated is None:
+ allow_unauthenticated = apt_pkg.config.find_b(
+ "APT::Get::" "AllowUnauthenticated", False
+ )
+
+ src = apt_pkg.SourceRecords()
+ acq = apt_pkg.Acquire(progress or apt.progress.text.AcquireProgress())
+
+ dsc = None
+ record = self._records
+ source_name = record.source_pkg or self.package.shortname
+ source_version = record.source_ver or self._cand.ver_str
+ source_lookup = src.lookup(source_name)
+
+ while source_lookup and source_version != src.version:
+ source_lookup = src.lookup(source_name)
+ if not source_lookup:
+ raise ValueError("No source for %r" % self)
+ files = list()
+
+ if not (allow_unauthenticated or src.index.is_trusted):
+ raise UntrustedError(
+ "Could not fetch %s %s source package: "
+ "Source %r is not trusted"
+ % (self.package.name, self.version, src.index.describe)
+ )
+ for fil in src.files:
+ base = os.path.basename(fil.path)
+ destfile = os.path.join(destdir, base)
+ if fil.type == "dsc":
+ dsc = destfile
+ if _file_is_same(destfile, fil.size, fil.hashes):
+ logging.debug("Ignoring already existing file: %s" % destfile)
+ continue
+
+ if not (allow_unauthenticated or fil.hashes.usable):
+ raise UntrustedError(
+ "The item %r could not be fetched: "
+ "No trusted hash found." % destfile
+ )
+ files.append(
+ apt_pkg.AcquireFile(
+ acq,
+ src.index.archive_uri(fil.path),
+ fil.hashes,
+ fil.size,
+ base,
+ destfile=destfile,
+ )
+ )
+ acq.run()
+
+ if dsc is None:
+ raise ValueError("No source for %r" % self)
+
+ for item in acq.items:
+ if item.status != item.STAT_DONE:
+ raise FetchError(
+ "The item %r could not be fetched: %s"
+ % (item.destfile, item.error_text)
+ )
+
+ if unpack:
+ outdir = src.package + "-" + apt_pkg.upstream_version(src.version)
+ outdir = os.path.join(destdir, outdir)
+ subprocess.check_call(["dpkg-source", "-x", dsc, outdir])
+ return os.path.abspath(outdir)
+ else:
+ return os.path.abspath(dsc)
+
+
+class VersionList(Sequence[Version]):
+ """Provide a mapping & sequence interface to all versions of a package.
+
+ This class can be used like a dictionary, where version strings are the
+ keys. It can also be used as a sequence, where integers are the keys.
+
+ You can also convert this to a dictionary or a list, using the usual way
+ of dict(version_list) or list(version_list). This is useful if you need
+ to access the version objects multiple times, because they do not have to
+ be recreated this way.
+
+ Examples ('package.versions' being a version list):
+ '0.7.92' in package.versions # Check whether 0.7.92 is a valid version.
+ package.versions[0] # Return first version or raise IndexError
+ package.versions[0:2] # Return a new VersionList for objects 0-2
+ package.versions['0.7.92'] # Return version 0.7.92 or raise KeyError
+ package.versions.keys() # All keys, as strings.
+ max(package.versions)
+ """
+
+ def __init__(self, package: Package, slice_: slice | None = None) -> None:
+ self._package = package # apt.package.Package()
+ self._versions = package._pkg.version_list # [apt_pkg.Version(), ...]
+ if slice_:
+ self._versions = self._versions[slice_]
+
+ def __getitem__(self, item: int | slice | str) -> Any:
+ # FIXME: Should not be returning Any, should have overloads; but
+ # pyflakes complains
+ if isinstance(item, slice):
+ return self.__class__(self._package, item)
+ try:
+ # Sequence interface, item is an integer
+ return Version(self._package, self._versions[item]) # type: ignore
+ except TypeError:
+ # Dictionary interface item is a string.
+ for ver in self._versions:
+ if ver.ver_str == item:
+ return Version(self._package, ver)
+ raise KeyError("Version: %r not found." % (item))
+
+ def __str__(self) -> str:
+ return "[%s]" % (", ".join(str(ver) for ver in self))
+
+ def __repr__(self) -> str:
+ return "<VersionList: %r>" % self.keys()
+
+ def __iter__(self) -> Iterator[Version]:
+ """Return an iterator over all value objects."""
+ return (Version(self._package, ver) for ver in self._versions)
+
+ def __contains__(self, item: object) -> bool:
+ if isinstance(item, Version): # Sequence interface
+ item = item.version
+ # Dictionary interface.
+ for ver in self._versions:
+ if ver.ver_str == item:
+ return True
+ return False
+
+ def __eq__(self, other: Any) -> bool:
+ return list(self) == list(other)
+
+ def __len__(self) -> int:
+ return len(self._versions)
+
+ # Mapping interface
+
+ def keys(self) -> list[str]:
+ """Return a list of all versions, as strings."""
+ return [ver.ver_str for ver in self._versions]
+
+ def get(self, key: str, default: Version | None = None) -> Version | None:
+ """Return the key or the default."""
+ try:
+ return self[key] # type: ignore # FIXME: should be deterined automatically # noqa
+ except LookupError:
+ return default
+
+
+class Package:
+ """Representation of a package in a cache.
+
+ This class provides methods and properties for working with a package. It
+ lets you mark the package for installation, check if it is installed, and
+ much more.
+ """
+
+ def __init__(self, pcache: apt.Cache, pkgiter: apt_pkg.Package) -> None:
+ """Init the Package object"""
+ self._pkg = pkgiter
+ self._pcache = pcache # python cache in cache.py
+ self._changelog = "" # Cached changelog
+
+ def __str__(self) -> str:
+ return self.name
+
+ def __repr__(self) -> str:
+ return "<Package: name:{!r} architecture={!r} id:{!r}>".format(
+ self._pkg.name,
+ self._pkg.architecture,
+ self._pkg.id,
+ )
+
+ def __lt__(self, other: Package) -> bool:
+ return self.name < other.name
+
+ @property
+ def candidate(self) -> Version | None:
+ """Return the candidate version of the package.
+
+ This property is writeable to allow you to set the candidate version
+ of the package. Just assign a Version() object, and it will be set as
+ the candidate version.
+ """
+ cand = self._pcache._depcache.get_candidate_ver(self._pkg)
+ if cand is not None:
+ return Version(self, cand)
+ return None
+
+ @candidate.setter
+ def candidate(self, version: Version) -> None:
+ """Set the candidate version of the package."""
+ self._pcache.cache_pre_change()
+ self._pcache._depcache.set_candidate_ver(self._pkg, version._cand)
+ self._pcache.cache_post_change()
+
+ @property
+ def installed(self) -> Version | None:
+ """Return the currently installed version of the package.
+
+ .. versionadded:: 0.7.9
+ """
+ if self._pkg.current_ver is not None:
+ return Version(self, self._pkg.current_ver)
+ return None
+
+ @property
+ def name(self) -> str:
+ """Return the name of the package, possibly including architecture.
+
+ If the package is not part of the system's preferred architecture,
+ return the same as :attr:`fullname`, otherwise return the same
+ as :attr:`shortname`
+
+ .. versionchanged:: 0.7.100.3
+
+ As part of multi-arch, this field now may include architecture
+ information.
+ """
+ return self._pkg.get_fullname(True)
+
+ @property
+ def fullname(self) -> str:
+ """Return the name of the package, including architecture.
+
+ Note that as for :meth:`architecture`, this returns the
+ native architecture for Architecture: all packages.
+
+ .. versionadded:: 0.7.100.3"""
+ return self._pkg.get_fullname(False)
+
+ @property
+ def shortname(self) -> str:
+ """Return the name of the package, without architecture.
+
+ .. versionadded:: 0.7.100.3"""
+ return self._pkg.name
+
+ @property
+ def id(self) -> int:
+ """Return a uniq ID for the package.
+
+ This can be used eg. to store additional information about the pkg."""
+ return self._pkg.id
+
+ @property
+ def essential(self) -> bool:
+ """Return True if the package is an essential part of the system."""
+ return self._pkg.essential
+
+ def architecture(self) -> str:
+ """Return the Architecture of the package.
+
+ Note that for Architecture: all packages, this returns the
+ native architecture, as they are internally treated like native
+ packages. To get the concrete architecture, look at the
+ :attr:`Version.architecture` attribute.
+
+ .. versionchanged:: 0.7.100.3
+ This is now the package's architecture in the multi-arch sense,
+ previously it was the architecture of the candidate version
+ and deprecated.
+ """
+ return self._pkg.architecture
+
+ # depcache states
+
+ @property
+ def marked_install(self) -> bool:
+ """Return ``True`` if the package is marked for install."""
+ return self._pcache._depcache.marked_install(self._pkg)
+
+ @property
+ def marked_upgrade(self) -> bool:
+ """Return ``True`` if the package is marked for upgrade."""
+ return self._pcache._depcache.marked_upgrade(self._pkg)
+
+ @property
+ def marked_delete(self) -> bool:
+ """Return ``True`` if the package is marked for delete."""
+ return self._pcache._depcache.marked_delete(self._pkg)
+
+ @property
+ def marked_keep(self) -> bool:
+ """Return ``True`` if the package is marked for keep."""
+ return self._pcache._depcache.marked_keep(self._pkg)
+
+ @property
+ def marked_downgrade(self) -> bool:
+ """Package is marked for downgrade"""
+ return self._pcache._depcache.marked_downgrade(self._pkg)
+
+ @property
+ def marked_reinstall(self) -> bool:
+ """Return ``True`` if the package is marked for reinstall."""
+ return self._pcache._depcache.marked_reinstall(self._pkg)
+
+ @property
+ def is_installed(self) -> bool:
+ """Return ``True`` if the package is installed."""
+ return self._pkg.current_ver is not None
+
+ @property
+ def is_upgradable(self) -> bool:
+ """Return ``True`` if the package is upgradable."""
+ return self.is_installed and self._pcache._depcache.is_upgradable(self._pkg)
+
+ @property
+ def is_auto_removable(self) -> bool:
+ """Return ``True`` if the package is no longer required.
+
+ If the package has been installed automatically as a dependency of
+ another package, and if no packages depend on it anymore, the package
+ is no longer required.
+ """
+ return (
+ self.is_installed or self.marked_install
+ ) and self._pcache._depcache.is_garbage(self._pkg)
+
+ @property
+ def is_auto_installed(self) -> bool:
+ """Return whether the package is marked as automatically installed."""
+ return self._pcache._depcache.is_auto_installed(self._pkg)
+
+ @property
+ def phasing_applied(self) -> bool:
+ """Return ``True`` if the package update is being phased."""
+ return self._pcache._depcache.phasing_applied(self._pkg)
+
+ # sizes
+
+ @property
+ def installed_files(self) -> list[str]:
+ """Return a list of files installed by the package.
+
+ Return a list of unicode names of the files which have
+ been installed by this package
+ """
+ for name in self.name, self.fullname:
+ path = "/var/lib/dpkg/info/%s.list" % name
+ try:
+ with open(path, "rb") as file_list:
+ return file_list.read().decode("utf-8").strip().split("\n")
+ except OSError:
+ continue
+
+ return []
+
+ def get_changelog(
+ self, uri: str | None = None, cancel_lock: threading.Event | None = None
+ ) -> str:
+ """
+ Download the changelog of the package and return it as unicode
+ string.
+
+ The parameter *uri* refers to the uri of the changelog file. It may
+ contain multiple named variables which will be substitued. These
+ variables are (src_section, prefix, src_pkg, src_ver). An example is
+ the Ubuntu changelog::
+
+ "http://changelogs.ubuntu.com/changelogs/pool" \\
+ "/%(src_section)s/%(prefix)s/%(src_pkg)s" \\
+ "/%(src_pkg)s_%(src_ver)s/changelog"
+
+ The parameter *cancel_lock* refers to an instance of threading.Event,
+ which if set, prevents the download.
+ """
+ # Return a cached changelog if available
+ if self._changelog != "":
+ return self._changelog
+
+ if not self.candidate:
+ return _("The list of changes is not available")
+
+ if uri is None:
+ if self.candidate.origins[0].origin == "Debian":
+ uri = (
+ "http://packages.debian.org/changelogs/pool"
+ "/%(src_section)s/%(prefix)s/%(src_pkg)s"
+ "/%(src_pkg)s_%(src_ver)s/changelog"
+ )
+ elif self.candidate.origins[0].origin == "Ubuntu":
+ uri = (
+ "http://changelogs.ubuntu.com/changelogs/pool"
+ "/%(src_section)s/%(prefix)s/%(src_pkg)s"
+ "/%(src_pkg)s_%(src_ver)s/changelog"
+ )
+ else:
+ res = _("The list of changes is not available")
+ if isinstance(res, str):
+ return res
+ else:
+ return res.decode("utf-8")
+
+ # get the src package name
+ src_pkg = self.candidate.source_name
+
+ # assume "main" section
+ src_section = "main"
+ # use the section of the candidate as a starting point
+ section = self.candidate.section
+
+ # get the source version
+ src_ver = self.candidate.source_version
+
+ try:
+ # try to get the source version of the pkg, this differs
+ # for some (e.g. libnspr4 on ubuntu)
+ # this feature only works if the correct deb-src are in the
+ # sources.list otherwise we fall back to the binary version number
+ src_records = apt_pkg.SourceRecords()
+ except SystemError:
+ pass
+ else:
+ while src_records.lookup(src_pkg):
+ if not src_records.version:
+ continue
+ if self.candidate.source_version == src_records.version:
+ # Direct match, use it and do not do more lookups.
+ src_ver = src_records.version
+ section = src_records.section
+ break
+ if apt_pkg.version_compare(src_records.version, src_ver) > 0:
+ # The version is higher, it seems to match.
+ src_ver = src_records.version
+ section = src_records.section
+
+ section_split = section.split("/", 1)
+ if len(section_split) > 1:
+ src_section = section_split[0]
+ del section_split
+
+ # lib is handled special
+ prefix = src_pkg[0]
+ if src_pkg.startswith("lib"):
+ prefix = "lib" + src_pkg[3]
+
+ # stip epoch
+ src_ver_split = src_ver.split(":", 1)
+ if len(src_ver_split) > 1:
+ src_ver = "".join(src_ver_split[1:])
+ del src_ver_split
+
+ uri = uri % {
+ "src_section": src_section,
+ "prefix": prefix,
+ "src_pkg": src_pkg,
+ "src_ver": src_ver,
+ }
+
+ timeout = socket.getdefaulttimeout()
+
+ # FIXME: when python2.4 vanishes from the archive,
+ # merge this into a single try..finally block (pep 341)
+ try:
+ try:
+ # Set a timeout for the changelog download
+ socket.setdefaulttimeout(2)
+
+ # Check if the download was canceled
+ if cancel_lock and cancel_lock.is_set():
+ return ""
+ # FIXME: python3.2: Should be closed manually
+ changelog_file = urlopen(uri)
+ # do only get the lines that are new
+ changelog = ""
+ regexp = "^%s \\((.*)\\)(.*)$" % (re.escape(src_pkg))
+ while True:
+ # Check if the download was canceled
+ if cancel_lock and cancel_lock.is_set():
+ return ""
+ # Read changelog line by line
+ line_raw = changelog_file.readline()
+ if not line_raw:
+ break
+ # The changelog is encoded in utf-8, but since there isn't
+ # any http header, urllib2 seems to treat it as ascii
+ line = line_raw.decode("utf-8")
+
+ # print line.encode('utf-8')
+ match = re.match(regexp, line)
+ if match:
+ # strip epoch from installed version
+ # and from changelog too
+ installed = getattr(self.installed, "version", None)
+ if installed and ":" in installed:
+ installed = installed.split(":", 1)[1]
+ changelog_ver = match.group(1)
+ if changelog_ver and ":" in changelog_ver:
+ changelog_ver = changelog_ver.split(":", 1)[1]
+
+ if (
+ installed
+ and apt_pkg.version_compare(changelog_ver, installed) <= 0
+ ):
+ break
+ # EOF (shouldn't really happen)
+ changelog += line
+
+ # Print an error if we failed to extract a changelog
+ if len(changelog) == 0:
+ changelog = _("The list of changes is not available")
+ if not isinstance(changelog, str):
+ changelog = changelog.decode("utf-8")
+ self._changelog = changelog
+
+ except HTTPError:
+ if self.candidate.origins[0].origin == "Ubuntu":
+ res = _(
+ "The list of changes is not available yet.\n\n"
+ "Please use "
+ "http://launchpad.net/ubuntu/+source/%s/"
+ "%s/+changelog\n"
+ "until the changes become available or try again "
+ "later."
+ ) % (src_pkg, src_ver)
+ else:
+ res = _("The list of changes is not available")
+ if isinstance(res, str):
+ return res
+ else:
+ return res.decode("utf-8")
+ except (OSError, BadStatusLine):
+ res = _(
+ "Failed to download the list of changes. \nPlease "
+ "check your Internet connection."
+ )
+ if isinstance(res, str):
+ return res
+ else:
+ return res.decode("utf-8")
+ finally:
+ socket.setdefaulttimeout(timeout)
+ return self._changelog
+
+ @property
+ def versions(self) -> VersionList:
+ """Return a VersionList() object for all available versions.
+
+ .. versionadded:: 0.7.9
+ """
+ return VersionList(self)
+
+ @property
+ def is_inst_broken(self) -> bool:
+ """Return True if the to-be-installed package is broken."""
+ return self._pcache._depcache.is_inst_broken(self._pkg)
+
+ @property
+ def is_now_broken(self) -> bool:
+ """Return True if the installed package is broken."""
+ return self._pcache._depcache.is_now_broken(self._pkg)
+
+ @property
+ def has_config_files(self) -> bool:
+ """Checks whether the package is is the config-files state."""
+ return self._pkg.current_state == apt_pkg.CURSTATE_CONFIG_FILES
+
+ # depcache actions
+
+ def mark_keep(self) -> None:
+ """Mark a package for keep."""
+ self._pcache.cache_pre_change()
+ self._pcache._depcache.mark_keep(self._pkg)
+ self._pcache.cache_post_change()
+
+ def mark_delete(self, auto_fix: bool = True, purge: bool = False) -> None:
+ """Mark a package for deletion.
+
+ If *auto_fix* is ``True``, the resolver will be run, trying to fix
+ broken packages. This is the default.
+
+ If *purge* is ``True``, remove the configuration files of the package
+ as well. The default is to keep the configuration.
+ """
+ self._pcache.cache_pre_change()
+ self._pcache._depcache.mark_delete(self._pkg, purge)
+ # try to fix broken stuffsta
+ if auto_fix and self._pcache._depcache.broken_count > 0:
+ fix = apt_pkg.ProblemResolver(self._pcache._depcache)
+ fix.clear(self._pkg)
+ fix.protect(self._pkg)
+ fix.remove(self._pkg)
+ fix.resolve()
+ self._pcache.cache_post_change()
+
+ def mark_install(
+ self, auto_fix: bool = True, auto_inst: bool = True, from_user: bool = True
+ ) -> None:
+ """Mark a package for install.
+
+ If *autoFix* is ``True``, the resolver will be run, trying to fix
+ broken packages. This is the default.
+
+ If *autoInst* is ``True``, the dependencies of the packages will be
+ installed automatically. This is the default.
+
+ If *fromUser* is ``True``, this package will not be marked as
+ automatically installed. This is the default. Set it to False if you
+ want to be able to automatically remove the package at a later stage
+ when no other package depends on it.
+ """
+ self._pcache.cache_pre_change()
+ self._pcache._depcache.mark_install(self._pkg, auto_inst, from_user)
+ # try to fix broken stuff
+ if auto_fix and self._pcache._depcache.broken_count > 0:
+ fixer = apt_pkg.ProblemResolver(self._pcache._depcache)
+ fixer.clear(self._pkg)
+ fixer.protect(self._pkg)
+ fixer.resolve(True)
+ self._pcache.cache_post_change()
+
+ def mark_upgrade(self, from_user: bool = True) -> None:
+ """Mark a package for upgrade."""
+ if self.is_upgradable:
+ auto = self.is_auto_installed
+ self.mark_install(from_user=from_user)
+ self.mark_auto(auto)
+ else:
+ # FIXME: we may want to throw a exception here
+ sys.stderr.write(
+ ("MarkUpgrade() called on a non-upgradeable pkg: " "'%s'\n")
+ % self._pkg.name
+ )
+
+ def mark_auto(self, auto: bool = True) -> None:
+ """Mark a package as automatically installed.
+
+ Call this function to mark a package as automatically installed. If the
+ optional parameter *auto* is set to ``False``, the package will not be
+ marked as automatically installed anymore. The default is ``True``.
+ """
+ self._pcache._depcache.mark_auto(self._pkg, auto)
+
+ def commit(self, fprogress: AcquireProgress, iprogress: InstallProgress) -> None:
+ """Commit the changes.
+
+ The parameter *fprogress* refers to a apt_pkg.AcquireProgress() object,
+ like apt.progress.text.AcquireProgress().
+
+ The parameter *iprogress* refers to an InstallProgress() object, as
+ found in apt.progress.base.
+ """
+ self._pcache._depcache.commit(fprogress, iprogress)
+
+
+@no_type_check
+def _test():
+ """Self-test."""
+ print("Self-test for the Package modul")
+ import random
+
+ apt_pkg.init()
+ progress = apt.progress.text.OpProgress()
+ cache = apt.Cache(progress)
+ pkg = cache["apt-utils"]
+ print("Name: %s " % pkg.name)
+ print("ID: %s " % pkg.id)
+ print("Priority (Candidate): %s " % pkg.candidate.priority)
+ print("Priority (Installed): %s " % pkg.installed.priority)
+ print("Installed: %s " % pkg.installed.version)
+ print("Candidate: %s " % pkg.candidate.version)
+ print("CandidateDownloadable: %s" % pkg.candidate.downloadable)
+ print("CandidateOrigins: %s" % pkg.candidate.origins)
+ print("SourcePkg: %s " % pkg.candidate.source_name)
+ print("Section: %s " % pkg.section)
+ print("Summary: %s" % pkg.candidate.summary)
+ print("Description (formatted) :\n%s" % pkg.candidate.description)
+ print("Description (unformatted):\n%s" % pkg.candidate.raw_description)
+ print("InstalledSize: %s " % pkg.candidate.installed_size)
+ print("PackageSize: %s " % pkg.candidate.size)
+ print("Dependencies: %s" % pkg.installed.dependencies)
+ print("Recommends: %s" % pkg.installed.recommends)
+ for dep in pkg.candidate.dependencies:
+ print(
+ ",".join(
+ f"{o.name} ({o.version}) ({o.relation}) ({o.pre_depend})"
+ for o in dep.or_dependencies
+ )
+ )
+ print("arch: %s" % pkg.candidate.architecture)
+ print("homepage: %s" % pkg.candidate.homepage)
+ print("rec: ", pkg.candidate.record)
+
+ print(cache["2vcard"].get_changelog())
+ for i in True, False:
+ print("Running install on random upgradable pkgs with AutoFix: ", i)
+ for pkg in cache:
+ if pkg.is_upgradable:
+ if random.randint(0, 1) == 1:
+ pkg.mark_install(i)
+ print("Broken: %s " % cache._depcache.broken_count)
+ print("InstCount: %s " % cache._depcache.inst_count)
+
+ print()
+ # get a new cache
+ for i in True, False:
+ print("Randomly remove some packages with AutoFix: %s" % i)
+ cache = apt.Cache(progress)
+ for name in cache.keys():
+ if random.randint(0, 1) == 1:
+ try:
+ cache[name].mark_delete(i)
+ except SystemError:
+ print("Error trying to remove: %s " % name)
+ print("Broken: %s " % cache._depcache.broken_count)
+ print("DelCount: %s " % cache._depcache.del_count)
+
+
+# self-test
+if __name__ == "__main__":
+ _test()
diff --git a/apt/progress/__init__.py b/apt/progress/__init__.py
new file mode 100644
index 0000000..d1687d5
--- /dev/null
+++ b/apt/progress/__init__.py
@@ -0,0 +1,28 @@
+# apt/progress/__init__.py - Initialization file for apt.progress.
+#
+# Copyright (c) 2009 Julian Andres Klode <jak@debian.org>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+"""Progress reporting.
+
+This package provides progress reporting for the python-apt package. The module
+'base' provides classes with no output, and the module 'text' provides classes
+for terminals, etc.
+"""
+
+from collections.abc import Sequence
+
+__all__: Sequence[str] = []
diff --git a/apt/progress/base.py b/apt/progress/base.py
new file mode 100644
index 0000000..ede5e5c
--- /dev/null
+++ b/apt/progress/base.py
@@ -0,0 +1,332 @@
+# apt/progress/base.py - Base classes for progress reporting.
+#
+# Copyright (C) 2009 Julian Andres Klode <jak@debian.org>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+# pylint: disable-msg = R0201
+"""Base classes for progress reporting.
+
+Custom progress classes should inherit from these classes. They can also be
+used as dummy progress classes which simply do nothing.
+"""
+from __future__ import annotations
+
+import errno
+import fcntl
+import io
+import os
+import re
+import select
+import sys
+
+import apt_pkg
+
+__all__ = ["AcquireProgress", "CdromProgress", "InstallProgress", "OpProgress"]
+
+
+class AcquireProgress:
+ """Monitor object for downloads controlled by the Acquire class.
+
+ This is an mostly abstract class. You should subclass it and implement the
+ methods to get something useful.
+ """
+
+ current_bytes = current_cps = fetched_bytes = last_bytes = total_bytes = 0.0
+ current_items = elapsed_time = total_items = 0
+
+ def done(self, item: apt_pkg.AcquireItemDesc) -> None:
+ """Invoked when an item is successfully and completely fetched."""
+
+ def fail(self, item: apt_pkg.AcquireItemDesc) -> None:
+ """Invoked when an item could not be fetched."""
+
+ def fetch(self, item: apt_pkg.AcquireItemDesc) -> None:
+ """Invoked when some of the item's data is fetched."""
+
+ def ims_hit(self, item: apt_pkg.AcquireItemDesc) -> None:
+ """Invoked when an item is confirmed to be up-to-date.
+
+ Invoked when an item is confirmed to be up-to-date. For instance,
+ when an HTTP download is informed that the file on the server was
+ not modified.
+ """
+
+ def media_change(self, media: str, drive: str) -> bool:
+ """Prompt the user to change the inserted removable media.
+
+ The parameter 'media' decribes the name of the media type that
+ should be changed, whereas the parameter 'drive' should be the
+ identifying name of the drive whose media should be changed.
+
+ This method should not return until the user has confirmed to the user
+ interface that the media change is complete. It must return True if
+ the user confirms the media change, or False to cancel it.
+ """
+ return False
+
+ def pulse(self, owner: apt_pkg.Acquire) -> bool:
+ """Periodically invoked while the Acquire process is underway.
+
+ This method gets invoked while the Acquire progress given by the
+ parameter 'owner' is underway. It should display information about
+ the current state.
+
+ This function returns a boolean value indicating whether the
+ acquisition should be continued (True) or cancelled (False).
+ """
+ return True
+
+ def start(self) -> None:
+ """Invoked when the Acquire process starts running."""
+ # Reset all our values.
+ self.current_bytes = 0.0
+ self.current_cps = 0.0
+ self.current_items = 0
+ self.elapsed_time = 0
+ self.fetched_bytes = 0.0
+ self.last_bytes = 0.0
+ self.total_bytes = 0.0
+ self.total_items = 0
+
+ def stop(self) -> None:
+ """Invoked when the Acquire process stops running."""
+
+
+class CdromProgress:
+ """Base class for reporting the progress of adding a cdrom.
+
+ Can be used with apt_pkg.Cdrom to produce an utility like apt-cdrom. The
+ attribute 'total_steps' defines the total number of steps and can be used
+ in update() to display the current progress.
+ """
+
+ total_steps = 0
+
+ def ask_cdrom_name(self) -> str | None:
+ """Ask for the name of the cdrom.
+
+ If a name has been provided, return it. Otherwise, return None to
+ cancel the operation.
+ """
+
+ def change_cdrom(self) -> bool:
+ """Ask for the CD-ROM to be changed.
+
+ Return True once the cdrom has been changed or False to cancel the
+ operation.
+ """
+ return False
+
+ def update(self, text: str, current: int) -> None:
+ """Periodically invoked to update the interface.
+
+ The string 'text' defines the text which should be displayed. The
+ integer 'current' defines the number of completed steps.
+ """
+
+
+class InstallProgress:
+ """Class to report the progress of installing packages."""
+
+ child_pid, percent, select_timeout, status = 0, 0.0, 0.1, ""
+
+ def __init__(self) -> None:
+ (self.statusfd, self.writefd) = os.pipe()
+ # These will leak fds, but fixing this safely requires API changes.
+ self.write_stream: io.TextIOBase = os.fdopen(self.writefd, "w")
+ self.status_stream: io.TextIOBase = os.fdopen(self.statusfd, "r") # noqa
+ fcntl.fcntl(self.statusfd, fcntl.F_SETFL, os.O_NONBLOCK)
+
+ def start_update(self) -> None:
+ """(Abstract) Start update."""
+
+ def finish_update(self) -> None:
+ """(Abstract) Called when update has finished."""
+
+ def __enter__(self) -> InstallProgress:
+ return self
+
+ def __exit__(self, type: object, value: object, traceback: object) -> None:
+ self.write_stream.close()
+ self.status_stream.close()
+
+ def error(self, pkg: str, errormsg: str) -> None:
+ """(Abstract) Called when a error is detected during the install."""
+
+ def conffile(self, current: str, new: str) -> None:
+ """(Abstract) Called when a conffile question from dpkg is detected."""
+
+ def status_change(self, pkg: str, percent: float, status: str) -> None:
+ """(Abstract) Called when the APT status changed."""
+
+ def dpkg_status_change(self, pkg: str, status: str) -> None:
+ """(Abstract) Called when the dpkg status changed."""
+
+ def processing(self, pkg: str, stage: str) -> None:
+ """(Abstract) Sent just before a processing stage starts.
+
+ The parameter 'stage' is one of "upgrade", "install"
+ (both sent before unpacking), "configure", "trigproc", "remove",
+ "purge". This method is used for dpkg only.
+ """
+
+ def run(self, obj: apt_pkg.PackageManager | bytes | str) -> int:
+ """Install using the object 'obj'.
+
+ This functions runs install actions. The parameter 'obj' may either
+ be a PackageManager object in which case its do_install() method is
+ called or the path to a deb file.
+
+ If the object is a PackageManager, the functions returns the result
+ of calling its do_install() method. Otherwise, the function returns
+ the exit status of dpkg. In both cases, 0 means that there were no
+ problems.
+ """
+ pid = self.fork()
+ if pid == 0:
+ try:
+ # PEP-446 implemented in Python 3.4 made all descriptors
+ # CLOEXEC, but we need to be able to pass writefd to dpkg
+ # when we spawn it
+ os.set_inheritable(self.writefd, True)
+ except AttributeError: # if we don't have os.set_inheritable()
+ pass
+ # pm.do_install might raise a exception,
+ # when this happens, we need to catch
+ # it, otherwise os._exit() is not run
+ # and the execution continues in the
+ # parent code leading to very confusing bugs
+ try:
+ os._exit(obj.do_install(self.write_stream.fileno())) # type: ignore # noqa
+ except AttributeError:
+ os._exit(
+ os.spawnlp(
+ os.P_WAIT,
+ "dpkg",
+ "dpkg",
+ "--status-fd",
+ str(self.write_stream.fileno()),
+ "-i",
+ obj, # type: ignore # noqa
+ )
+ )
+ except Exception as e:
+ sys.stderr.write("%s\n" % e)
+ os._exit(apt_pkg.PackageManager.RESULT_FAILED)
+
+ self.child_pid = pid
+ res = self.wait_child()
+ return os.WEXITSTATUS(res)
+
+ def fork(self) -> int:
+ """Fork."""
+ return os.fork()
+
+ def update_interface(self) -> None:
+ """Update the interface."""
+ try:
+ line = self.status_stream.readline()
+ except OSError as err:
+ # resource temporarly unavailable is ignored
+ if err.errno != errno.EAGAIN and err.errno != errno.EWOULDBLOCK:
+ print(err.strerror)
+ return
+
+ pkgname = status = status_str = percent = base = ""
+
+ if line.startswith("pm"):
+ try:
+ (status, pkgname, percent, status_str) = line.split(":", 3)
+ except ValueError:
+ # silently ignore lines that can't be parsed
+ return
+ elif line.startswith("status"):
+ try:
+ (base, pkgname, status, status_str) = line.split(":", 3)
+ except ValueError:
+ (base, pkgname, status) = line.split(":", 2)
+ elif line.startswith("processing"):
+ (status, status_str, pkgname) = line.split(":", 2)
+ self.processing(pkgname.strip(), status_str.strip())
+
+ # Always strip the status message
+ pkgname = pkgname.strip()
+ status_str = status_str.strip()
+ status = status.strip()
+
+ if status == "pmerror" or status == "error":
+ self.error(pkgname, status_str)
+ elif status == "conffile-prompt" or status == "pmconffile":
+ match = re.match("\\s*'(.*)'\\s*'(.*)'.*", status_str)
+ if match:
+ self.conffile(match.group(1), match.group(2))
+ elif status == "pmstatus":
+ # FIXME: Float comparison
+ if float(percent) != self.percent or status_str != self.status:
+ self.status_change(pkgname, float(percent), status_str.strip())
+ self.percent = float(percent)
+ self.status = status_str.strip()
+ elif base == "status":
+ self.dpkg_status_change(pkgname, status)
+
+ def wait_child(self) -> int:
+ """Wait for child progress to exit.
+
+ This method is responsible for calling update_interface() from time to
+ time. It exits once the child has exited. The return values is the
+ full status returned from os.waitpid() (not only the return code).
+ """
+ (pid, res) = (0, 0)
+ while True:
+ try:
+ select.select([self.status_stream], [], [], self.select_timeout)
+ except OSError as error:
+ (errno_, _errstr) = error.args
+ if errno_ != errno.EINTR:
+ raise
+
+ self.update_interface()
+ try:
+ (pid, res) = os.waitpid(self.child_pid, os.WNOHANG)
+ if pid == self.child_pid:
+ break
+ except OSError as err:
+ if err.errno == errno.ECHILD:
+ break
+ if err.errno != errno.EINTR:
+ raise
+
+ return res
+
+
+class OpProgress:
+ """Monitor objects for operations.
+
+ Display the progress of operations such as opening the cache."""
+
+ major_change, op, percent, subop = False, "", 0.0, ""
+
+ def update(self, percent: float | None = None) -> None:
+ """Called periodically to update the user interface.
+
+ You may use the optional argument 'percent' to set the attribute
+ 'percent' in this call.
+ """
+ if percent is not None:
+ self.percent = percent
+
+ def done(self) -> None:
+ """Called once an operation has been completed."""
diff --git a/apt/progress/text.py b/apt/progress/text.py
new file mode 100644
index 0000000..ea1a176
--- /dev/null
+++ b/apt/progress/text.py
@@ -0,0 +1,294 @@
+# Copyright (c) 2009 Julian Andres Klode <jak@debian.org>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+"""Progress reporting for text interfaces."""
+import io
+import os
+import signal
+import sys
+import types
+from collections.abc import Callable
+
+import apt_pkg
+
+from apt.progress import base
+
+__all__ = ["AcquireProgress", "CdromProgress", "OpProgress"]
+
+
+def _(msg: str) -> str:
+ """Translate the message, also try apt if translation is missing."""
+ res = apt_pkg.gettext(msg)
+ if res == msg:
+ res = apt_pkg.gettext(msg, "apt")
+ return res
+
+
+class TextProgress:
+ """Internal Base class for text progress classes."""
+
+ def __init__(self, outfile: io.TextIOBase | None = None) -> None:
+ self._file = outfile or sys.stdout
+ self._width = 0
+
+ def _write(self, msg: str, newline: bool = True, maximize: bool = False) -> None:
+ """Write the message on the terminal, fill remaining space."""
+ self._file.write("\r")
+ self._file.write(msg)
+
+ # Fill remaining stuff with whitespace
+ if self._width > len(msg):
+ self._file.write((self._width - len(msg)) * " ")
+ elif maximize: # Needed for OpProgress.
+ self._width = max(self._width, len(msg))
+ if newline:
+ self._file.write("\n")
+ else:
+ # self._file.write("\r")
+ self._file.flush()
+
+
+class OpProgress(base.OpProgress, TextProgress):
+ """Operation progress reporting.
+
+ This closely resembles OpTextProgress in libapt-pkg.
+ """
+
+ def __init__(self, outfile: io.TextIOBase | None = None) -> None:
+ TextProgress.__init__(self, outfile)
+ base.OpProgress.__init__(self)
+ self.old_op = ""
+
+ def update(self, percent: float | None = None) -> None:
+ """Called periodically to update the user interface."""
+ base.OpProgress.update(self, percent)
+ if self.major_change and self.old_op:
+ self._write(self.old_op)
+ self._write("%s... %i%%\r" % (self.op, self.percent), False, True)
+ self.old_op = self.op
+
+ def done(self) -> None:
+ """Called once an operation has been completed."""
+ base.OpProgress.done(self)
+ if self.old_op:
+ self._write(_("%c%s... Done") % ("\r", self.old_op), True, True)
+ self.old_op = ""
+
+
+class AcquireProgress(base.AcquireProgress, TextProgress):
+ """AcquireProgress for the text interface."""
+
+ def __init__(self, outfile: io.TextIOBase | None = None) -> None:
+ TextProgress.__init__(self, outfile)
+ base.AcquireProgress.__init__(self)
+ self._signal: (
+ Callable[[int, types.FrameType | None], None] | int | signal.Handlers | None
+ ) = None # noqa
+ self._width = 80
+ self._id = 1
+
+ def start(self) -> None:
+ """Start an Acquire progress.
+
+ In this case, the function sets up a signal handler for SIGWINCH, i.e.
+ window resize signals. And it also sets id to 1.
+ """
+ base.AcquireProgress.start(self)
+ self._signal = signal.signal(signal.SIGWINCH, self._winch)
+ # Get the window size.
+ self._winch()
+ self._id = 1
+
+ def _winch(self, *dummy: object) -> None:
+ """Signal handler for window resize signals."""
+ if hasattr(self._file, "fileno") and os.isatty(self._file.fileno()):
+ import fcntl
+ import struct
+ import termios
+
+ buf = fcntl.ioctl(self._file, termios.TIOCGWINSZ, 8 * b" ") # noqa
+ dummy, col, dummy, dummy = struct.unpack("hhhh", buf)
+ self._width = col - 1 # 1 for the cursor
+
+ def ims_hit(self, item: apt_pkg.AcquireItemDesc) -> None:
+ """Called when an item is update (e.g. not modified on the server)."""
+ base.AcquireProgress.ims_hit(self, item)
+ line = _("Hit ") + item.description
+ if item.owner.filesize:
+ line += " [%sB]" % apt_pkg.size_to_str(item.owner.filesize)
+ self._write(line)
+
+ def fail(self, item: apt_pkg.AcquireItemDesc) -> None:
+ """Called when an item is failed."""
+ base.AcquireProgress.fail(self, item)
+ if item.owner.status == item.owner.STAT_DONE:
+ self._write(_("Ign ") + item.description)
+ else:
+ self._write(_("Err ") + item.description)
+ self._write(" %s" % item.owner.error_text)
+
+ def fetch(self, item: apt_pkg.AcquireItemDesc) -> None:
+ """Called when some of the item's data is fetched."""
+ base.AcquireProgress.fetch(self, item)
+ # It's complete already (e.g. Hit)
+ if item.owner.complete:
+ return
+ item.owner.id = self._id
+ self._id += 1
+ line = _("Get:") + f"{item.owner.id} {item.description}"
+ if item.owner.filesize:
+ line += " [%sB]" % apt_pkg.size_to_str(item.owner.filesize)
+
+ self._write(line)
+
+ def pulse(self, owner: apt_pkg.Acquire) -> bool:
+ """Periodically invoked while the Acquire process is underway.
+
+ Return False if the user asked to cancel the whole Acquire process."""
+ base.AcquireProgress.pulse(self, owner)
+ # only show progress on a tty to not clutter log files etc
+ if hasattr(self._file, "fileno") and not os.isatty(self._file.fileno()):
+ return True
+
+ # calculate progress
+ percent = ((self.current_bytes + self.current_items) * 100.0) / float(
+ self.total_bytes + self.total_items
+ )
+
+ shown = False
+ tval = "%i%%" % percent
+ end = ""
+ if self.current_cps:
+ eta = int(float(self.total_bytes - self.current_bytes) / self.current_cps)
+ end = " {}B/s {}".format(
+ apt_pkg.size_to_str(self.current_cps),
+ apt_pkg.time_to_str(eta),
+ )
+
+ for worker in owner.workers:
+ val = ""
+ if not worker.current_item:
+ if worker.status:
+ val = " [%s]" % worker.status
+ if len(tval) + len(val) + len(end) >= self._width:
+ break
+ tval += val
+ shown = True
+ continue
+ shown = True
+
+ if worker.current_item.owner.id:
+ val += " [%i %s" % (
+ worker.current_item.owner.id,
+ worker.current_item.shortdesc,
+ )
+ else:
+ val += " [%s" % worker.current_item.description
+ if worker.current_item.owner.active_subprocess:
+ val += " %s" % worker.current_item.owner.active_subprocess
+
+ val += " %sB" % apt_pkg.size_to_str(worker.current_size)
+
+ # Add the total size and percent
+ if worker.total_size and not worker.current_item.owner.complete:
+ val += "/%sB %i%%" % (
+ apt_pkg.size_to_str(worker.total_size),
+ worker.current_size * 100.0 / worker.total_size,
+ )
+
+ val += "]"
+
+ if len(tval) + len(val) + len(end) >= self._width:
+ # Display as many items as screen width
+ break
+ else:
+ tval += val
+
+ if not shown:
+ tval += _(" [Working]")
+
+ if self.current_cps:
+ tval += (self._width - len(end) - len(tval)) * " " + end
+
+ self._write(tval, False)
+ return True
+
+ def media_change(self, medium: str, drive: str) -> bool:
+ """Prompt the user to change the inserted removable media."""
+ base.AcquireProgress.media_change(self, medium, drive)
+ self._write(
+ _(
+ "Media change: please insert the disc labeled\n"
+ " '%s'\n"
+ "in the drive '%s' and press enter\n"
+ )
+ % (medium, drive)
+ )
+ return input() not in ("c", "C")
+
+ def stop(self) -> None:
+ """Invoked when the Acquire process stops running."""
+ base.AcquireProgress.stop(self)
+ # Trick for getting a translation from apt
+ self._write(
+ (
+ _("Fetched %sB in %s (%sB/s)\n")
+ % (
+ apt_pkg.size_to_str(self.fetched_bytes),
+ apt_pkg.time_to_str(self.elapsed_time),
+ apt_pkg.size_to_str(self.current_cps),
+ )
+ ).rstrip("\n")
+ )
+
+ # Delete the signal again.
+ import signal
+
+ signal.signal(signal.SIGWINCH, self._signal)
+
+
+class CdromProgress(base.CdromProgress, TextProgress):
+ """Text CD-ROM progress."""
+
+ def ask_cdrom_name(self) -> str | None:
+ """Ask the user to provide a name for the disc."""
+ base.CdromProgress.ask_cdrom_name(self)
+ self._write(
+ _(
+ "Please provide a name for this medium, such as "
+ "'Debian 2.1r1 Disk 1'"
+ ),
+ False,
+ )
+ try:
+ return str(input(":"))
+ except KeyboardInterrupt:
+ return None
+
+ def update(self, text: str, current: int) -> None:
+ """Set the current progress."""
+ base.CdromProgress.update(self, text, current)
+ if text:
+ self._write(text, False)
+
+ def change_cdrom(self) -> bool:
+ """Ask the user to change the CD-ROM."""
+ base.CdromProgress.change_cdrom(self)
+ self._write(_("Please insert an installation medium and press enter"), False)
+ try:
+ return bool(input() == "")
+ except KeyboardInterrupt:
+ return False
diff --git a/apt/py.typed b/apt/py.typed
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/apt/py.typed
diff --git a/apt/utils.py b/apt/utils.py
new file mode 100644
index 0000000..5b1fd46
--- /dev/null
+++ b/apt/utils.py
@@ -0,0 +1,100 @@
+# Copyright (C) 2009 Canonical
+#
+# Authors:
+# Michael Vogt
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+import datetime
+import os
+
+import apt_pkg
+
+import apt
+
+
+def get_maintenance_end_date(
+ release_date: datetime.datetime, m_months: int
+) -> tuple[int, int]:
+ """
+ get the (year, month) tuple when the maintenance for the distribution
+ ends. Needs the data of the release and the number of months that
+ its is supported as input
+ """
+ # calc end date
+ years = m_months // 12
+ months = m_months % 12
+ support_end_year = release_date.year + years + (release_date.month + months) // 12
+ support_end_month = (release_date.month + months) % 12
+ # special case: this happens when e.g. doing 2010-06 + 18 months
+ if support_end_month == 0:
+ support_end_month = 12
+ support_end_year -= 1
+ return (support_end_year, support_end_month)
+
+
+def get_release_date_from_release_file(path: str) -> int | None:
+ """
+ return the release date as time_t for the given release file
+ """
+ if not path or not os.path.exists(path):
+ return None
+
+ with os.fdopen(apt_pkg.open_maybe_clear_signed_file(path)) as data:
+ tag = apt_pkg.TagFile(data)
+ section = next(tag)
+ if "Date" not in section:
+ return None
+ date = section["Date"]
+ return apt_pkg.str_to_time(date)
+
+
+def get_release_filename_for_pkg(
+ cache: apt.Cache, pkgname: str, label: str, release: str
+) -> str | None:
+ "get the release file that provides this pkg"
+ if pkgname not in cache:
+ return None
+ pkg = cache[pkgname]
+ ver = None
+ # look for the version that comes from the repos with
+ # the given label and origin
+ for aver in pkg._pkg.version_list:
+ if aver is None or aver.file_list is None:
+ continue
+ for ver_file, _index in aver.file_list:
+ # print verFile
+ if (
+ ver_file.origin == label
+ and ver_file.label == label
+ and ver_file.archive == release
+ ):
+ ver = aver
+ if not ver:
+ return None
+ indexfile = cache._list.find_index(ver.file_list[0][0])
+ for metaindex in cache._list.list:
+ for m in metaindex.index_files:
+ if indexfile and indexfile.describe == m.describe and indexfile.is_trusted:
+ dirname = apt_pkg.config.find_dir("Dir::State::lists")
+ for relfile in ["InRelease", "Release"]:
+ name = apt_pkg.uri_to_filename(
+ metaindex.uri
+ ) + "dists_{}_{}".format(
+ metaindex.dist,
+ relfile,
+ )
+ if os.path.exists(dirname + name):
+ return dirname + name
+ return None
diff --git a/aptsources/__init__.py b/aptsources/__init__.py
new file mode 100644
index 0000000..2ccf4fc
--- /dev/null
+++ b/aptsources/__init__.py
@@ -0,0 +1,6 @@
+import apt_pkg
+
+# init the package system, but do not re-initialize config
+if "APT" not in apt_pkg.config:
+ apt_pkg.init_config()
+apt_pkg.init_system()
diff --git a/aptsources/_deb822.py b/aptsources/_deb822.py
new file mode 100644
index 0000000..d3b3a7c
--- /dev/null
+++ b/aptsources/_deb822.py
@@ -0,0 +1,144 @@
+#!/usr/bin/python3
+#
+# Copyright (C) Canonical Ltd
+#
+# SPDX-License-Identifier: GPL-2.0+
+
+"""deb822 parser with support for comment headers and footers."""
+
+import collections
+import io
+import typing
+
+import apt_pkg
+
+T = typing.TypeVar("T")
+
+
+class Section:
+ """A single deb822 section, possibly with comments.
+
+ This represents a single deb822 section.
+ """
+
+ tags: collections.OrderedDict[str, str]
+ _case_mapping: dict[str, str]
+ header: str
+ footer: str
+
+ def __init__(self, section: typing.Union[str, "Section"]):
+ if isinstance(section, Section):
+ self.tags = collections.OrderedDict(section.tags)
+ self._case_mapping = {k.casefold(): k for k in self.tags}
+ self.header = section.header
+ self.footer = section.footer
+ return
+
+ comments = ["", ""]
+ in_section = False
+ trimmed_section = ""
+
+ for line in section.split("\n"):
+ if line.startswith("#"):
+ # remove the leading #
+ line = line[1:]
+ comments[in_section] += line + "\n"
+ continue
+
+ in_section = True
+ trimmed_section += line + "\n"
+
+ self.tags = collections.OrderedDict(apt_pkg.TagSection(trimmed_section))
+ self._case_mapping = {k.casefold(): k for k in self.tags}
+ self.header, self.footer = comments
+
+ def __getitem__(self, key: str) -> str:
+ """Get the value of a field."""
+ return self.tags[self._case_mapping.get(key.casefold(), key)]
+
+ def __delitem__(self, key: str) -> None:
+ """Delete a field"""
+ del self.tags[self._case_mapping.get(key.casefold(), key)]
+
+ def __setitem__(self, key: str, val: str) -> None:
+ """Set the value of a field."""
+ if key.casefold() not in self._case_mapping:
+ self._case_mapping[key.casefold()] = key
+ self.tags[self._case_mapping[key.casefold()]] = val
+
+ def __bool__(self) -> bool:
+ return bool(self.tags)
+
+ @typing.overload
+ def get(self, key: str) -> str | None:
+ ...
+
+ @typing.overload
+ def get(self, key: str, default: T) -> T | str:
+ ...
+
+ def get(self, key: str, default: T | None = None) -> T | None | str:
+ try:
+ return self[key]
+ except KeyError:
+ return default
+
+ @staticmethod
+ def __comment_lines(content: str) -> str:
+ return (
+ "\n".join("#" + line for line in content.splitlines()) + "\n"
+ if content
+ else ""
+ )
+
+ def __str__(self) -> str:
+ """Canonical string rendering of this section."""
+ return (
+ self.__comment_lines(self.header)
+ + "".join(f"{k}: {v}\n" for k, v in self.tags.items())
+ + self.__comment_lines(self.footer)
+ )
+
+
+class File:
+ """
+ Parse a given file object into a list of Section objects.
+ """
+
+ def __init__(self, fobj: io.TextIOBase):
+ self.sections = []
+ section = ""
+ for line in fobj:
+ if not line.isspace():
+ # A line is part of the section if it has non-whitespace characters
+ section += line
+ elif section:
+ # Our line is just whitespace and we have gathered section content, so let's write out the section
+ self.sections.append(Section(section))
+ section = ""
+
+ # The final section may not be terminated by an empty line
+ if section:
+ self.sections.append(Section(section))
+
+ def __iter__(self) -> typing.Iterator[Section]:
+ return iter(self.sections)
+
+ def __str__(self) -> str:
+ return "\n".join(str(s) for s in self.sections)
+
+
+if __name__ == "__main__":
+ st = """# Header
+# More header
+K1: V1
+# Inline
+K2: V2
+ # not a comment
+# Footer
+# More footer
+"""
+
+ s = Section(st)
+
+ print(s)
diff --git a/aptsources/distinfo.py b/aptsources/distinfo.py
new file mode 100644
index 0000000..bd30f81
--- /dev/null
+++ b/aptsources/distinfo.py
@@ -0,0 +1,415 @@
+# distinfo.py - provide meta information for distro repositories
+#
+# Copyright (c) 2005 Gustavo Noronha Silva <kov@debian.org>
+# Copyright (c) 2006-2007 Sebastian Heinlein <glatzor@ubuntu.com>
+#
+# Authors: Gustavo Noronha Silva <kov@debian.org>
+# Sebastian Heinlein <glatzor@ubuntu.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
+import csv
+import errno
+import logging
+import os
+import re
+from collections.abc import Iterator
+from subprocess import PIPE, Popen
+from typing import cast
+
+import apt_pkg
+from apt_pkg import gettext as _
+
+
+def _expand_template(template: str, csv_path: str) -> Iterator[str]:
+ """Expand the given template.
+
+ A template file consists of a header, followed by paragraphs
+ of templated suites, followed by a footer. A templated suite
+ is any paragraph where the Suite field contains {.
+
+ This function expands all templated suites using the information
+ found in the CSV file supplied by distro-info-data.
+
+ It yields lines of template info.
+ """
+
+ known_suites = set()
+
+ # Copy out any header, and gather all hardcoded suites
+ with apt_pkg.TagFile(template) as tmpl:
+ for section in tmpl:
+ if "X-Exclude-Suites" in section:
+ known_suites.update(section["X-Exclude-Suites"].split(", "))
+ if "Suite" in section:
+ if "{" in section["Suite"]:
+ break
+
+ known_suites.add(section["Suite"])
+
+ yield from str(section).splitlines()
+ else:
+ # We did not break, so we did copy all of them
+ return
+
+ for section in tmpl:
+ if "Suite" in section:
+ known_suites.add(section["Suite"])
+
+ with open(csv_path) as csv_object:
+ releases = reversed(list(csv.DictReader(csv_object)))
+
+ # Perform template substitution on the middle of the list
+ for rel in releases:
+ if rel["series"] in known_suites:
+ continue
+ yield ""
+ rel["version"] = rel["version"].replace(" LTS", "")
+ with apt_pkg.TagFile(template) as tmpl:
+ for section in tmpl:
+ # Only work on template sections, this skips head and tails
+ if "Suite" not in section or "{" not in section["Suite"]:
+ continue
+ if "X-Version" in section:
+ # Version requirements. Maybe should be made nicer
+ ver = rel["version"]
+ if any(
+ (
+ field.startswith("le")
+ and apt_pkg.version_compare(field[3:], ver) < 0
+ )
+ or (
+ field.startswith("ge")
+ and apt_pkg.version_compare(field[3:], ver) > 0
+ )
+ for field in section["X-Version"].split(", ")
+ ):
+ continue
+
+ for line in str(section).format(**rel).splitlines():
+ if line.startswith("X-Version"):
+ continue
+ yield line
+
+ # Copy out remaining suites
+ with apt_pkg.TagFile(template) as tmpl:
+ # Skip the head again, we don't want to copy it twice
+ for section in tmpl:
+ if "Suite" in section and "{" in section["Suite"]:
+ break
+
+ for section in tmpl:
+ # Ignore any template parts and copy the rest out,
+ # this is the inverse of the template substitution loop
+ if "Suite" in section and "{" in section["Suite"]:
+ continue
+
+ yield from str(section).splitlines()
+
+
+class Template:
+ def __init__(self) -> None:
+ self.name: str | None = None
+ self.child = False
+ self.parents: list[Template] = [] # ref to parent template(s)
+ self.match_name: str | None = None
+ self.description: str | None = None
+ self.base_uri: str | None = None
+ self.type: str | None = None
+ self.components: list[Component] = []
+ self.children: list[Template] = []
+ self.match_uri: str | None = None
+ self.mirror_set: dict[str, Mirror] = {}
+ self.distribution: str | None = None
+ self.available = True
+ self.official = True
+
+ def has_component(self, comp: str) -> bool:
+ """Check if the distribution provides the given component"""
+ return comp in (c.name for c in self.components)
+
+ def is_mirror(self, url: str) -> bool:
+ """Check if a given url of a repository is a valid mirror"""
+ proto, hostname, dir = split_url(url)
+ if hostname in self.mirror_set:
+ return self.mirror_set[hostname].has_repository(proto, dir)
+ else:
+ return False
+
+
+class Component:
+ def __init__(
+ self,
+ name: str,
+ desc: str | None = None,
+ long_desc: str | None = None,
+ parent_component: str | None = None,
+ ):
+ self.name = name
+ self.description = desc
+ self.description_long = long_desc
+ self.parent_component = parent_component
+
+ def get_parent_component(self) -> str | None:
+ return self.parent_component
+
+ def set_parent_component(self, parent: str) -> None:
+ self.parent_component = parent
+
+ def get_description(self) -> str | None:
+ if self.description_long is not None:
+ return self.description_long
+ elif self.description is not None:
+ return self.description
+ else:
+ return None
+
+ def set_description(self, desc: str) -> None:
+ self.description = desc
+
+ def set_description_long(self, desc: str) -> None:
+ self.description_long = desc
+
+ def get_description_long(self) -> str | None:
+ return self.description_long
+
+
+class Mirror:
+ """Storage for mirror related information"""
+
+ def __init__(
+ self, proto: str, hostname: str, dir: str, location: str | None = None
+ ):
+ self.hostname = hostname
+ self.repositories: list[Repository] = []
+ self.add_repository(proto, dir)
+ self.location = location
+
+ def add_repository(self, proto: str, dir: str) -> None:
+ self.repositories.append(Repository(proto, dir))
+
+ def get_repositories_for_proto(self, proto: str) -> list["Repository"]:
+ return [r for r in self.repositories if r.proto == proto]
+
+ def has_repository(self, proto: str, dir: str) -> bool:
+ if dir is None:
+ return False
+ for r in self.repositories:
+ if r.proto == proto and dir in r.dir:
+ return True
+ return False
+
+ def get_repo_urls(self) -> list[str]:
+ return [r.get_url(self.hostname) for r in self.repositories]
+
+ def get_location(self) -> str | None:
+ return self.location
+
+ def set_location(self, location: str) -> None:
+ self.location = location
+
+
+class Repository:
+ def __init__(self, proto: str, dir: str) -> None:
+ self.proto = proto
+ self.dir = dir
+
+ def get_info(self) -> tuple[str, str]:
+ return self.proto, self.dir
+
+ def get_url(self, hostname: str) -> str:
+ return f"{self.proto}://{hostname}/{self.dir}"
+
+
+def split_url(url: str) -> list[str]:
+ """split a given URL into the protocoll, the hostname and the dir part"""
+ split = re.split(":*\\/+", url, maxsplit=2)
+ while len(split) < 3:
+ split.append(None)
+ return split
+
+
+class DistInfo:
+ def __init__(
+ self,
+ dist: str | None = None,
+ base_dir: str = "/usr/share/python-apt/templates",
+ ):
+ self.metarelease_uri = ""
+ self.templates: list[Template] = []
+ self.arch = apt_pkg.config.find("APT::Architecture")
+
+ location = None
+ match_loc = re.compile(r"^#LOC:(.+)$")
+ match_mirror_line = re.compile(
+ r"^(#LOC:.+)|(((http)|(ftp)|(rsync)|(file)|(mirror)|(https))://"
+ r"[A-Za-z0-9/\.:\-_@]+)$"
+ )
+ # match_mirror_line = re.compile(r".+")
+
+ if not dist:
+ try:
+ dist = (
+ Popen(
+ ["lsb_release", "-i", "-s"],
+ universal_newlines=True,
+ stdout=PIPE,
+ )
+ .communicate()[0]
+ .strip()
+ )
+ except OSError as exc:
+ if exc.errno != errno.ENOENT:
+ logging.warning("lsb_release failed, using defaults: %s" % exc)
+ dist = "Debian"
+
+ self.dist = dist
+
+ map_mirror_sets = {}
+
+ dist_fname = f"{base_dir}/{dist}.info"
+ csv_fname = f"/usr/share/distro-info/{dist.lower()}.csv"
+
+ # FIXME: Logic doesn't work with types.
+ template = cast(Template, None)
+ component = cast(Component, None)
+ for line in _expand_template(dist_fname, csv_fname):
+ tokens = line.split(":", 1)
+ if len(tokens) < 2:
+ continue
+ field = tokens[0].strip()
+ value = tokens[1].strip()
+ if field == "ChangelogURI":
+ self.changelogs_uri = _(value)
+ elif field == "MetaReleaseURI":
+ self.metarelease_uri = value
+ elif field == "Suite":
+ self.finish_template(template, component)
+ component = cast(Component, None) # FIXME
+ template = Template()
+ template.name = value
+ template.distribution = dist
+ template.match_name = "^%s$" % value
+ elif field == "MatchName":
+ template.match_name = value
+ elif field == "ParentSuite":
+ template.child = True
+ for nanny in self.templates:
+ # look for parent and add back ref to it
+ if nanny.name == value:
+ template.parents.append(nanny)
+ nanny.children.append(template)
+ elif field == "Available":
+ template.available = apt_pkg.string_to_bool(value)
+ elif field == "Official":
+ template.official = apt_pkg.string_to_bool(value)
+ elif field == "RepositoryType":
+ template.type = value
+ elif field == "BaseURI" and not template.base_uri:
+ template.base_uri = value
+ elif field == "BaseURI-%s" % self.arch:
+ template.base_uri = value
+ elif field == "MatchURI" and not template.match_uri:
+ template.match_uri = value
+ elif field == "MatchURI-%s" % self.arch:
+ template.match_uri = value
+ elif field == "MirrorsFile" or field == "MirrorsFile-%s" % self.arch:
+ # Make the path absolute.
+ value = (
+ os.path.isabs(value)
+ and value
+ or os.path.abspath(os.path.join(base_dir, value))
+ )
+ if value not in map_mirror_sets:
+ mirror_set: dict[str, Mirror] = {}
+ try:
+ with open(value) as value_f:
+ mirror_data = list(
+ filter(
+ match_mirror_line.match,
+ [x.strip() for x in value_f],
+ )
+ )
+ except Exception:
+ print(f"WARNING: Failed to read mirror file {value}")
+ mirror_data = []
+ for line in mirror_data:
+ if line.startswith("#LOC:"):
+ location = match_loc.sub(r"\1", line)
+ continue
+ (proto, hostname, dir) = split_url(line)
+ if hostname in mirror_set:
+ mirror_set[hostname].add_repository(proto, dir)
+ else:
+ mirror_set[hostname] = Mirror(
+ proto, hostname, dir, location
+ )
+ map_mirror_sets[value] = mirror_set
+ template.mirror_set = map_mirror_sets[value]
+ elif field == "Description":
+ template.description = _(value)
+ elif field == "Component":
+ if component and not template.has_component(component.name):
+ template.components.append(component)
+ component = Component(value)
+ elif field == "CompDescription":
+ component.set_description(_(value))
+ elif field == "CompDescriptionLong":
+ component.set_description_long(_(value))
+ elif field == "ParentComponent":
+ component.set_parent_component(value)
+ self.finish_template(template, component)
+ template = cast(Template, None)
+ component = cast(Component, None)
+
+ def finish_template(self, template: Template, component: Component | None) -> None:
+ "finish the current tempalte"
+ if not template:
+ return
+ # reuse some properties of the parent template
+ if template.match_uri is None and template.child:
+ for t in template.parents:
+ if t.match_uri:
+ template.match_uri = t.match_uri
+ break
+ if template.mirror_set == {} and template.child:
+ for t in template.parents:
+ if t.match_uri:
+ template.mirror_set = t.mirror_set
+ break
+ if component and not template.has_component(component.name):
+ template.components.append(component)
+ component = None
+ # the official attribute is inherited
+ for t in template.parents:
+ template.official = t.official
+ self.templates.append(template)
+
+
+if __name__ == "__main__":
+ d = DistInfo("Ubuntu", "/usr/share/python-apt/templates")
+ logging.info(d.changelogs_uri)
+ for template in d.templates:
+ logging.info("\nSuite: %s" % template.name)
+ logging.info("Desc: %s" % template.description)
+ logging.info("BaseURI: %s" % template.base_uri)
+ logging.info("MatchURI: %s" % template.match_uri)
+ if template.mirror_set != {}:
+ logging.info("Mirrors: %s" % list(template.mirror_set.keys()))
+ for comp in template.components:
+ logging.info(f" {comp.name} -{comp.description} -{comp.description_long}")
+ for child in template.children:
+ logging.info(" %s" % child.description)
diff --git a/aptsources/distro.py b/aptsources/distro.py
new file mode 100644
index 0000000..546d0e7
--- /dev/null
+++ b/aptsources/distro.py
@@ -0,0 +1,648 @@
+# distro.py - Provide a distro abstraction of the sources.list
+#
+# Copyright (c) 2004-2009 Canonical Ltd.
+# Copyright (c) 2006-2007 Sebastian Heinlein
+# Copyright (c) 2016 Harald Sitter
+#
+# Authors: Sebastian Heinlein <glatzor@ubuntu.com>
+# Michael Vogt <mvo@debian.org>
+# Harald Sitter <sitter@kde.org>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
+import gettext
+import logging
+import os
+import re
+import shlex
+import warnings
+from xml.etree.ElementTree import ElementTree
+
+from apt_pkg import gettext as _
+
+
+class NoDistroTemplateException(Exception):
+ pass
+
+
+class Distribution:
+ def __init__(self, id, codename, description, release, is_like=[]):
+ """Container for distribution specific informations"""
+ # LSB information
+ self.id = id
+ self.codename = codename
+ self.description = description
+ self.release = release
+ self.is_like = is_like
+
+ self.binary_type = "deb"
+ self.source_type = "deb-src"
+
+ def get_sources(self, sourceslist):
+ """
+ Find the corresponding template, main and child sources
+ for the distribution
+ """
+
+ self.sourceslist = sourceslist
+ # corresponding sources
+ self.source_template = None
+ self.child_sources = []
+ self.main_sources = []
+ self.disabled_sources = []
+ self.cdrom_sources = []
+ self.download_comps = []
+ self.enabled_comps = []
+ self.cdrom_comps = []
+ self.used_media = []
+ self.get_source_code = False
+ self.source_code_sources = []
+
+ # location of the sources
+ self.default_server = ""
+ self.main_server = ""
+ self.nearest_server = ""
+ self.used_servers = []
+
+ # find the distro template
+ for template in self.sourceslist.matcher.templates:
+ if self.is_codename(template.name) and template.distribution == self.id:
+ # print "yeah! found a template for %s" % self.description
+ # print template.description, template.base_uri, \
+ # template.components
+ self.source_template = template
+ break
+ if self.source_template is None:
+ raise NoDistroTemplateException(
+ "Error: could not find a distribution template for %s/%s"
+ % (self.id, self.codename)
+ )
+
+ # find main and child sources
+ media = []
+ comps = []
+ cdrom_comps = []
+ enabled_comps = []
+ # source_code = []
+ for source in self.sourceslist.exploded_list():
+ if (
+ not source.invalid
+ and self.is_codename(source.dist)
+ and source.template
+ and source.template.official
+ and self.is_codename(source.template.name)
+ ):
+ # print "yeah! found a distro repo: %s" % source.line
+ # cdroms need do be handled differently
+ if source.uri.startswith("cdrom:") and not source.disabled:
+ self.cdrom_sources.append(source)
+ cdrom_comps.extend(source.comps)
+ elif source.uri.startswith("cdrom:") and source.disabled:
+ self.cdrom_sources.append(source)
+ elif source.type == self.binary_type and not source.disabled:
+ self.main_sources.append(source)
+ comps.extend(source.comps)
+ media.append(source.uri)
+ elif source.type == self.binary_type and source.disabled:
+ self.disabled_sources.append(source)
+ elif source.type == self.source_type and not source.disabled:
+ self.source_code_sources.append(source)
+ elif source.type == self.source_type and source.disabled:
+ self.disabled_sources.append(source)
+ if not source.invalid and source.template in self.source_template.children:
+ if not source.disabled and source.type == self.binary_type:
+ self.child_sources.append(source)
+ elif not source.disabled and source.type == self.source_type:
+ self.source_code_sources.append(source)
+ else:
+ self.disabled_sources.append(source)
+ self.download_comps = set(comps)
+ self.cdrom_comps = set(cdrom_comps)
+ enabled_comps.extend(comps)
+ enabled_comps.extend(cdrom_comps)
+ self.enabled_comps = set(enabled_comps)
+ self.used_media = set(media)
+ self.get_mirrors()
+
+ def get_mirrors(self, mirror_template=None):
+ """
+ Provide a set of mirrors where you can get the distribution from
+ """
+ # the main server is stored in the template
+ self.main_server = self.source_template.base_uri
+
+ # other used servers
+ for medium in self.used_media:
+ if not medium.startswith("cdrom:"):
+ # seems to be a network source
+ self.used_servers.append(medium)
+
+ if len(self.main_sources) == 0:
+ self.default_server = self.main_server
+ else:
+ self.default_server = self.main_sources[0].uri
+
+ # get a list of country codes and real names
+ self.countries = {}
+ fname = "/usr/share/xml/iso-codes/iso_3166.xml"
+ if os.path.exists(fname):
+ et = ElementTree(file=fname)
+ # python2.6 compat, the next two lines can get removed
+ # once we do not use py2.6 anymore
+ if getattr(et, "iter", None) is None:
+ et.iter = et.getiterator
+ it = et.iter("iso_3166_entry")
+ for elm in it:
+ try:
+ descr = elm.attrib["common_name"]
+ except KeyError:
+ descr = elm.attrib["name"]
+ try:
+ code = elm.attrib["alpha_2_code"]
+ except KeyError:
+ code = elm.attrib["alpha_3_code"]
+ self.countries[code.lower()] = gettext.dgettext("iso_3166", descr)
+
+ # try to guess the nearest mirror from the locale
+ self.country = None
+ self.country_code = None
+ locale = os.getenv("LANG", default="en_UK")
+ a = locale.find("_")
+ z = locale.find(".")
+ if z == -1:
+ z = len(locale)
+ country_code = locale[a + 1 : z].lower()
+
+ if mirror_template:
+ self.nearest_server = mirror_template % country_code
+
+ if country_code in self.countries:
+ self.country = self.countries[country_code]
+ self.country_code = country_code
+
+ def _get_mirror_name(self, server):
+ """Try to get a human readable name for the main mirror of a country
+ Customize for different distributions"""
+ country = None
+ i = server.find("://")
+ li = server.find(".archive.ubuntu.com")
+ if i != -1 and li != -1:
+ country = server[i + len("://") : li]
+ if country in self.countries:
+ # TRANSLATORS: %s is a country
+ return _("Server for %s") % self.countries[country]
+ else:
+ return "%s" % server.rstrip("/ ")
+
+ def get_server_list(self):
+ """Return a list of used and suggested servers"""
+
+ def compare_mirrors(mir1, mir2):
+ """Helper function that handles comaprision of mirror urls
+ that could contain trailing slashes"""
+ return re.match(mir1.strip("/ "), mir2.rstrip("/ "))
+
+ # Store all available servers:
+ # Name, URI, active
+ mirrors = []
+ if len(self.used_servers) < 1 or (
+ len(self.used_servers) == 1
+ and compare_mirrors(self.used_servers[0], self.main_server)
+ ):
+ mirrors.append([_("Main server"), self.main_server, True])
+ if self.nearest_server:
+ mirrors.append(
+ [
+ self._get_mirror_name(self.nearest_server),
+ self.nearest_server,
+ False,
+ ]
+ )
+ elif len(self.used_servers) == 1 and not compare_mirrors(
+ self.used_servers[0], self.main_server
+ ):
+ mirrors.append([_("Main server"), self.main_server, False])
+ # Only one server is used
+ server = self.used_servers[0]
+
+ # Append the nearest server if it's not already used
+ if self.nearest_server:
+ if not compare_mirrors(server, self.nearest_server):
+ mirrors.append(
+ [
+ self._get_mirror_name(self.nearest_server),
+ self.nearest_server,
+ False,
+ ]
+ )
+ if server:
+ mirrors.append([self._get_mirror_name(server), server, True])
+
+ elif len(self.used_servers) > 1:
+ # More than one server is used. Since we don't handle this case
+ # in the user interface we set "custom servers" to true and
+ # append a list of all used servers
+ mirrors.append([_("Main server"), self.main_server, False])
+ if self.nearest_server:
+ mirrors.append(
+ [
+ self._get_mirror_name(self.nearest_server),
+ self.nearest_server,
+ False,
+ ]
+ )
+ mirrors.append([_("Custom servers"), None, True])
+ for server in self.used_servers:
+ mirror_entry = [self._get_mirror_name(server), server, False]
+ if compare_mirrors(server, self.nearest_server) or compare_mirrors(
+ server, self.main_server
+ ):
+ continue
+ elif mirror_entry not in mirrors:
+ mirrors.append(mirror_entry)
+
+ return mirrors
+
+ def add_source(self, type=None, uri=None, dist=None, comps=None, comment=""):
+ """
+ Add distribution specific sources
+ """
+ if uri is None:
+ # FIXME: Add support for the server selector
+ uri = self.default_server
+ if dist is None:
+ dist = self.codename
+ if comps is None:
+ comps = list(self.enabled_comps)
+ if type is None:
+ type = self.binary_type
+
+ parent = None
+ file = None
+ for parent in reversed(self.child_sources) or reversed(self.main_sources):
+ file = parent.file
+ break
+
+ new_source = self.sourceslist.add(
+ type, uri, dist, comps, comment, parent=parent, file=file
+ )
+ # if source code is enabled add a deb-src line after the new
+ # source
+ if self.get_source_code and type == self.binary_type:
+ self.sourceslist.add(
+ self.source_type,
+ uri,
+ dist,
+ comps,
+ comment,
+ file=new_source.file,
+ parent=new_source,
+ pos=self.sourceslist.list.index(new_source) + 1,
+ )
+
+ def enable_component(self, comp):
+ """
+ Enable a component in all main, child and source code sources
+ (excluding cdrom based sources)
+
+ comp: the component that should be enabled
+ """
+ comps = list([comp])
+ # look for parent components that we may have to add
+ for source in self.main_sources:
+ for c in source.template.components:
+ if c.name == comp and c.parent_component:
+ if c.parent_component not in comps:
+ comps.append(c.parent_component)
+ for c in comps:
+ self._enable_component(c)
+
+ def _enable_component(self, comp):
+ def add_component_only_once(source, comps_per_dist):
+ """
+ Check if we already added the component to the repository, since
+ a repository could be splitted into different apt lines. If not
+ add the component
+ """
+ # if we don't have that distro, just return (can happen for e.g.
+ # dapper-update only in deb-src
+ if source.dist not in comps_per_dist:
+ return
+ # if we have seen this component already for this distro,
+ # return (nothing to do)
+ if comp in comps_per_dist[source.dist]:
+ return
+ # add it
+ source.comps = source.comps + [comp]
+ comps_per_dist[source.dist].add(comp)
+
+ sources = []
+ sources.extend(self.main_sources)
+ sources.extend(self.child_sources)
+ # store what comps are enabled already per distro (where distro is
+ # e.g. "dapper", "dapper-updates")
+ comps_per_dist = {}
+ comps_per_sdist = {}
+ for s in sources:
+ if s.type == self.binary_type:
+ if s.dist not in comps_per_dist:
+ comps_per_dist[s.dist] = set()
+ for c in s.comps:
+ comps_per_dist[s.dist].add(c)
+ for s in self.source_code_sources:
+ if s.type == self.source_type:
+ if s.dist not in comps_per_sdist:
+ comps_per_sdist[s.dist] = set()
+ for c in s.comps:
+ comps_per_sdist[s.dist].add(c)
+
+ # check if there is a main source at all
+ if len(self.main_sources) < 1:
+ # create a new main source
+ self.add_source(comps=["%s" % comp])
+ else:
+ # add the comp to all main, child and source code sources
+ for source in sources:
+ add_component_only_once(source, comps_per_dist)
+
+ for source in self.source_code_sources:
+ add_component_only_once(source, comps_per_sdist)
+
+ # check if there is a main source code source at all
+ if self.get_source_code:
+ if len(self.source_code_sources) < 1:
+ # create a new main source
+ self.add_source(type=self.source_type, comps=["%s" % comp])
+ else:
+ # add the comp to all main, child and source code sources
+ for source in self.source_code_sources:
+ add_component_only_once(source, comps_per_sdist)
+
+ def disable_component(self, comp):
+ """
+ Disable a component in all main, child and source code sources
+ (excluding cdrom based sources)
+ """
+ sources = []
+ sources.extend(self.main_sources)
+ sources.extend(self.child_sources)
+ sources.extend(self.source_code_sources)
+ if comp in self.cdrom_comps:
+ sources = []
+ sources.extend(self.main_sources)
+ for source in sources:
+ if comp in source.comps:
+ comps = source.comps
+ comps.remove(comp)
+ source.comps = comps
+ if len(source.comps) < 1:
+ self.sourceslist.remove(source)
+
+ def change_server(self, uri):
+ """Change the server of all distro specific sources to
+ a given host"""
+
+ def change_server_of_source(source, uri, seen):
+ # Avoid creating duplicate entries
+ source.uri = uri
+ for comp in source.comps:
+ if [source.uri, source.dist, comp] in seen:
+ source.comps.remove(comp)
+ else:
+ seen.append([source.uri, source.dist, comp])
+ if len(source.comps) < 1:
+ self.sourceslist.remove(source)
+
+ seen_binary = []
+ seen_source = []
+ self.default_server = uri
+ for source in self.main_sources:
+ change_server_of_source(source, uri, seen_binary)
+ for source in self.child_sources:
+ # Do not change the forces server of a child source
+ if (
+ source.template.base_uri is None
+ or source.template.base_uri != source.uri
+ ):
+ change_server_of_source(source, uri, seen_binary)
+ for source in self.source_code_sources:
+ change_server_of_source(source, uri, seen_source)
+
+ def is_codename(self, name):
+ """Compare a given name with the release codename."""
+ if name == self.codename:
+ return True
+ else:
+ return False
+
+
+class DebianDistribution(Distribution):
+ """Class to support specific Debian features"""
+
+ def is_codename(self, name):
+ """Compare a given name with the release codename and check if
+ if it can be used as a synonym for a development releases"""
+ if name == self.codename or self.release in ("testing", "unstable"):
+ return True
+ else:
+ return False
+
+ def _get_mirror_name(self, server):
+ """Try to get a human readable name for the main mirror of a country
+ Debian specific"""
+ country = None
+ i = server.find("://ftp.")
+ li = server.find(".debian.org")
+ if i != -1 and li != -1:
+ country = server[i + len("://ftp.") : li]
+ if country in self.countries:
+ # TRANSLATORS: %s is a country
+ return (
+ _("Server for %s")
+ % gettext.dgettext(
+ "iso_3166", self.countries[country].rstrip()
+ ).rstrip()
+ )
+ else:
+ return "%s" % server.rstrip("/ ")
+
+ def get_mirrors(self):
+ Distribution.get_mirrors(
+ self, mirror_template="http://ftp.%s.debian.org/debian/"
+ )
+
+
+class UbuntuDistribution(Distribution):
+ """Class to support specific Ubuntu features"""
+
+ def get_mirrors(self):
+ Distribution.get_mirrors(
+ self, mirror_template="http://%s.archive.ubuntu.com/ubuntu/"
+ )
+
+
+class UbuntuRTMDistribution(UbuntuDistribution):
+ """Class to support specific Ubuntu RTM features"""
+
+ def get_mirrors(self):
+ self.main_server = self.source_template.base_uri
+
+
+def _lsb_release():
+ """Call lsb_release --idrc and return a mapping."""
+ import errno
+ from subprocess import PIPE, Popen
+
+ result = {
+ "Codename": "sid",
+ "Distributor ID": "Debian",
+ "Description": "Debian GNU/Linux unstable (sid)",
+ "Release": "unstable",
+ }
+ try:
+ out = Popen(["lsb_release", "-idrc"], stdout=PIPE).communicate()[0]
+ # Convert to unicode string, needed for Python 3.1
+ out = out.decode("utf-8")
+ result.update(line.split(":\t") for line in out.split("\n") if ":\t" in line)
+ except OSError as exc:
+ if exc.errno != errno.ENOENT:
+ logging.warning("lsb_release failed, using defaults:" % exc)
+ return result
+
+
+def _system_image_channel():
+ """Get the current channel from system-image-cli -i if possible."""
+ import errno
+ from subprocess import DEVNULL, PIPE, Popen
+
+ try:
+ out = Popen(
+ ["system-image-cli", "-i"],
+ stdout=PIPE,
+ stderr=DEVNULL,
+ universal_newlines=True,
+ ).communicate()[0]
+ for line in out.splitlines():
+ if line.startswith("channel: "):
+ return line.split(": ", 1)[1]
+ except OSError as exc:
+ if exc.errno != errno.ENOENT:
+ logging.warning("system-image-cli failed, using defaults: %s" % exc)
+ return None
+
+
+class _OSRelease:
+ DEFAULT_OS_RELEASE_FILE = "/etc/os-release"
+ OS_RELEASE_FILE = "/etc/os-release"
+
+ def __init__(self, lsb_compat=True):
+ self.result = {}
+ self.valid = False
+ self.file = _OSRelease.OS_RELEASE_FILE
+
+ if not os.path.isfile(self.file):
+ return
+
+ self.parse()
+ self.valid = True
+
+ if lsb_compat:
+ self.inject_lsb_compat()
+
+ def inject_lsb_compat(self):
+ self.result["Distributor ID"] = self.result["ID"]
+ self.result["Description"] = self.result["PRETTY_NAME"]
+ # Optionals as per os-release spec.
+ self.result["Codename"] = self.result.get("VERSION_CODENAME")
+ if not self.result["Codename"]:
+ # Transient Ubuntu 16.04 field (LP: #1598212)
+ self.result["Codename"] = self.result.get("UBUNTU_CODENAME")
+ self.result["Release"] = self.result.get("VERSION_ID")
+
+ def parse(self):
+ f = open(self.file)
+ for line in f:
+ line = line.strip()
+ if not line:
+ continue
+ self.parse_entry(*line.split("=", 1))
+ f.close()
+
+ def parse_entry(self, key, value):
+ value = self.parse_value(value) # Values can be shell strings...
+ if key == "ID_LIKE" and isinstance(value, str):
+ # ID_LIKE is specified as quoted space-separated list. This will
+ # be parsed as string that we need to split manually.
+ value = value.split(" ")
+ self.result[key] = value
+
+ def parse_value(self, value):
+ values = shlex.split(value)
+ if len(values) == 1:
+ return values[0]
+ return values
+
+
+def get_distro(id=None, codename=None, description=None, release=None, is_like=[]):
+ """
+ Check the currently used distribution and return the corresponding
+ distriubtion class that supports distro specific features.
+
+ If no paramter are given the distro will be auto detected via
+ a call to lsb-release
+ """
+ # make testing easier
+ if not (id and codename and description and release):
+ if id or codename or description or release:
+ warnings.warn(
+ "Provided only a subset of arguments", DeprecationWarning, stacklevel=2
+ )
+ os_release = _OSRelease()
+ os_result = []
+ lsb_result = _lsb_release()
+ if os_release.valid:
+ os_result = os_release.result
+ # TODO: We cannot presently use os-release to fully replace lsb_release
+ # because os-release's ID, VERSION_ID and VERSION_CODENAME fields
+ # are specified as lowercase. In lsb_release they can be upcase
+ # or captizalized. So, switching to os-release would consitute
+ # a behavior break a which point lsb_release support should be
+ # fully removed.
+ # This in particular is a problem for template matching, as this
+ # matches against Distribution objects and depends on string
+ # case.
+ lsb_result = _lsb_release()
+ id = lsb_result["Distributor ID"]
+ codename = lsb_result["Codename"]
+ description = lsb_result["Description"]
+ release = lsb_result["Release"]
+ # Not available with LSB, use get directly.
+ is_like = os_result.get("ID_LIKE", [])
+ if id == "Ubuntu":
+ channel = _system_image_channel()
+ if channel is not None and "ubuntu-rtm/" in channel:
+ id = "Ubuntu-RTM"
+ codename = channel.rsplit("/", 1)[1].split("-", 1)[0]
+ description = codename
+ release = codename
+ if id == "Ubuntu":
+ return UbuntuDistribution(id, codename, description, release, is_like)
+ if id == "Ubuntu-RTM":
+ return UbuntuRTMDistribution(id, codename, description, release, is_like)
+ elif id == "Debian":
+ return DebianDistribution(id, codename, description, release, is_like)
+ else:
+ return Distribution(id, codename, description, release, is_like)
diff --git a/aptsources/sourceslist.py b/aptsources/sourceslist.py
new file mode 100644
index 0000000..b227690
--- /dev/null
+++ b/aptsources/sourceslist.py
@@ -0,0 +1,1083 @@
+# sourceslist.py - Provide an abstraction of the sources.list
+#
+# Copyright (c) 2004-2023 Canonical Ltd.
+# Copyright (c) 2004 Michiel Sikkes
+# Copyright (c) 2006-2007 Sebastian Heinlein
+#
+# Authors: Michiel Sikkes <michiel@eyesopened.nl>
+# Michael Vogt <mvo@debian.org>
+# Sebastian Heinlein <glatzor@ubuntu.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
+import builtins
+import glob
+import io
+import logging
+import os.path
+import re
+import shutil
+import time
+import weakref
+from collections.abc import Callable, Iterable, Iterator
+from typing import Any, Generic, Optional, TypeVar, Union
+
+import apt_pkg
+
+from . import _deb822
+from .distinfo import DistInfo, Template
+
+# from apt_pkg import gettext as _
+
+T = TypeVar("T")
+
+# some global helpers
+
+__all__ = [
+ "is_mirror",
+ "Deb822SourceEntry",
+ "SourceEntry",
+ "NullMatcher",
+ "SourcesList",
+ "SourceEntryMatcher",
+]
+
+
+def is_mirror(master_uri: str, compare_uri: str) -> bool:
+ """check if the given add_url is idential or a mirror of orig_uri e.g.:
+ master_uri = archive.ubuntu.com
+ compare_uri = de.archive.ubuntu.com
+ -> True
+ """
+ # remove traling spaces and "/"
+ compare_uri = compare_uri.rstrip("/ ")
+ master_uri = master_uri.rstrip("/ ")
+ # uri is identical
+ if compare_uri == master_uri:
+ # print "Identical"
+ return True
+ # add uri is a master site and orig_uri has the from "XX.mastersite"
+ # (e.g. de.archive.ubuntu.com)
+ try:
+ compare_srv = compare_uri.split("//")[1]
+ master_srv = master_uri.split("//")[1]
+ # print "%s == %s " % (add_srv, orig_srv)
+ except IndexError: # ok, somethings wrong here
+ # print "IndexError"
+ return False
+ # remove the leading "<country>." (if any) and see if that helps
+ if "." in compare_srv and compare_srv[compare_srv.index(".") + 1 :] == master_srv:
+ # print "Mirror"
+ return True
+ return False
+
+
+def uniq(s: Iterable[T]) -> list[T]:
+ """simple and efficient way to return uniq collection
+
+ This is not intended for use with a SourceList. It is provided
+ for internal use only. It does not have a leading underscore to
+ not break any old code that uses it; but it should not be used
+ in new code (and is not listed in __all__)."""
+ return list(set(s))
+
+
+class SingleValueProperty(property):
+ def __init__(self, key: str, doc: str):
+ self.key = key
+ self.__doc__ = doc
+
+ def __get__(
+ self, obj: Optional["Deb822SourceEntry"], objtype: type | None = None
+ ) -> str | None:
+ if obj is None:
+ return self # type: ignore
+ return obj.section.get(self.key, None)
+
+ def __set__(self, obj: "Deb822SourceEntry", value: str | None) -> None:
+ if value is None:
+ del obj.section[self.key]
+ else:
+ obj.section[self.key] = value
+
+
+class MultiValueProperty(property):
+ def __init__(self, key: str, doc: str):
+ self.key = key
+ self.__doc__ = doc
+
+ def __get__(
+ self, obj: Optional["Deb822SourceEntry"], objtype: type | None = None
+ ) -> list[str]:
+ if obj is None:
+ return self # type: ignore
+ return SourceEntry.mysplit(obj.section.get(self.key, ""))
+
+ def __set__(self, obj: "Deb822SourceEntry", values: list[str]) -> None:
+ obj.section[self.key] = " ".join(values)
+
+
+class ExplodedEntryProperty(property, Generic[T]):
+ def __init__(self, parent: T):
+ self.parent = parent
+
+ def __get__(
+ self, obj: Optional["ExplodedDeb822SourceEntry"], objtype: type | None = None
+ ) -> T:
+ if obj is None:
+ return self # type: ignore
+ return self.parent.__get__(obj.parent) # type: ignore
+
+ def __set__(self, obj: "ExplodedDeb822SourceEntry", value: T) -> None:
+ obj.split_out()
+ self.parent.__set__(obj.parent, value) # type: ignore
+
+
+def DeprecatedProperty(prop: T) -> T:
+ return prop
+
+
+def _null_weakref() -> None:
+ """Behaves like an expired weakref.ref, returning None"""
+ return None
+
+
+class Deb822SourceEntry:
+ def __init__(
+ self,
+ section: _deb822.Section | str | None,
+ file: str,
+ list: Optional["SourcesList"] = None,
+ ):
+ if section is None:
+ self.section = _deb822.Section("")
+ elif isinstance(section, str):
+ self.section = _deb822.Section(section)
+ else:
+ self.section = section
+
+ self._line = str(self.section)
+ self.file = file
+ self.template: Template | None = None # type DistInfo.Suite
+ self.may_merge = False
+ self._children = weakref.WeakSet["ExplodedDeb822SourceEntry"]()
+
+ if list:
+ self._list: Callable[[], SourcesList | None] = weakref.ref(list)
+ else:
+ self._list = _null_weakref
+
+ def __eq__(self, other: Any) -> Any:
+ # FIXME: Implement plurals more correctly
+ """equal operator for two sources.list entries"""
+ return (
+ self.disabled == other.disabled
+ and self.type == other.type
+ and self.uri
+ and self.uri.rstrip("/") == other.uri.rstrip("/")
+ and self.dist == other.dist
+ and self.comps == other.comps
+ )
+
+ architectures = MultiValueProperty("Architectures", "The list of architectures")
+ types = MultiValueProperty("Types", "The list of types")
+ type = DeprecatedProperty(SingleValueProperty("Types", "The list of types"))
+ uris = MultiValueProperty("URIs", "URIs in the source")
+ uri = DeprecatedProperty(SingleValueProperty("URIs", "URIs in the source"))
+ suites = MultiValueProperty("Suites", "Suites in the source")
+ dist = DeprecatedProperty(SingleValueProperty("Suites", "Suites in the source"))
+ comps = MultiValueProperty("Components", "Components in the source")
+
+ @property
+ def comment(self) -> str:
+ """Legacy attribute describing the paragraph header."""
+ return self.section.header
+
+ @comment.setter
+ def comment(self, comment: str) -> None:
+ """Legacy attribute describing the paragraph header."""
+ self.section.header = comment
+
+ @property
+ def trusted(self) -> bool | None:
+ """Return the value of the Trusted field"""
+ try:
+ return apt_pkg.string_to_bool(self.section["Trusted"])
+ except KeyError:
+ return None
+
+ @trusted.setter
+ def trusted(self, value: bool | None) -> None:
+ if value is None:
+ try:
+ del self.section["Trusted"]
+ except KeyError:
+ pass
+ else:
+ self.section["Trusted"] = "yes" if value else "no"
+
+ @property
+ def disabled(self) -> bool:
+ """Check if Enabled: no is set."""
+ return not apt_pkg.string_to_bool(self.section.get("Enabled", "yes"))
+
+ @disabled.setter
+ def disabled(self, value: bool) -> None:
+ if value:
+ self.section["Enabled"] = "no"
+ else:
+ try:
+ del self.section["Enabled"]
+ except KeyError:
+ pass
+
+ @property
+ def invalid(self) -> bool:
+ """A section is invalid if it doesn't have proper entries."""
+ return not self.section
+
+ @property
+ def line(self) -> str:
+ """The entire (original) paragraph."""
+ return self._line
+
+ def __str__(self) -> str:
+ return self.str().strip()
+
+ def str(self) -> str:
+ """Section as a string, newline terminated."""
+ return str(self.section)
+
+ def set_enabled(self, enabled: bool) -> None:
+ """Deprecated (for deb822) accessor for .disabled"""
+ self.disabled = not enabled
+
+ def merge(self, other: "AnySourceEntry") -> bool:
+ """Merge the two entries if they are compatible."""
+ if (
+ not self.may_merge
+ and self.template is None
+ and not all(child.template for child in self._children)
+ ):
+ return False
+ if self.file != other.file:
+ return False
+ if not isinstance(other, Deb822SourceEntry):
+ return False
+ if self.comment != other.comment and not any(
+ "Added by software-properties" in c for c in (self.comment, other.comment)
+ ):
+ return False
+
+ for tag in set(list(self.section.tags) + list(other.section.tags)):
+ if tag.lower() in (
+ "types",
+ "uris",
+ "suites",
+ "components",
+ "architectures",
+ "signed-by",
+ ):
+ continue
+ in_self = self.section.get(tag, None)
+ in_other = other.section.get(tag, None)
+ if in_self != in_other:
+ return False
+
+ if (
+ sum(
+ [
+ set(self.types) != set(other.types),
+ set(self.uris) != set(other.uris),
+ set(self.suites) != set(other.suites),
+ set(self.comps) != set(other.comps),
+ set(self.architectures) != set(other.architectures),
+ ]
+ )
+ > 1
+ ):
+ return False
+
+ for typ in other.types:
+ if typ not in self.types:
+ self.types += [typ]
+
+ for uri in other.uris:
+ if uri not in self.uris:
+ self.uris += [uri]
+
+ for suite in other.suites:
+ if suite not in self.suites:
+ self.suites += [suite]
+
+ for component in other.comps:
+ if component not in self.comps:
+ self.comps += [component]
+
+ for arch in other.architectures:
+ if arch not in self.architectures:
+ self.architectures += [arch]
+
+ return True
+
+ def _reparent_children(self, to: "Deb822SourceEntry") -> None:
+ """If we end up being split, check if any of our children need to be reparented to the new parent."""
+ for child in self._children:
+ for typ in to.types:
+ for uri in to.uris:
+ for suite in to.suites:
+ if (child._type, child._uri, child._suite) == (typ, uri, suite):
+ assert child.parent == self
+ child._parent = weakref.ref(to)
+
+
+class ExplodedDeb822SourceEntry:
+ """This represents a bit of a deb822 paragraph corresponding to a legacy sources.list entry"""
+
+ # Mostly we use slots to prevent accidentally assigning unproxied attributes
+ __slots__ = ["_parent", "_type", "_uri", "_suite", "template", "__weakref__"]
+
+ def __init__(self, parent: Deb822SourceEntry, typ: str, uri: str, suite: str):
+ self._parent = weakref.ref(parent)
+ self._type = typ
+ self._uri = uri
+ self._suite = suite
+ self.template = parent.template
+ parent._children.add(self)
+
+ @property
+ def parent(self) -> Deb822SourceEntry:
+ if self._parent is not None:
+ if (parent := self._parent()) is not None:
+ return parent
+ raise ValueError("The parent entry is no longer valid")
+
+ @property
+ def uri(self) -> str:
+ self.__check_valid()
+ return self._uri
+
+ @uri.setter
+ def uri(self, uri: str) -> None:
+ self.split_out()
+ self.parent.uris = [u if u != self._uri else uri for u in self.parent.uris]
+ self._uri = uri
+
+ @property
+ def types(self) -> list[str]:
+ return [self.type]
+
+ @property
+ def suites(self) -> list[str]:
+ return [self.dist]
+
+ @property
+ def uris(self) -> list[str]:
+ return [self.uri]
+
+ @property
+ def type(self) -> str:
+ self.__check_valid()
+ return self._type
+
+ @type.setter
+ def type(self, typ: str) -> None:
+ self.split_out()
+ self.parent.types = [typ]
+ self._type = typ
+ self.__check_valid()
+ assert self._type == typ
+ assert self.parent.types == [self._type]
+
+ @property
+ def dist(self) -> str:
+ self.__check_valid()
+ return self._suite
+
+ @dist.setter
+ def dist(self, suite: str) -> None:
+ self.split_out()
+ self.parent.suites = [suite]
+ self._suite = suite
+ self.__check_valid()
+ assert self._suite == suite
+ assert self.parent.suites == [self._suite]
+
+ def __check_valid(self) -> None:
+ if self.parent._list() is None:
+ raise ValueError("The parent entry is dead")
+ for type in self.parent.types:
+ for uri in self.parent.uris:
+ for suite in self.parent.suites:
+ if (type, uri, suite) == (self._type, self._uri, self._suite):
+ return
+ raise ValueError(f"Could not find parent of {self}")
+
+ def split_out(self) -> None:
+ parent = self.parent
+ if (parent.types, parent.uris, parent.suites) == (
+ [self._type],
+ [self._uri],
+ [self._suite],
+ ):
+ return
+ sources_list = parent._list()
+ if sources_list is None:
+ raise ValueError("The parent entry is dead")
+
+ try:
+ index = sources_list.list.index(parent)
+ except ValueError as e:
+ raise ValueError(
+ f"Parent entry for partial deb822 {self} no longer valid"
+ ) from e
+
+ sources_list.remove(parent)
+
+ reparented = False
+ for type in reversed(parent.types):
+ for uri in reversed(parent.uris):
+ for suite in reversed(parent.suites):
+ new = Deb822SourceEntry(
+ section=_deb822.Section(parent.section),
+ file=parent.file,
+ list=sources_list,
+ )
+ new.types = [type]
+ new.uris = [uri]
+ new.suites = [suite]
+ new.may_merge = True
+
+ parent._reparent_children(new)
+ sources_list.list.insert(index, new)
+ if (type, uri, suite) == (self._type, self._uri, self._suite):
+ self._parent = weakref.ref(new)
+ reparented = True
+ if not reparented:
+ raise ValueError(f"Could not find parent of {self}")
+
+ def __repr__(self) -> str:
+ return f"<child {self._type} {self._uri} {self._suite} of {self._parent}"
+
+ architectures = ExplodedEntryProperty(Deb822SourceEntry.architectures)
+ comps = ExplodedEntryProperty(Deb822SourceEntry.comps)
+ invalid = ExplodedEntryProperty(Deb822SourceEntry.invalid)
+ disabled = ExplodedEntryProperty[bool](Deb822SourceEntry.disabled) # type: ignore
+ trusted = ExplodedEntryProperty(Deb822SourceEntry.trusted)
+ comment = ExplodedEntryProperty(Deb822SourceEntry.comment)
+
+ def set_enabled(self, enabled: bool) -> None:
+ """Set the source to enabled."""
+ self.disabled = not enabled
+
+ @property
+ def file(self) -> str:
+ """Return the file."""
+ return self.parent.file
+
+
+class SourceEntry:
+ """single sources.list entry"""
+
+ def __init__(self, line: str, file: str | None = None):
+ self.invalid = False # is the source entry valid
+ self.disabled = False # is it disabled ('#' in front)
+ self.type = "" # what type (deb, deb-src)
+ self.architectures: list[str] = [] # architectures
+ self.trusted: bool | None = None # Trusted
+ self.uri = "" # base-uri
+ self.dist = "" # distribution (dapper, edgy, etc)
+ self.comps: list[str] = [] # list of available componetns (may empty)
+ self.comment = "" # (optional) comment
+ self.line = line # the original sources.list line
+ if file is None:
+ file = apt_pkg.config.find_file("Dir::Etc::sourcelist")
+ if file.endswith(".sources"):
+ raise ValueError("Classic SourceEntry cannot be written to .sources file")
+ self.file = file # the file that the entry is located in
+ self.parse(line)
+ self.template: Template | None = None # type DistInfo.Suite
+ self.children: list[SourceEntry] = []
+
+ def __eq__(self, other: Any) -> Any:
+ """equal operator for two sources.list entries"""
+ return (
+ self.disabled == other.disabled
+ and self.type == other.type
+ and self.uri.rstrip("/") == other.uri.rstrip("/")
+ and self.dist == other.dist
+ and self.comps == other.comps
+ )
+
+ @staticmethod
+ def mysplit(line: str) -> list[str]:
+ """a split() implementation that understands the sources.list
+ format better and takes [] into account (for e.g. cdroms)"""
+ line = line.strip()
+ pieces = []
+ tmp = ""
+ # we are inside a [..] block
+ p_found = False
+ space_found = False
+ for i in range(len(line)):
+ if line[i] == "[":
+ if space_found:
+ space_found = False
+ p_found = True
+ pieces.append(tmp)
+ tmp = line[i]
+ else:
+ p_found = True
+ tmp += line[i]
+ elif line[i] == "]":
+ p_found = False
+ tmp += line[i]
+ elif space_found and not line[i].isspace():
+ # we skip one or more space
+ space_found = False
+ pieces.append(tmp)
+ tmp = line[i]
+ elif line[i].isspace() and not p_found:
+ # found a whitespace
+ space_found = True
+ else:
+ tmp += line[i]
+ # append last piece
+ if len(tmp) > 0:
+ pieces.append(tmp)
+ return pieces
+
+ def parse(self, line: str) -> None:
+ """parse a given sources.list (textual) line and break it up
+ into the field we have"""
+ self.line = line
+ line = line.strip()
+ # check if the source is enabled/disabled
+ if line == "" or line == "#": # empty line
+ self.invalid = True
+ return
+ if line[0] == "#":
+ self.disabled = True
+ pieces = line[1:].strip().split()
+ # if it looks not like a disabled deb line return
+ if not pieces[0] in ("rpm", "rpm-src", "deb", "deb-src"):
+ self.invalid = True
+ return
+ else:
+ line = line[1:]
+ # check for another "#" in the line (this is treated as a comment)
+ i = line.find("#")
+ if i > 0:
+ self.comment = line[i + 1 :]
+ line = line[:i]
+ # source is ok, split it and see what we have
+ pieces = self.mysplit(line)
+ # Sanity check
+ if len(pieces) < 3:
+ self.invalid = True
+ return
+ # Type, deb or deb-src
+ self.type = pieces[0].strip()
+ # Sanity check
+ if self.type not in ("deb", "deb-src", "rpm", "rpm-src"):
+ self.invalid = True
+ return
+
+ if pieces[1].strip()[0] == "[":
+ options = pieces.pop(1).strip("[]").split()
+ for option in options:
+ try:
+ key, value = option.split("=", 1)
+ except Exception:
+ self.invalid = True
+ else:
+ if key == "arch":
+ self.architectures = value.split(",")
+ elif key == "trusted":
+ self.trusted = apt_pkg.string_to_bool(value)
+ else:
+ self.invalid = True
+
+ # URI
+ self.uri = pieces[1].strip()
+ if len(self.uri) < 1:
+ self.invalid = True
+ # distro and components (optional)
+ # Directory or distro
+ self.dist = pieces[2].strip()
+ if len(pieces) > 3:
+ # List of components
+ self.comps = pieces[3:]
+ else:
+ self.comps = []
+
+ def set_enabled(self, new_value: bool) -> None:
+ """set a line to enabled or disabled"""
+ self.disabled = not new_value
+ # enable, remove all "#" from the start of the line
+ if new_value:
+ self.line = self.line.lstrip().lstrip("#")
+ else:
+ # disabled, add a "#"
+ if self.line.strip()[0] != "#":
+ self.line = "#" + self.line
+
+ def __str__(self) -> str:
+ """debug helper"""
+ return self.str().strip()
+
+ def str(self) -> str:
+ """return the current line as string"""
+ if self.invalid:
+ return self.line
+ line = ""
+ if self.disabled:
+ line = "# "
+
+ line += self.type
+
+ if self.architectures and self.trusted is not None:
+ line += " [arch={} trusted={}]".format(
+ ",".join(self.architectures),
+ "yes" if self.trusted else "no",
+ )
+ elif self.trusted is not None:
+ line += " [trusted=%s]" % ("yes" if self.trusted else "no")
+ elif self.architectures:
+ line += " [arch=%s]" % ",".join(self.architectures)
+ line += f" {self.uri} {self.dist}"
+ if len(self.comps) > 0:
+ line += " " + " ".join(self.comps)
+ if self.comment != "":
+ line += " #" + self.comment
+ line += "\n"
+ return line
+
+ @property
+ def types(self) -> list[builtins.str]:
+ """deb822 compatible accessor for the type"""
+ return [self.type]
+
+ @property
+ def uris(self) -> list[builtins.str]:
+ """deb822 compatible accessor for the uri"""
+ return [self.uri]
+
+ @property
+ def suites(self) -> list[builtins.str]:
+ """deb822 compatible accessor for the suite"""
+ return [self.dist]
+
+
+AnySourceEntry = Union[SourceEntry, Deb822SourceEntry]
+AnyExplodedSourceEntry = Union[
+ SourceEntry, Deb822SourceEntry, ExplodedDeb822SourceEntry
+]
+
+
+class NullMatcher:
+ """a Matcher that does nothing"""
+
+ def match(self, s: AnyExplodedSourceEntry) -> bool:
+ return True
+
+
+class SourcesList:
+ """represents the full sources.list + sources.list.d file"""
+
+ def __init__(
+ self,
+ withMatcher: bool = True,
+ matcherPath: str = "/usr/share/python-apt/templates/",
+ *,
+ deb822: bool = False,
+ ):
+ self.list: list[AnySourceEntry] = [] # the actual SourceEntries Type
+ self.matcher: NullMatcher | SourceEntryMatcher
+ if withMatcher:
+ self.matcher = SourceEntryMatcher(matcherPath)
+ else:
+ self.matcher = NullMatcher()
+ self.deb822 = deb822
+ self.refresh()
+
+ def refresh(self) -> None:
+ """update the list of known entries"""
+ self.list = []
+ # read sources.list
+ file = apt_pkg.config.find_file("Dir::Etc::sourcelist")
+ if file != "/dev/null" and os.path.exists(file):
+ self.load(file)
+ # read sources.list.d
+ partsdir = apt_pkg.config.find_dir("Dir::Etc::sourceparts")
+ if partsdir != "/dev/null" and os.path.exists(partsdir):
+ for file in os.listdir(partsdir):
+ if (self.deb822 and file.endswith(".sources")) or file.endswith(
+ ".list"
+ ):
+ self.load(os.path.join(partsdir, file))
+ # check if the source item fits a predefined template
+ for source in self.list:
+ if not source.invalid:
+ self.matcher.match(source)
+
+ def __iter__(self) -> Iterator[AnySourceEntry]:
+ """simple iterator to go over self.list, returns SourceEntry
+ types"""
+ yield from self.list
+
+ def __find(
+ self, *predicates: Callable[[AnyExplodedSourceEntry], bool], **attrs: Any
+ ) -> Iterator[AnyExplodedSourceEntry]:
+ uri = attrs.pop("uri", None)
+ for source in self.exploded_list():
+ if uri and source.uri and uri.rstrip("/") != source.uri.rstrip("/"):
+ continue
+ if all(getattr(source, key) == attrs[key] for key in attrs) and all(
+ predicate(source) for predicate in predicates
+ ):
+ yield source
+
+ def add(
+ self,
+ type: str,
+ uri: str,
+ dist: str,
+ orig_comps: list[str],
+ comment: str = "",
+ pos: int = -1,
+ file: str | None = None,
+ architectures: Iterable[str] = [],
+ parent: AnyExplodedSourceEntry | None = None,
+ ) -> AnyExplodedSourceEntry:
+ """
+ Add a new source to the sources.list.
+ The method will search for existing matching repos and will try to
+ reuse them as far as possible
+ """
+
+ type = type.strip()
+ disabled = type.startswith("#")
+ if disabled:
+ type = type[1:].lstrip()
+ architectures = set(architectures)
+ # create a working copy of the component list so that
+ # we can modify it later
+ comps = orig_comps[:]
+ sources = self.__find(
+ lambda s: set(s.architectures) == architectures,
+ disabled=disabled,
+ invalid=False,
+ type=type,
+ uri=uri,
+ dist=dist,
+ )
+ # check if we have this source already in the sources.list
+ for source in sources:
+ for new_comp in comps:
+ if new_comp in source.comps:
+ # we have this component already, delete it
+ # from the new_comps list
+ del comps[comps.index(new_comp)]
+ if len(comps) == 0:
+ return source
+
+ sources = self.__find(
+ lambda s: set(s.architectures) == architectures,
+ invalid=False,
+ type=type,
+ uri=uri,
+ dist=dist,
+ )
+ for source in sources:
+ if source.disabled == disabled:
+ # if there is a repo with the same (disabled, type, uri, dist)
+ # just add the components
+ if set(source.comps) != set(comps):
+ source.comps = uniq(source.comps + comps)
+ return source
+ elif source.disabled and not disabled:
+ # enable any matching (type, uri, dist), but disabled repo
+ if set(source.comps) == set(comps):
+ source.disabled = False
+ return source
+
+ new_entry: AnySourceEntry
+ if file is None:
+ file = apt_pkg.config.find_file("Dir::Etc::sourcelist")
+ if file.endswith(".sources"):
+ new_entry = Deb822SourceEntry(None, file=file, list=self)
+ if parent:
+ parent = getattr(parent, "parent", parent)
+ assert isinstance(parent, Deb822SourceEntry)
+ for k in parent.section.tags:
+ new_entry.section[k] = parent.section[k]
+ new_entry.types = [type]
+ new_entry.uris = [uri]
+ new_entry.suites = [dist]
+ new_entry.comps = comps
+ if architectures:
+ new_entry.architectures = list(architectures)
+ new_entry.section.header = comment
+ new_entry.disabled = disabled
+ else:
+ # there isn't any matching source, so create a new line and parse it
+ parts = [
+ "#" if disabled else "",
+ type,
+ ("[arch=%s]" % ",".join(architectures)) if architectures else "",
+ uri,
+ dist,
+ ]
+ parts.extend(comps)
+ if comment:
+ parts.append("#" + comment)
+ line = " ".join(part for part in parts if part) + "\n"
+
+ new_entry = SourceEntry(line)
+ if file is not None:
+ new_entry.file = file
+
+ self.matcher.match(new_entry)
+ if pos < 0:
+ self.list.append(new_entry)
+ else:
+ self.list.insert(pos, new_entry)
+ return new_entry
+
+ def remove(self, source_entry: AnyExplodedSourceEntry) -> None:
+ """remove the specified entry from the sources.list"""
+ if isinstance(source_entry, ExplodedDeb822SourceEntry):
+ source_entry.split_out()
+ source_entry = source_entry.parent
+ self.list.remove(source_entry)
+
+ def restore_backup(self, backup_ext: str) -> None:
+ "restore sources.list files based on the backup extension"
+ file = apt_pkg.config.find_file("Dir::Etc::sourcelist")
+ if os.path.exists(file + backup_ext) and os.path.exists(file):
+ shutil.copy(file + backup_ext, file)
+ # now sources.list.d
+ partsdir = apt_pkg.config.find_dir("Dir::Etc::sourceparts")
+ for file in glob.glob("%s/*" % partsdir):
+ if os.path.exists(file + backup_ext):
+ shutil.copy(file + backup_ext, file)
+
+ def backup(self, backup_ext: str | None = None) -> str:
+ """make a backup of the current source files, if no backup extension
+ is given, the current date/time is used (and returned)"""
+ already_backuped: Iterable[str] = set()
+ if backup_ext is None:
+ backup_ext = time.strftime("%y%m%d.%H%M")
+ for source in self.list:
+ if source.file not in already_backuped and os.path.exists(source.file):
+ shutil.copy(source.file, f"{source.file}{backup_ext}")
+ return backup_ext
+
+ def load(self, file: str) -> None:
+ """(re)load the current sources"""
+ try:
+ with open(file) as f:
+ if file.endswith(".sources"):
+ for section in _deb822.File(f):
+ self.list.append(Deb822SourceEntry(section, file, list=self))
+ else:
+ for line in f:
+ source = SourceEntry(line, file)
+ self.list.append(source)
+ except Exception as exc:
+ logging.warning(f"could not open file '{file}': {exc}\n")
+
+ def index(self, entry: AnyExplodedSourceEntry) -> int:
+ if isinstance(entry, ExplodedDeb822SourceEntry):
+ return self.list.index(entry.parent)
+ return self.list.index(entry)
+
+ def merge(self) -> None:
+ """Merge consecutive entries that have been split back together."""
+ merged = True
+ while merged:
+ i = 0
+ merged = False
+ while i + 1 < len(self.list):
+ entry = self.list[i]
+ if isinstance(entry, Deb822SourceEntry):
+ j = i + 1
+ while j < len(self.list):
+ if entry.merge(self.list[j]):
+ del self.list[j]
+ merged = True
+ else:
+ j += 1
+ i += 1
+
+ def save(self) -> None:
+ """save the current sources"""
+ files: dict[str, io.TextIOWrapper] = {}
+ # write an empty default config file if there aren't any sources
+ if len(self.list) == 0:
+ path = apt_pkg.config.find_file("Dir::Etc::sourcelist")
+ header = (
+ "## See sources.list(5) for more information, especialy\n"
+ "# Remember that you can only use http, ftp or file URIs\n"
+ "# CDROMs are managed through the apt-cdrom tool.\n"
+ )
+
+ with open(path, "w") as f:
+ f.write(header)
+ return
+
+ self.merge()
+ try:
+ for source in self.list:
+ if source.file not in files:
+ files[source.file] = open(source.file, "w")
+ elif isinstance(source, Deb822SourceEntry):
+ files[source.file].write("\n")
+ files[source.file].write(source.str())
+ finally:
+ for f in files.values():
+ f.close()
+
+ def check_for_relations(
+ self, sources_list: Iterable[AnySourceEntry]
+ ) -> tuple[list[AnySourceEntry], dict[Template, list[AnySourceEntry]]]:
+ """get all parent and child channels in the sources list"""
+ parents = []
+ used_child_templates: dict[Template, list[AnySourceEntry]] = {}
+ for source in sources_list:
+ # try to avoid checking uninterressting sources
+ if source.template is None:
+ continue
+ # set up a dict with all used child templates and corresponding
+ # source entries
+ if source.template.child:
+ key = source.template
+ if key not in used_child_templates:
+ used_child_templates[key] = []
+ temp = used_child_templates[key]
+ temp.append(source)
+ else:
+ # store each source with children aka. a parent :)
+ if len(source.template.children) > 0:
+ parents.append(source)
+ # print self.used_child_templates
+ # print self.parents
+ return (parents, used_child_templates)
+
+ def exploded_list(self) -> list[AnyExplodedSourceEntry]:
+ """Present an exploded view of the list where each entry corresponds exactly to a Release file.
+
+ A release file is uniquely identified by the triplet (type, uri, suite). Old style entries
+ always referred to a single release file, but deb822 entries allow multiple values for each
+ of those fields.
+ """
+ res: list[AnyExplodedSourceEntry] = []
+ for entry in self.list:
+ if isinstance(entry, SourceEntry):
+ res.append(entry)
+ elif (
+ len(entry.types) == 1
+ and len(entry.uris) == 1
+ and len(entry.suites) == 1
+ ):
+ res.append(entry)
+ else:
+ for typ in entry.types:
+ for uri in entry.uris:
+ for sui in entry.suites:
+ res.append(ExplodedDeb822SourceEntry(entry, typ, uri, sui))
+ self.matcher.match(res[-1])
+
+ return res
+
+
+class SourceEntryMatcher:
+ """matcher class to make a source entry look nice
+ lots of predefined matchers to make it i18n/gettext friendly
+ """
+
+ def __init__(self, matcherPath: str):
+ self.templates: list[Template] = []
+ # Get the human readable channel and comp names from the channel .infos
+ spec_files = glob.glob("%s/*.info" % matcherPath)
+ for f in spec_files:
+ f = os.path.basename(f)
+ i = f.find(".info")
+ f = f[0:i]
+ dist = DistInfo(f, base_dir=matcherPath)
+ for template in dist.templates:
+ if template.match_uri is not None:
+ self.templates.append(template)
+ return
+
+ def match(self, source: AnyExplodedSourceEntry) -> bool:
+ """Add a matching template to the source"""
+ found = False
+ for template in self.templates:
+ if source.uri is None or source.dist is None:
+ continue
+ if (
+ template.match_uri is not None
+ and template.match_name is not None
+ and source.uri is not None
+ and source.dist is not None
+ and re.search(template.match_uri, source.uri)
+ and re.match(template.match_name, source.dist)
+ and
+ # deb is a valid fallback for deb-src (if that is not
+ # definied, see #760035
+ (source.type == template.type or template.type == "deb")
+ ):
+ found = True
+ source.template = template
+ break
+ elif (
+ template.is_mirror(source.uri)
+ and template.match_name is not None
+ and source.dist is not None
+ and re.match(template.match_name, source.dist)
+ ):
+ found = True
+ source.template = template
+ break
+ return found
+
+
+# some simple tests
+if __name__ == "__main__":
+ apt_pkg.init_config()
+ sources = SourcesList()
+
+ for entry in sources:
+ logging.info("entry %s" % entry.str())
+ # print entry.uri
+
+ mirror = is_mirror(
+ "http://archive.ubuntu.com/ubuntu/", "http://de.archive.ubuntu.com/ubuntu/"
+ )
+ logging.info("is_mirror(): %s" % mirror)
+
+ logging.info(
+ is_mirror(
+ "http://archive.ubuntu.com/ubuntu", "http://de.archive.ubuntu.com/ubuntu/"
+ )
+ )
+ logging.info(
+ is_mirror(
+ "http://archive.ubuntu.com/ubuntu/", "http://de.archive.ubuntu.com/ubuntu"
+ )
+ )
diff --git a/data/templates/Blankon.info.in b/data/templates/Blankon.info.in
new file mode 100644
index 0000000..f27c65b
--- /dev/null
+++ b/data/templates/Blankon.info.in
@@ -0,0 +1,370 @@
+ChangelogURI: http://arsip.blankonlinux.or.id/blankon/changelogs/pool/%s/%s/%s/%s_%s/changelog
+
+Suite: tambora
+RepositoryType: deb
+BaseURI: http://arsip.blankonlinux.or.id/blankon/
+MatchURI: arsip.blankonlinux.or.id/blankon
+MirrorsFile-amd64: Blankon.mirrors
+MirrorsFile-i386: Blankon.mirrors
+_Description: Blankon 10.0 'Tambora'
+Component: main
+_CompDescription: Officially supported
+_CompDescriptionLong: Blankon-supported Free/Open Source software
+Component: extras
+_CompDescription: Community-maintained
+_CompDescriptionLong: Community-maintained Free/Open Source software
+Component: restricted
+_CompDescription: Non-free drivers
+_CompDescriptionLong: Proprietary drivers for devices
+Component: extras-restricted
+_CompDescription: Restricted software
+_CompDescriptionLong: Software restricted by copyright or legal issues
+
+Suite: tambora
+MatchName: .*
+BaseURI: cdrom:\[Blankon.*10.0
+MatchURI: cdrom:\[Blankon.*10.0
+_Description: CDROM with Blankon 10.0 'Tambora'
+Available: False
+Component: main
+_CompDescription: Officially supported
+Component: restricted
+_CompDescription: Restricted copyright
+
+Suite: tambora-security
+ParentSuite: tambora
+RepositoryType: deb
+BaseURI: http://arsip.blankonlinux.or.id/blankon/
+MatchURI: arsip.blankonlinux.or.id/blankon
+_Description: Important security updates
+
+Suite: tambora-updates
+ParentSuite: tambora
+RepositoryType: deb
+_Description: Recommended updates
+
+Suite: suroboyo
+RepositoryType: deb
+BaseURI: http://arsip.blankonlinux.or.id/blankon/
+MatchURI: arsip.blankonlinux.or.id/blankon
+MirrorsFile-amd64: Blankon.mirrors
+MirrorsFile-i386: Blankon.mirrors
+_Description: Blankon 9.0 'Suroboyo'
+Component: main
+_CompDescription: Officially supported
+_CompDescriptionLong: Blankon-supported Free/Open Source software
+Component: extras
+_CompDescription: Community-maintained
+_CompDescriptionLong: Community-maintained Free/Open Source software
+Component: restricted
+_CompDescription: Non-free drivers
+_CompDescriptionLong: Proprietary drivers for devices
+Component: extras-restricted
+_CompDescription: Restricted software
+_CompDescriptionLong: Software restricted by copyright or legal issues
+
+Suite: suroboyo
+MatchName: .*
+BaseURI: cdrom:\[Blankon.*9.0
+MatchURI: cdrom:\[Blankon.*9.0
+_Description: CDROM with Blankon 9.0 'Suroboyo'
+Available: False
+Component: main
+_CompDescription: Officially supported
+Component: restricted
+_CompDescription: Restricted copyright
+
+Suite: suroboyo-security
+ParentSuite: suroboyo
+RepositoryType: deb
+BaseURI: http://arsip.blankonlinux.or.id/blankon/
+MatchURI: arsip.blankonlinux.or.id/blankon
+_Description: Important security updates
+
+Suite: suroboyo-updates
+ParentSuite: suroboyo
+RepositoryType: deb
+_Description: Recommended updates
+
+Suite: rote
+RepositoryType: deb
+BaseURI: http://arsip.blankonlinux.or.id/blankon/
+MatchURI: arsip.blankonlinux.or.id/blankon
+MirrorsFile-amd64: Blankon.mirrors
+MirrorsFile-i386: Blankon.mirrors
+_Description: Blankon 8.0 'Rote'
+Component: main
+_CompDescription: Officially supported
+_CompDescriptionLong: Blankon-supported Free/Open Source software
+Component: extras
+_CompDescription: Community-maintained
+_CompDescriptionLong: Community-maintained Free/Open Source software
+Component: restricted
+_CompDescription: Non-free drivers
+_CompDescriptionLong: Proprietary drivers for devices
+Component: extras-restricted
+_CompDescription: Restricted software
+_CompDescriptionLong: Software restricted by copyright or legal issues
+
+Suite: rote
+MatchName: .*
+BaseURI: cdrom:\[Blankon.*8.0
+MatchURI: cdrom:\[Blankon.*8.0
+_Description: CDROM with Blankon 8.0 'Rote'
+Available: False
+Component: main
+_CompDescription: Officially supported
+Component: restricted
+_CompDescription: Restricted copyright
+
+Suite: rote-security
+ParentSuite: rote
+RepositoryType: deb
+BaseURI: http://arsip.blankonlinux.or.id/blankon/
+MatchURI: arsip.blankonlinux.or.id/blankon
+_Description: Important security updates
+
+Suite: rote-updates
+ParentSuite: rote
+RepositoryType: deb
+_Description: Recommended updates
+
+Suite: pattimura
+RepositoryType: deb
+BaseURI: http://arsip.blankonlinux.or.id/blankon-legacy/
+MatchURI: arsip.blankonlinux.or.id/blankon-legacy
+MirrorsFile-amd64: Blankon.mirrors
+MirrorsFile-i386: Blankon.mirrors
+_Description: Blankon 7.0 'Pattimura'
+Component: main
+_CompDescription: Officially supported
+_CompDescriptionLong: Blankon-supported Free/Open Source software
+Component: extras
+_CompDescription: Community-maintained
+_CompDescriptionLong: Community-maintained Free/Open Source software
+Component: restricted
+_CompDescription: Non-free drivers
+_CompDescriptionLong: Proprietary drivers for devices
+Component: extras-restricted
+_CompDescription: Restricted software
+_CompDescriptionLong: Software restricted by copyright or legal issues
+
+Suite: pattimura
+MatchName: .*
+BaseURI: cdrom:\[Blankon.*7.0
+MatchURI: cdrom:\[Blankon.*7.0
+_Description: CDROM with Blankon 7.0 'Pattimura'
+Available: False
+Component: main
+_CompDescription: Officially supported
+Component: restricted
+_CompDescription: Restricted copyright
+
+Suite: pattimura-security
+ParentSuite: pattimura
+RepositoryType: deb
+BaseURI: http://arsip.blankonlinux.or.id/blankon-legacy/
+MatchURI: arsip.blankonlinux.or.id/blankon-legacy
+_Description: Important security updates
+
+Suite: pattimura-updates
+ParentSuite: pattimura
+RepositoryType: deb
+_Description: Recommended updates
+
+Suite: ombilin
+RepositoryType: deb
+BaseURI: http://arsip.blankonlinux.or.id/blankon-legacy/
+MatchURI: arsip.blankonlinux.or.id/blankon-legacy
+MirrorsFile-amd64: Blankon.mirrors
+MirrorsFile-i386: Blankon.mirrors
+_Description: Blankon 6.0 'Ombilin'
+Component: main
+_CompDescription: Officially supported
+_CompDescriptionLong: Blankon-supported Free/Open Source software
+Component: extras
+_CompDescription: Community-maintained
+_CompDescriptionLong: Community-maintained Free/Open Source software
+Component: restricted
+_CompDescription: Non-free drivers
+_CompDescriptionLong: Proprietary drivers for devices
+Component: extras-restricted
+_CompDescription: Restricted software
+_CompDescriptionLong: Software restricted by copyright or legal issues
+
+Suite: ombilin
+MatchName: .*
+BaseURI: cdrom:\[Blankon.*6.0
+MatchURI: cdrom:\[Blankon.*6.0
+_Description: CDROM with Blankon 6.0 'Ombilin'
+Available: False
+Component: main
+_CompDescription: Officially supported
+Component: restricted
+_CompDescription: Restricted copyright
+
+Suite: ombilin-security
+ParentSuite: ombilin
+RepositoryType: deb
+BaseURI: http://arsip.blankonlinux.or.id/blankon-legacy/
+MatchURI: arsip.blankonlinux.or.id/blankon-legacy
+_Description: Important security updates
+
+Suite: ombilin-updates
+ParentSuite: ombilin
+RepositoryType: deb
+_Description: Recommended updates
+
+Suite: nanggar
+RepositoryType: deb
+BaseURI: http://arsip.blankonlinux.or.id/blankon-legacy/
+MatchURI: arsip.blankonlinux.or.id/blankon-legacy
+MirrorsFile-amd64: Blankon.mirrors
+MirrorsFile-i386: Blankon.mirrors
+_Description: Blankon 5.0 'Nanggar'
+Component: main
+_CompDescription: Officially supported
+_CompDescriptionLong: BlankOn-supported Open Source software
+Component: universe
+_CompDescription: Community-maintained
+_CompDescriptionLong: Community-maintained Open Source software
+Component: restricted
+_CompDescription: Non-free drivers
+_CompDescriptionLong: Proprietary drivers for devices
+Component: multiverse
+_CompDescription: Restricted software
+_CompDescriptionLong: Software restricted by copyright or legal issues
+
+Suite: nanggar
+MatchName: .*
+BaseURI: cdrom:\[Blankon.*5.0
+MatchURI: cdrom:\[Blankon.*5.0
+_Description: Cdrom with Blankon 5.0 'Nanggar'
+Available: False
+Component: main
+_CompDescription: Officially supported
+Component: restricted
+_CompDescription: Restricted copyright
+
+Suite: nanggar-security
+ParentSuite: nanggar
+RepositoryType: deb
+BaseURI: http://arsip.blankonlinux.or.id/blankon-legacy/
+MatchURI: arsip.blankonlinux.or.id/blankon-legacy
+_Description: Important security updates
+
+Suite: nanggar-updates
+ParentSuite: nanggar
+RepositoryType: deb
+_Description: Recommended updates
+
+Suite: meuligoe
+RepositoryType: deb
+BaseURI: http://arsip.blankonlinux.or.id/blankon-legacy/
+MatchURI: arsip.blankonlinux.or.id/blankon-legacy
+MirrorsFile-amd64: Blankon.mirrors
+MirrorsFile-i386: Blankon.mirrors
+_Description: Blankon 4.1 'Meuligoe'
+Component: main
+_CompDescription: Officially supported
+_CompDescriptionLong: BlankOn-supported Open Source software
+Component: restricted
+_CompDescription: Non-free drivers
+_CompDescriptionLong: Proprietary drivers for devices
+
+Suite: meuligoe
+MatchName: .*
+BaseURI: cdrom:\[Blankon.*4.1
+MatchURI: cdrom:\[Blankon.*4.1
+_Description: Cdrom with Blankon 4.1 'Meuligoe'
+Available: False
+Component: main
+_CompDescription: Officially supported
+Component: restricted
+_CompDescription: Restricted copyright
+
+Suite: meuligoe-security
+ParentSuite: meuligoe
+RepositoryType: deb
+BaseURI: http://arsip.blankonlinux.or.id/blankon-legacy/
+MatchURI: arsip.blankonlinux.or.id/blankon-legacy
+_Description: Important security updates
+
+Suite: meuligoe-updates
+ParentSuite: meuligoe
+RepositoryType: deb
+_Description: Recommended updates
+
+Suite: lontara
+RepositoryType: deb
+BaseURI: http://arsip.blankonlinux.or.id/blankon-legacy/
+MatchURI: arsip.blankonlinux.or.id/blankon-legacy
+MirrorsFile-amd64: Blankon.mirrors
+MirrorsFile-i386: Blankon.mirrors
+_Description: BlankOn 3.0 'Lontara'
+Component: main
+_CompDescription: Officially supported
+_CompDescriptionLong: BlankOn-supported Open Source software
+Component: restricted
+_CompDescription: Non-free drivers
+_CompDescriptionLong: Proprietary drivers for devices
+
+Suite: lontara
+MatchName: .*
+BaseURI: cdrom:\[Blankon.*3.0
+MatchURI: cdrom:\[Blankon.*3.0
+_Description: Cdrom with Blankon 3.0 'Lontara'
+Available: False
+Component: main
+_CompDescription: Officially supported
+Component: restricted
+_CompDescription: Restricted copyright
+
+Suite: lontara-security
+ParentSuite: lontara
+RepositoryType: deb
+BaseURI: http://arsip.blankonlinux.or.id/blankon-legacy/
+MatchURI: arsip.blankonlinux.or.id/blankon-legacy
+_Description: Important security updates
+
+Suite: lontara-updates
+ParentSuite: lontara
+RepositoryType: deb
+_Description: Recommended updates
+
+Suite: konde
+RepositoryType: deb
+BaseURI: http://arsip.blankonlinux.or.id/blankon-legacy/
+MatchURI: arsip.blankonlinux.or.id/blankon-legacy
+MirrorsFile-amd64: Blankon.mirrors
+MirrorsFile-i386: Blankon.mirrors
+_Description: Blankon 2.0 'Konde'
+Component: main
+_CompDescription: Officially supported
+_CompDescriptionLong: BlankOn-supported Open Source software
+Component: restricted
+_CompDescription: Non-free drivers
+_CompDescriptionLong: Proprietary drivers for devices
+
+Suite: konde
+MatchName: .*
+BaseURI: cdrom:\[Blankon.*2.0
+MatchURI: cdrom:\[Blankon.*2.0
+_Description: Cdrom with Blankon 2.0 'Konde'
+Available: False
+Component: main
+_CompDescription: Officially supported
+Component: restricted
+_CompDescription: Restricted copyright
+
+Suite: konde-security
+ParentSuite: konde
+RepositoryType: deb
+BaseURI: http://arsip.blankonlinux.or.id/blankon-legacy/
+MatchURI: arsip.blankonlinux.or.id/blankon-legacy
+_Description: Important security updates
+
+Suite: konde-updates
+ParentSuite: konde
+RepositoryType: deb
+_Description: Recommended updates
diff --git a/data/templates/Blankon.mirrors b/data/templates/Blankon.mirrors
new file mode 100644
index 0000000..f277c03
--- /dev/null
+++ b/data/templates/Blankon.mirrors
@@ -0,0 +1,17 @@
+#LOC:ID
+http://kambing.ui.ac.id/blankon/
+http://mirror.omadata.com/blankon/
+http://repo.ugm.ac.id/repo/blankon/
+http://buaya.klas.or.id/blankon/
+http://bos.fkip.uns.ac.id/blankon
+http://pandawa.ipb.ac.id/blankon/
+http://dl2.foss-id.web.id/blankon/
+http://shol.vlsm.org/blankon/
+http://openstorage.gunadarma.ac.id/blankon/
+http://debian.rab.co.id/blankon/
+http://singo.ub.ac.id/blankon/
+http://ftp.paudni.kemdiknas.go.id/blankon/
+http://blankon.idrepo.or.id/blankon/
+http://mirror.kioss.undip.ac.id/blankon/
+http://repo.unnes.ac.id/repo/blankon/
+http://kartolo.sby.datautama.net.id/blankon/
diff --git a/data/templates/Debian.info.in b/data/templates/Debian.info.in
new file mode 100644
index 0000000..bc86a5e
--- /dev/null
+++ b/data/templates/Debian.info.in
@@ -0,0 +1,119 @@
+_ChangelogURI: https://metadata.ftp-master.debian.org/changelogs/%s/%s/%s/%s_%s_changelog
+X-Exclude-Suites: buzz, rex, bo, hamm, slink, potato, woody, experimental
+
+Suite: {series}
+RepositoryType: deb
+BaseURI: https://deb.debian.org/debian/
+MatchURI: ((http|https|ftp)[0-9]*\.([a-z]*\.){{0,1}}|deb\.|httpredir\.)debian\.org
+MirrorsFile: Debian.mirrors
+_Description: Debian {version} '{codename}'
+Component: main
+_CompDescription: Officially supported
+Component: contrib
+_CompDescription: DFSG-compatible Software with Non-Free Dependencies
+Component: non-free-firmware
+_CompDescription: Non-DFSG-compatible Firmware for Hardware Support
+Component: non-free
+_CompDescription: Non-DFSG-compatible Software
+X-Version: ge 12
+
+Suite: {series}
+RepositoryType: deb
+BaseURI: https://deb.debian.org/debian/
+MatchURI: ((http|https|ftp)[0-9]*\.([a-z]*\.){{0,1}}|deb\.|httpredir\.)debian\.org
+MirrorsFile: Debian.mirrors
+_Description: Debian {version} '{codename}'
+Component: main
+_CompDescription: Officially supported
+Component: contrib
+_CompDescription: DFSG-compatible Software with Non-Free Dependencies
+Component: non-free
+_CompDescription: Non-DFSG-compatible Software
+X-Version: le 11
+
+Suite: {series}-security
+RepositoryType: deb
+BaseURI: https://security.debian.org/
+MatchURI: security\.debian\.org
+ParentSuite: {series}
+_Description: Security updates
+X-Version: ge 11
+
+Suite: {series}/updates
+RepositoryType: deb
+BaseURI: https://security.debian.org/
+MatchURI: security\.debian\.org
+ParentSuite: {series}
+_Description: Security updates
+X-Version: le 10
+
+Suite: {series}-updates
+RepositoryType: deb
+ParentSuite: {series}
+_Description: Recommended updates
+X-Version: ge 7
+
+Suite: {series}-proposed-updates
+RepositoryType: deb
+ParentSuite: {series}
+_Description: Proposed updates
+
+Suite: stable
+RepositoryType: deb
+BaseURI: https://deb.debian.org/debian/
+MatchURI: ((http|https|ftp)[0-9]*\.([a-z]*\.){0,1}|deb\.|httpredir\.)debian\.org
+MirrorsFile: Debian.mirrors
+_Description: Debian current stable release
+Component: main
+_CompDescription: Officially supported
+Component: contrib
+_CompDescription: DFSG-compatible Software with Non-Free Dependencies
+Component: non-free-firmware
+_CompDescription: Non-DFSG-compatible Firmware for Hardware Support
+Component: non-free
+_CompDescription: Non-DFSG-compatible Software
+
+Suite: testing
+RepositoryType: deb
+BaseURI: https://deb.debian.org/debian/
+MatchURI: ((http|https|ftp)[0-9]*\.([a-z]*\.){0,1}|deb\.|httpredir\.)debian\.org
+MirrorsFile: Debian.mirrors
+_Description: Debian testing
+Component: main
+_CompDescription: Officially supported
+Component: contrib
+_CompDescription: DFSG-compatible Software with Non-Free Dependencies
+Component: non-free-firmware
+_CompDescription: Non-DFSG-compatible Firmware for Hardware Support
+Component: non-free
+_CompDescription: Non-DFSG-compatible Software
+
+Suite: sid
+RepositoryType: deb
+BaseURI: https://deb.debian.org/debian/
+MatchURI: ((http|https|ftp)[0-9]*\.([a-z]*\.){0,1}|deb\.|httpredir\.)debian\.org
+MirrorsFile: Debian.mirrors
+_Description: Debian 'Sid' (unstable)
+Component: main
+_CompDescription: Officially supported
+Component: contrib
+_CompDescription: DFSG-compatible Software with Non-Free Dependencies
+Component: non-free-firmware
+_CompDescription: Non-DFSG-compatible Firmware for Hardware Support
+Component: non-free
+_CompDescription: Non-DFSG-compatible Software
+
+Suite: unstable
+RepositoryType: deb
+BaseURI: https://deb.debian.org/debian/
+MatchURI: ((http|https|ftp)[0-9]*\.([a-z]*\.){0,1}|deb\.|httpredir\.)debian\.org
+MirrorsFile: Debian.mirrors
+_Description: Debian 'Sid' (unstable)
+Component: main
+_CompDescription: Officially supported
+Component: contrib
+_CompDescription: DFSG-compatible Software with Non-Free Dependencies
+Component: non-free-firmware
+_CompDescription: Non-DFSG-compatible Firmware for Hardware Support
+Component: non-free
+_CompDescription: Non-DFSG-compatible Software
diff --git a/data/templates/Debian.mirrors b/data/templates/Debian.mirrors
new file mode 100644
index 0000000..fdb09f1
--- /dev/null
+++ b/data/templates/Debian.mirrors
@@ -0,0 +1,394 @@
+#LOC:AM
+http://ftp.am.debian.org/debian/
+http://mirrors.asnet.am/debian/
+#LOC:AR
+http://debian.unnoba.edu.ar/debian/
+#LOC:AT
+http://debian.anexia.at/debian/
+http://debian.lagis.at/debian/
+http://debian.mur.at/debian/
+http://debian.sil.at/debian/
+http://ftp.at.debian.org/debian/
+http://ftp.tu-graz.ac.at/mirror/debian/
+http://mirror.alwyzon.net/debian/
+#LOC:AU
+http://debian.mirror.digitalpacific.com.au/debian/
+http://ftp.au.debian.org/debian/
+http://mirror.aarnet.edu.au/debian/
+http://mirror.amaze.com.au/debian/
+http://mirror.gsl.icu/debian/
+http://mirror.linux.org.au/debian/
+http://mirror.overthewire.com.au/debian/
+http://mirror.realcompute.io/debian/
+http://mirrors.xtom.au/debian/
+#LOC:BE
+http://ftp.be.debian.org/debian/
+http://ftp.belnet.be/debian/
+http://mirror.as35701.net/debian/
+#LOC:BG
+http://debian.a1.bg/debian/
+http://debian.ludost.net/debian/
+http://debian.mnet.bg/debian/
+http://debian.telecoms.bg/debian/
+http://ftp.bg.debian.org/debian/
+http://ftp.uni-sofia.bg/debian/
+http://mirror.telepoint.bg/debian/
+http://mirrors.netix.net/debian/
+#LOC:BR
+http://alcateia.ufscar.br/debian/
+http://debian.c3sl.ufpr.br/debian/
+http://ftp.br.debian.org/debian/
+http://mirror.uepg.br/debian/
+#LOC:BY
+http://ftp.by.debian.org/debian/
+http://ftp.byfly.by/debian/
+http://mirror.datacenter.by/debian/
+#LOC:CA
+http://debian.mirror.iweb.ca/debian/
+http://mirror.csclub.uwaterloo.ca/debian/
+http://mirror.dst.ca/debian/
+http://mirror.estone.ca/debian/
+http://mirror.it.ubc.ca/debian/
+http://mirror01-pcl-ott1.accuris.ca/debian/
+#LOC:CH
+http://debian.ethz.ch/debian/
+http://ftp.ch.debian.org/debian/
+http://mirror.init7.net/debian/
+http://mirror.iway.ch/debian/
+http://mirror.sinavps.ch/debian/
+http://mirror1.infomaniak.com/debian/
+http://mirror2.infomaniak.com/debian/
+http://pkg.adfinis.com/debian/
+#LOC:CL
+http://debian.redlibre.cl/debian/
+http://ftp.cl.debian.org/debian/
+http://mirror.hnd.cl/debian/
+http://mirror.insacom.cl/debian/
+http://mirror.ufro.cl/debian/
+#LOC:CN
+http://ftp.cn.debian.org/debian/
+http://mirror.nju.edu.cn/debian/
+http://mirror.nyist.edu.cn/debian/
+http://mirror.sjtu.edu.cn/debian/
+http://mirrors.163.com/debian/
+http://mirrors.bfsu.edu.cn/debian/
+http://mirrors.huaweicloud.com/debian/
+http://mirrors.jlu.edu.cn/debian/
+http://mirrors.neusoft.edu.cn/debian/
+http://mirrors.tuna.tsinghua.edu.cn/debian/
+http://mirrors.ustc.edu.cn/debian/
+http://mirrors.zju.edu.cn/debian/
+#LOC:CR
+http://debianmirror.una.ac.cr/debian/
+#LOC:CZ
+http://debian.mirror.web4u.cz/
+http://debian.superhosting.cz/debian/
+http://ftp.cvut.cz/debian/
+http://ftp.cz.debian.org/debian/
+http://ftp.debian.cz/debian/
+http://ftp.sh.cvut.cz/debian/
+http://ftp.zcu.cz/debian/
+http://merlin.fit.vutbr.cz/debian/
+http://mirror-prg.webglobe.com/debian/
+http://mirror.dkm.cz/debian/
+http://mirror.it4i.cz/debian/
+http://mirrors.nic.cz/debian/
+#LOC:DE
+http://artfiles.org/debian/
+http://de.mirrors.clouvider.net/debian/
+http://debian.charite.de/debian/
+http://debian.inf.tu-dresden.de/debian/
+http://debian.intergenia.de/debian/
+http://debian.mirror.iphh.net/debian/
+http://debian.mirror.lrz.de/debian/
+http://debian.netcologne.de/debian/
+http://debian.tu-bs.de/debian/
+http://ftp-stud.hs-esslingen.de/debian/
+http://ftp.de.debian.org/debian/
+http://ftp.fau.de/debian/
+http://ftp.gwdg.de/debian/
+http://ftp.hosteurope.de/mirror/ftp.debian.org/debian/
+http://ftp.plusline.net/debian/
+http://ftp.tu-chemnitz.de/debian/
+http://ftp.tu-clausthal.de/debian/
+http://ftp.uni-bayreuth.de/debian/
+http://ftp.uni-hannover.de/debian/debian/
+http://ftp.uni-kl.de/debian/
+http://ftp.uni-mainz.de/debian/
+http://ftp.wrz.de/debian/
+http://mirror.23m.com/debian/
+http://mirror.de.leaseweb.net/debian/
+http://mirror.dogado.de/debian/
+http://mirror.eu.oneandone.net/debian/
+http://mirror.informatik.tu-freiberg.de/debian/
+http://mirror.ipb.de/debian/
+http://mirror.netzwerge.de/debian/
+http://mirror.united-gameserver.de/debian/
+http://mirror.wtnet.de/debian/
+http://mirrors.xtom.de/debian/
+http://packages.hs-regensburg.de/debian/
+http://pubmirror.plutex.de/debian/
+#LOC:DK
+http://ftp.dk.debian.org/debian/
+http://mirror.asergo.com/debian/
+http://mirror.one.com/debian/
+http://mirrors.dotsrc.org/debian/
+http://mirrors.rackhosting.com/debian/
+#LOC:EE
+http://mirrors.xtom.ee/debian/
+#LOC:ES
+http://debian.grn.cat/debian/
+http://debian.redimadrid.es/debian/
+http://debian.redparra.com/debian/
+http://debian.uvigo.es/debian/
+http://ftp.caliu.cat/debian/
+http://ftp.cica.es/debian/
+http://ftp.es.debian.org/debian/
+http://ftp.udc.es/debian/
+http://repo.ifca.es/debian/
+http://softlibre.unizar.es/debian/
+http://ulises.hostalia.com/debian/
+#LOC:FI
+http://ftp.fi.debian.org/debian/
+http://www.nic.funet.fi/debian/
+#LOC:FR
+http://deb-mir1.naitways.net/debian/
+http://debian.apt-mirror.de/debian/
+http://debian.obspm.fr/debian/
+http://debian.polytech-lille.fr/debian/
+http://debian.proxad.net/debian/
+http://debian.univ-tlse2.fr/debian/
+http://ftp.ec-m.fr/debian/
+http://ftp.fr.debian.org/debian/
+http://ftp.lip6.fr/pub/linux/distributions/debian/
+http://ftp.rezopole.net/debian/
+http://ftp.u-picardie.fr/debian/
+http://ftp.u-strasbg.fr/debian/
+http://ftp.univ-pau.fr/linux/mirrors/debian/
+http://miroir.univ-lorraine.fr/debian/
+http://mirror.gitoyen.net/debian/
+http://mirror.ibcp.fr/debian/
+http://mirror.johnnybegood.fr/debian/
+http://mirror.plusserver.com/debian/debian/
+http://mirrors.ircam.fr/pub/debian/
+#LOC:GB
+http://debian.mirror.uk.sargasso.net/debian/
+http://debian.mirrors.uk2.net/debian/
+http://free.hands.com/debian/
+http://ftp.ticklers.org/debian/
+http://ftp.uk.debian.org/debian/
+http://mirror.cov.ukservers.com/debian/
+http://mirror.lchost.net/debian/
+http://mirror.mythic-beasts.com/debian/
+http://mirror.ox.ac.uk/debian/
+http://mirror.positive-internet.com/debian/
+http://mirror.sov.uk.goscomb.net/debian/
+http://mirror.vinehost.net/debian/
+http://mirrors.coreix.net/debian/
+http://mirrorservice.org/sites/ftp.debian.org/debian/
+http://uk.mirrors.clouvider.net/debian/
+http://ukdebian.mirror.anlx.net/debian/
+#LOC:GE
+http://debian.grena.ge/debian/
+#LOC:GR
+http://debian.otenet.gr/debian/
+#LOC:HK
+http://ftp.hk.debian.org/debian/
+http://mirror.xtom.com.hk/debian/
+#LOC:HR
+http://debian.carnet.hr/debian/
+http://debian.iskon.hr/debian/
+http://ftp.hr.debian.org/debian/
+#LOC:HU
+http://ftp.bme.hu/debian/
+http://repo.jztkft.hu/debian/
+#LOC:ID
+http://kartolo.sby.datautama.net.id/debian/
+http://kebo.pens.ac.id/debian/
+http://mirror.poliwangi.ac.id/debian/
+http://mirror.unair.ac.id/debian/
+http://mr.heru.id/debian/
+#LOC:IL
+http://debian.interhost.co.il/debian/
+#LOC:IN
+http://mirrors.iitd.ac.in/debian/
+#LOC:IR
+http://debian.hostiran.ir/debian/
+http://debian.parspack.com/debian/
+#LOC:IS
+http://ftp.is.debian.org/debian/
+http://is.mirror.flokinet.net/debian/
+#LOC:IT
+http://debian.dynamica.it/debian/
+http://debian.mirror.garr.it/debian/
+http://ftp.it.debian.org/debian/
+http://ftp.linux.it/debian/
+http://giano.com.dist.unige.it/debian/
+http://mirror.units.it/debian/
+#LOC:JP
+http://debian-mirror.sakura.ne.jp/debian/
+http://ftp.jp.debian.org/debian/
+http://ftp.kddilabs.jp/pub/debian/
+http://ftp.nara.wide.ad.jp/debian/
+http://ftp.riken.jp/Linux/debian/debian/
+http://mirrors.xtom.jp/debian/
+http://repo.jing.rocks/debian/
+#LOC:KE
+http://debian.mirror.ac.ke/debian/
+http://debian.mirror.liquidtelecom.com/debian/
+#LOC:KR
+http://ftp.kaist.ac.kr/debian/
+http://ftp.kr.debian.org/debian/
+http://mirror.siwoo.org/debian/
+#LOC:KZ
+http://mirror.hoster.kz/debian/
+http://mirror.ps.kz/debian/
+#LOC:LT
+http://debian.balt.net/debian/
+http://debian.mirror.vu.lt/debian/
+http://ftp.lt.debian.org/debian/
+http://mirror.litnet.lt/debian/
+http://mirror.vpsnet.com/debian/
+#LOC:LU
+http://debian.mirror.root.lu/debian/
+#LOC:LV
+http://debian.koyanet.lv/debian/
+http://mirror.cloudhosting.lv/debian/
+#LOC:MA
+http://mirror.marwan.ma/debian/
+#LOC:MD
+http://ftp.md.debian.org/debian/
+http://mirror.as43289.net/debian/
+#LOC:MK
+http://mirror-mk.interspace.com/debian/
+http://mirror.onevip.mk/debian/
+#LOC:NC
+http://debian.nautile.nc/debian/
+http://ftp.nc.debian.org/debian/
+http://mirror.lagoon.nc/debian/
+#LOC:NL
+http://debian.snt.utwente.nl/debian/
+http://ftp.nl.debian.org/debian/
+http://mirror.duocast.net/debian/
+http://mirror.i3d.net/debian/
+http://mirror.nl.datapacket.com/debian/
+http://mirror.nl.leaseweb.net/debian/
+http://mirror.seedvps.com/debian/
+http://mirrors.hostiserver.com/debian/
+http://mirrors.xtom.nl/debian/
+http://nl.mirrors.clouvider.net/debian/
+#LOC:NO
+http://ftp.no.debian.org/debian/
+http://ftp.uio.no/debian/
+#LOC:NZ
+http://ftp.nz.debian.org/debian/
+http://linux.purple-cat.net/debian/
+http://mirror.fsmg.org.nz/debian/
+#LOC:PL
+http://debian.inhost.pro/debian/
+http://ftp.agh.edu.pl/debian/
+http://ftp.icm.edu.pl/pub/Linux/debian/
+http://ftp.pl.debian.org/debian/
+http://ftp.psnc.pl/debian/
+http://ftp.task.gda.pl/debian/
+#LOC:PT
+http://debian.uevora.pt/debian/
+http://ftp.eq.uc.pt/software/Linux/debian/
+http://ftp.pt.debian.org/debian/
+http://mirrors.ptisp.pt/debian/
+http://mirrors.up.pt/debian/
+#LOC:RE
+http://debian.mithril.re/debian/
+http://depot-debian.univ-reunion.fr/debian/
+#LOC:RO
+http://mirror.linux.ro/debian/
+http://mirrors.hostico.ro/debian/
+http://mirrors.nav.ro/debian/
+http://mirrors.nxthost.com/debian/
+http://ro.mirror.flokinet.net/debian/
+#LOC:RU
+http://ftp.psn.ru/debian/
+http://ftp.ru.debian.org/debian/
+http://mirror.corbina.net/debian/
+http://mirror.docker.ru/debian/
+http://mirror.hyperdedic.ru/debian/
+http://mirror.mephi.ru/debian/
+http://mirrors.powernet.com.ru/debian/
+#LOC:SE
+http://debian.lth.se/debian/
+http://debian.mirror.su.se/debian/
+http://ftp.acc.umu.se/debian/
+http://ftp.se.debian.org/debian/
+http://ftpmirror1.infania.net/debian/
+http://mirror.zetup.net/debian/
+http://mirrors.glesys.net/debian/
+#LOC:SG
+http://mirror.coganng.com/debian/
+http://ossmirror.mycloud.services/debian/
+#LOC:SI
+http://ftp.si.debian.org/debian/
+#LOC:SK
+http://deb.bbxnet.sk/debian/
+http://ftp.antik.sk/debian/
+http://ftp.debian.sk/debian/
+http://ftp.sk.debian.org/debian/
+#LOC:TH
+http://ftp.debianclub.org/debian/
+http://mirror.applebred.net/debian/
+http://mirror.kku.ac.th/debian/
+#LOC:TR
+http://debian.gnu.gen.tr/debian/
+http://ftp.linux.org.tr/debian/
+http://ftp.tr.debian.org/debian/
+#LOC:TW
+http://debian.cs.nycu.edu.tw/debian/
+http://debian.csie.ntu.edu.tw/debian/
+http://ftp.tku.edu.tw/debian/
+http://ftp.tw.debian.org/debian/
+http://opensource.nchc.org.tw/debian/
+http://tw1.mirror.blendbyte.net/debian/
+#LOC:UA
+http://debian.netforce.hosting/debian/
+http://debian.volia.net/debian/
+http://fastmirror.pp.ua/debian/
+http://mirror.mirohost.net/debian/
+http://mirror.ukrnames.com/debian/
+#LOC:US
+http://atl.mirrors.clouvider.net/debian/
+http://debian-archive.trafficmanager.net/debian/
+http://debian.cc.lehigh.edu/debian/
+http://debian.cs.binghamton.edu/debian/
+http://debian.csail.mit.edu/debian/
+http://debian.mirror.constant.com/debian/
+http://debian.osuosl.org/debian/
+http://debian.uchicago.edu/debian/
+http://ftp.us.debian.org/debian/
+http://la.mirrors.clouvider.net/debian/
+http://mirror.0x626b.com/debian/
+http://mirror.clarkson.edu/debian/
+http://mirror.cogentco.com/debian/
+http://mirror.dal.nexril.net/debian/
+http://mirror.keystealth.org/debian/
+http://mirror.rustytel.net/debian/
+http://mirror.siena.edu/debian/
+http://mirror.steadfast.net/debian/
+http://mirror.us.leaseweb.net/debian/
+http://mirror.us.oneandone.net/debian/
+http://mirrors.accretive-networks.net/debian/
+http://mirrors.lug.mtu.edu/debian/
+http://mirrors.namecheap.com/debian/
+http://mirrors.ocf.berkeley.edu/debian/
+http://mirrors.vcea.wsu.edu/debian/
+http://mirrors.wikimedia.org/debian/
+http://mirrors.xtom.com/debian/
+http://nyc.mirrors.clouvider.net/debian/
+http://plug-mirror.rcac.purdue.edu/debian/
+http://repo.ialab.dsu.edu/debian/
+#LOC:UY
+http://debian.repo.cure.edu.uy/debian/
+#LOC:VN
+http://mirror.bizflycloud.vn/debian/
+http://mirrors.bkns.vn/debian/
+#LOC:ZA
+http://debian.saix.net/
+http://ftp.is.co.za/debian/
diff --git a/data/templates/Kali.info.in b/data/templates/Kali.info.in
new file mode 100644
index 0000000..d817c53
--- /dev/null
+++ b/data/templates/Kali.info.in
@@ -0,0 +1,32 @@
+_ChangelogURI: http://pkg.kali.org/media/packages/%s/%s/%s/%s/changelog-%s
+
+Suite: kali-rolling
+RepositoryType: deb
+BaseURI: http://http.kali.org/kali/
+MatchURI: (kali\.download|(archive.*|http)\.kali\.org)
+MirrorsFile: Kali.mirrors
+_Description: Kali Rolling
+Component: main
+_CompDescription: Officially supported
+Component: contrib
+_CompDescription: DFSG-compatible Software with Non-Free Dependencies
+Component: non-free
+_CompDescription: Non-DFSG-compatible Software
+
+Suite: kali-dev
+RepositoryType: deb
+BaseURI: http://http.kali.org/kali/
+MatchURI: (kali\.download|(archive.*|http)\.kali\.org)
+MirrorsFile: Kali.mirrors
+_Description: Kali Development Release
+Component: main
+_CompDescription: Officially supported
+Component: contrib
+_CompDescription: DFSG-compatible Software with Non-Free Dependencies
+Component: non-free
+_CompDescription: Non-DFSG-compatible Software
+
+Suite: kali-experimental
+RepositoryType: deb
+ParentSuite: kali-dev
+_Description: Kali Experimental Release
diff --git a/data/templates/Kali.mirrors b/data/templates/Kali.mirrors
new file mode 100644
index 0000000..419fb1e
--- /dev/null
+++ b/data/templates/Kali.mirrors
@@ -0,0 +1,2 @@
+http://http.kali.org/kali/
+http://kali.download/kali/
diff --git a/data/templates/README.templates b/data/templates/README.templates
new file mode 100644
index 0000000..276b674
--- /dev/null
+++ b/data/templates/README.templates
@@ -0,0 +1,59 @@
+Channel Definition
+------------------
+
+The .info files allow to specify a set of default channels that is available
+in the dialog "add channel". The .info file whose name corresponds to the
+LSB release name is used, e.g. 'Ubuntu.info' on a Ubuntu system.
+
+Furthermore all .info files are used to render the channels presented in the
+sources list more user friendly.
+
+Abstract paragraphs
+-------------------
+If the Suite name contains a {, the entire paragraph becomes a template
+that gets formatted with distro-info-data data. See the Ubuntu.info.in
+and Debian.info.in for examples.
+
+Note that in such a case, if these paragraphs use { in their values for
+non-template things, such as in regular expressions; they need to be
+escaped - { to {{ and } to }}.
+
+Abstract paragraphs can only be in the middle of the file, the head and the
+tail are copied unmodified. If abstract paragraphs are interleaved with
+concrete ones, the behavior is undefined.
+
+Tags
+----
+
+Suite: the name of the dist used in the repository
+
+MatchSuite: mainly used for cdroms. defaults to Suite
+
+ParentSuite: the channel only appears as a component of the parent suite in
+ the add dialog
+ the components/sections of the suite correspond to the ones of
+ the parent suite. specified components of the suite itself
+ are ignored
+
+Available: determs the availabilty of the suite in the add dialog.
+ defaults to False
+
+RepositoryType: does the repository contain binary or source packages
+
+BaseURI: the base URI of the repository
+
+MatchURI: used for identifing mirrors
+
+Description: description of the suite. the translation is done through
+ gettext at runtime
+
+Component: a component/section of the suite (ignored if ParentSuite is
+ set)
+
+CompDescription: humand readable description of the component/section
+ (ignored if ParentSuite is set). the translation is done
+ through gettext at runtime
+
+ValidMirros: A file that contains a list of mirrors
+
+
diff --git a/data/templates/Tanglu.info.in b/data/templates/Tanglu.info.in
new file mode 100644
index 0000000..df37083
--- /dev/null
+++ b/data/templates/Tanglu.info.in
@@ -0,0 +1,42 @@
+_ChangelogURI: http://changelogs.tanglu.org/changelogs/%s/%s/%s/%s_%s/changelog
+
+Suite: aequorea
+RepositoryType: deb
+BaseURI: http://archive.tanglu.org/tanglu/
+MatchURI: archive.tanglu.org/tanglu
+MirrorsFile: Tanglu.mirrors
+_Description: Tanglu 1.0 'Aequorea'
+Component: main
+_CompDescription: Officially supported
+Component: contrib
+_CompDescription: DFSG-compatible Software with Non-Free Dependencies
+Component: non-free
+_CompDescription: Non-DFSG-compatible Software
+
+Suite: aequorea-updates
+RepositoryType: deb
+ParentSuite: aequorea
+_Description: Recommended updates
+
+Suite: bartholomea
+RepositoryType: deb
+BaseURI: http://archive.tanglu.org/tanglu/
+MatchURI: archive.tanglu.org/tanglu
+MirrorsFile: Tanglu.mirrors
+_Description: Tanglu 2.0 'Bartholomea'
+Component: main
+_CompDescription: Officially supported
+Component: contrib
+_CompDescription: DFSG-compatible Software with Non-Free Dependencies
+Component: non-free
+_CompDescription: Non-DFSG-compatible Software
+
+Suite: bartholomea-security
+RepositoryType: deb
+ParentSuite: bartholomea
+_Description: Security updates
+
+Suite: bartholomea-updates
+RepositoryType: deb
+ParentSuite: bartholomea
+_Description: Recommended updates
diff --git a/data/templates/Tanglu.mirrors b/data/templates/Tanglu.mirrors
new file mode 100644
index 0000000..dd8ab42
--- /dev/null
+++ b/data/templates/Tanglu.mirrors
@@ -0,0 +1,3 @@
+#LOC:DE
+http://de.archive.tanglu.org/tanglu/
+http://mirror1.hs-esslingen.de/pub/Mirrors/archive.tanglu.org/tanglu/
diff --git a/data/templates/Ubuntu.info.in b/data/templates/Ubuntu.info.in
new file mode 100644
index 0000000..72c8955
--- /dev/null
+++ b/data/templates/Ubuntu.info.in
@@ -0,0 +1,223 @@
+_ChangelogURI: http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog
+
+Suite: devel
+RepositoryType: deb
+BaseURI: http://ports.ubuntu.com/ubuntu-ports/
+MatchURI: ports.ubuntu.com/ubuntu-ports
+BaseURI-amd64: http://archive.ubuntu.com/ubuntu
+MatchURI-amd64: archive.ubuntu.com/ubuntu
+BaseURI-i386: http://archive.ubuntu.com/ubuntu
+MatchURI-i386: archive.ubuntu.com/ubuntu
+MirrorsFile-amd64: Ubuntu.mirrors
+MirrorsFile-i386: Ubuntu.mirrors
+_Description: Ubuntu development series
+Component: main
+_CompDescription: Officially supported
+_CompDescriptionLong: Canonical-supported free and open-source software
+Component: universe
+_CompDescription: Community-maintained
+_CompDescriptionLong: Community-maintained free and open-source software
+Component: restricted
+_CompDescription: Non-free drivers
+_CompDescriptionLong: Proprietary drivers for devices
+Component: multiverse
+ParentComponent: universe
+_CompDescription: Restricted software
+_CompDescriptionLong: Software restricted by copyright or legal issues
+
+Suite: devel
+ParentSuite: devel
+RepositoryType: deb-src
+BaseURI: http://archive.ubuntu.com/ubuntu/
+MatchURI: archive.ubuntu.com/ubuntu|ports.ubuntu.com/ubuntu-ports
+_Description: Ubuntu development series
+
+Suite: devel
+Official: false
+RepositoryType: deb
+BaseURI: http://extras.ubuntu.com
+MatchURI: extras.ubuntu.com
+_Description: Independent
+Component: main
+_CompDescription: Provided by third-party software developers
+_CompDescriptionLong: Software offered by third party developers.
+
+Suite: devel-security
+ParentSuite: devel
+RepositoryType: deb
+BaseURI: http://ports.ubuntu.com/ubuntu-ports/
+MatchURI: ports.ubuntu.com/ubuntu-ports
+BaseURI-amd64: http://security.ubuntu.com/ubuntu/
+MatchURI-amd64: archive.ubuntu.com/ubuntu|security.ubuntu.com
+BaseURI-i386: http://security.ubuntu.com/ubuntu/
+MatchURI-i386: archive.ubuntu.com/ubuntu|security.ubuntu.com
+_Description: Important security updates
+
+Suite: devel-security
+ParentSuite: devel
+RepositoryType: deb-src
+BaseURI: http://archive.ubuntu.com/ubuntu/
+MatchURI: archive.ubuntu.com/ubuntu|ports.ubuntu.com/ubuntu-ports|security.ubuntu.com
+_Description: Important security updates
+
+Suite: devel-updates
+ParentSuite: devel
+RepositoryType: deb
+_Description: Recommended updates
+
+Suite: devel-updates
+ParentSuite: devel
+RepositoryType: deb-src
+BaseURI: http://archive.ubuntu.com/ubuntu/
+MatchURI: archive.ubuntu.com/ubuntu|ports.ubuntu.com/ubuntu-ports
+_Description: Recommended updates
+
+Suite: devel-proposed
+ParentSuite: devel
+RepositoryType: deb
+_Description: Pre-released updates
+
+Suite: devel-proposed
+ParentSuite: devel
+RepositoryType: deb-src
+BaseURI: http://archive.ubuntu.com/ubuntu/
+MatchURI: archive.ubuntu.com/ubuntu|ports.ubuntu.com/ubuntu-ports
+_Description: Pre-released updates
+
+Suite: devel-backports
+ParentSuite: devel
+RepositoryType: deb
+_Description: Unsupported updates
+
+Suite: devel-backports
+ParentSuite: devel
+RepositoryType: deb-src
+BaseURI: http://archive.ubuntu.com/ubuntu/
+MatchURI: archive.ubuntu.com/ubuntu|ports.ubuntu.com/ubuntu-ports
+_Description: Unsupported updates
+
+Suite: {series}
+RepositoryType: deb
+BaseURI: http://ports.ubuntu.com/ubuntu-ports/
+MatchURI: ports.ubuntu.com/ubuntu-ports
+BaseURI-amd64: http://archive.ubuntu.com/ubuntu
+MatchURI-amd64: archive.ubuntu.com/ubuntu
+BaseURI-i386: http://archive.ubuntu.com/ubuntu
+MatchURI-i386: archive.ubuntu.com/ubuntu
+MirrorsFile-amd64: Ubuntu.mirrors
+MirrorsFile-i386: Ubuntu.mirrors
+_Description: Ubuntu {version} '{codename}'
+Component: main
+_CompDescription: Officially supported
+_CompDescriptionLong: Canonical-supported free and open-source software
+Component: universe
+_CompDescription: Community-maintained
+_CompDescriptionLong: Community-maintained free and open-source software
+Component: restricted
+_CompDescription: Non-free drivers
+_CompDescriptionLong: Proprietary drivers for devices
+Component: multiverse
+ParentComponent: universe
+_CompDescription: Restricted software
+_CompDescriptionLong: Software restricted by copyright or legal issues
+
+Suite: {series}
+ParentSuite: {series}
+RepositoryType: deb-src
+BaseURI: http://archive.ubuntu.com/ubuntu/
+MatchURI: archive.ubuntu.com/ubuntu|ports.ubuntu.com/ubuntu-ports
+_Description: Ubuntu {version} '{codename}'
+X-Version: ge 11.04
+
+Suite: {series}
+RepositoryType: deb
+MatchName: .*
+BaseURI: cdrom:\[Ubuntu.*{version}
+MatchURI: cdrom:\[Ubuntu.*{version}
+_Description: Installation medium with Ubuntu {version} '{codename}'
+Available: False
+Component: main
+_CompDescription: Officially supported
+Component: restricted
+_CompDescription: Restricted copyright
+
+Suite: {series}
+Official: false
+RepositoryType: deb
+BaseURI: http://archive.canonical.com
+MatchURI: archive.canonical.com
+_Description: Canonical Partners
+Component: partner
+_CompDescription: Software packaged by Canonical for their partners
+_CompDescriptionLong: This software is not part of Ubuntu.
+X-Version: le 20.04, ge 10.10
+
+Suite: {series}
+Official: false
+RepositoryType: deb
+BaseURI: http://extras.ubuntu.com
+MatchURI: extras.ubuntu.com
+_Description: Independent
+Component: main
+_CompDescription: Provided by third-party software developers
+_CompDescriptionLong: Software offered by third party developers.
+X-Version: le 15.04, ge 10.10
+
+Suite: {series}-security
+ParentSuite: {series}
+RepositoryType: deb
+BaseURI: http://ports.ubuntu.com/ubuntu-ports/
+MatchURI: ports.ubuntu.com/ubuntu-ports
+BaseURI-amd64: http://security.ubuntu.com/ubuntu/
+MatchURI-amd64: archive.ubuntu.com/ubuntu|security.ubuntu.com
+BaseURI-i386: http://security.ubuntu.com/ubuntu/
+MatchURI-i386: archive.ubuntu.com/ubuntu|security.ubuntu.com
+_Description: Important security updates
+
+Suite: {series}-security
+ParentSuite: {series}
+RepositoryType: deb-src
+BaseURI: http://archive.ubuntu.com/ubuntu/
+MatchURI: archive.ubuntu.com/ubuntu|ports.ubuntu.com/ubuntu-ports|security.ubuntu.com
+_Description: Important security updates
+X-Version: ge 11.04
+
+Suite: {series}-updates
+ParentSuite: {series}
+RepositoryType: deb
+_Description: Recommended updates
+
+Suite: {series}-updates
+ParentSuite: {series}
+RepositoryType: deb-src
+BaseURI: http://archive.ubuntu.com/ubuntu/
+MatchURI: archive.ubuntu.com/ubuntu|ports.ubuntu.com/ubuntu-ports
+_Description: Recommended updates
+X-Version: ge 11.04
+
+Suite: {series}-proposed
+ParentSuite: {series}
+RepositoryType: deb
+_Description: Pre-released updates
+
+Suite: {series}-proposed
+ParentSuite: {series}
+RepositoryType: deb-src
+BaseURI: http://archive.ubuntu.com/ubuntu/
+MatchURI: archive.ubuntu.com/ubuntu|ports.ubuntu.com/ubuntu-ports
+_Description: Pre-released updates
+X-Version: ge 11.04
+
+Suite: {series}-backports
+ParentSuite: {series}
+RepositoryType: deb
+_Description: Unsupported updates
+
+Suite: {series}-backports
+ParentSuite: {series}
+RepositoryType: deb-src
+BaseURI: http://archive.ubuntu.com/ubuntu/
+MatchURI: archive.ubuntu.com/ubuntu|ports.ubuntu.com/ubuntu-ports
+_Description: Unsupported updates
+X-Version: ge 11.04
+
diff --git a/data/templates/Ubuntu.mirrors b/data/templates/Ubuntu.mirrors
new file mode 100644
index 0000000..651b069
--- /dev/null
+++ b/data/templates/Ubuntu.mirrors
@@ -0,0 +1,665 @@
+mirror://mirrors.ubuntu.com/mirrors.txt
+#LOC:AM
+http://mirrors.asnet.am/ubuntu/
+http://ubuntu.mirror.gnc.am/ubuntu/
+#LOC:AR
+http://ubuntu.unc.edu.ar/ubuntu/
+https://mirror.sitsa.com.ar/ubuntu/
+https://mirrors.dc.clear.net.ar/ubuntu/
+https://ubuntu.zero.com.ar/ubuntu/
+#LOC:AT
+http://mirror.easyname.at/ubuntu-archive/
+http://ubuntu.lagis.at/ubuntu/
+http://ubuntu.uni-klu.ac.at/ubuntu/
+https://mirror.alwyzon.net/ubuntu/
+https://ubuntu.anexia.at/ubuntu/
+#LOC:AU
+http://ftp.iinet.net.au/pub/ubuntu/
+http://mirror.aarnet.edu.au/pub/ubuntu/archive/
+http://mirror.internode.on.net/pub/ubuntu/ubuntu/
+http://mirror.netspace.net.au/pub/ubuntu/
+http://mirror.overthewire.com.au/ubuntu/
+https://mirror.datamossa.io/ubuntu/archive/
+https://mirror.gsl.icu/ubuntu/
+https://mirror.internet.asn.au/pub/ubuntu/archive/
+https://mirror.realcompute.io/ubuntu/
+https://ubuntu.mirror.digitalpacific.com.au/archive/
+https://ubuntu.mirror.serversaustralia.com.au/ubuntu/
+#LOC:AZ
+http://aze.archive.ubuntu.com/ubuntu/
+http://mirror.datacenter.az/ubuntu/
+#LOC:BA
+http://archive.ubuntu.mirror.ba/ubuntu/
+#LOC:BD
+https://mirror.xeonbd.com/ubuntu-archive/
+#LOC:BE
+http://ftp.belnet.be/ubuntu/
+http://mirror.unix-solutions.be/ubuntu/
+https://mirrors-ubuntu.behostings.com/ubuntu/
+#LOC:BG
+http://mirror.bg.host.ag/ubuntu/
+http://mirrors.neterra.net/ubuntu/
+http://ubuntu.ipacct.com/ubuntu/
+https://mirror.telepoint.bg/ubuntu/
+https://mirrors.storpool.com/ubuntu/archive/
+#LOC:BR
+http://mirror.ufam.edu.br/ubuntu/
+http://mirror.ufscar.br/ubuntu/
+http://mirror.unesp.br/ubuntu/
+http://sft.if.usp.br/ubuntu/
+http://ubuntu-archive.locaweb.com.br/ubuntu/
+http://ubuntu.c3sl.ufpr.br/ubuntu/
+http://ubuntu.mti.mt.gov.br/
+https://mirror.uepg.br/ubuntu/
+https://ubuntu.letscloud.io/ubuntu/
+#LOC:BW
+http://mirror.retentionrange.co.bw/ubuntu/
+#LOC:BY
+http://ftp.byfly.by/ubuntu/
+http://mirror.datacenter.by/ubuntu/
+#LOC:CA
+http://archive.ubuntu.mirror.rafal.ca/ubuntu/
+http://mirror.ca-tr.kamatera.com/ubuntu/
+http://mirror.its.dal.ca/ubuntu/
+http://mirror.rcg.sfu.ca/mirror/ubuntu/
+http://mirrors.layeronline.com/ubuntu/
+http://ubuntu.mirror.globo.tech/
+http://ubuntu.mirror.rafal.ca/ubuntu/
+https://gpl.savoirfairelinux.net/pub/mirrors/ubuntu/
+https://mirror.0xem.ma/ubuntu/
+https://mirror.csclub.uwaterloo.ca/ubuntu/
+https://mirror.digitaloceans.dev/ubuntu/
+https://mirror.hep.gg/ubuntu/
+https://mirror.it.ubc.ca/ubuntu/
+https://mirror.reenigne.net/ubuntu/
+https://mirror01-pcl-ott1.accuris.ca/ubuntu/
+https://muug.ca/mirror/ubuntu/
+#LOC:CD
+https://mirrors.united.cd/ubuntu/
+#LOC:CH
+http://archive.ubuntu.csg.uzh.ch/ubuntu/
+http://mirror.infomaniak.ch/ubuntu/
+http://pkg.adfinis.com/ubuntu/
+http://ubuntu.ethz.ch/ubuntu/
+https://mirror.init7.net/ubuntu/
+https://mirror.solnet.ch/ubuntu/
+#LOC:CL
+http://mirror.uchile.cl/ubuntu/
+https://mirror.hnd.cl/ubuntu/
+https://mirror.ufro.cl/ubuntu/
+#LOC:CN
+http://ftp.sjtu.edu.cn/ubuntu/
+http://mirror.lzu.edu.cn/ubuntu/
+http://mirrors.aliyun.com/ubuntu/
+http://mirrors.cn99.com/ubuntu/
+http://mirrors.cqu.edu.cn/ubuntu/
+http://mirrors.huaweicloud.com/repository/ubuntu/
+http://mirrors.sohu.com/ubuntu/
+http://mirrors.yun-idc.com/ubuntu/
+https://mirror.nju.edu.cn/ubuntu/
+https://mirror.nyist.edu.cn/ubuntu/
+https://mirrors.bfsu.edu.cn/ubuntu/
+https://mirrors.bupt.edu.cn/ubuntu/
+https://mirrors.cloud.tencent.com/ubuntu/
+https://mirrors.jlu.edu.cn/ubuntu/
+https://mirrors.jxust.edu.cn/ubuntu/
+https://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports/
+https://mirrors.tuna.tsinghua.edu.cn/ubuntu/
+https://mirrors.ustc.edu.cn/ubuntu/
+https://mirrors.xjtu.edu.cn/ubuntu/
+https://mirrors.zju.edu.cn/ubuntu/
+https://repo.huaweicloud.com/ubuntu/
+#LOC:CO
+http://mirror.unimagdalena.edu.co/ubuntu/
+https://edgeuno-bog2.mm.fcix.net/ubuntu/
+#LOC:CR
+http://ubuntu.ucr.ac.cr/ubuntu/
+#LOC:CY
+http://mirror.library.ucy.ac.cy/linux/ubuntu/archive/
+#LOC:CZ
+http://ftp.cvut.cz/ubuntu/
+http://ftp.linux.cz/pub/linux/ubuntu/
+http://ucho.ignum.cz/ubuntu/
+https://cz.archive.ubuntu.com/ubuntu/
+https://ftp.sh.cvut.cz/ubuntu/
+https://mirror.dkm.cz/ubuntu/
+https://mirror.it4i.cz/ubuntu/
+#LOC:DE
+ftp://ftp.fu-berlin.de/linux/ubuntu/
+ftp://ftp.rrzn.uni-hannover.de/pub/mirror/linux/ubuntu
+http://artfiles.org/ubuntu.com/
+http://ftp-stud.hs-esslingen.de/ubuntu/
+http://ftp.fau.de/ubuntu/
+http://ftp.halifax.rwth-aachen.de/ubuntu/
+http://ftp.hosteurope.de/mirror/archive.ubuntu.com/
+http://ftp.rrzn.uni-hannover.de/pub/mirror/linux/ubuntu/
+http://ftp.rz.tu-bs.de/pub/mirror/ubuntu-packages/
+http://ftp.stw-bonn.de/ubuntu/
+http://ftp.tu-chemnitz.de/pub/linux/ubuntu-ports/
+http://ftp.tu-chemnitz.de/pub/linux/ubuntu/
+http://ftp.tu-ilmenau.de/mirror/ubuntu/
+http://ftp.uni-bayreuth.de/linux/ubuntu/ubuntu/
+http://ftp.uni-kl.de/pub/linux/ubuntu/
+http://ftp.uni-mainz.de/ubuntu/
+http://ftp5.gwdg.de/pub/linux/debian/ubuntu/
+http://mirror.daniel-jost.net/ubuntu/
+http://mirror.eu-fr.kamatera.com/ubuntu/
+http://mirror.funkfreundelandshut.de/ubuntu/
+http://mirror.ipb.de/ubuntu/
+http://mirror.kamp.de/ubuntu/
+http://mirror.serverloft.eu/ubuntu/ubuntu/
+http://mirror.wtnet.de/ubuntu/
+http://mirror2.tuxinator.org/ubuntu/
+http://packages.oth-regensburg.de/ubuntu/
+http://suse.uni-leipzig.de/pub/releases.ubuntu.com/ubuntu/
+http://ubuntu.mirror.lrz.de/ubuntu/
+http://ubuntu.mirror.tudos.de/ubuntu/
+https://de.mirrors.clouvider.net/ubuntu/
+https://debian.charite.de/ubuntu/
+https://drmirror.physi.uni-heidelberg.de/ubuntu/
+https://ftp.uni-stuttgart.de/ubuntu/
+https://mirror.23m.com/ubuntu/
+https://mirror.creoline.net/ubuntu/
+https://mirror.de.leaseweb.net/ubuntu/
+https://mirror.dogado.de/ubuntu/
+https://mirror.informatik.tu-freiberg.de/ubuntu/
+https://mirror.kkg.berlin/ubuntu/
+https://mirror.netcologne.de/ubuntu/
+https://mirror.netzwerge.de/ubuntu/
+https://mirror.scaleuptech.com/ubuntu/
+https://mirror.united-gameserver.de/ubuntu/
+https://mirrors.xtom.de/ubuntu/
+#LOC:DK
+http://ftp.klid.dk/ftp/ubuntu/
+http://mirror.one.com/ubuntu/
+http://mirrors.dotsrc.org/ubuntu/
+https://mirror.asergo.com/ubuntu/
+https://mirror.netsite.dk/ubuntu/archive/
+https://mirrors.c0urier.net/linux/ubuntu/
+#LOC:EC
+http://mirror.cedia.org.ec/ubuntu/
+http://mirror.espol.edu.ec/ubuntu/
+#LOC:EE
+https://mirrors.xtom.ee/ubuntu/
+#LOC:ES
+http://dafi.inf.um.es/ubuntu/
+http://ftp.caliu.cat/pub/distribucions/ubuntu/archive/
+http://ftp.udc.es/ubuntu/
+http://mirror.tedra.es/ubuntu/
+http://softlibre.unizar.es/ubuntu/archive/
+http://ubuntu.cica.es/ubuntu/
+http://ubuntu.grn.cat/ubuntu/
+https://ftp.csuc.cat/ubuntu/archive/
+https://labs.eif.urjc.es/mirror/ubuntu/
+https://ubuntu.uvigo.es/
+#LOC:FI
+http://mirrors.nic.funet.fi/ubuntu/
+https://mirror.5i.fi/ubuntu/
+#LOC:FR
+http://distrib-coffee.ipsl.jussieu.fr/pub/linux/ubuntu/
+http://miroir.univ-lorraine.fr/ubuntu/
+http://mirror.plusserver.com/ubuntu/ubuntu/
+http://mirrors.ircam.fr/pub/ubuntu/archive/
+http://ubuntu.mirror.serverloft.de/ubuntu/
+http://ubuntu.univ-nantes.fr/ubuntu/
+http://ubuntu.univ-reims.fr/ubuntu/
+https://ftp.u-picardie.fr/mirror/ubuntu/ubuntu/
+https://mirror.johnnybegood.fr/ubuntu/
+https://mirror.ubuntu.ikoula.com/
+https://ubuntu.lafibre.info/ubuntu/
+https://ubuntu.mirrors.ovh.net/ubuntu/
+https://www-ftp.lip6.fr/pub/linux/distributions/Ubuntu/archive/
+#LOC:GB
+http://archive.ubuntu.com/ubuntu/
+http://mirror.as29550.net/archive.ubuntu.com/
+http://mirror.bytemark.co.uk/ubuntu/
+http://mirror.cov.ukservers.com/ubuntu/
+http://mirror.eu-lo.kamatera.com/ubuntu/
+http://mirror.freethought-internet.co.uk/ubuntu/
+http://mirror.mythic-beasts.com/ubuntu/
+http://mirror.ox.ac.uk/sites/archive.ubuntu.com/ubuntu/
+http://mirror.sov.uk.goscomb.net/ubuntu/
+http://mirror.vorboss.net/ubuntu-archive/
+http://mirrors.coreix.net/ubuntu/
+http://mirrors.melbourne.co.uk/ubuntu/
+http://mirrors.ukfast.co.uk/sites/archive.ubuntu.com/
+http://ubuntu.mirrors.uk2.net/ubuntu/
+http://ubuntu.positive-internet.com/ubuntu/
+http://www.mirrorservice.org/sites/archive.ubuntu.com/ubuntu/
+https://mirror.vinehost.net/ubuntu/
+https://mirrors.gethosted.online/ubuntu/
+https://uk.mirrors.clouvider.net/ubuntu/
+#LOC:GE
+http://ubuntu.grena.ge/ubuntu/
+#LOC:GL
+http://mirror.greennet.gl/ubuntu/
+#LOC:GR
+http://ftp.cc.uoc.gr/mirrors/linux/ubuntu/packages/
+http://ftp.ntua.gr/ubuntu/
+http://ubuntu.otenet.gr/
+#LOC:HK
+http://mirror-hk.koddos.net/ubuntu/
+http://mirror.as.kamatera.com/ubuntu/
+https://mirror.xtom.com.hk/ubuntu/
+#LOC:HR
+http://ubuntu.grad.hr/ubuntu/
+#LOC:HU
+http://repo.jztkft.hu/ubuntu/
+https://mirror.niif.hu/ubuntu/
+https://mirrors.sth.sze.hu/ubuntu/
+https://quantum-mirror.hu/mirrors/pub/ubuntu/
+#LOC:ID
+http://kartolo.sby.datautama.net.id/ubuntu/
+http://kebo.pens.ac.id/ubuntu/
+http://mirror.biznetgio.com/ubuntu/
+http://mirror.cepatcloud.id/ubuntu/
+http://mirror.cloudxchange.id/ubuntu/
+http://mirror.deace.id/ubuntu/
+http://mirror.poliwangi.ac.id/ubuntu/
+http://mirror.unej.ac.id/ubuntu/
+http://repo.ugm.ac.id/ubuntu/
+http://suro.ubaya.ac.id/ubuntu/
+https://buaya.klas.or.id/ubuntu/
+https://cdn.repo.cloudeka.id/ubuntu/
+https://cdn.ubuntu.repo.cloudeka.id/ubuntu/
+https://linux.domainesia.com/ubuntu/ubuntu-archive/
+https://mirror.amscloud.co.id/ubuntu/
+https://mirror.citrahost.com/ubuntu/
+https://mirror.faizuladib.com/ubuntu/
+https://mirror.gi.co.id/ubuntu/
+https://mirror.nevacloud.com/ubuntu/ubuntu-archive/
+https://mirror.papua.go.id/ubuntu/
+https://mirror.repository.id/ubuntu/
+https://mirror.unair.ac.id/ubuntu/
+https://mirrors.idcloudhost.com/ubuntu/
+https://mr.heru.id/ubuntu/
+https://repo.usk.ac.id/ubuntu/
+https://sby.mirror.bignet.id/ubuntu/
+#LOC:IE
+http://ftp.heanet.ie/pub/ubuntu/
+https://mirror.webworld.ie/ubuntu/
+#LOC:IL
+http://mirror.il-jr.kamatera.com/ubuntu/
+http://mirror.il-pt.kamatera.com/ubuntu/
+http://mirror.il-rh.kamatera.com/ubuntu/
+http://mirror.il-ta.kamatera.com/ubuntu/
+http://mirror.il.kamatera.com/ubuntu/
+http://mirror.isoc.org.il/pub/ubuntu/
+http://rep-ubuntu-il.upress.io/ubuntu/
+https://ubuntu-archive.interhost.co.il/ubuntu/
+#LOC:IN
+http://ftp.iitm.ac.in/ubuntu/
+http://mirror.cse.iitk.ac.in/ubuntu/
+http://mirrors.iitd.ac.in/ubuntu/
+http://mirrors.piconets.webwerks.in/ubuntu-mirror/ubuntu/
+http://repos.del.extreme-ix.org/ubuntu/
+https://in.mirror.coganng.com/ubuntu-ports/
+https://in.mirror.coganng.com/ubuntu/
+https://mirror.nitc.ac.in/ubuntu/
+https://mirrors.nxtgen.com/ubuntu-mirror/ubuntu/
+https://repo.extreme-ix.org/ubuntu/
+https://ubuntu-archive.mirror.net.in/
+https://ubuntu-ports.mirror.net.in/
+#LOC:IR
+http://linuxmirrors.ir/pub/ubuntu/
+http://mirror.aminidc.com/ubuntu/
+http://mirror.faraso.org/ubuntu/
+http://repo.iut.ac.ir/repo/Ubuntu/
+http://ubuntu.byteiran.com/ubuntu/
+https://archive.ubuntu.petiak.ir/ubuntu/
+https://ir.archive.ubuntu.com/ubuntu/
+https://ir.ubuntu.sindad.cloud/ubuntu/
+https://mirror.0-1.cloud/ubuntu/
+https://mirror.iranserver.com/ubuntu/
+https://mirror.rasanegar.com/ubuntu/
+https://mirrors.pardisco.co/ubuntu/
+https://ubuntu-mirror.kimiahost.com/
+https://ubuntu.bardia.tech/
+https://ubuntu.hostiran.ir/ubuntuarchive/
+https://ubuntu.shatel.ir/ubuntu/
+#LOC:IS
+http://ubuntu.hysing.is/ubuntu/
+https://is.mirror.flokinet.net/ubuntu/
+https://mirrors.opensource.is/ubuntu/
+#LOC:IT
+http://giano.com.dist.unige.it/ubuntu/
+https://it1.mirror.vhosting-it.com/ubuntu/
+https://it2.mirror.vhosting-it.com/ubuntu/
+https://ubuntu.mirror.garr.it/ubuntu/
+#LOC:JP
+http://archive.g4t1.pro/ubuntu/
+http://ftp.jaist.ac.jp/pub/Linux/ubuntu/
+http://ftp.riken.jp/Linux/ubuntu/
+http://ftp.tsukuba.wide.ad.jp/Linux/ubuntu/
+http://ubuntutym.u-toyama.ac.jp/ubuntu/
+http://www.ftp.ne.jp/Linux/packages/ubuntu/archive/
+https://ftp.udx.icscoe.jp/Linux/ubuntu/
+https://jp.mirror.coganng.com/ubuntu-ports/
+https://jp.mirror.coganng.com/ubuntu/
+https://linux.yz.yamagata-u.ac.jp/ubuntu/
+https://mirror.nishi.network/ubuntu-ports/
+https://mirror.nishi.network/ubuntu/
+https://repo.jing.rocks/ubuntu-ports/
+https://repo.jing.rocks/ubuntu/
+#LOC:KG
+http://mir.linux.kg/ubuntu/
+#LOC:KH
+https://mirror.sabay.com.kh/ubuntu/
+#LOC:KR
+http://ftp.daum.net/ubuntu/
+https://ftp.kaist.ac.kr/ubuntu-ports/
+https://ftp.kaist.ac.kr/ubuntu/
+https://ftp.lanet.kr/ubuntu-ports/
+https://ftp.lanet.kr/ubuntu/
+https://mirror.elice.io/ubuntu/
+https://mirror.kakao.com/ubuntu/
+https://mirror.morgan.kr/ubuntu/
+https://mirror.siwoo.org/ubuntu/
+https://mirror.yuki.net.uk/ubuntu-ports/
+https://mirror.yuki.net.uk/ubuntu/
+#LOC:KZ
+http://mirror.hoster.kz/ubuntu/
+http://mirror.neolabs.kz/ubuntu/
+http://mirror.ps.kz/ubuntu/
+#LOC:LT
+http://ftp.litnet.lt/ubuntu/
+http://ubuntu-archive.mirror.serveriai.lt/
+http://ubuntu.mirror.vu.lt/ubuntu/
+https://mirror.vpsnet.com/ubuntu/
+#LOC:LU
+http://ubuntu.mirror.root.lu/ubuntu/
+#LOC:LV
+http://mirror.cloudhosting.lv/ubuntu/
+http://ubuntu-arch.linux.edu.lv/ubuntu/
+http://ubuntu.koyanet.lv/ubuntu/
+#LOC:MA
+https://mirror.marwan.ma/ubuntu/
+#LOC:MD
+http://mirror.as43289.net/ubuntu/
+http://mirrors.mivocloud.com/ubuntu/
+https://mirror.ihost.md/ubuntu/
+#LOC:MG
+http://ubuntu.dts.mg/ubuntu/
+#LOC:MK
+http://mirror-mk.interspace.com/ubuntu/
+http://mirror.onevip.mk/ubuntu/
+http://mirror.t-home.mk/ubuntu/
+#LOC:MM
+https://mirror.ygn.mmix.net.mm/ubuntu/
+#LOC:MN
+http://mirror.datacenter.mn/ubuntu/
+#LOC:MU
+https://ubuntu-mirror.cloud.mu/ubuntu-ports/
+https://ubuntu-mirror.cloud.mu/ubuntu/
+#LOC:MY
+http://ubuntu.tuxuri.com/ubuntu/
+https://mirrors.gbnetwork.com/ubuntu/
+https://mirrors.ipserverone.com/ubuntu/
+#LOC:NA
+http://download.nust.na/pub/ubuntu/ubuntu/
+#LOC:NC
+http://archive.ubuntu.nautile.nc/ubuntu/
+http://ubuntu.lagoon.nc/ubuntu/
+#LOC:NL
+ftp://ftpserv.tudelft.nl/pub/Linux/archive.ubuntu.com/
+http://ftp.nluug.nl/os/Linux/distr/ubuntu/
+http://ftp.snt.utwente.nl/pub/os/linux/ubuntu/
+http://ftp.tudelft.nl/archive.ubuntu.com/
+http://mirror.eu.kamatera.com/ubuntu/
+http://mirror.hostnet.nl/ubuntu/archive/
+http://mirror.i3d.net/pub/ubuntu/
+http://mirror.nforce.com/pub/linux/ubuntu/
+http://mirror.nl.datapacket.com/ubuntu/
+http://mirror.previder.nl/ubuntu/
+http://mirror.serverion.com/ubuntu/
+http://mirror.serverius.net/ubuntu/
+http://mirror.transip.net/ubuntu/ubuntu/
+http://mirror.vpgrp.io/ubuntu/
+http://nl.archive.ubuntu.com/ubuntu/
+http://nl3.archive.ubuntu.com/ubuntu/
+http://osmirror.rug.nl/ubuntu/
+http://ubuntu.mirror.true.nl/ubuntu/
+https://mirror.lyrahosting.com/ubuntuarchive/
+https://mirror.nl.altushost.com/ubuntu/
+https://mirror.nl.leaseweb.net/ubuntu/
+https://mirrors.evoluso.com/ubuntu/
+https://mirrors.hostiserver.com/ubuntu/
+https://mirrors.xtom.nl/ubuntu/
+https://nl.mirrors.clouvider.net/ubuntu/
+https://ubuntu.mirror.intermax.nl/
+https://ubuntu.mirror.wearetriple.com/archive/
+#LOC:NO
+http://ftp.uninett.no/ubuntu/
+http://no.archive.ubuntu.com/ubuntu/
+http://no.mirrors.blix.com/ubuntu/
+http://ubuntu.uib.no/archive/
+https://ubuntu.hi.no/archive/
+#LOC:NP
+http://ntc.net.np/ubuntu/
+#LOC:NZ
+http://ubuntu.mirrors.theom.nz/
+http://ucmirror.canterbury.ac.nz/ubuntu/
+https://mirror.2degrees.nz/ubuntu/
+https://mirror.fsmg.org.nz/ubuntu/
+#LOC:PH
+http://mirror.rise.ph/ubuntu/
+#LOC:PL
+http://ftp.agh.edu.pl/ubuntu/
+http://ftp.vectranet.pl/ubuntu/
+http://mirror.chmuri.net/ubuntu/
+http://ubuntu.man.lodz.pl/ubuntu/
+http://ubuntu.task.gda.pl/ubuntu/
+https://ftp.psnc.pl/linux/ubuntu/
+#LOC:PR
+http://mirrors.upr.edu/ubuntu/
+#LOC:PT
+http://archive.ubuntumirror.dei.uc.pt/ubuntu/
+http://cesium.di.uminho.pt/pub/ubuntu-archive/
+http://ftp.rnl.tecnico.ulisboa.pt/pub/ubuntu/archive/
+http://glua.ua.pt/pub/ubuntu/
+http://mirrors.up.pt/ubuntu/
+https://mirrors.ptisp.pt/ubuntu/
+#LOC:RO
+http://mirrors.nxthost.com/ubuntu/
+http://mirrors.pidginhost.com/ubuntu/
+http://ubuntu.mirrors.linux.ro/archive/
+https://mirror.efect.ro/ubuntu/archive/
+https://mirror.flokinet.net/ubuntu/
+https://mirrors.chroot.ro/ubuntu/
+https://mirrors.hosterion.ro/ubuntu/
+https://mirrors.hostico.ro/ubuntu/archive/
+https://mirrors.layerbridge.com/ubuntu/
+https://mirrors.nav.ro/ubuntu/
+https://ubuntu-mirror.magnetic-it.com/ubuntu/
+https://ubuntu.mirrors.orange.ro/ubuntu/
+#LOC:RS
+http://mirror1.sox.rs/ubuntu/ubuntu/
+https://mirror1.sox.rs/ubuntu/ubuntu/
+#LOC:RU
+http://mirror.corbina.net/ubuntu/
+http://mirror.docker.ru/ubuntu/
+http://mirror.logol.ru/ubuntu/
+http://mirror.timeweb.ru/ubuntu/
+http://mirror.yandex.ru/ubuntu/
+http://mirrors.powernet.com.ru/ubuntu/
+https://mirror.hyperdedic.ru/ubuntu/
+https://mirror.linux-ia64.org/ubuntu/
+https://mirror.neftm.ru/ubuntu/
+https://mirror.truenetwork.ru/ubuntu/
+#LOC:SA
+https://mirrors.isu.net.sa/apt-mirror/
+#LOC:SE
+http://ftp.acc.umu.se/ubuntu/
+http://ftp.lysator.liu.se/ubuntu/
+http://mirror.zetup.net/ubuntu/
+http://ubuntu.mirror.su.se/ubuntu/
+https://ftpmirror1.infania.net/ubuntu/
+https://mirror.bahnhof.net/ubuntu/
+#LOC:SG
+http://cdn.0ms.dev/ubuntu/
+http://download.nus.edu.sg/mirror/ubuntu/
+http://mirror.aktkn.sg/ubuntu/
+http://mirror.sg.gs/ubuntu/
+http://ossmirror.mycloud.services/os/linux/ubuntu/
+https://mirror.coganng.com/ubuntu-ports/
+https://mirror.coganng.com/ubuntu/
+#LOC:SI
+http://ftp.arnes.si/pub/mirrors/ubuntu/
+#LOC:SK
+http://ftp.energotel.sk/pub/linux/ubuntu/
+http://tux.rainside.sk/ubuntu/
+https://mirror.vnet.sk/ubuntu/
+#LOC:TH
+http://ftp.psu.ac.th/pub/ubuntu/
+http://mirror.thaidns.co.th/ubuntu/
+http://mirror1.ku.ac.th/ubuntu/
+http://mirror1.totbb.net/ubuntu/
+http://mirrors.bangmod.cloud/ubuntu/
+http://mirrors.psu.ac.th/ubuntu/
+https://mirror.kku.ac.th/ubuntu/
+https://mirrors.nipa.cloud/ubuntu/
+#LOC:TR
+http://mirror.kapteyan.com.tr/ubuntu/
+http://ubuntu.turhost.com/ubuntu/
+http://ubuntu.vargonen.com/ubuntu/
+https://ftp.linux.org.tr/ubuntu/
+https://kozyatagi.mirror.guzel.net.tr/ubuntu/
+https://mirror.alastyr.com/ubuntu/ubuntu-archive/
+https://mirror.rabisu.com/ubuntu/ubuntu-archive/
+https://mirror.sh.com.tr/ubuntu/
+https://mirror.verinomi.com/ubuntu/ubuntu-archive/
+#LOC:TW
+http://free.nchc.org.tw/ubuntu/
+http://ftp.mirror.tw/pub/ubuntu/ubuntu/
+http://ftp.tku.edu.tw/ubuntu/
+http://ftp.tw.debian.org/ubuntu/
+http://mirror.nwlab.tk/ubuntu/
+http://mirror01.idc.hinet.net/ubuntu/
+http://ubuntu.cs.nctu.edu.tw/ubuntu/
+https://ftp.tc.edu.tw/Linux/ubuntu/
+https://ftp.ubuntu-tw.net/ubuntu/
+https://mirror.ossplanet.net/ubuntu/
+https://tw1.mirror.blendbyte.net/ubuntu/
+https://ubuntu.ccns.ncku.edu.tw/ubuntu/
+#LOC:TZ
+http://deb-mirror.habari.co.tz/ubuntu/
+http://mirror.aptus.co.tz/pub/ubuntuarchive/
+#LOC:UA
+http://mirror.mirohost.net/ubuntu/
+http://ubuntu.colocall.net/ubuntu/
+http://ubuntu.mirrors.omnilance.com/ubuntu/
+http://ubuntu.org.ua/ubuntu/
+http://ubuntu.volia.net/ubuntu-archive/
+https://ubuntu.ip-connect.vn.ua/
+https://ubuntu.netforce.hosting/ubuntu/
+#LOC:UG
+http://mirror.renu.ac.ug/ubuntu/
+#LOC:US
+http://archive.linux.duke.edu/ubuntu/
+http://babylon.cs.uh.edu/mirror-sites/ubuntu/
+http://ftp.usf.edu/pub/ubuntu/
+http://ftp.ussg.iu.edu/linux/ubuntu/
+http://mirror.arizona.edu/ubuntu/
+http://mirror.brightridge.com/ubuntuarchive/
+http://mirror.cc.vt.edu/pub2/ubuntu/
+http://mirror.cogentco.com/pub/linux/ubuntu/
+http://mirror.cs.jmu.edu/pub/ubuntu/
+http://mirror.math.princeton.edu/pub/ubuntu/
+http://mirror.math.ucdavis.edu/ubuntu/
+http://mirror.metrocast.net/ubuntu/
+http://mirror.mrjester.net/ubuntu/archive/
+http://mirror.nodesdirect.com/ubuntu/
+http://mirror.pit.teraswitch.com/ubuntu/
+http://mirror.rustytel.net/ubuntu/
+http://mirror.siena.edu/ubuntu/
+http://mirror.steadfastnet.com/ubuntu/
+http://mirror.team-cymru.com/ubuntu/
+http://mirror.team-cymru.org/ubuntu/
+http://mirror.umd.edu/ubuntu/
+http://mirror.uoregon.edu/ubuntu/
+http://mirror.us-midwest-1.nexcess.net/ubuntu/
+http://mirror.us-ny2.kamatera.com/ubuntu/
+http://mirror.us-sc.kamatera.com/ubuntu/
+http://mirror.us-tx.kamatera.com/ubuntu/
+http://mirror.vcu.edu/pub/gnu+linux/ubuntu/
+http://mirrors.accretive-networks.net/ubuntu/
+http://mirrors.advancedhosters.com/ubuntu/
+http://mirrors.arpnetworks.com/Ubuntu/
+http://mirrors.cat.pdx.edu/ubuntu/
+http://mirrors.cmich.edu/ubuntu/
+http://mirrors.codec-cluster.org/ubuntu/
+http://mirrors.gigenet.com/ubuntuarchive/
+http://mirrors.liquidweb.com/ubuntu/
+http://mirrors.lug.mtu.edu/ubuntu/
+http://mirrors.maine.edu/ubuntu/
+http://mirrors.mit.edu/ubuntu/
+http://mirrors.namecheap.com/ubuntu/
+http://mirrors.ocf.berkeley.edu/ubuntu/
+http://mirrors.rit.edu/ubuntu/
+http://mirrors.sonic.net/ubuntu/
+http://mirrors.syringanetworks.net/ubuntu-archive/
+http://mirrors.tripadvisor.com/ubuntu/
+http://mirrors.us.kernel.org/ubuntu/
+http://mirrors.usinternet.com/ubuntu/archive/
+http://mirrors.vcea.wsu.edu/ubuntu/
+http://mirrors.xmission.com/ubuntu/
+http://plug-mirror.rcac.purdue.edu/ubuntu/
+http://pubmirrors.dal.corespace.com/ubuntu/
+http://repo.miserver.it.umich.edu/ubuntu/
+http://ubuntu.cs.utah.edu/ubuntu/
+http://ubuntu.mirror.constant.com/
+http://ubuntu.mirror.frontiernet.net/ubuntu/
+http://ubuntu.mirrors.pair.com/archive/
+http://ubuntu.osuosl.org/ubuntu/
+http://ubuntu.phoenixnap.com/ubuntu/
+http://ubuntu.securedservers.com/
+http://www.club.cc.cmu.edu/pub/ubuntu/
+http://www.gtlib.gatech.edu/pub/ubuntu/
+https://atl.mirrors.clouvider.net/ubuntu/
+https://dal.mirrors.clouvider.net/ubuntu/
+https://la.mirrors.clouvider.net/ubuntu/
+https://lug.mines.edu/mirrors/ubuntu/
+https://mirror.clarkson.edu/ubuntu/
+https://mirror.cs.pitt.edu/ubuntu/archive/
+https://mirror.d.umn.edu/ubuntu/
+https://mirror.dal.nexril.net/ubuntu/
+https://mirror.enzu.com/ubuntu/
+https://mirror.fcix.net/ubuntu/
+https://mirror.hoobly.com/ubuntu/
+https://mirror.lstn.net/ubuntu/
+https://mirror.mia.velocihost.net/ubuntu/
+https://mirror.servaxnet.com/ubuntu/
+https://mirror.timkevin.us/ubuntu/
+https://mirror.ubuntu.serverforge.org/
+https://mirror.us.leaseweb.net/ubuntu/
+https://mirrors.bloomu.edu/ubuntu/
+https://mirrors.egr.msu.edu/ubuntu/
+https://mirrors.iu13.net/ubuntu/
+https://mirrors.ocf.berkeley.edu/ubuntu-ports/
+https://mirrors.sarak.as/ubuntu/
+https://mirrors.tscak.com/ubuntu/
+https://mirrors.wikimedia.org/ubuntu/
+https://mirrors.xtom.com/ubuntu/
+https://nyc.mirrors.clouvider.net/ubuntu/
+https://repo.ialab.dsu.edu/ubuntu/
+https://repos.eggycrew.com/ubuntu/
+https://ubuntu.macarne.com/
+https://ubuntu.mirror.shastacoe.net/ubuntu/
+#LOC:UY
+http://repos.interior.edu.uy/ubuntu/
+https://ubuntu.repo.cure.edu.uy/ubuntu/
+#LOC:UZ
+http://mirror.dc.uz/ubuntu/
+#LOC:VN
+http://mirror.bizflycloud.vn/ubuntu/
+http://mirror.clearsky.vn/ubuntu/
+http://mirror.vietnix.vn/ubuntu/
+http://mirror.viettelcloud.vn/ubuntu/
+http://mirrors.vhost.vn/ubuntu/
+http://opensource.xtdv.net/ubuntu/
+https://mirror.hostingviet.vn/ubuntu/
+https://mirrors.bkns.vn/ubuntu/
+#LOC:ZA
+http://mirror.hostafrica.co.za/ubuntu/
+http://ubuntu.mirror.ac.za/ubuntu/
+http://ubuntu.mirror.rain.co.za/ubuntu/
diff --git a/data/templates/gNewSense.info.in b/data/templates/gNewSense.info.in
new file mode 100644
index 0000000..c7636bc
--- /dev/null
+++ b/data/templates/gNewSense.info.in
@@ -0,0 +1,55 @@
+_ChangelogURI: http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog
+
+# gNS 3, to be based on Squeeze.
+Suite: parkes
+RepositoryType: deb
+BaseURI: http://archive.gnewsense.org/gnewsense/
+MatchURI: archive.gnewsense.org/gnewsense
+MirrorsFile: gNewSense.mirrors
+Description: gNewSense 3 - "parkes"
+Component: main
+_CompDescription: Main supported software
+_CompDescriptionLong: Core software
+
+Suite: parkes/updates
+RepositoryType: deb
+BaseURI: http://security.gnewsense.org/gnewsense
+MatchURI: security.gnewsense.org/security
+ParentSuite: parkes
+_Description: Security updates
+
+# gNS 2.x, based on hardy
+Suite: deltah
+RepositoryType: deb
+BaseURI: http://archive.gnewsense.org/gnewsense/
+MatchURI: archive.gnewsense.org/gnewsense
+MirrorsFile: gNewSense.mirrors
+_Description: gNewSense "deltah"
+Component: main
+_CompDescription: Main supported software
+_CompDescriptionLong: Core software
+Component: universe
+_CompDescription: Other useful software
+_CompDescriptionLong: Non-core useful software
+
+Suite: deltah-security
+ParentSuite: deltah
+RepositoryType: deb
+BaseURI: http://security.gnewsense.org/gnewsense/
+MatchURI: archive.gnewsense.org/gnewsense|security.gnewsense.org
+_Description: Important security updates
+
+Suite: deltah-updates
+ParentSuite: deltah
+RepositoryType: deb
+BaseURI: http://archive.gnewsense.org/gnewsense/
+MatchURI: archive.gnewsense.org/gnewsense
+_Description: Unsupported updates
+
+Suite: deltah-backports
+ParentSuite: deltah
+RepositoryType: deb
+BaseURI: http://archive.gnewsense.org/gnewsense/
+MatchURI: archive.gnewsense.org/gnewsense
+_Description: Package Backports
+
diff --git a/data/templates/gNewSense.mirrors b/data/templates/gNewSense.mirrors
new file mode 100644
index 0000000..7a8dbaa
--- /dev/null
+++ b/data/templates/gNewSense.mirrors
@@ -0,0 +1,489 @@
+
+#LOC:AD
+http://ad.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:AE
+http://ae.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:AF
+http://af.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:AG
+http://ag.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:AI
+http://ai.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:AL
+http://al.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:AM
+http://am.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:AN
+http://an.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:AO
+http://ao.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:AQ
+http://aq.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:AR
+http://ar.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:AS
+http://as.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:AT
+http://at.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:AU
+http://au.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:AW
+http://aw.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:AX
+http://ax.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:AZ
+http://az.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:BA
+http://ba.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:BB
+http://bb.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:BD
+http://bd.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:BE
+http://be.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:BF
+http://bf.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:BG
+http://bg.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:BH
+http://bh.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:BI
+http://bi.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:BJ
+http://bj.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:BM
+http://bm.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:BN
+http://bn.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:BO
+http://bo.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:BR
+http://br.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:BS
+http://bs.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:BT
+http://bt.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:BV
+http://bv.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:BW
+http://bw.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:BY
+http://by.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:BZ
+http://bz.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:CA
+http://ca.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:CC
+http://cc.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:CD
+http://cd.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:CF
+http://cf.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:CG
+http://cg.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:CH
+http://ch.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:CI
+http://ci.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:CK
+http://ck.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:CL
+http://cl.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:CM
+http://cm.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:CN
+http://cn.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:CO
+http://co.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:CR
+http://cr.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:CU
+http://cu.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:CV
+http://cv.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:CX
+http://cx.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:CY
+http://cy.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:CZ
+http://cz.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:DE
+http://de.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:DJ
+http://dj.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:DK
+http://dk.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:DM
+http://dm.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:DO
+http://do.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:DZ
+http://dz.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:EC
+http://ec.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:EE
+http://ee.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:EG
+http://eg.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:EH
+http://eh.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:ER
+http://er.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:ES
+http://es.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:ET
+http://et.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:FI
+http://fi.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:FJ
+http://fj.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:FK
+http://fk.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:FM
+http://fm.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:FO
+http://fo.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:FR
+http://fr.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:GA
+http://ga.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:GB
+http://gb.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:GD
+http://gd.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:GE
+http://ge.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:GF
+http://gf.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:GG
+http://gg.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:GH
+http://gh.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:GI
+http://gi.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:GL
+http://gl.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:GM
+http://gm.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:GN
+http://gn.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:GP
+http://gp.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:GQ
+http://gq.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:GR
+http://gr.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:GS
+http://gs.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:GT
+http://gt.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:GU
+http://gu.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:GW
+http://gw.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:GY
+http://gy.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:HK
+http://hk.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:HM
+http://hm.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:HN
+http://hn.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:HR
+http://hr.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:HT
+http://ht.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:HU
+http://hu.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:ID
+http://id.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:IE
+http://ie.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:IL
+http://il.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:IM
+http://im.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:IN
+http://in.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:IO
+http://io.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:IQ
+http://iq.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:IR
+http://ir.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:IS
+http://is.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:IT
+http://it.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:JE
+http://je.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:JM
+http://jm.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:JO
+http://jo.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:JP
+http://jp.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:KE
+http://ke.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:KG
+http://kg.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:KH
+http://kh.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:KI
+http://ki.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:KM
+http://km.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:KN
+http://kn.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:KP
+http://kp.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:KR
+http://kr.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:KW
+http://kw.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:KY
+http://ky.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:KZ
+http://kz.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:LA
+http://la.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:LB
+http://lb.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:LC
+http://lc.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:LI
+http://li.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:LK
+http://lk.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:LR
+http://lr.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:LS
+http://ls.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:LT
+http://lt.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:LU
+http://lu.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:LV
+http://lv.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:LY
+http://ly.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:MA
+http://ma.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:MC
+http://mc.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:MD
+http://md.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:ME
+http://me.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:MG
+http://mg.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:MH
+http://mh.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:MK
+http://mk.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:ML
+http://ml.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:MM
+http://mm.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:MN
+http://mn.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:MO
+http://mo.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:MP
+http://mp.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:MQ
+http://mq.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:MR
+http://mr.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:MS
+http://ms.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:MT
+http://mt.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:MU
+http://mu.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:MV
+http://mv.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:MW
+http://mw.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:MX
+http://mx.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:MY
+http://my.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:MZ
+http://mz.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:NA
+http://na.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:NC
+http://nc.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:NE
+http://ne.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:NF
+http://nf.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:NG
+http://ng.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:NI
+http://ni.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:NL
+http://nl.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:NO
+http://no.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:NP
+http://np.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:NR
+http://nr.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:NU
+http://nu.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:NZ
+http://nz.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:OM
+http://om.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:PA
+http://pa.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:PE
+http://pe.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:PF
+http://pf.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:PG
+http://pg.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:PH
+http://ph.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:PK
+http://pk.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:PL
+http://pl.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:PM
+http://pm.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:PN
+http://pn.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:PR
+http://pr.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:PS
+http://ps.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:PT
+http://pt.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:PW
+http://pw.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:PY
+http://py.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:QA
+http://qa.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:RE
+http://re.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:RO
+http://ro.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:RS
+http://rs.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:RU
+http://ru.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:RW
+http://rw.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:SA
+http://sa.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:SB
+http://sb.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:SC
+http://sc.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:SD
+http://sd.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:SE
+http://se.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:SG
+http://sg.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:SH
+http://sh.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:SI
+http://si.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:SJ
+http://sj.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:SK
+http://sk.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:SL
+http://sl.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:SM
+http://sm.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:SN
+http://sn.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:SO
+http://so.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:SR
+http://sr.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:ST
+http://st.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:SV
+http://sv.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:SY
+http://sy.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:SZ
+http://sz.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:TC
+http://tc.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:TD
+http://td.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:TF
+http://tf.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:TG
+http://tg.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:TH
+http://th.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:TJ
+http://tj.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:TK
+http://tk.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:TL
+http://tl.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:TM
+http://tm.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:TN
+http://tn.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:TO
+http://to.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:TR
+http://tr.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:TT
+http://tt.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:TV
+http://tv.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:TW
+http://tw.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:TZ
+http://tz.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:UA
+http://ua.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:UG
+http://ug.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:UM
+http://um.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:US
+http://us.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:UY
+http://uy.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:UZ
+http://uz.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:VA
+http://va.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:VC
+http://vc.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:VE
+http://ve.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:VG
+http://vg.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:VI
+http://vi.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:VN
+http://vn.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:VU
+http://vu.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:WF
+http://wf.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:WS
+http://ws.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:YE
+http://ye.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:YT
+http://yt.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:ZA
+http://za.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:ZM
+http://zm.archive.gnewsense.org/gnewsense-metad/gnewsense/
+#LOC:ZW
+http://zw.archive.gnewsense.org/gnewsense-metad/gnewsense/
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 0000000..327bba9
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,79 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
+
+.PHONY: help clean html web pickle htmlhelp latex changes linkcheck
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " changes to make an overview over all changed/added/deprecated items"
+ @echo " linkcheck to check all external links for integrity"
+
+clean:
+ -rm -rf build/*
+
+text:
+ mkdir -p build/text build/doctrees
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) build/text
+
+html:
+ mkdir -p build/html build/doctrees
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) build/html
+ @echo
+ @echo "Build finished. The HTML pages are in build/html."
+
+pickle:
+ mkdir -p build/pickle build/doctrees
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) build/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+web: pickle
+
+json:
+ mkdir -p build/json build/doctrees
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) build/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ mkdir -p build/htmlhelp build/doctrees
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) build/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in build/htmlhelp."
+
+latex:
+ mkdir -p build/latex build/doctrees
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) build/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in build/latex."
+ @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
+ "run these through (pdf)latex."
+
+changes:
+ mkdir -p build/changes build/doctrees
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) build/changes
+ @echo
+ @echo "The overview file is in build/changes."
+
+linkcheck:
+ mkdir -p build/linkcheck build/doctrees
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) build/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in build/linkcheck/output.txt."
diff --git a/doc/client-example.cc b/doc/client-example.cc
new file mode 100644
index 0000000..73fa3ee
--- /dev/null
+++ b/doc/client-example.cc
@@ -0,0 +1,68 @@
+/*
+ * client-example.cc - A simple example for using the python-apt C++ API.
+ *
+ * Copyright 2009 Julian Andres Klode <jak@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <python-apt/python-apt.h>
+#include <apt-pkg/hashes.h>
+
+// The module initialization.
+extern "C" void initclient() {
+ if (import_apt_pkg() < 0)
+ return;
+ // Initialize a module.
+ PyObject *Module = Py_InitModule("client", NULL);
+
+ // Create a HashString, which will be added to the module.
+ HashString *hash = new HashString("0966a120bb936bdc6fdeac445707aa6b");
+ // Create a Python object for the hashstring and add it to the module
+ PyModule_AddObject(Module, "hash", PyHashString_FromCpp(hash, false, NULL));
+
+ // Another example: Add the HashString type to the module.
+ Py_INCREF(&PyHashString_Type);
+ PyModule_AddObject(Module, "HashString", (PyObject*)(&PyHashString_Type));
+}
+
+int main(int argc, char *argv[]) {
+ // Return value.
+ int ret = 0;
+ // Initialize python
+ Py_Initialize();
+ // Make the client module importable
+ PyImport_AppendInittab("client", &initclient);
+ // Set the commandline arguments.
+ PySys_SetArgv(argc, argv);
+
+ // Import the module, so the user does not have to import it.
+ if (PyRun_SimpleString("import client\n") < 0) {
+ // Failure (should never be reached)
+ ret = 1;
+ goto end;
+ }
+
+ // Run IPython if available, otherwise a normal interpreter.
+ if (PyRun_SimpleString("from IPython.Shell import start\n") == 0)
+ PyRun_SimpleString("start(user_ns=dict(client=client)).mainloop()\n");
+ else
+ Py_Main(argc, argv);
+
+end:
+ Py_Finalize();
+ return ret;
+}
diff --git a/doc/examples/acquire.py b/doc/examples/acquire.py
new file mode 100644
index 0000000..3d1e31b
--- /dev/null
+++ b/doc/examples/acquire.py
@@ -0,0 +1,80 @@
+#!/usr/bin/python3
+import os
+
+import apt_pkg
+
+import apt
+import apt.progress.text
+
+
+def get_file(fetcher, uri, destfile):
+ # get the file
+ af = apt_pkg.AcquireFile(fetcher, uri=uri, descr="sample descr", destfile=destfile)
+ print(f"desc_uri: {af.desc_uri} -> {af.destfile}")
+ res = fetcher.run()
+ if res != fetcher.RESULT_CONTINUE:
+ return False
+ return True
+
+
+apt_pkg.init()
+
+# apt_pkg.config.set("Debug::pkgDPkgPM","1");
+# apt_pkg.config.set("Debug::pkgPackageManager","1");
+# apt_pkg.config.set("Debug::pkgDPkgProgressReporting","1");
+
+cache = apt_pkg.Cache()
+depcache = apt_pkg.DepCache(cache)
+
+recs = apt_pkg.PackageRecords(cache)
+list = apt_pkg.SourceList()
+list.read_main_list()
+
+# show the amount fetch needed for a dist-upgrade
+depcache.upgrade(True)
+progress = apt.progress.text.AcquireProgress()
+fetcher = apt_pkg.Acquire(progress)
+pm = apt_pkg.PackageManager(depcache)
+pm.get_archives(fetcher, list, recs)
+print(f"{apt_pkg.size_to_str(fetcher.fetch_needed)} ({fetcher.fetch_needed})")
+actiongroup = apt_pkg.ActionGroup(depcache)
+for pkg in cache.packages:
+ depcache.mark_keep(pkg)
+
+try:
+ os.mkdir("/tmp/pyapt-test")
+ os.mkdir("/tmp/pyapt-test/partial")
+except OSError:
+ pass
+apt_pkg.config.set("Dir::Cache::archives", "/tmp/pyapt-test")
+
+pkg = cache["2vcard"]
+depcache.mark_install(pkg)
+
+progress = apt.progress.text.AcquireProgress()
+fetcher = apt_pkg.Acquire(progress)
+# fetcher = apt_pkg.Acquire()
+pm = apt_pkg.PackageManager(depcache)
+
+print(pm)
+print(fetcher)
+
+get_file(fetcher, "ftp://ftp.debian.org/debian/dists/README", "/tmp/lala")
+
+pm.get_archives(fetcher, list, recs)
+
+for item in fetcher.items:
+ print(item)
+ if item.status == item.STAT_ERROR:
+ print("Some error ocured: '%s'" % item.error_text)
+ if not item.complete:
+ print("No error, still nothing downloaded (%s)" % item.error_text)
+ print()
+
+
+res = fetcher.run()
+print("fetcher.Run() returned: %s" % res)
+
+print("now runing pm.DoInstall()")
+res = pm.do_install(1)
+print("pm.DoInstall() returned: %s" % res)
diff --git a/doc/examples/action.py b/doc/examples/action.py
new file mode 100644
index 0000000..59e050b
--- /dev/null
+++ b/doc/examples/action.py
@@ -0,0 +1,116 @@
+#!/usr/bin/python3
+#
+# LOW LEVEL example how to deal with the depcache
+#
+# you probably do not want to use this low level code and use
+# the high level "apt" interface instead that can do all this
+# but with a nicer API
+
+import apt_pkg
+from progress import TextFetchProgress
+
+from apt.progress.text import OpProgress
+
+# init
+apt_pkg.init()
+
+progress = OpProgress()
+cache = apt_pkg.Cache(progress)
+print("Available packages: %s " % cache.package_count)
+
+print("Fetching")
+progress = TextFetchProgress()
+source = apt_pkg.SourceList()
+cache.update(progress, source)
+
+iter = cache["base-config"]
+print("example package iter: %s" % iter)
+
+# get depcache
+print("\n\n depcache")
+depcache = apt_pkg.DepCache(cache)
+depcache.read_pinfile()
+print("got a depcache: %s " % depcache)
+print("Marked for install: %s " % depcache.inst_count)
+
+print("\n\n Reinit")
+depcache.init(progress)
+
+# sys.exit()
+
+# get a canidate version
+ver = depcache.get_candidate_ver(iter)
+print("Candidate version: %s " % ver)
+
+print("\n\nQuerry interface")
+print(f"{iter.name}.is_upgradable(): {depcache.is_upgradable(iter)}")
+
+print("\nMarking interface")
+print("Marking '%s' for install" % iter.name)
+depcache.mark_install(iter)
+print("Install count: %s " % depcache.inst_count)
+print(f"{iter.name}.marked_install(): {depcache.marked_install(iter)}")
+print(f"{iter.name}.marked_upgrade(): {depcache.marked_upgrade(iter)}")
+print(f"{iter.name}.marked_delete(): {depcache.marked_delete(iter)}")
+
+print("Marking %s for delete" % iter.name)
+depcache.mark_delete(iter)
+print("del_count: %s " % depcache.del_count)
+print(f"{iter.name}.marked_delete(): {depcache.marked_delete(iter)}")
+
+iter = cache["apt"]
+print("\nMarking '%s' for install" % iter.name)
+depcache.mark_install(iter)
+print("Install count: %s " % depcache.inst_count)
+print(f"{iter.name}.marked_install(): {depcache.marked_install(iter)}")
+print(f"{iter.name}.marked_upgrade(): {depcache.marked_upgrade(iter)}")
+print(f"{iter.name}.marked_delete(): {depcache.marked_delete(iter)}")
+
+print("Marking %s for keep" % iter.name)
+depcache.mark_keep(iter)
+print("Install: %s " % depcache.inst_count)
+
+iter = cache["python-apt"]
+print("\nMarking '%s' for install" % iter.name)
+depcache.mark_install(iter)
+print("Install: %s " % depcache.inst_count)
+print("Broken count: %s" % depcache.broken_count)
+print("fix_broken() ")
+depcache.fix_broken()
+print("Broken count: %s" % depcache.broken_count)
+
+print("\nPerforming upgrade")
+depcache.upgrade()
+print("Keep: %s " % depcache.keep_count)
+print("Install: %s " % depcache.inst_count)
+print("Delete: %s " % depcache.del_count)
+print("usr_size: %s " % apt_pkg.size_to_str(depcache.usr_size))
+print("deb_size: %s " % apt_pkg.size_to_str(depcache.deb_size))
+
+for pkg in cache.packages:
+ if (
+ pkg.current_ver is not None
+ and not depcache.marked_install(pkg)
+ and depcache.is_upgradable(pkg)
+ ):
+ print("upgrade didn't upgrade (kept): %s" % pkg.name)
+
+print("\nPerforming Distupgrade")
+depcache.upgrade(True)
+print("Keep: %s " % depcache.keep_count)
+print("Install: %s " % depcache.inst_count)
+print("Delete: %s " % depcache.del_count)
+print("usr_size: %s " % apt_pkg.size_to_str(depcache.usr_size))
+print("deb_size: %s " % apt_pkg.size_to_str(depcache.deb_size))
+
+# overview about what would happen
+for pkg in cache.packages:
+ if depcache.marked_install(pkg):
+ if pkg.current_ver is not None:
+ print("Marked upgrade: %s " % pkg.name)
+ else:
+ print("Marked install: %s" % pkg.name)
+ elif depcache.marked_delete(pkg):
+ print("Marked delete: %s" % pkg.name)
+ elif depcache.marked_keep(pkg):
+ print("Marked keep: %s" % pkg.name)
diff --git a/doc/examples/all_deps.py b/doc/examples/all_deps.py
new file mode 100644
index 0000000..df8610a
--- /dev/null
+++ b/doc/examples/all_deps.py
@@ -0,0 +1,37 @@
+#!/usr/bin/python3
+import sys
+
+import apt
+
+
+def dependencies(cache, pkg, deps, key="Depends"):
+ # print "pkg: %s (%s)" % (pkg.name, deps)
+ candver = cache._depcache.get_candidate_ver(pkg._pkg)
+ if candver is None:
+ return deps
+ dependslist = candver.depends_list
+ if key in dependslist:
+ for depVerList in dependslist[key]:
+ for dep in depVerList:
+ if dep.target_pkg.name in cache:
+ if (
+ pkg.name != dep.target_pkg.name
+ and dep.target_pkg.name not in deps
+ ):
+ deps.add(dep.target_pkg.name)
+ dependencies(cache, cache[dep.target_pkg.name], deps, key)
+ return deps
+
+
+pkgname = sys.argv[1]
+c = apt.Cache()
+pkg = c[pkgname]
+
+deps = set()
+
+deps = dependencies(c, pkg, deps, "Depends")
+print(" ".join(deps))
+
+preDeps = set()
+preDeps = dependencies(c, pkg, preDeps, "PreDepends")
+print(" ".join(preDeps))
diff --git a/doc/examples/architecture.py b/doc/examples/architecture.py
new file mode 100644
index 0000000..3972234
--- /dev/null
+++ b/doc/examples/architecture.py
@@ -0,0 +1,12 @@
+import apt_pkg
+
+
+def main():
+ apt_pkg.init_config()
+
+ print("Native architecture:", apt_pkg.config["APT::Architecture"])
+ print("All architectures:", apt_pkg.config.value_list("APT::Architectures"))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/doc/examples/build-deps-old.py b/doc/examples/build-deps-old.py
new file mode 100755
index 0000000..71a081e
--- /dev/null
+++ b/doc/examples/build-deps-old.py
@@ -0,0 +1,74 @@
+#!/usr/bin/python3
+# this is a example how to access the build dependencies of a package
+
+import sys
+
+import apt_pkg
+
+
+def get_source_pkg(pkg, records, depcache):
+ """get the source package name of a given package"""
+ version = depcache.get_candidate_ver(pkg)
+ if not version:
+ return None
+ file, index = version.file_list.pop(0)
+ records.lookup((file, index))
+ if records.source_pkg != "":
+ srcpkg = records.source_pkg
+ else:
+ srcpkg = pkg.name
+ return srcpkg
+
+
+# main
+apt_pkg.init()
+cache = apt_pkg.Cache()
+depcache = apt_pkg.DepCache(cache)
+depcache.init()
+records = apt_pkg.PackageRecords(cache)
+srcrecords = apt_pkg.SourceRecords()
+
+# base package that we use for build-depends calculation
+if len(sys.argv) < 2:
+ print("need a package name as argument")
+ sys.exit(1)
+try:
+ pkg = base = cache[sys.argv[1]]
+except KeyError:
+ print("No package %s found" % sys.argv[1])
+ sys.exit(1)
+all_build_depends = set()
+
+# get the build depdends for the package itself
+srcpkg_name = get_source_pkg(base, records, depcache)
+print("srcpkg_name: %s " % srcpkg_name)
+if not srcpkg_name:
+ print("Can't find source package for '%s'" % pkg.mame)
+srcrec = srcrecords.lookup(srcpkg_name)
+if srcrec:
+ print("Files:")
+ print(srcrecords.files)
+ bd = srcrecords.build_depends
+ print("build-depends of the package: %s " % bd)
+ for b in bd:
+ all_build_depends.add(b[0])
+
+# calculate the build depends for all dependencies
+depends = depcache.get_candidate_ver(base).depends_list
+for dep in depends["Depends"]: # FIXME: do we need to consider PreDepends?
+ pkg = dep[0].target_pkg
+ srcpkg_name = get_source_pkg(pkg, records, depcache)
+ if not srcpkg_name:
+ print("Can't find source package for '%s'" % pkg.name)
+ continue
+ srcrec = srcrecords.lookup(srcpkg_name)
+ if srcrec:
+ # print srcrecords.package
+ # print srcrecords.binaries
+ bd = srcrecords.build_depends
+ # print "%s: %s " % (srcpkg_name, bd)
+ for b in bd:
+ all_build_depends.add(b[0])
+
+
+print("\n".join(all_build_depends))
diff --git a/doc/examples/build-deps.py b/doc/examples/build-deps.py
new file mode 100755
index 0000000..714d1c4
--- /dev/null
+++ b/doc/examples/build-deps.py
@@ -0,0 +1,58 @@
+#!/usr/bin/python3
+# this is a example how to access the build dependencies of a package
+
+import sys
+
+import apt_pkg
+
+import apt
+
+# main
+cache = apt.Cache()
+srcrecords = apt_pkg.SourceRecords()
+
+# base package that we use for build-depends calculation
+if len(sys.argv) < 2:
+ print("need a package name as argument")
+ sys.exit(1)
+try:
+ pkg = base = cache[sys.argv[1]]
+except KeyError:
+ print("No package %s found" % sys.argv[1])
+ sys.exit(1)
+all_build_depends = set()
+
+# get the build depdends for the package itself
+srcpkg_name = base.candidate.source_name
+print("srcpkg_name: %s " % srcpkg_name)
+if not srcpkg_name:
+ print("Can't find source package for '%s'" % pkg.name)
+srcrec = srcrecords.lookup(srcpkg_name)
+if srcrec:
+ print("Files:")
+ print(srcrecords.files)
+ bd = srcrecords.build_depends
+ print("build-depends of the package: %s " % bd)
+ for b in bd:
+ all_build_depends.add(b[0])
+
+# calculate the build depends for all dependencies
+depends = base.candidate.dependencies
+for or_dep in depends:
+ for dep in or_dep.or_dependencies:
+ pkg = cache[dep.name]
+ srcpkg_name = pkg.candidate.source_name
+ if not srcpkg_name:
+ print("Can't find source package for '%s'" % pkg.name)
+ continue
+ srcrec = srcrecords.lookup(srcpkg_name)
+ if srcrec:
+ # print srcrecords.package
+ # print srcrecords.binaries
+ bd = srcrecords.build_depends
+ # print "%s: %s " % (srcpkg_name, bd)
+ for b in bd:
+ all_build_depends.add(b[0])
+
+
+print("\n".join(all_build_depends))
diff --git a/doc/examples/cdrom.py b/doc/examples/cdrom.py
new file mode 100644
index 0000000..ad4d2ba
--- /dev/null
+++ b/doc/examples/cdrom.py
@@ -0,0 +1,24 @@
+#!/usr/bin/python3
+# example how to deal with the depcache
+
+import sys
+
+import apt_pkg
+from progress import TextCdromProgress
+
+# init
+apt_pkg.init()
+
+cdrom = apt_pkg.Cdrom()
+print(cdrom)
+
+progress = TextCdromProgress()
+
+(res, ident) = cdrom.ident(progress)
+print(f"ident result is: {res} ({ident}) ")
+
+apt_pkg.config["APT::CDROM::Rename"] = "True"
+cdrom.add(progress)
+
+print("Exiting")
+sys.exit(0)
diff --git a/doc/examples/checkstate.py b/doc/examples/checkstate.py
new file mode 100755
index 0000000..d4276e8
--- /dev/null
+++ b/doc/examples/checkstate.py
@@ -0,0 +1,37 @@
+#!/usr/bin/python3
+#
+#
+# this example is not usefull to find out about updated, upgradable packages
+# use the depcache.py example for it (because a pkgPolicy is not used here)
+#
+
+import apt_pkg
+
+apt_pkg.init()
+
+cache = apt_pkg.Cache()
+packages = cache.packages
+
+uninstalled, updated, upgradable = {}, {}, {}
+
+for package in packages:
+ versions = package.version_list
+ if not versions:
+ continue
+ version = versions[0]
+ for other_version in versions:
+ if apt_pkg.version_compare(version.ver_str, other_version.ver_str) < 0:
+ version = other_version
+ if package.current_ver:
+ current = package.current_ver
+ if apt_pkg.version_compare(current.ver_str, version.ver_str) < 0:
+ upgradable[package.name] = version
+ break
+ else:
+ updated[package.name] = current
+ else:
+ uninstalled[package.name] = version
+
+
+for line in (uninstalled, updated, upgradable):
+ print(list(line.items())[0])
diff --git a/doc/examples/config.py b/doc/examples/config.py
new file mode 100755
index 0000000..fb687e3
--- /dev/null
+++ b/doc/examples/config.py
@@ -0,0 +1,60 @@
+#!/usr/bin/python3
+# Example demonstrating how to use the configuration/commandline system
+# for configuration.
+# Some valid command lines..
+# config.py -h --help ; Turn on help
+# config.py -no-h --no-help --help=no ; Turn off help
+# config.py -qqq -q=3 ; verbosity to 3
+# config.py -c /etc/apt/apt.conf ; include that config file]
+# config.py -o help=true ; Turn on help by giving a
+# ; config file string
+# config.py -no-h -- -help ; Turn off help, specify the file '-help'
+# -c and -o are standard APT-program options.
+
+import posixpath
+import sys
+
+# This shows how to use the system for configuration and option control.
+# The other varient is for ISC object config files. See configisc.py.
+import apt_pkg
+
+# Create a new empty Configuration object - there is also the system global
+# configuration object apt_pkg.config which is used interally by apt-pkg
+# routines to control unusual situations. I recommend using the sytem global
+# whenever possible..
+Cnf = apt_pkg.Configuration()
+
+print("Command line is", sys.argv)
+
+# Load the default configuration file, init_config() does this better..
+Cnf.set("config-file", "/etc/apt/apt.conf") # or Cnf["config-file"] = ".."
+if posixpath.exists(Cnf.find_file("config-file")):
+ apt_pkg.read_config_file(Cnf, "/etc/apt/apt.conf")
+
+# Merge the command line arguments into the configuration space
+Arguments = [
+ ("h", "help", "help"),
+ ("v", "version", "version"),
+ ("q", "quiet", "quiet", "IntLevel"),
+ ("c", "config-file", "", "ConfigFile"),
+ ("o", "option", "", "ArbItem"),
+]
+print("FileNames", apt_pkg.parse_commandline(Cnf, Arguments, sys.argv))
+
+print("Quiet level selected is", Cnf.find_i("quiet", 0))
+
+# Do some stuff with it
+if Cnf.find_b("version", 0) == 1:
+ print("Version selected - 1.1")
+
+if Cnf.find_b("help", 0) == 1:
+ print("python-apt", apt_pkg.VERSION, "compiled on", apt_pkg.DATE, apt_pkg.TIME)
+ print("Hi, I am the help text for this program")
+ sys.exit(0)
+
+print("No help for you, try -h")
+
+# Print the configuration space
+print("The Configuration space looks like:")
+for item in list(Cnf.keys()):
+ print(f'{item} "{Cnf[item]}";')
diff --git a/doc/examples/configisc.py b/doc/examples/configisc.py
new file mode 100755
index 0000000..10700dc
--- /dev/null
+++ b/doc/examples/configisc.py
@@ -0,0 +1,49 @@
+#!/usr/bin/python3
+# Example demonstrating how to use the configuration/commandline system
+# for object setup.
+
+# This parses the given config file in 'ISC' style where the sections
+# represent object instances and shows how to iterate over the sections.
+# Pass it the sample apt-ftparchive configuration,
+# doc/examples/ftp-archive.conf
+# or a bind8 config file..
+
+import sys
+
+import apt_pkg
+
+ConfigFile = apt_pkg.parse_commandline(apt_pkg.config, [], sys.argv)
+
+if len(ConfigFile) != 1:
+ print("Must have exactly 1 file name")
+ sys.exit(0)
+
+Cnf = apt_pkg.Configuration()
+apt_pkg.read_config_file_isc(Cnf, ConfigFile[0])
+
+# Print the configuration space
+# print "The Configuration space looks like:"
+# for item in Cnf.keys():
+# print "%s \"%s\";" % (item, Cnf[item])
+
+# bind8 config file..
+if "Zone" in Cnf:
+ print("Zones: ", Cnf.sub_tree("zone").list())
+ for item in Cnf.list("zone"):
+ SubCnf = Cnf.sub_tree(item)
+ if SubCnf.find("type") == "slave":
+ print(
+ "Masters for {}: {}".format(
+ SubCnf.my_tag(), SubCnf.value_list("masters")
+ )
+ )
+else:
+ print("Tree definitions:")
+ for item in Cnf.list("tree"):
+ SubCnf = Cnf.sub_tree(item)
+ # This could use Find which would eliminate the possibility of
+ # exceptions.
+ print(
+ "Subtree %s with sections '%s' and architectures '%s'"
+ % (SubCnf.my_tag(), SubCnf["Sections"], SubCnf["Architectures"])
+ )
diff --git a/doc/examples/deb_inspect.py b/doc/examples/deb_inspect.py
new file mode 100755
index 0000000..72050e3
--- /dev/null
+++ b/doc/examples/deb_inspect.py
@@ -0,0 +1,61 @@
+#!/usr/bin/python3
+# some example for apt_inst
+
+import os.path
+import sys
+
+import apt_inst
+import apt_pkg
+
+
+def Callback(member, data):
+ """callback for debExtract"""
+ print(
+ "'%s','%s',%u,%u,%u,%u,%u,%u,%u"
+ % (
+ member.name,
+ member.linkname,
+ member.mode,
+ member.uid,
+ member.gid,
+ member.size,
+ member.mtime,
+ member.major,
+ member.minor,
+ )
+ )
+
+
+if __name__ == "__main__":
+ if len(sys.argv) < 2:
+ print("need filename argumnet")
+ sys.exit(1)
+ file = sys.argv[1]
+
+ print("Working on: %s" % file)
+ print("Displaying data.tar.gz:")
+ apt_inst.DebFile(open(file)).data.go(Callback)
+
+ print("Now extracting the control file:")
+ control = apt_inst.DebFile(open(file)).control.extractdata("control")
+ sections = apt_pkg.TagSection(control)
+
+ print("Maintainer is: ")
+ print(sections["Maintainer"])
+
+ print()
+ print("DependsOn: ")
+ depends = sections["Depends"]
+ print(apt_pkg.parse_depends(depends))
+
+ print("extracting archive")
+ dir = "/tmp/deb"
+ os.mkdir(dir)
+ apt_inst.DebFile(open(file)).data.extractall(dir)
+
+ def visit(arg, dirname, names):
+ print("%s/" % dirname)
+ for file in names:
+ print("\t%s" % file)
+
+ os.path.walk(dir, visit, None)
diff --git a/doc/examples/depcache.py b/doc/examples/depcache.py
new file mode 100644
index 0000000..f6dff52
--- /dev/null
+++ b/doc/examples/depcache.py
@@ -0,0 +1,109 @@
+#!/usr/bin/python3
+# example how to deal with the depcache
+
+import apt_pkg
+from progress import TextProgress
+
+# init
+apt_pkg.init()
+
+progress = TextProgress()
+cache = apt_pkg.Cache(progress)
+print("Available packages: %s " % cache.package_count)
+
+iter = cache["base-config"]
+print("example package iter: %s" % iter)
+
+# get depcache
+print("\n\n depcache")
+depcache = apt_pkg.DepCache(cache)
+depcache.read_pinfile()
+# init is needed after the creation/pin file reading
+depcache.init(progress)
+print("got a depcache: %s " % depcache)
+print("Marked for install: %s " % depcache.inst_count)
+
+print("\n\n Reinit")
+depcache.init(progress)
+
+# sys.exit()
+
+
+# get a canidate version
+ver = depcache.get_candidate_ver(iter)
+print("Candidate version: %s " % ver)
+
+print("\n\nQuerry interface")
+print(f"{iter.name}.is_upgradable(): {depcache.is_upgradable(iter)}")
+
+print("\nMarking interface")
+print("Marking '%s' for install" % iter.name)
+depcache.mark_install(iter)
+print("Install count: %s " % depcache.inst_count)
+print(f"{iter.name}.marked_install(): {depcache.marked_install(iter)}")
+print(f"{iter.name}.marked_upgrade(): {depcache.marked_upgrade(iter)}")
+print(f"{iter.name}.marked_delete(): {depcache.marked_delete(iter)}")
+
+print("Marking %s for delete" % iter.name)
+depcache.mark_delete(iter)
+print("del_count: %s " % depcache.del_count)
+print(f"{iter.name}.marked_delete(): {depcache.marked_delete(iter)}")
+
+
+iter = cache["3dchess"]
+print("\nMarking '%s' for install" % iter.name)
+depcache.mark_install(iter)
+print("Install count: %s " % depcache.inst_count)
+print(f"{iter.name}.marked_install(): {depcache.marked_install(iter)}")
+print(f"{iter.name}.marked_upgrade(): {depcache.marked_upgrade(iter)}")
+print(f"{iter.name}.marked_delete(): {depcache.marked_delete(iter)}")
+
+print("Marking %s for keep" % iter.name)
+depcache.mark_keep(iter)
+print("Install: %s " % depcache.inst_count)
+
+iter = cache["synaptic"]
+print("\nMarking '%s' for install" % iter.name)
+depcache.mark_install(iter)
+print("Install: %s " % depcache.inst_count)
+print("Broken count: %s" % depcache.broken_count)
+print("fix_broken() ")
+depcache.fix_broken()
+print("Broken count: %s" % depcache.broken_count)
+
+print("\nPerforming upgrade")
+depcache.upgrade()
+print("Keep: %s " % depcache.keep_count)
+print("Install: %s " % depcache.inst_count)
+print("Delete: %s " % depcache.del_count)
+print("usr_size: %s " % apt_pkg.size_to_str(depcache.usr_size))
+print("deb_size: %s " % apt_pkg.size_to_str(depcache.deb_size))
+
+for pkg in cache.packages:
+ if (
+ pkg.current_ver is not None
+ and not depcache.marked_install(pkg)
+ and depcache.is_upgradable(pkg)
+ ):
+ print("upgrade didn't upgrade (kept): %s" % pkg.name)
+
+
+print("\nPerforming DistUpgrade")
+depcache.upgrade(True)
+print("Keep: %s " % depcache.keep_count)
+print("Install: %s " % depcache.inst_count)
+print("Delete: %s " % depcache.del_count)
+print("usr_size: %s " % apt_pkg.size_to_str(depcache.usr_size))
+print("deb_size: %s " % apt_pkg.size_to_str(depcache.deb_size))
+
+# overview about what would happen
+for pkg in cache.packages:
+ if depcache.marked_install(pkg):
+ if pkg.current_ver is not None:
+ print("Marked upgrade: %s " % pkg.name)
+ else:
+ print("Marked install: %s" % pkg.name)
+ elif depcache.marked_delete(pkg):
+ print("Marked delete: %s" % pkg.name)
+ elif depcache.marked_keep(pkg):
+ print("Marked keep: %s" % pkg.name)
diff --git a/doc/examples/dependant-pkgs.py b/doc/examples/dependant-pkgs.py
new file mode 100755
index 0000000..e5985b8
--- /dev/null
+++ b/doc/examples/dependant-pkgs.py
@@ -0,0 +1,38 @@
+#!/usr/bin/python3
+
+import sys
+
+import apt
+
+pkgs = set()
+cache = apt.Cache()
+for pkg in cache:
+ candver = cache._depcache.get_candidate_ver(pkg._pkg)
+ if candver is None:
+ continue
+ dependslist = candver.depends_list
+ for dep in list(dependslist.keys()):
+ # get the list of each dependency object
+ for depVerList in dependslist[dep]:
+ for z in depVerList:
+ # get all TargetVersions of
+ # the dependency object
+ for tpkg in z.all_targets():
+ if sys.argv[1] == tpkg.parent_pkg.name:
+ pkgs.add(pkg.name)
+
+main = set()
+universe = set()
+for pkg in pkgs:
+ cand = cache[pkg].candidate
+ if "universe" in cand.section:
+ universe.add(cand.source_name)
+ else:
+ main.add(cand.source_name)
+
+print("main:")
+print("\n".join(sorted(main)))
+print()
+
+print("universe:")
+print("\n".join(sorted(universe)))
diff --git a/doc/examples/desc.py b/doc/examples/desc.py
new file mode 100644
index 0000000..7e8e3e8
--- /dev/null
+++ b/doc/examples/desc.py
@@ -0,0 +1,25 @@
+#!/usr/bin/python3
+
+import apt_pkg
+
+apt_pkg.init()
+
+apt_pkg.config.set("APT::Acquire::Translation", "de")
+
+cache = apt_pkg.Cache()
+depcache = apt_pkg.DepCache(cache)
+
+pkg = cache["gcc"]
+cand = depcache.get_candidate_ver(pkg)
+print(cand)
+
+desc = cand.TranslatedDescription
+print(desc)
+print(desc.file_list)
+(f, index) = desc.file_list.pop(0)
+
+records = apt_pkg.PackageRecords(cache)
+records.lookup((f, index))
+desc = records.long_desc
+print(len(desc))
+print(desc)
diff --git a/doc/examples/indexfile.py b/doc/examples/indexfile.py
new file mode 100644
index 0000000..34ea94e
--- /dev/null
+++ b/doc/examples/indexfile.py
@@ -0,0 +1,22 @@
+#!/usr/bin/python3
+
+import apt_pkg
+
+apt_pkg.init()
+
+sources = apt_pkg.SourceList()
+sources.read_main_list()
+
+cache = apt_pkg.Cache()
+depcache = apt_pkg.DepCache(cache)
+pkg = cache["libimlib2"]
+cand = depcache.get_candidate_ver(pkg)
+for f, i in cand.file_list:
+ index = sources.find_index(f)
+ print(index)
+ if index:
+ print(index.size)
+ print(index.is_trusted)
+ print(index.exists)
+ print(index.has_packages)
+ print(index.archive_uri("some/path"))
diff --git a/doc/examples/inst.py b/doc/examples/inst.py
new file mode 100644
index 0000000..892b43b
--- /dev/null
+++ b/doc/examples/inst.py
@@ -0,0 +1,47 @@
+#!/usr/bin/python3
+# example how to deal with the depcache
+
+import sys
+
+import apt
+from apt.progress import InstallProgress
+
+
+class TextInstallProgress(InstallProgress):
+ def __init__(self):
+ apt.progress.InstallProgress.__init__(self)
+ self.last = 0.0
+
+ def updateInterface(self):
+ InstallProgress.updateInterface(self)
+ if self.last >= self.percent:
+ return
+ sys.stdout.write(f"\r[{self.percent}] {self.status}\n")
+ sys.stdout.flush()
+ self.last = self.percent
+
+ def conffile(self, current, new):
+ print(f"conffile prompt: {current} {new}")
+
+ def error(self, errorstr):
+ print("got dpkg error: '%s'" % errorstr)
+
+
+cache = apt.Cache(apt.progress.OpTextProgress())
+
+fprogress = apt.progress.TextFetchProgress()
+iprogress = TextInstallProgress()
+
+pkg = cache["3dchess"]
+
+# install or remove, the importend thing is to keep us busy :)
+if pkg.is_installed:
+ print("Going to delete %s" % pkg.name)
+ pkg.mark_delete()
+else:
+ print("Going to install %s" % pkg.name)
+ pkg.mark_install()
+res = cache.commit(fprogress, iprogress)
+print(res)
+
+sys.exit(0)
diff --git a/doc/examples/metaindex.py b/doc/examples/metaindex.py
new file mode 100644
index 0000000..2497e65
--- /dev/null
+++ b/doc/examples/metaindex.py
@@ -0,0 +1,16 @@
+#!/usr/bin/python3
+
+import apt_pkg
+
+apt_pkg.init()
+
+sources = apt_pkg.SourceList()
+sources.read_main_list()
+
+
+for metaindex in sources.list:
+ print(metaindex)
+ print("uri: ", metaindex.uri)
+ print("dist: ", metaindex.dist)
+ print("index_files: ", "\n".join([str(i) for i in metaindex.index_files]))
+ print()
diff --git a/doc/examples/print_uris.py b/doc/examples/print_uris.py
new file mode 100755
index 0000000..1b59e00
--- /dev/null
+++ b/doc/examples/print_uris.py
@@ -0,0 +1,10 @@
+#!/usr/bin/python3
+#
+# a example that prints the URIs of all upgradable packages
+#
+
+import apt
+
+for pkg in apt.Cache():
+ if pkg.is_upgradable:
+ print(pkg.candidate.uri)
diff --git a/doc/examples/progress.py b/doc/examples/progress.py
new file mode 100644
index 0000000..680a64d
--- /dev/null
+++ b/doc/examples/progress.py
@@ -0,0 +1,118 @@
+#!/usr/bin/python3
+
+import sys
+import time
+
+import apt_pkg
+
+import apt
+import apt.progress.base
+
+
+class TextProgress(apt.progress.base.OpProgress):
+ def __init__(self):
+ self.last = 0.0
+
+ def update(self, percent):
+ if (self.last + 1.0) <= percent:
+ sys.stdout.write("\rProgress: %i.2 " % (percent))
+ self.last = percent
+ if percent >= 100:
+ self.last = 0.0
+
+ def done(self):
+ self.last = 0.0
+ print("\rDone ")
+
+
+class TextFetchProgress(apt.progress.base.AcquireProgress):
+ def __init__(self):
+ pass
+
+ def start(self):
+ pass
+
+ def stop(self):
+ pass
+
+ def fail(self, item):
+ print("fail", item)
+
+ def fetch(self, item):
+ print("fetch", item)
+
+ def ims_hit(self, item):
+ print("ims_hit", item)
+
+ def pulse(self, owner):
+ print(
+ "pulse: CPS: %s/s; Bytes: %s/%s; Item: %s/%s"
+ % (
+ apt_pkg.size_to_str(self.current_cps),
+ apt_pkg.size_to_str(self.current_bytes),
+ apt_pkg.size_to_str(self.total_bytes),
+ self.current_items,
+ self.total_items,
+ )
+ )
+ return True
+
+ def media_change(self, medium, drive):
+ print(f"Please insert medium {medium} in drive {drive}")
+ sys.stdin.readline()
+ # return False
+
+
+class TextInstallProgress(apt.progress.base.InstallProgress):
+ def __init__(self):
+ apt.progress.base.InstallProgress.__init__(self)
+
+ def start_update(self):
+ print("start_update")
+
+ def finish_update(self):
+ print("finish_update")
+
+ def status_change(self, pkg, percent, status):
+ print(f"[{percent}] {pkg}: {status}")
+
+ def update_interface(self):
+ apt.progress.base.InstallProgress.update_interface(self)
+ # usefull to e.g. redraw a GUI
+ time.sleep(0.1)
+
+
+class TextCdromProgress(apt.progress.base.CdromProgress):
+ def __init__(self):
+ pass
+
+ # update is called regularly so that the gui can be redrawn
+
+ def update(self, text, step):
+ # check if we actually have some text to display
+ if text != "":
+ print(f"Update: {text.strip()} {step}")
+
+ def ask_cdrom_name(self):
+ sys.stdout.write("Please enter cd-name: ")
+ cd_name = sys.stdin.readline()
+ return (True, cd_name.strip())
+
+ def change_cdrom(self):
+ print("Please insert cdrom and press <ENTER>")
+ answer = sys.stdin.readline()
+ print(answer)
+ return True
+
+
+if __name__ == "__main__":
+ c = apt.Cache()
+ pkg = c["3dchess"]
+ if pkg.is_installed:
+ pkg.mark_delete()
+ else:
+ pkg.mark_install()
+
+ res = c.commit(TextFetchProgress(), TextInstallProgress())
+
+ print(res)
diff --git a/doc/examples/recommends.py b/doc/examples/recommends.py
new file mode 100755
index 0000000..8539cd5
--- /dev/null
+++ b/doc/examples/recommends.py
@@ -0,0 +1,37 @@
+#!/usr/bin/python3
+
+import apt_pkg
+
+apt_pkg.init()
+
+cache = apt_pkg.Cache()
+
+
+class Wanted:
+ def __init__(self, name):
+ self.name = name
+ self.recommended = []
+ self.suggested = []
+
+
+wanted = {}
+
+for package in cache.packages:
+ current = package.current_ver
+ if not current:
+ continue
+ depends = current.depends_list
+ for key, attr in (("Suggests", "suggested"), ("Recommends", "recommended")):
+ list = depends.get(key, [])
+ for dependency in list:
+ name = dependency[0].target_pkg.name
+ dep = cache[name]
+ if dep.current_ver:
+ continue
+ getattr(wanted.setdefault(name, Wanted(name)), attr).append(package.name)
+
+ks = list(wanted.keys())
+ks.sort()
+
+for want in ks:
+ print(want, wanted[want].recommended, wanted[want].suggested)
diff --git a/doc/examples/records.py b/doc/examples/records.py
new file mode 100755
index 0000000..b88ed75
--- /dev/null
+++ b/doc/examples/records.py
@@ -0,0 +1,16 @@
+#!/usr/bin/python3
+
+import apt
+
+cache = apt.Cache()
+
+for pkg in cache:
+ if not pkg.candidate.record:
+ continue
+ if "Task" in pkg.candidate.record:
+ print(
+ "Pkg {} is part of '{}'".format(
+ pkg.name, pkg.candidate.record["Task"].split()
+ )
+ )
+ # print pkg.candidateRecord
diff --git a/doc/examples/sources.py b/doc/examples/sources.py
new file mode 100644
index 0000000..b467b7d
--- /dev/null
+++ b/doc/examples/sources.py
@@ -0,0 +1,21 @@
+#!/usr/bin/python3
+
+import apt_pkg
+
+apt_pkg.init()
+
+# cache = apt_pkg.Cache()
+# sources = apt_pkg.SourceRecords(cache)
+
+sources = apt_pkg.SourceRecords()
+sources.restart()
+while sources.lookup("hello"):
+ print(
+ sources.package,
+ sources.version,
+ sources.maintainer,
+ sources.section,
+ repr(sources.binaries),
+ )
+ print(sources.files)
+ print(sources.index.archive_uri(sources.files[0][2]))
diff --git a/doc/examples/tagfile.py b/doc/examples/tagfile.py
new file mode 100755
index 0000000..beb749b
--- /dev/null
+++ b/doc/examples/tagfile.py
@@ -0,0 +1,8 @@
+#!/usr/bin/python3
+import apt_pkg
+
+Parse = apt_pkg.TagFile(open("/var/lib/dpkg/status"))
+
+while Parse.step() == 1:
+ print(Parse.section.get("Package"))
+ print(apt_pkg.parse_depends(Parse.section.get("Depends", "")))
diff --git a/doc/examples/update.py b/doc/examples/update.py
new file mode 100755
index 0000000..a8d46b6
--- /dev/null
+++ b/doc/examples/update.py
@@ -0,0 +1,14 @@
+#!/usr/bin/python3
+import os.path
+
+import apt_pkg
+
+import apt
+
+if __name__ == "__main__":
+ apt_pkg.config.set("APT::Update::Pre-Invoke::", "touch /tmp/update-about-to-run")
+ apt_pkg.config.set("APT::Update::Post-Invoke::", "touch /tmp/update-was-run")
+ c = apt.Cache()
+ res = c.update(apt.progress.TextFetchProgress())
+ print("res: ", res)
+ assert os.path.exists("/tmp/update-about-to-run")
diff --git a/doc/examples/versiontest.py b/doc/examples/versiontest.py
new file mode 100755
index 0000000..fcc4c25
--- /dev/null
+++ b/doc/examples/versiontest.py
@@ -0,0 +1,54 @@
+#!/usr/bin/python3
+
+# This is a simple clone of tests/versiontest.cc
+import re
+import sys
+
+import apt_pkg
+
+apt_pkg.init_config()
+apt_pkg.init_system()
+
+TestFile = apt_pkg.parse_commandline(apt_pkg.config, [], sys.argv)
+if len(TestFile) != 1:
+ print("Must have exactly 1 file name")
+ sys.exit(0)
+
+# Go over the file..
+list = open(TestFile[0])
+CurLine = 0
+while True:
+ Line = list.readline()
+ CurLine = CurLine + 1
+ if Line == "":
+ break
+ Line = Line.strip()
+ if len(Line) == 0 or Line[0] == "#":
+ continue
+
+ Split = re.split("[ \n]", Line)
+
+ # Check forward
+ if apt_pkg.version_compare(Split[0], Split[1]) != int(Split[2]):
+ print(
+ "Comparision failed on line %u. '%s' ? '%s' %i != %i"
+ % (
+ CurLine,
+ Split[0],
+ Split[1],
+ apt_pkg.version_compare(Split[0], Split[1]),
+ int(Split[2]),
+ )
+ )
+ # Check reverse
+ if apt_pkg.version_compare(Split[1], Split[0]) != -1 * int(Split[2]):
+ print(
+ "Comparision failed on line %u. '%s' ? '%s' %i != %i"
+ % (
+ CurLine,
+ Split[1],
+ Split[0],
+ apt_pkg.version_compare(Split[1], Split[0]),
+ -1 * int(Split[2]),
+ )
+ )
diff --git a/doc/source/c++/api.rst b/doc/source/c++/api.rst
new file mode 100644
index 0000000..c8e52ab
--- /dev/null
+++ b/doc/source/c++/api.rst
@@ -0,0 +1,858 @@
+Python APT C++ API
+==================
+The C++ API provides functions to create Python objects from C++ objects and
+to retrieve the C++ object stored in the Python object. An object may have
+another Python object as its owner and keeps its owner alive for its
+lifetime. Some objects require an owner of a specific type, while others
+require none. Refer to the sections below for details.
+
+The C++ API names use the name of the class in apt_pkg and are prefixed with
+Py. For each supported class, there is a _Type object, a _Check() function,
+a _CheckExact() function, a _FromCpp() and a _ToCpp() function.
+
+.. versionadded:: 0.7.100
+
+Acquire (pkgAcquire)
+--------------------
+.. cpp:var:: PyTypeObject PyAcquire_Type
+
+ The type object for :class:`apt_pkg.Acquire` objects.
+
+.. cpp:function:: int PyAcquire_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Acquire` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyAcquire_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Acquire` object and no
+ subclass thereof.
+
+.. cpp:function:: PyObject* PyAcquire_FromCpp(pkgAcquire *acquire, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.Acquire` object from the :cpp:type:`pkgAcquire`
+ pointer given by the parameter *acquire*. If the parameter *delete* is
+ true, the object pointed to by *acquire* will be deleted when the refcount
+ of the return value reaches 0.
+
+.. cpp:function:: pkgAcquire* PyAcquire_ToCpp(PyObject *acquire)
+
+ Return the :cpp:type:`pkgAcquire` pointer contained in the Python object
+ *acquire*.
+
+
+AcquireFile (pkgAcqFile)
+------------------------
+.. cpp:var:: PyTypeObject PyAcquireFile_Type
+
+ The type object for :class:`apt_pkg.AcquireFile` objects.
+
+.. cpp:function:: int PyAcquireFile_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.AcquireFile` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyAcquireFile_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.AcquireFile` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyAcquireFile_FromCpp(pkgAcqFile *file, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.AcquireFile` object from the :cpp:type:`pkgAcqFile`
+ pointer given by the parameter *file*. If the parameter *delete* is
+ true, the object pointed to by *file* will be deleted when the reference
+ count of the returned object reaches 0. The parameter *owner* should point
+ to a :class:`apt_pkg.Acquire` object.
+
+.. cpp:function:: pkgAcqFile* PyAcquireFile_ToCpp(PyObject *acquire)
+
+ Return the :cpp:type:`pkgAcqFile` pointer contained in the Python object
+ *acquire*.
+
+AcquireItem (pkgAcquire::Item)
+------------------------------
+.. cpp:var:: PyTypeObject PyAcquireItem_Type
+
+ The type object for :class:`apt_pkg.AcquireItem` objects.
+
+.. cpp:function:: int PyAcquireItem_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.AcquireItem` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyAcquireItem_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.AcquireItem` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyAcquireItem_FromCpp(pkgAcquire::Item *item, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.AcquireItem` object from the :cpp:type:`pkgAcquire::Item`
+ pointer given by the parameter *item*. If the parameter *delete* is
+ true, the object pointed to by *item* will be deleted when the reference
+ count of the returned object reaches 0. The parameter *owner* should point
+ to a :class:`apt_pkg.Acquire` object.
+
+.. cpp:function:: pkgAcquire::Item* PyAcquireItem_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`pkgAcquire::Item` pointer contained in the Python object
+ *object*.
+
+AcquireItemDesc (pkgAcquire::ItemDesc)
+--------------------------------------
+.. cpp:var:: PyTypeObject PyAcquireItemDesc_Type
+
+ The type object for :class:`apt_pkg.AcquireItemDesc` objects.
+
+.. cpp:function:: int PyAcquireItemDesc_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.AcquireItemDesc` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyAcquireItemDesc_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.AcquireItemDesc` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyAcquireItemDesc_FromCpp(pkgAcquire::ItemDesc *desc, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.AcquireItemDesc` object from the :cpp:type:`pkgAcquire::ItemDesc`
+ pointer given by the parameter *desc*. If the parameter *delete* is
+ true, the object pointed to by *desc* will be deleted when the reference
+ count of the returned object reaches 0. The parameter *owner* should point
+ to a :class:`apt_pkg.AcquireItem` object.
+
+.. cpp:function:: pkgAcquire::ItemDesc* PyAcquireItemDesc_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`pkgAcquire::ItemDesc` pointer contained in the Python object
+ *object*.
+
+AcquireWorker (pkgAcquire::Worker)
+----------------------------------
+.. cpp:var:: PyTypeObject PyAcquireWorker_Type
+
+ The type object for :class:`apt_pkg.AcquireWorker` objects.
+
+.. cpp:function:: int PyAcquireWorker_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.AcquireWorker` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyAcquireWorker_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.AcquireWorker` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyAcquireWorker_FromCpp(pkgAcquire::Worker *worker, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.AcquireWorker` object from the :cpp:type:`pkgAcquire::Worker`
+ pointer given by the parameter *worker*. If the parameter *delete* is
+ true, the object pointed to by *worker* will be deleted when the reference
+ count of the returned object reaches 0. The parameter *owner* should point
+ to a :class:`apt_pkg.Acquire` object.
+
+.. cpp:function:: pkgAcquire::Worker* PyAcquireWorker_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`pkgAcquire::Worker` pointer contained in the Python object
+ *object*.
+
+ActionGroup (pkgDepCache::ActionGroup)
+--------------------------------------
+.. cpp:var:: PyTypeObject PyActionGroup_Type
+
+ The type object for :class:`apt_pkg.ActionGroup` objects.
+
+.. cpp:function:: int PyActionGroup_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.ActionGroup` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyActionGroup_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.ActionGroup` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyActionGroup_FromCpp(pkgDepCache::ActionGroup *agroup, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.ActionGroup` object from the :cpp:type:`pkgDepCache::ActionGroup`
+ pointer given by the parameter *agroup*. If the parameter *delete* is
+ true, the object pointed to by *agroup* will be deleted when the reference
+ count of the returned object reaches 0. The parameter *owner* should point
+ to a :class:`apt_pkg.DepCache` object.
+
+.. cpp:function:: pkgDepCache::ActionGroup* PyActionGroup_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`pkgDepCache::ActionGroup` pointer contained in the
+ Python object *object*.
+
+Cache (pkgCache)
+------------------------
+.. cpp:var:: PyTypeObject PyCache_Type
+
+ The type object for :class:`apt_pkg.Cache` objects.
+
+.. cpp:function:: int PyCache_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Cache` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyCache_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Cache` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyCache_FromCpp(pkgCache *cache, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.Cache` object from the :cpp:type:`pkgCache`
+ pointer given by the parameter *cache*. If the parameter *delete* is
+ true, the object pointed to by *cache* will be deleted when the reference
+ count of the returned object reaches 0. The parameter *owner* shall point
+ to a object of the type :cpp:var:`PyCacheFile_Type`.
+
+.. cpp:function:: pkgCache* PyCache_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`pkgCache` pointer contained in the Python object
+ *object*.
+
+
+CacheFile (pkgCacheFile)
+------------------------
+.. cpp:var:: PyTypeObject PyCacheFile_Type
+
+ The type object for CacheFile. This type is internal and not exported to
+ Python anywhere.
+
+.. cpp:function:: int PyCacheFile_Check(PyObject *object)
+
+ Check that the object *object* is of the type :cpp:var:`PyCacheFile_Type` or
+ a subclass thereof.
+
+.. cpp:function:: int PyCacheFile_CheckExact(PyObject *object)
+
+ Check that the object *object* is of the type :cpp:var:`PyCacheFile_Type` and
+ no subclass thereof.
+
+.. cpp:function:: PyObject* PyCacheFile_FromCpp(pkgCacheFile *file, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.CacheFile` object from the :cpp:type:`pkgCacheFile`
+ pointer given by the parameter *file* If the parameter *delete* is
+ true, the object pointed to by *file* will be deleted when the reference
+ count of the returned object reaches 0.
+
+.. cpp:function:: pkgCacheFile* PyCacheFile_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`pkgCacheFile` pointer contained in the Python object
+ *object*.
+
+Cdrom (pkgCdrom)
+------------------------
+.. cpp:var:: PyTypeObject PyCdrom_Type
+
+ The type object for :class:`apt_pkg.Cdrom` objects.
+
+.. cpp:function:: int PyCdrom_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Cdrom` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyCdrom_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Cdrom` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyCdrom_FromCpp(pkgCdrom &cdrom, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.Cdrom` object from the :cpp:type:`pkgCdrom`
+ reference given by the parameter *cdrom*. If the parameter *delete* is
+ true, *cdrom* will be deleted when the reference count of the returned
+ object reaches 0.
+
+.. cpp:function:: pkgCdrom& PyCdrom_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`pkgCdrom` reference contained in the Python object
+ *object*.
+
+Configuration (Configuration)
+-------------------------------
+.. cpp:var:: PyTypeObject PyConfiguration_Type
+
+ The type object for :class:`apt_pkg.Configuration` objects.
+
+.. cpp:function:: int PyConfiguration_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Configuration` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyConfiguration_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Configuration` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyConfiguration_FromCpp(Configuration *cpp, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.Configuration` object from the :cpp:type:`Configuration`
+ pointer given by the parameter *cpp*. If the parameter *delete* is
+ true, the object pointed to by *cpp* will be deleted when the reference
+ count of the returned object reaches 0. The parameter *owner* may refer to
+ a parent object (e.g. when exposing a sub tree of a configuration object).
+
+.. cpp:function:: Configuration* PyConfiguration_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`Configuration` pointer contained in the Python object
+ *object*.
+
+DepCache (pkgDepCache)
+------------------------
+.. cpp:var:: PyTypeObject PyDepCache_Type
+
+ The type object for :class:`apt_pkg.DepCache` objects.
+
+.. cpp:function:: int PyDepCache_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.DepCache` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyDepCache_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.DepCache` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyDepCache_FromCpp(pkgDepCache *cpp, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.DepCache` object from the :cpp:type:`pkgDepCache`
+ pointer given by the parameter *cpp*. If the parameter *delete* is
+ true, the object pointed to by *cpp* will be deleted when the reference
+ count of the returned object reaches 0. The parameter *owner* must be
+ a PyObject of the type :cpp:var:`PyCache_Type`.
+
+.. cpp:function:: pkgDepCache* PyDepCache_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`pkgDepCache` pointer contained in the Python object
+ *object*.
+
+Dependency (pkgCache::DepIterator)
+----------------------------------
+.. cpp:var:: PyTypeObject PyDependency_Type
+
+ The type object for :class:`apt_pkg.Dependency` objects.
+
+.. cpp:function:: int PyDependency_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Dependency` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyDependency_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Dependency` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyDependency_FromCpp(pkgCache::DepIterator &cpp, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.Dependency` object from the :cpp:type:`pkgCache::DepIterator`
+ reference given by the parameter *cpp*. If the parameter *delete* is
+ true, *cpp* will be deleted when the reference
+ count of the returned object reaches 0. The parameter *owner* must be
+ a PyObject of the type :cpp:var:`PyPackage_Type`.
+
+.. cpp:function:: pkgCache::DepIterator& PyDependency_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`pkgCache::DepIterator` reference contained in the
+ Python object *object*.
+
+Description (pkgCache::DescIterator)
+------------------------------------
+.. cpp:var:: PyTypeObject PyDescription_Type
+
+ The type object for :class:`apt_pkg.Description` objects.
+
+.. cpp:function:: int PyDescription_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Description` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyDescription_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Description` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyDescription_FromCpp(pkgCache::DescIterator &cpp, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.Description` object from the :cpp:type:`pkgCache::DescIterator`
+ reference given by the parameter *cpp*. If the parameter *delete* is
+ true, *cpp* will be deleted when the reference
+ count of the returned object reaches 0. The parameter *owner* must be
+ a PyObject of the type :cpp:var:`PyPackage_Type`.
+
+.. cpp:function:: pkgCache::DescIterator& PyDescription_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`pkgCache::DescIterator` reference contained in the
+ Python object *object*.
+
+
+Group (pkgCache::GrpIterator)
+----------------------------------
+.. versionadded:: 0.8.0
+
+.. cpp:var:: PyTypeObject PyGroup_Type
+
+ The type object for :class:`apt_pkg.Group` objects.
+
+.. cpp:function:: int PyGroup_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Group` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyGroup_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Group` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyGroup_FromCpp(pkgCache::GrpIterator &cpp, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.Group` object from the :cpp:type:`pkgCache::GrpIterator`
+ reference given by the parameter *cpp*. If the parameter *delete* is
+ true, *cpp* will be deleted when the reference
+ count of the returned object reaches 0. The parameter *owner* should be
+ a PyObject of the type :cpp:var:`PyCache_Type`.
+
+.. cpp:function:: pkgCache::GrpIterator& PyGroup_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`pkgCache::GrpIterator` reference contained in the
+ Python object *object*.
+
+Hashes (Hashes)
+----------------------------------
+.. cpp:var:: PyTypeObject PyHashes_Type
+
+ The type object for :class:`apt_pkg.Hashes` objects.
+
+.. cpp:function:: int PyHashes_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Hashes` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyHashes_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Hashes` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyHashes_FromCpp(Hashes &cpp, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.Hashes` object from the :cpp:type:`Hashes`
+ reference given by the parameter *cpp*. If the parameter *delete* is
+ true, *cpp* will be deleted when the reference count of the returned
+ object reaches 0.
+
+.. cpp:function:: Hashes& PyHashes_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`Hashes` reference contained in the
+ Python object *object*.
+
+HashString (HashString)
+------------------------
+.. cpp:var:: PyTypeObject PyHashString_Type
+
+ The type object for :class:`apt_pkg.HashString` objects.
+
+.. cpp:function:: int PyHashString_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.HashString` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyHashString_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.HashString` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyHashString_FromCpp(HashString *cpp, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.HashString` object from the :cpp:type:`HashString`
+ pointer given by the parameter *cpp*. If the parameter *delete* is
+ true, the object pointed to by *cpp* will be deleted when the reference
+ count of the returned object reaches 0.
+
+.. cpp:function:: HashString* PyHashString_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`HashString` pointer contained in the Python object
+ *object*.
+
+IndexRecords (indexRecords)
+----------------------------
+.. cpp:var:: PyTypeObject PyIndexRecords_Type
+
+ The type object for :class:`apt_pkg.IndexRecords` objects.
+
+.. cpp:function:: int PyIndexRecords_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.IndexRecords` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyIndexRecords_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.IndexRecords` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyIndexRecords_FromCpp(indexRecords *cpp, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.IndexRecords` object from the :cpp:type:`indexRecords`
+ pointer given by the parameter *cpp*. If the parameter *delete* is
+ true, the object pointed to by *cpp* will be deleted when the reference
+ count of the returned object reaches 0.
+
+.. cpp:function:: indexRecords* PyIndexRecords_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`indexRecords` pointer contained in the Python object
+ *object*.
+
+
+MetaIndex (metaIndex)
+------------------------
+.. cpp:var:: PyTypeObject PyMetaIndex_Type
+
+ The type object for :class:`apt_pkg.MetaIndex` objects.
+
+.. cpp:function:: int PyMetaIndex_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.MetaIndex` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyMetaIndex_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.MetaIndex` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyMetaIndex_FromCpp(metaIndex *cpp, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.MetaIndex` object from the :cpp:type:`metaIndex`
+ pointer given by the parameter *cpp*. If the parameter *delete* is
+ true, the object pointed to by *cpp* will be deleted when the reference
+ count of the returned object reaches 0. The parameter *owner* should be
+ a PyObject of the type :cpp:var:`PySourceList_Type`.
+
+.. cpp:function:: metaIndex* PyMetaIndex_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`metaIndex` pointer contained in the Python object
+ *object*.
+
+Package (pkgCache::PkgIterator)
+----------------------------------
+.. cpp:var:: PyTypeObject PyPackage_Type
+
+ The type object for :class:`apt_pkg.Package` objects.
+
+.. cpp:function:: int PyPackage_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Package` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyPackage_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Package` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyPackage_FromCpp(pkgCache::PkgIterator &cpp, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.Package` object from the :cpp:type:`pkgCache::PkgIterator`
+ reference given by the parameter *cpp*. If the parameter *delete* is
+ true, *cpp* will be deleted when the reference
+ count of the returned object reaches 0. The parameter *owner* should be
+ a PyObject of the type :cpp:var:`PyCache_Type`.
+
+.. cpp:function:: pkgCache::PkgIterator& PyPackage_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`pkgCache::PkgIterator` reference contained in the
+ Python object *object*.
+
+PackageFile (pkgCache::PkgFileIterator)
+----------------------------------------
+.. cpp:var:: PyTypeObject PyPackageFile_Type
+
+ The type object for :class:`apt_pkg.PackageFile` objects.
+
+.. cpp:function:: int PyPackageFile_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.PackageFile` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyPackageFile_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.PackageFile` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyPackageFile_FromCpp(pkgCache::PkgFileIterator &cpp, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.PackageFile` object from the :cpp:type:`pkgCache::PkgFileIterator`
+ reference given by the parameter *cpp*. If the parameter *delete* is
+ true, *cpp* will be deleted when the reference
+ count of the returned object reaches 0. The parameter *owner* should be
+ a PyObject of the type :cpp:var:`PyCache_Type`.
+
+.. cpp:function:: pkgCache::PkgFileIterator& PyPackageFile_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`pkgCache::PkgFileIterator` reference contained in the
+ Python object *object*.
+
+IndexFile (pkgIndexFile)
+--------------------------------------
+.. cpp:var:: PyTypeObject PyIndexFile_Type
+
+ The type object for :class:`apt_pkg.IndexFile` objects.
+
+.. cpp:function:: int PyIndexFile_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.IndexFile` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyIndexFile_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.IndexFile` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyIndexFile_FromCpp(pkgIndexFile *cpp, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.IndexFile` object from the :cpp:type:`pkgIndexFile`
+ pointer given by the parameter *cpp*. If the parameter *delete* is
+ true, the object pointed to by *cpp* will be deleted when the reference
+ count of the returned object reaches 0. The parameter *owner* should be
+ a PyObject of the type :cpp:var:`PyMetaIndex_Type`.
+
+.. cpp:function:: pkgIndexFile* PyIndexFile_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`pkgIndexFile` pointer contained in the Python object
+ *object*.
+
+OrderList (pkgOrderList)
+---------------------------
+.. cpp:var:: PyTypeObject PyOrderList_Type
+
+ The type object for :class:`apt_pkg.OrderList` objects.
+
+.. cpp:function:: int PyOrderList_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.OrderList` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyOrderList_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.OrderList` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyOrderList_FromCpp(pkgOrderList *cpp, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.OrderList` object from the :cpp:type:`pkgOrderList`
+ pointer given by the parameter *cpp*. If the parameter *delete* is
+ true, the object pointed to by *cpp* will be deleted when the reference
+ count of the returned object reaches 0. The owner must be a
+ :class:`apt_pkg.DepCache` object.
+
+.. cpp:function:: pkgOrderList* PyOrderList_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`pkgOrderList` pointer contained in the Python object
+ *object*.
+
+PackageManager (pkgPackageManager)
+----------------------------------
+.. cpp:var:: PyTypeObject PyPackageManager_Type
+
+ The type object for :class:`apt_pkg.PackageManager` objects.
+
+.. cpp:function:: int PyPackageManager_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.PackageManager` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyPackageManager_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.PackageManager` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyPackageManager_FromCpp(pkgPackageManager *cpp, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.PackageManager` object from the :cpp:type:`pkgPackageManager`
+ pointer given by the parameter *cpp*. If the parameter *delete* is
+ true, the object pointed to by *cpp* will be deleted when the reference
+ count of the returned object reaches 0.
+
+.. cpp:function:: pkgPackageManager* PyPackageManager_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`pkgPackageManager` pointer contained in the Python object
+ *object*.
+
+
+Policy (pkgPolicy)
+------------------
+.. cpp:var:: PyTypeObject PyPolicy_Type
+
+ The type object for :class:`apt_pkg.Policy` objects.
+
+.. cpp:function:: int PyPolicy_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Policy` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyPolicy_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Policy` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyPolicy_FromCpp(pkgPolicy *cpp, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.Policy` object from the :cpp:type:`pkgPolicy`
+ pointer given by the parameter *cpp*. If the parameter *delete* is
+ true, the object pointed to by *cpp* will be deleted when the reference
+ count of the returned object reaches 0. The parameter *owner* must be
+ a PyObject of the type :cpp:var:`PyCache_Type`.
+
+.. cpp:function:: pkgPolicy* PyPolicy_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`pkgPolicy` pointer contained in the Python object
+ *object*.
+
+
+ProblemResolver (pkgProblemResolver)
+--------------------------------------
+.. cpp:var:: PyTypeObject PyProblemResolver_Type
+
+ The type object for :class:`apt_pkg.ProblemResolver` objects.
+
+.. cpp:function:: int PyProblemResolver_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.ProblemResolver` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyProblemResolver_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.ProblemResolver` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyProblemResolver_FromCpp(pkgProblemResolver *cpp, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.ProblemResolver` object from the :cpp:type:`pkgProblemResolver`
+ pointer given by the parameter *cpp*. If the parameter *delete* is
+ true, the object pointed to by *cpp* will be deleted when the reference
+ count of the returned object reaches 0. The parameter *owner* must be
+ a PyObject of the type :cpp:var:`PyDepCache_Type`.
+
+.. cpp:function:: pkgProblemResolver* PyProblemResolver_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`pkgProblemResolver` pointer contained in the Python object
+ *object*.
+
+
+
+SourceList (pkgSourceList)
+---------------------------
+.. cpp:var:: PyTypeObject PySourceList_Type
+
+ The type object for :class:`apt_pkg.SourceList` objects.
+
+.. cpp:function:: int PySourceList_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.SourceList` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PySourceList_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.SourceList` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PySourceList_FromCpp(pkgSourceList *cpp, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.SourceList` object from the :cpp:type:`pkgSourceList`
+ pointer given by the parameter *cpp*. If the parameter *delete* is
+ true, the object pointed to by *cpp* will be deleted when the reference
+ count of the returned object reaches 0.
+
+.. cpp:function:: pkgSourceList* PySourceList_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`pkgSourceList` pointer contained in the Python object
+ *object*.
+
+
+TagFile (pkgTagFile)
+----------------------------------
+.. cpp:var:: PyTypeObject PyTagFile_Type
+
+ The type object for :class:`apt_pkg.TagFile` objects.
+
+.. cpp:function:: int PyTagFile_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.TagFile` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyTagFile_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.TagFile` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyTagFile_FromCpp(pkgTagFile &cpp, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.TagFile` object from the :cpp:type:`pkgTagFile`
+ reference given by the parameter *cpp*. If the parameter *delete* is
+ true, *cpp* will be deleted when the reference
+ count of the returned object reaches 0. The parameter *owner* may be any
+ Python object.
+
+.. cpp:function:: pkgTagFile& PyTagFile_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`pkgTagFile` reference contained in the
+ Python object *object*.
+
+TagSection (pkgTagSection)
+----------------------------------
+.. cpp:var:: PyTypeObject PyTagSection_Type
+
+ The type object for :class:`apt_pkg.TagSection` objects.
+
+.. cpp:function:: int PyTagSection_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.TagSection` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyTagSection_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.TagSection` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyTagSection_FromCpp(pkgTagSection &cpp, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.TagSection` object from the :cpp:type:`pkgTagSection`
+ reference given by the parameter *cpp*. If the parameter *delete* is
+ true, *cpp* will be deleted when the reference
+ count of the returned object reaches 0. The parameter *owner* may be
+ a PyObject of the type :cpp:var:`PyTagFile_Type`.
+
+.. cpp:function:: pkgTagSection& PyTagSection_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`pkgTagSection` reference contained in the
+ Python object *object*.
+
+Version (pkgCache::VerIterator)
+----------------------------------
+.. cpp:var:: PyTypeObject PyVersion_Type
+
+ The type object for :class:`apt_pkg.Version` objects.
+
+.. cpp:function:: int PyVersion_Check(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Version` object, or
+ a subclass thereof.
+
+.. cpp:function:: int PyVersion_CheckExact(PyObject *object)
+
+ Check that the object *object* is an :class:`apt_pkg.Version` object
+ and no subclass thereof.
+
+.. cpp:function:: PyObject* PyVersion_FromCpp(pkgCache::VerIterator &cpp, bool delete, PyObject *owner)
+
+ Create a new :class:`apt_pkg.Version` object from the :cpp:type:`pkgCache::VerIterator`
+ reference given by the parameter *cpp*. If the parameter *delete* is
+ true, *cpp* will be deleted when the reference
+ count of the returned object reaches 0. The parameter *owner* must be
+ a PyObject of the type :cpp:var:`PyPackage_Type`.
+
+.. cpp:function:: pkgCache::VerIterator& PyVersion_ToCpp(PyObject *object)
+
+ Return the :cpp:type:`pkgCache::VerIterator` reference contained in the
+ Python object *object*.
diff --git a/doc/source/c++/embedding.rst b/doc/source/c++/embedding.rst
new file mode 100644
index 0000000..cb175f8
--- /dev/null
+++ b/doc/source/c++/embedding.rst
@@ -0,0 +1,34 @@
+.. highlight:: c++
+
+Embedding Python APT
+====================
+This is a very basic tutorial for working with the C++ bindings.
+
+Basics
+-------
+To use the python-apt C++ bindings, first include the
+``python-apt/python-apt.h`` header::
+
+ #include <python-apt/python-apt.h>
+
+Now, the module needs to be initialized. This is done by calling the function
+:c:func:`import_apt_pkg`. This function returns 0 on success and a negative
+value in case of failure::
+
+ if (import_apt_pkg() < 0)
+ return;
+
+Longer example
+--------------
+The following code will create a standalone application which provides a
+module ``client`` with the attribute ``hash`` which stores an object of the
+type :class:`apt_pkg.HashString`:
+
+.. literalinclude:: ../../client-example.cc
+
+
+.. highlight:: sh
+
+If this file were called client-example.cc, you could compile it using::
+
+ g++ -lapt-pkg -lpython2.5 -I/usr/include/python2.5 -o client client-example.cc
diff --git a/doc/source/c++/index.rst b/doc/source/c++/index.rst
new file mode 100644
index 0000000..8f598f3
--- /dev/null
+++ b/doc/source/c++/index.rst
@@ -0,0 +1,8 @@
+Python APT and C++
+==================
+
+.. toctree::
+ :maxdepth: 1
+
+ api
+ embedding
diff --git a/doc/source/conf.py b/doc/source/conf.py
new file mode 100644
index 0000000..079cc50
--- /dev/null
+++ b/doc/source/conf.py
@@ -0,0 +1,245 @@
+#
+# python-apt documentation build configuration file, created by
+# sphinx-quickstart on Wed Jan 7 17:04:36 2009.
+#
+# This file is execfile()d with the current directory set to its containing
+# dir.
+#
+# The contents of this file are pickled, so don't put values in the namespace
+# that aren't pickleable (module imports are okay, they're removed
+# automatically).
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+import glob
+import os
+import sys
+
+# Find the path to the built apt_pkg and apt_inst extensions
+if os.path.exists("../../build"):
+ version = ".".join(str(x) for x in sys.version_info[:2])
+ for apt_pkg_path in glob.glob("../../build/lib*%s/*.so" % version):
+ sys.path.insert(0, os.path.abspath(os.path.dirname(apt_pkg_path)))
+ try:
+ import apt_pkg
+
+ apt_pkg # pyflakes
+ except ImportError as exc:
+ # Not the correct version
+ sys.stderr.write("W: Ignoring error %s\n" % exc)
+ sys.path.pop(0)
+ else:
+ sys.stdout.write("I: Found apt_pkg.so in %s\n" % sys.path[0])
+ break
+
+
+# General configuration
+# ---------------------
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = [
+ "sphinx.ext.autodoc",
+ "sphinx.ext.doctest",
+ "sphinx.ext.intersphinx",
+ "sphinx.ext.todo",
+]
+intersphinx_mapping = {"http://docs.python.org/": None}
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ["templates"]
+
+# The suffix of source filenames.
+source_suffix = ".rst"
+
+# The encoding of source files.
+# source_encoding = 'utf-8'
+
+# The master toctree document.
+master_doc = "contents"
+
+# General information about the project.
+project = "python-apt"
+copyright = "2009-2010, Julian Andres Klode <jak@debian.org>"
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+
+try:
+ release = os.environ["DEBVER"]
+except KeyError:
+ from subprocess import PIPE, Popen
+
+ p1 = Popen(["dpkg-parsechangelog", "-l../../debian/changelog"], stdout=PIPE)
+ p2 = Popen(["sed", "-n", "s/^Version: //p"], stdin=p1.stdout, stdout=PIPE)
+ release = p2.communicate()[0].decode("utf-8")
+
+
+# Handle the alpha release scheme
+release_raw = "0"
+for c in release.split("~")[0].split(".")[2]:
+ if not c.isdigit():
+ break
+ release_raw += c
+
+if int(release_raw) >= 90:
+ version_s = release.split("~")[0].split(".")[:3]
+ # Set the version to 0.X.100 if the release is 0.X.9Y (0.7.90 => 0.7.100)
+ # Use
+ # version_s[1] = str(int(version_s[1]) + 1)
+ # version_s[2] = "0"
+ # if the version of a 0.X.9Y release should be 0.X+1.0 (0.7.90=>0.8)
+ version_s[2] = "100"
+ version = ".".join(version_s)
+ del version_s
+else:
+ version = ".".join(release.split("~")[0].split(".")[:2])
+del release_raw
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+# language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+# today = ''
+# Else, today_fmt is used as the format for a strftime call.
+# today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+# unused_docs = []
+
+# List of directories, relative to source directory, that shouldn't be searched
+# for source files.
+exclude_trees = []
+
+# The reST default role (used for this markup: `text`) for all documents.
+# default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+# add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+# add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+# show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = "sphinx"
+
+
+# Options for HTML output
+# -----------------------
+
+# The style sheet to use for HTML and HTML Help pages. A file of that name
+# must exist either in Sphinx' static/ path, or in one of the custom paths
+# given in html_static_path.
+# html_style = 'default.css'
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+# html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+# html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+# html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+# html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = [".static"]
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+html_last_updated_fmt = None
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+# html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+# html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+html_additional_pages = {"index": "indexcontent.html"}
+
+# If false, no module index is generated.
+# html_use_modindex = True
+
+# If false, no index is generated.
+# html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+# html_split_index = False
+
+# If true, the reST sources are included in the HTML build as _sources/<name>.
+# html_copy_source = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+# html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+# html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = "python-aptdoc"
+
+
+# Options for LaTeX output
+# ------------------------
+
+# The paper size ('letter' or 'a4').
+# latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+# latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source index, target name, title, author, document class [howto/manual]).
+latex_documents = [
+ (
+ "contents",
+ "python-apt.tex",
+ "python-apt Documentation",
+ "Julian Andres Klode <jak@debian.org>",
+ "manual",
+ ),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+# latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+# latex_use_parts = False
+
+# Additional stuff for the LaTeX preamble.
+# latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+# latex_appendices = []
+
+# If false, no module index is generated.
+# latex_use_modindex = True
+
+todo_include_todos = True
diff --git a/doc/source/contents.rst b/doc/source/contents.rst
new file mode 100644
index 0000000..6c4e161
--- /dev/null
+++ b/doc/source/contents.rst
@@ -0,0 +1,19 @@
+Python APT Documentation contents
+======================================
+
+Contents:
+
+.. toctree::
+
+ whatsnew/index
+ library/index
+ tutorials/index
+ c++/index
+
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`search`
diff --git a/doc/source/examples/apt-cdrom.py b/doc/source/examples/apt-cdrom.py
new file mode 100644
index 0000000..13bfb97
--- /dev/null
+++ b/doc/source/examples/apt-cdrom.py
@@ -0,0 +1,79 @@
+#!/usr/bin/python3
+import sys
+
+import apt_pkg
+
+import apt
+
+
+def show_help():
+ print(f"apt {apt_pkg.VERSION} compiled on {apt_pkg.DATE} {apt_pkg.TIME}")
+ if apt_pkg.config.find_b("version"):
+ return 0
+
+ # Copied from apt-cdrom
+ print(
+ "Usage: apt-cdrom [options] command\n"
+ "\n"
+ "apt-cdrom is a tool to add CDROM's to APT's source list. The\n"
+ "CDROM mount point and device information is taken from apt.conf\n"
+ "and /etc/fstab.\n"
+ "\n"
+ "Commands:\n"
+ " add - Add a CDROM\n"
+ " ident - Report the identity of a CDROM\n"
+ "\n"
+ "Options:\n"
+ " -h This help text\n"
+ " -d CD-ROM mount point\n"
+ " -r Rename a recognized CD-ROM\n"
+ " -m No mounting\n"
+ " -f Fast mode, don't check package files\n"
+ " -a Thorough scan mode\n"
+ " -c=? Read this configuration file\n"
+ " -o=? Set an arbitrary configuration option, eg -o "
+ "dir::cache=/tmp\n"
+ "See fstab(5)"
+ )
+ return 0
+
+
+def main(args):
+ arguments = apt_pkg.parse_commandline(
+ apt_pkg.config,
+ [
+ ("h", "help", "help"),
+ ("v", "version", "version"),
+ ("d", "cdrom", "Acquire::cdrom::mount", "HasArg"),
+ ("r", "rename", "APT::CDROM::Rename"),
+ ("m", "no-mount", "APT::CDROM::NoMount"),
+ ("f", "fast", "APT::CDROM::Fast"),
+ ("n", "just-print", "APT::CDROM::NoAct"),
+ ("n", "recon", "APT::CDROM::NoAct"),
+ ("n", "no-act", "APT::CDROM::NoAct"),
+ ("a", "thorough", "APT::CDROM::Thorough"),
+ ("c", "config-file", "", "ConfigFile"),
+ ("o", "option", "", "ArbItem"),
+ ],
+ args,
+ )
+
+ if apt_pkg.config.find_b("help") or apt_pkg.config.find_b("version"):
+ return show_help()
+
+ progress = apt.progress.text.CdromProgress()
+ cdrom = apt_pkg.Cdrom()
+
+ if not arguments:
+ return show_help()
+ elif arguments[0] == "add":
+ cdrom.add(progress)
+ elif arguments[0] == "ident":
+ cdrom.ident(progress)
+ else:
+ sys.stderr.write("E: Invalid operation %s\n" % arguments[0])
+ return 1
+
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
diff --git a/doc/source/examples/cache-packages.py b/doc/source/examples/cache-packages.py
new file mode 100755
index 0000000..14ba85a
--- /dev/null
+++ b/doc/source/examples/cache-packages.py
@@ -0,0 +1,23 @@
+#!/usr/bin/python3
+"""Example for packages. Print all essential and important packages"""
+
+import apt_pkg
+
+
+def main():
+ """Main."""
+ apt_pkg.init_config()
+ apt_pkg.init_system()
+ cache = apt_pkg.Cache()
+ print("Essential packages:")
+ for pkg in cache.packages:
+ if pkg.essential:
+ print(" ", pkg.name)
+ print("Important packages:")
+ for pkg in cache.packages:
+ if pkg.important:
+ print(" ", pkg.name)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/doc/source/examples/cache-pkgfile.py b/doc/source/examples/cache-pkgfile.py
new file mode 100755
index 0000000..4e94a7a
--- /dev/null
+++ b/doc/source/examples/cache-pkgfile.py
@@ -0,0 +1,30 @@
+#!/usr/bin/python3
+import apt_pkg
+
+
+def main():
+ """Example for PackageFile()"""
+ apt_pkg.init()
+ cache = apt_pkg.Cache()
+ for pkgfile in cache.file_list:
+ print("Package-File:", pkgfile.filename)
+ print("Index-Type:", pkgfile.index_type) # 'Debian Package Index'
+ if pkgfile.not_source:
+ print("Source: None")
+ else:
+ if pkgfile.site:
+ # There is a source, and a site, print the site
+ print("Source:", pkgfile.site)
+ else:
+ # It seems to be a local repository
+ print("Source: Local package file")
+ if pkgfile.not_automatic:
+ # The system won't be updated automatically (eg. experimental)
+ print("Automatic: No")
+ else:
+ print("Automatic: Yes")
+ print()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/doc/source/examples/dpkg-contents.py b/doc/source/examples/dpkg-contents.py
new file mode 100755
index 0000000..e6ff620
--- /dev/null
+++ b/doc/source/examples/dpkg-contents.py
@@ -0,0 +1,68 @@
+#!/usr/bin/python3
+"""Emulate dpkg --contents"""
+
+import grp
+import pwd
+import stat
+import sys
+import time
+
+import apt_inst
+
+
+def format_mode(member):
+ """Return the symbolic mode"""
+ mode = member.mode
+ if member.isdir():
+ s_mode = "d"
+ elif member.islnk():
+ s_mode = "h"
+ else:
+ s_mode = "-"
+ s_mode += (mode & stat.S_IRUSR) and "r" or "-"
+ s_mode += (mode & stat.S_IWUSR) and "w" or "-"
+ s_mode += (
+ (mode & stat.S_IXUSR)
+ and (mode & stat.S_ISUID and "s" or "x")
+ or (mode & stat.S_ISUID and "S" or "-")
+ )
+ s_mode += (mode & stat.S_IRGRP) and "r" or "-"
+ s_mode += (mode & stat.S_IWGRP) and "w" or "-"
+ s_mode += (
+ (mode & stat.S_IXGRP)
+ and (mode & stat.S_ISGID and "s" or "x")
+ or (mode & stat.S_ISGID and "S" or "-")
+ )
+ s_mode += (mode & stat.S_IROTH) and "r" or "-"
+ s_mode += (mode & stat.S_IWOTH) and "w" or "-"
+ s_mode += (mode & stat.S_IXOTH) and "x" or "-"
+ return s_mode
+
+
+def callback(member, data):
+ """callback for deb_extract"""
+ s_mode = format_mode(member)
+ s_owner = f"{pwd.getpwuid(member.uid)[0]}/{grp.getgrgid(member.gid)[0]}"
+ s_size = "%9d" % member.size
+ s_time = time.strftime("%Y-%m-%d %H:%M", time.localtime(member.mtime))
+ s_name = member.name if member.name.startswith(".") else ("./" + member.name)
+ if member.islnk():
+ s_name += " link to %s" % member.linkname
+ print(s_mode, s_owner, s_size, s_time, s_name)
+
+
+def main():
+ """Main function"""
+ if len(sys.argv) < 2:
+ print("need filename argumnet", file=sys.stderr)
+ sys.exit(1)
+
+ fobj = open(sys.argv[1])
+ try:
+ apt_inst.DebFile(fobj).data.go(callback)
+ finally:
+ fobj.close()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/doc/source/examples/dpkg-extract.py b/doc/source/examples/dpkg-extract.py
new file mode 100755
index 0000000..02a9fdd
--- /dev/null
+++ b/doc/source/examples/dpkg-extract.py
@@ -0,0 +1,27 @@
+#!/usr/bin/python3
+"""Emulate dpkg --extract package.deb outdir"""
+
+import os
+import sys
+
+import apt_inst
+
+
+def main():
+ """Main function."""
+ if len(sys.argv) < 3:
+ print("Usage: %s package.deb outdir\n" % (__file__), file=sys.stderr)
+ sys.exit(1)
+ if not os.path.exists(sys.argv[2]):
+ print("The directory %s does not exist\n" % (sys.argv[2]), file=sys.stderr)
+ sys.exit(1)
+
+ fobj = open(sys.argv[1])
+ try:
+ apt_inst.DebFile(fobj).data.extractall(sys.argv[2])
+ finally:
+ fobj.close()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/doc/source/examples/dpkg-info.py b/doc/source/examples/dpkg-info.py
new file mode 100755
index 0000000..833c4ed
--- /dev/null
+++ b/doc/source/examples/dpkg-info.py
@@ -0,0 +1,22 @@
+#!/usr/bin/python3
+"""Emulate dpkg --info package.deb control-file"""
+
+import sys
+
+from apt_inst import DebFile
+
+
+def main():
+ """Main function."""
+ if len(sys.argv) < 3:
+ print("Usage: tool file.deb control-file\n", file=sys.stderr)
+ sys.exit(0)
+ fobj = open(sys.argv[1])
+ try:
+ print(DebFile(fobj).control.extractdata(sys.argv[2]))
+ finally:
+ fobj.close()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/doc/source/examples/missing-deps.py b/doc/source/examples/missing-deps.py
new file mode 100755
index 0000000..c3c56b8
--- /dev/null
+++ b/doc/source/examples/missing-deps.py
@@ -0,0 +1,59 @@
+#!/usr/bin/python3
+"""Check the archive for missing dependencies"""
+import apt_pkg
+
+
+def fmt_dep(dep):
+ """Format a Dependency object [of apt_pkg] as a string."""
+ ret = dep.target_pkg.name
+ if dep.target_ver:
+ ret += f" ({dep.comp_type} {dep.target_ver})"
+ return ret
+
+
+def check_version(pkgver):
+ """Check the version of the package"""
+ missing = []
+
+ for or_group in pkgver.depends_list.get(
+ "Pre-Depends", []
+ ) + pkgver.depends_list.get("Depends", []):
+ if not any(dep.all_targets() for dep in or_group):
+ # If none of the or-choices can be satisfied, add it to missing
+ missing.append(or_group)
+
+ if missing:
+ print("Package:", pkgver.parent_pkg.name)
+ print("Version:", pkgver.ver_str)
+ print("Missing:")
+ print(
+ ", ".join(" | ".join(fmt_dep(dep) for dep in or_group))
+ for or_group in missing
+ )
+ print()
+
+
+def main():
+ """The main function."""
+ apt_pkg.init_config()
+ apt_pkg.init_system()
+
+ cache = apt_pkg.Cache()
+
+ for pkg in sorted(cache.packages, key=lambda pkg: pkg.name):
+ # pkg is from a list of packages, sorted by name.
+ for version in pkg.version_list:
+ # Check every version
+ for pfile, _ in version.file_list:
+ if (
+ pfile.origin == "Debian"
+ and pfile.component == "main"
+ and pfile.archive == "unstable"
+ ):
+ # We only want packages from Debian unstable main.
+ check_version(version)
+ break
+
+
+if __name__ == "__main__":
+ main()
diff --git a/doc/source/examples/update-print-uris.py b/doc/source/examples/update-print-uris.py
new file mode 100755
index 0000000..02981f8
--- /dev/null
+++ b/doc/source/examples/update-print-uris.py
@@ -0,0 +1,24 @@
+#!/usr/bin/python3
+"""Print out the URIs of all indexes files.
+
+This behaves somewhat like apt-get --print-uris update."""
+import apt_pkg
+
+
+def main():
+ apt_pkg.init_config()
+ apt_pkg.init_system()
+ acquire = apt_pkg.Acquire()
+ slist = apt_pkg.SourceList()
+ # Read the list
+ slist.read_main_list()
+ # Add all indexes to the fetcher.
+ slist.get_indexes(acquire, True)
+
+ # Now print the URI of every item.
+ for item in acquire.items:
+ print(item.desc_uri)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/doc/source/library/apt.cache.rst b/doc/source/library/apt.cache.rst
new file mode 100644
index 0000000..f85deb2
--- /dev/null
+++ b/doc/source/library/apt.cache.rst
@@ -0,0 +1,83 @@
+:mod:`apt.cache` --- The Cache class
+=====================================
+.. automodule:: apt.cache
+
+The Cache class
+---------------
+
+.. autoclass:: Cache
+ :members:
+ :undoc-members:
+
+ .. describe:: cache[pkgname]
+
+ Return a :class:`Package()` for the package with the name *pkgname*.
+
+Example
+^^^^^^^
+
+The following example shows how to load the cache, update it, and upgrade
+all the packages on the system::
+
+ import apt
+ import apt.progress
+
+ # First of all, open the cache
+ cache = apt.Cache()
+ # Now, lets update the package list
+ cache.update()
+ # We need to re-open the cache because it needs to read the package list
+ cache.open(None)
+ # Now we can do the same as 'apt-get upgrade' does
+ cache.upgrade()
+ # or we can play 'apt-get dist-upgrade'
+ cache.upgrade(True)
+ # Q: Why does nothing happen?
+ # A: You forgot to call commit()!
+ cache.commit(apt.progress.TextFetchProgress(),
+ apt.progress.InstallProgress())
+
+
+
+Working with Filters
+--------------------
+.. autoclass:: Filter
+ :members:
+ :inherited-members:
+ :undoc-members:
+
+.. autoclass:: MarkedChangesFilter
+ :members:
+ :inherited-members:
+ :undoc-members:
+
+.. autoclass:: FilteredCache
+ :members:
+ :inherited-members:
+ :undoc-members:
+
+
+Example
+^^^^^^^
+
+This is an example for a filtered cache, which only allows access to the
+packages whose state has been changed, eg. packages marked for installation::
+
+ >>> from apt.cache import FilteredCache, Cache, MarkedChangesFilter
+ >>> cache = apt.Cache()
+ >>> changed = apt.FilteredCache(cache)
+ >>> changed.set_filter(MarkedChangesFilter())
+ >>> print(len(changed) == len(cache.get_changes())) # Both need to have same length
+ True
+
+The ProblemResolver class
+--------------------------
+
+.. autoclass:: ProblemResolver
+ :members:
+
+Exceptions
+----------
+.. autoexception:: FetchCancelledException
+.. autoexception:: FetchFailedException
+.. autoexception:: LockFailedException
diff --git a/doc/source/library/apt.cdrom.rst b/doc/source/library/apt.cdrom.rst
new file mode 100644
index 0000000..56381f1
--- /dev/null
+++ b/doc/source/library/apt.cdrom.rst
@@ -0,0 +1,7 @@
+:mod:`apt.cdrom` - Functionality like in apt-cdrom
+====================================================
+.. automodule:: apt.cdrom
+ :members:
+
+
+
diff --git a/doc/source/library/apt.debfile.rst b/doc/source/library/apt.debfile.rst
new file mode 100644
index 0000000..7133b5a
--- /dev/null
+++ b/doc/source/library/apt.debfile.rst
@@ -0,0 +1,39 @@
+:mod:`apt.debfile` --- Classes related to debian package files
+==============================================================
+The :mod:`apt.debfile` provides classes to work with locally available
+debian packages, or source packages.
+
+.. module:: apt.debfile
+
+Binary packages
+----------------
+.. autoclass:: DebPackage
+ :members:
+ :inherited-members:
+ :undoc-members:
+
+ The :class:`DebPackage` class is a class for working with '.deb' files,
+ also known as Debian packages.
+
+ It provides methods and attributes to get a list of the files in the
+ package, to install the package and much more.
+
+ If you specify *cache* it has to point to an :class:`apt.cache.Cache()`
+ object.
+
+ .. versionchanged:: 0.7.9
+ Introduce all new methods (everything except for :meth:`open()` and
+ :attr:`filelist`)
+
+
+Source packages
+----------------
+.. autoclass:: DscSrcPackage
+ :members:
+ :inherited-members:
+ :undoc-members:
+
+ Provide functionality to work with locally available source packages,
+ especially with their '.dsc' file.
+
+ .. versionadded:: 0.7.9
diff --git a/doc/source/library/apt.package.rst b/doc/source/library/apt.package.rst
new file mode 100644
index 0000000..ec7ed36
--- /dev/null
+++ b/doc/source/library/apt.package.rst
@@ -0,0 +1,122 @@
+:mod:`apt.package` --- Classes for package handling
+====================================================
+
+
+.. automodule:: apt.package
+
+
+The Package class
+-----------------
+.. autoclass:: Package
+ :members:
+
+ .. note::
+
+ Several methods have been deprecated in version 0.7.9 of python-apt,
+ please see the :class:`Version` class for the new alternatives.
+
+The Version class
+-----------------
+.. autoclass:: Version
+ :members:
+
+
+Dependency Information
+----------------------
+.. autoclass:: BaseDependency
+ :members:
+
+.. class:: Dependency
+
+ The dependency class represents a Or-Group of dependencies. It provides
+ an attribute to access the :class:`BaseDependency` object for the available
+ choices.
+
+ .. attribute:: or_dependencies
+
+ A list of :class:`BaseDependency` objects which could satisfy the
+ requirement of the Or-Group.
+
+
+Origin Information
+-------------------
+.. class:: Origin
+
+ The :class:`Origin` class provides access to the origin of the package.
+ It allows you to check the component, archive, the hostname, and even if
+ this package can be trusted.
+
+ .. attribute:: archive
+
+ The archive (eg. unstable)
+
+ .. attribute:: component
+
+ The component (eg. main)
+
+ .. attribute:: label
+
+ The Label, as set in the Release file
+
+ .. attribute:: origin
+
+ The Origin, as set in the Release file
+
+ .. attribute:: site
+
+ The hostname of the site.
+
+ .. attribute:: trusted
+
+ Boolean value whether this is trustworthy. An origin can be trusted, if
+ it provides a GPG-signed Release file and the GPG-key used is in the
+ keyring used by apt (see apt-key).
+
+
+
+The Record class
+-----------------
+.. autoclass:: Record
+ :members:
+
+ .. note::
+ .. versionchanged:: 0.7.100
+ This class is a subclass of :class:`collections.Mapping` when used
+ in Python 2.6 or newer.
+
+ .. describe:: record[name]
+
+ Return the value of the field with the name *name*.
+
+ .. describe:: name in record
+
+ Return whether a field *name* exists in record.
+
+ .. describe:: len(record)
+
+ The number of fields in the record
+
+ .. describe:: str(record)
+
+ Display the record as a string
+
+
+Examples
+---------
+.. code-block:: python
+
+ import apt
+
+ cache = apt.Cache()
+ pkg = cache['python-apt'] # Access the Package object for python-apt
+ print('python-apt is trusted:', pkg.candidate.origins[0].trusted)
+
+ # Mark python-apt for install
+ pkg.mark_install()
+
+ print('python-apt is marked for install:', pkg.marked_install)
+
+ print('python-apt is (summary):', pkg.candidate.summary)
+
+ # Now, really install it
+ cache.commit()
diff --git a/doc/source/library/apt.progress.base.rst b/doc/source/library/apt.progress.base.rst
new file mode 100644
index 0000000..7d43fe9
--- /dev/null
+++ b/doc/source/library/apt.progress.base.rst
@@ -0,0 +1,335 @@
+:mod:`apt.progress.base` --- Abstract classes for progress reporting
+====================================================================
+.. module:: apt.progress.base
+
+This module provides base classes for progress handlers from which all
+progress classes should inherit from. Progress reporting classes not
+inheriting from those classes may not work and are not supported.
+
+When creating a subclass of one of those classes, all overridden methods should
+call the parent's method first before doing anything else, because the parent
+method may have to set some attributes. Subclasses not doing so may not work
+correctly or may not work at all and are completely unsupported.
+
+AcquireProgress
+---------------
+.. class:: AcquireProgress
+
+ A monitor object for downloads controlled by the Acquire class. This base
+ class does nothing and should only be used as a base class to inherit
+ from. Instances of this class can be passed to the constructor of
+ :class:`apt_pkg.Acquire` and the Acquire object then uses it to report
+ its progress.
+
+ This class provides several methods which may be overridden by subclasses
+ to implement progress reporting:
+
+ .. method:: done(item: apt_pkg.AcquireItemDesc)
+
+ Invoked when an item is successfully and completely fetched.
+
+ .. method:: fail(item: apt_pkg.AcquireItemDesc)
+
+ Invoked when the process of fetching an item encounters a fatal error
+ like a non existing file or no connection to the server.
+
+ .. method:: fetch(item: apt_pkg.AcquireItemDesc)
+
+ Invoked when some of the item's data is fetched. This normally means
+ that the file is being fetched now and e.g. the headers have been
+ retrieved already.
+
+ .. method:: ims_hit(item: apt_pkg.AcquireItemDesc)
+
+ Invoked when an item is confirmed to be up-to-date. For instance,
+ when an HTTP download is informed that the file on the server was
+ not modified.
+
+ .. method:: media_change(media: str, drive: str) -> bool
+
+ Prompt the user to change the inserted removable media. This function
+ is called whenever a media change is needed to ask the user to insert
+ the needed media.
+
+ The parameter *media* decribes the name of the media type that
+ should be changed, whereas the parameter *drive* should be the
+ identifying name of the drive whose media should be changed.
+
+ This method should not return until the user has confirmed to the user
+ interface that the media change is complete. It must return True if
+ the user confirms the media change, or False to cancel it.
+
+ .. method:: pulse(owner: apt_pkg.Acquire) -> bool
+
+ This method gets invoked while the Acquire progress given by the
+ parameter *owner* is underway. It should display information about
+ the current state. It must return ``True`` to continue the acquistion
+ or ``False`` to cancel it. This base implementation always returns
+ ``True``.
+
+ .. method:: start()
+
+ Invoked when the Acquire process starts running.
+
+ .. method:: stop()
+
+ Invoked when the Acquire process stops running.
+
+ In addition to those methods, this class provides several attributes which
+ are set automatically and represent the fetch progress:
+
+ .. attribute:: current_bytes
+
+ The number of bytes fetched.
+
+ .. attribute:: current_cps
+
+ The current rate of download, in bytes per second.
+
+ .. attribute:: current_items
+
+ The number of items that have been successfully downloaded.
+
+ .. attribute:: elapsed_time
+
+ The amount of time that has elapsed since the download started.
+
+ .. attribute:: fetched_bytes
+
+ The total number of bytes accounted for by items that were
+ successfully fetched.
+
+ .. attribute:: last_bytes
+
+ The number of bytes fetched as of the previous call to pulse(),
+ including local items.
+
+ .. attribute:: total_bytes
+
+ The total number of bytes that need to be fetched. This member is
+ inaccurate, as new items might be enqueued while the download is
+ in progress!
+
+ .. attribute:: total_items
+
+ The total number of items that need to be fetched. This member is
+ inaccurate, as new items might be enqueued while the download is
+ in progress!
+
+
+CdromProgress
+-------------
+.. class:: CdromProgress
+
+ Base class for reporting the progress of adding a cdrom which could be
+ used with apt_pkg.Cdrom to produce an utility like apt-cdrom.
+
+ Methods defined here:
+
+ .. method:: ask_cdrom_name() -> str
+
+ Ask for the name of the cdrom. This method is called when a CD-ROM
+ is added (e.g. via :meth:`apt_pkg.Cdrom.add`) and no label for the
+ CD-ROM can be found.
+
+ Implementations should request a label from the user (e.g. via
+ :func:`raw_input`) and return this label from the function. The
+ operation can be cancelled if the function returns ``None`` instead
+ of a string.
+
+ .. method:: change_cdrom() -> bool
+
+ Ask for the CD-ROM to be changed. This method should return ``True``
+ if the CD-ROM has been changed or ``False`` if the CD-ROM has not been
+ changed and the operation should be cancelled. This base implementation
+ returns ``False`` and thus cancels the operation.
+
+ .. method:: update(text: str, current: int)
+
+ Periodically invoked in order to update the interface and give
+ information about the progress of the operation.
+
+ This method has two parameters. The first parameter *text* defines
+ the text which should be displayed to the user as the progress
+ message. The second parameter *current* is an integer describing how
+ many steps have been completed already.
+
+ .. attribute:: total_steps
+
+ The number of total steps, set automatically by python-apt. It may be
+ used in conjunction with the parameter *current* of the :meth:`update`
+ method to show how far the operation progressed.
+
+
+OpProgress
+----------
+.. class:: OpProgress
+
+ OpProgress classes are used for reporting the progress of operations
+ such as opening the cache. It is based on the concept of one operation
+ consisting of a series of sub operations.
+
+ Methods defined here:
+
+ .. method:: done()
+
+ Called once an operation has been completed.
+
+ .. method:: update([percent=None])
+
+ Called periodically to update the user interface. This function should
+ use the attributes defined below to display the progress information.
+
+ The optional parameter *percent* is included for compatibility
+ reasons and may be removed at a later time.
+
+ The following attributes are available and are changed by the classes
+ wanting to emit progress:
+
+ .. attribute:: major_change
+
+ An automatically set boolean value describing whether the current call
+ to update is caused by a major change. In this case, the last operation
+ has finished.
+
+ .. attribute:: op
+
+ An automatically set string which describes the current operation in
+ an human-readable way.
+
+ .. attribute:: percent
+
+ An automatically set float value describing how much of the operation
+ has been completed, in percent.
+
+ .. attribute:: subop
+
+ An automatically set string which describes the current sub-operation
+ in an human-readable way.
+
+
+InstallProgress
+---------------
+.. class:: InstallProgress
+
+ InstallProgress classes make it possible to monitor the progress of dpkg
+ and APT and emit information at certain stages. It uses file descriptors
+ to read the status lines from APT/dpkg and parses them and afterwards calls
+ the callback methods.
+
+ Subclasses should override the following methods in order to implement
+ progress reporting:
+
+ .. method:: conffile(current, new)
+
+ Called when a conffile question from dpkg is detected.
+
+ .. note::
+
+ This part of the API is semi-stable and may be extended with 2 more
+ parameters before the release of 0.7.100.
+
+ .. method:: error(pkg, errormsg)
+
+ (Abstract) Called when a error is detected during the install.
+
+ The following method should be overridden to implement progress reporting
+ for dpkg-based runs i.e. calls to :meth:`run` with a filename:
+
+ .. method:: processing(pkg, stage)
+
+ This method is called just before a processing stage starts. The
+ parameter *pkg* is the name of the package and the parameter *stage*
+ is one of the stages listed in the dpkg manual under the status-fd
+ option, i.e. "upgrade", "install" (both sent before unpacking),
+ "configure", "trigproc", "remove", "purge".
+
+ .. method:: dpkg_status_change(pkg: str, status: str)
+
+ This method is called whenever the dpkg status of the package
+ changes. The parameter *pkg* is the name of the package and the
+ parameter *status* is one of the status strings used in the status
+ file (:file:`/var/lib/dpkg/status`) and documented
+ in :manpage:`dpkg(1)`.
+
+ The following methods should be overridden to implement progress reporting
+ for :meth:`run` calls with an :class:`apt_pkg.PackageManager` object as
+ their parameter:
+
+ .. method:: status_change(pkg, percent, status)
+
+ This method implements progress reporting for package installation by
+ APT and may be extended to dpkg at a later time.
+
+ This method takes two parameters: The parameter *percent* is a float
+ value describing the overall progress and the parameter *status* is a
+ string describing the current status in an human-readable manner.
+
+ .. method:: start_update()
+
+ This method is called before the installation of any package starts.
+
+ .. method:: finish_update()
+
+ This method is called when all changes have been applied.
+
+ There are also several methods which are fully implemented and should not
+ be overridden by subclasses unless the subclass has very special needs:
+
+ .. method:: fork() -> int
+
+ Fork a child process and return 0 to the child process and the PID of
+ the child to the parent process. This implementation just calls
+ :func:`os.fork` and returns its value.
+
+ .. method:: run(obj)
+
+ This method runs install actions. The parameter *obj* may either
+ be a PackageManager object in which case its **do_install()** method is
+ called or the path to a deb file.
+
+ If the object is a :class:`apt_pkg.PackageManager`, the functions
+ returns the result of calling its ``do_install()`` method. Otherwise,
+ the function returns the exit status of dpkg. In both cases, ``0``
+ means that there were no problems and ``!= 0`` means that there were
+ issues.
+
+ .. method:: update_interface()
+
+ This method is responsible for reading the status from dpkg/APT and
+ calling the correct callback methods. Subclasses should not override
+ this method.
+
+ .. method:: wait_child()
+
+ This method is responsible for calling :meth:`update_interface` from
+ time to time. It exits once the child has exited. The return value
+ is the full status returned by :func:`os.waitpid` (not only the
+ return code). Subclasses should not override this method.
+
+ The class also provides several attributes which may be useful:
+
+ .. attribute:: percent
+
+ The percentage of completion as it was in the last call to
+ :meth:`status_change`.
+
+ .. attribute:: status
+
+ The status string passed in the last call to :meth:`status_change`.
+
+ .. attribute:: select_timeout
+
+ Used in :meth:`wait_child` to when calling :func:`select.select`
+ on dpkg's/APT's status descriptor. Subclasses may set their own value
+ if needed.
+
+ .. attribute:: statusfd
+
+ A readable :class:`file` object from which the status information from
+ APT or dpkg is read.
+
+ .. attribute:: writefd
+
+ A writable :class:`file` object to which dpkg or APT write their status
+ information.
diff --git a/doc/source/library/apt.progress.text.rst b/doc/source/library/apt.progress.text.rst
new file mode 100644
index 0000000..4e051e3
--- /dev/null
+++ b/doc/source/library/apt.progress.text.rst
@@ -0,0 +1,21 @@
+:mod:`apt.progress.text` --- Progress reporting for text interfaces
+===================================================================
+.. automodule:: apt.progress.text
+
+
+Acquire Progress Reporting
+--------------------------
+.. autoclass:: AcquireProgress
+ :members:
+
+
+CD-ROM Progress Reporting
+--------------------------
+.. autoclass:: CdromProgress
+ :members:
+
+Operation Progress Reporting
+-----------------------------
+.. autoclass:: OpProgress
+ :members:
+
diff --git a/doc/source/library/apt_inst.rst b/doc/source/library/apt_inst.rst
new file mode 100644
index 0000000..6ba330a
--- /dev/null
+++ b/doc/source/library/apt_inst.rst
@@ -0,0 +1,323 @@
+:mod:`apt_inst` - Working with local Debian packages
+====================================================
+.. module:: apt_inst
+
+This module provides useful classes and functions to work with archives,
+modelled after the :class:`tarfile.TarFile` class. For working with Debian
+packages, the :class:`DebFile` class should be used as it provides easy access
+to the control.tar.* and data.tar.* members.
+
+The classes are mostly modeled after the :class:`tarfile.TarFile` class and
+enhanced with APT-specific methods. Because APT only provides a stream based
+view on a tar archive, this module's :class:`TarFile` class only provides a
+very small subset of those functions.
+
+Exceptions
+----------
+
+.. class:: Error
+
+ This is the same class as :class:`apt_pkg.Error`, provided here for
+ convenience.
+
+AR Archives
+-----------
+.. class:: ArArchive(file)
+
+ An ArArchive object represents an archive in the 4.4 BSD AR format,
+ which is used for e.g. deb packages.
+
+ The parameter *file* may be a string specifying the path of a file, or
+ a :class:`file`-like object providing the :meth:`fileno` method. It may
+ also be an int specifying a file descriptor (returned by e.g.
+ :func:`os.open`). The recommended way is to pass in the path to the file.
+
+ ArArchive (and its subclasses) support the iterator protocol, meaning that
+ an :class:`ArArchive` object can be iterated over yielding the members in
+ the archive (same as :meth:`getmembers`).
+
+ .. describe:: archive[key]
+
+ Return a ArMember object for the member given by *key*. Raise
+ LookupError if there is no ArMember with the given name.
+
+ .. describe:: key in archive
+
+ Return True if a member with the name *key* is found in the archive, it
+ is the same function as :meth:`getmember`.
+
+ .. method:: extract(name[, target: str]) -> bool
+
+ Extract the member given by *name* into the directory given by
+ *target*. If the extraction failed, an error is raised. Otherwise,
+ the method returns True if the owner could be set or False if the
+ owner could not be changed. It may also raise LookupError if there
+ is no member with the given name.
+
+ The parameter *target* is completely optional. If it is not given, the
+ function extracts into the current directory.
+
+ .. method:: extractall([target: str]) -> bool
+
+ Extract all into the directory given by target or the current
+ directory if target is not given. If the extraction failed, an error
+ is raised. Otherwise, the method returns True if the owner could be
+ set or False if the owner could not be changed.
+
+ .. method:: extractdata(name: str) -> bytes
+
+ Return the contents of the member given by *name*, as a bytes object.
+ Raise LookupError if there is no ArMember with the given name.
+
+ .. method:: getmember(name: str) -> ArMember
+
+ Return a ArMember object for the member given by *name*. Raise
+ LookupError if there is no ArMember with the given name.
+
+ .. method:: getmembers() -> list
+
+ Return a list of all members in the AR archive.
+
+ .. method:: getnames() -> list
+
+ Return a list of the names of all members in the AR archive.
+
+ .. method:: gettar(name: str, comp: str) -> TarFile
+
+ Return a TarFile object for the member given by *name* which will be
+ decompressed using the compression algorithm given by *comp*.
+ This is almost equal to::
+
+ member = arfile.getmember(name)
+ tarfile = TarFile(file, member.start, member.size, 'gzip')'
+
+ It just opens a new TarFile on the given position in the stream.
+
+.. class:: ArMember
+
+ An ArMember object represents a single file within an AR archive. For
+ Debian packages this can be e.g. control.tar.gz. This class provides
+ information about this file, such as the mode and size. It has no
+ constructor.
+
+ .. attribute:: gid
+
+ The group id of the owner.
+
+ .. attribute:: mode
+
+ The mode of the file.
+
+ .. attribute:: mtime
+
+ Last time of modification.
+
+ .. attribute:: name
+
+ The name of the file.
+
+ .. attribute:: size
+
+ The size of the files.
+
+ .. attribute:: start
+
+ The offset in the archive where the file starts.
+
+ .. attribute:: uid
+
+ The user id of the owner.
+
+Debian Packages
+---------------
+.. class:: DebFile(file)
+
+ A DebFile object represents a file in the .deb package format. It inherits
+ :class:`ArArchive`. In addition to the attributes and methods from
+ :class:`ArArchive`, DebFile provides the following methods:
+
+ .. attribute:: control
+
+ The :class:`TarFile` object associated with the control.tar.gz member.
+
+ .. attribute:: data
+
+ The :class:`TarFile` object associated with the
+ data.tar.{gz,bz2,lzma,xz} member.
+
+ .. attribute:: debian_binary
+
+ The package version, as contained in debian-binary.
+
+Tar Archives
+-------------
+.. class:: TarFile(file[, min: int, max: int, comp: str])
+
+ A TarFile object represents a single .tar file stream.
+
+ The parameter *file* may be a string specifying the path of a file, or
+ a :class:`file`-like object providing the :meth:`fileno` method. It may
+ also be an int specifying a file descriptor (returned by e.g.
+ :func:`os.open`).
+
+ The parameter *min* describes the offset in the file where the archive
+ begins and the parameter *max* is the size of the archive.
+
+ The compression of the archive is set by the parameter *comp*. It can
+ be set to any program supporting the -d switch, the default being gzip.
+
+ .. method:: extractall([rootdir: str]) -> True
+
+ Extract the archive in the current directory. The argument *rootdir*
+ can be used to change the target directory.
+
+ .. method:: extractdata(member: str) -> bytes
+
+ Return the contents of the member, as a bytes object. Raise
+ LookupError if there is no member with the given name.
+
+ .. method:: go(callback: callable[, member: str]) -> True
+
+ Go through the archive and call the callable *callback* for each
+ member with 2 arguments. The first argument is the :class:`TarMember`
+ and the second one is the data, as bytes.
+
+ The optional parameter *member* can be used to specify the member for
+ which call the callback. If not specified, it will be called for all
+ members. If specified and not found, LookupError will be raised.
+
+.. class:: TarMember
+
+ Represent a single member of a 'tar' archive.
+
+ This class which has been modelled after :class:`tarfile.TarInfo`
+ represents information about a given member in an archive.
+
+ .. method:: isblk()
+
+ Determine whether the member is a block device.
+
+ .. method:: ischr()
+
+ Determine whether the member is a character device.
+
+ .. method:: isdev()
+
+ Determine whether the member is a device (block,character or FIFO).
+
+ .. method:: isdir()
+
+ Determine whether the member is a directory.
+
+ .. method:: isfifo()
+
+ Determine whether the member is a FIFO.
+
+ .. method:: isfile()
+
+ Determine whether the member is a regular file.
+
+ .. method:: islnk()
+
+ Determine whether the member is a hardlink.
+
+ .. method:: isreg()
+
+ Determine whether the member is a regular file, same as isfile().
+
+ .. method:: issym()
+
+ Determine whether the member is a symbolic link.
+
+ .. attribute:: gid
+
+ The owner's group id
+
+ .. attribute:: linkname
+
+ The target of the link.
+
+ .. attribute:: major
+
+ The major ID of the device.
+
+ .. attribute:: minor
+
+ The minor ID of the device.
+
+ .. attribute:: mode
+
+ The mode (permissions).
+
+ .. attribute:: mtime
+
+ Last time of modification.
+
+ .. attribute:: name
+
+ The name of the file.
+
+ .. attribute:: size
+
+ The size of the file.
+
+ .. attribute:: uid
+
+ The owner's user id.
+
+
+
+Removed functions
+---------------------
+The following functions have been removed in python-apt 0.8.
+They are listed here to help developers port their applications to the new
+API which is completely different. For this purpose each function documentation
+includes an example showing how the function can be replaced.
+
+.. function:: arCheckMember(file, membername)
+
+ This function has been replaced by using the :keyword:`in` check on an
+ :class:`ArArchive` object::
+
+ member in ArArchive(file)
+
+.. function:: debExtract(file, func, chunk)
+
+ This function has been replaced by the :meth:`TarFile.go`
+ method. The following example shows the old code and the new code::
+
+ debExtract(open("package.deb"), my_callback, "data.tar.gz") #old
+
+ DebFile("package.deb").data.go(my_callback)
+
+ Please note that the signature of the callback is different in
+ :meth:`TarFile.go`.
+
+.. function:: tarExtract(file,func,comp)
+
+ This function has been replaced by the :meth:`TarFile.go`
+ method. The following example shows the old code and the new code::
+
+ tarExtract(open("archive.tar.gz"), my_callback, "gzip") #old
+ TarFile("archive.tar.gz", 0, 0, "gzip").go(my_callback)
+
+ Please note that the signature of the callback is different in
+ :meth:`TarFile.go`, it now expects a :class:`TarMember` and a bytestring
+ of the data.
+
+.. function:: debExtractArchive(file, rootdir)
+
+ This function has been replaced by :meth:`TarFile.extractall` and
+ :attr:`DebFile.data`::
+
+ debExtractArchive(open("package.deb"), rootdir) # old
+ DebFile("package.deb").data.extractall(rootdir) # new
+
+.. function:: debExtractControl(file[, member='control'])
+
+ This function has been replaced by :attr:`DebFile.control` and
+ :meth:`TarFile.extractdata`. In the following example, both commands
+ return the contents of the control file::
+
+ debExtractControl(open("package.deb"))
+ DebFile("package.deb").control.extractdata("control")
diff --git a/doc/source/library/apt_pkg.rst b/doc/source/library/apt_pkg.rst
new file mode 100644
index 0000000..4290180
--- /dev/null
+++ b/doc/source/library/apt_pkg.rst
@@ -0,0 +1,2904 @@
+:mod:`apt_pkg` --- The low-level bindings for apt-pkg
+=====================================================
+.. module:: apt_pkg
+
+The apt_pkg extensions provides a more low-level way to work with apt. It can
+do everything apt can, and is written in C++. It has been in python-apt since
+the beginning.
+
+Module Initialization
+---------------------
+
+Initialization is needed for most functions, but not for all of them. Some can
+be called without having run init*(), but will not return the expected value.
+
+.. function:: init_config
+
+ Initialize the configuration of apt. This is needed for most operations.
+
+.. function:: init_system
+
+ Initialize the system.
+
+.. function:: init
+
+ A short cut to calling :func:`init_config` and :func:`init_system`. You
+ can use this if you do not use the command line parsing facilities provided
+ by :func:`parse_commandline`, otherwise call :func:`init_config`, parse
+ the commandline afterwards and finally call :func:`init_system`.
+
+
+Exceptions
+----------
+.. autoclass:: Error
+
+.. autoclass:: CacheMismatchError
+
+
+Working with the cache
+----------------------
+.. class:: Cache([progress: apt.progress.base.OpProgress])
+
+ A Cache object represents the cache used by APT which contains information
+ about packages. The object itself provides no means to modify the cache or
+ the installed packages, see the classes :class:`DepCache` and
+ :class:`PackageManager` for such functionality.
+
+ The constructor takes an optional argument which must be a subclass of
+ :class:`apt.progress.base.OpProgress`. This object will then be used to
+ display information during the cache opening process (or possible creation
+ of the cache). It may also be ``None``, in which case no progress will
+ be emitted. If not given, progress will be printed to standard output.
+
+ .. note::
+
+ The cache supports colon-separated name:architecture pairs. For
+ normal architectures, they are equal to a (name, architecture)
+ tuple. For the "any" architecture behavior is different, as
+ "name:any" is equivalent to ("name:any", "any"). This is done so
+ that "name:any" matches all packages with that name which have
+ Multi-Arch: allowed set.
+
+ .. describe:: cache[pkgname]
+
+ Return the :class:`Package()` object for the package name given by
+ *pkgname*. If *pkgname* includes a colon, the part after the colon
+ is used as the architecture.
+
+ .. describe:: cache[name, architecture]
+
+ Return the :class:`Package()` object for the package with the given
+ name and architecture.
+
+ .. versionadded: 0.8.0
+
+ .. describe:: pkgname in cache
+
+ Check whether a package with the name given by *pkgname* exists in
+ the cache for the native architecture. If *pkgname* includes a
+ colon, the part after the colon is used as the architecture.
+
+ .. describe:: (name, architecture) in cache
+
+ Check whether a package with the given name and architecture exists
+ in the cache.
+
+ .. versionadded: 0.8.0
+
+ .. method:: update(progress, sources [, pulse_interval]) -> bool
+
+ Update the index files used by the cache. A call to this method
+ does not affect the current Cache object, instead a new one
+ should be created in order to use the changed index files.
+
+ The parameter *progress* takes an
+ :class:`apt.progress.base.AcquireProgress` object which will display
+ the progress of fetching the index files. The parameter *sources* takes
+ a :class:`SourceList` object which lists the sources. The parameter
+ *progress* takes an integer describing the interval (in microseconds)
+ in which the pulse() method of the *progress* object will be called.
+
+ .. attribute:: depends_count
+
+ The total number of dependencies stored in the cache.
+
+ .. attribute:: file_list
+
+ A list of all :class:`PackageFile` objects stored in the cache.
+
+ .. attribute:: group_count
+
+ The number of groups in the cache.
+
+ .. versionadded: 0.8.0
+
+ .. attribute:: groups
+
+ A sequence of :class:`Group` objects, implemented as a
+ :class:`GroupList` object.
+
+ .. versionadded: 0.8.0
+
+ .. class:: GroupList
+
+ A simple sequence-like object which only provides a length and
+ an implementation of ``__getitem__`` for accessing groups at
+ a certain index. Apart from being iterable, it can be used in
+ the following ways:
+
+ .. versionadded: 0.8.0
+
+ .. describe:: list[index]
+
+ Get the :class:`Group` object for the group at the position
+ given by *index* in the GroupList *list*.
+
+ .. describe:: len(list)
+
+ Return the length of the GroupList object *list*.
+
+
+ .. attribute:: is_multi_arch
+
+ An attribute determining whether the cache supports multi-arch.
+
+ .. versionadded: 0.8.0
+
+ .. attribute:: package_count
+
+ The total number of packages available in the cache. This value is
+ equal to the length of the list provided by the :attr:`packages`
+ attribute.
+
+ .. attribute:: package_file_count
+
+ The total number of Packages files available (the Packages files
+ listing the packages). This is the same as the length of the list in
+ the attribute :attr:`file_list`.
+
+ .. attribute:: packages
+
+ A sequence of :class:`Package` objects, implemented as a
+ :class:`PackageList` object.
+
+ .. class:: PackageList
+
+ A simple sequence-like object which only provides a length and
+ an implementation of ``__getitem__`` for accessing packages at
+ a certain index. Apart from being iterable, it can be used in
+ the following ways:
+
+ .. describe:: list[index]
+
+ Get the :class:`Package` object for the package at the position
+ given by *index* in the PackageList *list*.
+
+ .. describe:: len(list)
+
+ Return the length of the PackageList object *list*.
+
+ .. attribute:: provides_count
+
+ The number of provided packages.
+
+ .. attribute:: ver_file_count
+
+ The total number of ``(Version, PackageFile)`` relations stored in
+ the cache.
+
+ .. attribute:: version_count
+
+ The total number of package versions available in the cache.
+
+Managing the cache with :class:`DepCache`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. class:: DepCache(cache: apt_pkg.Cache)
+
+ A DepCache object provides access to more information about the
+ objects made available by the :class:`Cache` object as well as
+ means to mark packages for removal and installation, among other
+ actions.
+
+ The constructor takes a single argument which specifies the
+ :class:`Cache` object the new object shall be related to. While
+ it is theoretically possible to create multiple DepCache objects
+ for the same cache, they will not be independent from each other
+ since they all access the same underlying C++ object.
+
+ Objects of this type provide several methods. Most of those methods
+ are safe to use and should never raise any exception (all those
+ methods for requesting state information or marking changes). If a
+ method is expected to raise an exception, it will be stated in the
+ description.
+
+ If an object of a different cache is passed, :class:`CacheMismatchError`
+ is raised.
+
+ .. method:: commit(acquire_progress, install_progress)
+
+ Commit all marked changes, while reporting the progress of
+ fetching packages via the :class:`apt.progress.base.AcquireProgress`
+ object given by *acquire_progress* and reporting the installation
+ of the package using the :class:`apt.progress.base.InstallProgress`
+ object given by *install_progress*.
+
+ If this fails, an exception of the type :exc:`SystemError` will
+ be raised.
+
+ .. method:: fix_broken() -> bool
+
+ Try to fix all broken packages in the cache and return ``True`` in
+ case of success. If an error occurred, a :exc:`SystemError`
+ exception is raised.
+
+ .. method:: get_candidate_ver(pkg: Package) -> Version
+
+ Return the candidate version for the package given by the parameter
+ *pkg* as a :class:`Version` object. The default candidate for a
+ package is the version with the highest pin, although a different
+ one may be set using :meth:`set_candidate_ver`. If no candidate
+ can be found, return ``None`` instead.
+
+ .. method:: init(progress: apt.progress.base.OpProgress)
+
+ Initialize the DepCache. This is done automatically when the
+ cache is opened, but sometimes it may be useful to reinitialize
+ the DepCache. Like the constructor of :class:`Cache`, this
+ function takes a single :class:`apt.progress.base.OpProgress`
+ object to display progress information.
+
+ .. method:: read_pinfile(file: str)
+
+ A proxy function which calls the method :meth:`Policy.read_pinfile` of
+ the :class:`Policy` object used by this object. This method raises
+ a :exc:`SystemError` exception if the file could not be parsed.
+
+ .. method:: set_candidate_ver(pkg: Package, version: Version) -> bool
+
+ Set the candidate version of the package given by the :class:`Package`
+ object *pkg* to the version given by the :class:`Version` object
+ *version* and return ``True``. If odd things happen, this function
+ may raise a :exc:`SystemError` exception, but this should not
+ happen in normal usage. See :meth:`get_candidate_ver` for a way
+ to retrieve the candidate version of a package.
+
+ .. method:: upgrade([dist_upgrade=False]) -> bool
+
+ Mark the packages for upgrade under the same conditions
+ :program:`apt-get` does. If *dist_upgrade* is ``True``, also
+ allow packages to be upgraded if they require installation/removal
+ of other packages; just like apt-get dist-upgrade.
+
+ Despite returning a boolean value, this raises :exc:`SystemError` and
+ does not return ``False`` if an error occurred.
+
+ The following methods can mark a single package for installation,
+ removal, etc:
+
+ .. method:: mark_auto(pkg: Package)
+
+ Mark the :class:`Package` *pkg* as automatically installed.
+
+ .. method:: mark_keep(pkg: Package)
+
+ Mark the :class:`Package` *pkg* for keep.
+
+ .. method:: mark_delete(pkg: Package[, purge])
+
+ Mark the :class:`Package` *pkg* for delete. If *purge* is True,
+ the configuration files will be removed as well.
+
+ .. method:: mark_install(pkg: Package[, auto_inst=True[, from_user=True]])
+
+ Mark the :class:`Package` *pkg* for install, and, if *auto_inst*
+ is ``True``, its dependencies as well. If *from_user* is ``True``,
+ the package will **not** be marked as automatically installed.
+
+ .. method:: set_reinstall(pkg: Package)
+
+ Set if the :class:`Package` *pkg* should be reinstalled.
+
+ The following methods can be used to check the state of a package:
+
+ .. method:: is_auto_installed(pkg: Package) -> bool
+
+ Return ``True`` if the package is automatically installed, that
+ is, as a dependency of another package.
+
+ .. method:: is_garbage(pkg: Package) -> bool
+
+ Return ``True`` if the package is garbage, that is, if it was
+ automatically installed and no longer referenced by other packages.
+
+ .. method:: is_inst_broken(pkg: Package) -> bool
+
+ Return ``True`` if the package is broken on the current install. This
+ takes changes which have not been marked not into account.
+
+ .. method:: is_now_broken(pkg: Package) -> bool
+
+ Return ``True`` if the package is now broken, that is, if the package
+ is broken if the marked changes are applied.
+
+ .. method:: is_upgradable(pkg: Package) -> bool
+
+ Return ``True`` if the package is upgradable, the package can then
+ be marked for upgrade by calling the method :meth:`mark_install`.
+
+ .. method:: marked_delete(pkg: Package) -> bool
+
+ Return ``True`` if the package is marked for delete.
+
+ .. method:: marked_downgrade(pkg: Package) -> bool
+
+ Return ``True`` if the package should be downgraded.
+
+ .. method:: marked_install(pkg: Package) -> bool
+
+ Return ``True`` if the package is marked for install.
+
+ .. method:: marked_keep(pkg: Package) -> bool
+
+ Return ``True`` if the package is marked for keep.
+
+ .. method:: marked_reinstall(pkg: Package) -> bool
+
+ Return ``True`` if the package should be reinstalled.
+
+ .. method:: marked_upgrade(pkg: Package) -> bool
+
+ Return ``True`` if the package is marked for upgrade.
+
+ .. method:: phasing_applied(pkg: Package) -> bool
+
+ Return ``True`` if the package update is being phased.
+
+ DepCache objects also provide several attributes containing information
+ on the marked changes:
+
+ .. attribute:: keep_count
+
+ Integer, number of packages marked as keep
+
+ .. attribute:: inst_count
+
+ Integer, number of packages marked for installation.
+
+ .. attribute:: del_count
+
+ Number of packages which should be removed.
+
+ .. attribute:: broken_count
+
+ Number of packages which are broken.
+
+ .. attribute:: usr_size
+
+ The size required for the changes on the filesystem. If you install
+ packages, this is positive, if you remove them its negative.
+
+ .. attribute:: deb_size
+
+ The size of the packages which are needed for the changes to be
+ applied.
+
+ .. attribute:: policy
+
+ The underlying :class:`Policy` object used by the :class:`DepCache` to
+ select candidate versions.
+
+Installing with :class:`PackageManager`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. class:: PackageManager(depcache)
+
+ Abstraction of a package manager. This object takes care of retrieving
+ packages, ordering the installation, and calling the package manager to
+ do the actual installation.
+
+ .. method:: get_archives(fetcher, list, records) -> bool
+
+ Add all packages marked for installation (or upgrade, anything
+ which needs a download) to the :class:`Acquire` object referenced
+ by *fetcher*.
+
+ The parameter *list* specifies a :class:`SourceList` object which
+ is used to retrieve the information about the archive URI for the
+ packages which will be fetched.
+
+ The parameter *records* takes a :class:`PackageRecords` object which
+ will be used to look up the file name of the package.
+
+ .. method:: do_install(status_fd: int) -> int
+
+ Install the packages and return one of the class constants
+ :attr:`RESULT_COMPLETED`, :attr:`RESULT_FAILED`,
+ :attr:`RESULT_INCOMPLETE`. The argument *status_fd* can be used
+ to specify a file descriptor that APT will write status information
+ on (see README.progress-reporting in the apt source code for
+ information on what will be written there).
+
+ .. method:: fix_missing() -> bool
+
+ Fix the installation if a package could not be downloaded.
+
+ .. attribute:: RESULT_COMPLETED
+
+ A constant for checking whether the result of the call to
+ :meth:`do_install` is 'failed'.
+
+ .. attribute:: RESULT_FAILED
+
+ A constant for checking whether the result of the call to
+ :meth:`do_install` is 'failed'.
+
+ .. attribute:: RESULT_INCOMPLETE
+
+ A constant for checking whether the result of the call to
+ :meth:`do_install` is 'incomplete'.
+
+ All instances of this class also support the following methods:
+
+ .. note::
+
+ This methods are provided mainly for subclassing purposes
+ and should not be used in most programs. This class is a
+ subclass of an internal :class:`_PackageManager` which does
+ not provide that methods. As the public C++ API creates such
+ an object without those methods, you should not rely on those
+ methods to be available unless you used the constructor of
+ :class:`PackageManager` to create the object.
+
+ .. method:: configure(pkg: Package) -> bool
+
+ Notify the package manager that the :class:`Package` given
+ by *pkg* is to be configured. Must return a ``True`` value
+ or ``None`` to continue, or a value which is ``False`` if
+ evaluated as boolean to abort.
+
+ .. versionadded:: 0.8.0
+
+ .. method:: install(pkg: Package, filename: str) -> bool
+
+ Notify the package manager that the :class:`Package` given
+ by *pkg* is to be installed from the .deb located at
+ *filename*. Must return a ``True`` value or ``None`` to
+ continue, or a value which is ``False`` if evaluated as
+ boolean to abort.
+
+
+ .. versionadded:: 0.8.0
+
+ .. method:: remove(pkg: Package, purge: bool) -> bool
+
+ Notify the package manager that the :class:`Package` given
+ by *pkg* is to be removed. If *purge* is ``True``, the package
+ shall be purged. Must return a ``True`` value or ``None`` to
+ continue, or a value which is ``False`` if evaluated as boolean
+ to abort.
+
+
+ .. versionadded:: 0.8.0
+
+ .. method:: go(status_fd: int) -> bool
+
+ Start dpkg, writing status information to the file descriptor
+ given by *status_fd*. Must return a ``True`` value or ``None`` to
+ continue, or a value which is ``False`` if evaluated as boolean
+ to abort.
+
+ .. versionadded:: 0.8.0
+
+ .. method:: reset()
+
+ Reset the package manager for a new round.
+
+ .. versionadded:: 0.8.0
+
+
+Installation ordering with :class:`OrderList`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. class:: OrderList(depcache: DepCache)
+
+ Represent a :c:type:`pkgOrderList`, used for installation
+ ordering. This class provides several methods and attributes,
+ is complicated and should not be used by normal programs.
+
+ .. versionadded:: 0.8.0
+
+ This class is a sequence and supports the following operations:
+
+ .. describe:: list[index]
+
+ Get the package at the given index in the list. Negative
+ index is supported.
+
+ .. describe:: len(list)
+
+ The length of the list.
+
+ It also supports the append() method from :class:`list`:
+
+ .. method:: append(pkg: Package)
+
+ Append a new package to the end of the list. Please note that
+ you may not append a package twice, as only as much packages
+ as in the cache can be added.
+
+ The class also defines several specific attributes and methods,
+ to be described hereinafter.
+
+ .. method:: score(pkg: Package)
+
+ Return the score of the package. Packages are basically
+ ordered by descending score.
+
+ This class allows flags to be set on packages. Those flags are:
+
+ .. attribute:: FLAG_ADDED
+ .. attribute:: FLAG_ADD_PENDING
+ .. attribute:: FLAG_IMMEDIATE
+ .. attribute:: FLAG_LOOP
+ .. attribute:: FLAG_UNPACKED
+ .. attribute:: FLAG_CONFIGURED
+ .. attribute:: FLAG_REMOVED
+ .. attribute:: FLAG_STATES_MASK
+
+ Same as ``FLAG_UNPACKED | FLAG_CONFIGURED | FLAG_REMOVED``
+
+ .. attribute:: FLAG_IN_LIST
+ .. attribute:: FLAG_AFTER
+
+ The methods to work with those flags are:
+
+ .. method:: flag(pkg: Package, flag: int[, unset_flags: int])
+
+ Flag a package. Sets the flags given in *flag* and unsets
+ any flags given in *unset_flags*.
+
+ .. method:: is_flag(pkg: Package, flag: int)
+
+ Check whether the flags in *flag* are set for the package.
+
+ .. method:: wipe_flags(flags: int)
+
+ Remove the flags in *flags* from all packages.
+
+ .. method:: is_missing(pkg: Package)
+
+ Check if the package is missing (not really usable right now)
+
+ .. method:: is_now(pkg: Package)
+
+ Check if the package is flagged for any state but removal.
+
+ The following methods for ordering are provided:
+
+ .. method:: order_critical()
+
+ Order the packages for critical unpacking; that is, only
+ respect pre-dependencies.
+
+ .. method:: order_unpack()
+
+ Order the packages for unpacking, repecting Pre-Depends and
+ Conflicts.
+
+ .. method:: order_configure()
+
+ Order the packages for configuration, respecting Depends.
+
+Improve performance with :class:`ActionGroup`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. class:: ActionGroup(depcache)
+
+ Create a new :class:`ActionGroup()` object for the :class:`DepCache` object
+ given by the parameter *depcache*.
+
+ :class:`ActionGroup()` objects make operations on the cache faster by
+ delaying certain cleanup operations until the action group is released.
+
+ An action group is also a context manager and therefore supports the
+ :keyword:`with` statement. But because it becomes active as soon as it
+ is created, you should not create an ActionGroup() object before entering
+ the with statement. Thus, you should always use the following form::
+
+ with apt_pkg.ActionGroup(depcache):
+ ...
+
+ For code which has to run on Python versions prior to 2.5, you can also
+ use the traditional way::
+
+ actiongroup = apt_pkg.ActionGroup(depcache)
+ ...
+ actiongroup.release()
+
+ In addition to the methods required to implement the context
+ manager interface, :class:`ActionGroup` objects provide the
+ following method:
+
+ .. method:: release()
+
+ Release the ActionGroup. This will reactive the collection of package
+ garbage.
+
+Resolving Dependencies with :class:`ProblemResolver`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. class:: ProblemResolver(depcache: DepCache)
+
+ ProblemResolver objects take care of resolving problems with
+ dependencies. They mark packages for installation/removal and
+ try to satisfy all dependencies. The constructor takes a single
+ argument of the type :class:`apt_pkg.DepCache` to determine the
+ cache that shall be manipulated in order to resolve the problems.
+
+ .. method:: clear(pkg: Package)
+
+ Revert the action of calling :meth:`protect` or :meth:`remove` on
+ a package, resetting it to the default state.
+
+ .. method:: install_protect()
+
+ Mark all protected packages for installation.
+
+ .. method:: protect(pkg: Package)
+
+ Mark the package given by *pkg* as protected; that is, its state
+ will not be changed.
+
+ .. method:: remove(pkg: Package)
+
+ Mark the package given by *pkg* for removal in the resolver.
+
+ .. method:: resolve([fix_broken: bool = True]) -> bool
+
+ Try to intelligently resolve problems by installing and removing
+ packages. If *fix_broken* is ``True``, apt will try to repair broken
+ dependencies of installed packages.
+
+ .. method:: resolve_by_keep() -> bool
+
+ Try to resolve the problems without installing or removing packages.
+
+ .. method:: keep_phased_updates() -> bool
+
+ Hold back upgrades to phased versions of already installed
+ packages, unless they are security updates.
+
+:class:`Group` of packages with the same name
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. class:: Group(cache: Cache, name: str)
+
+ .. versionadded:: 0.8.0
+
+ A collection of packages in which all packages have the same name. Groups
+ are used in multi-arch environments, where two or more packages have the
+ same name, but different architectures.
+
+ Group objects provide the following parts for sequential access:
+
+ .. describe:: group[index]
+
+ Get the package at the given **index** in the group.
+
+ .. note::
+ Groups are internally implemented using a linked list. The object
+ keeps a pointer to the current object and the first object, so
+ access to the first element, or accesses in order have a
+ complexity of O(1). Random-access complexity is ranges from
+ O(1) to O(n).
+
+ Group objects also provide special methods to find single packages:
+
+ .. method:: find_package(architecture: str) -> Package
+
+ Find a package with the groups name and the architecture given
+ in the argument *architecture*. If no such package exists, return
+ ``None``.
+
+ .. method:: find_preferred_package(prefer_nonvirtual: bool = True) -> Package
+
+ Find the preferred package. This is the package of the native
+ architecture (specified in ``APT::Architecture``) if available,
+ or the package from the first foreign architecture. If no package
+ could be found, return ``None``
+
+ If **prefer_nonvirtual** is ``True``, the preferred package
+ will be a non-virtual package, if one exists.
+
+
+:class:`Package` information
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. class:: Package
+
+ Represent a package. A package is uniquely identified by its name and
+ architecture and each package can have zero or more versions which can be
+ accessed via the :attr:`version_list` property. Packages can be
+ installed and removed by a :class:`DepCache` object.
+
+ Attributes:
+
+ .. attribute: architecture
+
+ The architecture of the package. This is relevant on multi-arch
+ systems only. Please note that if a package is Architecture: all,
+ this value is not "all", but the architecture of the package file
+ it comes from.
+
+ .. versionadded:: 0.7.100.3
+
+ .. attribute:: current_ver
+
+ The version currently installed as a :class:`Version` object, or None
+ if the package is not installed.
+
+ .. method:: get_fullname([pretty: bool = False]) -> str
+
+ Get the full name of the package, including the architecture. If
+ *pretty* is ``True``, the architecture is omitted for native packages,
+ that is, an amd64 "apt" package on an amd64 system would give "apt".
+
+ .. versionadded:: 0.7.100.3
+
+ .. attribute:: has_provides
+
+ A boolean value determining whether the list available via the
+ attribute :attr:`provides_list` has at least one element. This
+ value may be used in combination with :attr:`has_versions` to
+ check whether a package is virtual; that is, it has no versions
+ and is provided at least once::
+
+ pkg.has_provides and not pkg.has_versions
+
+ .. attribute:: has_versions
+
+ A boolean value determining whether the list available via the
+ attribute :attr:`version_list` has at least one element. This
+ value may be used in combination with :attr:`has_provides` to
+ check whether a package is virtual; that is, it has no versions
+ and is provided at least once::
+
+ pkg.has_provides and not pkg.has_versions
+
+ .. attribute:: id
+
+ The ID of the package. This can be used to store information about
+ the package. The ID is an int value.
+
+ .. attribute:: name
+
+ This is the name of the package.
+
+ .. attribute:: provides_list
+
+ A list of all package versions providing this package. Each element
+ of the list is a triplet, where the first element is the name of the
+ provided package, the second element the provided version (empty
+ string), and the third element the version providing this package
+ as a :class:`Version` object.
+
+ .. attribute:: rev_depends_list
+
+ An iterator of :class:`Dependency` objects for dependencies on this
+ package. The returned iterator is implemented by the class
+ :class:`DependencyList`:
+
+ .. class:: DependencyList
+
+ A simple list-like type for representing multiple dependency
+ objects in an efficient manner; without having to generate
+ all Dependency objects in advance.
+
+ .. describe:: list[index]
+
+ Return the item at the position *index* in the list.
+
+ .. method:: __len__()
+
+ The length of the list. This method should not be used
+ irectly, instead Python's built-in function :func:`len`
+ should be used.
+
+ .. attribute:: section
+
+ The section of the package, as specified in the record. The list of
+ possible sections is defined in the Policy. This is a string.
+
+ .. deprecated:: 1.0
+
+ A package can have multiple versions with different sections, so
+ the section information should be accessed from the version class.
+
+ .. attribute:: version_list
+
+ A list of :class:`Version` objects for all versions of this package
+ available in the cache.
+
+ **States**:
+
+ .. attribute:: selected_state
+
+ The state we want it to be, ie. if you mark a package for installation,
+ this is :attr:`apt_pkg.SELSTATE_INSTALL`.
+
+ See :ref:`SelStates` for a list of available states.
+
+ .. attribute:: inst_state
+
+ The state the currently installed version is in. This is normally
+ :attr:`apt_pkg.INSTSTATE_OK`, unless the installation failed.
+
+ See :ref:`InstStates` for a list of available states.
+
+ .. attribute:: current_state
+
+ The current state of the package (not installed, unpacked, installed,
+ etc). See :ref:`CurStates` for a list of available states.
+
+ **Flags**:
+
+ .. attribute:: essential
+
+ Whether the package has the 'Essential' flag set; that is,
+ whether it has a field 'Essential: yes' in its record.
+
+ .. attribute:: important
+
+ Whether the package has the (obsolete) 'Important' flag set; that is,
+ whether it has a field 'Important: yes' in its record.
+
+Example:
+~~~~~~~~~
+.. literalinclude:: ../examples/cache-packages.py
+
+
+
+:class:`Version`
+^^^^^^^^^^^^^^^^^
+.. class:: Version
+
+ The version object contains all information related to a specific package
+ version.
+
+ .. attribute:: arch
+
+ The architecture of the package, eg. amd64 or all.
+
+ .. attribute:: depends_list
+
+ This is basically the same as :attr:`depends_list_str`,
+ but instead of the ('pkgname', 'version', 'relation') tuples,
+ it returns :class:`Dependency` objects, which can assist you with
+ useful functions.
+
+ .. attribute:: depends_list_str
+
+ A dictionary of dependencies. The key specifies the type of the
+ dependency ('Depends', 'Recommends', etc.).
+
+ The value is a list, containing items which refer to the or-groups of
+ dependencies. Each of these or-groups is itself a list, containing
+ tuples like ('pkgname', 'version', 'relation') for each or-choice.
+
+ An example return value for a package with a 'Depends: python (>= 2.4)'
+ would be::
+
+ {'Depends': [
+ [
+ ('python', '2.4', '>=')
+ ]
+ ]
+ }
+
+ The same for a dependency on A (>= 1) | B (>= 2)::
+
+ {'Depends': [
+ [
+ ('A', '1', '>='),
+ ('B', '2', '>='),
+ ]
+ ]
+ }
+
+ The comparison operators are not the Debian ones, but the standard
+ comparison operators as used in languages such as C and Python. This
+ means that '>' means "larger than" and '<' means "less than".
+
+ .. attribute:: downloadable
+
+ Whether this package can be downloaded from a remote site.
+
+ .. attribute:: file_list
+
+ A list of (:class:`PackageFile`, int: index) tuples for all Package
+ files containing this version of the package.
+
+ .. attribute:: hash
+
+ An integer hash value used for the internal storage.
+
+ .. attribute:: id
+
+ A numeric identifier which uniquely identifies this version in all
+ versions in the cache.
+
+ .. attribute:: installed_size
+
+ The size of the package (in kilobytes), when unpacked on the disk.
+
+ .. attribute:: multi_arch
+
+ The multi-arch state of the package. Can be one of the following
+ attributes.
+
+ .. attribute:: MULTI_ARCH_NO
+
+ No multi-arch
+
+ .. attribute:: MULTI_ARCH_ALL
+
+ An ``Architecture: all`` package
+
+
+ .. attribute:: MULTI_ARCH_FOREIGN
+
+ Can satisfy dependencies of foreign-architecture
+ packages
+
+ .. attribute:: MULTI_ARCH_ALL_FOREIGN
+
+ :attr:`MULTI_ARCH_FOREIGN` for ``Architecture: all``
+ packages.
+
+ .. attribute:: MULTI_ARCH_SAME
+
+ Multiple versions from different architectures may be
+ installed in parallel, but may only satisfy dependencies
+ of packages from the same architecture
+
+ .. attribute:: MULTI_ARCH_ALLOWED
+
+ Installation in parallel and satisfying ``pkg:any``
+ style dependencies is allowed.
+
+ .. attribute:: MULTI_ARCH_ALL_ALLOWED
+
+ :attr:`MULTI_ARCH_ALLOWED` for ``Architecture: all``
+ packages.
+
+
+
+
+ .. attribute:: parent_pkg
+
+ The :class:`Package` object this version belongs to.
+
+ .. attribute:: priority
+
+ The integer representation of the priority. This can be used to speed
+ up comparisons a lot, compared to :attr:`priority_str`.
+
+ The values are defined in the :mod:`apt_pkg` extension, see
+ :ref:`Priorities` for more information.
+
+ .. attribute:: priority_str
+
+ Return the priority of the package version, as a string, eg.
+ "optional".
+
+ .. attribute:: provides_list
+
+ This returns a list of all packages provided by this version. Like
+ :attr:`Package.provides_list`, it returns a list of tuples
+ of the form ('virtualpkgname', '', :class:`Version`), where as the
+ last item is the same as the object itself.
+
+ .. attribute:: section
+
+ The usual sections (eg. admin, net, etc.). Prefixed with the component
+ name for packages not in main (eg. non-free/admin).
+
+ .. attribute:: size
+
+ The size of the .deb file, in bytes.
+
+ .. attribute:: translated_description
+
+ Return a :class:`Description` object for the translated description
+ of this package version.
+
+ .. attribute:: is_security_update
+
+ Whether this version is a security update.
+
+ .. attribute:: ver_str
+
+ The version, as a string.
+
+
+
+:class:`Dependency`
+^^^^^^^^^^^^^^^^^^^^
+.. class:: Dependency
+
+ Represent a dependency from one package to another one.
+
+ .. method:: all_targets
+
+ A list of all possible target :class:`Version` objects which satisfy
+ this dependency.
+
+ .. attribute:: comp_type
+
+ The type of comparison (<,<=,=,!=,>=,>,), as string. Note that the
+ empty string is a valid string as well, if no version is specified.
+
+ .. attribute:: dep_type
+
+ The type of the dependency, as string, eg. "Depends".
+
+ .. attribute:: dep_type_enum
+
+ The type of the dependency, as an integer which can be compared to
+ one of the TYPE_* constants below.
+
+ .. attribute:: dep_type_untranslated
+
+ The type of the depndency, as an untranslated string.
+
+ .. attribute:: id
+
+ The ID of the package, as integer.
+
+ .. attribute:: parent_pkg
+
+ The :class:`Package` object of the package which declares the
+ dependency. This is the same as using ParentVer.ParentPkg.
+
+ .. attribute:: parent_ver
+
+ The :class:`Version` object of the parent version, ie. the package
+ which declares the dependency.
+
+ .. attribute:: target_pkg
+
+ The :class:`Package` object of the target package.
+
+ .. attribute:: target_ver
+
+ The target version of the dependency, as string. Empty string if the
+ dependency is not versioned.
+
+ The following constants describe all values the attribute *dep_type_enum*
+ can take:
+
+ .. attribute:: TYPE_CONFLICTS
+
+ Constant for checking against dep_type_enum
+
+ .. attribute:: TYPE_DEPENDS
+
+ Constant for checking against dep_type_enum
+
+ .. attribute:: TYPE_DPKG_BREAKS
+
+ Constant for checking against dep_type_enum
+
+ .. attribute:: TYPE_ENHANCES
+
+ Constant for checking against dep_type_enum
+
+ .. attribute:: TYPE_OBSOLETES
+
+ Constant for checking against dep_type_enum
+
+ .. attribute:: TYPE_PREDEPENDS
+
+ Constant for checking against dep_type_enum
+
+ .. attribute:: TYPE_RECOMMENDS
+
+ Constant for checking against dep_type_enum
+
+ .. attribute:: TYPE_REPLACES
+
+ Constant for checking against dep_type_enum
+
+ .. attribute:: TYPE_SUGGESTS
+
+ Constant for checking against dep_type_enum
+
+Example: Find all missing dependencies
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+With the help of Dependency.all_targets(), you can easily find all packages with
+broken dependencies:
+
+.. literalinclude:: ../examples/missing-deps.py
+
+
+:class:`Description`
+^^^^^^^^^^^^^^^^^^^^^
+.. class:: Description
+
+ Represent the description of the package.
+
+ .. attribute:: language_code
+
+ The language code of the description; or, if the description
+ is untranslated, an empty string.
+
+ .. attribute:: md5
+
+ The MD5 checksum of the description.
+
+ .. attribute:: file_list
+
+ A list of tuples ``(packagefile: PackageFile, index: int)``.
+
+Package Pinning with :class:`Policy`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. class:: Policy(cache: apt_pkg.Cache)
+
+ Representation of the policy of the :class:`Cache` object given by
+ *cache*. This provides a superset of policy-related functionality
+ compared to the *DepCache* class. The DepCache can be used for most
+ purposes, but there may be some cases where a special policy class
+ is needed.
+
+ .. method:: create_pin(type: str, pkg: str, data: str, priority: int)
+
+ Create a pin for the policy. The parameter *type* refers to one of the
+ strings 'Version', 'Release', or 'Origin'. The argument *pkg* is the
+ name of the package. The parameter *data* refers to the value (such
+ as 'unstable' for type='Release') and the other possible options.
+ The parameter 'priority' gives the priority of the pin.
+
+ .. automethod:: init_defaults
+
+ .. method:: get_candidate_ver(package: apt_pkg.Package) -> apt_pkg.Version
+
+ Get the best package for the job; that is, the package with the
+ highest pin priority.
+
+ .. method:: get_priority(package: Union[apt_pkg.Version, apt_pkg.PackageFile]) -> int
+
+ Get the pin priority of the package, version, or package file
+ given by *package*.
+
+ .. versionchanged:: 1.7
+
+ Introduce support for per-version pins. Deprecated support
+ for :class:`apt_pkg.Package`.
+
+ .. method:: read_pindir(dirname: str) -> bool
+
+ Read the pin files in the given dir (e.g. '/etc/apt/preferences.d')
+ and add them to the policy.
+
+ .. method:: read_pinfile(filename: str) -> bool
+
+ Read the pin file given by *filename* (e.g. '/etc/apt/preferences')
+ and add it to the policy.
+
+
+Index Files
+-------------
+
+.. class:: MetaIndex
+
+ Represent a Release file as stored in the cache.
+
+ .. attribute:: uri
+
+ The URI the meta index file is located at, as a string.
+
+ .. attribute:: dist
+
+ The distribution stored in the meta index, as a string.
+
+ .. attribute:: is_trusted
+
+ A boolean value determining whether the meta index can be trusted. This
+ is ``True`` for signed Release files.
+
+ .. attribute:: index_files
+
+ A list of all :class:`IndexFile` objects associated with this meta
+ index.
+
+
+.. class:: IndexFile
+
+ Represent an index file, that is, package indexes, translation indexes,
+ and source indexes.
+
+ .. method:: archive_uri(path: str) -> str
+
+ Return the URI to the given path in the archive.
+
+ .. attribute:: label
+
+ The label of the index file.
+
+ .. attribute:: describe
+
+ A string describing this object.
+
+ .. attribute:: exists
+
+ A boolean value determining whether the index file exists.
+
+ .. attribute:: has_packages
+
+ A boolean value determining whether the index file has packages.
+
+ .. attribute:: size
+
+ The size of the file, measured in bytes.
+
+ .. attribute:: is_trusted
+
+ A boolean value determining whether the file can be trusted; that is,
+ because it is from a source with a GPG signed Release file.
+
+
+
+.. class:: PackageFile
+
+ Provide access to an index file stored in the cache, such as
+ :file:`/var/lib/dpkg/status`.
+
+ .. attribute:: architecture
+
+ The architecture of the package file. This attribute normally
+ contains an empty string and is thus not very useful.
+
+ .. attribute:: archive
+
+ The archive of the package file as set in the Release file via
+ the "Suite" field. If there is no Release file, this is an empty
+ string.
+
+ .. attribute:: component
+
+ The component of the package file, if it is provided by a repository
+ using the dists/ hierarchy. For other packages files, this property
+ is an empty string.
+
+ .. attribute:: filename
+
+ The path to the file on the local filesystem.
+
+ .. attribute:: id
+
+ The ID of the package. This is an integer which can be used to store
+ further information about the file [eg. as dictionary key].
+
+ .. attribute:: index_type
+
+ A string describing the type of index. Known values are
+ "Debian Package Index", "Debian Translation Index", and
+ "Debian dpkg status file".
+
+ .. attribute:: label
+
+ The label of the package file as set in the release file
+ via the 'Label' field. If there is no Release file, this
+ attribute is an empty string.
+
+ .. attribute:: not_automatic
+
+ Whether packages from this list will be updated automatically. The
+ default for example is False.
+
+ .. attribute:: not_source
+
+ Whether the file has no source from which it can be updated. In such a
+ case, the value is ``True``; else ``False``. For example, it is
+ ``False`` for :file:`/var/lib/dpkg/status`.
+
+ Example::
+
+ for pkgfile in cache.file_list:
+ if pkgfile.not_source:
+ print('The file %s has no source.' % pkgfile.filename)
+
+ .. attribute:: origin
+
+ The Origin, as set in the Release file
+
+ .. attribute:: site
+
+ The hostname of the site.
+
+ .. attribute:: size
+
+ The size of the file.
+
+ .. attribute:: version
+
+ The version, as set in the release file (eg. "4.0" for "Etch")
+
+
+The following example shows how to use PackageFile:
+
+.. literalinclude:: ../examples/cache-pkgfile.py
+
+
+Records (Release files, Packages, Sources)
+------------------------------------------
+
+.. class:: IndexRecords()
+
+ Represent a Release file and provide means to read information from
+ the file. This class provides several methods:
+
+ .. method:: get_dist() -> str
+
+ Return the distribution set in the Release file.
+
+ .. method:: load(filename: str)
+
+ Load the file located at the path given by *filename*.
+
+ .. method:: lookup(key: str) -> (HashString, int)
+
+ Look up the filename given by *key* and return a tuple (hash, size),
+ where the first element *hash* is a :class:`HashString` object
+ and the second element *size* is an int object.
+
+
+.. class:: PackageRecords(cache: apt_pkg.Cache)
+
+ Provide further information about the packages in the :class:`Cache` object
+ *cache*. This efficiently parses the package files to provide information
+ not available in the cache, such as maintainer, hash sums, description,
+ and the file name of the package. It also provides the complete record
+ of the package.
+
+ .. method:: lookup(verfile_iter: (PackageFile, int)) -> bool
+
+ Change the actual package to the package given by the verfile_iter.
+
+ The parameter *verfile_iter* refers to a tuple consisting
+ of (:class:`PackageFile()`, int: index), as returned by various
+ ``file_list`` attributes such as :attr:`Version.file_list`.
+
+ Example (shortened)::
+
+ cand = depcache.get_candidate_ver(cache['python-apt'])
+ records.lookup(cand.file_list[0])
+ # Now you can access the record
+ print(records.source_pkg) # == python-apt
+
+ .. describe:: section[key]
+
+ Return the value of the field at *key*. If *key* is not available,
+ raise :exc:`KeyError`.
+ Raises AttributeError if not yet looked up.
+
+ .. versionadded:: 1.7
+
+ .. describe:: key in section
+
+ Return ``True`` if *section* has a key *key*, else ``False``.
+ Raises AttributeError if not yet looked up.
+
+ .. versionadded:: 1.7
+
+ .. attribute:: filename
+
+ Return the field 'Filename' of the record. This is the path to the
+ package, relative to the base path of the archive.
+
+ .. attribute:: hashes
+
+ A :class:`apt_pkg.HashStringList` of all hashes.
+
+ .. versionadded:: 1.1
+
+ .. attribute:: md5_hash
+
+ Return the MD5 hashsum of the package This refers to the field
+ 'MD5Sum' in the raw record.
+
+ .. deprecated:: 1.1
+
+ Use :attr:`hashes` instead.
+
+ .. attribute:: sha1_hash
+
+ Return the SHA1 hashsum of the package. This refers to the field 'SHA1'
+ in the raw record.
+
+ .. deprecated:: 1.1
+
+ Use :attr:`hashes` instead.
+
+ .. attribute:: sha256_hash
+
+ Return the SHA256 hashsum of the package. This refers to the field
+ 'SHA256' in the raw record.
+
+ .. versionadded:: 0.7.9
+
+ .. deprecated:: 1.1
+
+ Use :attr:`hashes` instead.
+
+ .. attribute:: source_pkg
+
+ The name of the source package, if different from the name of the
+ binary package. This information is retrieved from the 'Source' field.
+
+ .. attribute:: source_ver
+
+ The version of the source package, if it differs from the version
+ of the binary package. Just like 'source_pkg', this information
+ is retrieved from the 'Source' field.
+
+ .. attribute:: maintainer
+
+ Return the maintainer of the package.
+
+ .. attribute:: short_desc
+
+ Return the short description. This is the summary on the first line of
+ the 'Description' field.
+
+ .. attribute:: long_desc
+
+ Return the long description. These are lines 2-END from the
+ 'Description' field.
+
+ .. attribute:: name
+
+ Return the name of the package. This is the 'Package' field.
+
+ .. attribute:: homepage
+
+ Return the Homepage. This is the 'Homepage' field.
+
+ .. attribute:: record
+
+ Return the whole record as a string. If you want to access fields of
+ the record not available as an attribute, you can use
+ :class:`apt_pkg.TagSection` to parse the record and access the field
+ name.
+
+ .. deprecated:: 1.7
+
+ This property can be considered deprecated for simple string
+ lookups, as keys can now be looked up in the record itself.
+
+ Example::
+
+ section = apt_pkg.TagSection(records.record)
+ print(section['SHA256']) # Use records.sha256_hash instead
+
+.. class:: SourceRecords
+
+ Provide an easy way to look up the records of source packages and
+ provide easy attributes for some widely used fields of the record.
+
+ .. note::
+
+ If the Lookup failed, because no package could be found, no error is
+ raised. Instead, the attributes listed below are simply not existing
+ anymore (same applies when no Lookup has been made, or when it has
+ been restarted).
+
+ .. method:: lookup(pkgname: str) -> bool
+
+ Look up the source package with the given name. Each call moves
+ the position of the records parser forward. If there are no
+ more records, return None. If the lookup failed this way,
+ access to any of the attributes will result in an
+ :exc:`AttributeError`.
+
+ Imagine a package P with two versions X, Y. The first ``lookup(P)``
+ would set the record to version X and the second ``lookup(P)`` to
+ version Y. A third call would return ``None`` and access to any
+ of the below attributes will result in an :exc:`AttributeError`
+
+ .. method:: restart()
+
+ Restart the lookup process. This moves the parser to the first
+ package and lookups can now be made just like on a new object.
+
+ Imagine a package P with two versions X, Y. The first ``Lookup(P)``
+ would set the record to version X and the second ``Lookup(P)`` to
+ version Y. If you now call ``restart()``, the internal position
+ will be cleared. Now you can call ``lookup(P)`` again to move to X.
+
+ .. attribute:: binaries
+
+ Return a list of strings describing the package names of the binaries
+ created by the source package. This matches the 'Binary' field in the
+ raw record.
+
+ .. attribute:: build_depends
+
+ Return a dictionary representing the build-time dependencies of the
+ package. The format is the same as for :attr:`Version.depends_list_str`
+ and possible keys being ``"Build-Depends"``, ``"Build-Depends-Indep"``,
+ ``"Build-Conflicts"`` or ``"Build-Conflicts-Indep"``.
+
+ .. attribute:: files
+
+ The list of files. This returns a list of :class:`SourceRecordsFile`
+
+ .. versionchanged:: 1.6
+
+ Used to be a list of tuples, see :class:`SourceRecordFile` for the tuple
+ layout.
+
+ .. attribute:: index
+
+ A list of :class:`IndexFile` objects associated with this
+ source package record.
+
+ .. attribute:: maintainer
+
+ A string describing the name of the maintainer.
+
+ .. attribute:: package
+
+ The name of the source package.
+
+ .. attribute:: record
+
+ The whole record, as a string. You can use :func:`apt_pkg.ParseSection`
+ if you need to parse it. You need to parse the record to access
+ fields not available via the attributes such as 'Standards-Version'
+
+ .. attribute:: section
+
+ A string describing the section.
+
+ .. attribute:: version
+
+ A string describing the version of the source package.
+
+.. class:: SourceRecordsFile
+
+ Represents a file in a source record.
+
+ .. versionadded:: 1.6
+
+ Before 1.6, this was a tuple `(md5, size, path, type)`.
+
+ .. attribute:: hashes
+
+ A :class:`HashStringList` of the file's hashes.
+
+ .. attribute:: path
+
+ The path to the file
+
+ .. attribute:: size
+
+ The size of the file
+
+ .. attribute:: type
+
+ The type of the file. Can be 'diff' (includes .debian.tar.gz), 'dsc', or 'tar'.
+
+The Acquire interface
+----------------------
+The Acquire Interface is responsible for all sorts of downloading in apt. All
+packages, index files, etc. downloading is done using the Acquire functionality.
+
+The :mod:`apt_pkg` module provides a subset of this functionality which allows
+you to implement file downloading in your applications. Together with the
+:class:`PackageManager` class you can also fetch all the packages marked for
+installation.
+
+.. class:: Acquire([progress: apt.progress.base.AcquireProgress])
+
+ Coordinate the retrieval of files via network or local file system
+ (using ``copy://path/to/file`` style URIs). Items can be added to
+ an Acquire object using various means such as creating instances
+ of :class:`AcquireFile` or the methods :meth:`SourceList.get_indexes`
+ and :meth:`PackageManager.get_archives`.
+
+ Acquire objects maintain a list of items which will be fetched or have
+ been fetched already during the lifetime of this object. To add new items
+ to this list, you can create new :class:`AcquireFile` objects which allow
+ you to add single files.
+
+ The constructor takes an optional parameter *progress* which takes an
+ :class:`apt.progress.base.AcquireProgress` object. This object may then
+ report progress information (see :mod:`apt.progress.text` for reporting
+ progress to a I/O stream).
+
+ Acquire items have two methods to start and stop the fetching:
+
+ .. method:: run() -> int
+
+ Fetch all the items which have been added by :class:`AcquireFile` and
+ return one of the constants :attr:`RESULT_CANCELLED`,
+ :attr:`RESULT_CONTINUE`, :attr:`RESULT_FAILED` to describe the
+ result of the run.
+
+ .. method:: shutdown()
+
+ Shut the fetcher down. This removes all items from the queue and
+ makes all :class:`AcquireItem`, :class:`AcquireWorker`,
+ :class:`AcquireItemDesc` objects useless. Accessing an object of one
+ of those types can cause a segfault then.
+
+ Removing an item does not mean that the already fetched data will
+ be removed from the destination. Instead, APT might use the partial
+ result and continue from thereon.
+
+ Furthermore, they provide three attributes which provide information
+ on how much data is already available and how much data still needs
+ to be fetched:
+
+ .. attribute:: fetch_needed
+
+ The amount of data that has to be fetched in order to fetch all
+ queued items.
+
+ .. attribute:: partial_present
+
+ The amount of data which is already available.
+
+ .. attribute:: total_needed
+
+ The total amount of bytes needed (including those of files which are
+ already present).
+
+ They also provide two attributes representing the items being processed
+ and the workers fetching them:
+
+ .. attribute:: items
+
+ A list of :class:`AcquireItem` objects which are attached to the
+ to this Acquire object. This includes all items ever attached to
+ this object (except if they were removed using, for example,
+ :meth:`shutdown()` or by deleting an :class:`AcquireFile` object.)
+
+ .. attribute:: workers
+
+ A list of :class:`AcquireWorker` objects which are currently active
+ on this instance.
+
+ The Acquire class comes with three constants which represents the results
+ of the :meth:`run` method:
+
+ .. attribute:: RESULT_CANCELLED
+
+ The fetching has been aborted, e.g. due to a progress class returning
+ ``False`` in its :meth:`pulse()` method.
+
+ .. attribute:: RESULT_CONTINUE
+
+ All items have been fetched successfully or failed transiently
+ and the process has not been canceled.
+
+ You need to look at the status of each item and check if it has not
+ failed transiently to discover errors like a Not Found when acquiring
+ packages.
+
+ .. attribute:: RESULT_FAILED
+
+ An item failed to fetch due to some reasons.
+
+
+.. class:: AcquireItem
+
+ An AcquireItem object represents a single item of an :class:`Acquire`
+ object. It is an abstract class to represent various types of items
+ which are implemented as subclasses. The only exported subclass is
+ :class:`AcquireFile` which can be used to fetch files.
+
+ .. attribute:: complete
+
+ A boolean value which is True only if the item has been
+ fetched successfully.
+
+ .. attribute:: desc_uri
+
+ An URI describing where the item is located at.
+
+ .. attribute:: destfile
+
+ The path to the local location where the fetched data will be
+ stored at.
+
+ .. attribute:: error_text
+
+ The error message. For example, when a file does not exist on a HTTP
+ server, this will contain a 404 error message.
+
+ .. attribute:: filesize
+
+ The size of the file, in bytes. If the size of the to be fetched file
+ is unknown, this attribute is set to ``0``.
+
+ .. attribute:: id
+
+ The ID of the item. This attribute is normally set to ``0``, users may
+ set a custom value here, for instance in an overridden
+ :meth:`apt.progress.base.AcquireProgress.fetch` method (the progress
+ class could keep a counter, increase it by one for every :meth:`fetch`
+ call and assign the current value to this attribute).
+
+ .. attribute:: is_trusted
+
+ A boolean value determining whether the file is trusted. Only ``True``
+ if the item represents a package coming from a repository which is
+ signed by one of the keys in APT's keyring.
+
+ .. attribute:: local
+
+ A boolean value determining whether this file is locally available
+ (``True``) or whether it has to be fetched from a remote source
+ (``False``).
+
+ .. attribute:: mode
+
+ Old name for active_subprocess
+
+ .. deprecated:: 1.0
+
+ .. attribute:: active_subprocess
+
+ The name of the active subprocess (for instance, 'gzip', 'rred' or 'gpgv').
+
+ .. versionadded:: 1.0
+
+ **Status**:
+
+ The following attribute represents the status of the item. This class
+ provides several constants for comparing against this value which are
+ listed here as well.
+
+ .. attribute:: status
+
+ Integer, representing the status of the item. This attribute can be
+ compared against the following constants to gain useful information
+ on the item's status.
+
+ .. attribute:: STAT_AUTH_ERROR
+
+ An authentication error occurred while trying to fetch the item.
+
+ .. attribute:: STAT_DONE
+
+ The item is completely fetched and there have been no problems
+ while fetching the item.
+
+ .. attribute:: STAT_ERROR
+
+ An error occurred while trying to fetch the item. This error is
+ normally not related to authentication problems, as thus are
+ dealt with using :attr:`STAT_AUTH_ERROR`.
+
+ .. attribute:: STAT_FETCHING
+
+ The item is being fetched currently.
+
+ .. attribute:: STAT_IDLE
+
+ The item is yet to be fetched.
+
+ .. attribute:: STAT_TRANSIENT_NETWORK_ERROR
+
+ There was a network error.
+
+
+.. class:: AcquireFile(owner, uri[, hash, size, descr, short_descr, destdir, destfile])
+
+ Create a new :class:`AcquireFile()` object and register it with *acquire*,
+ so it will be fetched. You must always keep around a reference to the
+ object, otherwise it will be removed from the Acquire queue again.
+
+ The parameter *owner* refers to an :class:`Acquire()` object as returned
+ by :func:`GetAcquire`. The file will be added to the Acquire queue
+ automatically.
+
+ The parameter *uri* refers to the location of the file, any protocol
+ of apt is supported.
+
+ The parameter *hash* refers to the hash of the file. If this is set
+ libapt will check the file after downloading. This should be an instance
+ of :class:`apt_pkg.HashStringList`.
+
+ The parameter *size* can be used to specify the size of the package,
+ which can then be used to calculate the progress and validate the download.
+
+ The parameter *descr* is a description of the download. It may be
+ used to describe the item in the progress class. *short_descr* is the
+ short form of it.
+
+ The parameters *descr* and *short_descr* can be used to specify
+ descriptions for the item. The string passed to *descr* should
+ describe the file and its origin (e.g. "http://localhost sid/main
+ python-apt 0.7.94.2") and the string passed to *short_descr* should
+ be one word such as the name of a package.
+
+ Normally, the file will be stored in the current directory using the
+ file name given in the URI. This directory can be changed by passing
+ the name of a directory to the *destdir* parameter. It is also possible
+ to set a path to a file using the *destfile* parameter, but both can
+ not be specified together.
+
+ In terms of attributes, this class is a subclass of :class:`AcquireItem`
+ and thus inherits all its attributes.
+
+ .. versionchanged:: 1.9.1
+
+ The *hash* parameter now accepts an :class:`apt_pkg.HashStringList`,
+ the old *md5* parameter has been removed.
+
+.. class:: AcquireWorker
+
+ An :class:`AcquireWorker` object represents a sub-process responsible for
+ fetching files from remote locations. There is no possibility to create
+ instances of this class from within Python, but a list of objects of
+ currently active workers is provided by :attr:`Acquire.workers`.
+
+ Objects of this type provide several attributes which give information
+ about the worker's current activity.
+
+ .. attribute:: current_item
+
+ The item which is currently being fetched. This returns an
+ :class:`AcquireItemDesc` object.
+
+ .. attribute:: current_size
+
+ How many bytes of the file have been downloaded. Zero if the current
+ progress of the file cannot be determined.
+
+ .. attribute:: resumepoint
+
+ The amount of data which was already available when the download was
+ started.
+
+ .. attribute:: status
+
+ The most recent (localized) status string received from the
+ sub-process.
+
+ .. attribute:: total_size
+
+ The total number of bytes to be downloaded for the item. Zero if the
+ total size is unknown.
+
+.. class:: AcquireItemDesc
+
+ An :class:`AcquireItemDesc` object stores information about the item which
+ can be used to describe the item. Objects of this class are used in the
+ progress classes, see the :class:`apt.progress.base.AcquireProgress`
+ documentation for information how.
+
+ .. attribute:: description
+
+ The long description given to the item.
+
+ .. attribute:: owner
+
+ The :class:`AcquireItem` object owning this object.
+
+ .. attribute:: shortdesc
+
+ A short description which has been given to this item.
+
+ .. attribute:: uri
+
+ The URI from which this item would be downloaded.
+
+
+Hashes
+------
+The apt_pkg module also provides several hash functions. If you develop
+applications with python-apt it is often easier to use these functions instead
+of the ones provides in Python's :mod:`hashlib` module.
+
+The module provides the two classes :class:`Hashes` and :class:`HashString` for
+generic hash support:
+
+.. autoclass:: Hashes
+ :members:
+
+.. class:: HashString(type: str[, hash: str])
+
+ HashString objects store the type of a hash and the corresponding hash.
+ They are used by e.g :meth:`IndexRecords.lookup`. The first parameter,
+ *type* refers to one of "MD5Sum", "SHA1" and "SHA256". The second parameter
+ *hash* is the corresponding hash.
+
+ You can also use a combined form by passing a string with type and hash
+ separated by a colon as the only argument. For example::
+
+ HashString("MD5Sum:d41d8cd98f00b204e9800998ecf8427e")
+
+
+ .. describe:: str(hashstring)
+
+ Convert the HashString to a string by joining the hash type and the
+ hash using ':', e.g. ``"MD5Sum:d41d8cd98f00b204e9800998ecf8427e"``.
+
+ .. attribute:: hashtype
+
+ The type of the hash, as a string. This may be "MD5Sum", "SHA1",
+ "SHA256" or "SHA512".
+
+ .. autoattribute:: hashvalue
+
+ .. autoattribute:: usable
+
+ .. method:: verify_file(filename: str) -> bool
+
+ Verify that the file given by the parameter *filename* matches the
+ hash stored in this object.
+
+.. autoclass:: HashStringList
+ :members:
+
+ .. describe:: len(list)
+
+ Return the length of the list
+
+ .. describe:: list[index]
+
+ Get the :class:`HashString` object at the specified index.
+
+The :mod:`apt_pkg` module also provides the functions :func:`md5sum`,
+:func:`sha1sum` and :func:`sha256sum` for creating a single hash from a
+:class:`bytes` or :class:`file` object:
+
+.. function:: md5sum(object)
+
+ Return the md5sum of the object. *object* may either be a string, in
+ which case the md5sum of the string is returned, or a :class:`file()`
+ object (or a file descriptor), in which case the md5sum of its contents is
+ returned.
+
+ .. versionchanged:: 0.7.100
+ Added support for using file descriptors.
+
+ .. deprecated:: 1.9
+
+ Use :class:`apt_pkg.Hashes` instead. This function will be removed
+ in a later release.
+
+.. function:: sha1sum(object)
+
+ Return the sha1sum of the object. *object* may either be a string, in
+ which case the sha1sum of the string is returned, or a :class:`file()`
+ object (or a file descriptor), in which case the sha1sum of its contents
+ is returned.
+
+ .. versionchanged:: 0.7.100
+ Added support for using file descriptors.
+
+ .. deprecated:: 1.9
+
+ Use :class:`apt_pkg.Hashes` instead. This function will be removed
+ in a later release.
+
+.. function:: sha256sum(object)
+
+ Return the sha256sum of the object. *object* may either be a string, in
+ which case the sha256sum of the string is returned, or a :class:`file()`
+ object (or a file descriptor), in which case the sha256sum of its contents
+ is returned.
+
+ .. versionchanged:: 0.7.100
+ Added support for using file descriptors.
+
+ .. deprecated:: 1.9
+
+ Use :class:`apt_pkg.Hashes` instead. This function will be removed
+ in a later release.
+
+Debian control files
+--------------------
+Debian control files are files containing multiple stanzas of :RFC:`822`-style
+header sections. They are widely used in the Debian community, and can represent
+many kinds of information. One example for such a file is the
+:file:`/var/lib/dpkg/status` file which contains a list of the currently
+installed packages.
+
+The :mod:`apt_pkg` module provides two classes to read those files and parts
+thereof and provides a function :func:`RewriteSection` which takes a
+:class:`TagSection()` object and sorting information and outputs a sorted
+section as a string.
+
+.. class:: TagFile(file, bytes: bool = False)
+
+ An object which represents a typical debian control file. Can be used for
+ Packages, Sources, control, Release, etc.
+
+ The *file* argument shall be a path name or an open file object. The
+ argument *bytes* specifies whether the file shall be represented using
+ bytes (``True``) or unicode (``False``) strings.
+
+ It is a context manager that can be used with a with statement or the
+ :meth:`close` method.
+
+ .. describe:: with TagFile(...) as ...:
+
+ Use the :class:`TagFile` as a context manager. This will automatically
+ close the file after the body finished execution.
+
+ .. versionadded:: 1.0
+
+ .. method:: close()
+
+ Close the file. It's recommended to use the context manager
+ instead (that is, the `with` statement).
+
+ .. versionadded:: 1.0
+
+ It provides two kinds of API which should not be used together:
+
+ The first API implements the iterator protocol and should be used whenever
+ possible because it has less side effects than the other one. It may be
+ used e.g. with a for loop::
+
+ with apt_pkg.TagFile('/var/lib/dpkg/status') as tagfile:
+ for section in tagfile:
+ print(section['Package'])
+
+ .. versionchanged:: 0.7.100
+ Added support for using gzip files, via :class:`gzip.GzipFile` or any
+ file containing a compressed gzip stream.
+
+ .. versionadded:: 0.8.5
+
+ Added support for using bytes instead of str in Python 3
+
+ .. method:: next()
+
+ A TagFile is its own iterator. This method is part of the iterator
+ protocol and returns a :class:`TagSection` object for the next
+ section in the file. If there is no further section, this method
+ raises the :exc:`StopIteration` exception.
+
+ From Python 3 on, this method is not available anymore, and the
+ global function ``next()`` replaces it.
+
+ The second API uses a shared :class:`TagSection` object which is exposed
+ through the :attr:`section` attribute. This object is modified by calls
+ to :meth:`step` and :meth:`jump`. This API provides more control and may
+ use less memory, but is not recommended because it works by modifying
+ one object. It can be used like this::
+
+ with apt_pkg.TagFile('/var/lib/dpkg/status') as tagf:
+ tagf.step()
+ print tagf.section['Package']
+
+ .. method:: step() -> bool
+
+ Step forward to the next section. This simply returns ``True`` if OK,
+ and ``False`` if there is no section.
+
+ .. method:: offset() -> int
+
+ Return the current offset (in bytes) from the beginning of the file.
+
+ .. method:: jump(offset) -> bool
+
+ Jump back/forward to *offset*. Use ``jump(0)`` to jump to the
+ beginning of the file again. Returns ``True`` if a section could
+ be parsed or ``False`` if not.
+
+ .. attribute:: section
+
+ This is the current :class:`TagSection()` instance.
+
+.. class:: TagSection(text)
+
+ Represent a single section of a debian control file.
+
+ .. describe:: section[key]
+
+ Return the value of the field at *key*. If *key* is not available,
+ raise :exc:`KeyError`.
+
+ .. describe:: key in section
+
+ Return ``True`` if *section* has a key *key*, else ``False``.
+
+ .. versionadded:: 0.7.100
+
+ .. method:: bytes() -> int
+
+ The number of bytes in the section.
+
+ .. method:: find(key: str, default: str = '') -> str
+
+ Return the value of the field at the key *key* if available,
+ else return *default*.
+
+ .. method:: find_flag(key: str) -> bool
+
+ Find a yes/no value for the key *key*. An example for such a
+ field is 'Essential'.
+
+ .. method:: find_raw(key: str, default: str = '') -> str
+
+ Similar to :meth:`find`, but instead of returning just the value,
+ it returns the complete field consisting of 'key: value'.
+
+ .. method:: get(key: str, default: str = '')
+
+ Return the value of the field at the key *key* if available, else
+ return *default*.
+
+ .. method:: keys()
+
+ Return a list of keys in the section.
+
+
+ .. automethod:: write
+
+
+A function can be rewritten by using tag classes:
+
+.. autoclass:: Tag
+ :members:
+
+ The following static members can be used to determine the meaning of
+ :attr:`action`:
+
+ .. data:: REWRITE
+
+ Change the field value to the value of :attr:`data`
+
+ .. data:: RENAME
+
+ Rename the tag to a new tag stored in :attr:`data`.
+
+ .. data:: REMOVE
+
+ Remove the tag.
+
+ Apart from this, the class provides access to several attributes.
+
+.. autoclass:: TagRewrite
+
+.. autoclass:: TagRemove
+
+.. autoclass:: TagRename
+
+Pre-defined ordering for tag sections are:
+
+.. data:: REWRITE_PACKAGE_ORDER
+
+ The order in which the information for binary packages should be rewritten,
+ i.e. the order in which the fields should appear.
+
+.. data:: REWRITE_SOURCE_ORDER
+
+ The order in which the information for source packages should be rewritten,
+ i.e. the order in which the fields should appear.
+
+
+Dependencies
+------------
+.. function:: check_dep(pkgver: str, op: str, depver: str) -> bool
+
+ Check that the given requirement is fulfilled; that is, that the version
+ string given by *pkg_ver* matches the version string *dep_ver* under
+ the condition specified by the operator 'dep_op' (<,<=,=,>=,>).
+
+ Return True if *pkg_ver* matches *dep_ver* under the condition 'dep_op';
+ for example::
+
+ >>> apt_pkg.check_dep("1.0", ">=", "1")
+ True
+
+The following two functions provide the ability to parse dependencies. They
+use the same format as :attr:`Version.depends_list_str`.
+
+.. function:: parse_depends(depends, strip_multiarch=True, architecture)
+
+ Parse the string *depends* which contains dependency information as
+ specified in Debian Policy, Section 7.1.
+
+ Returns a list. The members of this list are lists themselves and contain
+ one or more tuples in the format ``(package,version,operation)`` for every
+ 'or'-option given, e.g.::
+
+ >>> apt_pkg.parse_depends("PkgA (>= VerA) | PkgB (>= VerB)")
+ [[('PkgA', 'VerA', '>='), ('PkgB', 'VerB', '>=')]]
+
+ Note that multiarch dependency information is stripped off by default.
+ You can force the full dependency info (including the multiarch info)
+ by passing "False" as a additional parameter to this function.
+
+ You can specify an optional argument *architecture* that treats the given
+ architecture as the native architecture for purposes of parsing the
+ dependency.
+
+ .. note::
+
+ The behavior of this function is different than the behavior of the
+ old function :func:`ParseDepends()`, because the third field
+ ``operation`` uses `>` instead of `>>` and `<` instead of `<<` which
+ is specified in control files.
+
+
+.. function:: parse_src_depends(depends, strip_multiarch=True, architecture)
+
+ Parse the string *depends* which contains dependency information as
+ specified in Debian Policy, Section 7.1.
+
+ Returns a list. The members of this list are lists themselves and contain
+ one or more tuples in the format ``(package,version,operation)`` for every
+ 'or'-option given, e.g.::
+
+ >>> apt_pkg.parse_depends("PkgA (>= VerA) | PkgB (>= VerB)")
+ [[('PkgA', 'VerA', '>='), ('PkgB', 'VerB', '>=')]]
+
+
+ Furthemore, this function also supports to limit the architectures, as
+ used in e.g. Build-Depends::
+
+ >>> apt_pkg.parse_src_depends("a (>= 01) [i386 amd64]")
+ [[('a', '01', '>=')]]
+
+ Note that multiarch dependency information is stripped off by default.
+ You can force the full dependency info (including the multiarch info)
+ by passing "False" as a additional parameter to this function.
+
+ You can specify an optional argument *architecture* that treats the given
+ architecture as the native architecture for purposes of parsing the
+ dependency.
+
+ .. note::
+
+ The behavior of this function is different than the behavior of the
+ old function :func:`ParseDepends()`, because the third field
+ ``operation`` uses `>` instead of `>>` and `<` instead of `<<` which
+ is specified in control files.
+
+
+Configuration and Command-line parsing
+--------------------------------------
+
+.. class:: Configuration()
+
+ Provide access to and manipulation of APT's configuration which is
+ used by many classes and functions in this module to define their
+ behavior. There are options to install recommends, change the root
+ directory and much more. For an (incomplete) list of available options,
+ see the :manpage:`apt.conf(5)` manual page.
+
+ The most important Configuration object is the one available by the
+ module's :attr:`apt_pkg.config` attribute. It stores the global
+ configuration which affects the behavior of most functions and is
+ initialized by a call to the function :func:`init_config`. While
+ possible, it is generally not needed to create other instances of
+ this class.
+
+ For accessing and manipulating the configuration space, objects
+ of this type provide an interface which resembles Python mapping
+ types like :class:`dict`.
+
+ .. describe:: key in conf
+
+ Return ``True`` if *conf* has a key *key*, else ``False``.
+
+ .. describe:: conf[key]
+
+ Return the value of the option given key *key*. If it does not
+ exist, raise :exc:`KeyError`.
+
+ .. describe:: conf[key] = value
+
+ Set the option at *key* to *value*.
+
+ .. describe del conf[key]
+
+ Delete the option with the name *key* in the configuration object
+ *conf*.
+
+ .. method:: get(key[, default='']) -> str
+
+ Find the value for the given key and return it. If the given key does
+ not exist, return *default* instead.
+
+ In addition, they provide methods to resemble the interface provided
+ by the C++ class and some more mapping methods which have been enhanced
+ to support some more advanced configuration features:
+
+ .. method:: clear(key: str)
+
+ Remove the option at *key* and all of its children.
+
+ .. method:: dump() -> str
+
+ Return a string containing the values in the configuration object,
+ in the standard :manpage:`apt.conf(5)` format.
+
+ .. versionadded:: 0.7.100
+
+ .. method:: exists(key)
+
+ Check whether an option named *key* exists in the configuration.
+
+ .. method:: find(key[, default='']) -> str
+
+ Return the value stored at the option named *key*, or the value
+ given by the string *default* if the option in question is not
+ set.
+
+ .. method:: find_b(key[, default=False]) -> bool
+
+ Return the boolean value stored at *key*, or the value given by
+ the :class:`bool` object *default* if the requested option is
+ not set.
+
+ .. method:: find_file(key[, default='']) -> str
+ find_dir(key[, default='/']) -> str
+
+ Locate the given key using :meth:`find` and return the path to the
+ file/directory. This uses a special algorithms which moves upwards
+ in the configuration space and prepends the values of the options
+ to the result. These methods are generally used for the options
+ stored in the 'Dir' section of the configuration.
+
+ As an example of how this works, take a look at the following options
+ and their values:
+
+ .. table::
+
+ ============== ===========================
+ Option Value
+ ============== ===========================
+ Dir /
+ Dir::Etc etc/apt/
+ Dir::Etc::main apt.conf
+ ============== ===========================
+
+ A call to :meth:`find_file` would now return ``/etc/apt/apt.conf``
+ because it prepends the values of "Dir::Etc" and "Dir" to the value
+ of "Dir::Etc::main"::
+
+ >>> apt_pkg.config.find_file("Dir::Etc::main")
+ '/etc/apt/apt.conf'
+
+ If the special configuration variable "RootDir" is set, this value
+ would be prepended to every return value, even if the path is already
+ absolute. If not, the function ends as soon as an absolute path is
+ created (once an option with a value starting with "/" is read).
+
+ The method :meth:`find_dir` does exactly the same thing as
+ :meth:`find_file`, but adds a trailing forward slash before
+ returning the value.
+
+ .. method:: find_i(key[, default=0]) -> int
+
+ Return the integer value stored at *key*, or the value given by
+ the integer *default* if the requested option is not set.
+
+ .. method:: keys([key])
+
+ Return a recursive list of all configuration options or, if *key*
+ is given, a list of all its children. This method is comparable
+ to the **keys** method of a mapping object, but additionally
+ provides the parameter *key*.
+
+ .. method:: list([key])
+
+ Return a non-recursive list of all configuration options. If *key*
+ is not given, this returns a list of options like "Apt", "Dir", and
+ similar. If *key* is given, a list of the names of its child options
+ will be returned instead.
+
+ .. method:: my_tag()
+
+ Return the tag name of the current tree. Normally (for
+ :data:`apt_pkg.config`) this is an empty string, but for
+ sub-trees it is the key of the sub-tree.
+
+ .. method:: set(key: str, value: str)
+
+ Set the option named *key* to the value given by the argument
+ *value*. It is possible to store objects of the types :class:`int`
+ and :class:`bool` by calling :func:`str` on them to convert them
+ to a string object. They can then be retrieved again by using the
+ methods :meth:`find_i` or :meth:`find_b`.
+
+ .. method:: subtree(key)
+
+ Return a new apt_pkg.Configuration object which starts at the
+ given option. Example::
+
+ apttree = config.subtree('APT')
+ apttree['Install-Suggests'] = config['APT::Install-Suggests']
+
+ The configuration space is shared with the main object which means
+ that all modifications in one object appear in the other one as
+ well.
+
+ .. method:: value_list([key])
+
+ This is the opposite of the :meth:`list` method in that it returns the
+ values instead of the option names.
+
+.. data:: config
+
+ This variable contains the global configuration which is used by
+ all classes and functions in this module. After importing the
+ module, this object should be initialized by calling the module's
+ :func:`init_config` function.
+
+.. function:: read_config_file(configuration: Configuration, filename: str)
+
+ Read the configuration file *filename* and set the appropriate
+ options in the configuration object *configuration*.
+
+.. function:: read_config_dir(configuration, dirname)
+
+ Read all configuration files in the dir given by 'dirname' in the
+ correct order.
+
+
+.. function:: read_config_file_isc(configuration, filename)
+
+ Read the configuration file *filename* and set the appropriate
+ options in the configuration object *configuration*. This function
+ requires a slightly different format than APT configuration files,
+ if you are unsure, do not use it.
+
+.. function:: parse_commandline(configuration, options, argv)
+
+ Parse the command line in *argv* into the configuration space. The
+ list *options* contains a list of 3-tuples or 4-tuples in the form::
+
+ (short_option: str, long_option: str, variable: str[, type: str])
+
+ The element *short_option* is one character, the *long_option* element
+ is the name of the long option, the element *variable* the name of the
+ configuration option the result will be stored in and *type* is one of
+ 'HasArg', 'IntLevel', 'Boolean', 'InvBoolean', 'ConfigFile',
+ 'ArbItem'. The default type is 'Boolean'.
+
+ .. table:: Overview of all possible types
+
+ =========== =====================================================
+ Type What happens if the option is given
+ =========== =====================================================
+ HasArg The argument given to the option is stored in
+ the target.
+ IntLevel The integer value in the target is increased by one
+ Boolean The target variable is set to True.
+ InvBoolean The target variable is set to False.
+ ConfigFile The file given as an argument to this option is read
+ in and all configuration options are added to the
+ configuration object (APT's '-c' option).
+ ArbItem The option takes an argument *key*=*value*, and the
+ configuration option at *key* is set to the value
+ *value* (APT's '-o' option).
+ =========== =====================================================
+
+
+Locking
+--------
+When working on the global cache, it is important to lock the cache so other
+programs do not modify it. This module provides two context managers for
+locking the package system or file-based locking.
+
+.. class:: SystemLock
+
+ Context manager for locking the package system. The lock is established
+ as soon as the method __enter__() is called. It is released when
+ __exit__() is called. If the lock can not be acquired or can not be
+ released an exception is raised.
+
+ This should be used via the 'with' statement. For example::
+
+ with apt_pkg.SystemLock():
+ ... # Do your stuff here.
+ ... # Now it's unlocked again
+
+ Once the block is left, the lock is released automatically. The object
+ can be used multiple times::
+
+ lock = apt_pkg.SystemLock()
+ with lock:
+ ...
+ with lock:
+ ...
+
+.. class:: FileLock(filename: str)
+
+ Context manager for locking using a file. The lock is established
+ as soon as the method __enter__() is called. It is released when
+ __exit__() is called. If the lock can not be acquired or can not be
+ released, an exception is raised.
+
+ This should be used via the 'with' statement. For example::
+
+ with apt_pkg.FileLock(filename):
+ ...
+
+ Once the block is left, the lock is released automatically. The object
+ can be used multiple times::
+
+ lock = apt_pkg.FileLock(filename)
+ with lock:
+ ...
+ with lock:
+ ...
+
+For Python versions prior to 2.5, similar functionality is provided by the
+following three functions:
+
+.. function:: get_lock(filename: str, errors=False) -> int
+
+ Create an empty file at the path specified by the parameter *filename* and
+ lock it. If this fails and *errors* is **True**, the function raises an
+ error. If *errors* is **False**, the function returns -1.
+
+ The lock can be acquired multiple times within the same process, and can be
+ released by calling :func:`os.close` on the return value which is the file
+ descriptor of the created file.
+
+.. function:: pkgsystem_lock()
+
+ Lock the global pkgsystem. The lock should be released by calling
+ :func:`pkgsystem_unlock` again. If this function is called n-times, the
+ :func:`pkgsystem_unlock` function must be called n-times as well to release
+ all acquired locks.
+
+.. function:: pkgsystem_unlock()
+
+ Unlock the global pkgsystem. This reverts the effect of
+ :func:`pkgsystem_lock`.
+
+Since version 1.7, APT switches to the frontend locking approach where
+dpkg has two lock files, :file:`lock-frontend` and :file:`lock`, the
+latter being called the inner lock in apt.
+When running dpkg, the inner lock must be released before calling dpkg
+and reacquired afterwards. When not using APT functions to run dpkg,
+the variable `DPKG_FRONTEND_LOCKED` must be set to tell dpkg to not
+acquire the :file:`lock-frontend` lock.
+These functions usually do not need to be used by external code.
+
+.. function:: pkgsystem_unlock_inner()
+
+ Release the :file:`lock` lock file to allow dpkg to be run.
+
+ .. versionadded:: 1.7
+
+.. function:: pkgsystem_lock_inner()
+
+ Release the :file:`lock` lock file after a dpkg run.
+
+ .. versionadded:: 1.7
+
+.. function:: pkgsystem_is_locked()
+
+ Returns true if the global lock is hold. Can be used to check whether
+ :meth:`pkgsystem_unlock_inner` needs to be called.
+
+ .. versionadded:: 1.7
+
+
+
+Other classes
+--------------
+.. class:: Cdrom()
+
+ A Cdrom object identifies Debian installation media and adds them to
+ :file:`/etc/apt/sources.list`. The C++ version of this class is used by
+ the apt-cdrom tool and using this class, you can re-implement apt-cdrom
+ in Python, see :doc:`../tutorials/apt-cdrom`.
+
+ The class :class:`apt.cdrom.Cdrom` is a subclass of this class and
+ provides some additional functionality for higher level use and some
+ shortcuts for setting some related configuration options.
+
+ This class provides two functions which take an instance of
+ :class:`apt.progress.base.CdromProgress` as their argument.
+
+ .. method:: add(progress: apt.progress.base.CdromProgress) -> bool
+
+ Search for a Debian installation media and add it to the list of
+ sources stored in :file:`/etc/apt/sources.list`. On success, the
+ boolean value ``True`` is returned. If the process failed or was
+ canceled by the progress class, :exc:`SystemError` is raised or
+ ``False`` is returned.
+
+ .. method:: ident(progress: apt.progress.base.CdromProgress) -> str
+
+ Identify the installation media and return a string which describes
+ its identity. If no media could be identified, :exc:`SystemError` is
+ raised or ``None`` is returned.
+
+.. class:: SourceList
+
+ Represent the list of sources stored in files such as
+ :file:`/etc/apt/sources.list`.
+
+ .. method:: find_index(pkgfile: PackageFile) -> IndexFile
+
+ Return the :class:`IndexFile` object for the :class:`PackageFile`
+ object given by the argument *pkgfile*. If no index could be found,
+ return ``None``.
+
+ .. method:: get_indexes(acquire: Acquire[, all: bool = False]) -> bool
+
+ Add all indexes to the :class:`Acquire` object given by the argument
+ *acquire*. If *all* is ``True``, all indexes will be added, otherwise
+ only the meta indexes (Release files) will be added and others are
+ fetched as needed.
+
+ .. method:: read_main_list() -> bool
+
+ Read the files configured in Dir::Etc::SourceList and
+ Dir::Etc::sourceparts; that is (on normal system),
+ :file:`/etc/apt/sources.list` and the files in
+ :file:`/etc/apt/sources.list.d`.
+
+ .. attribute:: list
+
+ A list of :class:`MetaIndex` objects.
+
+String functions
+----------------
+.. function:: base64_encode(value: bytes) -> str
+
+ Encode the given bytes string (which may not contain a null byte)
+ using base64, for example, on Python 3 and newer::
+
+ >>> apt_pkg.base64_encode(b"A")
+ 'QQ=='
+
+ on Python versions prior to 3, the 'b' before the string has to be
+ omitted.
+
+.. function:: check_domain_list(host, list)
+
+ See if the host name given by *host* is one of the domains given in the
+ comma-separated list *list* or a subdomain of one of them.
+
+ >>> apt_pkg.check_domain_list("alioth.debian.org","debian.net,debian.org")
+ True
+
+.. function:: dequote_string(string: str)
+
+ Dequote the string specified by the parameter *string*, e.g.::
+
+ >>> apt_pkg.dequote_string("%61%70%74%20is%20cool")
+ 'apt is cool'
+
+.. function:: quote_string(string, repl)
+
+ Escape the string *string*, replacing any character not allowed in a URL
+ or specified by *repl* with its ASCII value preceded by a percent sign
+ (so for example ' ' becomes '%20').
+
+ >>> apt_pkg.quote_string("apt is cool","apt")
+ '%61%70%74%20is%20cool'
+
+.. function:: size_to_str(size: int)
+
+ Return a string describing the size in a human-readable manner using
+ SI prefix and base-10 units, e.g. '1k' for 1000, '1M' for 1000000, etc.
+
+ Example::
+
+ >>> apt_pkg.size_to_str(10000)
+ '10.0k'
+
+.. function:: string_to_bool(input)
+
+ Parse the string *input* and return one of **-1**, **0**, **1**.
+
+ .. table:: Return values
+
+ ===== =============================================
+ Value Meaning
+ ===== =============================================
+ -1 The string *input* is not recognized.
+ 0 The string *input* evaluates to **False**.
+ +1 The string *input* evaluates to **True**.
+ ===== =============================================
+
+ Example::
+
+ >>> apt_pkg.string_to_bool("yes")
+ 1
+ >>> apt_pkg.string_to_bool("no")
+ 0
+ >>> apt_pkg.string_to_bool("not-recognized")
+ -1
+
+
+.. function:: str_to_time(rfc_time)
+
+ Convert the :rfc:`1123` conforming string *rfc_time* to the unix time, and
+ return the integer. This is the opposite of :func:`TimeRFC1123`.
+
+ Example::
+
+ >> apt_pkg.str_to_time('Thu, 01 Jan 1970 00:00:00 GMT')
+ 0
+
+.. function:: time_rfc1123(seconds: int) -> str
+
+ Format the unix time specified by the integer *seconds*, according to the
+ requirements of :rfc:`1123`.
+
+ Example::
+
+ >>> apt_pkg.time_rfc1123(0)
+ 'Thu, 01 Jan 1970 00:00:00 GMT'
+
+
+.. function:: time_to_str(seconds: int) -> str
+
+ Format a given duration in a human-readable manner. The parameter *seconds*
+ refers to a number of seconds, given as an integer. The return value is a
+ string with a unit like 's' for seconds.
+
+ Example::
+
+ >>> apt_pkg.time_to_str(3601)
+ '1h0min1s'
+
+.. function:: upstream_version(version: str) -> str
+
+ Return the upstream version for the Debian package version given by
+ *version*.
+
+.. function:: uri_to_filename(uri: str) -> str
+
+ Take a string *uri* as parameter and return a filename which can be used to
+ store the file, based on the URI.
+
+ Example::
+
+ >>> apt_pkg.uri_to_filename('http://debian.org/index.html')
+ 'debian.org_index.html'
+
+
+.. function:: version_compare(a: str, b: str) -> int
+
+ Compare two versions, *a* and *b*, and return an integer value which has
+ the same meaning as the built-in :func:`cmp` function's return value has,
+ see the following table for details.
+
+ .. table:: Return values
+
+ ===== =============================================
+ Value Meaning
+ ===== =============================================
+ > 0 The version *a* is greater than version *b*.
+ = 0 Both versions are equal.
+ < 0 The version *a* is less than version *b*.
+ ===== =============================================
+
+
+Module Constants
+----------------
+.. _CurStates:
+
+Package States
+^^^^^^^^^^^^^^^
+.. data:: CURSTATE_CONFIG_FILES
+
+ Only the configuration files of the package exist on the system.
+
+.. data:: CURSTATE_HALF_CONFIGURED
+
+ The package is unpacked and configuration has been started, but not
+ yet completed.
+
+.. data:: CURSTATE_HALF_INSTALLED
+
+ The installation of the package has been started, but not completed.
+
+.. data:: CURSTATE_INSTALLED
+
+ The package is unpacked, configured and OK.
+
+.. data:: CURSTATE_NOT_INSTALLED
+
+ The package is not installed.
+
+.. data:: CURSTATE_UNPACKED
+
+ The package is unpacked, but not configured.
+
+.. _InstStates:
+
+Installed states
+^^^^^^^^^^^^^^^^
+.. data:: INSTSTATE_HOLD
+
+ The package is put on hold.
+
+.. data:: INSTSTATE_HOLD_REINSTREQ
+
+ The package is put on hold, but broken and has to be reinstalled.
+
+.. data:: INSTSTATE_OK
+
+ The package is OK.
+
+.. data:: INSTSTATE_REINSTREQ
+
+ The package is broken and has to be reinstalled.
+
+.. _Priorities:
+
+Priorities
+^^^^^^^^^^^
+.. data:: PRI_EXTRA
+
+ The integer representation of the priority 'extra'.
+
+.. data:: PRI_IMPORTANT
+
+ The integer representation of the priority 'important'.
+
+.. data:: PRI_OPTIONAL
+
+ The integer representation of the priority 'optional'.
+
+.. data:: PRI_REQUIRED
+
+ The integer representation of the priority 'required'.
+
+.. data:: PRI_STANDARD
+
+ The integer representation of the priority 'standard'.
+
+
+.. _SelStates:
+
+Package selection states
+^^^^^^^^^^^^^^^^^^^^^^^^
+.. data:: SELSTATE_DEINSTALL
+
+ The package is selected for deinstallation.
+
+.. data:: SELSTATE_HOLD
+
+ The package is marked to be on hold and will not be modified.
+
+.. data:: SELSTATE_INSTALL
+
+ The package is selected for installation.
+
+.. data:: SELSTATE_PURGE
+
+ The package is selected to be purged.
+
+.. data:: SELSTATE_UNKNOWN
+
+ The package is in an unknown state.
+
+
+Build information
+^^^^^^^^^^^^^^^^^
+.. data:: DATE
+
+ The date on which this extension has been compiled.
+
+.. data:: LIB_VERSION
+
+ The version of the apt_pkg library. This is **not** the version of apt,
+ nor the version of python-apt.
+
+.. data:: TIME
+
+ The time this extension has been built.
+
+.. data:: VERSION
+
+ The version of apt (not of python-apt).
diff --git a/doc/source/library/aptsources.distinfo.rst b/doc/source/library/aptsources.distinfo.rst
new file mode 100644
index 0000000..033ef48
--- /dev/null
+++ b/doc/source/library/aptsources.distinfo.rst
@@ -0,0 +1,11 @@
+:mod:`aptsources.distinfo` --- provide meta information for distro repositories
+===============================================================================
+.. note::
+
+ This part of the documentation is created automatically.
+
+
+.. automodule:: aptsources.distinfo
+ :members:
+ :undoc-members:
+
diff --git a/doc/source/library/aptsources.distro.rst b/doc/source/library/aptsources.distro.rst
new file mode 100644
index 0000000..6ebe438
--- /dev/null
+++ b/doc/source/library/aptsources.distro.rst
@@ -0,0 +1,11 @@
+:mod:`aptsources.distro` --- Distribution abstraction of the sources.list
+===============================================================================
+.. note::
+
+ This part of the documentation is created automatically.
+
+
+.. automodule:: aptsources.distro
+ :members:
+ :undoc-members:
+
diff --git a/doc/source/library/aptsources.sourceslist.rst b/doc/source/library/aptsources.sourceslist.rst
new file mode 100644
index 0000000..79b8dd0
--- /dev/null
+++ b/doc/source/library/aptsources.sourceslist.rst
@@ -0,0 +1,11 @@
+:mod:`aptsources.sourceslist` --- Provide an abstraction of the sources.list
+============================================================================
+.. note::
+
+ This part of the documentation is created automatically.
+
+
+.. automodule:: aptsources.sourceslist
+ :members:
+ :undoc-members:
+
diff --git a/doc/source/library/index.rst b/doc/source/library/index.rst
new file mode 100644
index 0000000..0b048c8
--- /dev/null
+++ b/doc/source/library/index.rst
@@ -0,0 +1,35 @@
+Python APT Library
+==================
+Python APT's library provides access to almost every functionality supported
+by the underlying apt-pkg and apt-inst libraries. This means that it is
+possible to rewrite frontend programs like apt-cdrom in Python, and this is
+relatively easy, as can be seen in e.g. :doc:`../tutorials/apt-cdrom`.
+
+When going through the library, the first two modules are :mod:`apt_pkg` and
+:mod:`apt_inst`. These modules are more or less straight bindings to the
+apt-pkg and apt-inst libraries and the base for the rest of python-apt.
+
+Going forward, the :mod:`apt` package appears. This package is using
+:mod:`apt_pkg` and :mod:`apt_inst` to provide easy to use ways to manipulate
+the cache, fetch packages, or install new packages. It also provides useful
+progress classes, currently only for text interfaces. The last package is
+:mod:`aptsources`. The aptsources package provides classes and functions to
+read files like :file:`/etc/apt/sources.list` and to modify them.
+
+.. toctree::
+ :maxdepth: 1
+
+ apt_pkg
+ apt_inst
+
+ apt.cache
+ apt.cdrom
+ apt.debfile
+ apt.package
+ apt.progress.base
+ apt.progress.text
+
+ aptsources.distinfo
+ aptsources.distro
+ aptsources.sourceslist
+
diff --git a/doc/source/templates/indexcontent.html b/doc/source/templates/indexcontent.html
new file mode 100644
index 0000000..be5277e
--- /dev/null
+++ b/doc/source/templates/indexcontent.html
@@ -0,0 +1,50 @@
+{% extends "layout.html" %}
+{% block body %}
+ <h1>{{ docstitle|e }}</h1>
+ <p>
+ Welcome! This is
+ {% block description %}the documentation for {{ project|e }}
+ {{ release|e }}{% if last_updated %}, last updated {{ last_updated|e }}{% endif %}{% endblock %}.
+ </p>
+
+ <p>
+ This documentation has been created using Sphinx and reStructuredText files
+ written by Julian Andres Klode &lt;jak@debian.org&gt;.
+ </p>
+
+
+
+
+ <p><strong>Parts of the documentation:</strong></p>
+ <table class="contentstable" align="center"><tr>
+ <td width="50%">
+ <p class="biglink"><a class="biglink" href="{{ pathto("whatsnew/" + version) }}">What's new in Python APT {{ version }}?</a><br/>
+ <span class="linkdescr">or <a href="{{ pathto("whatsnew/index") }}">all "What's new" documents</a></span></span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("library/index") }}">Library Reference</a><br/>
+ <span class="linkdescr">keep this under your pillow</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("tutorials/index") }}">Tutorials</a><br/>
+ <span class="linkdescr">examples and more...</span></p>
+ </td><td width="50%">
+ <p class="biglink"><a class="biglink" href="{{ pathto("c++/embedding") }}">Embedding</a><br/>
+ <span class="linkdescr">tutorial for C++ programmers</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("c++/api") }}">C++ API</a><br/>
+ <span class="linkdescr">reference for C++ programmers</span></p>
+ </td></tr>
+ </table>
+
+ <p><strong>Indices and tables:</strong></p>
+ <table class="contentstable" align="center"><tr>
+ <td width="50%">
+ <p class="biglink"><a class="biglink" href="{{ pathto("py-modindex") }}">Global Module Index</a><br/>
+ <span class="linkdescr">quick access to all modules</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("genindex") }}">General Index</a><br/>
+ <span class="linkdescr">all functions, classes, terms</span></p>
+ </td><td width="50%">
+ <p class="biglink"><a class="biglink" href="{{ pathto("search") }}">Search page</a><br/>
+ <span class="linkdescr">search this documentation</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("contents") }}">Complete Table of Contents</a><br/>
+ <span class="linkdescr">lists all sections and subsections</span></p>
+ </td></tr>
+ </table>
+
+{% endblock %}
diff --git a/doc/source/templates/layout.html b/doc/source/templates/layout.html
new file mode 100644
index 0000000..04a3e0d
--- /dev/null
+++ b/doc/source/templates/layout.html
@@ -0,0 +1,4 @@
+{% extends "!layout.html" %}
+{% block rootrellink %}
+ <li><a href="{{ pathto('index') }}">{{ shorttitle }}</a>{{ reldelim1 }}</li>
+{% endblock %}
diff --git a/doc/source/tutorials/apt-cdrom.rst b/doc/source/tutorials/apt-cdrom.rst
new file mode 100644
index 0000000..7e1d794
--- /dev/null
+++ b/doc/source/tutorials/apt-cdrom.rst
@@ -0,0 +1,156 @@
+Writing your own apt-cdrom
+==========================
+:Author: Julian Andres Klode <jak@debian.org>
+:Release: |release|
+:Date: |today|
+
+This article explains how to utilise python-apt to build your own clone of the
+:command:`apt-cdrom` command. To do this, we will take a look at the
+:mod:`apt.cdrom` and :mod:`apt.progress.text` modules, and we will learn how
+to use apt_pkg.parse_commandline to parse commandline arguments. The code shown
+here works on Python 2 and Python 3.
+
+Basics
+------
+The first step in building your own :command:`apt-cdrom` clone is to import the
+:mod:`apt` package, which will import :mod:`apt.cdrom` and
+:mod:`apt.progress.text`::
+
+ import apt
+
+Now we have to create a new :class:`apt.cdrom.Cdrom` object and pass to it an
+:class:`apt.progress.text.CdromProgress` object, which is responsible for
+displaying the progress and asking questions::
+
+ cdrom = apt.Cdrom(apt.progress.text.CdromProgress())
+
+Now we have to choose the action, depending on the given options on the
+command line. For now, we simply use the value of ``sys.argv[1]``::
+
+ import sys
+ if sys.argv[1] == 'add':
+ cdrom.add()
+ elif sys.argv[1] == 'ident':
+ cdrom.ident()
+
+Now we have a basic :command:`apt-cdrom` clone which can add and identify
+CD-ROMs::
+
+ import sys
+
+ import apt
+
+ cdrom = apt.Cdrom(apt.progress.text.CdromProgress())
+ if sys.argv[1] == 'add':
+ cdrom.add()
+ elif sys.argv[1] == 'ident':
+ cdrom.ident()
+
+Advanced example with command-line parsing
+-------------------------------------------
+Our example clearly misses a way to parse the commandline in a correct
+manner. Luckily, :mod:`apt_pkg` provides us with a function to do this:
+:func:`apt_pkg.parse_commandline`. To use it, we add ``import apt_pkg`` right
+after import apt::
+
+ import sys
+
+ import apt_pkg
+ import apt
+
+
+:func:`apt_pkg.parse_commandline` is similar to :mod:`getopt` functions, it
+takes a list of recognized options and the arguments and returns all unknown
+arguments. If it encounters an unknown argument which starts with a leading
+'-', the function raises an error indicating that the option is unknown. The
+major difference is that this function manipulates the apt configuration space.
+
+The function takes 3 arguments. The first argument is an
+:class:`apt_pkg.Configuration` object. The second argument is a list of tuples
+of the form ``(shortopt, longopt, config, type)``, whereas *shortopt* is a
+character indicating the short option name, *longopt* a string indicating the
+corresponding long option (e.g. ``"--help"``), *config* the name of the
+configuration item which should be set and *type* the type of the argument.
+
+For apt-cdrom, we can use the following statement::
+
+ arguments = apt_pkg.parse_commandline(apt_pkg.config,
+ [('h', "help", "help"),
+ ('v', "version", "version"),
+ ('d', "cdrom", "Acquire::cdrom::mount", "HasArg"),
+ ('r', "rename", "APT::CDROM::Rename"),
+ ('m', "no-mount", "APT::CDROM::NoMount"),
+ ('f', "fast", "APT::CDROM::Fast"),
+ ('n', "just-print", "APT::CDROM::NoAct"),
+ ('n', "recon", "APT::CDROM::NoAct"),
+ ('n', "no-act", "APT::CDROM::NoAct"),
+ ('a', "thorough", "APT::CDROM::Thorough"),
+ ('c', "config-file", "", "ConfigFile"),
+ ('o', "option", "", "ArbItem")], args)
+
+
+This allows us to support all options supported by apt-cdrom. The first option
+is --help. As you can see, it omits the fourth field of the tuple; which means
+it is a boolean argument. Afterwards you could use
+``apt_pkg.config.find_b("help")`` to see whether ``--help`` was specified. In
+``('d',"cdrom","Acquire::cdrom::mount","HasArg")`` the fourth field is
+``"HasArg"``. This means that the option has an argument, in this case the
+location of the mount point. ``('c',"config-file","","ConfigFile")`` shows how
+to include configuration files. This option takes a parameter which points to
+a configuration file which will be added to the configuration space.
+``('o',"option","","ArbItem")`` is yet another type of option, which allows users
+to set configuration options on the commandline.
+
+Now we have to check whether help or version is specified, and print a message
+and exit afterwards. To do this, we use :meth:`apt_pkg.Configuration.find_b`
+which returns ``True`` if the configuration option exists and evaluates to
+``True``::
+
+ if apt_pkg.config.find_b("help"):
+ print("This should be a help message")
+ sys.exit(0)
+ elif apt_pkg.config.find_b("version"):
+ print("Version blah.")
+ sys.exit(0)
+
+
+Now we are ready to create our progress object and our cdrom object. Instead
+of using :class:`apt.Cdrom` like in the first example, we will use
+:class:`apt_pkg.Cdrom` which provides a very similar interface. We could also
+use :class:`apt.Cdrom`, but `apt.Cdrom` provides options like *nomount* which
+conflict with our commandline parsing::
+
+ progress = apt.progress.text.CdromProgress()
+ cdrom = apt_pkg.Cdrom()
+
+
+Now we have to do the action requested by the user on the commandline. To see
+which option was requested, we check the list ``arguments`` which was returned
+by ``apt_pkg.parse_commandline`` above, and afterwards call ``cdrom.add`` or
+``cdrom.ident``::
+
+ if apt_pkg.config.find_b("help"):
+ print("This should be a help message")
+ sys.exit(0)
+ elif apt_pkg.config.find_b("version"):
+ print("Version blah.")
+ sys.exit(0)
+
+ if not arguments:
+ sys.stderr.write('E: No operation specified\n')
+ sys.exit(1)
+ elif arguments[0] == 'add':
+ cdrom.add(progress)
+ elif arguments[0] == 'ident':
+ cdrom.ident(progress)
+ else:
+ sys.stderr.write('E: Invalid operation %s\n' % arguments[0])
+ sys.exit(1)
+
+
+After putting all our actions into a main() function, we get a completely
+working apt-cdrom clone, which just misses useful ``--help`` and ``--version``
+options. If we add a function show_help(), we get an even more complete
+apt-cdrom clone:
+
+.. literalinclude:: ../examples/apt-cdrom.py
diff --git a/doc/source/tutorials/apt-get.rst b/doc/source/tutorials/apt-get.rst
new file mode 100644
index 0000000..26ebc3d
--- /dev/null
+++ b/doc/source/tutorials/apt-get.rst
@@ -0,0 +1,46 @@
+Doing stuff :command:`apt-get` does
+===================================
+:Author: Julian Andres Klode <jak@debian.org>
+:Release: |release|
+:Date: |today|
+
+The following article will show how you can use python-apt to do actions done
+by the :command:`apt-get` command.
+
+
+Printing the URIs of all index files
+------------------------------------
+We all now that we can print the URIs of all our index files by running a
+simple ``apt-get --print-uris update``. We can do the same. Responsible for
+the source entries is the class :class:`apt_pkg.SourceList`, which can be
+combined with an :class:`apt_pkg.Acquire` object using :meth:`get_indexes`.
+
+First of all, we have to create the objects::
+
+ acquire = apt_pkg.Acquire()
+ slist = apt_pkg.SourceList()
+
+Now we have to parse /etc/apt/sources.list and its friends, by using
+:meth:`apt_pkg.SourceList.read_main_list`::
+
+ slist.read_main_list()
+
+The **slist** object now knows about the location of the indexes. We now have
+to load those indexes into the *acquire* object by calling
+:meth:`apt_pkg.SourceList.get_indexes`::
+
+ slist.get_indexes(acquire, True)
+
+The first argument is the acquire object into which we will load these indexes,
+and the second argument means that we want to fetch all indexes. Now the only
+thing left to do is iterating over the list of items and printing out their
+URIs. Luckily, there is :attr:`apt_pkg.Acquire.items` which allows us to
+iterate over the items::
+
+ for item in acquire.items:
+ print(item.desc_uri)
+
+In the end a program could look like this:
+
+.. literalinclude:: ../examples/update-print-uris.py
+
diff --git a/doc/source/tutorials/contributing.rst b/doc/source/tutorials/contributing.rst
new file mode 100644
index 0000000..33f1654
--- /dev/null
+++ b/doc/source/tutorials/contributing.rst
@@ -0,0 +1,315 @@
+Contributing to python-apt
+==========================
+:Author: Julian Andres Klode <jak@debian.org>
+:Release: |release|
+:Date: |today|
+
+Let's say you need a new feature, you can develop it, and you want to get it
+included in python-apt. Then be sure to follow the following guidelines.
+
+Available branches
+-------------------
+First of all, let's talk a bit about the git branches of python-apt. In the
+following parts, we will assume that you use git to create your changes and
+submit them.
+
+Repositories
+^^^^^^^^^^^^
+
+https://salsa.debian.org/apt-team/python-apt.git
+
+ This is the official Debian repository of python-apt.
+ You can clone it using git by doing::
+
+ git clone git://salsa.debian.org/apt-team/python-apt.git
+
+
+ All code which will be uploaded to Debian is here.
+ There are also branches for Ubuntu releases, but those may not be up-to-date.
+
+ Branch names consist of the distribution vendor, followed by a slash,
+ followed by the release of that distribution, for example: ``debian/sid``.
+
+ The current working branch is usually pointed to by ``HEAD``, it is
+ either ``debian/sid`` or ``debian/experimental``.
+
+ If both sid and experimental are active, bug fixes are either cherry-picked from
+ ``debian/experimental`` to ``debian/sid``, or a new release is cut on the sid branch
+ and then merged into experimental.
+
+ Updates to stable release branches, such as ``debian/wheezy``, are almost always
+ cherry-picked or backported from the ``debian/sid`` branch.
+
+
+.. highlight:: cpp
+
+C++ Coding style
+----------------
+This document gives coding conventions for the C++ code comprising
+the C++ extensions of Python APT. Please see the companion
+informational PEP describing style guidelines for Python code (:PEP:`8`).
+
+Note, rules are there to be broken. Two good reasons to break a
+particular rule:
+
+ (1) When applying the rule would make the code less readable, even
+ for someone who is used to reading code that follows the rules.
+
+ (2) To be consistent with surrounding code that also breaks it
+ (maybe for historic reasons) -- although this is also an
+ opportunity to clean up someone else's mess (in true XP style).
+
+This part of the document is derived from :PEP:`7` which was written by
+Guido van Rossum.
+
+
+C++ dialect
+^^^^^^^^^^^
+
+- Use ISO standard C++ (the 2011 version of the standard), headers
+ should also adhere to the 1998 version of the standard.
+
+- Use C++ style // one-line comments for single-line comments.
+
+- No compiler warnings with ``gcc -std=c++11 -Wall -Wno-write-strings``. There
+ should also be no errors with ``-pedantic`` added.
+
+
+Code lay-out
+^^^^^^^^^^^^
+
+- Use 3-space indents, in files that already use them. In new source files,
+ that were created after this rule was introduced, use 4-space indents.
+
+ At some point, the whole codebase may be converted to use only
+ 4-space indents.
+
+- No line should be longer than 79 characters. If this and the
+ previous rule together don't give you enough room to code, your
+ code is too complicated -- consider using subroutines.
+
+- No line should end in whitespace. If you think you need
+ significant trailing whitespace, think again -- somebody's
+ editor might delete it as a matter of routine.
+
+- Function definition style: function name in column 2, outermost
+ curly braces in column 1, blank line after local variable
+ declarations::
+
+ static int extra_ivars(PyTypeObject *type, PyTypeObject *base)
+ {
+ int t_size = PyType_BASICSIZE(type);
+ int b_size = PyType_BASICSIZE(base);
+
+ assert(t_size >= b_size); /* type smaller than base! */
+ ...
+ return 1;
+ }
+
+- Code structure: one space between keywords like 'if', 'for' and
+ the following left paren; no spaces inside the paren; braces as
+ shown::
+
+ if (mro != NULL) {
+ ...
+ }
+ else {
+ ...
+ }
+
+- The return statement should *not* get redundant parentheses::
+
+ return Py_None; /* correct */
+ return(Py_None); /* incorrect */
+
+- Function and macro call style: ``foo(a, b, c)`` -- no space before
+ the open paren, no spaces inside the parens, no spaces before
+ commas, one space after each comma.
+
+- Always put spaces around assignment, Boolean and comparison
+ operators. In expressions using a lot of operators, add spaces
+ around the outermost (lowest-priority) operators.
+
+- Breaking long lines: if you can, break after commas in the
+ outermost argument list. Always indent continuation lines
+ appropriately, e.g.::
+
+ PyErr_Format(PyExc_TypeError,
+ "cannot create '%.100s' instances",
+ type->tp_name);
+
+- When you break a long expression at a binary operator, the
+ operator goes at the end of the previous line, e.g.::
+
+ if (type->tp_dictoffset != 0 && base->tp_dictoffset == 0 &&
+ type->tp_dictoffset == b_size &&
+ (size_t)t_size == b_size + sizeof(PyObject *))
+ return 0; /* "Forgive" adding a __dict__ only */
+
+- Put blank lines around functions, structure definitions, and
+ major sections inside functions.
+
+- Comments go before the code they describe.
+
+- All functions and global variables should be declared static
+ unless they are to be part of a published interface
+
+
+Naming conventions
+^^^^^^^^^^^^^^^^^^
+
+- Use a ``Py`` prefix for public functions; never for static
+ functions. The ``Py_`` prefix is reserved for global service
+ routines like ``Py_FatalError``; specific groups of routines
+ (e.g. specific object type APIs) use a longer prefix,
+ e.g. ``PyString_`` for string functions.
+
+- Public functions and variables use MixedCase with underscores,
+ like this: ``PyObject_GetAttr``, ``Py_BuildValue``, ``PyExc_TypeError``.
+
+- Internal functions and variables use lowercase with underscores, like
+ this: ``hashes_get_sha1.``
+
+- Occasionally an "internal" function has to be visible to the
+ loader; we use the _Py prefix for this, e.g.: ``_PyObject_Dump``.
+
+- Macros should have a MixedCase prefix and then use upper case,
+ for example: ``PyString_AS_STRING``, ``Py_PRINT_RAW``.
+
+
+Documentation Strings
+^^^^^^^^^^^^^^^^^^^^^
+- The first line of each function docstring should be a "signature
+ line" that gives a brief synopsis of the arguments and return
+ value. For example::
+
+ PyDoc_STRVAR(myfunction__doc__,
+ "myfunction(name: str, value) -> bool\n\n"
+ "Determine whether name and value make a valid pair.");
+
+ The signature line should be formatted using the format for function
+ annotations described in :PEP:`3107`, whereas the annotations shall reflect
+ the name of the type (e.g. ``str``). The leading ``def`` and the trailing
+ ``:`` as used for function definitions must not be included.
+
+ Always include a blank line between the signature line and the
+ text of the description.
+
+ If the return value for the function is always ``None`` (because
+ there is no meaningful return value), do not include the
+ indication of the return type.
+
+- When writing multi-line docstrings, be sure to always use
+ string literal concatenation::
+
+ PyDoc_STRVAR(myfunction__doc__,
+ "myfunction(name, value) -> bool\n\n"
+ "Determine whether name and value make a valid pair.");
+
+
+Python Coding Style
+-------------------
+The coding style for all code written in python is :PEP:`8`. Exceptions from
+this rule are the documentation, where code is sometimes formatted differently
+to explain aspects.
+
+When writing code, use tools like pylint, pyflakes, pychecker and pycodestyle
+(all available from Debian/Ubuntu) to verify that your code is
+OK. Fix all the problems which seem reasonable, and mention the unfixed issues
+when asking for merge.
+
+All code must work on both Python 2 and Python 3.
+
+Submitting your patch
+---------------------
+First of all, the patch you create should be based against the most current
+branch of python-apt (debian/sid or debian/experimental). If it is a bugfix,
+you should probably use debian/sid. If you choose the wrong branch, we will
+ask you to rebase your patches against the correct one.
+
+Once you have made your change, check that it:
+
+ * conforms to :PEP:`8` (checked with pycodestyle). It should, at least not
+ introduce new errors. (and never have whitespace at end of line)
+ * produces no new errors in pychecker, pyflakes and pylint (unless you
+ can't fix them, but please tell so when requesting the merge, so it can
+ be fixed before hitting one of the main branches).
+ * does not change the behaviour of existing code in a non-compatible way.
+ * works on both Python 2 and Python 3.
+
+If your change follows all points of the checklist, you can commit it to your
+repository. (You could commit it first, and check later, and then commit the
+fixes, but commits should be logical and it makes no sense to have to commits
+for one logical unit).
+
+The changelog message should follow standard git format. At the end of the
+message, tags understood by gbp-dch and other tags may be added. An example
+commit message could be:
+
+.. code-block:: none
+
+ apt.package: Fix blah blah
+
+ Fix a small bug where foo is doing bar, but should be doing baz
+ instead.
+
+ Closes: #bugnumber
+ LP: #ubuntu-bug-number
+ Reported-By: Bug Reporter Name <email@example.com>
+
+
+Once you have made all your changes, you can run ``git format-patch``,
+specifying the upstream commit or branch you want to create patches
+against. Then you can either:
+
+* report a bug against the python-apt package, attach the patches
+ you created in the previous step, and tag it with 'patch'. It might also be
+ a good idea to prefix the bug report with '[PATCH]'.
+
+* send the patches via ``git send-email``.
+
+For larger patch series, you can also publish a git branch on a
+public repository and request it to be pulled.
+
+If you choose that approach, you may want to base your patches against
+the latest release, and not against some random commit, for the sake of
+preserving a sane git history.
+
+Be prepared to rebase such a branch, and close any bugs you fix in the
+branch by mentioning them in the commit message using a Closes or LP
+tag.
+
+
+Documentation updates
+---------------------
+If you want to update the documentation, please follow the procedure as written
+above. You can send your content in plain text, but reStructuredText is the
+preferred format. I (Julian Andres Klode) will review your patch and include
+it.
+
+.. highlight:: sh
+
+Example patch session
+----------------------
+In the following example, we edit a file, create a patch (an enhanced
+patch), and report a wishlist bug with this patch against the python-apt
+package::
+
+ user@ pc:~$ git clone git://anonscm.debian.org/apt/python-apt.git
+ user@pc:~$ cd python-apt
+ user@pc:~/python-apt$ editor FILES
+ user@pc:~/python-apt$ pycodestyle FILES # Check with pycodestyle
+ user@pc:~/python-apt$ pylint -e FILES # Check with pylint
+ user@pc:~/python-apt$ pyflakes FILES # Check with pyflakes
+ user@pc:~/python-apt$ pychecker FILES # Check with pychecker
+ user@pc:~/python-apt$ git commit -p
+ user@pc:~/python-apt$ git format-patch origin/HEAD
+ user@pc:~/python-apt$ reportbug --severity=wishlist --tag=patch --attach=<patch> ... python-apt
+
+You may also send the patches to the mailing list instead of
+reporting the bug::
+
+ user@pc:~/python-apt$ git send-email --to=deity@lists.debian.org <patches created by format-patch>
+
+You can even push your changes to your own repository and request
+a pull request.
diff --git a/doc/source/tutorials/index.rst b/doc/source/tutorials/index.rst
new file mode 100644
index 0000000..06d31c6
--- /dev/null
+++ b/doc/source/tutorials/index.rst
@@ -0,0 +1,8 @@
+Tutorials
+=========
+
+.. toctree::
+ :maxdepth: 1
+ :glob:
+
+ *
diff --git a/doc/source/whatsnew/0.7.100.rst b/doc/source/whatsnew/0.7.100.rst
new file mode 100644
index 0000000..eda2764
--- /dev/null
+++ b/doc/source/whatsnew/0.7.100.rst
@@ -0,0 +1,211 @@
+What's New In python-apt 0.7.100
+================================
+Python-apt 0.7.100 is a new major release of the python bindings for the APT
+package management libraries. It provides support for Python 3, new language
+features and an API conforming to :PEP:`8`.
+
+Despite the many changes made in python-apt 0.7.100, the release still provides
+backwards compatibility to the 0.7 series. This makes it possible to run your
+old applications.
+
+This documents describes the important changes introduced since the release
+of python-apt 0.7.10.3, starting with the first development release 0.7.90
+from April 2009.
+
+.. note::
+
+ Applications using the old API should be updated to the new API because
+ the old ones will be dropped in a future release. To build a python-apt
+ variant without the deprecated API, build it without the -DCOMPAT_0_7
+ compiler flag.
+
+Support for Python 3
+--------------------
+Python-apt is the first Debian package to support the third major release of
+Python. The port is straight forward and integrates as nicely in Python 3 as
+the Python 2 builds integrate in Python 2.
+
+Please be aware that python-apt builds for Python 3 are built without the
+compatibility options enabled for Python 2 builds. They also do not provide
+methods like :meth:`has_key` on mapping objects, because it has been removed
+in Python 3.
+
+Python 3 support may be disabled by distributions.
+
+Real classes in :mod:`apt_pkg`
+------------------------------
+The 0.7.100 release introduces real classes in the :mod:`apt_pkg` extension. This
+is an important step forward and makes writing code much easier, because you
+can see the classes without having to create an object first. It also makes
+it easier to talk about those classes, because they have a real name now.
+
+The 0.7 series shipped many functions for creating new objects, because the
+classes were not exported. In 0.7.100, the classes themselves replace those
+functions, as you can see in the following table.
+
+.. table::
+
+ ===================================== =================================
+ Function Replacing class
+ ===================================== =================================
+ :func:`apt_pkg.GetAcquire` :class:`apt_pkg.Acquire`
+ :func:`apt_pkg.GetCache()` :class:`apt_pkg.Cache`
+ :func:`apt_pkg.GetCdrom()` :class:`apt_pkg.Cdrom`
+ :func:`apt_pkg.GetDepCache()` :class:`apt_pkg.DepCache`
+ :func:`apt_pkg.GetPackageManager` :class:`apt_pkg.PackageManager`
+ :func:`apt_pkg.GetPkgAcqFile` :class:`apt_pkg.AcquireFile`
+ :func:`apt_pkg.GetPkgActionGroup` :class:`apt_pkg.ActionGroup`
+ :func:`apt_pkg.GetPkgProblemResolver` :class:`apt_pkg.ProblemResolver`
+ :func:`apt_pkg.GetPkgRecords` :class:`apt_pkg.PackageRecords`
+ :func:`apt_pkg.GetPkgSourceList` :class:`apt_pkg.SourceList`
+ :func:`apt_pkg.GetPkgSrcRecords` :class:`apt_pkg.SourceRecords`
+ :func:`apt_pkg.ParseSection` :class:`apt_pkg.TagSection`
+ :func:`apt_pkg.ParseTagFile` :class:`apt_pkg.TagFile`
+ ===================================== =================================
+
+Complete rename of functions, methods and attributes
+-----------------------------------------------------
+In May 2008, Ben Finney reported bug 481061 against the python-apt package,
+asking for PEP8 conformant names. With the release of python-apt 0.7.100, this
+is finally happening.
+
+Context managers for the :keyword:`with` statement
+--------------------------------------------------
+This is not a real big change, but it's good to have it:
+:class:`apt_pkg.ActionGroup` can now be used as a context manager for the
+:keyword:`with` statement. This makes it more obvious that you are using an
+action group, and is just cooler::
+
+ with apt_pkg.ActionGroup(depcache):
+ for package in my_selected_packages:
+ depcache.mark_install(package)
+
+This also works for :class:`apt.Cache`::
+
+ with cache.actiongroup(): # cache is an Instance of apt.Cache
+ for package in my_selected_packages:
+ package.mark_install() # Instance of apt.Package
+
+Yet another context manager is available for locking the package system::
+
+ with apt_pkg.SystemLock():
+ # do your stuff here
+ pass
+
+There is also one for file based locking::
+
+ with apt_pkg.FileLock(filename):
+ # do your stuff here
+ pass
+
+
+Unification of dependency handling
+----------------------------------
+In apt 0.7.XX, there were three different return types of functions parsing
+dependencies.
+
+First of all, there were :func:`apt_pkg.ParseDepends()` and
+:func:`apt_pkg.ParseSrcDepends()` which returned a list of or groups (which
+are lists themselves) which contain tuples in the format ``(package,ver,op)``,
+whereas op is one of "<=",">=","<<",">>","=","!=".
+
+Secondly, there was Package.DependsListStr which returned a dictionary mapping
+the type of the dependency (e.g. 'Depends', 'Recommends') to a list similar to
+those of :func:`apt_pkg.ParseDepends()`. The only difference was that the
+values ">>", "<<" of op are ">", "<" instead.
+
+Thirdly, there was SourceRecords.BuildDepends, which returned a simple list
+of tuples in the format ``(package, version, op, type)``, whereas ``op`` was
+the integer representation of those ">>", "<<" actions and ``type`` an integer
+representing the type of the dependency (e.g. 'Build-Depends'). The whole
+format was almost useless from the Python perspective because the string
+representations or constants for checking the values were not exported.
+
+python-apt 0.7.100 puts an end to this confusion and uses one basic format, which
+is the format known from Package.DependsListStr. The format change only applies
+to the new functions and attributes, i.e. :attr:`SourceRecords.build_depends`
+will now return a dict, whereas :attr:`SourceRecords.BuildDepends` will still
+return the classic format. The functions :func:`apt_pkg.parse_depends` and
+:func:`apt_pkg.parse_src_depends` now use the same values for ``op`` as
+:attr:`Package.DependsListStr` does.
+
+Example::
+
+ >>> s = apt_pkg.SourceRecords()
+ >>> s.lookup("apt")
+ 1
+ >>> s.build_depends
+ {'Build-Depends': [[('debhelper', '5.0', '>=')],
+ [('libdb-dev', '', '')],
+ [('gettext', '0.12', '>=')],
+ [('libcurl4-gnutls-dev', '', ''),
+ ('libcurl3-gnutls-dev', '7.15.5', '>=')],
+ [('debiandoc-sgml', '', '')],
+ [('docbook-utils', '0.6.12', '>=')],
+ [('xsltproc', '', '')],
+ [('docbook-xsl', '', '')],
+ [('xmlto', '', '')]]}
+ >>> s.BuildDepends
+ [('debhelper', '5.0', 2, 0),
+ ('libdb-dev', '', 0, 0),
+ ('gettext', '0.12', 2, 0),
+ ('libcurl4-gnutls-dev', '', 16, 0),
+ ('libcurl3-gnutls-dev', '7.15.5', 2, 0),
+ ('debiandoc-sgml', '', 0, 0),
+ ('docbook-utils', '0.6.12', 2, 0),
+ ('xsltproc', '', 0, 0),
+ ('docbook-xsl', '', 0, 0),
+ ('xmlto', '', 0, 0)]
+
+C++ headers
+------------
+The 0.7.100 release introduces python-apt-dev which provides headers for
+developers to provide Python support in the libapt-pkg-using application.
+
+Redesign of :mod:`apt_inst`
+---------------------------
+The 0.7.100 series redesigns the :mod:`apt_inst` module to provide
+more flexible classes replacing the older functions. The older functions
+are still available in Python 2 builds, but are deprecated and will be
+removed in the future.
+
+Other changes
+-------------
+This release of python-apt also features several other, smaller changes:
+
+ * Reduced memory usage by making :class:`apt.Cache` create
+ :class:`apt.Package()` object dynamically, instead of creating all of
+ them during the cache initialization.
+ * Support to set the candidate version in :class:`apt.package.Package`
+ * Support for reading gzip-compressed files in apt_pkg.TagFile.
+ * Various changes to :mod:`apt.debfile` have been merged from gdebi.
+
+There have been various other changes, see the changelog for a complete list
+of changes.
+
+
+Porting your applications to the new python-apt API
+----------------------------------------------------
+Porting your application to the new python-apt API may be trivial. You
+should download the source tarball of python-apt and run the tool
+utils/migrate-0.8 over your code::
+
+ utils/migrate-0.8.py -c myapp.py mypackage/
+
+This will search your code for places where possibly deprecated names are
+used. Using the argument ``-c``, you can turn colorized output on.
+
+Now that you know which parts of your code have to be changed, you have to know
+how to do this. For classes, please look at the table. For all attributes,
+methods, functions, and their parameters the following rules apply:
+
+ 1. Replace leading [A-Z] with [a-z] (e.g DescURI => descURI)
+ 2. Replace multiple [A-Z] with [A-Z][a-z] (e.g. descURI => descUri)
+ 3. Replace every [A-Z] with the corresponding [a-z] (descUri => desc_uri)
+
+As an exception, refixes such as 'de' (e.g. 'dequote') or 'un' (e.g. 'unlock')
+are normally not separated by underscores from the next word. There are also
+some other exceptions which are listed here, and apply to any name containing
+this word: **filename**, **filesize**, **destdir**, **destfile**, **dequote**,
+**unlock**, **reinstall**, **pinfile**, **REINSTREQ**, **UNPACKED**,
+**parse_commandline**.
diff --git a/doc/source/whatsnew/0.8.0.rst b/doc/source/whatsnew/0.8.0.rst
new file mode 100644
index 0000000..2eeb135
--- /dev/null
+++ b/doc/source/whatsnew/0.8.0.rst
@@ -0,0 +1,38 @@
+What's New In python-apt 0.8
+============================
+Python-apt 0.8 is a new major release of the python bindings for the APT
+package management libraries.
+
+
+Removal of old API
+------------------
+The old API that was deprecated in 0.7.100 is no longer available. Applications
+that have not yet updated to the new API should do so.
+
+Multi-arch support
+------------------
+This version of python-apt introduces multi-arch support:
+
+ * A new class, :class:`apt_pkg.Group` has been added.
+ * :class:`apt_pkg.Cache` can now be indexed by ``(name, architecture)``
+ tuples
+
+Features for mancoosi
+----------------------
+Several new features related to ordering have been added on request
+of the mancoosi project:
+
+ * A new class :class:`apt_pkg.OrderList` has been added
+ * The :class:`apt_pkg.PackageManager` class now provides new methods
+ for registering install/remove/configure actions which can be
+ subclassed to check ordering.
+
+Other changes
+-------------
+This release of python-apt also features several other, smaller changes:
+
+ * apt_pkg.Cache() now takes None for the progress parameter, preventing
+ progress reporting.
+
+There have been various other changes, see the changelog for a complete list
+of changes.
diff --git a/doc/source/whatsnew/0.9.4.rst b/doc/source/whatsnew/0.9.4.rst
new file mode 100644
index 0000000..617ef08
--- /dev/null
+++ b/doc/source/whatsnew/0.9.4.rst
@@ -0,0 +1,17 @@
+What's New In python-apt 0.9.4
+==============================
+Python-apt 0.9.4 is a maintenance update.
+
+New features
+------------
+
+ * Support for apt_pkg.sha512sum()
+ * Support for apt_pkg.maybe_open_clear_signed_file()
+ * Use apt_pkg.open_maybe_clear_signed_file() when opening a .dsc file
+ * add MULTI_ARCH_NO constant (MULTI_ARCH_NONE is deprecated)
+
+Maintenance
+-----------
+
+ * Add Ubuntu Wily
+ * Update examples
diff --git a/doc/source/whatsnew/1.0.rst b/doc/source/whatsnew/1.0.rst
new file mode 100644
index 0000000..b3364ad
--- /dev/null
+++ b/doc/source/whatsnew/1.0.rst
@@ -0,0 +1,75 @@
+What's New In python-apt 1.0
+==============================
+Python-Apt 1.0 fixes several issues and use of deprecated methods. Most
+importantly, it introduces large file support
+
+New features
+------------
+* :class:`apt_pkg.AcquireFile` can now take a hash string that is not an
+ md5 value, using the new `hash` argument.
+* A new a :meth:`apt_pkg.TagFile.close` method was added
+* :class:`apt_pkg.TagFile` is now a context manager
+
+* The high-level cache class, :class:`apt.cache.Cache` and it's companion
+ :class:`apt.cache.FilteredCache` now support package
+ names with special architecture qualifiers such as :all and :native.
+
+* The method :meth:`apt.cache.Cache.connect2` allows connecting callbacks on
+ cache changes that take the cache as their first argument, reducing the
+ potential for reference cycles.
+
+* The property :attr:`apt.package.Version.is_installed` was added.
+* The properties :attr:`apt.package.BaseDependency.installed_target_versions`
+ and :attr:`apt.package.Dependency.installed_target_versions` were added.
+
+* The property :class:`apt.Dependency.rawtype` was added to give the raw type
+ of a dependency, such as 'Depends'.
+
+* The attribute :attr:`apt_pkg.Dependency.comp_type_deb` and the property
+ :attr:`apt.Dependency.relation_deb` were added, they return a Debian-style
+ comparison operator instead of a mathematical-style one.
+
+* A new filter for filtered caches is provided, :class:`apt.cache.InstalledFilter`.
+
+Backward-incompatible changes
+-----------------------------
+* :class:`apt.Version` now compares package names in addition to version only
+ when checking for equality. This was broken previously.
+
+Deprecated
+----------
+The following features are deprecated, starting with this release:
+
+* The `section` member of :class:`apt_pkg.Package`
+* The `files` member of of :class:`apt_pkg.SourceRecords`
+* The `md5` argument to :class:`apt_pkg.AcquireFile`, it is replaced by
+ the `hash` argument.
+* The method :meth:`apt.cache.Cache.connect` has been deprecated. It is
+ replaced by :meth:`apt.cache.Cache.connect2` which is more flexible and
+ less prone to reference cycles.
+* The attribute :attr:`apt_pkg.AcquireItem.mode` has been replaced by
+ :attr:`apt_pkg.AcquireItem.active_subprocess`
+* The class :class:`apt_pkg.IndexRecords` has been deprecated and will
+ be removed in the next release.
+
+Removed
+-------
+* The module :mod:`apt.progress.gtk2` has been removed. There were no
+ users in the Debian archive, its last update was in 2013, and it was buggy
+ already. Apart from that, it suggested that it is OK to run a graphical
+ application as root, and used the unmaintained GTK+ 2 version.
+
+ Therefore, there is no replacement, please use PackageKit or aptdaemon
+ for installation in graphical environments.
+* The attribute :attr:`apt_pkg.Package.auto` was not set anymore, and thus
+ removed.
+
+Maintenance
+-----------
+* The classes :class:`apt.cache.Cache` and :class:`apt.cache.FilteredCache` no
+ longer store cyclic references to/between them. This fixes a huge issue,
+ because a cache can have tens of open file descriptors, causing the maximum
+ of file descriptors to be reached easily.
+
+* :mod:`apt_inst` now supports ar and tar archives that are larger than 4 GiB
+* Various smaller bug fixes
diff --git a/doc/source/whatsnew/1.1.rst b/doc/source/whatsnew/1.1.rst
new file mode 100644
index 0000000..5a4f5c3
--- /dev/null
+++ b/doc/source/whatsnew/1.1.rst
@@ -0,0 +1,28 @@
+What's New In python-apt 1.1
+==============================
+This release is built against APT 1.1
+
+Highlights
+----------
+* Code that previously raised :class:`SystemError` now raises
+ :class:`apt_pkg.Error`.
+
+Removed
+-------
+* The class :class:`apt_pkg.IndexRecords` has been removed, as it was removed
+ in APT 1.1
+* :attr:`apt_pkg.Dependency.smart_target_pkg` has been removed.
+
+Added
+------
+* The class :class:`apt_pkg.HashStringList` has been added.
+* The class :class:`apt_pkg.Error` and an alias :class:`apt_inst.Error` has
+ been added.
+
+
+Deprecated
+----------
+* :attr:`apt_pkg.PackageRecords.md5_hash`,
+ :attr:`apt_pkg.PackageRecords.sha1_hash`, and
+ :attr:`apt_pkg.PackageRecords.sha256_hash`
+ are replaced by :attr:`apt_pkg.PackageRecords.hashes`.
diff --git a/doc/source/whatsnew/1.4.rst b/doc/source/whatsnew/1.4.rst
new file mode 100644
index 0000000..fa3f95d
--- /dev/null
+++ b/doc/source/whatsnew/1.4.rst
@@ -0,0 +1,16 @@
+What's New In python-apt 1.4
+============================
+This release is built against APT 1.4, see :doc:`1.1` for the other changes
+since 1.0, the last series with a feature-complete release. There are no 1.2
+or 1.3 series.
+
+Added
+------
+* The methods :meth:`apt_pkg.parse_depends` and :meth:`apt_pkg.parse_src_depends`
+ gained a new parameter *architecture* to change the architecture the dependency lines
+ are interpreted for, matching the change in apt 1.4~beta3.
+
+ This only really makes sense for the latter option right now, as it only
+ affects the parsing of architecture lists.
+
+ By default, the host architecture is used.
diff --git a/doc/source/whatsnew/1.6.rst b/doc/source/whatsnew/1.6.rst
new file mode 100644
index 0000000..2015bee
--- /dev/null
+++ b/doc/source/whatsnew/1.6.rst
@@ -0,0 +1,26 @@
+What's New In python-apt 1.6
+============================
+
+Changed
+-------
+* Methods of :class:`apt_pkg.DepCache` now raise an exception if passed
+ objects belonging to a different cache, in order to avoid segmentation
+ faults or wrong behavior.
+
+ .. versionchanged:: 1.6.1
+
+ Starting with 1.6.1 and 1.7~alpha1, the exception raised is
+ :class:`apt_pkg.CacheMismatchError`, and :class:`apt.cache.Cache` will
+ automatically remap open packages and versions to a new cache.
+
+* Initial type hints
+
+* :attr:`apt_pkg.SourceRecords.files` now returns a
+ :class:`apt_pkg.SourceRecordsFile` object with getters instead of
+ a tuple (but it also emulates the tuple).
+
+Bugfixes
+--------
+* Various other fixes for segmentation faults
+* apt/auth.py: Protect against race with gpg when removing tmpdir
+ (Closes: #871585)
diff --git a/doc/source/whatsnew/1.7.rst b/doc/source/whatsnew/1.7.rst
new file mode 100644
index 0000000..38485f7
--- /dev/null
+++ b/doc/source/whatsnew/1.7.rst
@@ -0,0 +1,42 @@
+What's New In python-apt 1.7
+============================
+
+Changed
+--------
+* Starting with 1.6.1 and 1.7~alpha1, the exception raised when
+ passing objects of a different cache to :class:`apt_pkg.DepCache`
+ is :class:`apt_pkg.CacheMismatchError`, and :class:`apt.cache.Cache` will
+ automatically remap open packages and versions to a new cache.
+
+* :meth:`apt_pkg.Policy.get_priority()` now accepts :class:`apt_pkg.Version`
+ objects in addition to :class:`apt_pkg.Package` and :class:`apt_pkg.PackageFile`
+ ones.
+
+* :attr:`apt.package.Version.policy_priority` now returns the priority
+ for that version rather than the highest priority for one of its
+ package files.
+
+* :meth:`apt.Cache.commit` and :meth:`apt_pkg.DepCache.commit` now use
+ frontend locking to run dpkg.
+
+Added
+------
+* The class :class:`apt_pkg.PackageRecords` can now lookup custom fields
+ using ``records[key]`` and ``key in records``.
+
+
+* All code is now statically typed. Some methods from :mod:`apt_pkg`
+ and :mod:`apt_inst` might still be missing or more strict than
+ necessary.
+
+* A new method :meth:`apt.cache.Cache.fix_broken` has been added.
+
+* New methods for frontend locking have been added:
+ :meth:`apt_pkg.pkgsystem_lock_inner`,
+ :meth:`apt_pkg.pkgsystem_unlock_inner`,
+ :meth:`apt_pkg.pkgsystem_is_locked` (starting in alpha 3).
+
+Deprecated
+----------
+* :meth:`apt_pkg.Policy.get_priority()` accepting :class:`apt_pkg.Package`
+ is deprecated.
diff --git a/doc/source/whatsnew/1.8.rst b/doc/source/whatsnew/1.8.rst
new file mode 100644
index 0000000..0f9704f
--- /dev/null
+++ b/doc/source/whatsnew/1.8.rst
@@ -0,0 +1,8 @@
+What's New In python-apt 1.8
+============================
+
+
+Added
+------
+* A new method :meth:`apt_pkg.Policy.init_defaults` has been added
+ in 1.8.2.
diff --git a/doc/source/whatsnew/2.0.rst b/doc/source/whatsnew/2.0.rst
new file mode 100644
index 0000000..ed2b063
--- /dev/null
+++ b/doc/source/whatsnew/2.0.rst
@@ -0,0 +1,37 @@
+What's New In python-apt 2.0
+============================
+Changes since 1.8.
+
+Added
+-----
+* The method :meth:`apt_pkg.TagSection.write()` has been added
+* The attribute :attr:`apt_pkg.HashString.hashvalue` has been added
+* The constructor :class:`apt_pkg.AcquireFile` now accepts an
+ :class:`apt_pkg.HashStringList` as the *hash* argument.
+
+* The classes :class:`apt_pkg.HashString` and :class:`apt_pkg.HashStringList`
+ gained a new ``usable`` property.
+
+Removed
+-------
+* The methods called `install_protect` have been removed
+* The `section` attribute has been removed from :class:`apt_pkg.Package`
+ and :class:`apt.package.Package`
+* The method :meth:`apt_pkg.rewrite_section` has been removed
+* The attributes :attr:`apt_pkg.Hashes.md5`, :attr:`apt_pkg.Hashes.sha1`, :attr:`apt_pkg.Hashes.sha256` have been removed
+* The method :meth:`apt_pkg.Policy.get_match` has been removed.
+* The constructor :class:`apt_pkg.AcquireFile` no longer takes an *md5* argument.
+
+Changed
+-------
+* In :class:`apt_pkg.SourceRecords`, the tuple view of files now always contains
+ None where it previously contained the md5 hash.
+* The method :meth:`apt_pkg.Policy.get_priority()` no longer accepts :class:`apt_pkg.Package` instances.
+* Instances of :class:`apt_pkg.HashString` can now be compared for equality
+* :class:`apt.progress.base.InstallProgress` is now a context manager, use it in
+ a ``with`` statement to avoid leaking file descriptors.
+
+Bug fixes
+---------
+
+* Fixed unterminated ``char*`` array in :class:`apt_pkg.TagRemove` constructor.
diff --git a/doc/source/whatsnew/2.1.rst b/doc/source/whatsnew/2.1.rst
new file mode 100644
index 0000000..ecbd995
--- /dev/null
+++ b/doc/source/whatsnew/2.1.rst
@@ -0,0 +1,7 @@
+What's New In python-apt 2.1
+============================
+2.1 is the development series for 2.2
+
+Removed
+-------
+* Support for Python 2 (2.1.0)
diff --git a/doc/source/whatsnew/index.rst b/doc/source/whatsnew/index.rst
new file mode 100644
index 0000000..cc270a1
--- /dev/null
+++ b/doc/source/whatsnew/index.rst
@@ -0,0 +1,9 @@
+What's new in python-apt
+========================
+
+.. toctree::
+ :maxdepth: 2
+ :glob:
+
+ *
+
diff --git a/mypy.ini b/mypy.ini
new file mode 100644
index 0000000..c9e9b53
--- /dev/null
+++ b/mypy.ini
@@ -0,0 +1,2 @@
+[mypy]
+mypy_path = $MYPY_CONFIG_FILE_DIR/typehinting
diff --git a/po/POTFILES.in b/po/POTFILES.in
new file mode 100644
index 0000000..eb91d52
--- /dev/null
+++ b/po/POTFILES.in
@@ -0,0 +1,8 @@
+[encoding: UTF-8]
+[type: gettext/rfc822deb] data/templates/Ubuntu.info.in
+[type: gettext/rfc822deb] data/templates/Debian.info.in
+aptsources/distro.py
+apt/package.py
+apt/debfile.py
+apt/progress/text.py
+apt/cache.py
diff --git a/po/ar.po b/po/ar.po
new file mode 100644
index 0000000..73c7654
--- /dev/null
+++ b/po/ar.po
@@ -0,0 +1,622 @@
+# Arabic translation for update-manager
+# Copyright (c) (c) 2006 Canonical Ltd, and Rosetta Contributors 2006
+# This file is distributed under the same license as the update-manager package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2006.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-16 04:14+0000\n"
+"Last-Translator: Saleh Odeh <kirk.lock@gmail.com>\n"
+"Language-Team: Arabic <ar@li.org>\n"
+"Language: ar\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n == 1 ? 0 : n == 2 ? 1 : 2\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+msgid "Canonical-supported free and open-source software"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+msgid "Community-maintained free and open-source software"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "ملاحظات الإصدار"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "تحديثات الإنترنت"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "مدعوم بشكل رسمي"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "حقوق نقل محدودة"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr ""
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+msgid "Debian 6.0 'Squeeze' "
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+msgid "Debian 5.0 'Lenny' "
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+msgid "Debian 4.0 'Etch'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+msgid "Debian 3.1 'Sarge'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "تحديثات الإنترنت"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr ""
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr ""
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr ""
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr ""
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "التّفاصيل"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr ""
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr ""
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+#, fuzzy
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr "الرجاء التأكد من إتصالك بالإنترنت"
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "تعذّر تثبيت '%s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "سيكون من الضروري إزالة رزم مهمة"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/be.po b/po/be.po
new file mode 100644
index 0000000..53470c3
--- /dev/null
+++ b/po/be.po
@@ -0,0 +1,638 @@
+# Belarusian translation for update-manager
+# Copyright (c) (c) 2006 Canonical Ltd, and Rosetta Contributors 2006
+# This file is distributed under the same license as the update-manager package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2006.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:42+0200\n"
+"PO-Revision-Date: 2012-06-20 18:42+0300\n"
+"Last-Translator: Viktar Siarheichyk <viсs@eq.by>\n"
+"Language-Team: Belarusian <be@li.org>\n"
+"Language: be\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 12.04 'Precise Pangolin'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "CD-ROM з Ubuntu 12.04 'Precise Pangolin'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 11.10 'Oneiric Ocelot'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "CD-ROM з Ubuntu 11.10 'Oneiric Ocelot'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 11.04 'Natty Narwhal'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "CD-ROM з Ubuntu 11.04 'Natty Narwhal'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 10.10 'Maverick Meerkat'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "CD-ROM з Ubuntu 10.10 'Maverick Meerkat'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr "Партнёры Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr "Праграмы, якія Canonical запакаваў для сваіх партнёраў"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr "Гэтая праграма не ўваходзіць у Ubuntu."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr "Незалежны"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr "Пададзены пабочнымі распрацоўнікамі праграмаў"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr "Праграма, прапанаваная пабочнымі распрацоўнікамі."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 10.04 'Lucid Lynx'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "CD-ROM з Ubuntu 10.04 'Lucid Lynx'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 9.10 'Karmic Koala'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "CD-ROM з Ubuntu 9.10 'Karmic Koala'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 9.04 'Jaunty Jackalope'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "CD-ROM з Ubuntu 9.04 'Jaunty Jackalope'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 8.10 'Intrepid Ibex'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "CD-ROM з Ubuntu 8.10 'Intrepid Ibex'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 8.04 'Hardy Heron'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "CD-ROM з Ubuntu 8.04 'Hardy Heron'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 7.10 'Gutsy Gibbon'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "CD-ROM з Ubuntu 7.10 'Gutsy Gibbon'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 7.04 'Feisty Fawn'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "CD-ROM з Ubuntu 7.04 'Feisty Fawn'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr "Утрымоўваецца супольнасцю"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Абмежаваная праграма"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "CD-ROM з Ubuntu 6.10 'Edgy Eft'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+msgid "Canonical-supported free and open-source software"
+msgstr ""
+"Свабодныя праграмы і праграмы з адкрытым кодам, што падтрымваюцца Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr "Падтрыманыя супольнасцю (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+msgid "Community-maintained free and open-source software"
+msgstr ""
+"Свабодныя праграмы і праграмы з адкрытым кодам, што падтрымваюцца супольнасцю"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Несвабодныя драйверы"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Уласніцкія драйверы прыладаў"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Абмежаваныя праграмы (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "Праграмы, абмежаваныя аўтарскім правам ці юрыдычнымі пытаннямі"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "CD-ROM з Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Важныя абнаўленні бяспекі"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Рэкамендаваныя абнаўленні"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr "Загадзя выдадзеныя абнаўленні"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+msgid "Unsupported updates"
+msgstr "Абнаўленні, што не падтрымваюцца"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "CD-ROM з Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Абнаўленні бяспекі Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Абнаўленні Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 Backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "CD-ROM з Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Афіцыйна падтрымваюцца"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Абнаўленні бяспекі Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Абнаўленні Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.04 Backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr "Падтымваецца супольнасцю (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Несвабодныя (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "CD-ROM з Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Больш не падтрымваюцца афіцыйна"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Абмежаванае аўтарскае права"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Абнаўленні бяспекі Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Абнаўленні Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 4.10 Backports"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 7 'Wheezy' "
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 6.0 'Squeeze' "
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 5.0 'Lenny' "
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 4.0 'Etch'"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 'Sarge'"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Прапанаваныя абнаўленні"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+msgid "Security updates"
+msgstr "Абнаўленні бяспекі"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr "Цяперашняе стабільнае выданне Debian"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr "Debian testing"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian 'Sid' (unstable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "Праграмы, сумяшчальныя з DFSG з несвабоднымі залежнымі"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Праграмы, несумяшчальныя з DFSG"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Сервер для %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Галоўны сервер"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Іншыя серверы"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Выгрузка файла %(current)li з %(total)li на хуткасці %(speed)s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Загрузка файла %(current)li of %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Падрабязнасці"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr "Пачынаецца..."
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr "Скончана"
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr "Несапраўдны unicode у апісанні да '%s' (%s). Паведаміце, калі ласка."
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "Недасяжны спіс зменаў"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+"Ліст зменаў пакуль што недасяжны.\n"
+"\n"
+"Глядзіце, калі ласка, http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"пакуль змены не стануць дасяжныя, альбо паспрабуйце пазней."
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Не ўдалося атрымаць спіс зменаў. \n"
+"Калі ласка, праверце вашае далучэнне да інтэрнэту."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr "Спіс файлаў да '%s' не атрымалася прачытаць"
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr "Спіс файлаў кіравання да '%s' не атрымалася прачытаць"
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr "Залежнасць, якую не ўдаецца задаволіць: %s\n"
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr "Канфліктуе з усталяваным пакетам '%s'"
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+"Парушае залежнасць %(depname)s (%(deprelation)s %(depversion)s) наяўнага "
+"пакета '%(pkgname)s'"
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+"Парушае канфлікт %(targetpkg)s (%(comptype)s %(targetver)s) наяўнага пакета "
+"'%(pkgname)s'"
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+"Парушае наяўны пакет '%(pkgname)s', які канфліктуе з: '%(targetpkg)s'. Але "
+"'%(debfile)s' забяспечваецца праз: '%(provides)s'"
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr "Гэты пакет не мае поля Architecture"
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr "Памылковая архітэктура '%s'"
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr "Ужо ўсталяваная апошняя версія"
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr "Не атрымалася задаволіць усе залежнасці (зламаны кэш)"
+
+#: ../apt/debfile.py:519
+#, python-format
+msgid "Cannot install '%s'"
+msgstr "Немагчыма ўсталяваць '%s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+"Аўтаматычна распакаваны:\n"
+"\n"
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr "Аўтаматычна ператвораны ў друкаваныя ASCII:\n"
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+"Усталяваць Build-Dependencies для зыходнага пакета '%s', які збірае %s\n"
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr "Трэба было б выдаліць абавязковы пакет"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr "%c%s... Скончана"
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr "Hit "
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr "Ign "
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr "Err "
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr "Атрымаць:"
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr " [Апрацоўваецца]"
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+"Змена носьбіта: Калі ласка, устаўце дыск з паметкай\n"
+" '%s'\n"
+"у прыладу '%s' і націсніце Enter\n"
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr "Атрымана %sB з %s (%sB/s)\n"
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+"Калі ласка, падайце імя для гэтага дыска, напрыклад, 'Debian 2.1r1 Disk 1'"
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr "Калі ласка, устаўце дыск у прыладу і націсніце Enter"
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr "Будуюцца структуры звестак"
diff --git a/po/bg.po b/po/bg.po
new file mode 100644
index 0000000..2c9942d
--- /dev/null
+++ b/po/bg.po
@@ -0,0 +1,680 @@
+# Bulgarian translation of update manager.
+# Copyright (C) 2005 THE update manager'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the update manager package.
+# Rostislav "zbrox" Raykov <zbrox@i-space.org>, 2005.
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: update manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-16 04:01+0000\n"
+"Last-Translator: Nikola Kasabov <nikola.kasabov@gmail.com>\n"
+"Language-Team: Bulgarian <dict@fsa-bg.org>\n"
+"Language: bg\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 5.10 актуализации на сигурността"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "CD с Ubuntu 4.10 „Warty Warthog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "CD с Ubuntu 4.10 „Warty Warthog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "CD с Ubuntu 4.10 „Warty Warthog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "CD с Ubuntu 4.10 „Warty Warthog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "CD с Ubuntu 4.10 „Warty Warthog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "CD с Ubuntu 4.10 „Warty Warthog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "CD с Ubuntu 5.04 „Hoary Hedgehog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "CD с Ubuntu 5.04 „Hoary Hedgehog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "CD с Ubuntu 4.10 „Warty Warthog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "CD с Ubuntu 4.10 „Warty Warthog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "CD с Ubuntu 4.10 „Warty Warthog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "CD с Ubuntu 4.10 „Warty Warthog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "CD с Ubuntu 5.04 „Hoary Hedgehog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "CD с Ubuntu 5.04 „Hoary Hedgehog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "CD с Ubuntu 5.04 „Hoary Hedgehog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "CD с Ubuntu 5.04 „Hoary Hedgehog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 5.10 актуализации на сигурността"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 5.10 актуализации на сигурността"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+#, fuzzy
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 5.10 актуализации"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "Поддържани от обществото (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+#, fuzzy
+msgid "Restricted software"
+msgstr "Допринесен софтуер"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+#, fuzzy
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "CD с Ubuntu 4.10 „Warty Warthog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+#, fuzzy
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "Поддържани от обществото (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "Поддържани от обществото (Universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "Поддържани от обществото (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+#, fuzzy
+msgid "Non-free drivers"
+msgstr "Несвободни (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+#, fuzzy
+msgid "Restricted software (Multiverse)"
+msgstr "Несвободни (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+#, fuzzy
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 'Dapper Drake'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+#, fuzzy
+msgid "Important security updates"
+msgstr "Ubuntu 5.10 актуализации на сигурността"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "_Инсталиране на актуализациите"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "_Инсталиране на актуализациите"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+#, fuzzy
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.10 актуализации на сигурността"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.10 актуализации"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 Състарени версии"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+#, fuzzy
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "CD с Ubuntu 5.04 „Hoary Hedgehog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+#, fuzzy
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "CD с Ubuntu 5.04 „Hoary Hedgehog“"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Официално поддържани"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+#, fuzzy
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Ubuntu 5.10 актуализации на сигурността"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+#, fuzzy
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ubuntu 5.10 актуализации"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+#, fuzzy
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.10 Състарени версии"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+#, fuzzy
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "CD с Ubuntu 4.10 „Warty Warthog“"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "Поддържани от обществото (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Несвободни (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+#, fuzzy
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "CD с Ubuntu 4.10 „Warty Warthog“"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+#, fuzzy
+msgid "No longer officially supported"
+msgstr "Официално поддържан"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Ограничени авторски права"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ubuntu 4.10 обновления по сигурността"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Ubuntu 4.10 обновления"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+#, fuzzy
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 5.10 Състарени версии"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 3.1 „Sarge“"
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 3.1 „Sarge“"
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian Testing"
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian Testing"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 „Sarge“"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+#, fuzzy
+msgid "Proposed updates"
+msgstr "_Инсталиране на актуализациите"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "Ubuntu 5.10 актуализации на сигурността"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+#, fuzzy
+msgid "Debian current stable release"
+msgstr "Debian Unstable „Sid“"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "Debian \"Etch\" (тестване)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian \"Sid\" (нестабилен)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "DFSG-съвместим софтуер с несвободни зависимости"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Софтуер несъвместим с DFSG"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr ""
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr ""
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, fuzzy, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Сваляне на файл %li от %li при %s/сек"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, fuzzy, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Сваляне на файл %li от %li при %s/сек"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Детайли"
+
+#: ../apt/progress/gtk2.py:428
+#, fuzzy
+msgid "Starting..."
+msgstr "Настройки"
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+#, fuzzy
+msgid "The list of changes is not available"
+msgstr "Списъкът с промените още не е наличен. Моля, опитайте по-късно!"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+#, fuzzy
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Неуспех при изтегляне на списъка с промени. Моля, проверете Интернет "
+"връзката си."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "Не може да се инсталира '%s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "Ще трябва да бъде премахнат важен пакет"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/bn.po b/po/bn.po
new file mode 100644
index 0000000..a20804c
--- /dev/null
+++ b/po/bn.po
@@ -0,0 +1,671 @@
+# Bengali translation for update-manager
+# Copyright (c) (c) 2006 Canonical Ltd, and Rosetta Contributors 2006
+# This file is distributed under the same license as the update-manager package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2006.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-16 04:02+0000\n"
+"Last-Translator: Khandakar Mujahidul Islam <suzan@bengalinux.org>\n"
+"Language-Team: Bengali <bn@li.org>\n"
+"Language: bn\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "উবুন্টু ৫.১০ নিরাপত্তামুলক আপডেট"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "উবুন্টু ৫.১০ নিরাপত্তামুলক আপডেট"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "উবুন্টু ৫.১০ নিরাপত্তামুলক আপডেট"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+#, fuzzy
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "উবুন্টু ৫.১০ আপডেট"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+#, fuzzy
+msgid "Restricted software"
+msgstr "ফ্রি নয় (মাল্টিভার্স)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+#, fuzzy
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "উবুন্টু ৬.০৬ 'ড্যাপার ড্রেক'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+msgid "Canonical-supported free and open-source software"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+msgid "Community-maintained free and open-source software"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+#, fuzzy
+msgid "Non-free drivers"
+msgstr "ফ্রি নয় (মাল্টিভার্স)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+#, fuzzy
+msgid "Restricted software (Multiverse)"
+msgstr "ফ্রি নয় (মাল্টিভার্স)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+#, fuzzy
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "উবুন্টু ৬.০৬ 'ড্যাপার ড্রেক'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+#, fuzzy
+msgid "Important security updates"
+msgstr "উবুন্টু ৫.১০ নিরাপত্তামুলক আপডেট"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "আপডেট ইন্সটল করো (_I)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "আপডেট ইন্সটল করো (_I)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+#, fuzzy
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "উবুন্টু ৫.১০ নিরাপত্তামুলক আপডেট"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "উবুন্টু ৫.১০ আপডেট"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "উবুন্টু ৫.১০ ব্যাকপোর্ট"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+#, fuzzy
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "অফিসিয়াল ভাবে সমর্থিত"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+#, fuzzy
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "উবুন্টু ৫.১০ নিরাপত্তামুলক আপডেট"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+#, fuzzy
+msgid "Ubuntu 5.04 Updates"
+msgstr "উবুন্টু ৫.১০ আপডেট"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+#, fuzzy
+msgid "Ubuntu 5.04 Backports"
+msgstr "উবুন্টু ৫.১০ ব্যাকপোর্ট"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+#, fuzzy
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "উবুন্টু ৫.১০ 'ব্রিজী ব্যাজার'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "ফ্রি নয় (মাল্টিভার্স)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+#, fuzzy
+msgid "No longer officially supported"
+msgstr "কিছু সফটওয়্যার অফিসিয়ালি আর সমর্থিত নয়"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+#, fuzzy
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "উবুন্টু ৫.১০ নিরাপত্তামুলক আপডেট"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+#, fuzzy
+msgid "Ubuntu 4.10 Updates"
+msgstr "উবুন্টু ৫.১০ আপডেট"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+#, fuzzy
+msgid "Ubuntu 4.10 Backports"
+msgstr "উবুন্টু ৫.১০ ব্যাকপোর্ট"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "ডেবিয়ান ৩.১ \"সার্জ\""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "ডেবিয়ান ৩.১ \"সার্জ\""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "ডেবিয়ান ৩.১ \"সার্জ\""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "ডেবিয়ান ৩.১ \"সার্জ\""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "ডেবিয়ান ৩.১ \"সার্জ\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+#, fuzzy
+msgid "Proposed updates"
+msgstr "আপডেট ইন্সটল করো (_I)"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "উবুন্টু ৫.১০ নিরাপত্তামুলক আপডেট"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "ডেবিয়ান \"Etch\" (testing)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "ডেবিয়ান \"Sid\" (unstable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr ""
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr ""
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr ""
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr ""
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "বিস্তারিত"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr ""
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+#, fuzzy
+msgid "The list of changes is not available"
+msgstr "পরিবর্তনের তালিকা এখনে উপস্হিত নয়। অনুগ্রহ করে পরে আবার চেষ্টা করুন।"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+#, fuzzy
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"পরিবর্তন তালিকা ডাউনলোড করতে ব্যর্থ। অনুগ্রহ করে আপনার ইন্টারনেট সংযোগ পরীক্ষা করুন।"
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "'%s' ইন্সটল করা যাচ্ছে না"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "একটি প্রয়োজনীয় প্যকেজ অপসারণ করা হতে পারে"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/ca.po b/po/ca.po
new file mode 100644
index 0000000..524a4ce
--- /dev/null
+++ b/po/ca.po
@@ -0,0 +1,679 @@
+# Catalan translation for update-manager
+# Copyright (C) 2006
+# This file is distributed under the same license as the update-manager package.
+# Jordi Irazuzta Cardús <irazuzta@gmail.com>, 2006.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-16 04:14+0000\n"
+"Last-Translator: Jordi Irazuzta <irazuzta@gmail.com>\n"
+"Language-Team: Catalan <tradgnome@softcatala.org>\n"
+"Language: ca\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Actualitzacions de seguretat d'Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "CD amb Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "CD amb Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "CD amb Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "CD amb Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "CD amb Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "CD amb Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "CD amb Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "CD amb Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "CD amb Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "CD amb Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "CD amb Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "CD amb Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "CD amb Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "CD amb Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "CD amb Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "CD amb Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "CD amb Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Actualitzacions de seguretat d'Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "CD amb Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Actualitzacions de seguretat d'Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "CD amb Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+#, fuzzy
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Actualitzacions d'Ubuntu 5.10"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "Paquets mantinguts per la comunitat (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+#, fuzzy
+msgid "Restricted software"
+msgstr "Programari de la comunitat"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+#, fuzzy
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "CD amb Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+#, fuzzy
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "Paquets mantinguts per la comunitat (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "Paquets mantinguts per la comunitat (Universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "Paquets mantinguts per la comunitat (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+#, fuzzy
+msgid "Non-free drivers"
+msgstr "Paquets sense llicència lliure (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+#, fuzzy
+msgid "Restricted software (Multiverse)"
+msgstr "Paquets sense llicència lliure (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+#, fuzzy
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 'Dapper Drake'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+#, fuzzy
+msgid "Important security updates"
+msgstr "Debian Stable Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "_Instal·la les actualitzacions"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "_Instal·la les actualitzacions"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+#, fuzzy
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "CD amb Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Actualitzacions de seguretat d'Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Actualitzacions d'Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+#, fuzzy
+msgid "Ubuntu 5.10 Backports"
+msgstr "Actualitzacions d'Ubuntu 6.06 LTS"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+#, fuzzy
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "CD amb Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+#, fuzzy
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "CD amb Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Paquets mantinguts oficialment (Main)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Actualitzacions de seguretat d'Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Actualitzacions d'Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+#, fuzzy
+msgid "Ubuntu 5.04 Backports"
+msgstr "Actualitzacions d'Ubuntu 6.06 LTS"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+#, fuzzy
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "CD amb Ubuntu 4.10 \"Warty Warthog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "Paquets mantinguts per la comunitat (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Paquets sense llicència lliure (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+#, fuzzy
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "CD amb Ubuntu 4.10 \"Warty Warthog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+#, fuzzy
+msgid "No longer officially supported"
+msgstr "Algun programari ja no es mantindrà oficialment"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Paquets amb restriccions per copyright (Restricted)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Actualitzacions de seguretat d'Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Actualitzacions d'Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+#, fuzzy
+msgid "Ubuntu 4.10 Backports"
+msgstr "Actualitzacions d'Ubuntu 6.06 LTS"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+#, fuzzy
+msgid "Proposed updates"
+msgstr "_Instal·la les actualitzacions"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "Debian Stable Security Updates"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+#, fuzzy
+msgid "Debian current stable release"
+msgstr "Debian Unstable \"Sid\""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "Debian Testing"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian \"Sid\" (unstable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "Programari compatible DFSG amb dependències no lliures"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Programari no compatible DFSG"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr ""
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Servidor principal"
+
+#: ../aptsources/distro.py:250
+#, fuzzy
+msgid "Custom servers"
+msgstr "Servidor més proper"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, fuzzy, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "S'està descarregant el fitxer %li de %li amb %s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, fuzzy, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "S'està descarregant el fitxer %li de %li amb %s/s"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Detalls"
+
+#: ../apt/progress/gtk2.py:428
+#, fuzzy
+msgid "Starting..."
+msgstr "Paràmetres"
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+#, fuzzy
+msgid "The list of changes is not available"
+msgstr "La llista de canvis encara no està disponible. Proveu-ho després."
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+#, fuzzy
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"S'ha produït un error en descarregar els canvis. Comproveu si teniu connexió "
+"a Internet."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "No s'ha pogut instal·lar '%s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "S'haurà d'esborrar un paquet essencial"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/cs.po b/po/cs.po
new file mode 100644
index 0000000..5e9fd73
--- /dev/null
+++ b/po/cs.po
@@ -0,0 +1,660 @@
+# Czech translation for update-manager
+# Copyright (c) (c) 2006 Canonical Ltd, and Rosetta Contributors 2006
+# This file is distributed under the same license as the update-manager package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2006.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-18 22:54+0000\n"
+"Last-Translator: Dominik Sauer <Dominik.Sauer@gmail.com>\n"
+"Language-Team: Czech <cs@li.org>\n"
+"Language: cs\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Bezpečnostní aktualizace Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Cdrom s Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Cdrom s Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+#| msgid "Ubuntu 4.10 'Warty Warthog'"
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Cdrom s Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Cdrom s Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Cdrom s Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Cdrom s Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Cdrom s Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Cdrom s Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Cdrom s Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Bezpečnostní aktualizace Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Cdrom s Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Bezpečnostní aktualizace Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Cdrom s Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "Udržováno komunitou"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Nesvobodný software"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "Cdrom s Ubuntu 6.10 'Edgy Eft'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "Svobodný software oficiálně podporovaný společností Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "Udržováno komunitou (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "Software s otevřeným zdrojovým kódem, který je udržován komunitou"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Nesvobodné ovladače"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Patentované (proprietární) ovladače zařízení"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Software s omezující licencí (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "Software omezený ochrannou známkou nebo jinými právními prostředky"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Cdrom s Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Důležité bezpečnostní aktualizace"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Doporučené aktualizace"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "Navržené aktualizace"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "Aktualizace přenesené z vyšších verzí distribuce"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Cdrom s Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Bezpečnostní aktualizace Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Aktualizace Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Software přenesený z vyšší verze distribuce na Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Cdrom s Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Oficiálně podporováno"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Bezpečnostní aktualizace Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Aktualizace Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Aplikace přenesené z vyšších verzí distribuce na Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "Udržováno komunitou (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Nesvobodný (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "Cdrom s Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Již není oficiálně podporováno"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Omezený copyright"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Bezpečnostní aktualizace Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Aktualizace Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Aplikace přenesené z vyšších verzí distribuce na Ubuntu 4.10"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Navržené aktualizace"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "Důležité bezpečnostní aktualizace"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "Debian \"Etch\" (testing)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian \"Sid\" (unstable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "Software kompatibilní s DFSG, ale závisející na nesvobodných balících"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Software nekompatibilní s DFSG"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Server pro zemi \"%s\""
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Hlavní server"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Uživatelem vybrané servery"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Stahuji %(current)li. soubor z %(total)li rychlostí %(speed)s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Stahuji %(current)li. soubor of %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Podrobnosti"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr ""
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "Seznam změn není dostupný."
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Stažení seznamu změn selhalo. \n"
+"Prosím zkontrolujte své internetové připojení."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "Nemohu nainstalovat '%s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "Toto by vedlo k odstranění základního balíku"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/csb.po b/po/csb.po
new file mode 100644
index 0000000..7335992
--- /dev/null
+++ b/po/csb.po
@@ -0,0 +1,621 @@
+# Kashubian translation for update-manager
+# Copyright (c) 2006 Rosetta Contributors and Canonical Ltd 2006
+# This file is distributed under the same license as the update-manager package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2006.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-08 04:10+0000\n"
+"Last-Translator: Michôł Òstrowsczi <ostrowski.michal@gmail.com>\n"
+"Language-Team: Kashubian <csb@li.org>\n"
+"Language: csb\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
+"|| n%100>=20) ? 1 : 2\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+msgid "Canonical-supported free and open-source software"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+msgid "Community-maintained free and open-source software"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "%s aktualizacëji"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr ""
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+msgid "Debian 6.0 'Squeeze' "
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+msgid "Debian 5.0 'Lenny' "
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+msgid "Debian 4.0 'Etch'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+msgid "Debian 3.1 'Sarge'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "%s aktualizacëji"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr ""
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Serwera dlô kraju %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Przédny serwera"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Jine serwerë"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr ""
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+#, fuzzy
+msgid "Details"
+msgstr "Codniowò"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr ""
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr ""
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "Nie je mòżno zainstalowac '%s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr ""
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/da.po b/po/da.po
new file mode 100644
index 0000000..9deb967
--- /dev/null
+++ b/po/da.po
@@ -0,0 +1,637 @@
+# Danish translation python-apt.
+# Copyright (C) 2012 python-apt & nedenstående oversætttere.
+# This file is distributed under the same license as the python-apt package.
+# Mads Bille Lundby <lundbymads@gmail.com>, 2009.
+# AJenbo <anders@jenbo.dk>, 2011.
+# Ask, 2011.
+# Joe Hansen <joedalton2@yahoo.dk>, 2011, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: python-apt\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2012-10-06 14:44+0200\n"
+"Last-Translator: Joe Hansen <joedalton2@yahoo.dk>\n"
+"Language-Team: Danish <debian-l10n-danish@lists.debian.org>\n"
+"Language: da\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 12.04 \"Precise Pangolin\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Cd-rom med Ubuntu 12.04 \"Precise Pangolin\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 11.10 \"Oneiric Ocelot\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Cd-rom med Ubuntu 11.10 \"Oneiric Ocelot\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 11.04 \"Natty Narwhal\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Cd-rom med Ubuntu 11.04 \"Natty Narwhal\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 10.10 \"Maverick Meerkat\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Cd-rom med Ubuntu 10.10 \"Maverick Meerkat\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr "Canonicalpartnere"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr "Programmer pakket af Canonical for deres partnere"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr "Dette program er ikke en del af Ubuntu."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr "Uafhængigt"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr "Tilbudt af tredjepartsprogramudviklere"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr "Programmer tilbudt af tredjepartsudviklere."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 10.04 \"Lucid Lynx\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Cd-rom med Ubuntu 10.04 \"Lucid Lynx\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 9.10 \"Karmic Koala\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Cd-rom med Ubuntu 9.10 \"Karmic Koala\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 9.04 \"Jaunty Jackalope\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Cd-rom med Ubuntu 9.04 \"Jaunty Jackalope\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 8.10 \"Intrepid Ibex\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Cd-rom med Ubuntu 8.10 \"Intrepid Ibex\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 8.04 \"Hardy Heron\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Cd-rom med Ubuntu 8.04 \"Hardy Heron\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 7.10 \"Gutsy Gibbon\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Cd-rom med Ubuntu 7.10 \"Gutsy Gibbon\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 7.04 \"Feisty Fawn\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Cd-rom med Ubuntu 7.04 \"Feisty Fawn\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 \"Edgy Eft\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr "Vedligeholdt af fællesskabet"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Ikke-frit software"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "Cd-rom med Ubuntu 6.10 \"Edgy Eft\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS \"Dapper Drake\""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+msgid "Canonical-supported free and open-source software"
+msgstr "Canonical-understøttede frie programmer med åben kildekode"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr "Vedligeholdt af fællesskabet (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+msgid "Community-maintained free and open-source software"
+msgstr "Fællesskabsvedligeholdt frie programmer med åben kildekode"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Proprietære drivere"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Proprietære drivere til enheder"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Ikke-frit software (multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "Software begrænset af ophavsret eller legale problemer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Cd-rom med Ubuntu 6.06 LTS \"Dapper Drake\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Vigtige sikkerhedsopdateringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Anbefalede opdateringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr "Ikke-frigivne opdateringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+msgid "Unsupported updates"
+msgstr "Ikke-understøttede opdateringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Cd-rom med Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.10 sikkerhedsopdateringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.10 opdateringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 tilbageporteringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Cd-rom med Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Understøttet officielt"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Ubuntu 5.04 sikkerhedsopdateringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ubuntu 5.04 opdateringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.04 tilbageporteringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 \"Warty Warthog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr "Vedligeholdt af fællesskabet (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Ikke-frit (multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "Cd-rom med Ubuntu 4.10 \"Warty Warthog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Ikke længere officielt supporteret"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Begrænset ophavsret"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ubuntu 4.10 sikkerhedsopdateringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Ubuntu 4.10 opdateringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 4.10 tilbageporteringer"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 7 \"Wheezy\" "
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 6.0 \"Squeeze\" "
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 5.0 \"Lenny\" "
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 4.0 \"Etch\""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Foreslåede opdateringer"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+msgid "Security updates"
+msgstr "Sikkerhedsopdateringer"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr "Debian aktuel stabil udgivelse"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr "Debian tester"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian \"Sid\" (ustabil)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "DFSG-kompatibel software med ikke-frie afhængigheder"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Ikke-DFSG-kompatibel software"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Server for %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Hovedserver"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Brugerdefinerede servere"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Henter fil %(current)li af %(total)li med %(speed)s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Henter fil %(current)li af %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Detaljer"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr "Starter..."
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr "Færdig"
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr "Ugyldig unicode i beskrivelsen af \"%s\" (%s). Se venligst rapport."
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "Listen med ændringer er ikke tilgængelig"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+"Listen over ændringer er ikke tilgængelig endnu\n"
+"\n"
+"Se venligst http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"indtil ændringerne bliver tilgængelige eller prøv igen senere."
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Fejl ved hentning af ændringslisten.\n"
+"Undersøg venligst din internetforbindelse."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr "Listen over filer for \"%s\" kunne ikke læses"
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr "Listen over filer for \"%s\" kunne ikke læses"
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr "Afhængighed kan ikke opfyldes; %s\n"
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr "I konflikt med den installerede pakke \"%s\""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+"Ødelægger eksisterende pakke \"%(pkgname)s\" afhængighed %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+"Ødelægger eksisterende pakke \"%(pkgname)s\" konflikt %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+"Ødelægger eksisterende pakke \"%(pkgname)s\" som er i konflikt: \"%(targetpkg)s\". "
+"Men \"%(debfile)s\" tilbyder den via: \"%(provides)s\""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr "Intet arkitekturfelt i pakken"
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr "Forkert arkitektur \"%s\""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr "Der er allerede installeret en senere version"
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr "Kunne ikke opfylde alle afhængigheder (beskadiget cache)"
+
+#: ../apt/debfile.py:519
+#, python-format
+msgid "Cannot install '%s'"
+msgstr "Kan ikke installere \"%s\""
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+"Automatisk pakket ud:\n"
+"\n"
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr "Automatisk konverteret til udskrivbar ascii:\n"
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr "Installer byggeafhængigheder for kildepakken \"%s\" der bygger %s\n"
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr "En nødvendig pakke vil blive fjernet"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr "%c%s ... Færdig"
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr "Tjekkede "
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr "Ign "
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr "Fejl "
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr "Henter:"
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr " [Arbejder]"
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+"Medieskift: Indsæt disken med navnet\n"
+" '%s'\n"
+"i drevet '%s' og tryk retur\n"
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr "Hentede %sB på %s (%sB/s)\n"
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr "Angiv et navn for denne disk, som f.eks. 'Debian 2.1r1 Disk 1'"
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr "Indsæt en disk i drevet og tryk retur"
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr "Opbygger datastrukturer"
+
+
diff --git a/po/de.po b/po/de.po
new file mode 100644
index 0000000..c7ee73e
--- /dev/null
+++ b/po/de.po
@@ -0,0 +1,645 @@
+# German translation of python-apt.
+# Copyright (C) 2005 Michiel Sikkes <michiel@eyesopened.nl>
+# Copyright (C) 2009 - 2010 Julian Andres Klode <jak@debian.org>
+# This file is distributed under the same license as the update-manager package.
+# Initial version by an unknown artist.
+# Frank Arnold <frank@scirocco-5v-turbo.de>, 2005.
+# Holger Wansing <linux@wansing-online.de>, 2012.
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: python-apt\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:42+0200\n"
+"PO-Revision-Date: 2012-06-17 20:23+0200\n"
+"Last-Translator: Holger Wansing <linux@wansing-online.de>\n"
+"Language-Team: German <debian-l10n-german@lists.debian.org>\n"
+"Language: de\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 12.04 »Precise Pangolin«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "CD-ROM mit Ubuntu 12.04 »Precise Pangolin«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 11.10 »Oneiric Ocelot«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "CD-ROM mit Ubuntu 11.10 »Oneiric Ocelot«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 11.04 »Natty Narwhal«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "CD-ROM mit Ubuntu 11.04 »Natty Narwhal«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 10.10 »Maverick Meerkat«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "CD-ROM mit Ubuntu 10.10 »Maverick Meerkat«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr "Canonical-Partner"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr "Software, die von Canonical für seine Partner paketiert wurde"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr "Diese Software ist nicht Teil von Ubuntu."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr "Unabhängig"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr "Bereitgestellt von Fremd-Software-Entwicklern"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr "Software, die von Fremd-Software-Entwicklern angeboten wurde"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 10.04 »Lucid Lynx«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "CD-ROM mit Ubuntu 10.04 »Lucid Lynx«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 9.10 »Karmic Koala«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "CD-ROM mit Ubuntu 9.10 »Karmic Koala«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 9.04 »Jaunty Jackalope«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "CD-ROM mit Ubuntu 9.04 »Jaunty Jackalope«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 8.10 »Intrepid Ibex«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "CD-ROM mit Ubuntu 8.10 »Intrepid Ibex«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 8.04 »Hardy Heron«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "CD-ROM mit Ubuntu 8.04 »Hardy Heron«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 7.10 »Gutsy Gibbon«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "CD-ROM mit Ubuntu 7.10 »Gutsy Gibbon«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 7.04 »Feisty Fawn«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "CD-ROM mit Ubuntu 7.04 »Feisty Fawn«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 »Edgy Eft«"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr "Von der Ubuntu-Gemeinde betreut"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Eingeschränkte Software"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "CD-ROM mit Ubuntu 6.10 »Edgy Eft«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS »Dapper Drake«"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+msgid "Canonical-supported free and open-source software"
+msgstr "Von Canonical unterstützte freie und quelloffene Software"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr "Von der Gemeinde betreut (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+msgid "Community-maintained free and open-source software"
+msgstr "Von der Ubuntu-Gemeinde betreute freie und quelloffene Software"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Proprietäre Treiber"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Proprietäre Gerätetreiber"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Eingeschränkte Software (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "Rechtlich eingeschränkte Software"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "CD-ROM mit Ubuntu 6.06 LTS »Dapper Drake«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Wichtige Sicherheitsaktualisierungen"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Empfohlene Aktualisierungen"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr "Vorabveröffentlichte Aktualisierungen"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+msgid "Unsupported updates"
+msgstr "Nicht unterstützte Aktualisierungen"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 »Breezy Badger«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "CD-ROM mit Ubuntu 5.10 »Breezy Badger«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.10 Sicherheitsaktualisierungen"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.10 Aktualisierungen"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 Backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 »Hoary Hedgehog«"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "CD-ROM mit Ubuntu 5.04 »Hoary Hedgehog«"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Offiziell unterstützt"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Ubuntu 5.04 Sicherheitsaktualisierungen"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ubuntu 5.04 Aktualisierungen"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.04 Backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 »Warty Warthog«"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr "Von der Ubuntu-Gemeinde betreut (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Unfrei (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "CD-ROM mit Ubuntu 4.10 »Warty Warthog«"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Unterstützung ist ausgelaufen"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Eingeschränktes Copyright"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ubuntu 4.10 Sicherheitsaktualisierungen"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Ubuntu 4.10 Aktualisierungen"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 4.10 Backports"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 7 »Wheezy«"
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 6.0 »Squeeze«"
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 5.0 »Lenny«"
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 4.0 »Etch«"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 »Sarge«"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Vorgeschlagene Aktualisierungen"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+msgid "Security updates"
+msgstr "Sicherheitsaktualisierungen"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr "Aktuelle stabile Veröffentlichung von Debian"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr "Debian Testing"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian »Sid« (Unstable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "DFSG-kompatible Software mit unfreien Abhängigkeiten"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Nicht DFSG-kompatible Software"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Server für %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Haupt-Server"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Benutzerdefinierte Server"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr ""
+"Datei %(current)li von %(total)li wird mit %(speed)s/s heruntergeladen."
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Datei %(current)li von %(total)li wird heruntergeladen."
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Details"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr "Starten ..."
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr "Fertig"
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr "Ungültiger Unicode-Wert in Beschreibung für '%s' (%s). Bitte melden."
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "Die Liste mit Änderungen ist momentan nicht verfügbar."
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+"Die Liste mit Änderungen ist momentan nicht verfügbar.\n"
+"\n"
+"Bitte benutzen Sie http://launchpad.net/ubuntu/+source/%s/%s/+changelog,\n"
+"bis die Liste verfügbar ist oder versuchen sie es später erneut."
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Die Liste mit Änderungen konnte nicht heruntergeladen werden. \n"
+"Bitte überprüfen Sie Ihre Internet-Verbindung."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr "Die Liste der Dateien von »%s« konnte nicht gelesen werden."
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr "Die Liste der Dateien von »%s« konnte nicht gelesen werden."
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr "Abhängigkeit nicht erfüllbar: %s\n"
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr "Steht in Konflikt zu dem installierten Paket »%s«"
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+"Beschädigt vorhandenes Paket »%(pkgname)s« wegen Abhängigkeit %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+"Beschädigt vorhandenes Paket »%(pkgname)s« wegen Konflikt: %(targetpkg)s "
+"(%(comptype)s %(targetver)s)"
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+"Beschädigt vorhandenes Paket »%(pkgname)s«, welches in Konflikt steht: "
+"»%(targetpkg)s«. Aber »%(debfile)s« bietet es an über: »%(provides)s«"
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr "Kein Architecture-Feld in dem Paket"
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr "Falsche Architektur »%s«"
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr "Eine neuere Version ist bereits installiert."
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+"Es konnten nicht alle Abhängigkeiten erfüllt werden (Zwischenspeicher "
+"defekt)."
+
+#: ../apt/debfile.py:519
+#, python-format
+msgid "Cannot install '%s'"
+msgstr "»%s« kann nicht installiert werden."
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+"Automatisch entpackt:\n"
+"\n"
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr "Automatisch konvertiert in druckfähiges ASCII:\n"
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+"Installieren der Bau-Abhängigkeiten für das Quellpaket »%s«, welches »%s« "
+"baut\n"
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr "Ein grundlegendes Paket müsste entfernt werden"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr "%c%s... Fertig"
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr "OK "
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr "Ign "
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr "Fehl "
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr "Hole:"
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr " [Verarbeiten]"
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+"Medienwechsel: Bitte legen Sie das Medium mit dem Namen\n"
+" »%s«\n"
+"in Laufwerk »%s« ein und drücken Sie die Eingabetaste.\n"
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr "Es wurden %sB in %s geholt (%sB/s)\n"
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+"Bitte geben Sie einen Namen für die CD an, wie zum Beispiel »Debian 2.1r1 "
+"Disk 1«."
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+"Bitte legen Sie ein Medium ins Laufwerk und drücken Sie die Eingabetaste."
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr "Datenstrukturen werden aufgebaut"
diff --git a/po/el.po b/po/el.po
new file mode 100644
index 0000000..a4a48cf
--- /dev/null
+++ b/po/el.po
@@ -0,0 +1,638 @@
+# translation of el.po to Greek
+# This file is distributed under the same license as the PACKAGE package.
+# Copyright (C) 2005 THE PACKAGE'S COPYRIGHT HOLDER.
+#
+# Kostas Papadimas <pkst@gnome.org>, 2005, 2006.
+# Thomas Vasileiou <thomas-v@wildmail.com>, 2012.
+msgid ""
+msgstr ""
+"Project-Id-Version: el\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:42+0200\n"
+"PO-Revision-Date: 2012-06-13 11:37+0100\n"
+"Last-Translator: Thomas Vasileiou <thomas-v@wildmail.com>\n"
+"Language-Team: Greek <team@gnome.gr>\n"
+"Language: el\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 12.04 'Precise Pangolin'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Cdrom με Ubuntu 12.04 'Precise Pangolin'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 11.10 'Oneiric Ocelot''"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Cdrom με το Ubuntu 11.10 'Oneiric Ocelot'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 11.04 'Natty Narwhal'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Cdrom με το Ubuntu 11.04 'Natty Narwhal'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 10.10 'Maverick Meerkat'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Cdrom με το Ubuntu 10.10 'Maverick Meerkat'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr "Συνεργάτες της Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr "Πακέτο λογισμικού της Canonical για τους συνεργάτες της "
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr "Αυτό το λογισμικό δεν αποτελεί μέρος των Ubuntu."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr "Ανεξάρτητο"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr "Παρέχεται από τρίτους"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr "Λογισμικό που προσφέρεται από τρίτους."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 10.04 'Lucid Lynx'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Cdrom με Ubuntu 10.04 'Lucid Lynx'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 9.10 'Karmic Koala'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Cdrom με το Ubuntu 9.10 'Karmic Koala'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 9.04 'Jaunty Jackalope"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Cdrom με το Ubuntu 9.04 'Jaunty Jackalope'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 8.10 'Intrepid Ibex'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Cdrom με Ubuntu 8.10 'Intrepid Ibex'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 8.04 'Hardy Heron'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Cdrom με Ubuntu 8.04 'Hardy Heron'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 7.10 'Gutsy Gibbon'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Cdrom με Ubuntu 7.10 'Gutsy Gibbon'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 7.04 'Feisty Fawn'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Cdrom με Ubuntu 7.04 'Feisty Fawn'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr "Υποστηριζόμενα από την κοινότητα"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Λογισμικό με περιορισμούς"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "Cdrom με το Ubuntu 6.10 'Edgy Eft"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 TLS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+msgid "Canonical-supported free and open-source software"
+msgstr "Λογισμικό ανοικτού κώδικα υποστηριζόμενο από την Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr "Υποστηριζόμενα από την κοινότητα (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+msgid "Community-maintained free and open-source software"
+msgstr "Λογισμικό ανοιχτού κώδικα υποστηριζόμενο από την κοινότητα"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Όχι-ελεύθεροι οδηγοί"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Οδηγοί με κλειστό κώδικα για συσκευές"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Όχι-ελεύθερο (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "Λογισμικό με περιορισμούς από πνευματικά δικαιώματα και νόμους"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Cdrom με Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Σημαντικές ενημερώσεις ασφαλείας"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Συνιστώμενες ενημερώσεις"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr "Προτεινόμενες ενημερώσεις"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+msgid "Unsupported updates"
+msgstr "Μη υποστηριζόμενες ενημερώσεις"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Cdrom με Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Αναβαθμίσεις ασφαλείας Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Αναβαθμίσεις Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 Backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Cdrom με Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Επίσημα υποστηριζόμενο"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Αναβαθμίσεις ασφαλείας Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ενημερώσεις Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.04 Backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr "Υποστηριζόμενα από την κοινότητα (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Όχι-ελεύθερα (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "Cdrom με το Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Δεν υποστηρίζονται πια επίσημα"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Περιορισμένα πνευματικά δικαιώματα"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ενημερώσεις ασφαλείας Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Ενημερώσεις Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 4.10 Backports"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 7 'Wheezy' "
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 6.0 'Squeeze' "
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 5.0 'Lenny' "
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 4.0 'Etch'"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 'Sarge'"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Προτεινόμενες ενημερώσεις"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+msgid "Security updates"
+msgstr "Ενημερώσεις ασφαλείας"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr "Τρέχουσα σταθερή έκδοση Debian "
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr "Debian testing"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian 'Sid' (unstable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "Λογισμικό συμβατό με DFSG με μη Ελεύθερες Εξαρτήσεις"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Λογισμικό μη συμβατό με DFSG"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Εξυπηρετητής για %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Κύριος εξυπηρετητής"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Προσαρμοσμένοι εξυπηρετητές"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Λήψη αρχείου %(current)li από %(total)li με %(speed)s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Λήψη αρχείου %(current)li από %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Λεπτομέρειες"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr "Εκκίνηση..."
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr "Ολοκληρώθηκε"
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+"Μη έγκυρος unicode στην περιγραφή για το '%s' (%s). Παρακαλώ αναφέρετέ το."
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "Η λίστα των αλλαγών δεν είναι διαθέσιμη."
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+"Η λίστα αλλαγών δεν είναι διαθέσιμη.\n"
+"\n"
+"Παρακαλώ χρησιμοποιήστε το http://launchpad.net/ubuntu/+source/%s/%s/"
+"+changelog\n"
+"έως ότου οι αλλαγές γίνουν διαθέσιμες ή προσπαθήστε αργότερα."
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Αποτυχία λήψης της λίστας των αλλαγών.\n"
+"Παρακαλώ ελέγξτε τη σύνδεση σας στο διαδίκτυο."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr "Η λίστα των αρχείων για το '%s' δεν μπόρεσε να διαβαστεί"
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr "Η λίστα των αρχείων ελέγχου για το '%s' δεν μπόρεσε να διαβαστεί"
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr "Η εξάρτηση δεν ικανοποιείται: %s\n"
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr "Συγκρούεται με το εγκατεστημένο πακέτο '%s'"
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+"Παραβιάζει υπάρχον πακέτο '%(pkgname)s' εξάρτηση %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+"Παραβιάζει υπάρχον πακέτο '%(pkgname)s' σύγκρουση με : %(targetpkg)s "
+"(%(comptype)s %(targetver)s)"
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+"Παραβιάζει υπάρχον πακέτο '%(pkgname)s' το οποίο συγκρούεται με: "
+"'%(targetpkg)s'. Αλλά το '%(debfile)s', το παρέχει μέσω του: '%(provides)s'"
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr "Δεν βρέθηκε το πεδίο Αρχιτεκτονική στο πακέτο"
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr "Λάθος αρχιτεκτονική '%s'"
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr "Μια πιο πρόσφατη έκδοση είναι ήδη εγκατεστημένη"
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr "Αποτυχία ικανοποίησης όλων των εξαρτήσεων (σπασμένη cache)"
+
+#: ../apt/debfile.py:519
+#, python-format
+msgid "Cannot install '%s'"
+msgstr "Αδυναμία εγκατάστασης του '%s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+"Αυτόματη αποσυμπίεση:\n"
+"\n"
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr "Μετατράπηκε αυτόματα σε εκτυπώσιμο ascii:\n"
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+"Εγκαταστήστε τις Εξαρτήσεις Μεταγλώττισης για το πηγαίο πακέτο '%s' που "
+"δομεί το %s\n"
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr "Ένα απαραίτητο πακέτα θα πρέπει να απομακρυνθεί"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr "%c%s... Ολοκληρώθηκε"
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr "Πιέστε"
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr "Αγν"
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr "Λαθ"
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr "Φέρε:"
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr "[Λειτουργεί]"
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+"Αλλαγή μέσου: παρακαλώ τοποθετήστε το δίσκο\n"
+" '%s'\n"
+"στον οδηγό '%s' και πατήστε enter\n"
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr "Μεταφέρθηκαν %sB σε %s (%sB/s)\n"
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr "Παρακαλώ δώστε ένα όνομα για το Δίσκο, όπως 'Debian 2.1r1 Disk 1'"
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr "Παρακαλώ τοποθετήστε ένα Δίσκο στον οδηγό και πατήστε enter"
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr "Κατασκευή δομών δεδομένων"
diff --git a/po/en_AU.po b/po/en_AU.po
new file mode 100644
index 0000000..3dc30fb
--- /dev/null
+++ b/po/en_AU.po
@@ -0,0 +1,660 @@
+# English (Australia) translation for update-manager
+# Copyright (c) (c) 2006 Canonical Ltd, and Rosetta Contributors 2006
+# This file is distributed under the same license as the update-manager package.
+# David Symons <david.symons@liberatedcomputing.net>, 2006.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-16 04:01+0000\n"
+"Last-Translator: David Satchell <david@davidsatchell.net>\n"
+"Language-Team: English (Australia) <en_AU@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "CD-ROM with Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "CD-ROM with Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+#| msgid "Ubuntu 4.10 'Warty Warthog'"
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "CD-ROM with Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "CD-ROM with Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "CD-ROM with Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "CD-ROM with Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "CD-ROM with Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "CD-ROM with Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "CD-ROM with Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "CD-ROM with Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "CD-ROM with Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "Community maintained"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Restricted software"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "CD-ROM with Ubuntu 6.10 'Edgy Eft'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "Community maintained Open Source software"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "Community maintained (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "Community maintained Open Source software"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Non-free drivers"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Proprietary drivers for devices"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Restricted software (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "CD-ROM with Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Important security updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Recommended updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "Proposed updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "Backported updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "CD-ROM with Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.10 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.10 Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 Backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "CD-ROM with Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Officially supported"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ubuntu 5.04 Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.04 Backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "Community maintained (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Non-free (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "CD-ROM with Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Restricted copyright"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ubuntu 4.10 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Ubuntu 4.10 Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 4.10 Backports"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Proposed updates"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "Important security updates"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "Debian \"Etch\" (testing)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian \"Sid\" (unstable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "DFSG-compatible Software with Non-Free Dependencies"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Non-DFSG-compatible Software"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Server for %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Main server"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Custom servers"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, fuzzy, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Downloading file %li of %li with %s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, fuzzy, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Downloading file %li of %li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Details"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr ""
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "The list of changes is not available"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+#, fuzzy
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Failed to download the list of changes. Please check your Internet "
+"connection."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "Can't install '%s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "An essential package would have to be removed"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/en_CA.po b/po/en_CA.po
new file mode 100644
index 0000000..d272067
--- /dev/null
+++ b/po/en_CA.po
@@ -0,0 +1,681 @@
+# Canadian English translation for update-manager
+# Copyright (C) 2005 Adam Weinberger and the GNOME Foundation
+# This file is distributed under the same licence as the update-manager package.
+# Adam Weinberger <adamw@gnome.org>, 2005.
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-16 04:06+0000\n"
+"Last-Translator: Adam Weinberger <adamw@gnome.org>\n"
+"Language-Team: Canadian English <adamw@gnome.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+#, fuzzy
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 5.04 Updates"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "Community maintained (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+#, fuzzy
+msgid "Restricted software"
+msgstr "Contributed software"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+#, fuzzy
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "Community maintained (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "Community maintained (Universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "Community maintained (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+#, fuzzy
+msgid "Non-free drivers"
+msgstr "Non-free (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+#, fuzzy
+msgid "Restricted software (Multiverse)"
+msgstr "Non-free (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+#, fuzzy
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+#, fuzzy
+msgid "Important security updates"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "_Install"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "_Install"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+#, fuzzy
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+#, fuzzy
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+#, fuzzy
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+#, fuzzy
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.04 Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+#, fuzzy
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.04 Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+#, fuzzy
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+#, fuzzy
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+#, fuzzy
+msgid "Officially supported"
+msgstr "Officially supported"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+#, fuzzy
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+#, fuzzy
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ubuntu 5.04 Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+#, fuzzy
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.04 Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+#, fuzzy
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "Community maintained (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Non-free (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+#, fuzzy
+msgid "No longer officially supported"
+msgstr "Officially supported"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Restricted copyright"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ubuntu 4.10 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+#, fuzzy
+msgid "Ubuntu 4.10 Updates"
+msgstr "Ubuntu 5.04 Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+#, fuzzy
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 5.04 Updates"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian Stable Security Updates"
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian Stable Security Updates"
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian Stable Security Updates"
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian Stable Security Updates"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian Stable Security Updates"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+#, fuzzy
+msgid "Proposed updates"
+msgstr "_Install"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr ""
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr ""
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr ""
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr ""
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+#, fuzzy
+msgid "Details"
+msgstr "<b>Details</b>"
+
+#: ../apt/progress/gtk2.py:428
+#, fuzzy
+msgid "Starting..."
+msgstr "Settings"
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+#, fuzzy
+msgid "The list of changes is not available"
+msgstr "There is a new release of Ubuntu available!"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+#, fuzzy
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Failed to download changes. Please check if there is an active internet "
+"connection."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, python-format
+msgid "Cannot install '%s'"
+msgstr ""
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr ""
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/eo.po b/po/eo.po
new file mode 100644
index 0000000..648006a
--- /dev/null
+++ b/po/eo.po
@@ -0,0 +1,649 @@
+# Esperanto translation for update-manager
+# Copyright (c) 2006 Canonical Ltd, and Rosetta Contributors 2006
+# This file is distributed under the same license as the update-manager package.
+# Ed GLEZ <herzo2@gmail.com>, 2006.
+# Aisano < >, 2010.
+# Patrick (Petriko) OUDEJANS < >, 2010.
+# Roĉjo HUURMAN < >, 2010.
+# Michael MORONI < >, 2009, 2011.
+# Kristjan SCHMIDT <kristjan.schmidt@googlemail.com>, 2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:42+0200\n"
+"PO-Revision-Date: 2012-06-11 09:54+0000\n"
+"Last-Translator: Michael Moroni <michael.moroni@mailoo.org>\n"
+"Language-Team: Esperanto <ubuntu-l10n-eo@lists.launchpad.net>\n"
+"Language: eo\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-06-11 09:56+0000\n"
+"X-Generator: Launchpad (build 15376)\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 12.04 'Precise Pangolin'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "KD kun Ubuntu 12.04 'Precise Pangolin'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 11.10 'Oneiric Ocelot'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "KD kun Ubuntu 11.10 'Oneiric Ocelot'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 11.04 'Natty Narwhal'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "KD kun Ubuntu 11.04 'Natty Narwhal'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 10.10 'Maverick Meerkat'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "KD kun Ubuntu 10.10 'Maverick Meerkat'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr "Partneroj de Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr "Programaro pakita de Canonical por siaj partneroj"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr "Ĉi tiu programaro ne estas parto de Ubuntu."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr "Sendepende"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr "Ofertitaj de eksteraj programistoj"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr "Programaro ofertita de eksteraj programistoj"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 10.04 'Lucid Lynx'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "KD kun Ubuntu 10.04 'Lucid Lynx'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 9.10 'Karmic Koala'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "KD kun Ubuntu 9.10 'Karmic Koala'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 9.04 'Jaunty Jackalope'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "KD kun Ubuntu 9.04 'Jaunty Jackalope'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 8.10 'Intrepid Ibex'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "KD kun Ubuntu 8.10 'Intrepid Ibex'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 8.04 'Hardy Heron'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "KD kun Ubuntu 8.04 'Hardy Heron'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 7.10 'Gutsy Gibbon'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "KD kun Ubuntu 7.10 'Gutsy Gibbon'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 7.04 'Feisty Fawn'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "KD kun Ubuntu 7.04 'Feisty Fawn'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr "Prizorgata de komunumo"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Limigita programaro"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "KD kun Ubuntu 6.10 'Edgy Eft'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+msgid "Canonical-supported free and open-source software"
+msgstr "Libera kaj malfermitkoda programaro subtenata de Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr "Prizorgata de komunumo (universo)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+msgid "Community-maintained free and open-source software"
+msgstr "Libera kaj malfermitkoda programaro prizorgata de komunumo"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Neliberaj peliloj"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Fermitkoda peliloj por aparatoj"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Limigita programaro (multiverso)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "Programaro limigita pro kopirajto aŭ leĝaj temoj"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "KD kun Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Gravaj ĝisdatigoj pri sekureco"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Rekomenditaj ĝisdatigoj"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr "Antaŭ-eldonataj ĝisdatigoj"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+msgid "Unsupported updates"
+msgstr "Nesubtenataj ĝisdatigoj"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "KD kun Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Sekurecaj ĝisdatigoj de Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ĝisdatigoj de Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Retroportoj de Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "KD kun Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Oficiale subtenata"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Sekurecaj ĝisdatigoj de Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ĝisdatigoj de Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Retroportoj de Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr "Prizorgata de komunumo (universo)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Mallibera (multiverso)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "KD kun Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Ne plu oficiale subtenata"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Limigita kopirajto"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Sekurecaj ĝisdatigoj de Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Ĝisdatigoj de Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Retroportoj de Ubuntu 4.10"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr "Debiano 7 'Wheezy' "
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debiano 6.0 'Squeeze' "
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debiano 5.0 'Lenny' "
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+msgid "Debian 4.0 'Etch'"
+msgstr "Debiano 4.0 'Etch'"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debiano 3.1 'Sarge'"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Proponitaj ĝisdatigoj"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+msgid "Security updates"
+msgstr "Sekurecaj ĝisdatigoj"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr "Aktuala stabila eldono de Debiano"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr "Testado de Debiano"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debiano 'Sid' (nestabila)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "DFSG-kongrua programaro kun malliberaj dependecoj"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "DFSG-nekongruaj programaroj"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Servilo por %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Ĉefa servilo"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Propraj serviloj"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Elŝutanta dosieron %(current)li el %(total)li per %(speed)s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Elŝutanta dosieron %(current)li el %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Detaloj"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr "Komencanta..."
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr "Kompleta"
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr "Nevalida unikodaĵo en priskribo por '%s' (%s). Bonvole raportu."
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "La listo de ŝanĝoj ne disponeblas"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+"La listo de ŝanĝoj ankoraŭ ne disponeblas.\n"
+"\n"
+"Bonvole uzu http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"ĝis kiam la ŝanĝoj disponebligos aŭ provu denove poste."
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Elŝutado de listo de ŝanĝoj fiaskis. \n"
+"Bonvole kontrolu vian interretan konekton."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr "Listo de dosieroj de '%s' ne legeblas"
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr "Listo de kontroldosieroj por '%s' ne legeblas"
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr "Dependeco ne plenumeblas: %s\n"
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr "Ĝi konfliktas kun la instalita pakaĵo '%s'"
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+"Ĝi malfunkciigas la dependaĵon %(depname)s (%(deprelation)s %(depversion)s) "
+"de la ekzistanta pakaĵo '%(pkgname)s'"
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+"Ĝi malfunkciigas la konflikton de la ekzistanta pakaĵo '%(pkgname)s': "
+"%(targetpkg)s (%(comptype)s %(targetver)s)"
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+"Ĝi malfunkciigas la ekzistantan pakaĵon '%(pkgname)s' kiu konfliktas kun "
+"'%(targetpkg)s' sed la '%(debfile)s' ofertas ĝin per '%(provides)s'"
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr "Neniu kampo pri arĥitekturo en la pakaĵo"
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr "Malkorekta arĥitekturo: '%s'"
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr "Pli nova versio estas jam instalita"
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr "Plenumado de ĉiuj dependecoj fiaskis (difektita kaŝmemoro)"
+
+#: ../apt/debfile.py:519
+#, python-format
+msgid "Cannot install '%s'"
+msgstr "'%s' ne instaleblas"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+"Aŭtomate malpakita:\n"
+"\n"
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr "Aŭtomate konvertita al presebla ascii:\n"
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr "Instali kunmet-dependecojn por fontpakaĵo '%s', kiu kunmetas %s\n"
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr "Esenca pakaĵo estus forigita"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr "%c%s... Farita"
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr "Trafo "
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr "Ign "
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr "Era "
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr "Aki:"
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr " [laboranta]"
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+"Ŝanĝo de datumportilo: bonvole enmetu la diskon nomatan\n"
+" '%s'\n"
+"en la diskingon '%s' kaj presu la enigan klavon\n"
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr "Prenitaj %sB en %s (%sB/s)\n"
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+"Bonvole provizi nomon al ĉi tiu disko, ekzemple 'Disko 1 de Debiano 2.1r1'"
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr "Bonvole enmetu diskon en la diskingon kaj presu la enigan klavon"
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr "Konstruanta datumstrukturojn"
+
+#~ msgid "Python-debian module not available"
+#~ msgstr "Modulo Python-debian ne haveblas"
+
+#~ msgid "Community-maintained Open Source software"
+#~ msgstr "Komunume prizorgata malfermitkoda programaro"
+
+#~ msgid "Canonical-supported Open Source software"
+#~ msgstr "Malfermitkoda programaro subtenata de Canonical"
diff --git a/po/es.po b/po/es.po
new file mode 100644
index 0000000..1611319
--- /dev/null
+++ b/po/es.po
@@ -0,0 +1,663 @@
+# python-apt po translation to Spanish
+# Copyright (C) 2004 - 2012 Software in the Public Interest
+# This file is distributed under the same license as the python-apt package.
+#
+# Changes:
+# - Initial translation
+# 2004 Michiel Sikkes
+# Jorge Bernal <koke@amedias.org>, 2005.
+# Jorge Bernal <koke@sindominio.net>, 2005.
+# - Updates
+# Omar Campagne <ocampagne@gmail.com>, 2012.
+#
+# Traductores, si no conocen el formato PO, merece la pena leer la
+# documentación de gettext, especialmente las secciones dedicadas a este
+# formato, por ejemplo ejecutando:
+# info -n '(gettext)PO Files'
+# info -n '(gettext)Header Entry'
+#
+# Equipo de traducción al español, por favor lean antes de traducir
+# los siguientes documentos:
+#
+# - El proyecto de traducción de Debian al español
+# http://www.debian.org/intl/spanish/
+# especialmente las notas y normas de traducción en
+# http://www.debian.org/intl/spanish/notas
+#
+# - La guía de traducción de po's de debconf:
+# /usr/share/doc/po-debconf/README-trans
+# o http://www.debian.org/intl/l10n/po-debconf/README-trans
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: python-apt 0.8.5\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2012-06-27 17:24+0200\n"
+"Last-Translator: Omar Campagne <ocampagne@gmail.com>\n"
+"Language-Team: Debian l10n Spanish <debian-l10n-spanish@lists.debian.org>\n"
+"Language: es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Virtaal 0.7.1\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 12.04 «Precise Pangolin»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Cdrom con Ubuntu 12.04 «Precise Pangolin»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 11.10 «Oneiric Ocelot»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Cdrom con Ubuntu 11.10 «Oneiric Ocelot»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 11.04 «Natty Narwhal»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Cdrom con Ubuntu 11.04 «Natty Narwhal»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 10.10 «Maverick Meerkat»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Cdrom con Ubuntu 10.10 «Maverick Meerkat»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr "Socios de Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr "Software empaquetado por Canonical para sus socios"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr "Este software no es parte de Ubuntu."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr "Independiente"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr "Proporcionado por desarrolladores de software externos"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr "Software proporcionado por desarrolladores externos."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 10.04 «Lucid Lynx»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Cdrom con Ubuntu 10.04 «Lucid Lynx»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 9.10 «Karmic Koala»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Cdrom con Ubuntu 9.10 «Karmic Koala»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 9.04 «Jaunty Jackalope»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Cdrom con Ubuntu 9.04 «Jaunty Jackalope»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 8.10 «Intrepid Ibex»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Cdrom con Ubuntu 8.10 «Intrepid Ibex»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 8.04 «Hardy Heron»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Cdrom con Ubuntu 8.04 «Hardy Heron»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 7.10 «Gutsy Gibbon»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Cdrom con Ubuntu 7.10 «Gutsy Gibbon»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 7.04 «Feisty Fawn»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Cdrom con Ubuntu 7.04 «Feisty Fawn»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 «Edgy Eft»"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr "Mantenido por la comunidad"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Software restringido"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "Cdrom con Ubuntu 6.10 «Edgy Eft»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS «Dapper Drake»"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+msgid "Canonical-supported free and open-source software"
+msgstr "Software libre y abierto mantenido por Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr "Mantenido por la comunidad (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+msgid "Community-maintained free and open-source software"
+msgstr "Software libre y abierto mantenido por la comunidad"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Controladores no libres"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Controladores privativos para dispositivos"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Software restringido (multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "Software restringido por copyright o cuestiones legales"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Cdrom con Ubuntu 6.06 LTS «Dapper Drake»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Actualizaciones importantes de seguridad"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Actualizaciones recomendadas"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr "Actualizaciones previas a la publicación"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+msgid "Unsupported updates"
+msgstr "Actualizaciones de paquetes no oficiales"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 «Breezy Badger»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Cdrom con Ubuntu 5.10 «Breezy Badger»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Actualizaciones de seguridad de Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Actualizaciones de Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "«Backports» de Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 «Hoary Hedgehog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Cdrom con Ubuntu 5.04 «Hoary Hedgehog»"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Soportado oficialmente"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Actualizaciones de seguridad de Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Actualizaciones de Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "«Backports» de Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 «Warty Warthog»"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr "Mantenido por la comunidad (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Software no libre (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "Cdrom con Ubuntu 4.10 «Warty Warthog»"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Sin más soporte oficial"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Copyright restringido"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ubuntu 4.10 Actualizaciones de seguridad"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Actualizaciones de Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "«Backports» de Ubuntu 4.10"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 7 «Wheezy» "
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 6.0 «Squeeze» "
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 5.0 «Lenny» "
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 4.0 «Etch»"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 «Sarge»"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Actualizaciones propuestas"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+msgid "Security updates"
+msgstr "Actualizaciones de seguridad"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr "Publicación estable actual de Debian"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr "Debian testing («en pruebas»)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian «Sid» («inestable»)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "Software compatible con las «DFSG» con dependencias no libres"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Software no compatible con las «DFSG»"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Servidor para %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Servidor principal"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Servidores personalizados"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Descargando archivo %(current)li de %(total)li a %(speed)s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Descargando archivo %(current)li de %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Detalles"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr "Iniciando..."
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr "Completo"
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+"Unicode inválido en la descripción de «%s» (%s). Le rogamos que informe de "
+"ello."
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "La lista de cambios no se encuentra disponible."
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+"La lista de cambios aún no está disponible.\n"
+"\n"
+"Utilice «http://launchpad.net/ubuntu/+source/%s/%s/+changelog»\n"
+"hasta que la lista esté disponible o inténtelo en otro momento."
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Hubo un fallo al descargar la lista de cambios. \n"
+"Por favor, compruebe su conexión a Internet."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr "No se ha podido leer la lista de ficheros de «%s»"
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr "No se ha podido leer la lista de ficheros de control de «%s»"
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr "No se puede satisfacer la dependencia: %s\n"
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr "Conflictos con el paquete instalado «%s»"
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+"La dependencia «%(depname)s» rompe el paquete «%(pkgname)s» (%(deprelation)s "
+"%(depversion)s)"
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+"Conflicto con el paquete «%(pkgname)s»: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+"Conflicto con el paquete «%(pkgname)s»: «%(targetpkg)s». Pero «%(debfile)s» "
+"lo proporciona mediante «%(provides)s»"
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr "El paquete no contiene un campo «Architecture»"
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr "Arquitectura no válida «%s»"
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr "Una versión posterior ya está instalada"
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr "Fallo al satisfacer todas las dependencias (caché corrupto)"
+
+#: ../apt/debfile.py:519
+#, python-format
+msgid "Cannot install '%s'"
+msgstr "No se ha podido instalar «%s»"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+"Descomprimido automáticamente:\n"
+"\n"
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr "Convertido de forma automática a ASCII imprimible:\n"
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+"Instale las dependencias de construcción del paquete fuente «%s», que "
+"construye «%s»\n"
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr "Se desinstalaría un paquete esencial"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr "%c%s... Finalizado"
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr "Conexión"
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr "Ignorado"
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr "Error"
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr "Obtener:"
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr " [En funcionamiento]"
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+"Cambio de dispositivo: introduzca el disco denominado\n"
+"«%s»\n"
+"en el dispositivo «%s» y pulse Intro\n"
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr "Obtenidos %sB en %s (%sB/s)\n"
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr "Proporcione un nombre para este disco, como «Debian 2.1r1 Disco 1»"
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr "Introduzca un disco en el dispositivo y pulse Intro"
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr "Generando estructuras de datos"
diff --git a/po/fi.po b/po/fi.po
new file mode 100644
index 0000000..ba718ff
--- /dev/null
+++ b/po/fi.po
@@ -0,0 +1,639 @@
+# update-manager's Finnish translation.
+# Copyright (C) 2005-2006 Timo Jyrinki
+# This file is distributed under the same license as the update-manager package.
+# Timo Jyrinki <timo.jyrinki@iki.fi>, 2005-2006.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:42+0200\n"
+"PO-Revision-Date: 2012-06-11 08:55+0300\n"
+"Last-Translator: Timo Jyrinki <timo.jyrinki@iki.fi>\n"
+"Language-Team: Finnish <ubuntu-fi@lists.ubuntu.com>\n"
+"Language: fi\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 12.04 \"Precise PAngolin\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 12.04 \"Precise Pangolin\" -CD-levy"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 11.10 \"Oneiric Ocelot\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 11.10 \"Oneiric Ocelot\" -CD-levy"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 11.04 \"Natty Narwhal\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 11.04 \"Natty Narwhal\" -CD-levy"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 10.10 \"Maverick Meerkat\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 10.10 \"Maverick Meerkat\" -CD-levy"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr "Canonicalin partnerit"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr "Canonicalin pakkaamia partnereiden sovelluksia"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr "Tämä ohjelma ei ole osa Ubuntua."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr "Riippumaton"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr "Muiden kehittäjien sovelluksia"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr "Kolmansien osapuolien tarjoamia sovelluksia."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 10.04 \"Lucid Lynx\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 10.04 \"Lucid Lynx\" -CD-levy"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 9.10 \"Karmic Koala\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 9.10 \"Karmic Koala\" -CD-levy"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 9.04 \"Jaunty Jackalope\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 9.04 \"Jaunty Jackalope\" -CD-levy"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 8.10 \"Intrepid Ibex\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 8.10 \"Intrepid Ibex\" -CD-levy"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 8.04 \"Hardy Heron\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 8.04 \"Hardy Heron\" -CD-levy"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 7.10 \"Gutsy Gibbon\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 7.10 \"Gutsy Gibbon\" -CD-levy"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 7.04 \"Feisty Fawn\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 7.04 \"Feisty Fawn\" -CD-levy"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 \"Edgy Eft\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr "Yhteisön ylläpitämät"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Rajoitetut ohjelmistot"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 \"Edgy Eft\" -CD-levy"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS \"Dapper Drake\""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+msgid "Canonical-supported free and open-source software"
+msgstr "Canonicalin tukemat vapaat ja avoimen lähdekoodin ohjelmistot"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr "Yhteisön ylläpitämät (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+msgid "Community-maintained free and open-source software"
+msgstr "Yhteisön ylläpitämät vapaat ja avoimen lähdekoodin ohjelmistot"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Ei-vapaat ajurit"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Suljetut laiteajurit"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Käyttörajoitetut ohjelmistot (multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "Tekijänoikeus- tai lakiasioilla rajoitetut ohjelmistot"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS \"Dapper Drake\" -CD-levy"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Tärkeät turvallisuuspäivitykset"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Suositellut päivitykset"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr "Esijulkaistut päivitykset"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+msgid "Unsupported updates"
+msgstr "Tukemattomat päivitykset"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 \"Breezy Badger\" -CD-levy"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.10 turvallisuuspäivitykset"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.10 päivitykset"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 takaisinsovitukset"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 \"Hoary Hedgehog\" -CD-levy"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Virallisesti tuettu"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Ubuntu 5.04 turvallisuuspäivitykset"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ubuntu 5.04 päivitykset"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.04 takaisinsovitukset"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 \"Warty Warthog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr "Yhteisön ylläpitämät (universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Ei-vapaat ohjelmistot (multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 \"Warty Warthog\" -CD-levy"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Ei enää virallisesti tuettu"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Rajoitettu käyttöoikeus"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ubuntu 4.10 turvallisuuspäivitykset"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Ubuntu 4.10 päivitykset"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 4.10 takaisinsovitukset"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 7 \"Wheezy\" "
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 6.0 \"Squeeze\" "
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 5.0 \"Lenny\" "
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 4.0 \"Etch\""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Ehdotetut päivitykset"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+msgid "Security updates"
+msgstr "Turvallisuuspäivitykset"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr "Debian stable (tämänhetkinen vakaa julkaisu)"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr "Debian testing (testattava)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian \"Sid\" (epävakaa)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr ""
+"DFSG-yhteensopivat ohjelmistot joilla riippuvuuksia epävapaisiin ohjelmiin"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "DFSG-epäyhteensopivat ohjelmistot"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Palvelin maalle: %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Pääpalvelin"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Määrittele palvelin"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Noudetaan tiedostoa %(current)li/%(total)li nopeudella %(speed)s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Noudetaan tiedostoa %(current)li/%(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Yksityiskohdat"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr "Käynnistetään..."
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr "Valmis"
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+"\"%s\":n kuvauksessa virheellinen unicode-merkki %s. Ole hyvä ja raportoi "
+"virheestä kehittäjille."
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "Muutosluettelo ei ole saatavilla."
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+"Muutosluettelo ei ole vielä saatavilla.\n"
+"\n"
+"Käytä osoitetta http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"kunnes muutokset tulevat saataville, tai yritä myöhemmin uudelleen."
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Muutosluettelon nouto epäonnistui. \n"
+"Tarkista Internet-yhteytesi toimivuus."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr "Kohteen \"%s\" tiedostoluetteloa ei voi lukea"
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr "Kohteen \"%s\" hallintatiedostoja ei voi lukea"
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr "Riippuvuus ei täytettävissä: %s\n"
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr "Ristiriidassa asennetun paketin \"%s\" kanssa"
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+"Rikkoo olemassa olevan paketin '%(pkgname)s', riippuvuus %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+"Rikkoo olemassa olevan paketin '%(pkgname)s', ristiriita: %(targetpkg)s "
+"(%(comptype)s %(targetver)s)"
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+"Rikkoo olemassa olevan paketin '%(pkgname)s', joka on ristiriidassa "
+"seuraavien kanssa: '%(targetpkg)s'. Mutta '%(debfile)s' tarjoaa sen "
+"seuraavasti: '%(provides)s'"
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr "Ei Architecture-kenttää paketissa"
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr "Väärä arkkitehtuuri \"%s\""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr "Myöhempi versio on jo asennettu"
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr "Kaikkia riippuvuuksia ei voi täyttää (rikkinäinen välimuisti)"
+
+#: ../apt/debfile.py:519
+#, python-format
+msgid "Cannot install '%s'"
+msgstr "Ei voi asentaa \"%s\""
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+"Purettu automaattisesti:\n"
+"\n"
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr "Automaattisesti muunnettu tulostettavaksi asciiksi:\n"
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+"Asenna käännösriippuvuudet (Build-Dependencies) lähdepaketille \"%s\", josta "
+"%s rakennetaan\n"
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr "Välttämätön paketti jouduttaisiin poistamaan"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr "%c%s... valmis"
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr "Osuma "
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr "Ohi "
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr "Vir "
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr "Hae:"
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr " [Työskennellään]"
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+"Tallennusvälineen vaihto: syötä levy \n"
+"\"%s\"\n"
+"asemaan ”%s” ja paina Enter\n"
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr "Noudettu %sB in %s (%sB/s)\n"
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr "Syötä nimi tälle levylle, esimerkiksi \"Debian 6.0r2 levy 1\""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr "Syötä levy asemaan ja paina Enter"
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr "Kasataan tietorakenteita"
diff --git a/po/fr.po b/po/fr.po
new file mode 100644
index 0000000..6ba61f2
--- /dev/null
+++ b/po/fr.po
@@ -0,0 +1,652 @@
+# french translation of python-apt
+# Copyright (C) 2007 Hugues NAULET <hnaulet@gmail.com>
+# Copyright (C) 2005, 2007-2010, 2012 Debian French l10n team <debian-l10n-french@lists.debian.org>
+# This file is distributed under the same license as the python-apt package.
+#
+# Jean Privat <privat@lirmm.fr>, 2005.
+# Vincent Carriere <carriere_vincent@yahoo.fr>, 2005.
+# Hugues NAULET <hnaulet@gmail.com>, 2007-2009.
+# Bruno Travouillon <debian@travouillon.fr>, 2010.
+# David Prévot <david@tilapin.org>, 2012.
+msgid ""
+msgstr ""
+"Project-Id-Version: python-apt 0.7.2\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:42+0200\n"
+"PO-Revision-Date: 2012-01-12 18:20-0400\n"
+"Last-Translator: David Prévot <david@tilapin.org>\n"
+"Language-Team: French <debian-l10n-french@lists.debian.org>\n"
+"Language: fr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n > 1\n"
+"X-Generator: Lokalize 1.2\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 12.04 « Precise Pangolin »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "CD contenant Ubuntu 12.04 « Precise Pangolin »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 11.10 « Oneiric Ocelot »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "CD contenant Ubuntu 11.10 « Oneiric Ocelot »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 11.04 « Natty Narwhal »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "CD contenant Ubuntu 11.04 « Natty Narwhal »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 10.10 « Maverick Meerkat »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "CD contenant Ubuntu 10.10 « Maverick Meerkat »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr "Partenaires de Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr "Logiciel empaqueté par Canonical pour ses partenaires"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr "Ce logiciel ne fait pas partie d'Ubuntu."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr "Indépendant"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr "Fourni par des développeurs de logiciel tiers"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr "Logiciel offert par des développeurs de logiciel tiers."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 10.04 « Lucid Lynx »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "CD contenant Ubuntu 10.04 « Lucid Lynx »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 9.10 « Karmic Koala »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "CD contenant Ubuntu 9.10 « Karmic Koala »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 9.04 « Jaunty Jackalope »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "CD contenant Ubuntu 9.04 « Jaunty Jackalope »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 8.10 « Intrepid Ibex »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "CD contenant Ubuntu 8.10 « Intrepid Ibex »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 8.04 « Hardy Heron »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "CD contenant Ubuntu 8.04 « Hardy Heron »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 7.10 « Gutsy Gibbon »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "CD contenant Ubuntu 7.10 « Gutsy Gibbon »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 7.04 « Feisty Fawn »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "CD contenant Ubuntu 7.04 « Feisty Fawn »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 « Edgy Eft »"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr "Maintenu par la communauté"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Logiciel non libre"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "CD contenant Ubuntu 6.10 « Edgy Eft »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS « Dapper Drake »"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+msgid "Canonical-supported free and open-source software"
+msgstr "Logiciel libre maintenu par Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr "Maintenu par la communauté (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+msgid "Community-maintained free and open-source software"
+msgstr "Logiciel libre maintenu par la communauté"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Pilotes non libres"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Pilotes propriétaires de périphériques"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Logiciel non libre (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "Logiciel soumis au droit d'auteur ou à des restrictions légales"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "CD contenant Ubuntu 6.06 LTS « Dapper Drake »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Mises à jour de sécurité"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Mises à jour recommandées"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr "Mises à jour suggérées"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+msgid "Unsupported updates"
+msgstr "Mises à jour non gérées"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 « Breezy Badger »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "CD contenant Ubuntu 5.10 « Breezy Badger »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Mises à jour de sécurité pour Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Mises à jour pour Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Rétroportages pour Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 « Hoary Hedgehog »"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "CD contenant Ubuntu 5.04 « Hoary Hedgehog »"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Officiellement pris en charge"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Mises à jour de sécurité pour Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Mises à jour pour Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Rétroportages pour Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 « Warty Warthog »"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr "Maintenu par la communauté (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Non libre (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "CD contenant Ubuntu 4.10 « Warty Warthog »"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Suivi officiel terminé"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Copyright restreint"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Mises à jour de sécurité pour Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Mises à jour pour Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Rétroportages pour Ubuntu 4.10"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 7 « Wheezy »"
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 6.0 « Squeeze »"
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 5.0 « Lenny »"
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 4.0 « Etch »"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 « Sarge »"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Mises à jour suggérées"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+msgid "Security updates"
+msgstr "Mises à jour de sécurité"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr "Debian stable actuelle"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr "Debian « Lenny » (testing)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian « Sid » (unstable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr ""
+"Logiciel libre (selon les principes du projet Debian) dont les dépendances "
+"ne sont pas libres"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Logiciel non libre (selon les principes du projet Debian)"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Serveur pour %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Serveur principal"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Serveurs personnalisés"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Téléchargement du fichier %(current)li sur %(total)li à %(speed)s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Téléchargement du fichier %(current)li sur %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Détails"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr "Démarrage…"
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr "Terminé"
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+"Unicode incorrect dans la description de « %s » (%s). Merci de le signaler."
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "La liste des modifications n'est pas disponible"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+"La liste des modifications n'est pas encore disponible.\n"
+"\n"
+"Veuillez utiliser http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"jusqu'à ce que les changements soient disponibles ou essayer plus tard."
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Échec lors du téléchargement de la liste des modifications. \n"
+"Veuillez vérifier votre connexion Internet."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr "La liste des fichiers pour « %s » ne peut pas être lue"
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr "La liste des fichiers de contrôle pour « %s » ne peut pas être lue"
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr "La dépendance ne peut être satisfaite : %s\n"
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr "Conflit avec le paquet installé « %s »"
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+"Casse le paquet existant « %(pkgname)s » à cause de sa dépendance "
+"%(depname)s (%(deprelation)s %(depversion)s)"
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+"Casse le paquet existant « %(pkgname)s » car en conflit avec %(targetpkg)s "
+"(%(comptype)s %(targetver)s)"
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+"Casse le paquet existant « %(pkgname)s » car en conflit avec %(targetpkg)s. "
+"Mais le « %(debfile)s » le fournit à l'aide de « %(provides)s »"
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr "Aucun champ Architecture dans ce paquet"
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr "Architecture « %s » incorrecte"
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr "Une version plus récente est déjà installée"
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr "Impossible de résoudre les dépendances, le cache est corrompu."
+
+#: ../apt/debfile.py:519
+#, python-format
+msgid "Cannot install '%s'"
+msgstr "Impossible d'installer « %s »"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+"Décompression automatique :\n"
+"\n"
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr "Conversion automatique en ASCII affichable :\n"
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+"Installation des dépendances de construction pour le paquet source « %s » "
+"qui compile %s\n"
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr "Un paquet essentiel devrait être désinstallé"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr "%c%s… Terminé"
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr "Att "
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr "Ign "
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr "Err "
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr "Prendre :"
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr " [En cours]"
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+"Changement de support : veuillez insérer le disque nommé\n"
+" « %s »\n"
+"dans le lecteur « %s » et appuyer sur entrée\n"
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr "%s o téléchargés en %s (%s o/s)\n"
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+"Veuillez fournir le nom de ce disque, par exemple « Debian 2.1r1 disque 1 »"
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr "Veuillez insérer un disque dans le lecteur et appuyer sur entrée"
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr "Construction des structures de données"
+
+#~ msgid "Python-debian module not available"
+#~ msgstr "Module Python-debian non disponible"
+
+#~ msgid "This is not a valid DEB archive, missing '%s' member"
+#~ msgstr ""
+#~ "Ce n'est pas une archive « DEB » valide, le membre « %s » est absent"
diff --git a/po/gl.po b/po/gl.po
new file mode 100644
index 0000000..505ccc2
--- /dev/null
+++ b/po/gl.po
@@ -0,0 +1,661 @@
+# translation of gl.po to galician
+# translation of update-manager-gl.po to galician
+# This file is distributed under the same license as the update-manager package.
+# Copyright (c) 2004 Canonical
+# 2004 Michiel Sikkes
+# Mar Castro <mariamarcp@gmail.com>, 2006.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gl\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-19 00:43+0000\n"
+"Last-Translator: Felipe Gil Castiñeira <xil@det.uvigo.es>\n"
+"Language-Team: galician\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.10.2\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Actualizacións de Seguranza para Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Cdrom con Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Cdrom con Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+#| msgid "Ubuntu 4.10 'Warty Warthog'"
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Cdrom con Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Cdrom con Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Cdrom con Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Cdrom con Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Cdrom con Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Cdrom con Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Cdrom con Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Actualizacións de Seguranza para Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Cdrom con Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Actualizacións de Seguranza para Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Cdrom con Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 \"Edgy Eft\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "Mantido pola Comunidade"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Aplicacións restrinxidas"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "Cdrom con Ubuntu 6.10 \"Edgy Eft\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS \"Dapper Drake\""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "Software de Código Aberto soportado por Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "Mantido pola Comunidade (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "Software de Código Aberto mantido pola Comunidade"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Controladores non libres"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Controladores propietarios de dispositivos"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Software restrinxido (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "Software restrinxido por razóns de copyright ou legais"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Cdrom con Ubuntu 6.06 LTS \"Dapper Drake\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Actualizacións de seguranza importantes"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Actualizacións recomendadas"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "Actualizacións aconselladas"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "Actualizacións de backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "CD con Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Cdrom con Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Actualizacións de seguranza de Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Actualizacións de Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Actualizacións de Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Cdrom con Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Soportado oficialmente"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Actualizacións de Seguranza para Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Actualizacións para Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Backports para Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 \"Warty Warthog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "Mantido pola comunidade (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Software non libre (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "Cdrom con Ubuntu 4.10 \"Warty Warthog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Xa non se mantén oficialmente"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Copyright restrinxido"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Actualizacións de seguranza de Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Actualizacións de Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Backports para Ubuntu 4.10"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Actualizacións aconselladas"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "Actualizacións de seguranza importantes"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "Debian \"Etch\" (probas)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian \"Sid\" (inestable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "Software compatible coa DFSG con dependencias non libres"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Software non compatible coa DFSG"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Servidor desde %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Servidor principal"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Servidores personalizados"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "A descargar o ficheiro %(current)li de %(total)li con %(speed)s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "A descargar o ficheiro %(current)li de %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Detalles"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr ""
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "Non se dispón da lista de cambios"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Non se puido descargar a lista de cambios.\n"
+"Comprobe a súa conexión á Internet."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "Non se puido instalar '%s»"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "Tívose que desinstalar un paquete esencial"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/he.po b/po/he.po
new file mode 100644
index 0000000..6942f56
--- /dev/null
+++ b/po/he.po
@@ -0,0 +1,667 @@
+# translation of update-manager.HEAD.po to Hebrew
+# This file is distributed under the same license as the PACKAGE package.
+# Yuval Tanny, 2005.
+# Yuval Tanny, 2005.
+# Yuval Tanny, 2005.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER.
+# Yuval Tanny, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager.HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-16 08:48+0000\n"
+"Last-Translator: Yaniv Abir <yanivabir@gmail.com>\n"
+"Language-Team: Hebrew <he@li.org>\n"
+"Language: he\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: KBabel 1.10.2\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "עדכוני אבטחה - אובונטו 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "תקליטור אובונטו 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "אובונטו 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "תקליטור אובונטו 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+#| msgid "Ubuntu 4.10 'Warty Warthog'"
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "אובונטו 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "תקליטור אובונטו 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "אובונטו 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "תקליטור אובונטו 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "אובונטו 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "תקליטור אובונטו 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "אובונטו 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "תקליטור אובונטו 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "אובונטו 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "תקליטור אובונטו 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "אובונטו 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "תקליטור אובונטו 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "אובונטו 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "תקליטור אובונטו 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "עדכוני אבטחה - אובונטו 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "תקליטור אובונטו 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "עדכוני אבטחה - אובונטו 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "תקליטור אובונטו 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "אובונטו 6.10 \"Edgy Eft\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "מתוחזק ע\"י הקהילה"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "תוכנה בעלת הגבלות"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "תקליטור אובונטו 6.10 \"Edgy Eft\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "אובונטו 6.06 LTS \"DapperDrake\""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "תוכנות קוד פתוח הנתמכות ע\"י Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "מתוחזק ע\"י הקהילה (Universe("
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "תוכנות קוד פתוח המתוחזקות ע\"י הקהילה"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "דרייברים לא חופשיים"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "דרייברים קניינים להתקנים"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "תוכנה בעלת הגבלות (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "תקליטור אובונטו 6.06 LTS \"Dapper Drake\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "עדכוני אבטחה חשובים"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "עדכונים מומלצים"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "עדכונים מוצעים"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "עדכונים מוצעים"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "אובונטו 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "תקליטור אובונטו 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "עדכוני אבטחה - אובונטו 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "עדכונים - אובונטו 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+#, fuzzy
+msgid "Ubuntu 5.10 Backports"
+msgstr "עדכונים - אובונטו 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "אובונטו 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "תקליטור אובונטו 5.04 \"Hoary Hedgehog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "נתמך רשמית"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "עדכוני אבטחה - אובונטו 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "עדכונים - אובונטו 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+#, fuzzy
+msgid "Ubuntu 5.04 Backports"
+msgstr "עדכונים - אובונטו 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "אובונטו 4.10 \"Warty Warthog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "מתוחזק ע\"י קהילה (Universe("
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "לא-חופשי (Multiverse("
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "תקליטור אובונטו 4.10 \"Warty Warthog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "אינה נתמכת רשמית יותר"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "זכויות יוצרים מגבילות"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "עדכוני אבטחה - אובונטו 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "עדכונים - אובונטו 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+#, fuzzy
+msgid "Ubuntu 4.10 Backports"
+msgstr "עדכונים - אובונטו 5.10"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "דביאן 3.1 \"סארג'\""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "דביאן 3.1 \"סארג'\""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "דביאן בדיקה"
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "דביאן בדיקה"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "דביאן 3.1 \"סארג'\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "עדכונים מוצעים"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "עדכוני אבטחה חשובים"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+#, fuzzy
+msgid "Debian current stable release"
+msgstr "דביאן לא יציב \"סיד\""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "דביאן בדיקה"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "דביאן לא ארה\"ב (לא יציב)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr ""
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "השרת ב%s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "שרת ראשי"
+
+#: ../aptsources/distro.py:250
+#, fuzzy
+msgid "Custom servers"
+msgstr "השרת הקרוב ביותר"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, fuzzy, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "מוריד קובץ %li מתוך %li ב-%s לשנייה"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, fuzzy, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "מוריד קובץ %li מתוך %li ב-%s לשנייה"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "פרטים"
+
+#: ../apt/progress/gtk2.py:428
+#, fuzzy
+msgid "Starting..."
+msgstr "הגדרות"
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "רשימת השינויים אינה זמינה"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+#, fuzzy
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr "נכשל בהורדת רשימת השינויים. אנא בדוק אם החיבור לאינטרנט עובד."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "לא ניתן להתקין את \"%s\""
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "חבילה חיונית תוסר בלית ברירה"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/hr.po b/po/hr.po
new file mode 100644
index 0000000..66c76e3
--- /dev/null
+++ b/po/hr.po
@@ -0,0 +1,660 @@
+# Croatian translation for update-manager
+# Copyright (c) (c) 2006 Canonical Ltd, and Rosetta Contributors 2006
+# This file is distributed under the same license as the update-manager package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2006.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-18 19:37+0000\n"
+"Last-Translator: Ante Karamatić <ivoks@grad.hr>\n"
+"Language-Team: Croatian <hr@li.org>\n"
+"Language: hr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 5.04 sigurnosne nadogradnje"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "CDROM s Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 4.10 'Wart Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Cdrom sa Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+#| msgid "Ubuntu 4.10 'Warty Warthog'"
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 4.10 'Wart Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Cdrom sa Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 4.10 'Wart Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Cdrom sa Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Cdrom sa Ubuntu 5.04 ' Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 4.10 'Wart Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Cdrom sa Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 4.10 'Wart Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Cdrom sa Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Cdrom sa Ubuntu 5.04 ' Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Cdrom sa Ubuntu 5.04 ' Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 5.04 sigurnosne nadogradnje"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "CDROM s Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 5.04 sigurnosne nadogradnje"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "CDROM s Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "Održavani od strane zajednice"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Neslobodni softver"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "CDROM sa Ubuntu 6.10 'Edgy Eft'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "Službeno podržani Open Source softver"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "Održavani od strane zajednice (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "Softver održavan od strane zajednice"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Neslobodni pogonski programi"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Neslobodni upogonitelji za uređaje"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Ograničeni softver (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "Softver ograničen autorskim pravom ili legalnim pitanjima"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "CDROM s Ubuntu 6.06 'Dapper Drake'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Važne sigurnosne nadogradnje"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Preporučene nadogradnje"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "Predložene nadogradnje"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "Backport nadogradnje"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "CDROM s Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.10 sigurnosne nadogradnje"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.10 osvježenja"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 backporti"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Cdrom sa Ubuntu 5.04 ' Hoary Hedgehog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Službeno podržani"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Ubuntu 5.04 sigurnosne nadogradnje"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ubuntu 5.04 nadogradnje"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.04 backporti"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Wart Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "Održavani od strane zajednice (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Neslobodni (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "Cdrom sa Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Više nisu službeno podržani"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Ograničeno autorsko pravo"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ubuntu 4.10 sigurnosne nadogradnje"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Ubuntu 4.10 osvježenja"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 4.10 backports"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Predložene nadogradnje"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "Važne sigurnosne nadogradnje"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "Debian \"Etch\" (testni)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian \"Sid\" (nestabilni)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "DFSG-kompatibilni programi sa neslobodnim ovisnostima"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "DFSG-nekompatibilni programi"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Poslužitelj za %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Glavni poslužitelj"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Osobni poslužitelji"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Preuzimanje datoteke %(current)li od %(total)li brzinom %(speed)s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Preuzimam datoteku %(current)li od %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Detalji"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr ""
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "Popis promjena nije dostupan."
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Preuzimanje popisa promjena nije uspjelo. \n"
+"Molim, provjerite svoju internet vezu."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "Ne mogu instalirati '%s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "Bitan paket bi morao biti uklonjen"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/hu.po b/po/hu.po
new file mode 100644
index 0000000..8045f25
--- /dev/null
+++ b/po/hu.po
@@ -0,0 +1,647 @@
+# Hungarian translation of update-manager
+# This file is distributed under the same license as the update-manager package.
+# Copyright (C) 2005, 2007, Free Software Foundation, Inc.
+#
+# Gabor Kelemen <kelemeng@gnome.hu>, 2005, 2007.
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager.HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:42+0200\n"
+"PO-Revision-Date: 2012-06-11 18:21+0000\n"
+"Last-Translator: Gabor Kelemen <kelemeng@gnome.hu>\n"
+"Language-Team: Hungarian <gnome@gnome.hu>\n"
+"Language: hu\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-06-11 18:32+0000\n"
+"X-Generator: Launchpad (build 15376)\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 12.04 „Precise Pangolin”"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Az Ubuntu 12.04 „Precise Pangolin”-t tartalmazó CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 11.10 „Oneiric Ocelot”"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Az Ubuntu 11.10 „Oneiric Ocelot”-ot tartalmazó CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 11.04 „Natty Narwhal”"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Az Ubuntu 11.04 „Natty Narwhal”-t tartalmazó CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 10.10 „Maverick Meerkat”"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Az Ubuntu 10.10 „Maverick Meerkat”-ot tartalmazó CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr "Canonical partnerek"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr "A Canonical által partnereinek csomagolt szoftverek"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr "Ezek a szoftverek nem részei az Ubuntunak."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr "Független"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr "Külső szoftverfejlesztők által biztosított"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr "Külső szoftverfejlesztők által biztosított szoftverek."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 10.04 „Lucid Lynx”"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Az Ubuntu 10.04 „Lucid Lynx”-et tartalmazó CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 9.10 „Karmic Koala”"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Az Ubuntu 9.10 „Karmic Koala”-t tartalmazó CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 9.04 „Jaunty Jackalope”"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Az Ubuntu 9.04 „Jaunty Jackalope”-ot tartalmazó CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 8.10 „Intrepid Ibex”"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Az Ubuntu 8.10 „Intrepid Ibex”-et tartalmazó CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 8.04 „Hardy Heron”"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Az Ubuntu 8.04 „Hardy Heron”-t tartalmazó CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 7.10 „Gutsy Gibbon”"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Az Ubuntu 7.10 „Gutsy Gibbon”-t tartalmazó CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 7.04 „Feisty Fawn”"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Az Ubuntu 7.04 „Feisty Fawn”-t tartalmazó CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 „Edgy Eft”"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr "Közösségi karbantartású"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Nem-szabad"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "Az Ubuntu 6.10 „Edgy Eft” CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS „Dapper Drake”"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+msgid "Canonical-supported free and open-source software"
+msgstr "A Canonical által támogatott szabad és nyílt forrású szoftverek"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr "Közösségi karbantartású (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+msgid "Community-maintained free and open-source software"
+msgstr "A közösség által karbantartott szabad és nyílt forrású szoftverek"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Nem-szabad meghajtók"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Szabadalmazott eszközmeghajtók"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Nem-szabad szoftverek (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "Szerzői vagy egyéb jogi problémák miatt korlátozott szoftver"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Az Ubuntu 6.06 LTS „Dapper Drake”-et tartalmazó CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Fontos biztonsági frissítések"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Ajánlott frissítések"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr "Előzetesen kiadott frissítések"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+msgid "Unsupported updates"
+msgstr "Nem támogatott frissítések"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Az Ubuntu 5.10 „Breezy Badger”-t tartalmazó CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.10 biztonsági frissítések"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.10 frissítések"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 visszaportolt csomagok"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 „Hoary Hedgehog”"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Az Ubuntu 5.04 „Hoary Hedgehog”-ot tartalmazó CD-ROM"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Hivatalosan támogatott"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Ubuntu 5.04 biztonsági frissítések"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ubuntu 5.04 frissítések"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.04 visszaportolt csomagok"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 „Warty Warthog”"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr "Közösségi karbantartású (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Nem-szabad (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "Az Ubuntu 4.10 „Warty Warthog”-ot tartalmazó CD-ROM"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Hivatalosan már nem támogatott"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Szerzői jogi korlátozás alatt"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ubuntu 4.10 biztonsági frissítések"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Ubuntu 4.10 frissítések"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 4.10 visszaportolt csomagok"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 7 „Wheezy” "
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 6.0 „Squeeze” "
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 5.0 „Lenny” "
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 4.0 „Etch”"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 „Sarge”"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Javasolt frissítések"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+msgid "Security updates"
+msgstr "Biztonsági frissítések"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr "Jelenlegi stabil Debian kiadás"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr "Debian – tesztelés alatt"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian „Sid” (instabil)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "DFSG-kompatibilis szoftver nem-szabad függőségekkel"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Nem DFSG-kompatibilis szoftver"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Kiszolgáló a következőhöz: %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Fő kiszolgáló"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Egyéni kiszolgálók"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr ""
+"%(current)li. fájl letöltése, összesen: %(total)li, sebesség: %(speed)s/mp"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "%(current)li. fájl letöltése, összesen: %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "<b>Részletek</b>"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr "Indítás…"
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr "Kész"
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+"Érvénytelen unicode karakter a(z) „%s” leírásában (%s). Kérem jelentse."
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "A módosítások listája nem érhető el"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+"A változtatások listája még nem érhető el.\n"
+"\n"
+"Használja a http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"oldalt, míg nem válik hozzáférhetővé, vagy próbálja meg később."
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"A módosítások listájának letöltése meghiúsult.\n"
+"Ellenőrizze az internetkapcsolatát."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr "„%s” fájljainak listája nem olvasható"
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr "„%s” vezérlőfájljainak listája nem olvasható"
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr "A következő függőség nem elégíthető ki: %s\n"
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr "Ütközik a következő telepített csomaggal: „%s”"
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+"„%(pkgname)s” csomag törik „%(depname)s” függősége által (%(deprelation)s "
+"%(depversion)s)"
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+"Megsérti a meglévő „%(pkgname)s” csomag függőségeit; ütközés: %(targetpkg)s "
+"(%(comptype)s %(targetver)s)"
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+"Megsérti a meglévő „%(pkgname)s” csomag függőségeit; ütközés: "
+"„%(targetpkg)s”. Azonban a(z) „%(debfile)s” biztosítja ezen keresztül: "
+"„%(provides)s”"
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr "A csomagban nincs Architecture mező"
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr "Rossz architektúra: „%s”"
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr "Már telepítve van egy újabb verzió"
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr "Nem elégíthető ki minden függőség (a gyorsítótár sérült)"
+
+#: ../apt/debfile.py:519
+#, python-format
+msgid "Cannot install '%s'"
+msgstr "„%s” nem telepíthető"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+"Automatikusan kibontva:\n"
+"\n"
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr "Automatikusan nyomtatható ascii-vé konvertálva:\n"
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+"„%s” csomag fordítási függőségeinek telepítése, ami a(z) %s csomagot építi\n"
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr "Egy alapvető csomag törlődne"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr "%c%s... Kész"
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr "Találat "
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr "Mellőz "
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr "Hiba "
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr "Letöltés:"
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr " [Folyamatban]"
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+"Helyezze be a(z)\n"
+" „%s”\n"
+"címkéjű lemezt a(z) %s meghajtóba, és nyomja meg az Entert\n"
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr "%sB letöltve %s alatt (%sB/s)\n"
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr "Adja meg a lemez nevét, például „Debian 2.1r1 1. lemez”"
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr "Helyezzen be egy lemezt a meghajtóba, és nyomja meg az Entert"
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr "Adatstruktúrák építése"
+
+#~ msgid "Community-maintained Open Source software"
+#~ msgstr "Közösségi karbantartású nyílt forrású szoftverek"
+
+#~ msgid "Canonical-supported Open Source software"
+#~ msgstr "A Canonical által támogatott nyílt forrású szoftverek"
+
+#~ msgid "Python-debian module not available"
+#~ msgstr "A Python-debian modul nem érhető el"
diff --git a/po/id.po b/po/id.po
new file mode 100644
index 0000000..5698096
--- /dev/null
+++ b/po/id.po
@@ -0,0 +1,638 @@
+# Indonesian translation for python-apt
+# Copyright (c) (c) 2006 Canonical Ltd, and Rosetta Contributors 2006
+# This file is distributed under the same license as the python-apt package.
+# Andy Apdhani <imtheface@gmail.com>, 2006.
+# Andika Triwidada <andika@gmail.com>, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: python-apt\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:42+0200\n"
+"PO-Revision-Date: 2012-06-11 01:59+0700\n"
+"Last-Translator: Andika Triwidada <andika@gmail.com>\n"
+"Language-Team: Indonesian <id@li.org>\n"
+"Language: id\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"X-Poedit-Language: Indonesian\n"
+"X-Poedit-Country: INDONESIA\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 12.04 'Precise Pangolin'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Cdrom dengan Ubuntu 12.04 'Precise Pangolin'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 11.10 'Oneiric Ocelot'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Cdrom dengan Ubuntu 11.10 'Oneiric Ocelot'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 11.04 'Natty Narwhal'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Cdrom dengan Ubuntu 11.04 'Natty Narwhal'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 10.10 'Maverick Meerkat'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Cdrom dengan Ubuntu 10.10 'Maverick Meerkat'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr "Partner Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr "Perangkat lunak yang dipaketkan oleh Canonical bagi partner mereka"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr "Perangkat lunak ini bukan bagian dari Ubuntu."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr "Independen"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr "Disediakan oleh para pengembang perangkat lunak pihak ketiga"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr "Perangkat lunak ditawarkan oleh para pengembang pihak ketiga."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 10.04 'Lucid Lynx'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Cdrom dengan Ubuntu 10.04 'Lucid Lynx'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 9.10 'Karmic Koala'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Cdrom dengan Ubuntu 9.10 'Karmic Koala'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 9.04 'Jaunty Jackalope'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Cdrom dengan Ubuntu 9.04 'Jaunty Jackalope'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 8.10 'Intrepid Ibex'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Cdrom dengan Ubuntu 8.10 'Intrepid Ibex'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 8.04 'Hardy Heron'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Cdrom dengan Ubuntu 8.04 'Hardy Heron'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 7.10 'Gutsy Gibbon'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Cdrom dengan Ubuntu 7.10 'Gutsy Gibbon'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 7.04 'Feisty Fawn'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Cdrom dengan Ubuntu 7.04 'Feisty Fawn'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr "Dikelola oleh komunitas"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Perangkat lunak terbatas"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "Cdrom dengan Ubuntu 6.10 'Edgy Eft'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+msgid "Canonical-supported free and open-source software"
+msgstr "Perangkat lunak open-source dan bebas yang didukung oleh Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr "Dikelola oleh komunitas (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+msgid "Community-maintained free and open-source software"
+msgstr "Perangkat lunak open-source dan bebas yang dikelola oleh komunitas"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Driver tidak-bebas"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Driver proprietary bagi perangkat"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Perangkat lunak terbatas (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "Perangkat lunak yang terbatas karena masalah hak cipta atau hukum"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Cdrom dengan Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Pemutakhiran keamanan penting"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Pemutakhiran yang disarankan"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr "Pemutakhira prarilis"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+msgid "Unsupported updates"
+msgstr "Pemutakhiran yang tak didukung"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Cdrom dengan Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Pemutakhiran Keamanan Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Pemutakhiran Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 Backport"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Cdrom dengan Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Resmi didukung"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Pemutakhiran Keamanan Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Pemutakhiran Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.04 Backport"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr "Dikelola oleh komunitas (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Tidak-bebas (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "Cdrom dengan Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Tak lagi didukung secara resmi"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Hak cipta terbatas"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Pemutakhiran Keamanan Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Pemutakhiran Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 4.10 Backport"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 7 'Wheezy' "
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 6.0 'Squeeze' "
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 5.0 'Lenny' "
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 4.0 'Etch'"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 'Sarge'"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Pemutakhiran yang diusulkan"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+msgid "Security updates"
+msgstr "Pemutakhiran keamanan"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr "Rilis stabil Debian saat ini"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr "Debian testing"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian 'Sid' (unstable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr ""
+"Perangkat lunak yang kompatibel dengan DFSG tapi tergantung pada Perangkat "
+"Lunak Tidak-Bebas"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Perangkat Lunak yang tidak kompatibel dengan DFSG"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Server untuk %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Server utama"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Server gubahan"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Mengunduh berkas %(current)li dari %(total)li dalam %(speed)s/dt"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Mengunduh berkas %(current)li dari %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Rincian"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr "Memulai..."
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr "Komplit"
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr "Unicode tak valid dalam deskripsi bagi '%s' (%s). Mohon laporkan."
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "Senarai dari perubahan tak tersedia"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+"Senarai perubahan belum tersedia.\n"
+"\n"
+"Silakan pakai http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"sampai perubahan menjadi tersedia atau coba lagi nanti"
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Gagal mengunduh senarai dari perubahan. \n"
+"Silakan periksa koneksi Internet Anda."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr "Senarai berkas bagi '%s' tak dapat dibaca"
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr "Senarai berkas kendali bagi '%s' tak dapat dibaca"
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr "Kebergantungan tak dapat dipenuhi: %s\n"
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr "Konflik dengan paket terpasang '%s'"
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+"Merusak kebergantungan %(depname)s (%(deprelation)s %(depversion)s) dari "
+"paket '%(pkgname)s' yang telah ada"
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+"Merusak paket '%(pkgname)s' yang telah ada, konflik: %(targetpkg)s "
+"(%(comptype)s %(targetver)s)"
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+"Merusak paket '%(pkgname)s' yang telah ada, yang konflik: %(targetpkg)s. "
+"Tapi '%(debfile)s' menyediakannya melalui: '%(provides)s'"
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr "Tak ada ruas Architecture dalam paket"
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr "Arsitektur '%s' salah"
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr "Versi lebih baru telah terpasang"
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr "Gagal memenuhi semua kebergantungan (singgahan rusak)"
+
+#: ../apt/debfile.py:519
+#, python-format
+msgid "Cannot install '%s'"
+msgstr "Tak bisa memasang '%s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+"Membuka kompresi secara otomatis:\n"
+"\n"
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr "Otomatis dikonversi ke ascii yang dapat dicetak:\n"
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr "Memasang Build-Dependencies bagi paket sumber '%s' yang membangun %s\n"
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr "Paket esensial akan dihapus"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr "%c%s... Usai"
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr "Hit "
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr "Ign "
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr "Err "
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr "Ambil:"
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr " [Bekerja]"
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+"Media berubah: mohon masukkan cakram berlabel\n"
+"'%s'\n"
+"ke drive '%s' dan tekan enter\n"
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr "Diambil %sB dalam %s (%sB/s)\n"
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr "Mohon beri nama Cakram ini, seperti misalnya 'Debian 2.1r1 Disk 1'"
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr "Mohon masukkan Cakram ke dalam drive dan menekan enter"
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr "Membangun struktur data"
diff --git a/po/it.po b/po/it.po
new file mode 100644
index 0000000..2981eb3
--- /dev/null
+++ b/po/it.po
@@ -0,0 +1,662 @@
+# Italian translation for update-manager
+# Copyright (c) (c) 2005 Canonical Ltd, and Rosetta Contributors 2005
+# This file is distributed under the same license as the update-manager package.
+# Fabio Marzocca <thesaltydog@gmail.com>, 2005.
+#
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-22 10:13+0000\n"
+"Last-Translator: Luca Ferretti <elle.uca@libero.it>\n"
+"Language-Team: Italian <it@li.org>\n"
+"Language: it\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 5.04 - Aggiornamenti di sicurezza"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "CD-ROM con Ubuntu 5.10 «Breezy Badger»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 4.10 «Warty Warthog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "CD-ROM con Ubuntu 4.10 «Warty Warthog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+#| msgid "Ubuntu 4.10 'Warty Warthog'"
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 4.10 «Warty Warthog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "CD-ROM con Ubuntu 4.10 «Warty Warthog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 4.10 «Warty Warthog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "CD-ROM con Ubuntu 4.10 «Warty Warthog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 5.04 «Hoary Hedgehog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "CD-ROM con Ubuntu 5.04 «Hoary Hedgehog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 4.10 «Warty Warthog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "CD-ROM con Ubuntu 4.10 «Warty Warthog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 4.10 «Warty Warthog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "CD-ROM con Ubuntu 4.10 «Warty Warthog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 5.04 «Hoary Hedgehog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "CD-ROM con Ubuntu 5.04 «Hoary Hedgehog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 5.04 «Hoary Hedgehog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "CD-ROM con Ubuntu 5.04 «Hoary Hedgehog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 5.04 - Aggiornamenti di sicurezza"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "CD-ROM con Ubuntu 5.10 «Breezy Badger»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 5.04 - Aggiornamenti di sicurezza"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "CD-ROM con Ubuntu 5.10 «Breezy Badger»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 «Edgy Eft»"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "Mantenuto dalla comunità"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Software con restrizioni"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "CD-ROM con Ubuntu 6.10 «Edgy Eft»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS «Dapper Drake»"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "Software open source supportato da Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "Mantenuto dalla comunità (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "Software open source mantenuto dalla comunità"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Driver non liberi"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Driver proprietari per i dispositivi"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Software con restrizioni (multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "Software con restrizioni per copyright o motivi legali"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "CD-ROM con Ubuntu 6.06 LTS «Drapper Drake»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Aggiornamenti di sicurezza importanti"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Aggiornamenti raccomandati"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "Aggiornamenti proposti"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "Aggiornamenti di backport"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "CD-ROM con Ubuntu 5.10 «Breezy Badger»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.10 - Aggiornamenti di sicurezza"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.10 - Aggiornamenti"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Backport di Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 «Hoary Hedgehog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "CD-ROM con Ubuntu 5.04 «Hoary Hedgehog»"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Supportati ufficialmente"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Ubuntu 5.04 - Aggiornamenti di sicurezza"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ubuntu 5.04 - Aggiornamenti"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Backport per Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 «Warty Warthog»"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "Mantenuti dalla comunità (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Non libero (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "CD-ROM con Ubuntu 4.10 «Warty Warthog»"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Software non più supportato ufficialmente"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Copyright con restrizioni"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ubuntu 4.10 - Aggiornamenti di sicurezza"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Aggiornamenti di Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Backport per Ubuntu 4.10"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Aggiornamenti proposti"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "Aggiornamenti di sicurezza importanti"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+#, fuzzy
+msgid "Debian current stable release"
+msgstr "Debian Unstable"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "Debian \"Etch\" (testing)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian \"Sid\" (Unstable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "Software compatibile con le DFSG con dipendenze non libere"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Software non compatibile con le DFSG"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Server in %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Server principale"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Server personalizzati"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Scaricamento del file %(current)li di %(total)li a %(speed)s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Scaricamento del file %(current)li di %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Dettagli"
+
+#: ../apt/progress/gtk2.py:428
+#, fuzzy
+msgid "Starting..."
+msgstr "Impostazioni"
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "L'elenco dei cambiamenti non è disponibile"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Fallito lo scaricamento dell'elenco dei cambiamenti. \n"
+"Verificare la connessione a Internet."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "Impossibile installare \"%s\""
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "Un pacchetto essenziale dovrebbe essere rimosso"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/ja.po b/po/ja.po
new file mode 100644
index 0000000..2a3b033
--- /dev/null
+++ b/po/ja.po
@@ -0,0 +1,640 @@
+# Ubuntu-ja translation of update-manager.
+# Copyright (C) 2006 THE update-manager'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the update-manager package.
+# Kenshi Muto <kmuto@debian.org>, 2007-2012
+# Ikuya Awashiro <ikuya@fruitsbasket.info>, 2006.
+# Hiroyuki Ikezoe <ikezoe@good-day.co.jp>, 2005
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: python-apt 0.8.4\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2012-06-30 23:02+0900\n"
+"Last-Translator: Kenshi Muto <kmuto@debian.org>\n"
+"Language-Team: Ubuntu Japanese Team <ubuntu-ja-users@freeml.com>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 12.04 'Precise Pangolin'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 12.04 'Precise Pangolin' の CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 11.10 'Oneiric Ocelot'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 11.10 'Oneiric Ocelot' の CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 11.04 'Natty Narwhal'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 11.04 'Natty Narwhal' の CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 10.10 'Maverick Meerkat'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 10.10 'Maverick Meerkat' の CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr "Canonical パートナー"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr "Canonical によってそのパートナーのためにパッケージされたソフトウェア"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr "このソフトウェアは Ubuntu の構成要素ではありません。"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr "独立"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr "サードパーティのソフトウェア開発者によって提供されたもの"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr "サードパーティ開発者によって提供されたソフトウェアです。"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 10.04 'Lucid Lynx'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 10.04 'Lucid Lynx' の CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 9.10 'Karmic Koala'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 9.10 'Karmic Koala' の CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 9.04 'Jaunty Jackalope'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 9.04 'Jaunty Jackalope' の CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 8.10 'Intrepid Ibex'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 8.10 'Intrepid Ibex' の CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 8.04 'Hardy Heron'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 8.04 'Hardy Heron' の CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 7.10 'Gutsy Gibbon'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 7.10 'Gutsy Gibbon' の CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 7.04 'Feisty Fawn'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 7.04 'Feisty Fawn' の CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr "コミュニティによるメンテナンス"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "制限のあるソフトウェア"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft' の CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+msgid "Canonical-supported free and open-source software"
+msgstr "Canonical によってサポートされるフリー/オープンソースソフトウェア"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr "コミュニティによるメンテナンス (Universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+msgid "Community-maintained free and open-source software"
+msgstr ""
+"コミュニティによってメンテナンスされるフリー/オープンソースソフトウェア"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "フリーではないドライバ"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "デバイス用のプロプライエタリなドライバ"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "制限されたソフトウェア (Multiuniverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "著作権もしくは法的な問題によって制限されたソフトウェア"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake' の CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "重要なセキュリティアップデート"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "推奨アップデート"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr "プレリリースされたアップデート"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+msgid "Unsupported updates"
+msgstr "サポートされていないアップデート"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger' の CD-ROM"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.10 セキュリティアップデート"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.10 アップデート"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 バックポート"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog' の CD-ROM"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "公式なサポート対象"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Ubuntu 5.04 セキュリティアップデート"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ubuntu 5.04 アップデート"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.04 バックポート"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr "コミュニティによるメンテナンス (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "フリーではない (Multiuniverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog' の CD-ROM"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "もう公式にサポートされません"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "制限された著作権"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ubuntu 4.10 セキュリティアップデート"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Ubuntu 4.10 アップデート"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 4.10 バックポート"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 7 'Wheezy' "
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 6.0 'Squeeze' "
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 5.0 'Lenny' "
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 4.0 'Etch'"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 'Sarge'"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "提案されたアップデート"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+msgid "Security updates"
+msgstr "セキュリティアップデート"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr "Debian の現安定版"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr "Debian テスト版"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian 'Sid' (不安定版)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "フリーではないものに依存関係のある DFSG 適合ソフトウェア"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "DFSG に適合しないソフトウェア"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "%s のサーバ"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "メインサーバ"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "カスタムサーバ"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr ""
+"%(total)li 個のファイル中 %(current)li 個を %(speed)s/秒でダウンロードしてい"
+"ます"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "%(total)li 個のファイル中 %(current)li 個をダウンロードしています"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "詳細"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr "開始しています..."
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr "完了"
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr "'%s' の説明に無効な Unicode 文字があります (%s)。報告してください。"
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "変更の一覧を利用できません"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+"変更の一覧がまだ利用できません。\n"
+"\n"
+"変更が利用できるようになるまで http://launchpad.net/ubuntu/+source/%s/%s/"
+"+changelog\n"
+"を使用するか、後で再試行してください。"
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"変更の一覧のダウンロードに失敗しました。\n"
+"インターネット接続を確認してください。"
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr "'%s' のファイルの一覧を読み取れませんでした"
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr "'%s' の control ファイルの一覧を読み取れませんでした"
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr "依存関係が満たされていません: %s\n"
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr "インストール済みパッケージ '%s' と競合"
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+"既存のパッケージ '%(pkgname)s の依存関係 %(depname)s (%(deprelation)s "
+"%(depversion)s) を壊します"
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+"%(targetpkg)s (%(comptype)s %(targetver)s) と競合する既存のパッケージ "
+"'%(pkgname)s' を壊します"
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+"'%(targetpkg)s' と競合する既存のパッケージ '%(pkgname)s' を壊します。しか"
+"し、'%(debfile)s' は '%(provides)s' を通じて提供されます。"
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr "パッケージに Architecture 欄がありません"
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr "無効なアーキテクチャ '%s'"
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr "より新しいバージョンがすでにインストール済みです"
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr "すべての依存関係を満たすことに失敗しました (キャッシュの破損)"
+
+#: ../apt/debfile.py:519
+#, python-format
+msgid "Cannot install '%s'"
+msgstr "'%s' をインストールできません"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+"自動的に圧縮されました:\n"
+"\n"
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr "自動で表示可能なアスキー文字に変換されました:\n"
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr "ソースパッケージ '%s' (%s をビルド) のビルド依存関係をインストール\n"
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr "必須パッケージが削除されます"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr "%c%s... 完了"
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr "ヒット:"
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr "無視:"
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr "エラー:"
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr "取得:"
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr " [作業中]"
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+"メディアの変更: '%s'\n"
+"のラベルのディスクをドライブ '%s' に挿入し、\n"
+"Enter キーを押してください。\n"
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr "%sバイト/%s を取得しました (%sB/秒)\n"
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr "このディスクの名前を入力してください (例: 'Debian 2.1r1 Disk 1')。"
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr "ディスクをドライブに挿入して、Enter キーを押してください"
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr "データ構造を構築しています"
diff --git a/po/ka.po b/po/ka.po
new file mode 100644
index 0000000..d2844a6
--- /dev/null
+++ b/po/ka.po
@@ -0,0 +1,661 @@
+# translation of update-manager.po to Georgian
+# Georgian translation for update-manager
+# Copyright (c) (c) 2006 Canonical Ltd, and Rosetta Contributors 2006
+# This file is distributed under the same license as the update-manager package.
+#
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2006.
+# Vladimer Sichinava <alinux@siena.linux.it>, 2006.
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-18 01:28+0000\n"
+"Last-Translator: Malkhaz Barkalaya <malxaz@gmail.com>\n"
+"Language-Team: Georgian <geognome@googlegroups.com>\n"
+"Language: ka\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"X-Generator: KBabel 1.11.2\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 5.04 უსაფრთხოების განახლება"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 5.10 'Breezy Badger'-ის ლაზერული დისკი"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 4.10 'Warty Warthog'-ის ლაზერული დისკი"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+#| msgid "Ubuntu 4.10 'Warty Warthog'"
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 4.10 'Warty Warthog'-ის ლაზერული დისკი"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 4.10 'Warty Warthog'-ის ლაზერული დისკი"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'-ის ლაზერული დისკი"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 4.10 'Warty Warthog'-ის ლაზერული დისკი"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 4.10 'Warty Warthog'-ის ლაზერული დისკი"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'-ის ლაზერული დისკი"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'-ის ლაზერული დისკი"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 5.04 უსაფრთხოების განახლება"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 5.10 'Breezy Badger'-ის ლაზერული დისკი"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 5.04 უსაფრთხოების განახლება"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 5.10 'Breezy Badger'-ის ლაზერული დისკი"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "universe საზოგადოების მხრდაჭერით"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "არათავისუფალი პროგრამები"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'-ს ლაზერული დისკი"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "თავისუფალი პროგრამები (Open Source) Canonical-ის მხარდაჭერით"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "universe საზოგადოების მხრდაჭერით"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "თავისუფალი პროგრამები (Open Source) universe საზოგადოების მხარდაჭერით"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "არათავისუფალი დრაივერები"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "მოწყობილობების საკუთარი დრაივერები"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "არათავისუფალი პროგრამები (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "პატენტებითა და კანონებით შეზღუდული პროგრამები"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake'-ის ლაზერული დისკი"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "უსაფრთხოების მნიშვნელოვანი განახლებები"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "რეკომენდებული განახლებები"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "შემოთავაზებული განახლებები"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "Backport-განახლებები"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'-ის ლაზერული დისკი"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.10 უსაფრთხოების განახლება"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.10 განახლებები"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 ბექპორტები"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'-ის ლაზერული დისკი"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "ოფიციალური მხარდაჭერით"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Ubuntu 5.04 უსაფრთხოების განახლება"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ubuntu 5.04 განახლებები"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.04 ბექპორტები"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "საზოგადოების მხარდაჭერით (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "არათავისუფალი (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog'-ის ლაზერული დისკი"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "მოხსნილი აქვს ოფიციალური მხარდაჭერა"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "შეზღუდული საავტორო უფლება"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ubuntu 4.10 უსაფრთხოების განახლებები"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Ubuntu 4.10 განახლებები"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 4.10 ბექპორტები"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "შემოთავაზებული განახლებები"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "უსაფრთხოების მნიშვნელოვანი განახლებები"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "Debian \"Etch\" (testing)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian \"Sid\" (unstable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "არათავისუფალ პროგრამებზე დამოკიდებული DFSG-თავსებადი პროგრამები"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "DFSG-არათავსებადი პროგრამები"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "%s სერვერი"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "მთავარი სერვერი"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "საკუთარი სერვერები"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "მე-%(current)li ფაილის ჩამოქაჩვა %(total)li-დან. სიჩქარე - %(speed)s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "მე-%(current)li ფაილის ჩამოქაჩვა %(total)li-დან"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "ცნობები"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr ""
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "ცვლილებების სია არ არის ხელმისაწვდომი."
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"ვერ განხორციელდა ცვლილებების სიის ჩამოქაჩვა.\n"
+"შეამოწმეთ ინტერნეტ-კავშირი."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "'%s' ვერ დაყენდა"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "ამით საჭირო პაკეტი წაიშლება"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/ko.po b/po/ko.po
new file mode 100644
index 0000000..46d2613
--- /dev/null
+++ b/po/ko.po
@@ -0,0 +1,659 @@
+# Korean translation for update-manager
+# Copyright (c) (c) 2006 Canonical Ltd, and Rosetta Contributors 2006
+# This file is distributed under the same license as the update-manager package.
+# darehanl <darehanl@gmail.com>, 2006.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-16 04:04+0000\n"
+"Last-Translator: Eungkyu Song <eungkyu@gmail.com>\n"
+"Language-Team: Korean <ko@li.org>\n"
+"Language: ko\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "우분투 5.04 보안 업데이트"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "우분투 5.10 'Breezy Badger' 씨디롬"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "우분투 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "우분투 4.10 'Warty Warthog' 씨디롬"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+#| msgid "Ubuntu 4.10 'Warty Warthog'"
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "우분투 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "우분투 4.10 'Warty Warthog' 씨디롬"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "우분투 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "우분투 4.10 'Warty Warthog' 씨디롬"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "우분투 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "우분투 5.04 'Hoary Hedgehog' 씨디롬"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "우분투 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "우분투 4.10 'Warty Warthog' 씨디롬"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "우분투 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "우분투 4.10 'Warty Warthog' 씨디롬"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "우분투 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "우분투 5.04 'Hoary Hedgehog' 씨디롬"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "우분투 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "우분투 5.04 'Hoary Hedgehog' 씨디롬"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "우분투 5.04 보안 업데이트"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "우분투 5.10 'Breezy Badger' 씨디롬"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "우분투 5.04 보안 업데이트"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "우분투 5.10 'Breezy Badger' 씨디롬"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "우분투 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "커뮤니티에서 관리"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "제한된 소프트웨어"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "우분투 6.10 'Edgy Eft' 씨디롬"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "우분투 6.06 LTS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "Canonical이 지원하는 오픈 소스 소프트웨어"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "커뮤니티에서 관리 (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "커뮤니티에서 관리하는 오픈 소스 소프트웨어"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "비자유 드라이버"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "장치의 독점 드라이버"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "제한된 소프트웨어 (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "우분투 6.06 LTS 'Dapper Drake' 씨디롬"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "중요한 보안 업데이트"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "추천하는 업데이트"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "제안하는 업데이트"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "Backport 업데이트"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "우분투 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "우분투 5.10 'Breezy Badger' 씨디롬"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "우분투 5.10 보안 업데이트"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "우분투 5.10 업데이트"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "우분투 5.10 Backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "우분투 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "우분투 5.04 'Hoary Hedgehog' 씨디롬"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "공식적으로 지원함"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "우분투 5.04 보안 업데이트"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "우분투 5.04 업데이트"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "우분투 5.04 Backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "우분투 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "커뮤니티에서 관리 (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "비자유 (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "우분투 4.10 'Warty Warthog' 씨디롬"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "더 이상 공식적으로 지원하지 않음"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "저작권이 제한됨"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "우분투 4.10 보안 업데이트"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "우분투 4.10 업데이트"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "우분투 4.10 Backports"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "데비안 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "데비안 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "데비안 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "데비안 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "데비안 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "제안하는 업데이트"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "중요한 보안 업데이트"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "데비안 \"Etch\" (testing)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "데비안 \"Sid\" (unstable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "DFSG 호환이 되지만 비자유 소프트웨어에 의존하는 소프트웨어"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "DFSG와 호환이 되지 않는 소프트웨어"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "%s 서버"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "주 서버"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "사용자 정의 서버"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr ""
+"%(total)li개중 %(current)li번째 파일을 %(speed)s/s의 속도로 받고 있습니다"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "%(total)li개중 %(current)li번째 파일을 받고 있습니다"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "자세한 정보"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr ""
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "변경 사항 목록이 없습니다"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+#, fuzzy
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"변경 사항 목록을 다운로드하는데 실패했습니다. 인터넷 연결을 확인해 주십시오."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "'%s'을(를) 설치할 수 없습니다"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "필수적인 패키지를 제거해야만 합니다."
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/ku.po b/po/ku.po
new file mode 100644
index 0000000..9ba4a54
--- /dev/null
+++ b/po/ku.po
@@ -0,0 +1,660 @@
+# Kurdish translation for update-manager
+# Copyright (c) (c) 2006 Canonical Ltd, and Rosetta Contributors 2006
+# This file is distributed under the same license as the update-manager package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2006.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-17 09:50+0000\n"
+"Last-Translator: rizoye-xerzi <rizoxerzi@gmail.com>\n"
+"Language-Team: Kurdish <ku@li.org>\n"
+"Language: ku\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Rojanekirinên Ewlekariyên yên Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Cdroma Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Cdroma Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+#| msgid "Ubuntu 4.10 'Warty Warthog'"
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Cdroma Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Cdroma Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Cdroma Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Cdroma Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Cdroma Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Cdroma Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Cdroma Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Rojanekirinên Ewlekariyên yên Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Cdroma Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Rojanekirinên Ewlekariyên yên Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Cdroma Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "Yên ji aliyê komekê ber çav hatiye derbaskirin"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Nivîsbariya bi sînor"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "Cdroma Ubuntu 6.10 'Edgy Eft'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "Çavkaniya xwezayî ya li gorî bingeha nermalavê"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "Yên ji aliyê koman lê hatine nihêrtin"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr ""
+"Nivîsbariyên Kodên Çavkaniyên Azad yên ji aliyê koman lê hatine nihêrtin"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Ajokerên ne azad"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Ji bo cîhazan ajokerên ku çavkaniyên wan girtî ne"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Nivîsbariya bi sînor"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "Nivîsbariya bi mafên weşan û belavkirinê sînor kirî"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Cdroma Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Rojanekirinên ewlekariyê yên girîng"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Rojanekirinên têne pêşniyarkirin"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "Rojanekirinên hatine pêşniyarkirin"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "Rojanekirinên paş de hatine kişandin"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Cdroma Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Rojanekirinên Ewlekariyê yên Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Rojanekirina Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Rojanekirinên Paş de Hatine Kişandin yên Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Cdroma Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Bi piştgiriya fermî"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Rojanekirinên Ewlekariyên yên Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Rojanekirinên Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Rojanekirinên Paş de Hatine Kişandin yên Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "Yên ji aliyê koman ve lê tê nihêrîn (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Ne-azad (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "Cdroma Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Êdi bi awayekî fermî nayê destekkirin"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Mafê kopîkrinê yê sînorkirî"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Rojanekirinên Ubuntu 4.10 yên Ewlekarî"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Rojanekirinên Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 4.10 nivîsbariyên bi paş de kişandî (Backports)"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Rojanekirinên hatine pêşniyarkirin"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "Rojanekirinên ewlekariyê yên girîng"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "Debian \"Etch\" (testing)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian \"Sid\" (unstable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "DFSG-nivîsbariya hevgirtî ya ne azad"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "nivîsbariya hevgirtî ya ne li gorî -DFSG"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Pêşkêşkera %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Pêşkêşkera Mak"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Pêşkêşkera taybet"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Pelgeha %(current)li ji %(total)li bi %(speed)s/ç tê daxistin"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Pelgeha %(current)li ji %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Hûragahî"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr ""
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "Lîsteya guherînan ne gihiştbar e"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Daxistina lîsteya guhertinan biserneket.\n"
+"Ji kerema xwe re girêdana internetê kontrol bike."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "Nikarî '%s' saz bike"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "Dê pêwiste be ku pakêta bingehîn were jêbirin"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/lt.po b/po/lt.po
new file mode 100644
index 0000000..7fd8f1f
--- /dev/null
+++ b/po/lt.po
@@ -0,0 +1,664 @@
+# Lithuanian translation for Update Manager package.
+# Copyright (C) 2005, the Free Software Foundation, Inc.
+# This file is distributed under the same license as the update-manager package.
+# Žygimantas Beručka <uid0@akl.lt>, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-16 04:04+0000\n"
+"Last-Translator: Mantas Kriaučiūnas <mantas@akl.lt>\n"
+"Language-Team: Lithuanian <komp_lt@konferencijos.lt>\n"
+"Language: lt\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n"
+"%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 5.04 saugumo atnaujinimai"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "CD diskas su Ubuntu 5.10 „Breezy Badger“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 4.10 „Warty Warthog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "CD diskas su Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+#| msgid "Ubuntu 4.10 'Warty Warthog'"
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 4.10 „Warty Warthog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "CD diskas su Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 4.10 „Warty Warthog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "CD diskas su Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 5.04 „Hoary Hedgehog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "CD diskas Ubuntu 5.04 „Hoary Hedgehog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 4.10 „Warty Warthog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "CD diskas su Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 4.10 „Warty Warthog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "CD diskas su Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 5.04 „Hoary Hedgehog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "CD diskas Ubuntu 5.04 „Hoary Hedgehog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 5.04 „Hoary Hedgehog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "CD diskas Ubuntu 5.04 „Hoary Hedgehog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 5.04 saugumo atnaujinimai"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "CD diskas su Ubuntu 5.10 „Breezy Badger“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 5.04 saugumo atnaujinimai"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "CD diskas su Ubuntu 5.10 „Breezy Badger“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "Prižiūrima bendruomenės"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+#, fuzzy
+msgid "Restricted software"
+msgstr "Ne Laisva (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "CD diskas su Ubuntu 6.10 'Edgy Eft'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+#, fuzzy
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS „Dapper Drake“"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "Prižiūrima bendruomenės (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "Prižiūrima bendruomenės (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "Bendruomenės prižiūrima laisva programinė įranga"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+#, fuzzy
+msgid "Non-free drivers"
+msgstr "Ne Laisva (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+#, fuzzy
+msgid "Restricted software (Multiverse)"
+msgstr "Ne Laisva (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "CD diskas su Ubuntu 6.06 LTS „Dapper Drake“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Svarbūs saugumo atnaujinimai"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Rekomenduojami atnaujinimai"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "Testuojami atnaujinimai"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "Naujos ir atnaujintos programos"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 „Breezy Badger“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "CD diskas su Ubuntu 5.10 „Breezy Badger“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.10 saugumo atnaujinimai"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.10 atnaujinimai"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Naujos programos Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 „Hoary Hedgehog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "CD diskas Ubuntu 5.04 „Hoary Hedgehog“"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Oficialiai palaikoma"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Ubuntu 5.04 saugumo atnaujinimai"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ubuntu 5.04 atnaujinimai"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Naujos programos Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 „Warty Warthog“"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "Prižiūrima bendruomenės (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Ne Laisva (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "CD diskas su Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+#, fuzzy
+msgid "No longer officially supported"
+msgstr "Kai kuri programinė įranga nebėra oficialiai palaikoma"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Apribotos autorinės teisės"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ubuntu 4.10 saugumo atnaujinimai"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Ubuntu 4.10 atnaujinimai"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Naujos programos Ubuntu 4.10"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 3.1 „Sarge“"
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 3.1 „Sarge“"
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 3.1 „Sarge“"
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 3.1 „Sarge“"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 „Sarge“"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Testuojami atnaujinimai"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "Svarbūs saugumo atnaujinimai"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "Debian „Etch“ (testing)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian „Sid“ (unstable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "Su DFSG suderinama programinė įranga su Ne Laisvomis priklausomybėmis"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Su DFSG nesuderinama programinė įranga"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr ""
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr ""
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Atsiunčiamas failas %(current)li iš %(total)li, %(speed)s/s greičiu"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Atsiunčiamas failas %(current)li iš %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Detalės"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr ""
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "Pakeitimų sąrašas neprieinamas"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Nepavyko atsiųsti pakeitimų sąrašo. \n"
+"Patikrinkite Interneto ryšį."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "Negalima įdiegti „%s“"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "Turėtų būti pašalintas esminis paketas"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/lv.po b/po/lv.po
new file mode 100644
index 0000000..272b8c9
--- /dev/null
+++ b/po/lv.po
@@ -0,0 +1,627 @@
+# translation of lp-upd-manager-lv.po to Latvian
+# Latvian translation for update-manager
+# Copyright (c) (c) 2006 Canonical Ltd, and Rosetta Contributors 2006
+# This file is distributed under the same license as the update-manager package.
+#
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2006.
+# Raivis Dejus <orvils@gmail.com>, 2006.
+msgid ""
+msgstr ""
+"Project-Id-Version: lp-upd-manager-lv\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-09-05 20:00+0000\n"
+"Last-Translator: Raivis Dejus <orvils@gmail.com>\n"
+"Language-Team: Latvian <locale@laka.lv>\n"
+"Language: lv\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : "
+"2);\n"
+"X-Generator: KBabel 1.11.2\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "Sabiedrības uzturētie (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "Sabiedrības uzturētie (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "Sabiedrības uzturētie (Universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "Sabiedrības uzturētie (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "%s atjauninājumi"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Oficiāli atbalstītie"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "Sabiedrības uzturētie (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Maksas (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Saistītie autortiesību"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr ""
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+msgid "Debian 6.0 'Squeeze' "
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+msgid "Debian 5.0 'Lenny' "
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+msgid "Debian 4.0 'Etch'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+msgid "Debian 3.1 'Sarge'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "%s atjauninājumi"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr ""
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr ""
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Galvenais serveris"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr ""
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Detaļas"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr ""
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr ""
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "Nevar instalēt '%s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr ""
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/mk.po b/po/mk.po
new file mode 100644
index 0000000..bb6f0c9
--- /dev/null
+++ b/po/mk.po
@@ -0,0 +1,681 @@
+# translation of mk.po to Macedonian
+# This file is distributed under the same license as the PACKAGE package.
+# Copyright (C) 2005 THE PACKAGE'S COPYRIGHT HOLDER.
+# Арангел Ангов <ufo@linux.net.mk>, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: mk\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-16 04:04+0000\n"
+"Last-Translator: Арангел Ангов <ufo@linux.net.mk>\n"
+"Language-Team: Macedonian <ossm-members@hedona.on.net.mk>\n"
+"Language: mk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural= n==1 || n%10==1 ? 0 : 1\n"
+"X-Generator: KBabel 1.10\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Безбедносни надградби за Убунту 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "CD диск со Убунту 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "CD диск со Убунту 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "CD диск со Убунту 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "CD диск со Убунту 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "CD диск со Убунту 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "CD диск со Убунту 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "CD диск со Убунту 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "CD диск со Убунту 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "CD диск со Убунту 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "CD диск со Убунту 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "CD диск со Убунту 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "CD диск со Убунту 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "CD диск со Убунту 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "CD диск со Убунту 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "CD диск со Убунту 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "CD диск со Убунту 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "CD диск со Убунту 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Безбедносни надградби за Убунту 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "CD диск со Убунту 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Безбедносни надградби за Убунту 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "CD диск со Убунту 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+#, fuzzy
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Надградби за Убунту 5.10"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "Оддржувано од заедницата (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+#, fuzzy
+msgid "Restricted software"
+msgstr "Додатен софтвер"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+#, fuzzy
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "CD диск со Убунту 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+#, fuzzy
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Надградби за Убунту 5.04"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "Оддржувано од заедницата (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "Оддржувано од заедницата (Universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "Оддржувано од заедницата (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+#, fuzzy
+msgid "Non-free drivers"
+msgstr "Неслободно (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+#, fuzzy
+msgid "Restricted software (Multiverse)"
+msgstr "Неслободно (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+#, fuzzy
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Надградби за Убунту 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+#, fuzzy
+msgid "Important security updates"
+msgstr "Безбедносни надградби за Debian Stable"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "Инсталирам надградби..."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "Инсталирам надградби..."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+#, fuzzy
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "CD диск со Убунту 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+#, fuzzy
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "CD диск со Убунту 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Безбедносни надградби за Убунту 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Надградби за Убунту 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+#, fuzzy
+msgid "Ubuntu 5.10 Backports"
+msgstr "Надградби за Убунту 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+#, fuzzy
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "CD диск со Убунту 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+#, fuzzy
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "CD диск со Убунту 5.04 \"Hoary Hedgehog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Официјално поддржано"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Безбедносни надградби за Убунту 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Надградби за Убунту 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+#, fuzzy
+msgid "Ubuntu 5.04 Backports"
+msgstr "Надградби за Убунту 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+#, fuzzy
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "CD диск со Убунту 4.10 \"Warty Warthog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "Оддржувано од заедницата (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Неслободно (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+#, fuzzy
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "CD диск со Убунту 4.10 \"Warty Warthog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+#, fuzzy
+msgid "No longer officially supported"
+msgstr "Официјално поддржано"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Restricted copyright"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Безбедносни надградби за Убунту 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Надградби за Убунту 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+#, fuzzy
+msgid "Ubuntu 4.10 Backports"
+msgstr "Надградби за Убунту 5.10"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+#, fuzzy
+msgid "Proposed updates"
+msgstr "Инсталирам надградби..."
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "Безбедносни надградби за Debian Stable"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+#, fuzzy
+msgid "Debian current stable release"
+msgstr "Debian Unstable \"Sid\""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "Debian Testing"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian Non-US (Unstable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "DFSG-компатибилен софтвер со неслободни зависности"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Не-DFSG-компатибилен софтвер"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr ""
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr ""
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr ""
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+#, fuzzy
+msgid "Details"
+msgstr "<b>Детали</b>"
+
+#: ../apt/progress/gtk2.py:428
+#, fuzzy
+msgid "Starting..."
+msgstr "Поставувања"
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+#, fuzzy
+msgid "The list of changes is not available"
+msgstr "Достапна е нова верзија на Убунту!"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+#, fuzzy
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Не успеав да ги преземам промените. Ве молам проверете дали Вашата интернет "
+"врска е активна."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "Не може да се инсталира %s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "Важен пакет мора да се отстрани"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/nb.po b/po/nb.po
new file mode 100644
index 0000000..58e1b56
--- /dev/null
+++ b/po/nb.po
@@ -0,0 +1,683 @@
+# translation of nb.po to Norwegian Bokmal
+# This file is distributed under the same license as the PACKAGE package.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER.
+# Terance Edward Sola <terance@lyse.net>, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: nb\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-16 04:04+0000\n"
+"Last-Translator: Hans Petter Birkeland <hanspb@bluezone.no>\n"
+"Language-Team: Norwegian Bokmal <i18n-nb@lister.ping.uio.no>\n"
+"Language: nb\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: KBabel 1.10\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 5.10 Sikkerhetsoppdateringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "CD med Ubuntu 4.10 «Warty Warthog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "CD med Ubuntu 4.10 «Warty Warthog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "CD med Ubuntu 4.10 «Warty Warthog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "CD med Ubuntu 4.10 «Warty Warthog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "CD med Ubuntu 4.10 «Warty Warthog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "CD med Ubuntu 4.10 «Warty Warthog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "CD med Ubuntu 5.04 «Hoary Hedgedog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "CD med Ubuntu 5.04 «Hoary Hedgedog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "CD med Ubuntu 4.10 «Warty Warthog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "CD med Ubuntu 4.10 «Warty Warthog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "CD med Ubuntu 4.10 «Warty Warthog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "CD med Ubuntu 4.10 «Warty Warthog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "CD med Ubuntu 5.04 «Hoary Hedgedog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "CD med Ubuntu 5.04 «Hoary Hedgedog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "CD med Ubuntu 5.04 «Hoary Hedgedog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "CD med Ubuntu 5.04 «Hoary Hedgedog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 5.10 Sikkerhetsoppdateringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 5.10 Sikkerhetsoppdateringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+#, fuzzy
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 5.10 Oppdateringer"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "Vedlikeholdt av miljøet (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+#, fuzzy
+msgid "Restricted software"
+msgstr "Bidratt programvare"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+#, fuzzy
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "CD med Ubuntu 4.10 «Warty Warthog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+#, fuzzy
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "Vedlikeholdt av miljøet (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "Vedlikeholdt av miljøet (Universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "Vedlikeholdt av miljøet (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+#, fuzzy
+msgid "Non-free drivers"
+msgstr "Non-free (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+#, fuzzy
+msgid "Restricted software (Multiverse)"
+msgstr "Non-free (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+#, fuzzy
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 'Dapper Drake'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+#, fuzzy
+msgid "Important security updates"
+msgstr "Ubuntu 5.10 Sikkerhetsoppdateringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+#, fuzzy
+msgid "Recommended updates"
+msgstr "Anbefalte oppdateringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "Installerer oppdateringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "Installerer oppdateringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+#, fuzzy
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.10 Sikkerhetsoppdateringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.10 Oppdateringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 Backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+#, fuzzy
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "CD med Ubuntu 5.04 «Hoary Hedgedog»"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+#, fuzzy
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "CD med Ubuntu 5.04 «Hoary Hedgedog»"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Offisielt støttet"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+#, fuzzy
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Ubuntu 5.10 Sikkerhetsoppdateringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+#, fuzzy
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ubuntu 5.10 Oppdateringer"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+#, fuzzy
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.10 Backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+#, fuzzy
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "CD med Ubuntu 4.10 «Warty Warthog»"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "Vedlikeholdt av miljøet (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Non-free (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+#, fuzzy
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "CD med Ubuntu 4.10 «Warty Warthog»"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+#, fuzzy
+msgid "No longer officially supported"
+msgstr "Noe programvare er ikke lenger offisielt støttet"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Begrenset opphavsrett"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ubuntu 4.10 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Ubuntu 4.10 Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+#, fuzzy
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 5.10 Backports"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian Testing"
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian Testing"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+#, fuzzy
+msgid "Proposed updates"
+msgstr "Installerer oppdateringer"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "Ubuntu 5.10 Sikkerhetsoppdateringer"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+#, fuzzy
+msgid "Debian current stable release"
+msgstr "Debian Unstable «Sid»"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "Debian \"Etch\" (testing)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian \"Sid\" (unstable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "DFSG-kompatiblel programvare med Non-Free avhengigheter"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Ikke-DFSG-kompatibel programvare"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, fuzzy, python-format
+msgid "Server for %s"
+msgstr "Tjener for %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+#, fuzzy
+msgid "Main server"
+msgstr "Hovedtjener"
+
+#: ../aptsources/distro.py:250
+#, fuzzy
+msgid "Custom servers"
+msgstr "Egendefinerte tjenere"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, fuzzy, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Laster ned filen %li av %li med %s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, fuzzy, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Laster ned filen %li av %li med %s/s"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Detaljer"
+
+#: ../apt/progress/gtk2.py:428
+#, fuzzy
+msgid "Starting..."
+msgstr "Instillinger"
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+#, fuzzy
+msgid "The list of changes is not available"
+msgstr "Listen over endringer er ikke tilgjengelig ennå. Prøv senere."
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+#, fuzzy
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Kunne ikke laste ned listen med endringer. Vennligst kontrollér "
+"internettilkoblingen."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "Kan ikke installere '%s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "En nødvendig pakke må fjernes"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/ne.po b/po/ne.po
new file mode 100644
index 0000000..e7de8d8
--- /dev/null
+++ b/po/ne.po
@@ -0,0 +1,682 @@
+# translation of update-manager.HEAD.po to Nepali
+# This file is distributed under the same license as the PACKAGE package.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER.
+# Pawan Chitrakar <pawan@mpp.org.np>, 2005.
+# Jaydeep Bhusal <zaydeep@hotmail.com>, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager.HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-16 04:13+0000\n"
+"Last-Translator: Jaydeep Bhusal <zaydeep@hotmail.com>\n"
+"Language-Team: Nepali <info@mpp.org.np>\n"
+"Language: ne\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.9.1\n"
+"Plural-Forms: nplurals=2;plural=(n!=0)\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+#, fuzzy
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "युबन्टु ५.०४ अद्यावधिकहरु"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "समुदाय सम्हालिएको (ब्रह्माण्ड)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+#, fuzzy
+msgid "Restricted software"
+msgstr "योगदान गरिएको सफ्टवेयर"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+#, fuzzy
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "युबन्टु ५.०४ अद्यावधिकहरु"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "समुदाय सम्हालिएको (ब्रह्माण्ड)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "समुदाय सम्हालिएको (ब्रह्माण्ड)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "समुदाय सम्हालिएको (ब्रह्माण्ड)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+#, fuzzy
+msgid "Non-free drivers"
+msgstr "नन-फ्री (बहुभर्स)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+#, fuzzy
+msgid "Restricted software (Multiverse)"
+msgstr "नन-फ्री (बहुभर्स)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+#, fuzzy
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "युबन्टु ५.०४ अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+#, fuzzy
+msgid "Important security updates"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "स्तरवृद्धिहरु स्थापना गर्दै"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "स्तरवृद्धिहरु स्थापना गर्दै"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+#, fuzzy
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+#, fuzzy
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+#, fuzzy
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+#, fuzzy
+msgid "Ubuntu 5.10 Updates"
+msgstr "युबन्टु ५.०४ अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+#, fuzzy
+msgid "Ubuntu 5.10 Backports"
+msgstr "युबन्टु ५.०४ अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+#, fuzzy
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+#, fuzzy
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+#, fuzzy
+msgid "Officially supported"
+msgstr "कार्यालय बाट समर्थित"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+#, fuzzy
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+#, fuzzy
+msgid "Ubuntu 5.04 Updates"
+msgstr "युबन्टु ५.०४ अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+#, fuzzy
+msgid "Ubuntu 5.04 Backports"
+msgstr "युबन्टु ५.०४ अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+#, fuzzy
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "समुदाय सम्हालिएको (ब्रह्माण्ड)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "नन-फ्री (बहुभर्स)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+#, fuzzy
+msgid "No longer officially supported"
+msgstr "कार्यालय बाट समर्थित"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "निषेधित प्रतिलिपि अधिकार"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "युबन्टु ४.१० सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+#, fuzzy
+msgid "Ubuntu 4.10 Updates"
+msgstr "युबन्टु ५.०४ अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+#, fuzzy
+msgid "Ubuntu 4.10 Backports"
+msgstr "युबन्टु ५.०४ अद्यावधिकहरु"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "डेबियन अचल सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "डेबियन अचल सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "डेबियन अचल सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "डेबियन अचल सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "डेबियन अचल सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+#, fuzzy
+msgid "Proposed updates"
+msgstr "स्तरवृद्धिहरु स्थापना गर्दै"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "युबन्टु ५.०४ सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+#, fuzzy
+msgid "Debian current stable release"
+msgstr "डेबियन अचल सुरक्षा अद्यावधिकहरु"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "डेबियन अचल सुरक्षा अद्यावधिकहरु"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr ""
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr ""
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr ""
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr ""
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+#, fuzzy
+msgid "Details"
+msgstr "<b>विवरणहरु</b>"
+
+#: ../apt/progress/gtk2.py:428
+#, fuzzy
+msgid "Starting..."
+msgstr "सेटिंगहरु"
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+#, fuzzy
+msgid "The list of changes is not available"
+msgstr "युबन्टुको एउटा नयाँ विमोचन उपलब्ध छ!"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+#, fuzzy
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr "परिवर्तनहरु डाउनलोड गर्न असफल. यदि सक्रिय इन्टरनेट जडान छ भने जाँच्नुहोस"
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, python-format
+msgid "Cannot install '%s'"
+msgstr ""
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr ""
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/nl.po b/po/nl.po
new file mode 100644
index 0000000..24f3e26
--- /dev/null
+++ b/po/nl.po
@@ -0,0 +1,639 @@
+# Ducht translation of python-apt.
+# Copyright (C) 2006-2012 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the python-apt package.
+# Tino Meinen <a.t.meinen@chello.nl>, 2006.
+# Jeroen Schot <schot@a-eskwadraat.nl, 2011, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: python-apt 0.8.4+nmu1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:42+0200\n"
+"PO-Revision-Date: 2012-06-13 12:12+0200\n"
+"Last-Translator: Jeroen Schot <schot@a-eskwadraat.nl>\n"
+"Language-Team: Debian l10n Dutch <debian-l10n-dutch@lists.debian.org>\n"
+"Language: nl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 12.04 'Precise Pangolin'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "CD met Ubuntu 12.04 'Precise Pangolin'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 11.10 'Oneiric Ocelot'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "CD met Ubuntu 11.10 'Oneiric Ocelot'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 11.04 'Natty Narwhal'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "CD met Ubuntu 11.04 'Natty Narwhal'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 10.10 'Maverick Meerkat'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "CD met Ubuntu 10.10 'Maverick Meerkat'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr "Partners van Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr "Software dis is verpakt door Canonical voor zijn partners"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr "Deze software is geen onderdeel van Ubuntu."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr "Onafhankelijk"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr "Aangeboden door externe ontwikkelaars"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr "Software die door externe ontwikkelaars wordt aangeboden."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 10.04 'Lucid Lynx'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "CD met Ubuntu 10.04 'Lucid Lynx'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 9.10 'Karmic Koala'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "CD met Ubuntu 9.10 'Karmic Koala'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 9.04 'Jaunty Jackalope'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "CD met Ubuntu 9.04 'Jaunty Jackalope'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 8.10 'Intrepid Ibex'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "CD met Ubuntu 8.10 'Intrepid Ibex'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 8.04 'Hardy Heron'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "CD met Ubuntu 8.04 'Hardy Heron'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 7.10 'Gutsy Gibbon'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "CD met Ubuntu 7.10 'Gutsy Gibbon'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 7.04 'Feisty Fawn'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "CD met Ubuntu 7.04 'Feisty Fawn'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr "Door de gemeenschap beheerd"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Beperkte software"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "CD met Ubuntu 6.10 'Edgy Eft'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+msgid "Canonical-supported free and open-source software"
+msgstr "Door Canonical ondersteunde vrije en opensourcesoftware"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr "Door de gemeenschap beheerd (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+msgid "Community-maintained free and open-source software"
+msgstr "Door de gemeenschap beheerde vrije en opensourcesoftware"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Niet-vrije stuurprogramma's"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Niet-vrije stuurprogramma's voor apparaten"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Beperkte software (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+"Software die door auteursrechten of wettelijke regelingen beperkt wordt."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "CD met Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Belangrijke veiligheidsupdates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Aanbevolen updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr "Voorgestelde updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+msgid "Unsupported updates"
+msgstr "Niet-ondersteunde updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "CD met Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.10 veiligheidsupdates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.10 updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "CD met Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Officieel ondersteund"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Ubuntu 5.04 veiligheidsupdates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ubuntu 5.04 updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.04 backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr "Door de gemeenschap beheerd (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Niet-vrij (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "CD met Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Niet meer officieel ondersteund"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Beperkte auteursrechten"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ubuntu 4.10 veiligheidsupdates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Ubuntu 4.10 updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 4.10 backports"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 7 'Wheezy' "
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 6.0 'Squeeze' "
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 5.0 'Lenny' "
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 4.0 'Etch'"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 'Sarge'"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Voorgestelde updates"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+msgid "Security updates"
+msgstr "veiligheidsupdates"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr "Huidige stabiele uitgave van Debian"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr "Debian testing (test)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian 'Sid' (unstable/onstabiel)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "Software compatibel met DFSG, maar met niet-vrije afhankelijkheden"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Software niet compatibel met DFSG"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Server voor %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Hoofdserver"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Andere servers"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Downloaden van bestand %(current)li uit %(total)li met %(speed)s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Downloaden van bestand %(current)li uit %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Details"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr "Opstarten..."
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr "Voltooid"
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+"Ongeldige unicode in de beschrijving van '%s' (%s). Gelieve dit te melden."
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "Een overzicht van de wijzigingen is nog niet beschikbaar."
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+"De lijst van veranderingen is nog niet beschikbaar\n"
+"\n"
+"Gebruik http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"todat de veranderingen beschikbaar zijn of probeer het later nog eens."
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Kon de lijst met wijzigingen niet downloaden. \n"
+"Controleer uw internetverbinding."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr "De lijst van bestanden voor '%s' kon niet gelezen worden"
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr "De lijst van bestanden voor '%s' kon niet gelezen worden"
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr "Afhankelijkheid is niet vervulbaar: %s\n"
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr "Conflicteerd met het geinstalleerde pakket '%s'"
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+"Maakt het bestaande pakket '%(pkgname)s' stuk door afhankelijkheid "
+"%(depname)s (%(deprelation)s %(depversion)s)"
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+"Maakt het bestaande pakket '%(pkgname)s' stuk door conflict: %(targetpkg)s "
+"(%(comptype)s %(targetver)s) "
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+"Maakt het bestaande pakket '%(pkgname)s' stuk die conflicteert: "
+"'%(targetpkg)s'. Maar de '%(debfile)s biedt deze aan via: '%(provides)s'"
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr "Pakket heeft geen Architecture-veld"
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr "Verkeerde architectuur '%s'"
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr "Er is al een nieuwere versie geïnstalleerd"
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr "Voldoen van alle vereisten is mislukt (defecte cache)"
+
+#: ../apt/debfile.py:519
+#, python-format
+msgid "Cannot install '%s'"
+msgstr "Kan '%s' niet installeren"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+"Automatisch uitgepakt:\n"
+"\n"
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr "Automatisch omgezet naar toonbare ASCII:\n"
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+"Installeer de bouwevereisten voor het bronpakket '%s' waaruit '%s' wordt "
+"gebouwd\n"
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr "Een essentieel pakket zou verwijderd worden"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr "%c%s... Klaar"
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr "Geraakt "
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr "Genegeerd "
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr "Fout "
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr "Ophalen:"
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr " [Bezig]"
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+"Medium wisselen: Gelieve de schijf met label\n"
+" '%s'\n"
+"in het station '%s' te plaatsen en op 'enter' te drukken\n"
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr "%sB opgehaald in %s (%sB/s)\n"
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+"Gelieve een naam voor deze schijf op te geven, bijvoorbeeld 'Debian 2.1r1 "
+"schijf 1'"
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr "Gelieve een schijf in het station te plaatsen en op 'Enter' te drukken"
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr "Opbouwen van pakketstructuren"
diff --git a/po/oc.po b/po/oc.po
new file mode 100644
index 0000000..4b4647c
--- /dev/null
+++ b/po/oc.po
@@ -0,0 +1,661 @@
+# Occitan (post 1500) translation for update-manager
+# Copyright (c) (c) 2006 Canonical Ltd, and Rosetta Contributors 2006
+# This file is distributed under the same license as the update-manager package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2006.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-18 10:01+0000\n"
+"Last-Translator: Yannig MARCHEGAY (Kokoyaya) <yannick.marchegay@lokanova."
+"com>\n"
+"Language-Team: Occitan (post 1500) <oc@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n > 1\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Mesas a jorn de seguretat per Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "CD-ROM amb Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "CD-ROM que conten Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "CD-ROM que conten Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "CD-ROM que conten Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "CD-ROM que conten Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "CD-ROM que conten Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "CD-ROM que conten Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "CD-ROM que conten Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "CD-ROM que conten Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Mesas a jorn de seguretat per Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "CD-ROM amb Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Mesas a jorn de seguretat per Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "CD-ROM amb Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+#, fuzzy
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+#, fuzzy
+msgid "Restricted software"
+msgstr "Pas liure (multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "CD-ROM que conten Ubuntu 6.10 'Edgy Eft'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+#, fuzzy
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Mesas a jorn per Ubuntu 6.06 LTS"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+msgid "Canonical-supported free and open-source software"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+msgid "Community-maintained free and open-source software"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Pilòts pas liures"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+#, fuzzy
+msgid "Restricted software (Multiverse)"
+msgstr "Pas liure (multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "CD-ROM que conten Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Mesas a jorn de seguretat importantas"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "Autras mesas a jorn"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "Mesas a jorn de seguretat importantas"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "CD-ROM amb Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Mesas a jorn de seguretat per Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+#, fuzzy
+msgid "Ubuntu 5.10 Updates"
+msgstr "Mesas a jorn per Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+#, fuzzy
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "CD-ROM que conten Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Mesas a jorn de seguretat per Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+#, fuzzy
+msgid "Ubuntu 5.04 Updates"
+msgstr "Mesas a jorn per Ubuntu 6.06 LTS"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+#, fuzzy
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Pas liure (multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+#, fuzzy
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Mesas a jorn per Ubuntu 6.06 LTS"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+#, fuzzy
+msgid "Ubuntu 4.10 Updates"
+msgstr "Mesas a jorn per Ubuntu 6.06 LTS"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr ""
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "Mesas a jorn de seguretat importantas"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "Debian \"Etch\" (en tèst)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian \"Sid\" (instable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr ""
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Servidor per %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Servidor principal"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Servidors personalizats"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr ""
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Detalhs"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr ""
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "La tièra de las modificacioons es pas disponibla"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+#, fuzzy
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr "Verificatz vòstra connection internet."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "Impossible d'installar '%s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr ""
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/pl.po b/po/pl.po
new file mode 100644
index 0000000..d6c4c48
--- /dev/null
+++ b/po/pl.po
@@ -0,0 +1,644 @@
+# Polish translation of Update Manager.
+# Copyright (C) 2005 Zygmunt Krynicki <zyga@www.suxx.pl>
+# This file is distributed under the same license as the update-manager package.
+#
+# Dominik Zablotny <doza@sztorm.net>, 2006.
+# Michał Kułach <michal.kulach@gmail.com>, 2012.
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager cvs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2012-07-28 23:07+0100\n"
+"Last-Translator: Michał Kułach <michal.kulach@gmail.com>\n"
+"Language-Team: Polish <debian-l10n-polish@lists.debian.org>\n"
+"Language: pl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
+"|| n%100>=20) ? 1 : 2);\n"
+"X-Generator: Lokalize 1.4\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 12.04 \"Precise Pangolin\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "CD-ROM z Ubuntu 12.04 \"Precise Pangolin\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 11.10 \"Oneiric Ocelot\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "CD-ROM z Ubuntu 11.10 \"Oneiric Ocelot\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#| msgid "Ubuntu 4.10 'Warty Warthog'"
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 11.04 \"Natty Narwhal\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#| msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "CD-ROM z Ubuntu 11.04 \"Natty Narwhal\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 10.10 \"Maverick Meerkat\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "CD-ROM z Ubuntu 10.10 \"Maverick Meerkat\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr "Partnerzy Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr "Programy spakietowane przez firmę Canonical dla jej partnerów"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr "To oprogramowanie nie jest częścią Ubuntu."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr "Niezależne"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr "Udostępniane przez zewnętrznych deweloperów"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr "Oprogramowanie oferowane przez zewnętrznych deweloperów."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 10.04 \"Lucid Lynx\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "CD-ROM z Ubuntu 10.04 \"Lucid Lynx\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 9.10 \"Karmic Koala\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "CD-ROM z Ubuntu 9.10 \"Karmic Koala\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 9.04 \"Jaunty Jackalope\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "CD-ROM z Ubuntu 9.04 \"Jaunty Jackalope\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 8.10 \"Intrepid Ibex\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "CD-ROM z Ubuntu 8.10 \"Intrepid Ibex\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 8.04 \"Hardy Heron\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "CD-ROM z Ubuntu 8.04 \"Hardy Heron\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 7.10 \"Gutsy Gibbon\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "CD-ROM z Ubuntu 7.10 \"Gutsy Gibbon\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 7.04 \"Feisty Fawn\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "CD-ROM z Ubuntu 7.04 \"Feisty Fawn\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 \"Edgy Eft\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr "Pod opieką społeczności"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Ograniczone oprogramowanie"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "CD-ROM z Ubuntu 6.10 \"Edgy Eft\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS \"Dapper Drake\""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+msgid "Canonical-supported free and open-source software"
+msgstr "Wolne i otwarte oprogramowanie wspierane przez firmę Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr "Utrzymywane przez społeczność (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+msgid "Community-maintained free and open-source software"
+msgstr "Wolne i otwarte oprogramowanie wspierane przez społeczność"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Sterowniki niewolne"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Własnościowe sterowniki do urządzeń"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Oprogramowanie niewolnodostępne (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+"Oprogramowanie ograniczone prawami autorskimi lub problemami natury prawnej"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "CD-ROM z Ubuntu 6.06 LTS \"Dapper Drake\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Ważne aktualizacje bezpieczeństwa"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Aktualizacje polecane"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr "Wstępne wydania aktualizacji"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+msgid "Unsupported updates"
+msgstr "Niewspierane aktualizacje"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "CD-ROM z Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Aktualizacje bezpieczeństwa do Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Aktualizacje do Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Aktualizacje do Ubuntu 5.10 (backporty)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu·5.04·\"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "CD-ROM z Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Wspierane oficjalnie"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Aktualizacje bezpieczeństwa do Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Aktualizacje do Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Aktualizacje do Ubuntu 5.04 (backporty)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu·4.10·\"Warty Warthog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr "Utrzymywane przez społeczność (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Niewolne (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "CD-ROM z Ubuntu 4.10 \"Warty Warthog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Już nieobsługiwane"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "O ograniczonych prawach kopiowania"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Aktualizacje bezpieczeństwa do Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Aktualizacje do Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Aktualizacje do Ubuntu 4.10 (backporty)"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 7 \"Wheezy\" "
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 6.0 \"Squeeze\" "
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 5.0 \"Lenny\" "
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 4.0 \"Etch\""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Aktualizacje proponowane"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+msgid "Security updates"
+msgstr "Aktualizacje bezpieczeństwa"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr "Obecne wydanie stabilne Debiana"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr "Dystrybucja testowa Debiana"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian \"Sid\" (niestabilny)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "Oprogramowanie kompatybilne z DFSG z niewolnymi zależnościami"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Oprogramowanie niekompatybilne z DFSG"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Serwer dla kraju %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Serwer główny"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Inne serwery"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Pobieranie pliku %(current)li z %(total)li z prędkością %(speed)s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Pobieranie pliku %(current)li z %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Szczegóły"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr "Rozpoczynanie..."
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr "Zakończono"
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+"Nieprawidłowy znak unikodu w opisie pakietu \"%s\" (%s). Prosimy zgłosić ten "
+"błąd."
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "Lista zmian nie jest dostępna"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+"Lista zmian nie jest jeszcze dostępna.\n"
+"\n"
+"Proszę użyć http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"dopóki zmiany nie będą dostępne lub spróbować ponownie później."
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Nie udało się pobrać listy zmian. \n"
+"Proszę sprawdzić swoje połączenie internetowe."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr "Nie można odczytać listy plików \"%s\""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr "Nie można odczytać listy plików kontrolnych \"%s\""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr "Zależność nie może być spełniona: %s\n"
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr "Konflikty z zainstalowanym pakietem \"%s\""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+"Psuje istniejący pakiet \"%(pkgname)s\" zależność %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+"Psuje istniejący pakiet \"%(pkgname)s\" konflikt: %(targetpkg)s "
+"(%(comptype)s %(targetver)s)"
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+"Psuje istniejący pakiet \"%(pkgname)s\", następującym konfliktem: "
+"\"%(targetpkg)s\". Jest on udostępniany przez \"%(debfile)s\" za pomocą: "
+"\"%(provides)s\""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr "Brak pola architektury (Architecture) w pakiecie"
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr "Nieprawidłowa architektura \"%s\""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr "Nowsza wersja jest już zainstalowana"
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr "Nie udało się spełnić wszystkich zależności (zepsuta pamięć podręczna)"
+
+#: ../apt/debfile.py:519
+#, python-format
+msgid "Cannot install '%s'"
+msgstr "Nie można zainstalować \"%s\""
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+"Automatycznie rozpakowano:\n"
+"\n"
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr "Automatycznie skonwertowano do drukowalnego ascii:\n"
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+"Instalacja zależności czasu budowania pakietu źródłowego \"%s\", który "
+"buduje %s\n"
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr "Istotny pakiet musiałby zostać usunięty"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr "%c%s... Gotowe"
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr "Stary "
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr "Ign. "
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr "Błąd "
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr "Pobieranie:"
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr " [Pracuje]"
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+"Zmiana nośnika: proszę włożyć płytę oznaczoną\n"
+" \"%s\"\n"
+"do napędu \"%s\" i wcisnąć enter\n"
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr "Pobrano %sB w %s (%sB/s)\n"
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr "Proszę wprowadzić nazwę dla tej płyty, np. \"Debian 2.1r1 Disk 1\""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr "Proszę włożyć dysk do napędu i nacisnąć enter"
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr "Budowanie struktur danych"
diff --git a/po/pt.po b/po/pt.po
new file mode 100644
index 0000000..aca824f
--- /dev/null
+++ b/po/pt.po
@@ -0,0 +1,657 @@
+# Portuguese translation of update-manager.
+# Copyright (C) 2005 Free Software Foundation, Inc.
+# This file is distributed under the same license as the update-manager package.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-16 11:04+0000\n"
+"Last-Translator: Tiago Silva <tiagosilva29@gmail.com>\n"
+"Language-Team: Ubuntu Portuguese Team <ubuntu-pt.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Actualizações de Segurança do Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Cdrom com o Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Cdrom com Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+#| msgid "Ubuntu 4.10 'Warty Warthog'"
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Cdrom com Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Cdrom com Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Cdrom com o Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Cdrom com Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Cdrom com Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Cdrom com o Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Cdrom com o Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Actualizações de Segurança do Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Cdrom com o Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Actualizações de Segurança do Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Cdrom com o Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "Mantido pela comunidade"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Software Restrito"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "Cdrom com o Ubuntu 6.10 'Edgy Eft'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "Software de Código Aberto suportado pela Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "Mantido pela comunidade (universal)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "Software de Código Fonte Aberto mantido pela comunidade"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Controladores não-livres"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Drivers proprietários para dispositivos"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Software não-livre (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "Software restringido por copyright ou questões legais"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Cdrom com o Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Actualizações de segurança importantes"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Actualizações recomendadas"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "Actualizações propostas"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "Actualizações dos repositórios \"backport\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Cdrom com o Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.10 Actualizações de Segurança"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.10 Actualizações"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 Backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Cdrom com o Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Suportado Oficialmente"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Actualizações de Segurança do Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Actualizações do Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Backports do Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "Mantido pela comunidade (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Não-livre (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "Cdrom com Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Sem mais suporte oficial"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Direitos de autor restritos"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Actualizações de Segurança do Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Actualizações do Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Backports do Ubuntu 4.10"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Actualizações propostas"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "Actualizações de segurança importantes"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "Debian \"Etch\" (testing)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian \"Sid\" (unstable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "Software compatível-DFSG com Dependências Não-Livres"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Software compatível-DFSG"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Servidor para %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Servidor principal"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Servidores personalizados"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "A descarregar ficheiro %(current)li de %(total)li a %(speed)s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "A descarregar ficheiro %(current)li de %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Detalhes"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr ""
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "A lista de alterações não está disponível."
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Falha ao descarregar a lista de alterações. \n"
+"Por favor verifique a sua ligação à Internet."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "Impossível de instalar '%s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "Um pacote essencial teria que ser removido"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/pt_BR.po b/po/pt_BR.po
new file mode 100644
index 0000000..fe0d5ce
--- /dev/null
+++ b/po/pt_BR.po
@@ -0,0 +1,648 @@
+# Brazilian Portuguese translation for python-apt.
+# This file is distributed under the same licence as the update-manager package.
+# Sérgio Cipolla <secipolla@gmail.com>, 2010 - 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:42+0200\n"
+"PO-Revision-Date: 2012-06-10 15:53-0300\n"
+"Last-Translator: Sérgio Cipolla <secipolla@gmail.com>\n"
+"Language-Team: \n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: Portuguese\n"
+"X-Poedit-Country: BRAZIL\n"
+"Plural-Forms: nplurals=2; plural=n > 1\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 12.04 'Precise Pangolin'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "CD-ROM com o Ubuntu 12.04 'Precise Pangolin'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 11.10 'Oneiric Ocelot'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "CD-ROM com o Ubuntu 11.10 'Oneiric Ocelot'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 11.04 'Natty Narwhal'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "CD-ROM com o Ubuntu 11.04 'Natty Narwhal'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 10.10 'Maverick Meerkat'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "CD-ROM com o Ubuntu 10.10 'Maverick Meerkat'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr "Parceiros da Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr "Aplicativos empacotados pela Canonical para os seus parceiros"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr "Estes aplicativos não são parte do Ubuntu."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr "Independentes"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr "Fornecidos por desenvolvedores de software terceiros"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr "Aplicativos oferecidos por desenvolvedores terceiros."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 10.04 'Lucid Lynx'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "CD-ROM com o Ubuntu 10.04 'Lucid Lynx'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 9.10 'Karmic Koala'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "CD-ROM com o Ubuntu 9.10 'Karmic Koala'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 9.04 'Jaunty Jackalope'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "CD-ROM com o Ubuntu 9.04 'Jaunty Jackalope'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 8.10 'Intrepid Ibex'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "CD-ROM com o Ubuntu 8.10 'Intrepid Ibex'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 8.04 'Hardy Heron'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "CD-ROM com o Ubuntu 8.04 'Hardy Heron'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 7.10 'Gutsy Gibbon'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "CD-ROM com o Ubuntu 7.10 'Gutsy Gibbon'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 7.04 'Feisty Fawn'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "CD-ROM com o Ubuntu 7.04 'Feisty Fawn'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr "Mantido pela comunidade"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Aplicativos restritos"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "CD-ROM com o Ubuntu 6.10 'Edgy Eft'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+msgid "Canonical-supported free and open-source software"
+msgstr "Aplicativos livres de código aberto suportados pela Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr "Mantido pela comunidade (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+msgid "Community-maintained free and open-source software"
+msgstr "Aplicativos livres de código aberto mantidos pela comunidade"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Drivers não-livres"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Drivers proprietários para dispositivos"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Aplicativos restritos (multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "Aplicativos restritos por copyright ou questões legais"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "CD-ROM com o Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Atualizações de segurança importantes"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Atualizações recomendadas"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr "Atualizações de pré-lançamento"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+msgid "Unsupported updates"
+msgstr "Atualizações não suportadas"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "CD-ROM com o Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Atualizações de segurança do Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Atualizações do Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Backports do Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "CD-ROM com o Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Suportados oficialmente"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Atualizações de segurança do Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Atualizações do Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Backports do Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr "Mantido pela comunidade (universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Não-livres (multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "CD-ROM com o Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Não mais suportado oficialmente"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Copyright restrito"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Atualizações de segurança do Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Atualizações do Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Backports do Ubuntu 4.10"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 7 'Wheezy' "
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 6.0 'Squeeze' "
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 5.0 'Lenny' "
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 4.0 'Etch'"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 'Sarge'"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Atualizações sugeridas"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+msgid "Security updates"
+msgstr "Atualizações de segurança"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr "Atual versão estável do Debian"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr "Debian testing"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian 'Sid' (unstable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "Aplicativos compatíveis com a DFSG mas com dependências não-livres"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Aplicativos não compatíveis com a DFSG"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Servidor - %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Servidor principal"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Servidores personalizados"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Baixando arquivo %(current)li de %(total)li a %(speed)s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Baixando arquivo %(current)li de %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Detalhes"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr "Iniciando..."
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr "Completo"
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr "Unicode inválido na descrição de '%s' (%s). Por favor, relate o erro."
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "A lista de alterações não está disponível"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+"A lista de alterações ainda não está disponível.\n"
+"\n"
+"Por favor, utilize http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"até que as alterações estejam disponíveis ou tente novamente mais tarde."
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Falha ao baixar a lista de alterações. \n"
+"Por favor verifique sua conexão com a Internet."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr "A lista de arquivos de '%s' não pôde ser lida"
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr "A lista de arquivos de controle de '%s' não pôde ser lida"
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr "A dependência não é contentável: %s\n"
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr "Conflita com o pacote instalado '%s'"
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+"Quebra o pacote existente '%(pkgname)s', dependência %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+"Quebra o pacote existente '%(pkgname)s', conflito: %(targetpkg)s "
+"(%(comptype)s %(targetver)s)"
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+"Quebra o pacote existente '%(pkgname)s' que conflita com '%(targetpkg)s'. "
+"Mas '%(debfile)s' o provê via '%(provides)s'"
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr "Sem campo de arquitetura no pacote"
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr "Arquitetura incorreta '%s'"
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr "Uma versão mais atual já está instalada"
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr "Falha na satisfação de todas as dependências (cache quebrado)"
+
+#: ../apt/debfile.py:519
+#, python-format
+msgid "Cannot install '%s'"
+msgstr "Incapaz de instalar '%s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+"Descompactado automaticamente:\n"
+"\n"
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr "Convertido automaticamente para ascii imprimível:\n"
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+"Instalar dependências construtivas para o pacote fonte '%s' que constrói %s\n"
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr "Um pacote essencial teria de ser removido"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr "%c%s... Feito"
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr "Atingido "
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr "Ignorando "
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr "Erro "
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr "Obtendo:"
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr " [Trabalhando]"
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+"Mudança de mídia: por favor, insira o disco de nome\n"
+"'%s'\n"
+"no drive '%s' e tecle Enter\n"
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr "Obtidos %sB em %s (%sB/s)\n"
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+"Por favor, forneça um nome para este disco, como 'Debian 6.0.1 Disco 1'"
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr "Por favor, insira um disco no drive e tecle Enter"
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr "Construindo estruturas de dados"
+
+#~ msgid "Python-debian module not available"
+#~ msgstr "Módulo python-debian não disponível"
+
+#~ msgid "Failed to fetch %s %s\n"
+#~ msgstr "Falha ao buscar %s, %s\n"
+
+#~ msgid "--fix-missing and media swapping is not currently supported"
+#~ msgstr "--fix-missing e troca de mídia não são suportados atualmente"
+
+#~ msgid "This is not a valid DEB archive, missing '%s' member"
+#~ msgstr "Este não é um arquivo DEB válido, membro '%s' faltando"
diff --git a/po/python-apt.pot b/po/python-apt.pot
new file mode 100644
index 0000000..a422fa1
--- /dev/null
+++ b/po/python-apt.pot
@@ -0,0 +1,365 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2023-11-22 15:35+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:33
+msgid "Ubuntu development series"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:112
+msgid "Canonical-supported free and open-source software"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:114
+msgid "Community-maintained"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:115
+msgid "Community-maintained free and open-source software"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:117
+msgid "Non-free drivers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:118
+msgid "Proprietary drivers for devices"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:121
+msgid "Restricted software"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:122
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:129
+msgid "Ubuntu {version} '{codename}'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:137
+msgid "Installation medium with Ubuntu {version} '{codename}'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:140 ../data/templates/Debian.info.in:113
+msgid "Officially supported"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:142
+msgid "Restricted copyright"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:149
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:152
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:160
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:162
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:163
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:182
+msgid "Important security updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:195 ../data/templates/Debian.info.in:53
+msgid "Recommended updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:208
+msgid "Pre-released updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:221
+msgid "Unsupported updates"
+msgstr ""
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid ""
+"https://metadata.ftp-master.debian.org/changelogs/%s/%s/%s/%s_%s_changelog"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:25
+msgid "Debian {version} '{codename}'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:47
+msgid "Security updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:59
+msgid "Proposed updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:66
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:81
+msgid "Debian testing"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:111
+msgid "Debian 'Sid' (unstable)"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:115
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:117
+msgid "Non-DFSG-compatible Firmware for Hardware Support"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:119
+msgid "Non-DFSG-compatible Software"
+msgstr ""
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:461
+#, python-format
+msgid "Server for %s"
+msgstr ""
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:225 ../aptsources/distro.py:237
+#: ../aptsources/distro.py:258
+msgid "Main server"
+msgstr ""
+
+#: ../aptsources/distro.py:267
+msgid "Custom servers"
+msgstr ""
+
+#: ../apt/package.py:619
+#, python-format
+msgid "Missing description for '%s'.Please report."
+msgstr ""
+
+#: ../apt/package.py:629
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1330 ../apt/package.py:1346 ../apt/package.py:1459
+#: ../apt/package.py:1475
+msgid "The list of changes is not available"
+msgstr ""
+
+#: ../apt/package.py:1467
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1482
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+
+#: ../apt/debfile.py:96
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:108
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:242
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:272
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#: ../apt/debfile.py:434
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#: ../apt/debfile.py:465
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:482
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:543
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:555
+#, python-format
+msgid ""
+"Wrong architecture '%s' -- Run dpkg --add-architecture to add it and update "
+"afterwards"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:570
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:596
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:627
+#, python-format
+msgid "Cannot install '%s'"
+msgstr ""
+
+#: ../apt/debfile.py:707
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:713
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:824
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:838
+msgid "An essential package would be removed"
+msgstr ""
+
+#: ../apt/progress/text.py:97
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:143
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:153
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:155
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:167
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:238
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:252
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#: ../apt/progress/text.py:267
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:291
+msgid "Please provide a name for this medium, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:312
+msgid "Please insert an installation medium and press enter"
+msgstr ""
diff --git a/po/ro.po b/po/ro.po
new file mode 100644
index 0000000..05885f0
--- /dev/null
+++ b/po/ro.po
@@ -0,0 +1,663 @@
+# Romanian translation of update-manager.
+# Copyright (C) 2005 Free Software Foundation, Inc.
+# This file is distributed under the same license as the update-manager package.
+# Dan Damian <dand@gnome.ro>, 2005.
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-16 04:13+0000\n"
+"Last-Translator: Sami POTIRCA <spotirca@gmail.com>\n"
+"Language-Team: Romanian <gnomero-list@lists.sourceforge.net>\n"
+"Language: ro\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3;plural=(n==1?0:(n==0||((n%100)>0&&(n%100)<20))?"
+"1:2)\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Actualizări de Securitate Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Cdrom cu Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Cdrom cu Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+#| msgid "Ubuntu 4.10 'Warty Warthog'"
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Cdrom cu Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Cdrom cu Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Cdrom cu Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Cdrom cu Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Cdrom cu Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Cdrom cu Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Cdrom cu Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Actualizări de Securitate Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Cdrom cu Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Actualizări de Securitate Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Cdrom cu Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "Pachete întreţinute de comunitate (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+#, fuzzy
+msgid "Restricted software"
+msgstr "Software în contribuţie"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "Cdrom cu Ubuntu 6.10 'Edgy Eft'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "Pachete întreţinute de comunitate (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "Pachete întreţinute de comunitate (Universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "Pachete întreţinute de comunitate (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Pachete non-libere"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Software restricţionat (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Cdrom cu Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Actualizări importante de securitate"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Actualizări recomandate"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "Pachete propuse"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "Actualizări portate înapoi"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Cdrom cu Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Actualizări de Securitate Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Actualizări Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 Backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Cdrom cu Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Pachete suportate oficial"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Actualizări de Securitate Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Actualizări Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.04 Backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "Pachete întreţinute de comunitate (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Pachete non-libere (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "Cdrom cu Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+#, fuzzy
+msgid "No longer officially supported"
+msgstr "Pachete suportate oficial"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Copyright restrictiv"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Actualizări de securitate Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Actualizări Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 4.10 Backports"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Pachete propuse"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "Actualizări importante de securitate"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "Debian \"Etch\" (testing)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian \"Sid\" (unstable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "Software compatibil DFSG cu dependenţe negratuite"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Software incompatibil DFSG"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Server pentru %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Server principal"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Servere preferenţiale"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr ""
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Detalii"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr ""
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "Lista schimbărilor nu este disponibilă"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+#, fuzzy
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Nu am putut descărca lista modificărilor. Vă rog să verificaţi dacă aveţi o "
+"conexiune internet activă."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "Nu pot instala '%s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "Un pachet esenţial ar trebui şters"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/ru.po b/po/ru.po
new file mode 100644
index 0000000..4a457f0
--- /dev/null
+++ b/po/ru.po
@@ -0,0 +1,665 @@
+# Russian translation for update-manager
+# Copyright (c) (c) 2006 Canonical Ltd, and Rosetta Contributors 2006
+# This file is distributed under the same license as the update-manager package.
+# Igor Zubarev <igor4u@gmail.com>, 2006.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:42+0200\n"
+"PO-Revision-Date: 2006-10-18 09:11+0000\n"
+"Last-Translator: Igor Zubarev <igor4u@gmail.com>\n"
+"Language-Team: Russian <ru@li.org>\n"
+"Language: ru\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 12.04 'Precise Pangolin'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Диск с Ubuntu 12.04 'Precise Pangolin'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 11.10 'Oneiric Ocelot'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Диск с Ubuntu 11.10 'Oneiric Ocelot'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 11.04 'Natty Narwhal'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Диск с Ubuntu 11.04 'Natty Narwhal'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 10.10 'Maverick Meerkat'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Диск с Ubuntu 10.10 'Maverick Meerkat'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr "Партнеры Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr "Програмное обеспечение упаковано Canonical для партнеров"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr "Это програмное обеспечение не является частью Ubuntu."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr "Независимый"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr "Предоставлено сторонними разработчиками."
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr "Програмное обеспечение предлагается сторонними разработчиками."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 10.04 'Lucid Lynx'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Диск с Ubuntu 10.04 'Lucid Lynx'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 9.10 'Karmic Koala'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Диск с Ubuntu 9.10 'Karmic Koala'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 9.04 'Jaunty Jackalope'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Диск с Ubuntu 9.04 'Jaunty Jackalope'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 8.10 'Intrepid Ibex'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Диск с Ubuntu 8.10 'Intrepid Ibex'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 8.04 'Hardy Heron'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Диск с Ubuntu 8.04 'Hardy Heron'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Обновления безопасности Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Диск с Ubuntu 7.10 'Gutsy Gibbon'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 7.04 'Feisty Fawn'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Диск с Ubuntu 7.04 'Feisty Fawn'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "Поддерживается сообществом"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Несвободное ПО"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "CDROM с Ubuntu 6.10 'Edgy Eft'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "Open Source приложения, поддерживаемые Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "Поддерживается сообществом (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "Поддерживаемое сообществом свободное ПО"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Несвободные драйвера"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Проприетарные драйвера устройств"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Несвободное обеспечение (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "Программы, ограниченные патентами или законами"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "CD с Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Важные обновления безопасности"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Рекомендованые обновления"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "Пред-релизные обновления"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "Не поддерживаемые обновления"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "CD с Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Обновления безопасности Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Обновления Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 Backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "CD с Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Официально поддерживается"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Обновления безопасности Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Обновления Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.04 бэкпорты"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "Поддерживается сообществом (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Несвободное (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "CD с Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Официально больше не поддерживается"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Ограниченные авторские права"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Обновления безопасности Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Обновления Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 4.10 бэкпорты"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 7 'Wheezy' "
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 6.0 'Squeeze' "
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 5.0 'Lenny' "
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 4.0 'Etch'"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 'Sarge'"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Предлагаемые обновления"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "Обновления безопасности"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr "Текущий стабильный релиз Debian"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "Debian testing"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian 'Sid' (unstable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "DFSG-совместимое ПО с зависимостями от несвободного ПО"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Не-DFSG-совместимое ПО"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Сервер %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Основной сервер"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Свои сервера"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Загрузка файла %(current)li из %(total)li со скоростью %(speed)s/с"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Загрузка файла %(current)li из %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Подробности"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr "Начинаем..."
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr "Завершено"
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr "Неправильный unicode в описании '%s' (%s). Пожалуйста, сообщите."
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "Список изменений недоступен или отсутствует."
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+"Список изменений еще недоступен.\n"
+"\n"
+"Пожалуйста используйте http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"до тех пор, пока изменения не станут доступны или попробуйте позже."
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Ошибка при загрузке списка изменений. \n"
+"Пожалуйста, проверьте ваше соединение с Интернет."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr "Список файлов для '%s' не может быть прочтен"
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr "Список контролирующих файлов для '%s' не может быть прочтен"
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr "Неразрешимая зависимость: %s\n"
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr "Конфликт с установленым пакетом '%s'"
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+"Ломает в существующем пакете '%(pkgname)s' зависимость %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+"Ломает существующий пакет '%(pkgname)s' конфликтует с: %(targetpkg)s "
+"(%(comptype)s %(targetver)s)"
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr "Нет указания архитектуры в пакете"
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr "Неправильная архитектура '%s'"
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr "Более поздняя версия уже установлена"
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr "Неудалось определить все зависимости (broken cache)"
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "Невозможно установить '%s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "Будет удален необходимый пакет"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/sk.po b/po/sk.po
new file mode 100644
index 0000000..a34b84b
--- /dev/null
+++ b/po/sk.po
@@ -0,0 +1,638 @@
+# Slovak translation for update-manager
+# Copyright (C) 2006 Canonical Ltd, and Rosetta Contributors 2006
+# This file is distributed under the same license as the update-manager package.
+# Peter Chabada <sk-i18n_chabada_sk>, 2006.
+# Ivan Masár <helix84@centrum.sk>, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:42+0200\n"
+"PO-Revision-Date: 2012-06-10 23:28+0100\n"
+"Last-Translator: Ivan Masár <helix84@centrum.sk>\n"
+"Language-Team: Slovak <debian-l10n-slovak@lists.debian.org>\n"
+"Language: sk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural= (n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 12.04 „Precise Pangolin“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "CD-ROM s Ubuntu 12.04 „Precise Pangolin“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 11.10 „Oneiric Ocelot“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "CD-ROM s Ubuntu 11.10 „Oneiric Ocelot“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 11.04 „Natty Narwhal“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "CD-ROM s Ubuntu 11.04 „Natty Narwhal“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 10.10 „Maverick Meerkat“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "CD-ROM s Ubuntu 10.10 „Maverick Meerkat“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr "Partneri Canonicalu"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr "Balíky softvéru, ktoré pripravil Canonical pre svojich partnerov"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr "Tento softvér nie je súčasťou Ubuntu."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr "Nezávislé"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr "Poskytované vývojármi tretích strán"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr "Softvér, ktorý ponúkajú vývojári tretích strán."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 10.04 „Lucid Lynx“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "CD-ROM s Ubuntu 10.04 „Lucid Lynx“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 9.10 „Karmic Koala“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "CD-ROM s Ubuntu 9.10 „Karmic Koala“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 9.04 „Jaunty Jackalope“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "CD-ROM s Ubuntu 9.04 „Jaunty Jackalope“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 8.10 „Intrepid Ibex“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Disk s Ubuntu 5.04 „Hoary Hedgehog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 8.04 „Hardy Heron“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "CD-ROM s Ubuntu 8.04 „Hardy Heron“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 7.10 „Gutsy Gibbon“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "CD-ROM s Ubuntu 7.10 „Gutsy Gibbon“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 7.04 „Feisty Fawn“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "CD-ROM s Ubuntu 7.04 „Feisty Fawn“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 „Edgy Eft“"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr "Udržiavané komunitou"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Softvér závislý na neslobodnom softvéri"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "CD-ROM s Ubuntu 6.10 „Edgy Eft“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS „Dapper Drake“"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+msgid "Canonical-supported free and open-source software"
+msgstr "Slobodný a open source softvér, ktorý podporuje Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr "Udržiavané komunitou (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+msgid "Community-maintained free and open-source software"
+msgstr "Slobodný a open source softvér udržiavaný komunitou"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Neslobodné ovládače"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Proprietárne ovládače zariadení"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Neslobodný softvér (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "Softvér obmedzený autorskými právami alebo právnymi otázkami"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "CD-ROM s Ubuntu 6.06 LTS „Dapper Drake“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Dôležité bezpečnostné aktualizácie"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Odporúčané aktualizácie"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr "Aktualizácie pred vydaním"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+msgid "Unsupported updates"
+msgstr "Nepodporované aktualizácie"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "CD-ROM s Ubuntu 5.10 „Breezy Badger“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.10 - bezpečnostné aktualizácie"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.10 - aktualizácie"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 - backporty"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 „Hoary Hedgehog“"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "CD-ROM s Ubuntu 5.04 „Hoary Hedgehog“"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Oficiálne podporované"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Ubuntu 5.04 - bezpečnostné aktualizácie"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ubuntu 5.04 - aktualizácie"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.04 - backporty"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 „Warty Warthog“"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr "Udržiavané komunitou (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Neslobodné (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "CD-ROM s Ubuntu 4.10 „Warty Warthog“"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Už nie sú oficiálne podporované"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "S obmedzujúcou licenciou"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ubuntu 4.10 bezpečnostné aktualizácie"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Ubuntu 4.10 aktualizácie"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 4.10 - backporty"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 7 „Wheezy“ "
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 6.0 „Squeeze“ "
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 5.0 „Lenny“ "
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 4.0 „Etch“"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 „Sarge“"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Navrhované aktualizácie"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+msgid "Security updates"
+msgstr "Bezpečnostné aktualizácie"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr "Aktuálne vydanie Debian stable"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr "Debian testing"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian „Sid“ (nestabilné)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "Softvér kompatibilný s DFSG bez závislostí na neslobodnom softvére"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Softvér nekompatibilný s DFSG"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Server pre %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Hlavný server"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Vlastné servery"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Sťahuje sa súbor %(current)li z %(total)li pri %(speed)s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Sťahuje sa súbor %(current)li z %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Podrobnosti"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr "Spúšťa sa..."
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr "Hotovo"
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr "Neplatný Unicode v pospise „%s“ (%s). Nahláste to, prosím."
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "Zoznam zmien nie je k dispozícii"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+"Zoznam zmien zatiaľ nie je dostupný.\n"
+"\n"
+"Prosím, použite http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"pokým zmeny nebudú dostupné alebo to skúste znova neskôr."
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Nepodarilo sa stiahnuť zoznam zmien. \n"
+"Prosím, skontrolujte si svoje pripojenie k internetu."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr "Zoznam súborov „%s“ nebolo možné načítať"
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr "Zoznam riadiacich súborov „%s“ nebolo možné načítať"
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr "Závislosť nemožno uspokojiť: %s\n"
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr "Je v konflikte s nainštalovaným balíkom „%s“"
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+"Kazí závislosť %(depname)s (%(deprelation)s %(depversion)s) existujúceho "
+"balíka „'%(pkgname)s“"
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+"Kazí konflikt %(targetpkg)s (%(comptype)s %(targetver)s) existujúceho balíka "
+"„'%(pkgname)s“"
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+"Kazí existujúci balík „'%(pkgname)s“, ktorý je v konflikte s: "
+"„'%(targetpkg)s“. Ale „'%(debfile)s“ ho poskytuje prostredníctvom "
+"„'%(provides)s“"
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr "Balíku chýba pole Architecture (architektúra)"
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr "Nesprávna architektúra „%s“"
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr "Novšia verzia už je nainštalovaná"
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+"Nepodarilo sa uspokojiť všetky závislosti (poškodená vyrovnávacia pamäť)"
+
+#: ../apt/debfile.py:519
+#, python-format
+msgid "Cannot install '%s'"
+msgstr "Nie je možné bainštalovať „%s“"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+"Automaticky rozbalené:\n"
+"\n"
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr "Automaticky prevedené na tlačiteľné znaky ASCII:\n"
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+"Nainštalovať závislosti zostavenia zdrojového balíka „%s“, ktorý zostavuje "
+"%s\n"
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr "Bol by odstránený nevyhnutný balík"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr "%c%s... Hotovo"
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr "Stiah "
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr "Ignor "
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr "Chyba "
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr "Získať:"
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr " [Pracuje sa]"
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+"Výmena média: prosím, vložte disk s označením\n"
+" „%s“\n"
+"do mechaniky „%s“ a stlačte Enter\n"
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr "Stiahnutých %sB za %s (%sB/s)\n"
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr "Prosím, zadajte názov tohto disku. Napr. „Debian 2.1r1 Disk 1“"
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr "Prosím, vložte disk do mechaniky a stlačte Enter"
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr "Zostavujú sa údajové štruktúry"
diff --git a/po/sl.po b/po/sl.po
new file mode 100644
index 0000000..3c67f3e
--- /dev/null
+++ b/po/sl.po
@@ -0,0 +1,649 @@
+# Slovenian translation for python-apt-rosetta.
+# Copyright (c) (c) 2006 Canonical Ltd, and Rosetta Contributors 2006
+# This file is distributed under the same license as the python-apt-rosetta package.
+#
+# Matej Urbančič <mateju@svn.gnome.org>, 2006 - 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: python-apt-rosetta\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:42+0200\n"
+"PO-Revision-Date: 2012-06-10 22:24+0100\n"
+"Last-Translator: Matej Urbančič <mateju@svn.gnome.org>\n"
+"Language-Team: Slovenian <sl@li.org>\n"
+"Language: sl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n"
+"%100==4 ? 3 : 0);\n"
+"X-Launchpad-Export-Date: 2010-12-03 00:21+0000\n"
+"X-Generator: Launchpad (build Unknown)\n"
+"X-Poedit-Language: Slovenian\n"
+"X-Poedit-Country: SLOVENIA\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "xUbuntu 7.04 'Feisty Fawn'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Nosilec CD z Ubuntu 12.04 'Precise Pangolin'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "xUbuntu 10.10 'Maverick Meerkat'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Nosilec CD z Ubuntu 11.10 'Oneiric Ocelot'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "xUbuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Nosilec CD z Ubuntu 11.04 'Natty Narwhal'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 10.10 'Maverick Meerkat'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Nosilec CD z Ubuntu 10.10 'Maverick Meerkat'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr "Partnerske ustanove Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr "Programska oprema Canonical za partnerske ustanove"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr "Programska opreme ni del distribucije Ubuntu."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr "Neodvisno"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr "Programska oprema, ki jo objavljajo razvijalci skupnosti"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr "Programska oprema tretje roke."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 10.04 'Lucid Lynx'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Nosilec CD z Ubuntu 10.04 'Lucid Lynx'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 9.10 'Karmic Koala'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Nosilec CD z Ubuntu 9.10 'Karmic Koala'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 9.04 'Jaunty Jackalope'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Nosilec CD z Ubuntu 9.04 'Jaunty Jackalope'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 8.10 'Intrepid Ibex'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Nosilec CD z Ubuntu 8.10 'Intrepid Ibex'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 8.04 'Hardy Heron'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Nosilec CD z Ubuntu 8.04 'Hardy Heron'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 7.10 'Gutsy Gibbon'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Nosilec CD z Ubuntu 7.10 'Gutsy Gibbon'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 7.04 'Feisty Fawn'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Nosilec CD z Ubuntu 7.04 'Feisty Fawn'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr "Paketi skupnosti"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Avtorsko omejena programska oprema"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "Nosilec CD z Ubuntu 6.10 'Edgy Eft'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+msgid "Canonical-supported free and open-source software"
+msgstr "Odprtokodna programska oprema podprta s strani Canonical Ltd"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr "Paketi skupnosti (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+msgid "Community-maintained free and open-source software"
+msgstr "Programska oprema, ki jo vzdržuje odprtokodna skupnost"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Neprosti gonilniki"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Lastniški gonilniki za naprave"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Avtorsko omejena programska oprema (multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+"Programska oprema, ki je omejena z avtorskimi pravicami ali drugimi pravnimi "
+"vidiki"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Nosilec CD z Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Pomembne varnostne posodobitve"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Priporočene posodobitve"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr "Predhodno izdane posodobitve"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+msgid "Unsupported updates"
+msgstr "Nepodprte posodobitve"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Nosilec CD z Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.10 varnostne posodobitve"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.10 posodobitve"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 postarani paketi"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Nosilec CD z Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Uradno podprto"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Ubuntu 5.04 varnostne posodobitve"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ubuntu 5.04 posodobitve"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.04 postarani paketi"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr "Paketi skupnosti (universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Ne-prosti paketi (multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "Nosilec CD z Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Brez uradne podpore"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Omejeno z avtorskimi pravicami"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ubuntu 4.10 varnostne posodobitve"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Ubuntu 4.10 posodobitve"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 4.10 postarani paketi"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 7 'Wheezy' "
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 6.0 'Squeeze' "
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 5.0 'Lenny' "
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 4.0 'Etch'"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 'Sarge'"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Predlagane posodobitve"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+msgid "Security updates"
+msgstr "Varnostne posodobitve"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr "Debian trenutna stabilna različica"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr "Debian preizkusna različica"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian \"Sid\" (razvojna različica)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "Program je skladen z DFSG-compatible ne prostimi odvisnostmi"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Program ni skladen z DFSG"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Strežnik za %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Glavni strežnik"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Strežniki po meri"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr ""
+"Prejemanje datoteke %(current)li od skupno %(total)li s hitrostjo %(speed)s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Prejemanje datoteke %(current)li od skupno %(total)li."
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Podrobnosti"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr "Začenjanje ..."
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr "Končano"
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+"Neveljaven znak unikod v opisu za '%s' (%s). Pošljite poročilo o napaki."
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "Seznam sprememb ni na voljo"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+"Seznam sprememb še ni na voljo.\n"
+"\n"
+"Več podrobnosti je na http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"dokler dnevnik ne bo posodobljen ali pa poskusite kasneje."
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Prejemanje seznama sprememb je spodletelo.\n"
+"Preverite internetno povezavo."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr "Seznama datotek za '%s' ni mogoče prebrati"
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr "Nadzornega seznama datotek za '%s' ni mogoče prebrati"
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr "Odvisnost ni razrešena: %s\n"
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr "Spor z nameščenim paketom '%s'"
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+"Pokvari odvisnost obstoječega paketa '%(pkgname)s' %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+"Pokvari spor obstoječega paketa '%(pkgname)s': %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+"Pokvari obstoječi paket '%(pkgname)s', ki je v sporu s paketom: "
+"'%(targetpkg)s'. Paket '%(debfile)s' ga zagotavlja preko: '%(provides)s'"
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr "V paketu ni polja določila arhitekture sistema"
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr "Napačna arhitektura '%s'"
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr "Novejša različica je že nameščena."
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr "Ni mogoče razrešiti vseh odvisnosti (napaka v predpomnilniku)"
+
+#: ../apt/debfile.py:519
+#, python-format
+msgid "Cannot install '%s'"
+msgstr "Ni mogoče namestiti '%s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+"Samodejno razširjeno:\n"
+"\n"
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr "Samodejno pretvorjeno v zapis ASCII:\n"
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+"Namestiti je treba pakete za izgradnjo iz izvorne kode '%s' s katerimi je "
+"mogoče izgraditi %s\n"
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr "Z dejanjem bi bil odstranjen sistemski paket"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr "%c%s ... Končano."
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr "Zad "
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr "Prz "
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr "Nap "
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr "Pridobi:"
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr " [V delovanju]"
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+"Zamenjava nosilca: vstavite disk z oznako\n"
+" '%s'\n"
+"v enoto '%s' in pritisnite vnosno tipko\n"
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr "Pridobljenih %sB v %s (%sB/s)\n"
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr "Poimenujte disk, na primer 'Debian 2.1r1 Disk 1'"
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr "Vstavite disk v pogon in pritisnite vnosno tipko"
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr "Izgradnja podatkovnega drevesa"
+
+#~ msgid "Python-debian module not available"
+#~ msgstr "Modul Python-debian ni na voljo"
diff --git a/po/sq.po b/po/sq.po
new file mode 100644
index 0000000..5bf5e5d
--- /dev/null
+++ b/po/sq.po
@@ -0,0 +1,623 @@
+# Albanian translation for update-manager
+# Copyright (c) (c) 2006 Canonical Ltd, and Rosetta Contributors 2006
+# This file is distributed under the same license as the update-manager package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2006.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-09 15:50+0000\n"
+"Last-Translator: Alejdin Tirolli <a.tirolli@hotmail.com>\n"
+"Language-Team: Albanian <sq@li.org>\n"
+"Language: sq\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+msgid "Canonical-supported free and open-source software"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+msgid "Community-maintained free and open-source software"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "%s përmirësimet"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr ""
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+msgid "Debian 6.0 'Squeeze' "
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+msgid "Debian 5.0 'Lenny' "
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+msgid "Debian 4.0 'Etch'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+msgid "Debian 3.1 'Sarge'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "%s përmirësimet"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr ""
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Serveri për %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+#, fuzzy
+msgid "Main server"
+msgstr "Serveri më i afërt"
+
+#: ../aptsources/distro.py:250
+#, fuzzy
+msgid "Custom servers"
+msgstr "Serveri më i afërt"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr ""
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+#, fuzzy
+msgid "Details"
+msgstr "Përditë"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr ""
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr ""
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "'%s' nuk mund të instalohet"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "Një paketë themelore u deshtë të largohej"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/sr.po b/po/sr.po
new file mode 100644
index 0000000..7e2fbca
--- /dev/null
+++ b/po/sr.po
@@ -0,0 +1,648 @@
+# Serbian translation for update-manager
+# Copyright (c) (c) 2006 Canonical Ltd, and Rosetta Contributors 2006
+# This file is distributed under the same license as the update-manager package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2006.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:42+0200\n"
+"PO-Revision-Date: 2006-10-16 04:17+0000\n"
+"Last-Translator: Nikola Nenadic <nikola.nenadic@gmail.com>\n"
+"Language-Team: Serbian <sr@li.org>\n"
+"Language: sr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 12.04 'Precise Pangolin'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Оптички диск са Ubuntu 12.04 'Precise Pangolin'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 11.10 'Oneiric Ocelot'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Оптички диск са 11.10 'Oneiric Ocelot'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 11.04 'Natty Narwhal'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Оптички диск са Ubuntu 11.04 'Natty Narwhal'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 10.10 'Maverick Meerkat'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Оптички диск са Ubuntu 10.10 'Maverick Meerkat'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr "Canonical партнери"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr "Софтвер упакован од Canonical за њихове партнере"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr "Овај софтвер није дио Ubuntu"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr "Независан"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr "Обезбјеђен од независних програмера софтвера"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr "Софтвер је понуђен од независних програмера софтвера"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 10.04 'Lucid Lynx'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Оптички диск са Ubuntu 10.04 'Lucid Lynx'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 9.10 'Karmic Koala'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Оптички диск са Ubuntu 9.10 'Karmic Koala'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 9.04 'Jaunty Jackalope"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Оптички диск са Ubuntu 9.04 'Jaunty Jackalope"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 8.10 'Intrepid Ibex'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Оптички диск са Ubuntu 8.10 'Intrepid Ibex'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 8.04 'Hardy Heron'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Оптички диск са Ubuntu 8.04 'Hardy Heron'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 7.10 'Gutsy Gibbon'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Оптички диск са Ubuntu 7.10 'Gutsy Gibbon'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 7.04 'Feisty Fawn'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Оптички диск са Ubuntu 7.04 'Feisty Fawn'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr "Одржаван од стране заједнице"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Ограничени софтвер"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "Оптички диск са Ubuntu 6.10 'Edgy Eft'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "Canonical-подржава слободан софтвер и софтвер отвореног кода"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr "Одржаван од стране заједнице"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "Заједница одржава слободан софтвер и софтвер отвореног кода"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Комерцијални драјвери"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Власнички драјвери за уређаје"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Ограничени софтвер"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "Софтвер ограничен ауторским правом или правним регулативама"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Оптички диск са Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Важне сигурносне исправке"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Препоручено ажурирање"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr "Унапријед објављене исправке"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+msgid "Unsupported updates"
+msgstr "Некомпитабилна ажурирања"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Оптички диск са Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.10 сигурносне исправке"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.10 исправке"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 Backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Оптички диск са Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Званично подржани"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ubuntu 5.04 Исправке"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.04 Backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr "Одржаван од стране заједнице"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Не слободн драјвери"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "Оптички диск са Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Званично није више подржано"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Ограничена права"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ubuntu 4.10 сигурносне исправке"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Ubuntu 4.10 Исправке"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 4.10 Backports"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 7 'Wheezy' "
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 6.0 'Squeeze'"
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 5.0 'Lenny'"
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 4.0 'Etch'"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 'Sarge'"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Предложене исправке (ажурирања)"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+msgid "Security updates"
+msgstr "Сигурносне исправке"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr "Дебиан-тренутно стабилно издање"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr "Дебиан-тестирање"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian 'Sid' (нестабилно)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "DFSG-компитабилан са не слободним софтвером"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Непостоји-DFSG компитабилног софтвера"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Сервер за %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Главни сервер"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Прилагођени сервер"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Преузимам фајл %(current)li од %(total)li са %(speed)s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Преузимам фајл %(current)li од %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Детаљи"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr "Покретање..."
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr "Завршено"
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr "Неважећи unicode у опису за '%s' (%s). Молим извјештај"
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "Листа промјена није доступна"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+"Листа промјена није још доступна.\n"
+"Молимо искористите http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"док промјене не постану доступне или покушајте поново касније."
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Преузиманје листе промјена неуспјешно. \n"
+"Молимо провјерите своју конекцију са интернетом."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr "Листа фајлова за '%s' не може да се прочита"
+
+#: ../apt/debfile.py:93
+#, fuzzy, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr "Листа фајлова за '%s' не може да се прочита"
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr "Зависнот није задовољена: %s\n"
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr "Сукоби међу инсталираним пакетима '%s'"
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+"Прекид постојања пакета '%(pkgname)s' зависи од %(depname)s (%(deprelation)s "
+"%(depversion)s)"
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+"Прекид постојања пакета '%(pkgname)s' конфликт: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+
+#: ../apt/debfile.py:399
+#, fuzzy, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+"Прекид посојања пакета '%(pkgname)s' који је иѕаѕвао конфликт: "
+"'%(targetpkg)s'. Али '%(targetpkg)s' га даје преко: '%(provides)s'"
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr "Нема поља архитектуре у пакету"
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr "Погрешна архитектура '%s'"
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr "Новија верзија је већ инсталирана"
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr "Није успео да задовољи све зависности (грешка у кешу)"
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "Не могу да се инсталирају %s"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr "Аутомацка декомпресија:\n"
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr "Аутомацко пребацивање за штампање ascii:\n"
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr "Инсталирајте Build-Dependencies за кодни пакет '%s' који гради %s\n"
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr "Битан пакет би био уклоњен"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr "%c%s... Крај"
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr "Погодак"
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr "Игнорисано"
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr "Грешка"
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr "Узимам:"
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr "[Радим]"
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+"Молимо вас да убаците означени диск\n"
+" у оптички диск '%s' и притиснете enter\n"
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr "Преузето %sB in %s (%sB/s)\n"
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr "Молимо обезбједите име за диск, као нпр. 'Debian 2.1r1 Disk 1'"
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr "Молимо Вас да убаците диск у оптички уређај и притиснете enter"
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr "Изградња структуре података"
+
+#~ msgid "This is not a valid DEB archive, missing '%s' member"
+#~ msgstr "Ово није валидна DEB архива, недостаје '% с' члан"
diff --git a/po/sv.po b/po/sv.po
new file mode 100644
index 0000000..08e858b
--- /dev/null
+++ b/po/sv.po
@@ -0,0 +1,662 @@
+# Swedish messages for update-manager.
+# Copyright (C) 2005 Free Software Foundation, Inc.
+# Daniel Nylander <po@danielnylander.se>, 2006.
+# Christian Rose <menthos@menthos.com>, 2005.
+#
+# $Id: sv.po,v 1.5 2005/04/04 08:49:52 mvogt Exp $
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-16 05:06+0000\n"
+"Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
+"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
+"Language: sv\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Säkerhetsuppdateringar för Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Cd-rom med Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Cd-rom med Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+#| msgid "Ubuntu 4.10 'Warty Warthog'"
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Cd-rom med Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Cd-rom med Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Cd-rom med Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Cd-rom med Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Cd-rom med Ubuntu 4.10 \"Warty Warthog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Cd-rom med Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Cd-rom med Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Säkerhetsuppdateringar för Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Cd-rom med Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Säkerhetsuppdateringar för Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Cd-rom med Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 \"Edgy Eft\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "Gemenskapsunderhållen"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Inskränkt programvara"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "Cd-rom med Ubuntu 6.10 \"Edgy Eft\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS \"Dapper Drake\""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "Öppen källkodsprogramvara som stöds av Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "Gemenskapsunderhållen (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "Öppen källkodsprogramvara underhållen av gemenskapen"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Ickefria drivrutiner"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Properitära drivrutiner för enheter"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Inskränkt programvara (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "Programvara begränsad av upphovsrätt eller juridiska avtal"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Cd-rom med Ubuntu 6.06 LTS \"Dapper Drake\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Viktiga säkerhetsuppdateringar"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Rekommenderade uppdateringar"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "Föreslagna uppdateringar"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "Bakåtporterade uppdateringar"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Cd-rom med Ubuntu 5.10 \"Breezy Badger\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.10 Säkerhetsuppdateringar"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.10 Uppdateringar"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 Bakåtportar"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Cd-rom med Ubuntu 5.04 \"Hoary Hedgehog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Stöds officiellt"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Säkerhetsuppdateringar för Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Uppdateringar för Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Bakåtporteringar för Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 \"Warty Warthog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "Gemenskapsunderhållen (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Ickefri (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "Cd-rom med Ubuntu 4.10 \"Warty Warthog\""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Stöds inte längre officiellt"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Begränsad upphovsrätt"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Säkerhetsuppdateringar för Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Uppdateringar för Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Bakåtporteringar för Ubuntu 4.10"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Föreslagna uppdateringar"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "Viktiga säkerhetsuppdateringar"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "Debian \"Etch\" (testing)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian \"Sid\" (unstable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "DFSG-kompatibel programvara med icke-fria beroenden"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Icke-DFSG-kompatibel programvara"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Server för %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Huvudserver"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Anpassade servrar"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Hämtar fil %(current)li av %(total)li med %(speed)s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Hämtar fil %(current)li av %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Detaljer"
+
+#: ../apt/progress/gtk2.py:428
+#, fuzzy
+msgid "Starting..."
+msgstr "Söker..."
+
+#: ../apt/progress/gtk2.py:434
+#, fuzzy
+msgid "Complete"
+msgstr "Komponenter"
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "Listan över ändringar finns inte tillgänglig"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Misslyckades med att hämta listan över ändringar. \n"
+"Kontrollera din Internetanslutning."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, fuzzy, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr "Beroendeupplösning misslyckades"
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "Kan inte installera \"%s\""
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "Ett grundläggande paket skulle behöva tas bort"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/th.po b/po/th.po
new file mode 100644
index 0000000..bfc7ca6
--- /dev/null
+++ b/po/th.po
@@ -0,0 +1,659 @@
+# Thai translation for update-manager
+# Copyright (c) (c) 2006 Canonical Ltd, and Rosetta Contributors 2006
+# This file is distributed under the same license as the update-manager package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2006.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-16 04:17+0000\n"
+"Last-Translator: Roys Hengwatanakul <roysheng@gmail.com>\n"
+"Language-Team: Thai <th@li.org>\n"
+"Language: th\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "อูบันตู 5.04 ปรับปรุงด้านความปลอดภัย"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "ซีดีรอมที่มี อูบันตู 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "อูบันตู 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "ซีดีรอมที่มีอูบันตู 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+#| msgid "Ubuntu 4.10 'Warty Warthog'"
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "อูบันตู 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "ซีดีรอมที่มีอูบันตู 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "อูบันตู 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "ซีดีรอมที่มีอูบันตู 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "อูบันตู 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "ซีดีรอมที่มีอูบันตู 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "อูบันตู 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "ซีดีรอมที่มีอูบันตู 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "อูบันตู 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "ซีดีรอมที่มีอูบันตู 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "อูบันตู 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "ซีดีรอมที่มีอูบันตู 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "อูบันตู 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "ซีดีรอมที่มีอูบันตู 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "อูบันตู 5.04 ปรับปรุงด้านความปลอดภัย"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "ซีดีรอมที่มี อูบันตู 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "อูบันตู 5.04 ปรับปรุงด้านความปลอดภัย"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "ซีดีรอมที่มี อูบันตู 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "อูบันตู 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "ชุมชนดูแล"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "ซอฟต์แวร์จำกัดการใช้งาน"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "ซีดีรอมที่มีอูบันตู 6.10 'Edgy Eft'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "อูบันตู 6.06 LTS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "ซอฟต์แบบเปิดเผยสนับสนุนโดย Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "ชุมชนดูแล (Universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "ชุมชนดูแล ซอฟต์แวร์แบบเปิดเผย"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "ไดรเวอร์ที่ไม่ฟรี"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "ไดรเวอร์ที่มีกรรมสิทธิ์สำหรับอุปกรณ์"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "ซอฟต์แวร์จำกัดการใช้งาน(Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "ซอฟต์แวร์นี้มีลิขสิทธ์หรือข้อกฏหมายจำกัดอยู่"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "ซีดีรอมที่มีอูบันตู 6.06 LST 'Dapper Drake'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "ปรับปรุงด้านความปลอดภัยที่สำคัญ"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "การปรับปรุงที่แนะนำให้ทำ"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "การปรับปรุงที่เสนอให้ทำ"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "การปรับปรุงแบบย้อนหลัง"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "อูบันตู 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "ซีดีรอมที่มี อูบันตู 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "อูบันตู 5.10 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "อูบันตู 5.10 Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "อูบันตู 5.10 Backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "อูบันตู 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "ซีดีรอมที่มีอูบันตู 5.04 'Hoary Hedgehog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "สนับสนุนอย่างเป็นทางการ"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "อูบันตู 5.04 ปรับปรุงด้านความปลอดภัย"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "อูบันตู 5.04 ปรับปรุง"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "อูบันตู 5.04 พอร์ตย้อนหลัง"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "อูบันตู 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "ชุมชนดูแล (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "ไม่ฟรี(ลิขสิทธิ์)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "ซีดีรอมที่มีอูบันตู 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "ไม่ได้รับการสนับสนุนอย่างเป็นทางการแล้ว"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "จำกัดลิขสิทธิ์"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "อูบันตู 4.10 ปรับปรุงด้านความปลอดภัย"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "อูบันตู 4.10 ปรับปรุง"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "อูบันตู 4.10 พอร์ตย้อนหลัง"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "เดเบียน 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "เดเบียน 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "เดเบียน 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "เดเบียน 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "เดเบียน 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "การปรับปรุงที่เสนอให้ทำ"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "ปรับปรุงด้านความปลอดภัยที่สำคัญ"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "เดเบียน \"Etch\" (กำลังทดสอบ)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "เดเบียน \"Sid\" (ผันผวน)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "เข้ากับ DFSG ซอฟแวร์แต่ขึ้นอยู่กับไม่ฟรี"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "ไม่เข้ากับ DFSG ซอฟแวร์"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "เซิร์ฟเวอร์สำหรับประเทศ %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "เซิร์ฟเวอร์หลัก"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "เซิร์ฟเวอร์ที่กำหนดเอาเอง"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr ""
+"กำลังดาวน์โหลดไฟล์ที่ %(current)li จากทั้งหมด %(total)li ด้วยความเร็ว %(speed)s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "กำลังดาวน์โหลดไฟล์ที่ %(current)li จากทั้งหมด %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "รายละเอียด"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr ""
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "รายการของการเปลี่ยนแปลงยังไม่มีให้"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"ไม่สามารถดาวน์โหลดรายการของการเปลี่ยนแปลง \n"
+"กรุณาตรวจสอบการสื่อสารทางอินเตอร์เน็ตของคุณ"
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "ไม่สามารถติดตั้ง '%s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "แพจเกจที่สำคัญจะถูกลบออก"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/tl.po b/po/tl.po
new file mode 100644
index 0000000..3273376
--- /dev/null
+++ b/po/tl.po
@@ -0,0 +1,639 @@
+# Tagalog translation for update-manager
+# Copyright (c) (c) 2006 Canonical Ltd, and Rosetta Contributors 2006
+# This file is distributed under the same license as the update-manager package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2006.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:42+0200\n"
+"PO-Revision-Date: 2012-06-11 11:13+0800\n"
+"Last-Translator: Ariel S. Betan <ariel.betan@up.edu.ph>\n"
+"Language-Team: Tagalog <tl@li.org>\n"
+"Language: tl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n > 1\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 12.04 'Precise Pangolin'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Cdrom na may Ubuntu 12.04 'Precise Pangolin'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 11.10 'Oneiric Ocelot'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Cdrom na may Ubuntu 11.10 'Oneiric Ocelot'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 11.04 'Natty Narwhal'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Cdrom na may Ubuntu 11.04 'Natty Narwhal'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 10.10 'Maverick Meerkat'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Cdrom na may Ubuntu 10.10 'Maverick Meerkat'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr "Mga Kasama ng Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr "Software na pinakete ng Canonical para sa kanilang mga kasama"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr "Ang software na ito ay hindi bahagi ng Ubuntu."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr "Malaya"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr "Ipinamahagi ng mga third-party software developers"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr "Software na ibinigay mga third party developers "
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 10.04 'Lucid Lynx'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Cdrom na may Ubuntu 10.04 'Lucid Lynx'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 9.10 'Karmic Koala'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Cdrom na may Ubuntu 9.10 'Karmic Koala'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 9.04 'Jaunty Jackalope'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Cdrom na may Ubuntu 9.04 'Jaunty Jackalope'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 8.10 'Intrepid Ibex'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Cdrom na may Ubuntu 8.10 'Intrepid Ibex'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 8.04 'Hardy Heron'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Cdrom na may Ubuntu 8.04 'Hardy Heron'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 7.10 'Gutsy Gibbon'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Cdrom na may Ubuntu 7.10 'Gutsy Gibbon'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 7.04 'Feisty Fawn'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Cdrom na may Ubuntu 7.04 'Feisty Fawn'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr "Inaalagaan ng kumunidad"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Software na may mahigpit na gamit"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "Cdrom na may Ubuntu 6.10 'Edgy Eft'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+msgid "Canonical-supported free and open-source software"
+msgstr "Malaya at bukas na software suportado ng Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr "Inaalagaan ng kumunidad (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+msgid "Community-maintained free and open-source software"
+msgstr "Malaya at bukas na software suportado ng Canonical"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Hindi malayang drivers"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Proprietary drivers para sa mga devices"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Software na may mahigpit na gamit (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+"Software na may mahigpit na gamit dahil sa copyright o mga legal issues"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Cdrom na may Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Mga mahalagang updates pang-seguridad"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Mga mungkahing updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr "Mga updates bago ma-released"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+msgid "Unsupported updates"
+msgstr "Mga hindi suportadong updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Cdrom na may Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.10 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.10 Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 Backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Cdrom na may Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Opisyal na sinusuportahan"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Ubuntu 5.04 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ubuntu 5.04 Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.04 Backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr "Inaalagaan ng kumunidad (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Di-malaya (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "Cdrom na may Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Hindi na opisyal na sinusuportahan"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Mahigpit na copyright"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ubuntu 4.10 Security Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Ubuntu 4.10 Updates"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 4.10 Backports"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 7 'Wheezy' "
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 6.0 'Squeeze' "
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 5.0 'Lenny' "
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 4.0 'Etch'"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 'Sarge'"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Mga mungkahing updates"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+msgid "Security updates"
+msgstr "Mga updates pang-seguridad"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr "Kasalukuyang stable release ng Debian"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr "Debian testing"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian 'Sid' (unstable)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "Software na DFSG-compatible na may Di-Malayang mga Dependensiya"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "Software na Di-DFSG-compatible"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "Server para sa %s"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Pangunahing server"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Pasadyang mga servers"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Downloading file %(current)li of %(total)li with %(speed)s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Downloading file %(current)li of %(total)li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Mga Detalye"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr "Nagsisimula..."
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr "Kumpleto"
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+"Invalidong unicode sa deskripsyon para '%s' (%s). Mangyaring ipagbigay alam."
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "Ang talaan ng mga pagbabago ay wala"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+"Ang talaan ng mga pagbabago ay wala pa.\n"
+"\n"
+"Mangyaring gamitin http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"hanggang mayroon ng mga pagbabago o subukang muli mamaya."
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Bigo sa pag-download ng talaan ng mga pagbabago. \n"
+"Mangyaring suriin ang inyong koneksyon sa internet."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr "Ang talaan ng mga files para sa '%s' ay hindi mabasa"
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr "Ang talaan ng mga files na pang-kontrol para sa '%s' ay hindi mabasa"
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr "Ang Dependensiya ay hindi sapat: %s\n"
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr "Mga mga conflicts sa na-install na paketeng '%s'"
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+"Binabasag ang umiiral na paketeng '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+"Binabasag ang umiiral na paketeng '%(pkgname)s' conflict: %(targetpkg)s "
+"(%(comptype)s %(targetver)s)"
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+"Binabasag ang umiiral na paketeng '%(pkgname)s' na may conflict sa: "
+"'%(targetpkg)s'. Ngunit ang '%(debfile)s' ay nagbibigay nito sa pamamagitan "
+"ng: '%(provides)s'"
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr "Walang Architecture field sa loob ng pakete"
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr "Maling architecture '%s'"
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr "Mas naunang bersiyon ang kasalukuyang naka-install"
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr "Bigo na maging sapat ang lahat ng dependensiya (broken cache)"
+
+#: ../apt/debfile.py:519
+#, python-format
+msgid "Cannot install '%s'"
+msgstr "Hindi ma-install '%s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+"Automatikong na decompressed:\n"
+"\n"
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr "Automatikong na-convert sa printable ascii:\n"
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+"Install Build-Dependencies para sa pinagmulang pakete '%s' na nag-build ng "
+"%s\n"
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr "Isang kinakailangang pakete ang kailangang tanggalin"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr "%c%s... Tapos na"
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr "Hit "
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr "Ign "
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr "Err "
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr "Kunin:"
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr " [Nagtatrabaho]"
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+"Bagong media: magyaring ipasok ang disc na may label na\n"
+" '%s'\n"
+"sa drive '%s' at pindutin ang enter\n"
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr "Kinuha %sB sa %s (%sB/s)\n"
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+"Mangyaring magbigay ng pangalan para sa Disc, tulad ng 'Debian 2.1r1 Disk 1'"
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr "Mangyaring magpasok ng Disc sa drive at pindutin ang enter"
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr "Nagbubuo ng data structures"
diff --git a/po/tr.po b/po/tr.po
new file mode 100644
index 0000000..aea4661
--- /dev/null
+++ b/po/tr.po
@@ -0,0 +1,659 @@
+# Turkish translation for update-manager
+# Copyright (c) (c) 2006 Canonical Ltd, and Rosetta Contributors 2006
+# This file is distributed under the same license as the update-manager package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2006.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-21 20:58+0000\n"
+"Last-Translator: Atilla Karaman <atillakaraman@gmail.com>\n"
+"Language-Team: Turkish <tr@li.org>\n"
+"Language: tr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 5.04 Güvenlik Güncelleştirmeleri"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 5.10 'Breezy Badger' Cdrom'u"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 4.10 'Warty Warthog' Cdrom'u"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+#| msgid "Ubuntu 4.10 'Warty Warthog'"
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 4.10 'Warty Warthog' Cdrom'u"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 4.10 'Warty Warthog' Cdrom'u"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog' Cdrom'u"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 4.10 'Warty Warthog' Cdrom'u"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 4.10 'Warty Warthog' Cdrom'u"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog' Cdrom'u"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog' Cdrom'u"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 5.04 Güvenlik Güncelleştirmeleri"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 5.10 'Breezy Badger' Cdrom'u"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 5.04 Güvenlik Güncelleştirmeleri"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 5.10 'Breezy Badger' Cdrom'u"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "Topluluk tarafından bakılan"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "Kısıtlı yazılımlar"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft' Cdrom'u"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "Canonical Açık Kaynak yazılımı destekledi"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "Topluluk tarafından bakılan (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "Topluluk tarafından bakılan Açık Kaynak Kodlu yazılımlar"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "Özgür olmayan sürücüler"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "Aygıtlar için kapalı kaynak sürücüler"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "Kısıtlı yazılımlar (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "Yazılım telif haklarıyla veya yasal sorunlar sebebiyle kısıtlanmıştır"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake' Cdrom'u"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "Önemli güvenlik güncelleştirmeleri"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "Önerilen güncellemeler"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "Teklif edilmiş güncellemeler"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "Geritaşınmış (backported) güncellemeler"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger' Cdrom'u"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.10 Güvenlik Güncelleştirmeleri"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.10 Güvenlik Güncelleştirmeleri"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 Geritaşınmış Yazılımlar (Backports)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog' Cdrom'u"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Resmi olarak desteklenenler"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Ubuntu 5.04 Güvenlik Güncelleştirmeleri"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ubuntu 5.04 Güncelleştirmeleri"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.04 Geritaşınmış Yazılımlar (Backports)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "Topluluk tarafından bakılan (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Özgür olmayan (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog' Cdrom'u"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "Artık resmi olarak desteklenmiyor"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Sınırlı telif hakkı"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ubuntu 4.10 Güvenlik Güncelleştirmeleri"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Ubuntu 4.10 Güncelleştirmeleri"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 4.10 Geritaşınmış Yazılımlar (Backports)"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "Teklif edilmiş güncellemeler"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "Önemli güvenlik güncelleştirmeleri"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "Debian \"Etch\" (test)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian \"Sid\" (kararsız)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "Özgür Olmayan Bağımlılığı Bulunan DFSG Uyumlu Yazılım"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "DFSG Uyumlu Olmayan Yazılım"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "%s sunucusu"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "Ana sunucu"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "Özel sunucular"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr ""
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Ayrıntılar"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr ""
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr "Değişiklikler listesi erişilebilir değil"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Değişiklik listesini indirme başarısız oldu. \n"
+"Lütfen İnternet bağlantınızı kontrol edin."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "'%s' yüklenemiyor"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "Gerekli bir paketin kaldırılması gerekmekte"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/uk.po b/po/uk.po
new file mode 100644
index 0000000..9ed1185
--- /dev/null
+++ b/po/uk.po
@@ -0,0 +1,635 @@
+# translation of uk(5).po to Ukrainian
+# Maxim Dziumanenko <mvd@mylinux.ua>, 2005.
+# Vadim Abramchuck <Abram@email.ua>, 2006.
+# Ukrainian translation of update-manager.
+# Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+msgid ""
+msgstr ""
+"Project-Id-Version: uk(5)\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-16 04:15+0000\n"
+"Last-Translator: Vadim Abramchuck <abram@email.ua>\n"
+"Language-Team: Ukrainian <uk@li.org>\n"
+"Language: uk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Generator: KBabel 1.11.2\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "Підтримується спільнотою (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "Підтримується спільнотою (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "Підтримується спільнотою (Universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "Підтримується спільнотою (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "<b>Оновлення через Інтернет</b>"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "Офіційно підтримуються"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "Підтримується спільнотою (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Не-вільний (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Обмежені авторські права"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr ""
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "<b>Оновлення через Інтернет</b>"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "Debian \"Etch\" (тестовий)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian \"Sid\" (нестабільний)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr ""
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr ""
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr ""
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, fuzzy, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "Завантажується файл %li of %li at %s/s"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, fuzzy, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "Завантажується файл %li of %li at %s/s"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "Деталі"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr ""
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr ""
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+#, fuzzy
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"не вдається завантажити зміни. Перевірте чи активне з'єднання з Інтернет."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "Не можливо встановити '%s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "Це призведе до видалення !essential! пакунку системи"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/vi.po b/po/vi.po
new file mode 100644
index 0000000..31ac60c
--- /dev/null
+++ b/po/vi.po
@@ -0,0 +1,683 @@
+# Vietnamese translation for Update Manager.
+# Copyright © 2005 Gnome i18n Project for Vietnamese.
+# Clytie Siddall <clytie@riverland.net.au>, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager Gnome HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-16 04:17+0000\n"
+"Last-Translator: Tran The Trung <tttrung@hotmail.com>\n"
+"Language-Team: Vietnamese <gnomevi-list@lists.sourceforge.net>\n"
+"Language: vi\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+"X-Generator: LocFactoryEditor 1.2.2\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Bản cập nhật bảo mặt Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Đĩa CD chứa « Breezy Badger » của Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Đĩa CD chứa « Warty Warthog » của Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Đĩa CD chứa « Warty Warthog » của Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Đĩa CD chứa « Warty Warthog » của Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Đĩa CD chứa « Warty Warthog » của Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Đĩa CD chứa « Warty Warthog » của Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Đĩa CD chứa « Warty Warthog » của Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Đĩa CD chứa « Hoary Hedgehog » của Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Đĩa CD chứa « Hoary Hedgehog » của Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Đĩa CD chứa « Warty Warthog » của Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Đĩa CD chứa « Warty Warthog » của Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Đĩa CD chứa « Warty Warthog » của Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Đĩa CD chứa « Warty Warthog » của Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Đĩa CD chứa « Hoary Hedgehog » của Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Đĩa CD chứa « Hoary Hedgehog » của Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Đĩa CD chứa « Hoary Hedgehog » của Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Đĩa CD chứa « Hoary Hedgehog » của Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Bản cập nhật bảo mặt Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Đĩa CD chứa « Breezy Badger » của Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Bản cập nhật bảo mặt Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Đĩa CD chứa « Breezy Badger » của Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+#, fuzzy
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Bản cập nhật Ubuntu 5.10"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "Do cộng đồng bảo quản (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+#, fuzzy
+msgid "Restricted software"
+msgstr "Phần mềm đã đóng góp"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+#, fuzzy
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "Đĩa CD chứa « Warty Warthog » của Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+#, fuzzy
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Bản cập nhật Ubuntu 5.04"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "Do cộng đồng bảo quản (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "Do cộng đồng bảo quản (Universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "Do cộng đồng bảo quản (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+#, fuzzy
+msgid "Non-free drivers"
+msgstr "Không tự do (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+#, fuzzy
+msgid "Restricted software (Multiverse)"
+msgstr "Không tự do (Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+#, fuzzy
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Bản cập nhật Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+#, fuzzy
+msgid "Important security updates"
+msgstr "Bản cập nhật bảo mặt Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "Đang cài đặt bản cập nhật..."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "Đang cài đặt bản cập nhật..."
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+#, fuzzy
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Đĩa CD chứa « Breezy Badger » của Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+#, fuzzy
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Đĩa CD chứa « Breezy Badger » của Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Bản cập nhật bảo mặt Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Bản cập nhật Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+#, fuzzy
+msgid "Ubuntu 5.10 Backports"
+msgstr "Bản cập nhật Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+#, fuzzy
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Đĩa CD chứa « Hoary Hedgehog » của Ubuntu 5.04"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+#, fuzzy
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Đĩa CD chứa « Hoary Hedgehog » của Ubuntu 5.04"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+#, fuzzy
+msgid "Officially supported"
+msgstr "Được hỗ trợ một cách chính thức"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+#, fuzzy
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Bản cập nhật bảo mặt Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+#, fuzzy
+msgid "Ubuntu 5.04 Updates"
+msgstr "Bản cập nhật Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+#, fuzzy
+msgid "Ubuntu 5.04 Backports"
+msgstr "Bản cập nhật Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+#, fuzzy
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Đĩa CD chứa « Warty Warthog » của Ubuntu 4.10"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "Do cộng đồng bảo quản (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "Không tự do (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+#, fuzzy
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "Đĩa CD chứa « Warty Warthog » của Ubuntu 4.10"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+#, fuzzy
+msgid "No longer officially supported"
+msgstr "Được hỗ trợ một cách chính thức"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "Bản quyền bị giới hạn"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Bản cập nhật bảo mặt Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Bản cập nhật Ubuntu 4.10"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+#, fuzzy
+msgid "Ubuntu 4.10 Backports"
+msgstr "Bản cập nhật Ubuntu 5.10"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 3.1 « Sarge »"
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 3.1 « Sarge »"
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 3.1 « Sarge »"
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 3.1 « Sarge »"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 « Sarge »"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+#, fuzzy
+msgid "Proposed updates"
+msgstr "Đang cài đặt bản cập nhật..."
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "Bản cập nhật bảo mặt Ubuntu 5.10"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+#, fuzzy
+msgid "Debian current stable release"
+msgstr "Bất định Debian « Sid »"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "Thử ra Debian"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Không Mỹ Debian (Bất định)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr ""
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr ""
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr ""
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr ""
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+#, fuzzy
+msgid "Details"
+msgstr "<b>Chi tiết</b>"
+
+#: ../apt/progress/gtk2.py:428
+#, fuzzy
+msgid "Starting..."
+msgstr "Thiết lập"
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+#, fuzzy
+msgid "The list of changes is not available"
+msgstr "Có một bản phát hành Ubuntu mới công bố."
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+#, fuzzy
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+"Không tải thay đổi về được. Bạn hãy kiểm tra có kết nối đến Mạng hoạt động "
+"chưa."
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "Không thể cài đặt '%s'"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "Một gói quan trọng cần phải bị gỡ bỏ"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/zh_CN.po b/po/zh_CN.po
new file mode 100644
index 0000000..004245c
--- /dev/null
+++ b/po/zh_CN.po
@@ -0,0 +1,656 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# Funda Wang <fundawang@linux.net.cn>, 2005.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager HEAD\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2009-09-06 03:14+0000\n"
+"Last-Translator: Feng Chao <rainofchaos@gmail.com>\n"
+"Language-Team: zh_CN <i18n-translation@lists.linux.net.cn>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+#| msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 7.04‘(Feisty Fawn)’"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "已插入 Ubuntu 7.04 'Feisty Fawn' 光盘的光驱"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 6.10 'Edgy Eft' 光盘"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+#| msgid "Ubuntu 4.10 'Warty Warthog'"
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 4.10 'Warty Warthog'光盘"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+#| msgid "Ubuntu 4.10 'Warty Warthog'"
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 4.10 'Warty Warthog'光盘"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+#| msgid "Ubuntu 8.04 'Hardy Heron'"
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 8.04‘Hardy Heron’"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "已插入 Ubuntu 8.04 'Hardy Heron' 光盘的光驱"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+#| msgid "Ubuntu 4.10 'Warty Warthog'"
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 4.10 'Warty Warthog'光盘"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+#| msgid "Ubuntu 4.10 'Warty Warthog'"
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 4.10 'Warty Warthog'光盘"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+#| msgid "Ubuntu 8.04 'Hardy Heron'"
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 8.04‘Hardy Heron’"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "已插入 Ubuntu 8.04 'Hardy Heron' 光盘的光驱"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 8.04‘Hardy Heron’"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "已插入 Ubuntu 8.04 'Hardy Heron' 光盘的光驱"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 7.10‘Gutsy Gibbon’"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 7.10‘Gutsy Gibbon’光盘"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 7.04‘(Feisty Fawn)’"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "已插入 Ubuntu 7.04 'Feisty Fawn' 光盘的光驱"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+msgid "Community-maintained"
+msgstr "社区维护"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr "受限软件"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft' 光盘"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+#| msgid "Canonical-supported Open Source software"
+msgid "Canonical-supported free and open-source software"
+msgstr "Canonical 支持的开源软件"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+msgid "Community-maintained (universe)"
+msgstr "社区维护 (universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+#| msgid "Community-maintained Open Source software"
+msgid "Community-maintained free and open-source software"
+msgstr "社区维护的开源软件"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr "非开源或私有驱动"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr "设备的专有驱动"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr "受限软件(Multiverse)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr "有版权和合法性问题的的软件"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake' 光盘"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "重要安全更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "推荐更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+msgid "Pre-released updates"
+msgstr "提前释放出的更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+msgid "Unsupported updates"
+msgstr "不支持的更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger' 光盘"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.10 安全更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.10 更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr "Ubuntu 5.10 移植"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'光盘"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "官方支持"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Ubuntu 5.04 安全更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ubuntu 5.10 更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr "Ubuntu 5.04 Backports"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+msgid "Community-maintained (Universe)"
+msgstr "社区维护 (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "非自由"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog'光盘"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr "官方不再支持"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "版权受限"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ubuntu 4.10 安全更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Ubuntu 4.10 更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr "Ubuntu 4.10 Backports"
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 \"Sarge\""
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr "建议更新"
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+msgid "Security updates"
+msgstr "安全更新"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr "当前稳定的 Debian 发布"
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+msgid "Debian testing"
+msgstr "Debian testing"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian \"Sid\" (非稳定)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "带有非自由依赖关系的DFSG兼容软件"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "非DFSG兼容软件"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "%s 的服务器"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "主服务器"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "自定义服务器"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr ""
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr ""
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+msgid "The list of changes is not available"
+msgstr ""
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr ""
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, python-format
+msgid "Cannot install '%s'"
+msgstr ""
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+msgid "An essential package would be removed"
+msgstr ""
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/zh_HK.po b/po/zh_HK.po
new file mode 100644
index 0000000..08190a3
--- /dev/null
+++ b/po/zh_HK.po
@@ -0,0 +1,633 @@
+# Chinese (Hong Kong) translation of update-manager.
+# Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+# Abel Cheung <abel@oaka.org>, 2005, 2006.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager 0.42.2\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-16 04:15+0000\n"
+"Last-Translator: Abel Cheung <abelcheung@gmail.com>\n"
+"Language-Team: Chinese (Hong Kong) <community@linuxhall.org>\n"
+"Language: zh_HK\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "協力維護軟件 (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "協力維護軟件 (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "協力維護軟件 (Universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "協力維護軟件 (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "發行通告"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "網絡更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "正式支援"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "協力維護軟件 (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "非自由軟件 (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "版權受限"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr ""
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 3.1「Sarge」"
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 3.1「Sarge」"
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 3.1「Sarge」"
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 3.1「Sarge」"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1「Sarge」"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "網絡更新"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "Debian 「Etch」(測試版)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian 「Sid」(不穩定版)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "符合 DFSG 的軟件,但依賴於非自由軟件"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "和 DFSG 不相容的軟件"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr ""
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr ""
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr ""
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, fuzzy, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "正在下載檔案 %li/%li,下載速度為 %s/秒"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, fuzzy, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "正在下載檔案 %li/%li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "詳細資料"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr ""
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+#, fuzzy
+msgid "The list of changes is not available"
+msgstr "修改紀錄不存在,請稍後再試。"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+#, fuzzy
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr "無法下載更改紀錄。請檢查網絡連線是否正常。"
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "無法安裝「%s」"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "準備移除 %s 個套件。"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/po/zh_TW.po b/po/zh_TW.po
new file mode 100644
index 0000000..8fb1060
--- /dev/null
+++ b/po/zh_TW.po
@@ -0,0 +1,653 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: update-manager 0.41.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 14:31+0200\n"
+"PO-Revision-Date: 2006-10-16 04:15+0000\n"
+"Last-Translator: SOC Ho <soc.scho@gmail.com>\n"
+"Language-Team: Chinese (Taiwan) <zh-l10n@linux.org.tw>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0\n"
+
+#. ChangelogURI
+#: ../data/templates/Ubuntu.info.in.h:4
+#, no-c-format
+msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:151
+#, fuzzy
+msgid "Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 5.04安全性更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:158
+#, fuzzy
+msgid "Cdrom with Ubuntu 12.04 'Precise Pangolin'"
+msgstr "Ubuntu 5.10 'Breezy Badger'的光碟"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:269
+#, fuzzy
+msgid "Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:276
+#, fuzzy
+msgid "Cdrom with Ubuntu 11.10 'Oneiric Ocelot'"
+msgstr "含Ubuntu 4.10 'Warty Warthog'之光碟"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:388
+#, fuzzy
+#| msgid "Ubuntu 4.10 'Warty Warthog'"
+msgid "Ubuntu 11.04 'Natty Narwhal'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:395
+#, fuzzy
+#| msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgid "Cdrom with Ubuntu 11.04 'Natty Narwhal'"
+msgstr "含Ubuntu 4.10 'Warty Warthog'之光碟"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:486
+#, fuzzy
+msgid "Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:506
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.10 'Maverick Meerkat'"
+msgstr "含Ubuntu 4.10 'Warty Warthog'之光碟"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:518
+msgid "Canonical Partners"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:520
+msgid "Software packaged by Canonical for their partners"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:521
+msgid "This software is not part of Ubuntu."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:528
+msgid "Independent"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:530
+msgid "Provided by third-party software developers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:531
+msgid "Software offered by third party developers."
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:569
+#, fuzzy
+msgid "Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:589
+#, fuzzy
+msgid "Cdrom with Ubuntu 10.04 'Lucid Lynx'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'的光碟"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:632
+#, fuzzy
+msgid "Ubuntu 9.10 'Karmic Koala'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:652
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.10 'Karmic Koala'"
+msgstr "含Ubuntu 4.10 'Warty Warthog'之光碟"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:695
+#, fuzzy
+msgid "Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:714
+#, fuzzy
+msgid "Cdrom with Ubuntu 9.04 'Jaunty Jackalope'"
+msgstr "含Ubuntu 4.10 'Warty Warthog'之光碟"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:757
+#, fuzzy
+msgid "Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:777
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.10 'Intrepid Ibex'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'的光碟"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:821
+#, fuzzy
+msgid "Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:841
+#, fuzzy
+msgid "Cdrom with Ubuntu 8.04 'Hardy Heron'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'的光碟"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:886
+#, fuzzy
+msgid "Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 5.04安全性更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:905
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.10 'Gutsy Gibbon'"
+msgstr "Ubuntu 5.10 'Breezy Badger'的光碟"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:950
+#, fuzzy
+msgid "Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 5.04安全性更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:969
+#, fuzzy
+msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'"
+msgstr "Ubuntu 5.10 'Breezy Badger'的光碟"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1011
+msgid "Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1016
+#, fuzzy
+msgid "Community-maintained"
+msgstr "協力維護軟體 (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1022
+msgid "Restricted software"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1030
+msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'"
+msgstr "Ubuntu 6.10 'Edgy Eft'的光碟"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1072
+msgid "Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "Ubuntu 6.06 LTS 'Dapper Drake'"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1075
+#, fuzzy
+msgid "Canonical-supported free and open-source software"
+msgstr "協力維護軟體 (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1077
+#, fuzzy
+msgid "Community-maintained (universe)"
+msgstr "協力維護軟體 (Universe)"
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1078
+#, fuzzy
+msgid "Community-maintained free and open-source software"
+msgstr "協力維護軟體 (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1080
+msgid "Non-free drivers"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1081
+msgid "Proprietary drivers for devices"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1083
+msgid "Restricted software (Multiverse)"
+msgstr ""
+
+#. CompDescriptionLong
+#: ../data/templates/Ubuntu.info.in:1084
+msgid "Software restricted by copyright or legal issues"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1091
+msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'"
+msgstr "含Ubuntu 6.06 LTS 'Dapper Drake'之光碟"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1107
+msgid "Important security updates"
+msgstr "重要的安全更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1112
+msgid "Recommended updates"
+msgstr "建議的安全更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1117
+#, fuzzy
+msgid "Pre-released updates"
+msgstr "建議的安全更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1122
+#, fuzzy
+msgid "Unsupported updates"
+msgstr "重要的安全更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1133
+msgid "Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1148
+msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'"
+msgstr "Ubuntu 5.10 'Breezy Badger'的光碟"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1164
+msgid "Ubuntu 5.10 Security Updates"
+msgstr "Ubuntu 5.10安全性更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1169
+msgid "Ubuntu 5.10 Updates"
+msgstr "Ubuntu 5.10更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1174
+msgid "Ubuntu 5.10 Backports"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1185
+msgid "Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1200
+msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'"
+msgstr "Ubuntu 5.04 'Hoary Hedgehog'的光碟"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1203 ../data/templates/Debian.info.in:174
+msgid "Officially supported"
+msgstr "官方支援"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1216
+msgid "Ubuntu 5.04 Security Updates"
+msgstr "Ubuntu 5.04安全性更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1221
+msgid "Ubuntu 5.04 Updates"
+msgstr "Ubuntu 5.04更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1226
+msgid "Ubuntu 5.04 Backports"
+msgstr ""
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1232
+msgid "Ubuntu 4.10 'Warty Warthog'"
+msgstr "Ubuntu 4.10 'Warty Warthog'"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1238
+#, fuzzy
+msgid "Community-maintained (Universe)"
+msgstr "協力維護軟體 (Universe)"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1240
+msgid "Non-free (Multiverse)"
+msgstr "非自由軟體 (Multiverse)"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1247
+msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'"
+msgstr "含Ubuntu 4.10 'Warty Warthog'之光碟"
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1250
+msgid "No longer officially supported"
+msgstr ""
+
+#. CompDescription
+#: ../data/templates/Ubuntu.info.in:1252
+msgid "Restricted copyright"
+msgstr "版權受限制"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1259
+msgid "Ubuntu 4.10 Security Updates"
+msgstr "Ubuntu 4.10安全性更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1264
+msgid "Ubuntu 4.10 Updates"
+msgstr "Ubuntu 4.10更新"
+
+#. Description
+#: ../data/templates/Ubuntu.info.in:1269
+msgid "Ubuntu 4.10 Backports"
+msgstr ""
+
+#. ChangelogURI
+#: ../data/templates/Debian.info.in.h:4
+#, no-c-format
+msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+msgstr "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog"
+
+#. Description
+#: ../data/templates/Debian.info.in:8
+#, fuzzy
+msgid "Debian 7 'Wheezy' "
+msgstr "Debian 3.1 “Sarge”"
+
+#. Description
+#: ../data/templates/Debian.info.in:33
+#, fuzzy
+msgid "Debian 6.0 'Squeeze' "
+msgstr "Debian 3.1 “Sarge”"
+
+#. Description
+#: ../data/templates/Debian.info.in:58
+#, fuzzy
+msgid "Debian 5.0 'Lenny' "
+msgstr "Debian 3.1 “Sarge”"
+
+#. Description
+#: ../data/templates/Debian.info.in:83
+#, fuzzy
+msgid "Debian 4.0 'Etch'"
+msgstr "Debian 3.1 “Sarge”"
+
+#. Description
+#: ../data/templates/Debian.info.in:108
+#, fuzzy
+msgid "Debian 3.1 'Sarge'"
+msgstr "Debian 3.1 “Sarge”"
+
+#. Description
+#: ../data/templates/Debian.info.in:119
+msgid "Proposed updates"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:126
+#, fuzzy
+msgid "Security updates"
+msgstr "重要的安全更新"
+
+#. Description
+#: ../data/templates/Debian.info.in:133
+msgid "Debian current stable release"
+msgstr ""
+
+#. Description
+#: ../data/templates/Debian.info.in:146
+#, fuzzy
+msgid "Debian testing"
+msgstr "Debian “Etch”(測試版)"
+
+#. Description
+#: ../data/templates/Debian.info.in:172
+#, fuzzy
+msgid "Debian 'Sid' (unstable)"
+msgstr "Debian “Sid”(不穩定版)"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:176
+msgid "DFSG-compatible Software with Non-Free Dependencies"
+msgstr "符合 DFSG 的軟體,但有依賴於非自由軟體"
+
+#. CompDescription
+#: ../data/templates/Debian.info.in:178
+msgid "Non-DFSG-compatible Software"
+msgstr "不符合 DFSG 的軟體"
+
+#. TRANSLATORS: %s is a country
+#: ../aptsources/distro.py:206 ../aptsources/distro.py:436
+#, python-format
+msgid "Server for %s"
+msgstr "位於%s的伺服器"
+
+#. More than one server is used. Since we don't handle this case
+#. in the user interface we set "custom servers" to true and
+#. append a list of all used servers
+#: ../aptsources/distro.py:224 ../aptsources/distro.py:230
+#: ../aptsources/distro.py:246
+msgid "Main server"
+msgstr "主要伺服器"
+
+#: ../aptsources/distro.py:250
+msgid "Custom servers"
+msgstr "個人伺服器"
+
+#: ../apt/progress/gtk2.py:258 ../apt/progress/gtk2.py:314
+#, fuzzy, python-format
+msgid "Downloading file %(current)li of %(total)li with %(speed)s/s"
+msgstr "正在下載檔案 %li/%li,下載速度為 %s/秒"
+
+#: ../apt/progress/gtk2.py:264 ../apt/progress/gtk2.py:320
+#, fuzzy, python-format
+msgid "Downloading file %(current)li of %(total)li"
+msgstr "正在下載檔案 %li/%li"
+
+#. Setup some child widgets
+#: ../apt/progress/gtk2.py:340
+msgid "Details"
+msgstr "詳細資料"
+
+#: ../apt/progress/gtk2.py:428
+msgid "Starting..."
+msgstr ""
+
+#: ../apt/progress/gtk2.py:434
+msgid "Complete"
+msgstr ""
+
+#: ../apt/package.py:359
+#, python-format
+msgid "Invalid unicode in description for '%s' (%s). Please report."
+msgstr ""
+
+#: ../apt/package.py:1088 ../apt/package.py:1194
+#, fuzzy
+msgid "The list of changes is not available"
+msgstr "修改紀錄不存在,請稍後再試。"
+
+#: ../apt/package.py:1200
+#, python-format
+msgid ""
+"The list of changes is not available yet.\n"
+"\n"
+"Please use http://launchpad.net/ubuntu/+source/%s/%s/+changelog\n"
+"until the changes become available or try again later."
+msgstr ""
+
+#: ../apt/package.py:1207
+#, fuzzy
+msgid ""
+"Failed to download the list of changes. \n"
+"Please check your Internet connection."
+msgstr "無法下載更動列表。請檢查網路連線是否正常。"
+
+#: ../apt/debfile.py:82
+#, python-format
+msgid "List of files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:93
+#, python-format
+msgid "List of control files for '%s' could not be read"
+msgstr ""
+
+#: ../apt/debfile.py:211
+#, python-format
+msgid "Dependency is not satisfiable: %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:232
+#, python-format
+msgid "Conflicts with the installed package '%s'"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that breaks, the second the dependency that makes it break, the third the relation (e.g. >=) and the latest the version for the releation
+#: ../apt/debfile.py:373
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' dependency %(depname)s "
+"(%(deprelation)s %(depversion)s)"
+msgstr ""
+
+#. TRANSLATORS: the first '%s' is the package that conflicts, the second the packagename that it conflicts with (so the name of the deb the user tries to install), the third is the relation (e.g. >=) and the last is the version for the relation
+#: ../apt/debfile.py:389
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' conflict: %(targetpkg)s (%(comptype)s "
+"%(targetver)s)"
+msgstr ""
+
+#: ../apt/debfile.py:399
+#, python-format
+msgid ""
+"Breaks existing package '%(pkgname)s' that conflict: '%(targetpkg)s'. But "
+"the '%(debfile)s' provides it via: '%(provides)s'"
+msgstr ""
+
+#: ../apt/debfile.py:447
+msgid "No Architecture field in the package"
+msgstr ""
+
+#: ../apt/debfile.py:457
+#, python-format
+msgid "Wrong architecture '%s'"
+msgstr ""
+
+#. the deb is older than the installed
+#: ../apt/debfile.py:464
+msgid "A later version is already installed"
+msgstr ""
+
+#: ../apt/debfile.py:489
+msgid "Failed to satisfy all dependencies (broken cache)"
+msgstr ""
+
+#: ../apt/debfile.py:519
+#, fuzzy, python-format
+msgid "Cannot install '%s'"
+msgstr "無法安裝‘%s’"
+
+#: ../apt/debfile.py:593
+msgid ""
+"Automatically decompressed:\n"
+"\n"
+msgstr ""
+
+#: ../apt/debfile.py:599
+msgid "Automatically converted to printable ascii:\n"
+msgstr ""
+
+#: ../apt/debfile.py:689
+#, python-format
+msgid "Install Build-Dependencies for source package '%s' that builds %s\n"
+msgstr ""
+
+#: ../apt/debfile.py:700
+#, fuzzy
+msgid "An essential package would be removed"
+msgstr "將會移除的核心套件"
+
+#: ../apt/progress/text.py:82
+#, python-format
+msgid "%c%s... Done"
+msgstr ""
+
+#: ../apt/progress/text.py:122
+msgid "Hit "
+msgstr ""
+
+#: ../apt/progress/text.py:131
+msgid "Ign "
+msgstr ""
+
+#: ../apt/progress/text.py:133
+msgid "Err "
+msgstr ""
+
+#: ../apt/progress/text.py:144
+msgid "Get:"
+msgstr ""
+
+#: ../apt/progress/text.py:203
+msgid " [Working]"
+msgstr ""
+
+#: ../apt/progress/text.py:214
+#, python-format
+msgid ""
+"Media change: please insert the disc labeled\n"
+" '%s'\n"
+"in the drive '%s' and press enter\n"
+msgstr ""
+
+#. Trick for getting a translation from apt
+#: ../apt/progress/text.py:223
+#, python-format
+msgid "Fetched %sB in %s (%sB/s)\n"
+msgstr ""
+
+#: ../apt/progress/text.py:239
+msgid "Please provide a name for this Disc, such as 'Debian 2.1r1 Disk 1'"
+msgstr ""
+
+#: ../apt/progress/text.py:255
+msgid "Please insert a Disc in the drive and press enter"
+msgstr ""
+
+#: ../apt/cache.py:157
+msgid "Building data structures"
+msgstr ""
diff --git a/pre-build.sh b/pre-build.sh
new file mode 100755
index 0000000..930be76
--- /dev/null
+++ b/pre-build.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+set -e
+
+echo "Running pycodestyle test"
+black --check . || [ "$IGNORE_BLACK" ] || \
+ [ "$IGNORE_PYCODESTYLE" ] || [ "$IGNORE_PEP8" ]
+
+dpkg-checkbuilddeps -d 'python3-debian, python3-feedparser'
+
+echo "updating Ubuntu mirror list from launchpad"
+if [ -n "$https_proxy" ]; then
+ echo "disabling https_proxy as Python's urllib doesn't support it; see #94130"
+ unset https_proxy
+fi
+utils/get_ubuntu_mirrors_from_lp.py > data/templates/Ubuntu.mirrors
+
+echo "updating Debian mirror list"
+utils/get_debian_mirrors.py > data/templates/Debian.mirrors
diff --git a/python/acquire-item.cc b/python/acquire-item.cc
new file mode 100644
index 0000000..af79fd9
--- /dev/null
+++ b/python/acquire-item.cc
@@ -0,0 +1,356 @@
+/*
+ * acquire-item.cc - Wrapper around pkgAcquire::Item and pkgAcqFile.
+ *
+ * Copyright 2004-2009 Canonical Ltd.
+ * Copyright 2009 Julian Andres Klode <jak@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include "generic.h"
+#include "apt_pkgmodule.h"
+
+#include <apt-pkg/acquire-item.h>
+#include <map>
+
+using namespace std;
+
+inline pkgAcquire::Item *acquireitem_tocpp(PyObject *self)
+{
+ pkgAcquire::Item *itm = GetCpp<pkgAcquire::Item*>(self);
+ if (itm == 0)
+ PyErr_SetString(PyExc_ValueError, "Acquire() has been shut down or "
+ "the AcquireFile() object has been deallocated.");
+ return itm;
+}
+
+static PyObject *acquireitem_get_complete(PyObject *self, void *closure)
+{
+ pkgAcquire::Item *item = acquireitem_tocpp(self);
+ return item ? PyBool_FromLong(item->Complete) : 0;
+}
+
+static PyObject *acquireitem_get_desc_uri(PyObject *self, void *closure)
+{
+ pkgAcquire::Item *item = acquireitem_tocpp(self);
+ return item ? CppPyString(item->DescURI()) : 0;
+}
+
+static PyObject *acquireitem_get_destfile(PyObject *self, void *closure)
+{
+ pkgAcquire::Item *item = acquireitem_tocpp(self);
+ return item ? CppPyPath(item->DestFile) : 0;
+}
+
+
+static PyObject *acquireitem_get_error_text(PyObject *self, void *closure)
+{
+ pkgAcquire::Item *item = acquireitem_tocpp(self);
+ return item ? CppPyString(item->ErrorText) : 0;
+}
+
+static PyObject *acquireitem_get_filesize(PyObject *self, void *closure)
+{
+ pkgAcquire::Item *item = acquireitem_tocpp(self);
+ return item ? MkPyNumber(item->FileSize) : 0;
+}
+
+static PyObject *acquireitem_get_id(PyObject *self, void *closure)
+{
+ pkgAcquire::Item *item = acquireitem_tocpp(self);
+ return item ? MkPyNumber(item->ID) : 0;
+}
+
+static PyObject *acquireitem_get_active_subprocess(PyObject *self, void *closure)
+{
+ pkgAcquire::Item *item = acquireitem_tocpp(self);
+#if APT_PKG_MAJOR >= 5
+ return item ? Py_BuildValue("s", item->ActiveSubprocess.c_str()) : 0;
+#else
+ return item ? Py_BuildValue("s", item->Mode) : 0;
+#endif
+}
+
+static PyObject *acquireitem_get_mode(PyObject *self, void *closure)
+{
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,
+ "AcquireItem.mode is deprecated, use AcquireItem.active_subprocess instead.", 1) == -1)
+ return NULL;
+ return acquireitem_get_active_subprocess(self, closure);
+}
+
+static PyObject *acquireitem_get_is_trusted(PyObject *self, void *closure)
+{
+ pkgAcquire::Item *item = acquireitem_tocpp(self);
+ return item ? PyBool_FromLong(item->IsTrusted()) : 0;
+}
+
+static PyObject *acquireitem_get_local(PyObject *self, void *closure)
+{
+ pkgAcquire::Item *item = acquireitem_tocpp(self);
+ return item ? PyBool_FromLong(item->Local) : 0;
+}
+
+static PyObject *acquireitem_get_partialsize(PyObject *self, void *closure)
+{
+ pkgAcquire::Item *item = acquireitem_tocpp(self);
+ return item ? MkPyNumber(item->PartialSize) : 0;
+}
+
+static PyObject *acquireitem_get_status(PyObject *self, void *closure)
+{
+ pkgAcquire::Item *item = acquireitem_tocpp(self);
+ return item ? MkPyNumber(item->Status) : 0;
+}
+
+static int acquireitem_set_id(PyObject *self, PyObject *value, void *closure)
+{
+ pkgAcquire::Item *Itm = acquireitem_tocpp(self);
+ if (Itm == 0)
+ return -1;
+ if (PyLong_Check(value)) {
+ Itm->ID = PyLong_AsUnsignedLong(value);
+ }
+ else if (PyInt_Check(value)) {
+ Itm->ID = PyInt_AsLong(value);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "value must be integer.");
+ return -1;
+ }
+ return 0;
+}
+
+
+static PyGetSetDef acquireitem_getset[] = {
+ {"complete",acquireitem_get_complete,0,
+ "A boolean value determining whether the item has been fetched\n"
+ "completely"},
+ {"desc_uri",acquireitem_get_desc_uri,NULL,
+ "A string describing the URI from which the item is acquired."},
+ {"destfile",acquireitem_get_destfile,NULL,
+ "The path to the file where the item will be stored."},
+ {"error_text",acquireitem_get_error_text,NULL,
+ "If an error occurred, a string describing the error; empty string\n"
+ "otherwise."},
+ {"filesize",acquireitem_get_filesize,NULL,
+ "The size of the file (number of bytes). If unknown, it is set to 0."},
+ {"id",acquireitem_get_id,acquireitem_set_id,
+ "The ID of the item. An integer which can be set by progress classes."},
+ {"mode",acquireitem_get_mode,NULL,
+ "Old name for active_subprocess"},
+ {"active_subprocess",acquireitem_get_active_subprocess,NULL,
+ "The name of the active subprocess (for instance, 'gzip', 'rred' or 'gpgv')."},
+ {"is_trusted",acquireitem_get_is_trusted,NULL,
+ "Whether the item is trusted or not. Only True for packages\n"
+ "which come from a repository signed with one of the keys in\n"
+ "APT's keyring."},
+ {"local",acquireitem_get_local,NULL,
+ "Whether we are fetching a local item (copy:/) or not."},
+ {"partialsize",acquireitem_get_partialsize,NULL,
+ "The amount of data which has already been fetched (number of bytes)."},
+ {"status",acquireitem_get_status,NULL,
+ "An integer representing the item's status which can be compared\n"
+ "against one of the STAT_* constants defined in this class."},
+ {}
+};
+
+static PyObject *acquireitem_repr(PyObject *Self)
+{
+ pkgAcquire::Item *Itm = acquireitem_tocpp(Self);
+ if (Itm == 0)
+ return 0;
+
+ string repr;
+ strprintf(repr, "<%s object:"
+ "Status: %i Complete: %i Local: %i IsTrusted: %i "
+ "FileSize: %llu DestFile:'%s' "
+ "DescURI: '%s' ID:%lu ErrorText: '%s'>",
+ Self->ob_type->tp_name,
+ Itm->Status, Itm->Complete, Itm->Local, Itm->IsTrusted(),
+ Itm->FileSize, Itm->DestFile.c_str(), Itm->DescURI().c_str(),
+ Itm->ID,Itm->ErrorText.c_str());
+ // Use CppPyPath here, the string may contain a path, so we should
+ // decode it like one.
+ return CppPyPath(repr);
+}
+
+static void acquireitem_dealloc(PyObject *self)
+{
+ CppDeallocPtr<pkgAcquire::Item*>(self);
+}
+
+static const char *acquireitem_doc =
+ "Represent a single item to be fetched by an Acquire object.\n\n"
+ "It is not possible to construct instances of this class directly.\n"
+ "Prospective users should construct instances of a subclass such as\n"
+ "AcquireFile instead. It is not possible to create subclasses on the\n"
+ "Python level, only on the C++ level.";
+PyTypeObject PyAcquireItem_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.AcquireItem", // tp_name
+ sizeof(CppPyObject<pkgAcquire::Item*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ acquireitem_dealloc, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ acquireitem_repr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT |
+ Py_TPFLAGS_HAVE_GC, // tp_flags
+ acquireitem_doc, // tp_doc
+ CppTraverse<pkgAcquire::Item*>, // tp_traverse
+ CppClear<pkgAcquire::Item*>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ acquireitem_getset, // tp_getset
+};
+
+static PyObject *acquirefile_new(PyTypeObject *type, PyObject *Args, PyObject * kwds)
+{
+ PyObject *pyfetcher;
+ PyObject *pyhashes = nullptr;
+ HashStringList hashes;
+ const char *uri, *descr, *shortDescr;
+ PyApt_Filename destDir, destFile;
+ unsigned long long size = 0;
+ uri = descr = shortDescr = destDir = destFile = "";
+
+ char *kwlist[] = {"owner", "uri", "hash", "size", "descr", "short_descr",
+ "destdir", "destfile", NULL
+ };
+#if PY_MAJOR_VERSION >= 3
+ const char *fmt = "O!s|OKssO&O&";
+#else
+ // no "$" support to indicate that the remaining args are keyword only
+ // in py2.x :/
+ const char *fmt = "O!s|OKssO&O&";
+#endif
+ if (PyArg_ParseTupleAndKeywords(Args, kwds, fmt, kwlist,
+ &PyAcquire_Type, &pyfetcher, &uri,
+ &pyhashes,
+ &size, &descr, &shortDescr,
+ PyApt_Filename::Converter, &destDir,
+ PyApt_Filename::Converter, &destFile) == 0)
+ return 0;
+
+ if (pyhashes == nullptr)
+ ;
+ else if (PyString_Check(pyhashes))
+ hashes = HashStringList(PyString_AsString(pyhashes));
+ else if (PyObject_TypeCheck(pyhashes, &PyHashStringList_Type))
+ hashes = GetCpp <HashStringList>(pyhashes);
+ else
+ return PyErr_SetString(PyExc_TypeError, "'hash' value must be an apt_pkg.HashStringList or a string"), nullptr;
+
+ pkgAcquire *fetcher = GetCpp<pkgAcquire*>(pyfetcher);
+ pkgAcqFile *af = new pkgAcqFile(fetcher, // owner
+ uri, // uri
+ hashes, // hash
+ size, // size
+ descr, // descr
+ shortDescr,
+ destDir,
+ destFile); // short-desc
+ CppPyObject<pkgAcqFile*> *AcqFileObj = CppPyObject_NEW<pkgAcqFile*>(pyfetcher, type);
+ AcqFileObj->Object = af;
+ return AcqFileObj;
+}
+
+
+static char *acquirefile_doc =
+ "AcquireFile(owner, uri[, hash: Union[apt_pkg.HashStringList, str], size, descr, short_descr, destdir,"
+ "destfile])\n\n"
+ "Represent a file to be fetched. The parameter 'owner' points to\n"
+ "an apt_pkg.Acquire object and the parameter 'uri' to the source\n"
+ "location. Normally, the file will be stored in the current directory\n"
+ "using the file name given in the URI. This directory can be changed\n"
+ "by passing the name of a directory to the 'destdir' parameter. It is\n"
+ "also possible to set a path to a file using the 'destfile' parameter,\n"
+ "but both cannot be specified together.\n"
+ "\n"
+ "The parameters 'short_descr' and 'descr' can be used to specify\n"
+ "a short description and a longer description for the item. This\n"
+ "information is used by progress classes to refer to the item and\n"
+ "should be short, for example, package name as 'short_descr' and\n"
+ "and something like 'http://localhost sid/main python-apt 0.7.94.2'\n"
+ "as 'descr'."
+ "\n"
+ "The parameters 'hash' and 'size' are used to verify the resulting\n"
+ "file. The parameter 'size' is also to calculate the total amount\n"
+ "of data to be fetched and is useful for resuming a interrupted\n"
+ "download.\n\n"
+ "All parameters can be given by name (i.e. as keyword arguments).";
+
+PyTypeObject PyAcquireFile_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.AcquireFile", // tp_name
+ sizeof(CppPyObject<pkgAcqFile*>),// tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ acquireitem_dealloc, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE |
+ Py_TPFLAGS_HAVE_GC,
+ acquirefile_doc, // tp_doc
+ CppTraverse<pkgAcqFile*>, // tp_traverse
+ CppClear<pkgAcqFile*>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ &PyAcquireItem_Type, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ acquirefile_new, // tp_new
+};
+
diff --git a/python/acquire.cc b/python/acquire.cc
new file mode 100644
index 0000000..aab899f
--- /dev/null
+++ b/python/acquire.cc
@@ -0,0 +1,424 @@
+/* acquire.cc - Wrapper for pkgAcquire.
+ *
+ * Copyright 2004-2009 Canonical Ltd
+ * Copyright 2009 Julian Andres Klode <jak@debian.org>
+ *
+ * Authors: Michael Vogt
+ * Julian Andres Klode
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include "generic.h"
+#include "apt_pkgmodule.h"
+#include "progress.h"
+
+#include <apt-pkg/acquire-item.h>
+#include <apt-pkg/acquire-worker.h>
+
+
+static PyObject *acquireworker_get_current_item(PyObject *self, void *closure)
+{
+ pkgAcquire::Worker *worker = GetCpp<pkgAcquire::Worker*>(self);
+ pkgAcquire::ItemDesc *desc = worker->CurrentItem;
+ if (desc == NULL) {
+ Py_RETURN_NONE;
+ }
+ PyObject *PyAcq = GetOwner<pkgAcquire::Worker*>(self);
+ PyObject *PyItem = PyAcquireItem_FromCpp(desc->Owner, false, PyAcq);
+ PyObject *PyDesc = PyAcquireItemDesc_FromCpp(desc, false, PyItem);
+ Py_XDECREF(PyItem);
+ return PyDesc;
+}
+
+static PyObject *acquireworker_get_status(PyObject *self, void *closure)
+{
+ return CppPyString(GetCpp<pkgAcquire::Worker*>(self)->Status);
+}
+
+static PyObject *acquireworker_get_current_size(PyObject *self, void *closure)
+{
+ if (GetCpp<pkgAcquire::Worker*>(self)->CurrentItem == nullptr)
+ return 0;
+ return MkPyNumber(GetCpp<pkgAcquire::Worker*>(self)->CurrentItem->CurrentSize);
+}
+
+static PyObject *acquireworker_get_total_size(PyObject *self, void *closure)
+{
+ if (GetCpp<pkgAcquire::Worker*>(self)->CurrentItem == nullptr)
+ return 0;
+ return MkPyNumber(GetCpp<pkgAcquire::Worker*>(self)->CurrentItem->TotalSize);
+}
+
+static PyObject *acquireworker_get_resumepoint(PyObject *self, void *closure)
+{
+ if (GetCpp<pkgAcquire::Worker*>(self)->CurrentItem == nullptr)
+ return 0;
+ return MkPyNumber(GetCpp<pkgAcquire::Worker*>(self)->CurrentItem->ResumePoint);
+}
+
+static PyGetSetDef acquireworker_getset[] = {
+ {"current_item",acquireworker_get_current_item,0,
+ "The item currently being fetched, as an apt_pkg.AcquireItemDesc object."},
+ {"status",acquireworker_get_status,0,
+ "The status of the worker, as a string."},
+ {"current_size",acquireworker_get_current_size,0,
+ "The amount of data fetched so far for the current item."},
+ {"total_size",acquireworker_get_total_size,0,
+ "The total size of the item."},
+ {"resumepoint",acquireworker_get_resumepoint,0,
+ "The amount of data which was already available when the download was\n"
+ "started."},
+ {NULL}
+};
+
+static const char *acquireworker_doc =
+ "Represent a sub-process responsible for fetching files from\n"
+ "remote locations. This sub-process uses 'methods' located in\n"
+ "the directory specified by the configuration option\n"
+ "Dir::Bin::Methods.";
+PyTypeObject PyAcquireWorker_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.AcquireWorker", // tp_name
+ sizeof(CppPyObject<pkgAcquire::Worker*>),// tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgAcquire::Worker*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT| // tp_flags
+ Py_TPFLAGS_HAVE_GC,
+ acquireworker_doc, // tp_doc
+ CppTraverse<pkgAcquire::Worker*>, // tp_traverse
+ CppClear<pkgAcquire::Worker*>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ acquireworker_getset, // tp_getset
+};
+
+
+static pkgAcquire::ItemDesc* acquireitemdesc_tocpp(PyObject *self) {
+ pkgAcquire::ItemDesc *item = GetCpp<pkgAcquire::ItemDesc*>(self);
+ if (item == NULL)
+ PyErr_SetString(PyExc_ValueError, "Acquire has been shutdown");
+ return item;
+}
+
+static PyObject *acquireitemdesc_get_uri(PyObject *self, void *closure)
+{
+ pkgAcquire::ItemDesc *item = acquireitemdesc_tocpp(self);
+ return item ? CppPyString(item->URI) : NULL;
+}
+static PyObject *acquireitemdesc_get_description(PyObject *self, void *closure)
+{
+ pkgAcquire::ItemDesc *item = acquireitemdesc_tocpp(self);
+ return item ? CppPyString(item->Description) : NULL;
+}
+static PyObject *acquireitemdesc_get_shortdesc(PyObject *self, void *closure)
+{
+ pkgAcquire::ItemDesc *item = acquireitemdesc_tocpp(self);
+ return item ? CppPyString(item->ShortDesc) : NULL;
+}
+static PyObject *acquireitemdesc_get_owner(CppPyObject<pkgAcquire::ItemDesc*> *self, void *closure)
+{
+ if (self->Owner != NULL) {
+ Py_INCREF(self->Owner);
+ return self->Owner;
+ }
+ else if (self->Object) {
+ self->Owner = PyAcquireItem_FromCpp(self->Object->Owner, false, NULL);
+ Py_INCREF(self->Owner);
+ return self->Owner;
+ }
+ Py_RETURN_NONE;
+}
+
+static PyGetSetDef acquireitemdesc_getset[] = {
+ {"uri",acquireitemdesc_get_uri,0,
+ "The URI from which this item would be downloaded."},
+ {"description",acquireitemdesc_get_description,0,
+ "A string describing the item."},
+ {"shortdesc",acquireitemdesc_get_shortdesc,0,
+ "A short string describing the item (e.g. package name)."},
+ {"owner",(getter)acquireitemdesc_get_owner,0,
+ "The owner of the item, an apt_pkg.AcquireItem object."},
+ {NULL}
+};
+
+static char *acquireitemdesc_doc =
+ "Provide the description of an item and the URI the item is\n"
+ "fetched from. Progress classes make use of such objects to\n"
+ "retrieve description and other information about an item.";
+PyTypeObject PyAcquireItemDesc_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.AcquireItemDesc", // tp_name
+ sizeof(CppPyObject<pkgAcquire::ItemDesc*>),// tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgAcquire::ItemDesc*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_HAVE_GC),
+ acquireitemdesc_doc, // tp_doc
+ CppTraverse<pkgAcquire::ItemDesc*>,// tp_traverse
+ CppClear<pkgAcquire::ItemDesc*>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ acquireitemdesc_getset, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ 0, // tp_new
+};
+
+static PyObject *PkgAcquireRun(PyObject *Self,PyObject *Args)
+{
+ pkgAcquire *fetcher = GetCpp<pkgAcquire*>(Self);
+
+ int pulseInterval = 500000;
+ if (PyArg_ParseTuple(Args, "|i", &pulseInterval) == 0)
+ return 0;
+
+ pkgAcquire::RunResult run = fetcher->Run(pulseInterval);
+
+ return HandleErrors(MkPyNumber(run));
+}
+
+
+static PyObject *PkgAcquireShutdown(PyObject *Self,PyObject *Args)
+{
+ pkgAcquire *fetcher = GetCpp<pkgAcquire*>(Self);
+ if (PyArg_ParseTuple(Args, "") == 0)
+ return 0;
+ fetcher->Shutdown();
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static PyObject *PkgAcquireGetLock(PyObject *Self,PyObject *Args)
+{
+ pkgAcquire *fetcher = GetCpp<pkgAcquire*>(Self);
+ PyApt_Filename path;
+ if (PyArg_ParseTuple(Args, "O&", PyApt_Filename::Converter, &path) == 0)
+ return 0;
+ fetcher->GetLock(path);
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+
+
+static PyMethodDef PkgAcquireMethods[] = {
+ {"run",PkgAcquireRun,METH_VARARGS,
+ "run() -> int\n\nRun the fetcher and return one of RESULT_CANCELLED,\n"
+ "RESULT_CONTINUE, RESULT_FAILED.\n\n"
+ "RESULT_CONTINUE means that all items which where queued prior to\n"
+ "calling run() have been fetched successfully or failed transiently.\n\n"
+ "RESULT_CANCELLED means canceled by the progress class.\n\n"
+ "RESULT_FAILED means a generic failure."},
+ {"shutdown",PkgAcquireShutdown, METH_VARARGS,
+ "shutdown()\n\n"
+ "Shut the fetcher down, removing all items from it. Future access to\n"
+ "queued AcquireItem objects will cause a segfault. The partial result\n"
+ "is kept on the disk and not removed and APT might reuse it."},
+ {"get_lock",PkgAcquireGetLock, METH_VARARGS,
+ "get_lock(log: str)\n\n"
+ "Acquires a log for the given directory, using a file 'lock' in it."},
+ {}
+};
+
+#define fetcher (GetCpp<pkgAcquire*>(Self))
+static PyObject *PkgAcquireGetTotalNeeded(PyObject *Self,void*)
+{
+ return MkPyNumber(fetcher->TotalNeeded());
+}
+static PyObject *PkgAcquireGetFetchNeeded(PyObject *Self,void*)
+{
+ return MkPyNumber(fetcher->FetchNeeded());
+}
+static PyObject *PkgAcquireGetPartialPresent(PyObject *Self,void*)
+{
+ return MkPyNumber(fetcher->PartialPresent());
+}
+#undef fetcher
+
+static PyObject *PkgAcquireGetWorkers(PyObject *self, void *closure)
+{
+ PyObject *List = PyList_New(0);
+ pkgAcquire *Owner = GetCpp<pkgAcquire*>(self);
+ PyObject *PyWorker = NULL;
+ for (pkgAcquire::Worker *Worker = Owner->WorkersBegin();
+ Worker != 0; Worker = Owner->WorkerStep(Worker)) {
+ PyWorker = PyAcquireWorker_FromCpp(Worker, false, self);
+ PyList_Append(List, PyWorker);
+ Py_DECREF(PyWorker);
+ }
+ return List;
+}
+static PyObject *PkgAcquireGetItems(PyObject *Self,void*)
+{
+ pkgAcquire *fetcher = GetCpp<pkgAcquire*>(Self);
+ PyObject *List = PyList_New(0);
+ PyObject *Obj;
+ for (pkgAcquire::ItemIterator I = fetcher->ItemsBegin();
+ I != fetcher->ItemsEnd(); I++) {
+ Obj = PyAcquireItem_FromCpp(*I, false, Self);
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+static PyGetSetDef PkgAcquireGetSet[] = {
+ {"fetch_needed",PkgAcquireGetFetchNeeded,0,
+ "The total amount of data to be fetched (number of bytes)."},
+ {"items",PkgAcquireGetItems,0,
+ "A list of all items as apt_pkg.AcquireItem objects, including already\n"
+ "fetched ones and to be fetched ones."},
+ {"workers",PkgAcquireGetWorkers,0,
+ "A list of all active workers as apt_pkg.AcquireWorker objects."},
+ {"partial_present",PkgAcquireGetPartialPresent,0,
+ "The amount of data which is already available (number of bytes)."},
+ {"total_needed",PkgAcquireGetTotalNeeded,0,
+ "The amount of data that needs to fetched plus the amount of data\n"
+ "which has already been fetched (number of bytes)."},
+ {}
+};
+
+static PyObject *PkgAcquireNew(PyTypeObject *type,PyObject *Args,PyObject *kwds)
+{
+ pkgAcquire *fetcher;
+
+ PyObject *pyFetchProgressInst = NULL;
+ char *kwlist[] = {"progress", 0};
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"|O",kwlist,&pyFetchProgressInst) == 0)
+ return 0;
+
+ PyFetchProgress *progress = 0;
+ if (pyFetchProgressInst != NULL) {
+ // FIXME: memleak?
+ progress = new PyFetchProgress();
+ progress->setCallbackInst(pyFetchProgressInst);
+ }
+
+ fetcher = new pkgAcquire();
+ fetcher->SetLog(progress);
+
+ PyObject *FetcherObj = CppPyObject_NEW<pkgAcquire*>(NULL, type, fetcher);
+
+ if (progress != 0)
+ progress->setPyAcquire(FetcherObj);
+ // prepare our map of items.
+ return HandleErrors(FetcherObj);
+}
+
+/**
+ * Create a new apt_pkg.Acquire Python object from the pkgAcquire object.
+ */
+PyObject *PyAcquire_FromCpp(pkgAcquire *fetcher, bool Delete, PyObject *owner) {
+ CppPyObject<pkgAcquire*> *obj = CppPyObject_NEW<pkgAcquire*>(owner, &PyAcquire_Type, fetcher);
+ obj->NoDelete = (!Delete);
+ return obj;
+}
+
+static char *doc_PkgAcquire =
+ "Acquire([progress: apt.progress.base.AcquireProgress])\n\n"
+ "Coordinate the retrieval of files via network or local file system\n"
+ "(using 'copy:/path/to/file' style URIs). The optional argument\n"
+ "'progress' takes an apt.progress.base.AcquireProgress object\n"
+ "which may report progress information.";
+
+PyTypeObject PyAcquire_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Acquire", // tp_name
+ sizeof(CppPyObject<pkgAcquire*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<pkgAcquire*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE),
+ doc_PkgAcquire, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PkgAcquireMethods, // tp_methods
+ 0, // tp_members
+ PkgAcquireGetSet, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ PkgAcquireNew, // tp_new
+};
+
+
diff --git a/python/apt_instmodule.cc b/python/apt_instmodule.cc
new file mode 100644
index 0000000..eb01074
--- /dev/null
+++ b/python/apt_instmodule.cc
@@ -0,0 +1,87 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: apt_instmodule.cc,v 1.3 2002/01/08 06:53:04 jgg Exp $
+/* ######################################################################
+
+ apt_intmodule - Top level for the python module. Create the internal
+ structures for the module in the interpriter.
+
+ Note, this module shares state (particularly global config) with the
+ apt_pkg module.
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "apt_instmodule.h"
+#include "generic.h"
+
+#include <apt-pkg/debfile.h>
+#include <apt-pkg/error.h>
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <Python.h>
+ /*}}}*/
+
+PyObject *PyAptError;
+PyObject *PyAptWarning;
+static PyMethodDef *methods = 0;
+
+
+static const char *apt_inst_doc =
+ "Functions for working with ar/tar archives and .deb packages.\n\n"
+ "This module provides useful classes and functions to work with\n"
+ "archives, modelled after the 'TarFile' class in the 'tarfile' module.";
+#define ADDTYPE(mod,name,type) { \
+ if (PyType_Ready(type) == -1) RETURN(0); \
+ Py_INCREF(type); \
+ PyModule_AddObject(mod,name,(PyObject *)type); }
+
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "apt_inst",
+ apt_inst_doc,
+ -1,
+ methods,
+ 0,
+ 0,
+ 0,
+ 0
+};
+#define RETURN(x) return x
+#define INIT_ERROR return 0
+extern "C" PyObject * PyInit_apt_inst()
+#else
+#define INIT_ERROR return
+extern "C" void initapt_inst()
+#define RETURN(x) return
+#endif
+{
+#if PY_MAJOR_VERSION >= 3
+ PyObject *module = PyModule_Create(&moduledef);
+#else
+ PyObject *module = Py_InitModule3("apt_inst",methods, apt_inst_doc);
+#endif
+
+ PyObject *apt_pkg = PyImport_ImportModule("apt_pkg");
+ if (apt_pkg == NULL)
+ INIT_ERROR;
+ PyAptError = PyObject_GetAttrString(apt_pkg, "Error");
+ if (PyAptError == NULL)
+ INIT_ERROR;
+ PyAptWarning = PyObject_GetAttrString(apt_pkg, "Warning");
+ if (PyAptWarning == NULL)
+ INIT_ERROR;
+
+ PyModule_AddObject(module,"Error",PyAptError);
+ PyModule_AddObject(module,"Warning",PyAptWarning);
+ ADDTYPE(module,"ArMember",&PyArMember_Type);
+ ADDTYPE(module,"ArArchive",&PyArArchive_Type);
+ ADDTYPE(module,"DebFile",&PyDebFile_Type);
+ ADDTYPE(module,"TarFile",&PyTarFile_Type);
+ ADDTYPE(module,"TarMember",&PyTarMember_Type);
+ ADDTYPE(module,"__FileFd",&PyFileFd_Type);
+ RETURN(module);
+}
diff --git a/python/apt_instmodule.h b/python/apt_instmodule.h
new file mode 100644
index 0000000..92c9800
--- /dev/null
+++ b/python/apt_instmodule.h
@@ -0,0 +1,29 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: apt_instmodule.h,v 1.2 2002/01/08 06:53:04 jgg Exp $
+/* ######################################################################
+
+ Prototypes for the module
+
+ ##################################################################### */
+ /*}}}*/
+#ifndef APT_INSTMODULE_H
+#define APT_INSTMODULE_H
+
+#include <Python.h>
+#include "generic.h"
+#include <apt-pkg/extracttar.h>
+
+
+extern PyTypeObject PyArMember_Type;
+extern PyTypeObject PyArArchive_Type;
+extern PyTypeObject PyDebFile_Type;
+extern PyTypeObject PyTarFile_Type;
+extern PyTypeObject PyTarMember_Type;
+extern PyTypeObject PyFileFd_Type;
+struct PyTarFileObject : public CppPyObject<ExtractTar*> {
+ int min;
+ FileFd Fd;
+};
+
+#endif
diff --git a/python/apt_pkgmodule.cc b/python/apt_pkgmodule.cc
new file mode 100644
index 0000000..84b1e92
--- /dev/null
+++ b/python/apt_pkgmodule.cc
@@ -0,0 +1,1117 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: apt_pkgmodule.cc,v 1.5 2003/07/23 02:20:24 mdz Exp $
+/* ######################################################################
+
+ apt_pkgmodule - Top level for the python module. Create the internal
+ structures for the module in the interpriter.
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "apt_pkgmodule.h"
+#include "generic.h"
+
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/acquire-item.h>
+#include <apt-pkg/packagemanager.h>
+#include <apt-pkg/version.h>
+#include <apt-pkg/deblistparser.h>
+#include <apt-pkg/pkgcache.h>
+#include <apt-pkg/tagfile.h>
+#include <apt-pkg/hashes.h>
+#include <apt-pkg/init.h>
+#include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/orderlist.h>
+#include <apt-pkg/aptconfiguration.h>
+#include <apt-pkg/fileutl.h>
+#include <apt-pkg/gpgv.h>
+
+#include <sys/stat.h>
+#include <libintl.h>
+#include <unistd.h>
+#include <Python.h>
+ /*}}}*/
+
+static char PyAptError_Doc[] =
+ "Exception class for most python-apt exceptions.\n"
+ "\n"
+ "This class replaces the use of :class:`SystemError` in previous versions\n"
+ "of python-apt. It inherits from :class:`SystemError`, so make sure to\n"
+ "catch this class first.\n\n"
+ ".. versionadded:: 1.1";
+
+PyObject *PyAptError;
+
+static char PyAptWarning_Doc[] =
+ "Exception class for most python-apt warnings.\n"
+ "\n"
+ ".. versionadded:: 2.7";
+
+PyObject *PyAptWarning;
+
+static char PyAptCacheMismatchError_Doc[] =
+ "Raised when passing an object from a different cache to\n"
+ ":class:`apt_pkg.DepCache` methods\n\n"
+ ".. versionadded:: 1.6.1";
+
+PyObject *PyAptCacheMismatchError;
+
+/**
+ * A Python->C->Python gettext() function.
+ *
+ * Python's gettext() ignores setlocale() which causes a strange behavior
+ * because the values received from apt-pkg respect setlocale(). We circumvent
+ * this problem by calling the C version of gettext(). This is also much
+ * faster.
+ */
+static PyObject *py_gettext(PyObject *self, PyObject *Args) {
+ const char *msg;
+ char *domain = "python-apt";
+ if (PyArg_ParseTuple(Args,"s|s:gettext",&msg, &domain) == 0)
+ return 0;
+
+ return CppPyString(dgettext(domain, msg));
+}
+
+// newConfiguration - Build a new configuration class /*{{{*/
+// ---------------------------------------------------------------------
+ /*}}}*/
+
+// Version Wrappers /*{{{*/
+// These are kind of legacy..
+static char *doc_VersionCompare =
+ "version_compare(a: str, b: str) -> int\n\n"
+ "Compare the given versions; return a strictly negative value if 'a' is \n"
+ "smaller than 'b', 0 if they are equal, and a strictly positive value if\n"
+ "'a' is larger than 'b'.";
+static PyObject *VersionCompare(PyObject *Self,PyObject *Args)
+{
+ char *A;
+ char *B;
+ Py_ssize_t LenA;
+ Py_ssize_t LenB;
+
+ if (PyArg_ParseTuple(Args,"s#s#",&A,&LenA,&B,&LenB) == 0)
+ return 0;
+
+ if (_system == 0)
+ {
+ PyErr_SetString(PyExc_ValueError,"_system not initialized");
+ return 0;
+ }
+
+ return MkPyNumber(_system->VS->DoCmpVersion(A,A+LenA,B,B+LenB));
+}
+
+static char *doc_CheckDep =
+ "check_dep(pkg_ver: str, dep_op: str, dep_ver: str) -> bool\n\n"
+ "Check that the given requirement is fulfilled; i.e. that the version\n"
+ "string given by 'pkg_ver' matches the version string 'dep_ver' under\n"
+ "the condition specified by the operator 'dep_op' (<,<=,=,>=,>).\n\n"
+ "Return True if 'pkg_ver' matches 'dep_ver' under the\n"
+ "condition 'dep_op'; for example, this returns True:\n\n"
+ " apt_pkg.check_dep('1', '<=', '2')";
+static PyObject *CheckDep(PyObject *Self,PyObject *Args)
+{
+ char *A;
+ char *B;
+ char *OpStr;
+ unsigned int Op = 0;
+
+ if (PyArg_ParseTuple(Args,"sss",&A,&OpStr,&B) == 0)
+ return 0;
+
+ if (strcmp(OpStr, ">") == 0) OpStr = ">>";
+ if (strcmp(OpStr, "<") == 0) OpStr = "<<";
+ if (*debListParser::ConvertRelation(OpStr,Op) != 0)
+ {
+ PyErr_SetString(PyExc_ValueError,"Bad comparison operation");
+ return 0;
+ }
+
+ if (_system == 0)
+ {
+ PyErr_SetString(PyExc_ValueError,"_system not initialized");
+ return 0;
+ }
+
+ return PyBool_FromLong(_system->VS->CheckDep(A,Op,B));
+}
+
+
+static char *doc_UpstreamVersion =
+ "upstream_version(ver: str) -> str\n\n"
+ "Return the upstream version for the package version given by 'ver'.";
+static PyObject *UpstreamVersion(PyObject *Self,PyObject *Args)
+{
+ char *Ver;
+ if (PyArg_ParseTuple(Args,"s",&Ver) == 0)
+ return 0;
+ return CppPyString(_system->VS->UpstreamVersion(Ver));
+}
+
+static const char *doc_ParseDepends =
+"parse_depends(s: str[, strip_multi_arch : bool = True[, architecture : string]]) -> list\n"
+"\n"
+"Parse the dependencies given by 's' and return a list of lists. Each of\n"
+"these lists represents one or more options for an 'or' dependency in\n"
+"the form of '(pkg, ver, comptype)' tuples. The tuple element 'pkg'\n"
+"is the name of the package; the element 'ver' is the version, or ''\n"
+"if no version was requested. The element 'ver' is a comparison\n"
+"operator ('<', '<=', '=', '>=', or '>').\n\n"
+"If 'strip_multi_arch' is True, :any (and potentially other special values)\n"
+"will be stripped from the full package name"
+"The 'architecture' parameter may be used to specify a non-native architecture\n"
+"for the dependency parsing.";
+
+static const char *parse_src_depends_doc =
+"parse_src_depends(s: str[, strip_multi_arch : bool = True[, architecture : string]]) -> list\n"
+"\n"
+"Parse the dependencies given by 's' and return a list of lists. Each of\n"
+"these lists represents one or more options for an 'or' dependency in\n"
+"the form of '(pkg, ver, comptype)' tuples. The tuple element 'pkg'\n"
+"is the name of the package; the element 'ver' is the version, or ''\n"
+"if no version was requested. The element 'ver' is a comparison\n"
+"operator ('<', '<=', '=', '>=', or '>')."
+"\n\n"
+"Dependencies may be restricted to certain architectures and the result\n"
+"only contains those dependencies for the architecture set in the\n"
+"configuration variable APT::Architecture\n\n"
+"If 'strip_multi_arch' is True, :any (and potentially other special values)\n"
+"will be stripped from the full package name"
+"The 'architecture' parameter may be used to specify a non-native architecture\n"
+"for the dependency parsing.";
+static PyObject *RealParseDepends(PyObject *Self,PyObject *Args,PyObject *Kwds,
+ bool ParseArchFlags, bool ParseRestrictionsList,
+ std::string name, bool debStyle=false)
+{
+ std::string Package;
+ std::string Version;
+ unsigned int Op;
+ bool StripMultiArch=true;
+
+ const char *Start;
+ const char *Stop;
+ Py_ssize_t Len;
+ const char *Arch = NULL;
+ char *kwlist[] = {"s", "strip_multi_arch", "architecture", 0};
+
+ if (PyArg_ParseTupleAndKeywords(Args,Kwds,(char *)("s#|bs:" + name).c_str(), kwlist,
+ &Start, &Len, &StripMultiArch, &Arch) == 0)
+ return 0;
+ Stop = Start + Len;
+ PyObject *List = PyList_New(0);
+ PyObject *LastRow = 0;
+ while (1)
+ {
+ if (Start == Stop)
+ break;
+ if (Arch == NULL)
+ Start = debListParser::ParseDepends(Start,Stop,Package,Version,Op,
+ ParseArchFlags, StripMultiArch,
+ ParseRestrictionsList);
+ else
+ Start = debListParser::ParseDepends(Start,Stop,Package,Version,Op,
+ ParseArchFlags, StripMultiArch,
+ ParseRestrictionsList, Arch);
+
+ if (Start == 0)
+ {
+ PyErr_SetString(PyExc_ValueError,"Problem Parsing Dependency");
+ Py_DECREF(List);
+ return 0;
+ }
+
+ if (LastRow == 0)
+ LastRow = PyList_New(0);
+
+ if (Package.empty() == false)
+ {
+ PyObject *Obj;
+ PyList_Append(LastRow,Obj = Py_BuildValue("sss",Package.c_str(),
+ Version.c_str(),
+ debStyle ? pkgCache::CompTypeDeb(Op) : pkgCache::CompType(Op)));
+ Py_DECREF(Obj);
+ }
+
+ // Group ORd deps into a single row..
+ if ((Op & pkgCache::Dep::Or) != pkgCache::Dep::Or)
+ {
+ if (PyList_Size(LastRow) != 0)
+ PyList_Append(List,LastRow);
+ Py_DECREF(LastRow);
+ LastRow = 0;
+ }
+ }
+ return List;
+}
+static PyObject *ParseDepends(PyObject *Self,PyObject *Args, PyObject *Kwds)
+{
+ return RealParseDepends(Self, Args, Kwds, false, false, "parse_depends");
+}
+static PyObject *ParseSrcDepends(PyObject *Self,PyObject *Args, PyObject *Kwds)
+{
+ return RealParseDepends(Self, Args, Kwds, true, true, "parse_src_depends");
+}
+ /*}}}*/
+// md5sum - Compute the md5sum of a file or string /*{{{*/
+// ---------------------------------------------------------------------
+static const char *doc_md5sum =
+ "md5sum(object) -> str\n\n"
+ "Return the md5sum of the object. 'object' may either be a string, in\n"
+ "which case the md5sum of the string is returned, or a file() object\n"
+ "(or file descriptor), in which case the md5sum of its contents is\n"
+ "returned.";
+static PyObject *md5sum(PyObject *Self,PyObject *Args)
+{
+ PyObject *Obj;
+ if (PyArg_ParseTuple(Args,"O",&Obj) == 0)
+ return 0;
+
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,
+ "apt_pkg.md5sum is deprecated, use apt_pkg.Hashes", 1) == -1)
+ return NULL;
+
+ // Digest of a string.
+ if (PyBytes_Check(Obj) != 0)
+ {
+ char *s;
+ Py_ssize_t len;
+ Hashes Sum(Hashes::MD5SUM);
+ PyBytes_AsStringAndSize(Obj, &s, &len);
+ Sum.Add((const unsigned char*)s, len);
+ return CppPyString(Sum.GetHashString(Hashes::MD5SUM).HashValue());
+ }
+
+ // Digest of a file
+ int Fd = PyObject_AsFileDescriptor(Obj);
+ if (Fd != -1)
+ {
+ Hashes Sum(Hashes::MD5SUM);
+ struct stat St;
+ if (fstat(Fd,&St) != 0 ||
+ Sum.AddFD(Fd,St.st_size) == false)
+ {
+ PyErr_SetFromErrno(PyAptError);
+ return 0;
+ }
+
+ return CppPyString(Sum.GetHashString(Hashes::MD5SUM).HashValue());
+ }
+
+ PyErr_SetString(PyExc_TypeError,"Only understand strings and files");
+ return 0;
+}
+ /*}}}*/
+// sha1sum - Compute the sha1sum of a file or string /*{{{*/
+// ---------------------------------------------------------------------
+static const char *doc_sha1sum =
+ "sha1sum(object) -> str\n\n"
+ "Return the sha1sum of the object. 'object' may either be a string, in\n"
+ "which case the sha1sum of the string is returned, or a file() object\n"
+ "(or file descriptor), in which case the sha1sum of its contents is\n"
+ "returned.";
+static PyObject *sha1sum(PyObject *Self,PyObject *Args)
+{
+ PyObject *Obj;
+ if (PyArg_ParseTuple(Args,"O",&Obj) == 0)
+ return 0;
+
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,
+ "apt_pkg.sha1sum is deprecated, use apt_pkg.Hashes", 1) == -1)
+ return NULL;
+
+ // Digest of a string.
+ if (PyBytes_Check(Obj) != 0)
+ {
+ char *s;
+ Py_ssize_t len;
+ Hashes Sum(Hashes::SHA1SUM);
+ PyBytes_AsStringAndSize(Obj, &s, &len);
+ Sum.Add((const unsigned char*)s, len);
+ return CppPyString(Sum.GetHashString(Hashes::SHA1SUM).HashValue());
+ }
+
+ // Digest of a file
+ int Fd = PyObject_AsFileDescriptor(Obj);
+ if (Fd != -1)
+ {
+ Hashes Sum(Hashes::SHA1SUM);
+ struct stat St;
+ if (fstat(Fd,&St) != 0 ||
+ Sum.AddFD(Fd,St.st_size) == false)
+ {
+ PyErr_SetFromErrno(PyAptError);
+ return 0;
+ }
+
+ return CppPyString(Sum.GetHashString(Hashes::SHA1SUM).HashValue());
+ }
+
+ PyErr_SetString(PyExc_TypeError,"Only understand strings and files");
+ return 0;
+}
+ /*}}}*/
+// sha256sum - Compute the sha256sum of a file or string /*{{{*/
+// ---------------------------------------------------------------------
+static const char *doc_sha256sum =
+ "sha256sum(object) -> str\n\n"
+ "Return the sha256sum of the object. 'object' may either be a string, in\n"
+ "which case the sha256sum of the string is returned, or a file() object\n"
+ "(or file descriptor), in which case the sha256sum of its contents is\n"
+ "returned.";;
+static PyObject *sha256sum(PyObject *Self,PyObject *Args)
+{
+ PyObject *Obj;
+ if (PyArg_ParseTuple(Args,"O",&Obj) == 0)
+ return 0;
+
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,
+ "apt_pkg.sha256sum is deprecated, use apt_pkg.Hashes", 1) == -1)
+ return NULL;
+
+ // Digest of a string.
+ if (PyBytes_Check(Obj) != 0)
+ {
+ char *s;
+ Py_ssize_t len;
+ Hashes Sum(Hashes::SHA256SUM);
+ PyBytes_AsStringAndSize(Obj, &s, &len);
+ Sum.Add((const unsigned char*)s, len);
+ return CppPyString(Sum.GetHashString(Hashes::SHA256SUM).HashValue());
+ }
+
+ // Digest of a file
+ int Fd = PyObject_AsFileDescriptor(Obj);
+ if (Fd != -1)
+ {
+ Hashes Sum(Hashes::SHA256SUM);
+ struct stat St;
+ if (fstat(Fd,&St) != 0 ||
+ Sum.AddFD(Fd,St.st_size) == false)
+ {
+ PyErr_SetFromErrno(PyAptError);
+ return 0;
+ }
+
+ return CppPyString(Sum.GetHashString(Hashes::SHA256SUM).HashValue());
+ }
+
+ PyErr_SetString(PyExc_TypeError,"Only understand strings and files");
+ return 0;
+}
+ /*}}}*/
+// sha512sum - Compute the sha512sum of a file or string /*{{{*/
+// ---------------------------------------------------------------------
+static const char *doc_sha512sum =
+ "sha512sum(object) -> str\n\n"
+ "Return the sha512sum of the object. 'object' may either be a string, in\n"
+ "which case the sha512sum of the string is returned, or a file() object\n"
+ "(or file descriptor), in which case the sha512sum of its contents is\n"
+ "returned.";;
+static PyObject *sha512sum(PyObject *Self,PyObject *Args)
+{
+ PyObject *Obj;
+ if (PyArg_ParseTuple(Args,"O",&Obj) == 0)
+ return 0;
+
+ if (PyErr_WarnEx(PyExc_DeprecationWarning,
+ "apt_pkg.sha512sum is deprecated, use apt_pkg.Hashes", 1) == -1)
+ return NULL;
+
+ // Digest of a string.
+ if (PyBytes_Check(Obj) != 0)
+ {
+ char *s;
+ Py_ssize_t len;
+ Hashes Sum(Hashes::SHA512SUM);
+ PyBytes_AsStringAndSize(Obj, &s, &len);
+ Sum.Add((const unsigned char*)s, len);
+ return CppPyString(Sum.GetHashString(Hashes::SHA512SUM).HashValue());
+ }
+
+ // Digest of a file
+ int Fd = PyObject_AsFileDescriptor(Obj);
+ if (Fd != -1)
+ {
+ Hashes Sum(Hashes::SHA512SUM);
+ struct stat St;
+ if (fstat(Fd,&St) != 0 ||
+ Sum.AddFD(Fd,St.st_size) == false)
+ {
+ PyErr_SetFromErrno(PyAptError);
+ return 0;
+ }
+
+ return CppPyString(Sum.GetHashString(Hashes::SHA512SUM).HashValue());
+ }
+
+ PyErr_SetString(PyExc_TypeError,"Only understand strings and files");
+ return 0;
+}
+ /*}}}*/
+// get_architectures - return the list of architectures /*{{{*/
+// ---------------------------------------------------------------------
+static const char *doc_GetArchitectures =
+ "get_architectures() -> list\n\n"
+ "Return the list of supported architectures on this system. On a \n"
+ "multiarch system this can be more than one. The main architectures\n"
+ "is the first item in the list.";;
+static PyObject *GetArchitectures(PyObject *Self,PyObject *Args)
+{
+ PyObject *Obj;
+ if (PyArg_ParseTuple(Args,"",&Obj) == 0)
+ return 0;
+
+ PyObject *List = PyList_New(0);
+ std::vector<std::string> arches = APT::Configuration::getArchitectures();
+ std::vector<std::string>::const_iterator I;
+ for (I = arches.begin(); I != arches.end(); I++)
+ {
+ PyList_Append(List, CppPyString(*I));
+ }
+
+ return List;
+}
+ /*}}}*/
+// init - 3 init functions /*{{{*/
+// ---------------------------------------------------------------------
+static char *doc_Init =
+"init()\n\n"
+"Shorthand for doing init_config() and init_system(). When working\n"
+"with command line arguments, first call init_config() then parse\n"
+"the command line and finally call init_system().";
+static PyObject *Init(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ pkgInitConfig(*_config);
+ pkgInitSystem(*_config,_system);
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static char *doc_InitConfig =
+"init_config()\n\n"
+"Load the default configuration and the config file.";
+static PyObject *InitConfig(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ pkgInitConfig(*_config);
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static char *doc_InitSystem =
+"init_system()\n\n"
+"Construct the apt_pkg system.";
+static PyObject *InitSystem(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ pkgInitSystem(*_config,_system);
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+ /*}}}*/
+// gpgv.cc:OpenMaybeClearSignedFile /*{{{*/
+// ---------------------------------------------------------------------
+static char *doc_OpenMaybeClearSignedFile =
+"open_maybe_clear_signed_file(file: str) -> int\n\n"
+"Open a file and ignore a PGP clear signature.\n"
+"Return a open file descriptor or a error.";
+static PyObject *PyOpenMaybeClearSignedFile(PyObject *Self,PyObject *Args)
+{
+ PyApt_Filename file;
+ char errors = false;
+ if (PyArg_ParseTuple(Args,"O&",PyApt_Filename::Converter, &file,&errors) == 0)
+ return 0;
+
+ FileFd Fd;
+ if (OpenMaybeClearSignedFile(file, Fd) == false)
+ return HandleErrors(MkPyNumber(-1));
+
+ return HandleErrors(MkPyNumber(dup(Fd.Fd())));
+}
+
+// fileutils.cc: GetLock /*{{{*/
+// ---------------------------------------------------------------------
+static char *doc_GetLock =
+"get_lock(file: str, errors: bool) -> int\n\n"
+"Create an empty file of the given name and lock it. If the locking\n"
+"succeeds, return the file descriptor of the lock file. Afterwards,\n"
+"locking the file from another process will fail and thus cause\n"
+"get_lock() to return -1 or raise an Error (if 'errors' is True).\n\n"
+"From Python 2.6 on, it is recommended to use the context manager\n"
+"provided by apt_pkg.FileLock instead using the with-statement.";
+static PyObject *GetLock(PyObject *Self,PyObject *Args)
+{
+ PyApt_Filename file;
+ char errors = false;
+ if (PyArg_ParseTuple(Args,"O&|b",PyApt_Filename::Converter, &file,&errors) == 0)
+ return 0;
+
+ int fd = GetLock(file, errors);
+
+ return HandleErrors(MkPyNumber(fd));
+}
+
+static char *doc_PkgSystemLock =
+"pkgsystem_lock() -> bool\n\n"
+"Acquire the global lock for the package system by using /var/lib/dpkg/lock-frontend\n"
+"and /var/lib/dpkg/lock to do the locking. From Python 2.6 on, the apt_pkg.SystemLock context\n"
+"manager is available and should be used instead.";
+static PyObject *PkgSystemLock(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ bool res = _system->Lock();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static char *doc_PkgSystemUnLock =
+"pkgsystem_unlock() -> bool\n\n"
+"Release the global lock for the package system.";
+static PyObject *PkgSystemUnLock(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ bool res = _system->UnLock();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static char *doc_PkgSystemLockInner =
+"pkgsystem_lock_inner() -> bool\n\n"
+"Reacquire the dpkg 'lock' lock file. Must be called only after\n"
+":meth:`pkgsystem_unlock_inner` and only around invocations of dpkg.\n"
+"\n"
+".. versionadded:: 1.7";
+static PyObject *PkgSystemLockInner(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ bool res = _system->LockInner();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static char *doc_PkgSystemUnLockInner =
+"pkgsystem_unlock_inner() -> bool\n\n"
+"Release the dpkg lock file 'lock'. To be called before manually\n"
+"invoking dpkg.\n"
+"\n"
+".. versionadded:: 1.7";
+static PyObject *PkgSystemUnLockInner(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ bool res = _system->UnLockInner();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static char *doc_PkgSystemIsLocked =
+"pkgsystem_is_locked() -> bool\n\n"
+"Check if the system is locked. Can be used to check whether the inner\n"
+"lock needs to be released or not in generic code.\n"
+"\n"
+".. versionadded:: 1.7";
+static PyObject *PkgSystemIsLocked(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ bool res = _system->IsLocked();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+ /*}}}*/
+
+// initapt_pkg - Core Module Initialization /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+static PyMethodDef methods[] =
+{
+ // Constructors
+ {"init",Init,METH_VARARGS,doc_Init},
+ {"init_config",InitConfig,METH_VARARGS,doc_InitConfig},
+ {"init_system",InitSystem,METH_VARARGS,doc_InitSystem},
+
+ // Internationalization.
+ {"gettext",py_gettext,METH_VARARGS,
+ "gettext(msg: str[, domain: str = 'python-apt']) -> str\n\n"
+ "Translate the given string. This is much faster than Python's version\n"
+ "and only does translations after setlocale() has been called."},
+
+ // Tag File
+
+ {"open_maybe_clear_signed_file",PyOpenMaybeClearSignedFile,METH_VARARGS,
+ doc_OpenMaybeClearSignedFile},
+
+ // Locking
+ {"get_lock",GetLock,METH_VARARGS,doc_GetLock},
+ {"pkgsystem_lock",PkgSystemLock,METH_VARARGS,doc_PkgSystemLock},
+ {"pkgsystem_unlock",PkgSystemUnLock,METH_VARARGS,doc_PkgSystemUnLock},
+ {"pkgsystem_lock_inner",PkgSystemLockInner,METH_VARARGS,doc_PkgSystemLockInner},
+ {"pkgsystem_unlock_inner",PkgSystemUnLockInner,METH_VARARGS,doc_PkgSystemUnLockInner},
+ {"pkgsystem_is_locked",PkgSystemIsLocked,METH_VARARGS,doc_PkgSystemIsLocked},
+
+ // Command line
+ {"read_config_file",LoadConfig,METH_VARARGS,doc_LoadConfig},
+ {"read_config_dir",LoadConfigDir,METH_VARARGS,doc_LoadConfigDir},
+ {"read_config_file_isc",LoadConfigISC,METH_VARARGS,doc_LoadConfig},
+ {"parse_commandline",ParseCommandLine,METH_VARARGS,doc_ParseCommandLine},
+
+ // Versioning
+ {"version_compare",VersionCompare,METH_VARARGS,doc_VersionCompare},
+ {"check_dep",CheckDep,METH_VARARGS,doc_CheckDep},
+ {"upstream_version",UpstreamVersion,METH_VARARGS,doc_UpstreamVersion},
+
+ // Depends
+ {"parse_depends",reinterpret_cast<PyCFunction>(static_cast<PyCFunctionWithKeywords>(ParseDepends)),METH_VARARGS|METH_KEYWORDS,doc_ParseDepends},
+ {"parse_src_depends",reinterpret_cast<PyCFunction>(static_cast<PyCFunctionWithKeywords>(ParseSrcDepends)),METH_VARARGS|METH_KEYWORDS,parse_src_depends_doc},
+
+ // Hashes
+ {"md5sum",md5sum,METH_VARARGS,doc_md5sum},
+ {"sha1sum",sha1sum,METH_VARARGS,doc_sha1sum},
+ {"sha256sum",sha256sum,METH_VARARGS,doc_sha256sum},
+ {"sha512sum",sha512sum,METH_VARARGS,doc_sha512sum},
+
+ // multiarch
+ {"get_architectures", GetArchitectures, METH_VARARGS, doc_GetArchitectures},
+
+ // Strings
+ {"check_domain_list",StrCheckDomainList,METH_VARARGS,
+ "check_domain_list(host: str, domains: str) -> bool\n\n"
+ "Check if the host given by 'host' belongs to one of the domains\n"
+ "specified in the comma separated string 'domains'. An example\n"
+ "would be:\n\n"
+ " check_domain_list('alioth.debian.org','debian.net,debian.org')\n\n"
+ "which would return True because alioth belongs to debian.org."},
+ {"quote_string",StrQuoteString,METH_VARARGS,
+ "quote_string(string: str, repl: str) -> str\n\n"
+ "Escape the string 'string', replacing any character not allowed in a URL"
+ "or specified by 'repl' with its ASCII value preceded by a percent sign"
+ "(so for example ' ' becomes '%20')."},
+ {"dequote_string",StrDeQuote,METH_VARARGS,
+ "dequote_string(string: str) -> str\n\n"
+ "Dequote the given string by replacing all HTTP encoded values such\n"
+ "as '%20' with their decoded value (in this case, ' ')."},
+ {"size_to_str",StrSizeToStr,METH_VARARGS,
+ "size_to_str(bytes: int) -> str\n\n"
+ "Return a string describing the size in a human-readable manner using\n"
+ "SI prefix and base-10 units, e.g. '1k' for 1000, '1M' for 1000000, etc."},
+ {"time_to_str",StrTimeToStr,METH_VARARGS,
+ "time_to_str(seconds: int) -> str\n\n"
+ "Return a string describing the number of seconds in a human\n"
+ "readable manner using days, hours, minutes and seconds."},
+ {"uri_to_filename",StrURItoFileName,METH_VARARGS,
+ "uri_to_filename(uri: str) -> str\n\n"
+ "Return a filename based on the given URI after replacing some\n"
+ "parts not suited for filenames (e.g. '/')."},
+ {"base64_encode",StrBase64Encode,METH_VARARGS,
+ "base64_encode(value: bytes) -> str\n\n"
+ "Encode the given bytestring into Base64. The input may not\n"
+ "contain a null byte character (use the base64 module for this)."},
+ {"string_to_bool",StrStringToBool,METH_VARARGS,
+ "string_to_bool(string: str) -> int\n\n"
+ "Return 1 if the string is a value such as 'yes', 'true', '1';\n"
+ "0 if the string is a value such as 'no', 'false', '0'; -1 if\n"
+ "the string is not recognized."},
+ {"time_rfc1123",StrTimeRFC1123,METH_VARARGS,
+ "time_rfc1123(unixtime: int) -> str\n\n"
+ "Format the given Unix time according to the requirements of\n"
+ "RFC 1123."},
+ {"str_to_time",StrStrToTime,METH_VARARGS,
+ "str_to_time(rfc_time: str) -> int\n\n"
+ "Convert the given RFC 1123 formatted string to a Unix timestamp."},
+
+ // DEPRECATED
+
+ {}
+};
+
+static struct _PyAptPkgAPIStruct API = {
+ &PyAcquire_Type, // acquire_type
+ &PyAcquire_FromCpp, // acquire_fromcpp
+ &PyAcquire_ToCpp, // acquire_tocpp
+ &PyAcquireFile_Type, // acquirefile_type
+ &PyAcquireFile_FromCpp, // acquirefile_fromcpp
+ &PyAcquireFile_ToCpp, // acquirefile_tocpp
+ &PyAcquireItem_Type, // acquireitem_type
+ &PyAcquireItem_FromCpp, // acquireitem_fromcpp
+ &PyAcquireItem_ToCpp, // acquireitem_type
+ &PyAcquireItemDesc_Type, // acquireitemdesc_type
+ &PyAcquireItemDesc_FromCpp,// acquireitemdesc_fromcpp
+ &PyAcquireItemDesc_ToCpp, // acquireitemdesc_tocpp
+ &PyAcquireWorker_Type, // acquireworker_type
+ &PyAcquireWorker_FromCpp, // acquireworker_fromcpp
+ &PyAcquireWorker_ToCpp, // acquireworker_tocpp
+ &PyActionGroup_Type, // actiongroup_type
+ &PyActionGroup_FromCpp, // actiongroup_fromcpp
+ &PyActionGroup_ToCpp, // actiongroup_tocpp
+ &PyCache_Type, // cache_type
+ &PyCache_FromCpp, // cache_fromcpp
+ &PyCache_ToCpp, // cache_tocpp
+ &PyCacheFile_Type, // cachefile_type
+ &PyCacheFile_FromCpp, // cachefile_fromcpp
+ &PyCacheFile_ToCpp, // cachefile_tocpp
+ &PyCdrom_Type, // cdrom_type
+ &PyCdrom_FromCpp, // cdrom_fromcpp
+ &PyCdrom_ToCpp, // cdrom_tocpp
+ &PyConfiguration_Type, // configuration_type
+ &PyConfiguration_FromCpp, // configuration_fromcpp
+ &PyConfiguration_ToCpp, // configuration_tocpp
+ &PyDepCache_Type, // depcache_type
+ &PyDepCache_FromCpp, // depcache_fromcpp
+ &PyDepCache_ToCpp, // depcache_tocpp
+ &PyDependency_Type, // dependency_type
+ &PyDependency_FromCpp, // dependency_fromcpp
+ &PyDependency_ToCpp, // dependency_tocpp
+ &PyDependencyList_Type, // dependencylist_type
+ 0, // FIXME: dependencylist_fromcpp
+ 0, // FIXME: dependencylist_tocpp
+ &PyDescription_Type, // description_type
+ &PyDescription_FromCpp, // description_fromcpp
+ &PyDescription_ToCpp, // description_tocpp
+ &PyHashes_Type, // hashes_type
+ &PyHashes_FromCpp, // hashes_fromcpp
+ &PyHashes_ToCpp, // hashes_tocpp
+ &PyHashString_Type, // hashstring_type
+ &PyHashString_FromCpp, // hashstring_fromcpp
+ &PyHashString_ToCpp, // hashstring_tocpp
+ &PyMetaIndex_Type, // metaindex_type
+ &PyMetaIndex_FromCpp, // metaindex_tocpp
+ &PyMetaIndex_ToCpp, // metaindex_tocpp
+ &PyPackage_Type, // package_type
+ &PyPackage_FromCpp, // package_tocpp
+ &PyPackage_ToCpp, // package_tocpp
+ &PyPackageFile_Type, // packagefile_type
+ &PyPackageFile_FromCpp, // packagefile_tocpp
+ &PyPackageFile_ToCpp, // packagefile_tocpp
+ &PyIndexFile_Type, // packageindexfile_type
+ &PyIndexFile_FromCpp, // packageindexfile_tocpp
+ &PyIndexFile_ToCpp, // packageindexfile_tocpp
+ &PyPackageList_Type, // packagelist_type
+ 0, // FIXME: packagelist_fromcpp
+ 0, // FIXME: packagelist_tocpp
+ &PyPackageManager_Type, // packagemanager_type
+ &PyPackageManager_FromCpp, // packagemanager_type
+ &PyPackageManager_ToCpp, // packagemanager_type
+ &PyPackageRecords_Type, // packagerecords_type
+ 0, // FIXME: packagerecords_fromcpp
+ 0, // FIXME: packagerecords_tocpp
+ &PyPolicy_Type, // policy_type
+ &PyPolicy_FromCpp, // policy_tocpp
+ &PyPolicy_ToCpp, // policy_tocpp
+ &PyProblemResolver_Type, // problemresolver_type
+ &PyProblemResolver_FromCpp, // problemresolver_tocpp
+ &PyProblemResolver_ToCpp, // problemresolver_tocpp
+ &PySourceList_Type, // sourcelist_type
+ &PySourceList_FromCpp, // sourcelist_tocpp
+ &PySourceList_ToCpp, // sourcelist_tocpp
+ &PySourceRecords_Type, // sourcerecords_type
+ 0, // FIXME: sourcerecords_fromcpp
+ 0, // FIXME: sourcerecords_tocpp
+ &PyTagFile_Type, // tagfile_type
+ &PyTagFile_FromCpp, // tagfile_tocpp
+ &PyTagFile_ToCpp, // tagfile_tocpp
+ &PyTagSection_Type, // tagsection_type
+ &PyTagSection_FromCpp, // tagsection_tocpp
+ &PyTagSection_ToCpp, // tagsection_tocpp
+ &PyVersion_Type, // version_type
+ &PyVersion_FromCpp, // version_tocpp
+ &PyVersion_ToCpp, // version_tocpp
+ &PyGroup_Type, // group_type
+ &PyGroup_FromCpp, // group_fromcpp
+ &PyGroup_ToCpp, // group_tocpp
+ &PyOrderList_Type, // orderlist_type
+ &PyOrderList_FromCpp, // orderlist_fromcpp
+ &PyOrderList_ToCpp, // orderlist_tocpp
+ &PySourceRecordFiles_Type, // sourcerecordfiles_type
+ 0, // FIXME: sourcerecordfiles_fromcpp
+ 0, // FIXME: sourcerecordfiles_tocpp
+};
+
+
+#define ADDTYPE(mod,name,type) { \
+ if (PyType_Ready(type) == -1) INIT_ERROR; \
+ Py_INCREF(type); \
+ PyModule_AddObject(mod,name,(PyObject *)type); }
+
+
+static const char *apt_pkg_doc =
+ "Classes and functions wrapping the apt-pkg library.\n\n"
+ "The apt_pkg module provides several classes and functions for accessing\n"
+ "the functionality provided by the apt-pkg library. Typical uses might\n"
+ "include reading APT index files and configuration files and installing\n"
+ "or removing packages.";
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "apt_pkg",
+ apt_pkg_doc,
+ -1,
+ methods,
+ 0,
+ 0,
+ 0,
+ 0,
+};
+
+#define INIT_ERROR return 0
+extern "C" PyObject * PyInit_apt_pkg()
+#else
+#define INIT_ERROR return
+extern "C" void initapt_pkg()
+#endif
+{
+ // Finalize our types to add slots, etc.
+ if (PyType_Ready(&PyConfiguration_Type) == -1) INIT_ERROR;
+ if (PyType_Ready(&PyCacheFile_Type) == -1) INIT_ERROR;
+ PyAptError = PyErr_NewExceptionWithDoc("apt_pkg.Error", PyAptError_Doc, PyExc_SystemError, NULL);
+ if (PyAptError == NULL)
+ INIT_ERROR;
+ PyAptWarning = PyErr_NewExceptionWithDoc("apt_pkg.Warning", PyAptWarning_Doc, PyExc_Warning, NULL);
+ if (PyAptWarning == NULL)
+ INIT_ERROR;
+
+ PyAptCacheMismatchError = PyErr_NewExceptionWithDoc("apt_pkg.CacheMismatchError", PyAptCacheMismatchError_Doc, PyExc_ValueError, NULL);
+ if (PyAptCacheMismatchError == NULL)
+ INIT_ERROR;
+
+ // Initialize the module
+ #if PY_MAJOR_VERSION >= 3
+ PyObject *Module = PyModule_Create(&moduledef);
+ #else
+ PyObject *Module = Py_InitModule3("apt_pkg",methods, apt_pkg_doc);
+ #endif
+
+ // Global variable linked to the global configuration class
+ CppPyObject<Configuration*> *Config = CppPyObject_NEW<Configuration*>(NULL, &PyConfiguration_Type);
+ Config->Object = _config;
+ // Global configuration, should never be deleted.
+ Config->NoDelete = true;
+ PyModule_AddObject(Module,"config",Config);
+ PyModule_AddObject(Module,"Error",PyAptError);
+ PyModule_AddObject(Module,"Warning",PyAptWarning);
+ PyModule_AddObject(Module,"CacheMismatchError", PyAptCacheMismatchError);
+
+
+
+ // Add our classes.
+ /* ============================ tag.cc ============================ */
+ ADDTYPE(Module,"TagSection",&PyTagSection_Type);
+ ADDTYPE(Module,"TagFile",&PyTagFile_Type);
+ ADDTYPE(Module,"Tag",&PyTag_Type);
+ ADDTYPE(Module,"TagRewrite",&PyTagRewrite_Type);
+ ADDTYPE(Module,"TagRename",&PyTagRename_Type);
+ ADDTYPE(Module,"TagRemove",&PyTagRemove_Type);
+ /* ============================ acquire.cc ============================ */
+ ADDTYPE(Module,"Acquire",&PyAcquire_Type);
+ ADDTYPE(Module,"AcquireFile",&PyAcquireFile_Type);
+ ADDTYPE(Module,"AcquireItem",&PyAcquireItem_Type); // NO __new__()
+ ADDTYPE(Module,"AcquireWorker",&PyAcquireWorker_Type); // NO __new__()
+ /* ============================ cache.cc ============================ */
+ ADDTYPE(Module,"Cache",&PyCache_Type);
+ ADDTYPE(Module,"Dependency",&PyDependency_Type); // NO __new__()
+ ADDTYPE(Module,"Description",&PyDescription_Type); // NO __new__()
+ ADDTYPE(Module,"PackageFile",&PyPackageFile_Type); // NO __new__()
+ ADDTYPE(Module,"PackageList",&PyPackageList_Type); // NO __new__(), internal
+ ADDTYPE(Module,"DependencyList",&PyDependencyList_Type); // NO __new__(), internal
+ ADDTYPE(Module,"Package",&PyPackage_Type); // NO __new__()
+ ADDTYPE(Module,"Version",&PyVersion_Type); // NO __new__()
+ ADDTYPE(Module,"Group", &PyGroup_Type);
+ ADDTYPE(Module,"GroupList", &PyGroupList_Type);
+ /* ============================ cdrom.cc ============================ */
+ ADDTYPE(Module,"Cdrom",&PyCdrom_Type);
+ /* ========================= configuration.cc ========================= */
+ ADDTYPE(Module,"Configuration",&PyConfiguration_Type);
+ /* ========================= depcache.cc ========================= */
+ ADDTYPE(Module,"ActionGroup",&PyActionGroup_Type);
+ ADDTYPE(Module,"DepCache",&PyDepCache_Type);
+ ADDTYPE(Module,"ProblemResolver",&PyProblemResolver_Type);
+ /* ========================= indexfile.cc ========================= */
+ ADDTYPE(Module,"IndexFile",&PyIndexFile_Type); // NO __new__()
+ /* ========================= metaindex.cc ========================= */
+ ADDTYPE(Module,"MetaIndex",&PyMetaIndex_Type); // NO __new__()
+ /* ========================= pkgmanager.cc ========================= */
+ ADDTYPE(Module,"_PackageManager",&PyPackageManager_Type);
+ ADDTYPE(Module,"PackageManager",&PyPackageManager2_Type);
+ /* ========================= pkgrecords.cc ========================= */
+ ADDTYPE(Module,"PackageRecords",&PyPackageRecords_Type);
+ /* ========================= pkgsrcrecords.cc ========================= */
+ ADDTYPE(Module,"SourceRecords",&PySourceRecords_Type);
+ ADDTYPE(Module,"SourceRecordFiles",&PySourceRecordFiles_Type);
+ /* ========================= sourcelist.cc ========================= */
+ ADDTYPE(Module,"SourceList",&PySourceList_Type);
+ ADDTYPE(Module,"HashString",&PyHashString_Type);
+ ADDTYPE(Module,"Policy",&PyPolicy_Type);
+ ADDTYPE(Module,"Hashes",&PyHashes_Type);
+ ADDTYPE(Module,"AcquireItemDesc",&PyAcquireItemDesc_Type);
+ ADDTYPE(Module,"SystemLock",&PySystemLock_Type);
+ ADDTYPE(Module,"FileLock",&PyFileLock_Type);
+ ADDTYPE(Module,"OrderList",&PyOrderList_Type);
+ ADDTYPE(Module,"HashStringList",&PyHashStringList_Type);
+ // Tag file constants
+ PyModule_AddObject(Module,"REWRITE_PACKAGE_ORDER",
+ CharCharToList(TFRewritePackageOrder));
+
+ PyModule_AddObject(Module,"REWRITE_SOURCE_ORDER",
+ CharCharToList(TFRewriteSourceOrder));
+
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_ADDED", MkPyNumber(pkgOrderList::Added));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_ADD_PENDIG", MkPyNumber(pkgOrderList::AddPending));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_IMMEDIATE", MkPyNumber(pkgOrderList::Immediate));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_LOOP", MkPyNumber(pkgOrderList::Loop));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_UNPACKED", MkPyNumber(pkgOrderList::UnPacked));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_CONFIGURED", MkPyNumber(pkgOrderList::Configured));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_REMOVED", MkPyNumber(pkgOrderList::Removed));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_IN_LIST", MkPyNumber(pkgOrderList::InList));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_AFTER", MkPyNumber(pkgOrderList::After));
+ PyDict_SetItemString(PyOrderList_Type.tp_dict, "FLAG_STATES_MASK", MkPyNumber(pkgOrderList::States));
+
+ // Acquire constants.
+ // some constants
+ PyDict_SetItemString(PyAcquire_Type.tp_dict, "RESULT_CANCELLED",
+ MkPyNumber(pkgAcquire::Cancelled));
+ PyDict_SetItemString(PyAcquire_Type.tp_dict, "RESULT_CONTINUE",
+ MkPyNumber(pkgAcquire::Continue));
+ PyDict_SetItemString(PyAcquire_Type.tp_dict, "RESULT_FAILED",
+ MkPyNumber(pkgAcquire::Failed));
+ // Dependency constants
+ PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_DEPENDS",
+ MkPyNumber(pkgCache::Dep::Depends));
+ PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_PREDEPENDS",
+ MkPyNumber(pkgCache::Dep::PreDepends));
+ PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_SUGGESTS",
+ MkPyNumber(pkgCache::Dep::Suggests));
+ PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_RECOMMENDS",
+ MkPyNumber(pkgCache::Dep::Recommends));
+ PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_CONFLICTS",
+ MkPyNumber(pkgCache::Dep::Conflicts));
+ PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_REPLACES",
+ MkPyNumber(pkgCache::Dep::Replaces));
+ PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_OBSOLETES",
+ MkPyNumber(pkgCache::Dep::Obsoletes));
+ PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_DPKG_BREAKS",
+ MkPyNumber(pkgCache::Dep::DpkgBreaks));
+ PyDict_SetItemString(PyDependency_Type.tp_dict, "TYPE_ENHANCES",
+ MkPyNumber(pkgCache::Dep::Enhances));
+
+
+ // PackageManager constants
+ PyDict_SetItemString(PyPackageManager_Type.tp_dict, "RESULT_COMPLETED",
+ MkPyNumber(pkgPackageManager::Completed));
+ PyDict_SetItemString(PyPackageManager_Type.tp_dict, "RESULT_FAILED",
+ MkPyNumber(pkgPackageManager::Failed));
+ PyDict_SetItemString(PyPackageManager_Type.tp_dict, "RESULT_INCOMPLETE",
+ MkPyNumber(pkgPackageManager::Incomplete));
+
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_NO",
+ MkPyNumber(pkgCache::Version::No));
+ // NONE is deprecated (#782802)
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_NONE",
+ MkPyNumber(pkgCache::Version::No));
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_ALL",
+ MkPyNumber(pkgCache::Version::All));
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_FOREIGN",
+ MkPyNumber(pkgCache::Version::Foreign));
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_SAME",
+ MkPyNumber(pkgCache::Version::Same));
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_ALLOWED",
+ MkPyNumber(pkgCache::Version::Allowed));
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_ALL_FOREIGN",
+ MkPyNumber(pkgCache::Version::AllForeign));
+ PyDict_SetItemString(PyVersion_Type.tp_dict, "MULTI_ARCH_ALL_ALLOWED",
+ MkPyNumber(pkgCache::Version::AllAllowed));
+ // AcquireItem Constants.
+ PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_IDLE",
+ MkPyNumber(pkgAcquire::Item::StatIdle));
+ PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_FETCHING",
+ MkPyNumber(pkgAcquire::Item::StatFetching));
+ PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_DONE",
+ MkPyNumber(pkgAcquire::Item::StatDone));
+ PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_TRANSIENT_NETWORK_ERROR",
+ MkPyNumber(pkgAcquire::Item::StatTransientNetworkError));
+ PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_ERROR",
+ MkPyNumber(pkgAcquire::Item::StatError));
+ PyDict_SetItemString(PyAcquireItem_Type.tp_dict, "STAT_AUTH_ERROR",
+ MkPyNumber(pkgAcquire::Item::StatAuthError));
+ // TagSection constants
+ PyDict_SetItemString(PyTag_Type.tp_dict, "REMOVE",
+ MkPyNumber(pkgTagSection::Tag::REMOVE));
+ PyDict_SetItemString(PyTag_Type.tp_dict, "REWRITE",
+ MkPyNumber(pkgTagSection::Tag::REWRITE));
+ PyDict_SetItemString(PyTag_Type.tp_dict, "RENAME",
+ MkPyNumber(pkgTagSection::Tag::RENAME));
+
+#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 1
+ PyObject *PyCapsule = PyCapsule_New(&API, "apt_pkg._C_API", NULL);
+#else
+ PyObject *PyCapsule = PyCObject_FromVoidPtr(&API, NULL);
+#endif
+ PyModule_AddObject(Module, "_C_API", PyCapsule);
+ // Version..
+ PyModule_AddStringConstant(Module,"VERSION",(char *)pkgVersion);
+ PyModule_AddStringConstant(Module,"LIB_VERSION",(char *)pkgLibVersion);
+#ifdef DATE
+ PyModule_AddStringConstant(Module,"DATE",DATE);
+ PyModule_AddStringConstant(Module,"TIME",TIME);
+#else
+ PyModule_AddStringConstant(Module,"DATE", "Jan 1 1970");
+ PyModule_AddStringConstant(Module,"TIME", "00:00:00");
+#endif
+
+ // My constants
+ PyModule_AddIntConstant(Module,"PRI_IMPORTANT",pkgCache::State::Important);
+ PyModule_AddIntConstant(Module,"PRI_REQUIRED",pkgCache::State::Required);
+ PyModule_AddIntConstant(Module,"PRI_STANDARD",pkgCache::State::Standard);
+ PyModule_AddIntConstant(Module,"PRI_OPTIONAL",pkgCache::State::Optional);
+ PyModule_AddIntConstant(Module,"PRI_EXTRA",pkgCache::State::Extra);
+ // CurState
+ PyModule_AddIntConstant(Module,"CURSTATE_NOT_INSTALLED",pkgCache::State::NotInstalled);
+ PyModule_AddIntConstant(Module,"CURSTATE_UNPACKED",pkgCache::State::UnPacked);
+ PyModule_AddIntConstant(Module,"CURSTATE_HALF_CONFIGURED",pkgCache::State::HalfConfigured);
+ PyModule_AddIntConstant(Module,"CURSTATE_HALF_INSTALLED",pkgCache::State::HalfInstalled);
+ PyModule_AddIntConstant(Module,"CURSTATE_CONFIG_FILES",pkgCache::State::ConfigFiles);
+ PyModule_AddIntConstant(Module,"CURSTATE_INSTALLED",pkgCache::State::Installed);
+ // SelState
+ PyModule_AddIntConstant(Module,"SELSTATE_UNKNOWN",pkgCache::State::Unknown);
+ PyModule_AddIntConstant(Module,"SELSTATE_INSTALL",pkgCache::State::Install);
+ PyModule_AddIntConstant(Module,"SELSTATE_HOLD",pkgCache::State::Hold);
+ PyModule_AddIntConstant(Module,"SELSTATE_DEINSTALL",pkgCache::State::DeInstall);
+ PyModule_AddIntConstant(Module,"SELSTATE_PURGE",pkgCache::State::Purge);
+ // InstState
+ PyModule_AddIntConstant(Module,"INSTSTATE_OK",pkgCache::State::Ok);
+ PyModule_AddIntConstant(Module,"INSTSTATE_REINSTREQ",pkgCache::State::ReInstReq);
+ PyModule_AddIntConstant(Module,"INSTSTATE_HOLD",pkgCache::State::Hold);
+ PyModule_AddIntConstant(Module,"INSTSTATE_HOLD_REINSTREQ",pkgCache::State::HoldReInstReq);
+
+ #if PY_MAJOR_VERSION >= 3
+ return Module;
+ #endif
+}
+ /*}}}*/
+
diff --git a/python/apt_pkgmodule.h b/python/apt_pkgmodule.h
new file mode 100644
index 0000000..ee92c50
--- /dev/null
+++ b/python/apt_pkgmodule.h
@@ -0,0 +1,214 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: apt_pkgmodule.h,v 1.4 2003/07/23 02:20:24 mdz Exp $
+/* ######################################################################
+
+ Prototypes for the module
+
+ ##################################################################### */
+ /*}}}*/
+#ifndef APT_PKGMODULE_H
+#define APT_PKGMODULE_H
+
+#include <Python.h>
+#include <apt-pkg/hashes.h>
+#include <apt-pkg/acquire-item.h>
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/packagemanager.h>
+#include <apt-pkg/version.h>
+#include <apt-pkg/deblistparser.h>
+#include <apt-pkg/pkgcache.h>
+#include <apt-pkg/cachefile.h>
+#include <apt-pkg/tagfile.h>
+#include <apt-pkg/init.h>
+#include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/cdrom.h>
+#include <apt-pkg/algorithms.h>
+#include <apt-pkg/metaindex.h>
+#include "generic.h"
+
+// Configuration Stuff
+extern PyTypeObject PyConfiguration_Type;
+extern PyTypeObject PyVersion_Type;
+
+extern char *doc_LoadConfig;
+extern char *doc_LoadConfigISC;
+extern char *doc_LoadConfigDir;
+extern char *doc_ParseCommandLine;
+PyObject *LoadConfig(PyObject *Self,PyObject *Args);
+PyObject *LoadConfigISC(PyObject *Self,PyObject *Args);
+PyObject *LoadConfigDir(PyObject *Self,PyObject *Args);
+PyObject *ParseCommandLine(PyObject *Self,PyObject *Args);
+
+// Tag File Stuff
+extern PyTypeObject PyTagSection_Type;
+extern PyTypeObject PyTagFile_Type;
+extern PyTypeObject PyTag_Type;
+extern PyTypeObject PyTagRewrite_Type;
+extern PyTypeObject PyTagRename_Type;
+extern PyTypeObject PyTagRemove_Type;
+extern char *doc_ParseSection;
+extern char *doc_ParseTagFile;
+PyObject *ParseSection(PyObject *self,PyObject *Args);
+PyObject *ParseTagFile(PyObject *self,PyObject *Args);
+
+// String Stuff
+PyObject *StrQuoteString(PyObject *self,PyObject *Args);
+PyObject *StrDeQuote(PyObject *self,PyObject *Args);
+PyObject *StrSizeToStr(PyObject *self,PyObject *Args);
+PyObject *StrTimeToStr(PyObject *self,PyObject *Args);
+PyObject *StrURItoFileName(PyObject *self,PyObject *Args);
+PyObject *StrBase64Encode(PyObject *self,PyObject *Args);
+PyObject *StrStringToBool(PyObject *self,PyObject *Args);
+PyObject *StrTimeRFC1123(PyObject *self,PyObject *Args);
+PyObject *StrStrToTime(PyObject *self,PyObject *Args);
+PyObject *StrCheckDomainList(PyObject *Self,PyObject *Args);
+
+PyObject *PyAcquire_GetItem(PyObject *self, pkgAcquire::Item *item);
+PyObject *PyAcquire_GetItemDesc(PyObject *self, pkgAcquire::ItemDesc *item);
+bool PyAcquire_DropItem(PyObject *self, pkgAcquire::Item *item);
+
+// Cache Stuff
+extern PyTypeObject PyCache_Type;
+extern PyTypeObject PyCacheFile_Type;
+extern PyTypeObject PyPackageList_Type;
+extern PyTypeObject PyDescription_Type;
+extern PyTypeObject PyGroup_Type;
+extern PyTypeObject PyGroupList_Type; /* internal */
+extern PyTypeObject PyPackage_Type;
+extern PyTypeObject PyPackageFile_Type;
+extern PyTypeObject PyDependency_Type;
+extern PyTypeObject PyDependencyList_Type;
+PyObject *TmpGetCache(PyObject *Self,PyObject *Args);
+
+// DepCache
+extern PyTypeObject PyDepCache_Type;
+PyObject *GetDepCache(PyObject *Self,PyObject *Args);
+
+// pkgProblemResolver
+extern PyTypeObject PyProblemResolver_Type;
+PyObject *GetPkgProblemResolver(PyObject *Self, PyObject *Args);
+PyObject *GetPkgActionGroup(PyObject *Self, PyObject *Args);
+
+extern PyTypeObject PyActionGroup_Type;
+// cdrom
+extern PyTypeObject PyCdrom_Type;
+PyObject *GetCdrom(PyObject *Self,PyObject *Args);
+
+// acquire
+extern PyTypeObject PyAcquireItem_Type;
+extern PyTypeObject PyAcquire_Type;
+extern PyTypeObject PyAcquireFile_Type;
+extern char *doc_GetPkgAcqFile;
+PyObject *GetAcquire(PyObject *Self,PyObject *Args);
+PyObject *GetPkgAcqFile(PyObject *Self, PyObject *Args, PyObject *kwds);
+
+// packagemanager
+extern PyTypeObject PyPackageManager_Type;
+extern PyTypeObject PyPackageManager2_Type;
+PyObject *GetPkgManager(PyObject *Self,PyObject *Args);
+
+
+// PkgRecords Stuff
+extern PyTypeObject PyPackageRecords_Type;
+extern PyTypeObject PySourceRecords_Type;
+extern PyTypeObject PySourceRecordFiles_Type;
+PyObject *GetPkgRecords(PyObject *Self,PyObject *Args);
+PyObject *GetPkgSrcRecords(PyObject *Self,PyObject *Args);
+
+// pkgSourceList
+extern PyTypeObject PySourceList_Type;
+PyObject *GetPkgSourceList(PyObject *Self,PyObject *Args);
+
+// pkgSourceList
+extern PyTypeObject PyIndexFile_Type;
+
+// metaIndex
+extern PyTypeObject PyMetaIndex_Type;
+
+// HashString
+extern PyTypeObject PyHashString_Type;
+
+extern PyTypeObject PyHashStringList_Type;
+
+
+// Policy
+extern PyTypeObject PyPolicy_Type;
+extern PyTypeObject PyHashes_Type;
+extern PyTypeObject PyAcquireItemDesc_Type;
+extern PyTypeObject PyAcquireWorker_Type;
+extern PyTypeObject PySystemLock_Type;
+extern PyTypeObject PyFileLock_Type;
+extern PyTypeObject PyOrderList_Type;
+
+// Functions to be exported in the public API.
+
+# define PyAcquire_ToCpp GetCpp<pkgAcquire*>
+# define PyAcquireFile_ToCpp GetCpp<pkgAcqFile*>
+# define PyAcquireItem_ToCpp GetCpp<pkgAcquire::Item*>
+# define PyAcquireItemDesc_ToCpp GetCpp<pkgAcquire::ItemDesc*>
+# define PyAcquireWorker_ToCpp GetCpp<pkgAcquire::Worker*>
+# define PyActionGroup_ToCpp GetCpp<pkgDepCache::ActionGroup*>
+# define PyCache_ToCpp GetCpp<pkgCache*>
+# define PyCacheFile_ToCpp GetCpp<pkgCacheFile*>
+# define PyCdrom_ToCpp GetCpp<pkgCdrom>
+# define PyConfiguration_ToCpp GetCpp<Configuration*>
+# define PyDepCache_ToCpp GetCpp<pkgDepCache*>
+# define PyDependency_ToCpp GetCpp<pkgCache::DepIterator>
+# define PyDependencyList_ToCpp GetCpp<RDepListStruct> // TODO
+# define PyDescription_ToCpp GetCpp<pkgCache::DescIterator>
+# define PyGroup_ToCpp GetCpp<pkgCache::GrpIterator>
+# define PyHashes_ToCpp GetCpp<Hashes>
+# define PyHashString_ToCpp GetCpp<HashString*>
+# define PyMetaIndex_ToCpp GetCpp<metaIndex*>
+# define PyPackage_ToCpp GetCpp<pkgCache::PkgIterator>
+# define PyPackageFile_ToCpp GetCpp<pkgCache::PkgFileIterator>
+# define PyIndexFile_ToCpp GetCpp<pkgIndexFile*>
+# define PyOrderList_ToCpp GetCpp<pkgOrderList*>
+# define PyPackageList_ToCpp GetCpp<PkgListStruct> // TODO
+# define PyPackageManager_ToCpp GetCpp<pkgPackageManager*>
+# define PyPackageRecords_ToCpp GetCpp<PkgRecordsStruct> // TODO
+# define PyPolicy_ToCpp GetCpp<pkgPolicy*>
+# define PyProblemResolver_ToCpp GetCpp<pkgProblemResolver*>
+# define PySourceList_ToCpp GetCpp<pkgSourceList*>
+# define PySourceRecords_ToCpp GetCpp<PkgSrcRecordsStruct> // TODO
+# define PyTagFile_ToCpp GetCpp<pkgTagFile>
+# define PyTagSection_ToCpp GetCpp<pkgTagSection>
+# define PyVersion_ToCpp GetCpp<pkgCache::VerIterator>
+
+PyObject* PyAcquire_FromCpp(pkgAcquire *fetcher, bool Delete, PyObject *Owner);
+PyObject* PyAcquireFile_FromCpp(pkgAcqFile* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyAcquireItem_FromCpp(pkgAcquire::Item* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyAcquireItemDesc_FromCpp(pkgAcquire::ItemDesc* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyAcquireWorker_FromCpp(pkgAcquire::Worker* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyActionGroup_FromCpp(pkgDepCache::ActionGroup* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyCache_FromCpp(pkgCache* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyCacheFile_FromCpp(pkgCacheFile* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyCdrom_FromCpp(pkgCdrom const &obj, bool Delete, PyObject *Owner);
+PyObject* PyConfiguration_FromCpp(Configuration* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyDepCache_FromCpp(pkgDepCache* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyDependency_FromCpp(pkgCache::DepIterator const &obj, bool Delete, PyObject *Owner);
+//PyObject* PyDependencyList_FromCpp(RDepListStruct const &obj, bool Delete, PyObject *Owner);
+PyObject* PyDescription_FromCpp(pkgCache::DescIterator const &obj, bool Delete, PyObject *Owner);
+PyObject* PyHashes_FromCpp(Hashes const &obj, bool Delete, PyObject *Owner);
+PyObject* PyHashString_FromCpp(HashString* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyMetaIndex_FromCpp(metaIndex* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyPackage_FromCpp(pkgCache::PkgIterator const &obj, bool Delete, PyObject *Owner);
+PyObject* PyGroup_FromCpp(pkgCache::GrpIterator const &obj, bool Delete, PyObject *Owner);
+PyObject* PyIndexFile_FromCpp(pkgIndexFile* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyOrderList_FromCpp(pkgOrderList* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyPackageFile_FromCpp(pkgCache::PkgFileIterator const &obj, bool Delete, PyObject *Owner);
+//PyObject* PyPackageList_FromCpp(PkgListStruct const &obj, bool Delete, PyObject *Owner);
+PyObject* PyPackageManager_FromCpp(pkgPackageManager* const &obj, bool Delete, PyObject *Owner);
+//PyObject* PyPackageRecords_FromCpp(PkgRecordsStruct const &obj, bool Delete, PyObject *Owner);
+PyObject* PyPolicy_FromCpp(pkgPolicy* const &obj, bool Delete, PyObject *Owner);
+PyObject* PyProblemResolver_FromCpp(pkgProblemResolver* const &obj, bool Delete, PyObject *Owner);
+PyObject* PySourceList_FromCpp(pkgSourceList* const &obj, bool Delete, PyObject *Owner);
+//PyObject* PySourceRecords_FromCpp(PkgSrcRecordsStruct const &obj, bool Delete, PyObject *Owner);
+PyObject* PyTagFile_FromCpp(pkgTagFile const &obj, bool Delete, PyObject *Owner);
+PyObject* PyTagSection_FromCpp(pkgTagSection const &obj, bool Delete, PyObject *Owner);
+PyObject* PyVersion_FromCpp(pkgCache::VerIterator const &obj, bool Delete, PyObject *Owner);
+
+#include "python-apt.h"
+#endif
+
diff --git a/python/arfile.cc b/python/arfile.cc
new file mode 100644
index 0000000..8f623b3
--- /dev/null
+++ b/python/arfile.cc
@@ -0,0 +1,744 @@
+/*
+ * arfile.cc - Wrapper around ARArchive and ARArchive::Member.
+ *
+ * Copyright 2009 Julian Andres Klode <jak@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <Python.h>
+#include "generic.h"
+#include "apt_instmodule.h"
+#include <apt-pkg/arfile.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/aptconfiguration.h>
+#include <apt-pkg/configuration.h>
+#include <utime.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <array>
+
+static PyObject *armember_get_name(PyObject *self, void *closure)
+{
+ return CppPyPath(GetCpp<ARArchive::Member*>(self)->Name);
+}
+
+static PyObject *armember_get_mtime(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<ARArchive::Member*>(self)->MTime);
+}
+
+static PyObject *armember_get_uid(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<ARArchive::Member*>(self)->UID);
+}
+
+static PyObject *armember_get_gid(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<ARArchive::Member*>(self)->GID);
+}
+
+static PyObject *armember_get_mode(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<ARArchive::Member*>(self)->Mode);
+}
+
+static PyObject *armember_get_size(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<ARArchive::Member*>(self)->Size);
+}
+
+static PyObject *armember_get_start(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<ARArchive::Member*>(self)->Start);
+}
+
+static PyObject *armember_repr(PyObject *self)
+{
+ return PyString_FromFormat("<%s object: name:'%s'>",
+ self->ob_type->tp_name,
+ GetCpp<ARArchive::Member*>(self)->Name.c_str());
+}
+
+static PyGetSetDef armember_getset[] = {
+ {"gid",armember_get_gid,0,"The group id of the owner."},
+ {"mode",armember_get_mode,0,"The mode of the file."},
+ {"mtime",armember_get_mtime,0,"Last time of modification."},
+ {"name",armember_get_name,0,"The name of the file."},
+ {"size",armember_get_size,0,"The size of the files."},
+ {"start",armember_get_start,0,
+ "The offset in the archive where the file starts."},
+ {"uid",armember_get_uid,0,"The user ID of the owner."},
+ {NULL}
+};
+
+static const char *armember_doc =
+ "Represent a single file within an AR archive. For\n"
+ "Debian packages this can be e.g. control.tar.gz. This class provides\n"
+ "information about this file, such as the mode and size.";
+PyTypeObject PyArMember_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_inst.ArMember", // tp_name
+ sizeof(CppPyObject<ARArchive::Member*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<ARArchive::Member*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ armember_repr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_HAVE_GC,
+ armember_doc, // tp_doc
+ CppTraverse<ARArchive::Member*>,// tp_traverse
+ CppClear<ARArchive::Member*>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ armember_getset, // tp_getset
+};
+
+
+static const char *filefd_doc=
+ "Internal helper type, representing a FileFd.";
+PyTypeObject PyFileFd_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_inst.__FileFd" , // tp_name
+ sizeof(CppPyObject<FileFd>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<FileFd>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_HAVE_GC,
+ filefd_doc, // tp_doc
+ CppTraverse<FileFd>, // tp_traverse
+ CppClear<FileFd>, // tp_clear
+};
+
+
+// We just add an inline method and should thus be ABI compatible in a way that
+// we can simply cast ARArchive instances to PyARArchiveHack.
+class PyARArchiveHack : public ARArchive
+{
+public:
+ inline Member *Members() {
+ return List;
+ }
+};
+
+struct PyArArchiveObject : public CppPyObject<PyARArchiveHack*> {
+ CppPyObject<FileFd> *Fd;
+};
+
+static const char *ararchive_getmember_doc =
+ "getmember(name: str) -> ArMember\n\n"
+ "Return an ArMember object for the member given by 'name'. Raise\n"
+ "LookupError if there is no ArMember with the given name.";
+static PyObject *ararchive_getmember(PyArArchiveObject *self, PyObject *arg)
+{
+ PyApt_Filename name;
+ CppPyObject<ARArchive::Member*> *ret;
+ if (!name.init(arg))
+ return 0;
+
+ const ARArchive::Member *member = self->Object->FindMember(name);
+ if (!member) {
+ PyErr_Format(PyExc_LookupError,"No member named '%s'",name.path);
+ return 0;
+ }
+
+ // Create our object.
+ ret = CppPyObject_NEW<ARArchive::Member*>(self,&PyArMember_Type);
+ ret->Object = const_cast<ARArchive::Member*>(member);
+ ret->NoDelete = true;
+ return ret;
+}
+
+static const char *ararchive_extractdata_doc =
+ "extractdata(name: str) -> bytes\n\n"
+ "Return the contents of the member, as a bytes object. Raise\n"
+ "LookupError if there is no ArMember with the given name.";
+static PyObject *ararchive_extractdata(PyArArchiveObject *self, PyObject *args)
+{
+ PyApt_Filename name;
+ if (PyArg_ParseTuple(args, "O&:extractdata", PyApt_Filename::Converter, &name) == 0)
+ return 0;
+ const ARArchive::Member *member = self->Object->FindMember(name);
+ if (!member) {
+ PyErr_Format(PyExc_LookupError,"No member named '%s'",name.path);
+ return 0;
+ }
+ if (member->Size > SIZE_MAX) {
+ PyErr_Format(PyExc_MemoryError,
+ "Member '%s' is too large to read into memory",name.path);
+ return 0;
+ }
+ if (!self->Fd->Object.Seek(member->Start))
+ return HandleErrors();
+
+ char* value;
+ try {
+ value = new char[member->Size];
+ } catch (std::bad_alloc&) {
+ PyErr_Format(PyExc_MemoryError,
+ "Member '%s' is too large to read into memory",name.path);
+ return 0;
+ }
+ self->Fd->Object.Read(value, member->Size, true);
+ PyObject *result = PyBytes_FromStringAndSize(value, member->Size);
+ delete[] value;
+ return result;
+}
+
+// Helper class to close the FD automatically.
+class IntFD {
+ public:
+ int fd;
+ inline operator int() { return fd; };
+ inline IntFD(int fd): fd(fd) { };
+ inline ~IntFD() { close(fd); };
+};
+
+static PyObject *_extract(FileFd &Fd, const ARArchive::Member *member,
+ const char *dir)
+{
+ if (!Fd.Seek(member->Start))
+ return HandleErrors();
+
+ std::string outfile_str = flCombine(dir,member->Name);
+ char *outfile = (char*)outfile_str.c_str();
+
+ // We are not using FileFd here, because we want to raise OSErrror with
+ // the correct errno and filename. IntFD's are closed automatically.
+ IntFD outfd(open(outfile, O_NDELAY|O_WRONLY|O_CREAT|O_TRUNC|O_APPEND,
+ member->Mode));
+ if (outfd == -1)
+ return PyErr_SetFromErrnoWithFilename(PyExc_OSError, outfile);
+ if (fchmod(outfd, member->Mode) == -1)
+ return PyErr_SetFromErrnoWithFilename(PyExc_OSError, outfile);
+ if (fchown(outfd, member->UID, member->GID) != 0 && errno != EPERM)
+ return PyErr_SetFromErrnoWithFilename(PyExc_OSError, outfile);
+
+ // Read 4 KiB from the file, until all of the file is read. Deallocated
+ // automatically when the function returns.
+ std::array<char, 4096> value;
+ unsigned long long size = member->Size;
+ unsigned long long read = 4096;
+ while (size > 0) {
+ if (size < read)
+ read = size;
+ if (!Fd.Read(value.data(), read, true))
+ return HandleErrors();
+ if (write(outfd, value.data(), read) != (signed long long)read)
+ return PyErr_SetFromErrnoWithFilename(PyExc_OSError, outfile);
+ size -= read;
+ }
+ utimbuf time = {static_cast<time_t>(member->MTime),
+ static_cast<time_t>(member->MTime)};
+ if (utime(outfile,&time) == -1)
+ return PyErr_SetFromErrnoWithFilename(PyExc_OSError, outfile);
+ Py_RETURN_TRUE;
+}
+
+static const char *ararchive_extract_doc =
+ "extract(name: str[, target: str]) -> bool\n\n"
+ "Extract the member given by 'name' into the directory given\n"
+ "by 'target'. If the extraction fails, raise OSError. In case\n"
+ "of success, return True if the file owner could be set or\n"
+ "False if this was not possible. If the requested member\n"
+ "does not exist, raise LookupError.";
+static PyObject *ararchive_extract(PyArArchiveObject *self, PyObject *args)
+{
+ PyApt_Filename name;
+ PyApt_Filename target;
+
+ target = "";
+ if (PyArg_ParseTuple(args, "O&|O&:extract", PyApt_Filename::Converter, &name, PyApt_Filename::Converter, &target) == 0)
+ return 0;
+
+ const ARArchive::Member *member = self->Object->FindMember(name);
+
+ if (!member) {
+ PyErr_Format(PyExc_LookupError,"No member named '%s'",name.path);
+ return 0;
+ }
+ return _extract(self->Fd->Object, member, target);
+}
+
+static const char *ararchive_extractall_doc =
+ "extractall([target: str]) -> bool\n\n"
+ "Extract all archive contents into the directory given by 'target'. If\n"
+ "the extraction fails, raise an error. Otherwise, return True if the\n"
+ "owner could be set or False if the owner could not be changed.";
+
+static PyObject *ararchive_extractall(PyArArchiveObject *self, PyObject *args)
+{
+ PyApt_Filename target;
+ target = "";
+ if (PyArg_ParseTuple(args, "|O&:extractall", PyApt_Filename::Converter, &target) == 0)
+ return 0;
+
+ const ARArchive::Member *member = self->Object->Members();
+
+ do {
+ if (_extract(self->Fd->Object, member, target) == 0)
+ return 0;
+ } while ((member = member->Next));
+ Py_RETURN_TRUE;
+}
+
+static const char *ararchive_gettar_doc =
+ "gettar(name: str, comp: str) -> TarFile\n\n"
+ "Return a TarFile object for the member given by 'name' which will be\n"
+ "decompressed using the compression algorithm given by 'comp'.\n"
+ "This is almost equal to:\n\n"
+ " member = arfile.getmember(name)\n"
+ " tarfile = TarFile(file, member.start, member.size, 'gzip')'\n\n"
+ "It just opens a new TarFile on the given position in the stream.";
+static PyObject *ararchive_gettar(PyArArchiveObject *self, PyObject *args)
+{
+ PyApt_Filename name;
+ const char *comp;
+ if (PyArg_ParseTuple(args, "O&s:gettar", PyApt_Filename::Converter, &name, &comp) == 0)
+ return 0;
+
+ const ARArchive::Member *member = self->Object->FindMember(name);
+ if (!member) {
+ PyErr_Format(PyExc_LookupError,"No member named '%s'",name.path);
+ return 0;
+ }
+
+ PyTarFileObject *tarfile = (PyTarFileObject*)CppPyObject_NEW<ExtractTar*>(self->Fd,&PyTarFile_Type);
+ new (&tarfile->Fd) FileFd(self->Fd->Object.Fd());
+ tarfile->min = member->Start;
+ tarfile->Object = new ExtractTar(self->Fd->Object, member->Size, comp);
+ return HandleErrors(tarfile);
+}
+
+static const char *ararchive_getmembers_doc =
+ "getmembers() -> list\n\n"
+ "Return a list of all members in the archive.";
+static PyObject *ararchive_getmembers(PyArArchiveObject *self)
+{
+ PyObject *list = PyList_New(0);
+ ARArchive::Member *member = self->Object->Members();
+ do {
+ CppPyObject<ARArchive::Member*> *ret;
+ ret = CppPyObject_NEW<ARArchive::Member*>(self,&PyArMember_Type);
+ ret->Object = member;
+ ret->NoDelete = true;
+ PyList_Append(list, ret);
+ Py_DECREF(ret);
+ } while ((member = member->Next));
+ return list;
+}
+
+static const char *ararchive_getnames_doc =
+ "getnames() -> list\n\n"
+ "Return a list of the names of all members in the archive.";
+static PyObject *ararchive_getnames(PyArArchiveObject *self)
+{
+ PyObject *list = PyList_New(0);
+ ARArchive::Member *member = self->Object->Members();
+ do {
+ PyObject *item = CppPyString(member->Name);
+ PyList_Append(list, item);
+ Py_DECREF(item);
+ } while ((member = member->Next));
+ return list;
+}
+
+// Just run getmembers() and return an iterator over the list.
+static PyObject *ararchive_iter(PyArArchiveObject *self) {
+ PyObject *members = ararchive_getmembers(self);
+ PyObject *iter = PyObject_GetIter(members);
+ Py_DECREF(members);
+ return iter;
+}
+
+static PyMethodDef ararchive_methods[] = {
+ {"getmember",(PyCFunction)ararchive_getmember,METH_O,
+ ararchive_getmember_doc},
+ {"gettar",(PyCFunction)ararchive_gettar,METH_VARARGS,
+ ararchive_gettar_doc},
+ {"extractdata",(PyCFunction)ararchive_extractdata,METH_VARARGS,
+ ararchive_extractdata_doc},
+ {"extract",(PyCFunction)ararchive_extract,METH_VARARGS,
+ ararchive_extract_doc},
+ {"extractall",(PyCFunction)ararchive_extractall,METH_VARARGS,
+ ararchive_extractall_doc},
+ {"getmembers",(PyCFunction)ararchive_getmembers,METH_NOARGS,
+ ararchive_getmembers_doc},
+ {"getnames",(PyCFunction)ararchive_getnames,METH_NOARGS,
+ ararchive_getnames_doc},
+ {NULL}
+};
+
+static PyObject *ararchive_new(PyTypeObject *type, PyObject *args,
+ PyObject *kwds)
+{
+ PyObject *file;
+ PyApt_Filename filename;
+ int fileno;
+ if (PyArg_ParseTuple(args,"O:__new__",&file) == 0)
+ return 0;
+
+ PyApt_UniqueObject<PyArArchiveObject> self(NULL);
+ // We receive a filename.
+ if (filename.init(file)) {
+ self.reset((PyArArchiveObject*) CppPyObject_NEW<ARArchive*>(0,type));
+ self->Fd = CppPyObject_NEW<FileFd>(NULL, &PyFileFd_Type);
+ new (&self->Fd->Object) FileFd(filename,FileFd::ReadOnly);
+ }
+ // We receive a file object.
+ else if ((fileno = PyObject_AsFileDescriptor(file)) != -1) {
+ // Clear the error set by PyObject_AsString().
+ PyErr_Clear();
+ self.reset((PyArArchiveObject*) CppPyObject_NEW<ARArchive*>(NULL,type));
+ self->Fd = CppPyObject_NEW<FileFd>(file, &PyFileFd_Type);
+ new (&self->Fd->Object) FileFd(fileno,false);
+ }
+ else {
+ return 0;
+ }
+ self->Object = (PyARArchiveHack*)new ARArchive(self->Fd->Object);
+ if (_error->PendingError() == true)
+ return HandleErrors();
+ return self.release();
+}
+
+static int ararchive_traverse(PyObject *_self, visitproc visit, void* arg)
+{
+ PyArArchiveObject *self = (PyArArchiveObject*)_self;
+ Py_VISIT(self->Fd);
+ return CppTraverse<ARArchive*>(self, visit, arg);
+}
+
+static int ararchive_clear(PyObject *_self)
+{
+ PyArArchiveObject *self = (PyArArchiveObject*)_self;
+ Py_CLEAR(self->Fd);
+ return CppClear<ARArchive*>(self);
+}
+
+static void ararchive_dealloc(PyObject *self)
+{
+ ararchive_clear(self);
+ CppDeallocPtr<ARArchive*>(self);
+}
+
+// Return bool or -1 (exception).
+static int ararchive_contains(PyObject *self, PyObject *arg)
+{
+ PyApt_Filename name;
+ if (!name.init(arg))
+ return -1;
+ return (GetCpp<ARArchive*>(self)->FindMember(name) != 0);
+}
+
+static PySequenceMethods ararchive_as_sequence = {
+ 0,0,0,0,0,0,0,ararchive_contains,0,0
+};
+
+static PyMappingMethods ararchive_as_mapping = {
+ 0,(PyCFunction)ararchive_getmember,0
+};
+
+static const char *ararchive_doc =
+ "ArArchive(file: str/int/file)\n\n"
+ "Represent an archive in the 4.4 BSD ar format,\n"
+ "which is used for e.g. deb packages.\n\n"
+ "The parameter 'file' may be a string specifying the path of a file, or\n"
+ "a file-like object providing the fileno() method. It may also be an int\n"
+ "specifying a file descriptor (returned by e.g. os.open()).\n"
+ "The recommended way of using it is to pass in the path to the file.";
+
+PyTypeObject PyArArchive_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_inst.ArArchive", // tp_name
+ sizeof(PyArArchiveObject), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ ararchive_dealloc, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &ararchive_as_sequence, // tp_as_sequence
+ &ararchive_as_mapping, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_HAVE_GC,
+ ararchive_doc, // tp_doc
+ ararchive_traverse, // tp_traverse
+ ararchive_clear, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ (getiterfunc)ararchive_iter, // tp_iter
+ 0, // tp_iternext
+ ararchive_methods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ ararchive_new // tp_new
+};
+
+/**
+ * Representation of a Debian package.
+ *
+ * This does not resemble debDebFile in apt-inst, but instead is a subclass
+ * of ArFile which adds properties for the control.tar.$compression and
+ * data.tar.$compression members which return TarFile objects. It also adds
+ * a descriptor 'version' which returns the content of 'debian-binary'.
+ *
+ * We are using it this way as it seems more natural to represent this special
+ * kind of AR archive as an AR archive with some extras.
+ */
+struct PyDebFileObject : PyArArchiveObject {
+ PyObject *data;
+ PyObject *control;
+ PyObject *debian_binary;
+};
+
+static PyObject *debfile_get_data(PyDebFileObject *self)
+{
+ return Py_INCREF(self->data), self->data;
+}
+
+static PyObject *debfile_get_control(PyDebFileObject *self)
+{
+ return Py_INCREF(self->control), self->control;
+}
+
+static PyObject *debfile_get_debian_binary(PyDebFileObject *self)
+{
+ return Py_INCREF(self->debian_binary), self->debian_binary;
+}
+
+static PyObject *_gettar(PyDebFileObject *self, const ARArchive::Member *m,
+ const char *comp)
+{
+ if (!m)
+ return 0;
+ PyTarFileObject *tarfile = (PyTarFileObject*)CppPyObject_NEW<ExtractTar*>(self->Fd,&PyTarFile_Type);
+ new (&tarfile->Fd) FileFd(self->Fd->Object.Fd());
+ tarfile->min = m->Start;
+ tarfile->Object = new ExtractTar(self->Fd->Object, m->Size, comp);
+ return tarfile;
+}
+
+/*
+ * Mostly copy-paste from APT
+ */
+static PyObject *debfile_get_tar(PyDebFileObject *self, const char *Name)
+{
+ // Get the archive member
+ const ARArchive::Member *Member = NULL;
+ const ARArchive &AR = *self->Object;
+ std::string Compressor;
+
+ std::vector<APT::Configuration::Compressor> compressor =
+ APT::Configuration::getCompressors();
+ for (std::vector<APT::Configuration::Compressor>::const_iterator c =
+ compressor.begin(); c != compressor.end(); ++c) {
+ Member = AR.FindMember(std::string(Name).append(c->Extension).c_str());
+ if (Member == NULL)
+ continue;
+ Compressor = c->Name;
+ break;
+ }
+
+ if (Member == NULL)
+ Member = AR.FindMember(std::string(Name).c_str());
+
+ if (Member == NULL) {
+ std::string ext = std::string(Name) + ".{";
+ for (std::vector<APT::Configuration::Compressor>::const_iterator c =
+ compressor.begin(); c != compressor.end(); ++c) {
+ if (!c->Extension.empty())
+ ext.append(c->Extension.substr(1));
+ }
+ ext.append("}");
+ _error->Error(("Internal error, could not locate member %s"),
+ ext.c_str());
+ return HandleErrors();
+ }
+
+ return _gettar(self, Member, Compressor.c_str());
+}
+
+
+static PyObject *debfile_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ PyApt_UniqueObject<PyDebFileObject> self((PyDebFileObject*)ararchive_new(type, args, kwds));
+ if (self == NULL)
+ return NULL;
+
+ // DebFile
+ self->control = debfile_get_tar(self.get(), "control.tar");
+ if (self->control == NULL)
+ return NULL;
+
+ self->data = debfile_get_tar(self.get(), "data.tar");
+ if (self->data == NULL)
+ return NULL;
+
+ const ARArchive::Member *member = self->Object->FindMember("debian-binary");
+ if (!member)
+ return PyErr_Format(PyAptError, "No debian archive, missing %s",
+ "debian-binary");
+
+ if (!self->Fd->Object.Seek(member->Start))
+ return HandleErrors();
+
+ char* value = new char[member->Size];
+ self->Fd->Object.Read(value, member->Size, true);
+ self->debian_binary = PyBytes_FromStringAndSize(value, member->Size);
+ delete[] value;
+ return self.release();
+}
+
+static int debfile_traverse(PyObject *_self, visitproc visit, void* arg)
+{
+ PyDebFileObject *self = (PyDebFileObject*)_self;
+ Py_VISIT(self->data);
+ Py_VISIT(self->control);
+ Py_VISIT(self->debian_binary);
+ return PyArArchive_Type.tp_traverse(self, visit, arg);
+}
+
+static int debfile_clear(PyObject *_self) {
+ PyDebFileObject *self = (PyDebFileObject*)_self;
+ Py_CLEAR(self->data);
+ Py_CLEAR(self->control);
+ Py_CLEAR(self->debian_binary);
+ return PyArArchive_Type.tp_clear(self);
+}
+
+static void debfile_dealloc(PyObject *self) {
+ debfile_clear((PyDebFileObject *)self);
+ PyArArchive_Type.tp_dealloc(self);
+}
+
+static PyGetSetDef debfile_getset[] = {
+ {"control",(getter)debfile_get_control,0,
+ "The TarFile object associated with the control.tar.gz member."},
+ {"data",(getter)debfile_get_data,0,
+ "The TarFile object associated with the data.tar.$compression member. "
+ "All apt compression methods are supported. "
+ },
+ {"debian_binary",(getter)debfile_get_debian_binary,0,
+ "The package version, as contained in debian-binary."},
+ {NULL}
+};
+
+static const char *debfile_doc =
+ "DebFile(file: str/int/file)\n\n"
+ "A DebFile object represents a file in the .deb package format.\n\n"
+ "The parameter 'file' may be a string specifying the path of a file, or\n"
+ "a file-like object providing the fileno() method. It may also be an int\n"
+ "specifying a file descriptor (returned by e.g. os.open()).\n"
+ "The recommended way of using it is to pass in the path to the file.\n\n"
+ "It differs from ArArchive by providing the members 'control', 'data'\n"
+ "and 'version' for accessing the control.tar.gz, data.tar.$compression \n"
+ "(all apt compression methods are supported), and debian-binary members \n"
+ "in the archive.";
+
+PyTypeObject PyDebFile_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_inst.DebFile", // tp_name
+ sizeof(PyDebFileObject), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ debfile_dealloc, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_HAVE_GC,
+ debfile_doc, // tp_doc
+ debfile_traverse, // tp_traverse
+ debfile_clear, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ debfile_getset, // tp_getset
+ &PyArArchive_Type, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ debfile_new // tp_new
+};
diff --git a/python/cache.cc b/python/cache.cc
new file mode 100644
index 0000000..81bbb96
--- /dev/null
+++ b/python/cache.cc
@@ -0,0 +1,1600 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: cache.cc,v 1.5 2003/06/03 03:03:23 mdz Exp $
+/* ######################################################################
+
+ Cache - Wrapper for the cache related functions
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "generic.h"
+#include "apt_pkgmodule.h"
+
+#include <apt-pkg/pkgcache.h>
+#include <apt-pkg/cachefile.h>
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/sourcelist.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/packagemanager.h>
+#include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/sourcelist.h>
+#include <apt-pkg/algorithms.h>
+#include <apt-pkg/update.h>
+
+#include <Python.h>
+#include "progress.h"
+
+class pkgSourceList;
+
+// must be in sync with pkgCache::DepType in libapt
+// it sucks to have it here duplicated, but we get it
+// translated from libapt and that is certainly not what
+// we want in a programing interface
+const char *UntranslatedDepTypes[] =
+{
+ "", "Depends","PreDepends","Suggests",
+ "Recommends","Conflicts","Replaces",
+ "Obsoletes", "Breaks", "Enhances"
+};
+
+ /*}}}*/
+
+template<typename T> struct IterListStruct
+{
+ T Iter;
+ unsigned long LastIndex;
+
+ IterListStruct(T const &I) : Iter(I), LastIndex(0) {}
+ IterListStruct() : LastIndex(0) {};
+
+ bool move(unsigned long Index) {
+ if ((unsigned)Index >= Count())
+ {
+ PyErr_SetNone(PyExc_IndexError);
+ return false;
+ }
+
+ if ((unsigned)Index < LastIndex)
+ {
+ LastIndex = 0;
+ Iter = Begin();
+ }
+
+ while ((unsigned)Index > LastIndex)
+ {
+ LastIndex++;
+ Iter++;
+ if (Iter.end() == true)
+ {
+ PyErr_SetNone(PyExc_IndexError);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ virtual unsigned Count() = 0;
+ virtual T Begin() = 0;
+
+};
+
+struct PkgListStruct : public IterListStruct<pkgCache::PkgIterator> {
+ unsigned Count() { return Iter.Cache()->HeaderP->PackageCount; }
+ pkgCache::PkgIterator Begin() { return Iter.Cache()->PkgBegin(); }
+
+ PkgListStruct(pkgCache::PkgIterator const &I) { Iter = I; }
+};
+
+struct GrpListStruct : public IterListStruct<pkgCache::GrpIterator> {
+ unsigned Count() { return Iter.Cache()->HeaderP->GroupCount; }
+ pkgCache::GrpIterator Begin() { return Iter.Cache()->GrpBegin(); }
+ GrpListStruct(pkgCache::GrpIterator const &I) { Iter = I; }
+};
+
+struct RDepListStruct
+{
+ pkgCache::DepIterator Iter;
+ pkgCache::DepIterator Start;
+ unsigned long LastIndex;
+ unsigned long Len;
+
+ RDepListStruct(pkgCache::DepIterator const &I) : Iter(I), Start(I),
+ LastIndex(0)
+ {
+ Len = 0;
+ pkgCache::DepIterator D = I;
+ for (; D.end() == false; D++)
+ Len++;
+ }
+ RDepListStruct() {abort();}; // G++ Bug..
+};
+
+static PyObject *CreateProvides(PyObject *Owner,pkgCache::PrvIterator I)
+{
+ PyObject *List = PyList_New(0);
+ for (; I.end() == false; I++)
+ {
+ PyObject *Obj;
+ PyObject *Ver;
+ Ver = CppPyObject_NEW<pkgCache::VerIterator>(Owner,&PyVersion_Type,
+ I.OwnerVer());
+ Obj = Py_BuildValue("ssN",I.ParentPkg().Name(),I.ProvideVersion(),
+ Ver);
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+// Cache Class /*{{{*/
+// ---------------------------------------------------------------------
+
+static const char *cache_update_doc =
+ "update(progress, sources: SourceList, pulse_interval: int) -> bool\n\n"
+ "Update the index files used by the cache. A call to this method\n"
+ "does not affect the current Cache object; instead, a new one\n"
+ "should be created in order to use the changed index files.\n\n"
+ "The parameter 'progress' can be used to specify an\n"
+ "apt.progress.base.AcquireProgress() object , which will report\n"
+ "progress information while the index files are being fetched.\n"
+ "The parameter 'sources', if provided, is an apt_pkg.SourcesList\n"
+ "object listing the remote repositories to be used.\n"
+ "The 'pulse_interval' parameter indicates how long (in microseconds)\n"
+ "to wait between calls to the pulse() method of the 'progress' object.\n"
+ "The default is 500000 microseconds.";
+static PyObject *PkgCacheUpdate(PyObject *Self,PyObject *Args)
+{
+ PyObject *pyFetchProgressInst = 0;
+ PyObject *pySourcesList = 0;
+ int pulseInterval = 0;
+ if (PyArg_ParseTuple(Args, "OO!|i", &pyFetchProgressInst,
+ &PySourceList_Type, &pySourcesList, &pulseInterval) == 0)
+ return 0;
+
+ PyFetchProgress progress;
+ progress.setCallbackInst(pyFetchProgressInst);
+ pkgSourceList *source = GetCpp<pkgSourceList*>(pySourcesList);
+ bool res = ListUpdate(progress, *source, pulseInterval);
+
+ PyObject *PyRes = PyBool_FromLong(res);
+ return HandleErrors(PyRes);
+}
+
+
+static PyMethodDef PkgCacheMethods[] =
+{
+ {"update",PkgCacheUpdate,METH_VARARGS,cache_update_doc},
+ {}
+};
+
+static PyObject *PkgCacheGetGroupCount(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ return MkPyNumber(Cache->HeaderP->GroupCount);
+}
+
+static PyObject *PkgCacheGetGroups(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ return CppPyObject_NEW<GrpListStruct>(Self,&PyGroupList_Type,Cache->GrpBegin());
+}
+
+static PyObject *PkgCacheGetPolicy(PyObject *Self, void*) {
+ PyObject *CacheFilePy = GetOwner<pkgCache*>(Self);
+ pkgCacheFile *CacheF = GetCpp<pkgCacheFile*>(CacheFilePy);
+ pkgDepCache *DepCache = (pkgDepCache *)(*CacheF);
+
+ pkgPolicy *Policy = (pkgPolicy *)&DepCache->GetPolicy();
+ CppPyObject<pkgPolicy*> *PyPolicy =
+ CppPyObject_NEW<pkgPolicy*>(Self,&PyPolicy_Type,Policy);
+ // Policy should not be deleted, it is managed by CacheFile.
+ PyPolicy->NoDelete = true;
+ return PyPolicy;
+}
+
+static PyObject *PkgCacheGetPackages(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ return CppPyObject_NEW<PkgListStruct>(Self,&PyPackageList_Type,Cache->PkgBegin());
+}
+
+static PyObject *PkgCacheGetPackageCount(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ return MkPyNumber((int)Cache->HeaderP->PackageCount);
+}
+
+static PyObject *PkgCacheGetVersionCount(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ return MkPyNumber(Cache->HeaderP->VersionCount);
+}
+static PyObject *PkgCacheGetDependsCount(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ return MkPyNumber(Cache->HeaderP->DependsCount);
+}
+
+static PyObject *PkgCacheGetPackageFileCount(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ return MkPyNumber(Cache->HeaderP->PackageFileCount);
+}
+
+static PyObject *PkgCacheGetVerFileCount(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ return MkPyNumber(Cache->HeaderP->VerFileCount);
+}
+
+static PyObject *PkgCacheGetProvidesCount(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ return MkPyNumber(Cache->HeaderP->ProvidesCount);
+}
+
+static PyObject *PkgCacheGetFileList(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ PyObject *List = PyList_New(0);
+ for (pkgCache::PkgFileIterator I = Cache->FileBegin(); I.end() == false; I++)
+ {
+ PyObject *Obj;
+ Obj = CppPyObject_NEW<pkgCache::PkgFileIterator>(Self,&PyPackageFile_Type,I);
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+static PyObject *PkgCacheGetIsMultiArch(PyObject *Self, void*) {
+ pkgCache *Cache = GetCpp<pkgCache *>(Self);
+ return PyBool_FromLong(Cache->MultiArchCache());
+}
+
+static PyGetSetDef PkgCacheGetSet[] = {
+ {"depends_count",PkgCacheGetDependsCount,0,
+ "The number of apt_pkg.Dependency objects stored in the cache."},
+ {"file_list",PkgCacheGetFileList,0,
+ "A list of apt_pkg.PackageFile objects stored in the cache."},
+ {"group_count",PkgCacheGetGroupCount,0,
+ "The number of apt_pkg.Group objects stored in the cache."},
+ {"groups", PkgCacheGetGroups, 0, "A list of Group objects in the cache"},
+ {"policy", PkgCacheGetPolicy, 0, "The PkgPolicy for the cache"},
+ {"is_multi_arch", PkgCacheGetIsMultiArch, 0,
+ "Whether the cache supports multi-arch."},
+ {"package_count",PkgCacheGetPackageCount,0,
+ "The number of apt_pkg.Package objects stored in the cache."},
+ {"package_file_count",PkgCacheGetPackageFileCount,0,
+ "The number of apt_pkg.PackageFile objects stored in the cache."},
+ {"packages",PkgCacheGetPackages,0,
+ "A list of apt_pkg.Package objects stored in the cache."},
+ {"provides_count",PkgCacheGetProvidesCount,0,
+ "Number of Provides relations described in the cache."},
+ {"ver_file_count",PkgCacheGetVerFileCount,0,
+ "The number of (Version, PackageFile) relations."},
+ {"version_count",PkgCacheGetVersionCount,0,
+ "The number of apt_pkg.Version objects stored in the cache."},
+ {}
+};
+
+// Helper to call FindPkg(name) or FindPkg(name, architecture)
+static pkgCache::PkgIterator CacheFindPkg(PyObject *self, PyObject *arg)
+{
+ const char *name;
+ const char *architecture;
+ pkgCache *cache = GetCpp<pkgCache *>(self);
+
+ name = PyObject_AsString(arg);
+
+ if (name != NULL)
+ return cache->FindPkg(name);
+
+ PyErr_Clear();
+
+ if (PyArg_ParseTuple(arg, "ss", &name, &architecture) == 0) {
+ PyErr_Clear();
+ PyErr_Format(PyExc_TypeError, "Expected a string or a pair of strings");
+ return pkgCache::PkgIterator();
+ }
+
+ return cache->FindPkg(name, architecture);
+}
+
+// Map access, operator []
+static PyObject *CacheMapOp(PyObject *Self,PyObject *Arg)
+{
+ pkgCache::PkgIterator Pkg = CacheFindPkg(Self, Arg);
+ if (Pkg.end() == true)
+ {
+ if (!PyErr_Occurred())
+ PyErr_SetObject(PyExc_KeyError,Arg);
+ return 0;
+ }
+
+ return CppPyObject_NEW<pkgCache::PkgIterator>(Self,&PyPackage_Type,Pkg);
+}
+
+// Check whether the cache contains a package with a given name.
+static int CacheContains(PyObject *Self,PyObject *Arg)
+{
+ bool res = (CacheFindPkg(Self, Arg).end() == false);
+ PyErr_Clear();
+ return res;
+}
+
+static PyObject *PkgCacheNew(PyTypeObject *type,PyObject *Args,PyObject *kwds)
+{
+ PyObject *pyCallbackInst = 0;
+ char *kwlist[] = {"progress", 0};
+
+ if (PyArg_ParseTupleAndKeywords(Args, kwds, "|O", kwlist,
+ &pyCallbackInst) == 0)
+ return 0;
+
+ if (_system == 0) {
+ PyErr_SetString(PyExc_ValueError,"_system not initialized");
+ return 0;
+ }
+
+ pkgCacheFile *Cache = new pkgCacheFile();
+
+ if (pyCallbackInst == Py_None) {
+ OpProgress Prog;
+ if (Cache->Open(&Prog,false) == false)
+ return HandleErrors();
+ } else if(pyCallbackInst != 0) {
+ // sanity check for the progress object, see #497049
+ if (PyObject_HasAttrString(pyCallbackInst, "done") != true) {
+ PyErr_SetString(PyExc_ValueError,
+ "OpProgress object must implement done()");
+ return 0;
+ }
+ if (PyObject_HasAttrString(pyCallbackInst, "update") != true) {
+ PyErr_SetString(PyExc_ValueError,
+ "OpProgress object must implement update()");
+ return 0;
+ }
+ PyOpProgress progress;
+ progress.setCallbackInst(pyCallbackInst);
+ if (Cache->Open(&progress,false) == false)
+ return HandleErrors();
+ }
+ else {
+ OpTextProgress Prog;
+ if (Cache->Open(&Prog,false) == false)
+ return HandleErrors();
+ }
+
+ // ensure that the states are correct (LP: #659438)
+ pkgApplyStatus(*Cache);
+
+ CppPyObject<pkgCacheFile*> *CacheFileObj =
+ CppPyObject_NEW<pkgCacheFile*>(0,&PyCacheFile_Type, Cache);
+
+ CppPyObject<pkgCache *> *CacheObj =
+ CppPyObject_NEW<pkgCache *>(CacheFileObj,type,
+ (pkgCache *)(*Cache));
+
+ // Do not delete the pointer to the pkgCache, it is managed by pkgCacheFile.
+ CacheObj->NoDelete = true;
+ Py_DECREF(CacheFileObj);
+ return CacheObj;
+}
+
+static Py_ssize_t CacheMapLen(PyObject *Self)
+{
+ return GetCpp<pkgCache*>(Self)->HeaderP->PackageCount;
+}
+
+static char *doc_PkgCache = "Cache([progress]) -> Cache() object.\n\n"
+ "The APT cache file contains a hash table mapping names of binary\n"
+ "packages to their metadata. A Cache object is the in-core\n"
+ "representation of the same. It provides access to APT’s idea of the\n"
+ "list of available packages.\n"
+ "The optional parameter *progress* can be used to specify an \n"
+ "apt.progress.base.OpProgress() object (or similar) which reports\n"
+ "progress information while the cache is being opened. If this\n"
+ "parameter is not supplied, the progress will be reported in simple,\n"
+ "human-readable text to standard output. If it is None, no output\n"
+ "will be made.\n\n"
+ "The cache can be used like a mapping from package names to Package\n"
+ "objects (although only getting items is supported). Instead of a name,\n"
+ "a tuple of a name and an architecture may be used.";
+static PySequenceMethods CacheSeq = {0,0,0,0,0,0,0,CacheContains,0,0};
+static PyMappingMethods CacheMap = {CacheMapLen,CacheMapOp,0};
+PyTypeObject PyCache_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Cache", // tp_name
+ sizeof(CppPyObject<pkgCache *>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<pkgCache *>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &CacheSeq, // tp_as_sequence
+ &CacheMap, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE |
+ Py_TPFLAGS_HAVE_GC),
+ doc_PkgCache, // tp_doc
+ CppTraverse<pkgCache *>, // tp_traverse
+ CppClear<pkgCache *>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PkgCacheMethods, // tp_methods
+ 0, // tp_members
+ PkgCacheGetSet, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ PkgCacheNew, // tp_new
+};
+ /*}}}*/
+// PkgCacheFile Class /*{{{*/
+// ---------------------------------------------------------------------
+PyTypeObject PyCacheFile_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "pkgCacheFile", // tp_name
+ sizeof(CppPyObject<pkgCacheFile*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<pkgCacheFile*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flags
+};
+
+// Package List Class /*{{{*/
+// ---------------------------------------------------------------------
+static Py_ssize_t PkgListLen(PyObject *Self)
+{
+ return GetCpp<PkgListStruct>(Self).Iter.Cache()->HeaderP->PackageCount;
+}
+
+static PyObject *PkgListItem(PyObject *iSelf,Py_ssize_t Index)
+{
+ PkgListStruct &Self = GetCpp<PkgListStruct>(iSelf);
+
+ if (!Self.move(Index))
+ return 0;
+ return CppPyObject_NEW<pkgCache::PkgIterator>(GetOwner<PkgListStruct>(iSelf),&PyPackage_Type,
+ Self.Iter);
+}
+
+static PySequenceMethods PkgListSeq =
+{
+ PkgListLen,
+ 0, // concat
+ 0, // repeat
+ PkgListItem,
+ 0, // slice
+ 0, // assign item
+ 0 // assign slice
+};
+
+static const char *packagelist_doc =
+ "A PackageList is an internally used structure to represent\n"
+ "the 'packages' attribute of apt_pkg.Cache objects in a more\n"
+ "efficient manner by creating Package objects only when they\n"
+ "are accessed.";
+
+PyTypeObject PyPackageList_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.PackageList", // tp_name
+ sizeof(CppPyObject<PkgListStruct>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<PkgListStruct>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &PkgListSeq, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
+ packagelist_doc, // tp_doc
+ CppTraverse<PkgListStruct>, // tp_traverse
+ CppClear<PkgListStruct>, // tp_clear
+};
+
+/* The same for groups */
+static Py_ssize_t GrpListLen(PyObject *Self)
+{
+ return GetCpp<GrpListStruct>(Self).Iter.Cache()->HeaderP->GroupCount;
+}
+
+static PyObject *GrpListItem(PyObject *iSelf,Py_ssize_t Index)
+{
+ GrpListStruct &Self = GetCpp<GrpListStruct>(iSelf);
+
+ if (!Self.move(Index))
+ return 0;
+ return CppPyObject_NEW<pkgCache::GrpIterator>(GetOwner<GrpListStruct>(iSelf),&PyGroup_Type,
+ Self.Iter);
+}
+
+static PySequenceMethods GrpListSeq =
+{
+ GrpListLen,
+ 0, // concat
+ 0, // repeat
+ GrpListItem,
+ 0, // slice
+ 0, // assign item
+ 0 // assign slice
+};
+
+static const char *grouplist_doc =
+ "A GroupList is an internally used structure to represent\n"
+ "the 'groups' attribute of apt_pkg.Cache objects in a more\n"
+ "efficient manner by creating Group objects only when they\n"
+ "are accessed.";
+
+PyTypeObject PyGroupList_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.GroupList", // tp_name
+ sizeof(CppPyObject<GrpListStruct>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<GrpListStruct>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &GrpListSeq, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
+ grouplist_doc, // tp_doc
+ CppTraverse<GrpListStruct>, // tp_traverse
+ CppClear<GrpListStruct>, // tp_clear
+};
+
+
+#define Owner (GetOwner<pkgCache::PkgIterator>(Self))
+#define MkGet(PyFunc,Ret) static PyObject *PyFunc(PyObject *Self,void*) \
+{ \
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self); \
+ return Ret; \
+}
+
+MkGet(PackageGetName,CppPyString(Pkg.Name()))
+MkGet(PackageGetArch,CppPyString(Pkg.Arch()))
+MkGet(PackageGetRevDependsList,CppPyObject_NEW<RDepListStruct>(Owner,
+ &PyDependencyList_Type, Pkg.RevDependsList()))
+MkGet(PackageGetProvidesList,CreateProvides(Owner,Pkg.ProvidesList()))
+MkGet(PackageGetSelectedState,MkPyNumber(Pkg->SelectedState))
+MkGet(PackageGetInstState,MkPyNumber(Pkg->InstState))
+MkGet(PackageGetCurrentState,MkPyNumber(Pkg->CurrentState))
+MkGet(PackageGetID,MkPyNumber(Pkg->ID))
+#
+MkGet(PackageGetEssential,PyBool_FromLong((Pkg->Flags & pkgCache::Flag::Essential) != 0))
+MkGet(PackageGetImportant,PyBool_FromLong((Pkg->Flags & pkgCache::Flag::Important) != 0))
+#undef MkGet
+#undef Owner
+
+static const char PackageGetFullName_doc[] =
+ "get_fullname([pretty: bool = False]) -> str\n\n"
+ "Get the full name of the package, including the architecture. If\n"
+ "'pretty' is True, the architecture is omitted for native packages,\n"
+ "that is, and amd64 apt package on an amd64 system would give 'apt'.";
+static PyObject *PackageGetFullName(PyObject *Self,PyObject *Args,PyObject *kwds)
+{
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self);
+ char pretty = 0;
+ char *kwlist[] = {"pretty", 0};
+
+ if (PyArg_ParseTupleAndKeywords(Args, kwds, "|b", kwlist,
+ &pretty) == 0)
+ return 0;
+
+
+ return CppPyString(Pkg.FullName(pretty));
+}
+
+static PyObject *PackageGetVersionList(PyObject *Self,void*)
+{
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::PkgIterator>(Self);
+
+ PyObject *List = PyList_New(0);
+ for (pkgCache::VerIterator I = Pkg.VersionList(); I.end() == false; I++)
+ {
+ PyObject *Obj;
+ Obj = CppPyObject_NEW<pkgCache::VerIterator>(Owner,&PyVersion_Type,I);
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+static PyObject *PackageGetHasVersions(PyObject *Self,void*)
+{
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self);
+ return PyBool_FromLong(Pkg.VersionList().end() == false);
+}
+
+static PyObject *PackageGetHasProvides(PyObject *Self,void*)
+{
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self);
+ return PyBool_FromLong(Pkg.ProvidesList().end() == false);
+}
+
+static PyObject *PackageGetCurrentVer(PyObject *Self,void*)
+{
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::PkgIterator>(Self);
+ if (Pkg->CurrentVer == 0)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ return CppPyObject_NEW<pkgCache::VerIterator>(Owner,&PyVersion_Type,
+ Pkg.CurrentVer());
+}
+
+
+static PyMethodDef PackageMethods[] =
+{
+ {"get_fullname",(PyCFunction)PackageGetFullName,METH_VARARGS|METH_KEYWORDS,
+ PackageGetFullName_doc},
+ {}
+};
+
+static PyGetSetDef PackageGetSet[] = {
+ {"name",PackageGetName,0,
+ "The name of the package."},
+ {"architecture",PackageGetArch,0, "The architecture of the package."},
+ {"rev_depends_list",PackageGetRevDependsList,0,
+ "An apt_pkg.DependencyList object of all reverse dependencies."},
+ {"provides_list",PackageGetProvidesList,0,
+ "A list of all packages providing this package. The list contains\n"
+ "tuples in the format (providesname, providesver, version)\n"
+ "where 'version' is an apt_pkg.Version object."},
+ {"selected_state",PackageGetSelectedState,0,
+ "The state of the selection, which can be compared against the constants\n"
+ "SELSTATE_DEINSTALL, SELSTATE_HOLD, SELSTATE_INSTALL, SELSTATE_PURGE,\n"
+ "SELSTATE_UNKNOWN of the apt_pkg module."},
+ {"inst_state",PackageGetInstState,0,
+ "The state of the install, which be compared against the constants\n"
+ "INSTSTATE_HOLD, INSTSTATE_HOLD_REINSTREQ, INSTSTATE_OK,\n"
+ "INSTSTATE_REINSTREQ of the apt_pkg module."},
+ {"current_state",PackageGetCurrentState,0,
+ "The current state, which can be compared against the constants\n"
+ "CURSTATE_CONFIG_FILES, CURSTATE_HALF_CONFIGURED,\n"
+ "CURSTATE_HALF_INSTALLED, CURSTATE_INSTALLED, CURSTATE_NOT_INSTALLED,\n"
+ "CURSTATE_UNPACKED of the apt_pkg module."},
+ {"id",PackageGetID,0,
+ "The numeric ID of the package"},
+ {"essential",PackageGetEssential,0,
+ "Boolean value determining whether the package is essential."},
+ {"important",PackageGetImportant,0,
+ "Boolean value determining whether the package has the 'important'\n"
+ "flag set ('Important: yes' in the Packages file). No longer used."},
+ {"version_list",PackageGetVersionList,0,
+ "A list of all apt_pkg.Version objects for this package."},
+ {"current_ver",PackageGetCurrentVer,0,
+ "The version of the package currently installed or None."},
+ {"has_versions",PackageGetHasVersions,0,
+ "Whether the package has at least one version in the cache."},
+ {"has_provides",PackageGetHasProvides,0,
+ "Whether the package is provided by at least one other package."},
+ {}
+};
+
+static PyObject *PackageRepr(PyObject *Self)
+{
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(Self);
+ return PyString_FromFormat("<%s object: name:'%s' id:%u>", Self->ob_type->tp_name,
+ Pkg.Name(), Pkg->ID);
+}
+
+static const char *package_doc =
+ "Represent a package. A package is uniquely identified by its name\n"
+ "and each package can have zero or more versions which can be\n"
+ "accessed via the version_list property. Packages can be installed\n"
+ "and removed by apt_pkg.DepCache.";
+
+PyTypeObject PyPackage_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Package", // tp_name
+ sizeof(CppPyObject<pkgCache::PkgIterator>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgCache::PkgIterator>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ PackageRepr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
+ package_doc, // tp_doc
+ CppTraverse<pkgCache::PkgIterator>, // tp_traverse
+ CppClear<pkgCache::PkgIterator>,// tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PackageMethods, // tp_methods
+ 0, // tp_members
+ PackageGetSet, // tp_getset
+};
+
+#define Description_MkGet(PyFunc,Ret) static PyObject \
+ *PyFunc(PyObject *Self,void*) { \
+ pkgCache::DescIterator &Desc = GetCpp<pkgCache::DescIterator>(Self); \
+ return Ret; }
+
+Description_MkGet(DescriptionGetLanguageCode,
+ CppPyString(Desc.LanguageCode()))
+Description_MkGet(DescriptionGetMd5,CppPyString(Desc.md5()))
+#undef Description_MkGet
+
+static PyObject *DescriptionGetFileList(PyObject *Self,void*)
+{
+ pkgCache::DescIterator &Desc = GetCpp<pkgCache::DescIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::DescIterator>(Self);
+
+ /* The second value in the tuple is the index of the VF item. If the
+ user wants to request a lookup then that number will be used.
+ Maybe later it can become an object. */
+ PyObject *List = PyList_New(0);
+ for (pkgCache::DescFileIterator I = Desc.FileList(); I.end() == false; I++)
+ {
+ PyObject *DescFile;
+ PyObject *Obj;
+ DescFile = CppPyObject_NEW<pkgCache::PkgFileIterator>(Owner,&PyPackageFile_Type,I.File());
+ Obj = Py_BuildValue("NN",DescFile,MkPyNumber(I.Index()));
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+static PyGetSetDef DescriptionGetSet[] = {
+ {"language_code",DescriptionGetLanguageCode,0,
+ "The language code of the description. Empty string for untranslated\n"
+ "descriptions."},
+ {"md5",DescriptionGetMd5,0,
+ "The MD5 hash of the description."},
+ {"file_list",DescriptionGetFileList,0,
+ "A list of all apt_pkg.PackageFile objects related to this description."},
+ {}
+};
+
+static PyObject *DescriptionRepr(PyObject *Self)
+{
+ pkgCache::DescIterator &Desc = GetCpp<pkgCache::DescIterator>(Self);
+ return PyString_FromFormat("<%s object: language_code:'%s' md5:'%s' ",
+ Self->ob_type->tp_name, Desc.LanguageCode(),
+ Desc.md5());
+}
+
+static const char *description_doc =
+ "Represent a package description and some attributes. Needed for\n"
+ "things like translated descriptions.";
+
+PyTypeObject PyDescription_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Description", // tp_name
+ sizeof(CppPyObject<pkgCache::DescIterator>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgCache::DescIterator>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ DescriptionRepr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
+ description_doc, // tp_doc
+ CppTraverse<pkgCache::DescIterator>, // tp_traverse
+ CppClear<pkgCache::DescIterator>,// tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ DescriptionGetSet, // tp_getset
+};
+ /*}}}*/
+// Version Class /*{{{*/
+// ---------------------------------------------------------------------
+
+/* This is the simple depends result, the elements are split like
+ ParseDepends does */
+static PyObject *MakeDepends(PyObject *Owner,pkgCache::VerIterator &Ver,
+ bool AsObj)
+{
+ PyObject *Dict = PyDict_New();
+ PyObject *LastDep = 0;
+ unsigned LastDepType = 0;
+ for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;)
+ {
+ pkgCache::DepIterator Start;
+ pkgCache::DepIterator End;
+ D.GlobOr(Start,End);
+
+ // Switch/create a new dict entry
+ if (LastDepType != Start->Type || LastDep != 0)
+ {
+ PyObject *Dep = CppPyString(UntranslatedDepTypes[Start->Type]);
+ LastDepType = Start->Type;
+ LastDep = PyDict_GetItem(Dict,Dep);
+ if (LastDep == 0)
+ {
+ LastDep = PyList_New(0);
+ PyDict_SetItem(Dict,Dep,LastDep);
+ Py_DECREF(LastDep);
+ }
+ Py_DECREF(Dep);
+ }
+
+ PyObject *OrGroup = PyList_New(0);
+ while (1)
+ {
+ PyObject *Obj;
+ if (AsObj == true)
+ Obj = CppPyObject_NEW<pkgCache::DepIterator>(Owner,&PyDependency_Type,
+ Start);
+ else
+ {
+ if (Start->Version == 0)
+ Obj = Py_BuildValue("sss",
+ Start.TargetPkg().Name(),
+ "",
+ Start.CompType());
+ else
+ Obj = Py_BuildValue("sss",
+ Start.TargetPkg().Name(),
+ Start.TargetVer(),
+ Start.CompType());
+ }
+ PyList_Append(OrGroup,Obj);
+ Py_DECREF(Obj);
+
+ if (Start == End)
+ break;
+ Start++;
+ }
+
+ PyList_Append(LastDep,OrGroup);
+ Py_DECREF(OrGroup);
+ }
+
+ return Dict;
+}
+
+static inline pkgCache::VerIterator Version_GetVer(PyObject *Self) {
+ return GetCpp<pkgCache::VerIterator>(Self);
+}
+
+// Version attributes.
+static PyObject *VersionGetVerStr(PyObject *Self, void*) {
+ return CppPyString(Version_GetVer(Self).VerStr());
+}
+static PyObject *VersionGetSection(PyObject *Self, void*) {
+ return CppPyString(Version_GetVer(Self).Section());
+}
+static PyObject *VersionGetArch(PyObject *Self, void*) {
+ return CppPyString(Version_GetVer(Self).Arch());
+}
+static PyObject *VersionGetFileList(PyObject *Self, void*) {
+ pkgCache::VerIterator &Ver = GetCpp<pkgCache::VerIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::VerIterator>(Self);
+ PyObject *List = PyList_New(0);
+ for (pkgCache::VerFileIterator I = Ver.FileList(); I.end() == false; I++)
+ {
+ PyObject *PkgFile;
+ PyObject *Obj;
+ PkgFile = CppPyObject_NEW<pkgCache::PkgFileIterator>(Owner,&PyPackageFile_Type,I.File());
+ Obj = Py_BuildValue("NN",PkgFile,MkPyNumber(I.Index()));
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+static PyObject *VersionGetDependsListStr(PyObject *Self, void*) {
+ pkgCache::VerIterator &Ver = GetCpp<pkgCache::VerIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::VerIterator>(Self);
+ return MakeDepends(Owner,Ver,false);
+}
+static PyObject *VersionGetDependsList(PyObject *Self, void*) {
+ pkgCache::VerIterator &Ver = GetCpp<pkgCache::VerIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::VerIterator>(Self);
+ return MakeDepends(Owner,Ver,true);
+}
+static PyObject *VersionGetParentPkg(PyObject *Self, void*) {
+ PyObject *Owner = GetOwner<pkgCache::VerIterator>(Self);
+ return CppPyObject_NEW<pkgCache::PkgIterator>(Owner,&PyPackage_Type,
+ Version_GetVer(Self).ParentPkg());
+}
+static PyObject *VersionGetProvidesList(PyObject *Self, void*) {
+ PyObject *Owner = GetOwner<pkgCache::VerIterator>(Self);
+ return CreateProvides(Owner,Version_GetVer(Self).ProvidesList());
+}
+static PyObject *VersionGetSize(PyObject *Self, void*) {
+ return MkPyNumber(Version_GetVer(Self)->Size);
+}
+static PyObject *VersionGetInstalledSize(PyObject *Self, void*) {
+ return MkPyNumber(Version_GetVer(Self)->InstalledSize);
+}
+static PyObject *VersionGetHash(PyObject *Self, void*) {
+ return MkPyNumber(Version_GetVer(Self)->Hash);
+}
+static PyObject *VersionGetID(PyObject *Self, void*) {
+ return MkPyNumber(Version_GetVer(Self)->ID);
+}
+static PyObject *VersionGetPriority(PyObject *Self, void*) {
+ return MkPyNumber(Version_GetVer(Self)->Priority);
+}
+static PyObject *VersionGetPriorityStr(PyObject *Self, void*) {
+ return CppPyString(Version_GetVer(Self).PriorityType());
+}
+static PyObject *VersionGetDownloadable(PyObject *Self, void*) {
+ return PyBool_FromLong(Version_GetVer(Self).Downloadable());
+}
+static PyObject *VersionGetTranslatedDescription(PyObject *Self, void*) {
+ pkgCache::VerIterator &Ver = GetCpp<pkgCache::VerIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::VerIterator>(Self);
+ return CppPyObject_NEW<pkgCache::DescIterator>(Owner,
+ &PyDescription_Type,
+ Ver.TranslatedDescription());
+}
+
+static PyObject *VersionGetIsSecurityUpdate(PyObject *Self, void*) {
+ return PyBool_FromLong(Version_GetVer(Self).IsSecurityUpdate());
+}
+
+static PyObject *VersionGetMultiArch(PyObject *Self, void*)
+{
+ return MkPyNumber(Version_GetVer(Self)->MultiArch);
+}
+
+#if 0 // FIXME: enable once pkgSourceList is stored somewhere
+static PyObject *VersionGetIsTrusted(PyObject *Self, void*) {
+ else if (strcmp("IsTrusted", Name) == 0)
+ {
+ pkgSourceList Sources;
+ Sources.ReadMainList();
+ for(pkgCache::VerFileIterator i = Ver.FileList(); !i.end(); i++)
+ {
+ pkgIndexFile *index;
+ if(Sources.FindIndex(i.File(), index) && !index->IsTrusted())
+ Py_RETURN_FALSE;
+ }
+ Py_RETURN_TRUE;
+ }
+}
+#endif
+
+#define NOTNULL(x) (x ? x : "")
+
+static PyObject *VersionRepr(PyObject *Self)
+{
+ pkgCache::VerIterator &Ver = GetCpp<pkgCache::VerIterator>(Self);
+ return PyString_FromFormat("<%s object: Pkg:'%s' Ver:'%s' Section:'%s' "
+ " Arch:'%s' Size:%lu ISize:%lu Hash:%u ID:%u "
+ "Priority:%u>", Self->ob_type->tp_name,
+ Ver.ParentPkg().Name(), Ver.VerStr(),
+ NOTNULL(Ver.Section()), NOTNULL(Ver.Arch()),
+ (unsigned long)Ver->Size,
+ (unsigned long)Ver->InstalledSize,
+ Ver->Hash, Ver->ID, Ver->Priority);
+}
+#undef NOTNULL
+
+static PyObject *version_richcompare(PyObject *obj1, PyObject *obj2, int op)
+{
+ if (!PyVersion_Check(obj2))
+ return Py_INCREF(Py_NotImplemented), Py_NotImplemented;
+
+ const pkgCache::VerIterator &a = GetCpp<pkgCache::VerIterator>(obj1);
+ const pkgCache::VerIterator &b = GetCpp<pkgCache::VerIterator>(obj2);
+ const int comparison = _system->VS->CmpVersion(a.VerStr(), b.VerStr());
+ switch (op) {
+ case Py_LT: return PyBool_FromLong(comparison < 0);
+ case Py_LE: return PyBool_FromLong(comparison <= 0);
+ case Py_EQ: return PyBool_FromLong(comparison == 0);
+ case Py_NE: return PyBool_FromLong(comparison != 0);
+ case Py_GE: return PyBool_FromLong(comparison >= 0);
+ case Py_GT: return PyBool_FromLong(comparison > 0);
+ default: return NULL; // should not happen.
+ }
+}
+
+static PyGetSetDef VersionGetSet[] = {
+ {"arch",VersionGetArch,0,
+ "The architecture of this specific version of the package."},
+ {"depends_list",VersionGetDependsList,0,
+ "A dictionary mapping dependency types to lists (A) of lists (B) of\n"
+ "apt_pkg.Dependency objects. The lists (B) represent or dependencies\n"
+ "like 'a || b'."},
+ {"depends_list_str",VersionGetDependsListStr,0,
+ "Same as depends_list, except that the apt_pkg.Dependency objects\n"
+ "are 3-tuples of the form (name, version, operator); where operator\n"
+ "is one of '<', '<=', '=', '>=', '>'."},
+ {"downloadable",VersionGetDownloadable,0,
+ "Whether the version can be downloaded."},
+ {"file_list",VersionGetFileList,0,
+ "A list of tuples (packagefile: apt_pkg.PackageFile, index: int) for the\n"
+ "PackageFile objects related to this package. The index can be used\n"
+ "to retrieve the record of this package version."},
+ {"hash",VersionGetHash,0,
+ "The numeric hash of the version used in the internal storage."},
+ {"id",VersionGetID,0,
+ "The numeric ID of the package."},
+ {"installed_size",VersionGetInstalledSize,0,
+ "The installed size of this package version."},
+ {"multi_arch",VersionGetMultiArch,0,
+ "Multi-arch state of this package, as an integer. See\n"
+ "the various MULTI_ARCH_* members."},
+ {"parent_pkg",VersionGetParentPkg,0,
+ "The parent package of this version."},
+ {"priority",VersionGetPriority,0,
+ "The priority of the package as an integer, which can be compared to\n"
+ "the constants PRI_EXTRA, PRI_IMPORTANT, PRI_OPTIONAL, PRI_REQUIRED,\n"
+ "PRI_STANDARD of the apt_pkg module."},
+ {"priority_str",VersionGetPriorityStr,0,
+ "The priority of the package, as a string."},
+ {"provides_list",VersionGetProvidesList,0,
+ "A list of all packages provided by this version. The list contains\n"
+ "tuples in the format (providesname, providesver, version)\n"
+ "where 'version' is an apt_pkg.Version object."},
+ {"section",VersionGetSection,0,
+ "The section of this package version."},
+ {"size",VersionGetSize,0,
+ "The size of the package file."},
+ {"translated_description",VersionGetTranslatedDescription,0,
+ "An apt_pkg.Description object for the translated description if\n"
+ "available or the untranslated fallback."},
+ {"is_security_update",VersionGetIsSecurityUpdate,0,
+ "Whether this version is a security update."},
+ {"ver_str",VersionGetVerStr,0,
+ "The version string."},
+ {}
+};
+
+PyTypeObject PyVersion_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Version", // tp_name
+ sizeof(CppPyObject<pkgCache::VerIterator>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgCache::VerIterator>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ VersionRepr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
+ "Version Object", // tp_doc
+ CppTraverse<pkgCache::VerIterator>, // tp_traverse
+ CppClear<pkgCache::VerIterator>,// tp_clear
+ version_richcompare, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ VersionGetSet, // tp_getset
+};
+
+ /*}}}*/
+
+// PackageFile Class /*{{{*/
+// ---------------------------------------------------------------------
+static PyObject *PackageFile_GetFileName(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return CppPyPath(File.FileName());
+}
+
+static PyObject *PackageFile_GetArchive(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return CppPyString(File.Archive());
+}
+
+static PyObject *PackageFile_GetComponent(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return CppPyString(File.Component());
+}
+
+static PyObject *PackageFile_GetVersion(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return CppPyString(File.Version());
+}
+
+static PyObject *PackageFile_GetOrigin(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return CppPyString(File.Origin());
+}
+
+static PyObject *PackageFile_GetLabel(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return CppPyString(File.Label());
+}
+
+static PyObject *PackageFile_GetArchitecture(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return CppPyString(File.Architecture());
+}
+
+static PyObject *PackageFile_GetCodename(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return CppPyString(File.Codename());
+}
+
+static PyObject *PackageFile_GetSite(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return CppPyString(File.Site());
+}
+
+static PyObject *PackageFile_GetIndexType(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return CppPyString(File.IndexType());
+}
+static PyObject *PackageFile_GetSize(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return MkPyNumber(File->Size);
+}
+
+static PyObject *PackageFile_GetNotSource(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return PyBool_FromLong((File->Flags & pkgCache::Flag::NotSource) != 0);
+}
+static PyObject *PackageFile_GetNotAutomatic(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return PyBool_FromLong((File->Flags & pkgCache::Flag::NotAutomatic) != 0);
+}
+
+static PyObject *PackageFile_GetID(PyObject *Self,void*)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+ return MkPyNumber(File->ID);
+}
+
+#define S(s) (s == NULL ? "" : s)
+static PyObject *PackageFileRepr(PyObject *Self)
+{
+ pkgCache::PkgFileIterator &File = GetCpp<pkgCache::PkgFileIterator>(Self);
+
+ return PyString_FromFormat("<%s object: filename:'%s'"
+ " a=%s,c=%s,v=%s,o=%s,l=%s arch='%s' site='%s'"
+ " IndexType='%s' Size=%lu ID:%u>",
+ Self->ob_type->tp_name, File.FileName(),
+ S(File.Archive()),
+ S(File.Component()),S(File.Version()),
+ S(File.Origin()),S(File.Label()),
+ S(File.Architecture()),S(File.Site()),
+ S(File.IndexType()),File->Size,File->ID);
+}
+#undef S
+
+static PyGetSetDef PackageFileGetSet[] = {
+ {"architecture",PackageFile_GetArchitecture,0,
+ "The architecture of the package file. Unused, empty string nowadays."},
+ {"archive",PackageFile_GetArchive,0,
+ "The archive of the package file (i.e. 'Suite' in the Release file)."},
+ {"component",PackageFile_GetComponent,0,
+ "The component of this package file (e.g. 'main')."},
+ {"codename",PackageFile_GetCodename,0,
+ "The codename of this package file (e.g. squeeze-updates)."},
+ {"filename",PackageFile_GetFileName,0,
+ "The path to the file."},
+ {"id",PackageFile_GetID,0,
+ "The numeric ID of this PackageFile object."},
+ {"index_type",PackageFile_GetIndexType,0,
+ "A string describing the type of index. Known values are\n"
+ "'Debian Package Index', 'Debian Translation Index', and\n"
+ "'Debian dpkg status file'."},
+ {"label",PackageFile_GetLabel,0,
+ "The label set in the release file (e.g. 'Debian')."},
+ {"not_automatic",PackageFile_GetNotAutomatic,0,
+ "Whether the NotAutomatic flag is set in the Release file."},
+ {"not_source",PackageFile_GetNotSource,0,
+ "Whether this package file lacks an active (sources.list) source;"
+ "packages listed in such a file cannot be downloaded."},
+ {"origin",PackageFile_GetOrigin,0,
+ "The origin set in the release file."},
+ {"site",PackageFile_GetSite,0,
+ "The hostname of the location this file comes from."},
+ {"size",PackageFile_GetSize,0,
+ "The size of the file."},
+ {"version",PackageFile_GetVersion,0,
+ "The version set in the release file (e.g. '5.0.X' for lenny, where X\n"
+ "is a point release)."},
+ {}
+};
+
+static const char *packagefile_doc =
+ "A package file is an index file stored in the cache with some\n"
+ "additional pieces of information.";
+
+PyTypeObject PyPackageFile_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.PackageFile", // tp_name
+ sizeof(CppPyObject<pkgCache::PkgFileIterator>), // tp_basicsize
+ 0, // tp_itemsize
+ CppDealloc<pkgCache::PkgFileIterator>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ PackageFileRepr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
+ packagefile_doc, // tp_doc
+ CppTraverse<pkgCache::PkgFileIterator>, // tp_traverse
+ CppClear<pkgCache::PkgFileIterator>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ PackageFileGetSet, // tp_getset
+};
+
+// depends class
+static PyObject *DependencyRepr(PyObject *Self)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+
+ return PyString_FromFormat("<%s object: pkg:'%s' ver:'%s' comp:'%s'>",
+ Self->ob_type->tp_name, Dep.TargetPkg().Name(),
+ (Dep.TargetVer() == 0 ? "" : Dep.TargetVer()),
+ Dep.CompType());
+}
+
+static PyObject *DepAllTargets(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::DepIterator>(Self);
+
+ std::unique_ptr<pkgCache::Version *[]> Vers(Dep.AllTargets());
+ PyObject *List = PyList_New(0);
+ for (pkgCache::Version **I = Vers.get(); *I != 0; I++)
+ {
+ PyObject *Obj;
+ Obj = CppPyObject_NEW<pkgCache::VerIterator>(Owner,&PyVersion_Type,
+ pkgCache::VerIterator(*Dep.Cache(),*I));
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+static PyMethodDef DependencyMethods[] =
+{
+ {"all_targets",DepAllTargets,METH_VARARGS,
+ "all_targets() -> list\n\n"
+ "A list of all possible apt_pkg.Version objects which satisfy this\n"
+ "dependency."},
+ {}
+};
+
+// Dependency Class /*{{{*/
+// ---------------------------------------------------------------------
+
+static PyObject *DependencyGetTargetVer(PyObject *Self,void*)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ if (Dep->Version == 0)
+ return CppPyString("");
+ return CppPyString(Dep.TargetVer());
+}
+
+static PyObject *DependencyGetTargetPkg(PyObject *Self,void*)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::DepIterator>(Self);
+ return CppPyObject_NEW<pkgCache::PkgIterator>(Owner,&PyPackage_Type,
+ Dep.TargetPkg());
+}
+
+static PyObject *DependencyGetParentVer(PyObject *Self,void*)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::DepIterator>(Self);
+ return CppPyObject_NEW<pkgCache::VerIterator>(Owner,&PyVersion_Type,
+ Dep.ParentVer());
+}
+
+static PyObject *DependencyGetParentPkg(PyObject *Self,void*)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ PyObject *Owner = GetOwner<pkgCache::DepIterator>(Self);
+ return CppPyObject_NEW<pkgCache::PkgIterator>(Owner,&PyPackage_Type,
+ Dep.ParentPkg());
+}
+
+static PyObject *DependencyGetCompType(PyObject *Self,void*)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ return CppPyString(Dep.CompType());
+}
+
+static PyObject *DependencyGetCompTypeDeb(PyObject *Self,void*)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ return CppPyString(pkgCache::CompTypeDeb(Dep->CompareOp));
+}
+
+static PyObject *DependencyGetDepType(PyObject *Self,void*)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ return CppPyString(Dep.DepType());
+}
+
+static PyObject *DependencyGetDepTypeUntranslated(PyObject *Self,void*)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ return CppPyString(UntranslatedDepTypes[Dep->Type]);
+}
+
+static PyObject *DependencyGetDepTypeEnum(PyObject *Self,void*)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ return MkPyNumber(Dep->Type);
+}
+
+static PyObject *DependencyGetID(PyObject *Self,void*)
+{
+ pkgCache::DepIterator &Dep = GetCpp<pkgCache::DepIterator>(Self);
+ return MkPyNumber(Dep->ID);
+}
+
+static PyGetSetDef DependencyGetSet[] = {
+ {"comp_type",DependencyGetCompType,0,
+ "The type of comparison in mathematical notation, as a string, namely one "
+ "of:\n"
+ "'<', '<=', '=', '!=', '>=', '>', ''.\n"
+ "The empty string will be returned in case of an unversioned dependency."},
+ {"comp_type_deb",DependencyGetCompTypeDeb,0,
+ "The type of comparison in Debian notation, as a string, namely one of:\n"
+ "'<<', '<=', '=', '!=', '>=', '>>', ''.\n"
+ "The empty string will be returned in case of an unversioned dependency.\n"
+ "For details see the Debian Policy Manual on the syntax of relationship "
+ "fields:\n"
+ "https://www.debian.org/doc/debian-policy/ch-relationships.html#s-depsyntax"},
+ {"dep_type",DependencyGetDepType,0,
+ "The type of the dependency; may be translated"},
+ {"dep_type_untranslated",DependencyGetDepTypeUntranslated,0,
+ "Same as dep_type, but guaranteed to be untranslated."},
+ {"dep_type_enum",DependencyGetDepTypeEnum,0,
+ "Same as dep_type, but with a numeric value instead of a string. Can\n"
+ "be compared against the TYPE_ constants defined in this class."},
+ {"id",DependencyGetID,0,
+ "The numeric ID of this dependency object."},
+ {"parent_pkg",DependencyGetParentPkg,0,
+ "The apt_pkg.Package object of the package which depends."},
+ {"parent_ver",DependencyGetParentVer,0,
+ "The apt_pkg.Version object of the package which depends."},
+ {"target_pkg",DependencyGetTargetPkg,0,
+ "The apt_pkg.Package object of the package depended upon"},
+ {"target_ver",DependencyGetTargetVer,0,
+ "The version of the package depended upon as a string"},
+ {}
+};
+
+static const char *dependency_doc =
+ "Represent a dependency from one package version to a package,\n"
+ "and (optionally) a version relation (e.g. >= 1). Dependency\n"
+ "objects also provide useful functions like all_targets()\n"
+ "for selecting packages to satisfy the dependency.";
+
+PyTypeObject PyDependency_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Dependency", // tp_name
+ sizeof(CppPyObject<pkgCache::DepIterator>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgCache::DepIterator>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ DependencyRepr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
+ dependency_doc, // tp_doc
+ CppTraverse<pkgCache::DepIterator>, // tp_traverse
+ CppClear<pkgCache::DepIterator>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ DependencyMethods, // tp_methods
+ 0, // tp_members
+ DependencyGetSet, // tp_getset
+};
+
+ /*}}}*/
+ /*}}}*/
+// Reverse Dependency List Class /*{{{*/
+// ---------------------------------------------------------------------
+static Py_ssize_t RDepListLen(PyObject *Self)
+{
+ return GetCpp<RDepListStruct>(Self).Len;
+}
+
+static PyObject *RDepListItem(PyObject *iSelf,Py_ssize_t Index)
+{
+ RDepListStruct &Self = GetCpp<RDepListStruct>(iSelf);
+ if (Index < 0 || (unsigned)Index >= Self.Len)
+ {
+ PyErr_SetNone(PyExc_IndexError);
+ return 0;
+ }
+
+ if ((unsigned)Index < Self.LastIndex)
+ {
+ Self.LastIndex = 0;
+ Self.Iter = Self.Start;
+ }
+
+ while ((unsigned)Index > Self.LastIndex)
+ {
+ Self.LastIndex++;
+ Self.Iter++;
+ if (Self.Iter.end() == true)
+ {
+ PyErr_SetNone(PyExc_IndexError);
+ return 0;
+ }
+ }
+
+ return CppPyObject_NEW<pkgCache::DepIterator>(GetOwner<RDepListStruct>(iSelf),
+ &PyDependency_Type,Self.Iter);
+}
+
+static PySequenceMethods RDepListSeq =
+{
+ RDepListLen,
+ 0, // concat
+ 0, // repeat
+ RDepListItem,
+ 0, // slice
+ 0, // assign item
+ 0 // assign slice
+};
+
+static const char *dependencylist_doc =
+ "A simple list-like type for representing multiple dependency\n"
+ "objects in an efficient manner; without having to generate\n"
+ "all Dependency objects in advance.";
+PyTypeObject PyDependencyList_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.DependencyList", // tp_name
+ sizeof(CppPyObject<RDepListStruct>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<RDepListStruct>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &RDepListSeq, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
+ dependencylist_doc, // tp_doc
+ CppTraverse<RDepListStruct>, // tp_traverse
+ CppClear<RDepListStruct>, // tp_clear
+};
+
+ /*}}}*/
+
+
diff --git a/python/cachegroup.cc b/python/cachegroup.cc
new file mode 100644
index 0000000..4fc6c37
--- /dev/null
+++ b/python/cachegroup.cc
@@ -0,0 +1,188 @@
+/*
+ * cachegroup.cc - Wrapper around pkgCache::GrpIterator
+ *
+ * Copyright 2011 Julian Andres Klode <jak@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+#include <Python.h>
+#include "apt_pkgmodule.h"
+#include "generic.h"
+#include <apt-pkg/pkgcache.h>
+
+struct PyGroup : CppPyObject<pkgCache::GrpIterator> {
+ pkgCache::PkgIterator current;
+ int nextIndex;
+};
+
+static PyObject *group_new(PyTypeObject *type,PyObject *args,
+ PyObject *kwds)
+{
+ PyObject *pyCache;
+ char *name;
+ char *kwlist[] = {"cache", "name", NULL};
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O!s", kwlist,
+ &PyCache_Type, &pyCache,
+ &name) == 0)
+ return 0;
+
+ pkgCache *cache = GetCpp<pkgCache *>(pyCache);
+
+ pkgCache::GrpIterator grp = cache->FindGrp(name);
+
+ if (!grp.end()) {
+ return PyGroup_FromCpp(grp, true, pyCache);
+ } else {
+ PyErr_SetString(PyExc_KeyError, name);
+ return NULL;
+ }
+}
+
+static const char group_find_package_doc[] =
+ "find_package(architecture: str) -> Package\n\n"
+ "Return a package for the given architecture, or None if none exists";
+static PyObject *group_find_package(PyObject *self,PyObject *args)
+{
+ pkgCache::GrpIterator grp = GetCpp<pkgCache::GrpIterator>(self);
+ PyObject *owner = GetOwner<pkgCache::GrpIterator>(self);
+
+ char *architecture;
+ if (PyArg_ParseTuple(args, "s", &architecture) == 0)
+ return 0;
+
+ pkgCache::PkgIterator pkg = grp.FindPkg(architecture);
+
+ if (pkg.end()) {
+ Py_RETURN_NONE;
+ } else {
+ return PyPackage_FromCpp(pkg, true, owner ? owner : self);
+ }
+}
+
+static const char group_find_preferred_package_doc[] =
+ "find_preferred_package(prefer_non_virtual: bool = True) -> Package\n\n"
+ "Return a package for the best architecture, either the native one\n"
+ "or the first found one. If none exists, return None. If non_virtual\n"
+ "is True, prefer non-virtual packages over virtual ones.";
+static PyObject *group_find_preferred_package(PyObject *self,PyObject *args,
+ PyObject *kwds)
+{
+ pkgCache::GrpIterator grp = GetCpp<pkgCache::GrpIterator>(self);
+ PyObject *owner = GetOwner<pkgCache::GrpIterator>(self);
+ char nonvirtual = 1;
+ char *kwlist[] = {"prefer_non_virtual", NULL};
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "|b", kwlist, &nonvirtual) == 0)
+ return 0;
+ pkgCache::PkgIterator pkg = grp.FindPreferredPkg(nonvirtual);
+
+ if (pkg.end()) {
+ Py_RETURN_NONE;
+ } else {
+ return PyPackage_FromCpp(pkg, true, owner);
+ }
+}
+
+static PyMethodDef group_methods[] = {
+ {"find_package",group_find_package,METH_VARARGS,group_find_package_doc},
+ {"find_preferred_package",(PyCFunction) group_find_preferred_package,
+ METH_VARARGS|METH_KEYWORDS,group_find_preferred_package_doc},
+ {}
+};
+
+static PyObject *group_seq_item(PyObject *pySelf,Py_ssize_t index)
+{
+ PyGroup *self = static_cast<PyGroup *>(pySelf);
+ pkgCache::GrpIterator grp = GetCpp<pkgCache::GrpIterator>(self);
+ PyObject *owner = GetOwner<pkgCache::GrpIterator>(self);
+
+ if (self->nextIndex > index || self->nextIndex == 0) {
+ self->nextIndex = 1;
+ new (&self->current) pkgCache::PkgIterator(grp.PackageList());
+ }
+
+ if (self->nextIndex != index + 1) {
+ while (self->nextIndex <= index && !self->current.end()) {
+ self->current = grp.NextPkg(self->current);
+ self->nextIndex++;
+ }
+ }
+
+ if (self->current.end())
+ return PyErr_Format(PyExc_IndexError, "Out of range: %zd", index);
+
+ return PyPackage_FromCpp(self->current, true, owner);
+}
+
+
+static PySequenceMethods group_as_sequence =
+{
+ 0,
+ 0, // concat
+ 0, // repeat
+ group_seq_item,
+ 0, // slice
+ 0, // assign item
+ 0 // assign slice
+};
+
+
+static const char group_doc[] = "Group(cache, name)\n\n"
+ "Group of packages with the same name.\n\n"
+ "Provides access to all packages sharing a name. Can be used this\n"
+ "like a list, or by using the special find_*() methods. If you use\n"
+ "it as a sequence, make sure to access it linearly, as this uses a\n"
+ "linked list internally.";
+PyTypeObject PyGroup_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Group", // tp_name
+ sizeof(PyGroup), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgCache::GrpIterator>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &group_as_sequence, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flags
+ group_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ group_methods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ group_new, // tp_new
+};
diff --git a/python/cdrom.cc b/python/cdrom.cc
new file mode 100644
index 0000000..392dd83
--- /dev/null
+++ b/python/cdrom.cc
@@ -0,0 +1,139 @@
+/* cdrom.cc - Wrapper for pkgCdrom.
+ *
+ * Copyright 2004-2009 Canonical Ltd.
+ * Copyright 2009 Julian Andres Klode <jak@debian.org>
+ *
+ * Authors: Michael Vogt
+ * Julian Andres Klode
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include "generic.h"
+#include "apt_pkgmodule.h"
+#include "progress.h"
+
+#include <apt-pkg/cdrom.h>
+
+static char *cdrom_add_doc =
+ "add(progress: apt_pkg.CdromProgress) -> bool\n\n"
+ "Add the given CD-ROM to the sources.list. Return True on success;\n"
+ "raise an error on failure or return False.";
+static PyObject *cdrom_add(PyObject *Self,PyObject *Args)
+{
+ pkgCdrom &Cdrom = GetCpp<pkgCdrom>(Self);
+
+ PyObject *pyCdromProgressInst = 0;
+ if (PyArg_ParseTuple(Args, "O", &pyCdromProgressInst) == 0) {
+ return 0;
+ }
+
+ PyCdromProgress progress;
+ progress.setCallbackInst(pyCdromProgressInst);
+
+ bool res = Cdrom.Add(&progress);
+
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static char *cdrom_ident_doc =
+ "ident(progress: apt_pkg.CdromProgress) -> str\n\n"
+ "Try to identify the CD-ROM and if successful return the hexadecimal\n"
+ "CDROM-ID (and a integer version suffix separated by -) as a\n"
+ "string. Otherwise, return None or raise an error.\n\n"
+ "The ID is created by hashing all file and directory names on the\n"
+ "CD-ROM and appending the version.";
+static PyObject *cdrom_ident(PyObject *Self,PyObject *Args)
+{
+ pkgCdrom &Cdrom = GetCpp<pkgCdrom>(Self);
+ PyObject *pyCdromProgressInst = 0;
+ if (PyArg_ParseTuple(Args, "O", &pyCdromProgressInst) == 0) {
+ return 0;
+ }
+
+ PyCdromProgress progress;
+ progress.setCallbackInst(pyCdromProgressInst);
+
+ std::string ident;
+ bool res = Cdrom.Ident(ident, &progress);
+
+ if (res)
+ return CppPyString(ident);
+ else {
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+ }
+}
+
+
+static PyMethodDef cdrom_methods[] = {
+ {"add",cdrom_add,METH_VARARGS,cdrom_add_doc},
+ {"ident",cdrom_ident,METH_VARARGS,cdrom_ident_doc},
+ {}
+};
+
+static PyObject *cdrom_new(PyTypeObject *type,PyObject *Args,PyObject *kwds)
+{
+ return CppPyObject_NEW<pkgCdrom>(NULL, type);
+}
+
+static char *cdrom_doc =
+ "Cdrom()\n\n"
+ "Cdrom objects can be used to identify Debian installation media and to\n"
+ "add them to /etc/apt/sources.list.";
+PyTypeObject PyCdrom_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Cdrom", // tp_name
+ sizeof(CppPyObject<pkgCdrom>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgCdrom>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE,
+ cdrom_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ cdrom_methods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ cdrom_new, // tp_new
+};
+
diff --git a/python/configuration.cc b/python/configuration.cc
new file mode 100644
index 0000000..dab2cc4
--- /dev/null
+++ b/python/configuration.cc
@@ -0,0 +1,613 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: configuration.cc,v 1.4 2003/06/03 03:22:27 mdz Exp $
+/* ######################################################################
+
+ Configuration - Binding for the configuration object.
+
+ The Configuration object can have an owner (a parent Configuration object),
+ and it always uses a pointer.
+
+ The wrapping is mostly 1:1 with the C++ code, but there are additions to
+ wrap the linked tree walking into nice flat sequence walking.
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "generic.h"
+#include "apt_pkgmodule.h"
+
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/cmndline.h>
+#include <sstream>
+#include <Python.h>
+ /*}}}*/
+
+// GetSelf - Convert PyObject to Configuration /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+static inline Configuration &GetSelf(PyObject *Obj)
+{
+ return *GetCpp<Configuration*>(Obj);
+}
+ /*}}}*/
+
+// Method Wrappers /*{{{*/
+static const char *doc_Find =
+ "find(key: str[, default: str = '']) -> str\n\n"
+ "Find the value for the given key and return it. If the\n"
+ "given key does not exist, return default instead.";
+static PyObject *CnfFind(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ char *Default = 0;
+ if (PyArg_ParseTuple(Args,"s|s",&Name,&Default) == 0)
+ return 0;
+ return CppPyString(GetSelf(Self).Find(Name,Default));
+}
+
+static const char *doc_FindFile =
+ "find_file(key: str[, default: str = '']) -> str\n\n"
+ "Same as find(), but for filenames. In the APT configuration, there\n"
+ "is a special section Dir:: for storing filenames. find_file() locates\n"
+ "the given key and then goes up and prepends the directory names to the\n"
+ "return value. For example, for:\n"
+ "\n"
+ " apt_pkg.config['Dir'] = 'a'\n"
+ " apt_pkg.config['Dir::D'] = 'b'\n"
+ " apt_pkg.config['Dir::D::F'] = 'c'\n"
+ "\n"
+ "find_file('Dir::D::F') returns 'a/b/c'. There is also a special\n"
+ "configuration setting RootDir which will always be prepended to the\n"
+ "result (the default being ''). Thus, if RootDir is 'x', the example\n"
+ "would return 'x/a/b/c'.";
+static PyObject *CnfFindFile(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ char *Default = 0;
+ if (PyArg_ParseTuple(Args,"s|s",&Name,&Default) == 0)
+ return 0;
+ return CppPyPath(GetSelf(Self).FindFile(Name,Default));
+}
+
+static const char *doc_FindDir =
+ "find_dir(key: str[, default: str = '']) -> str\n\n"
+ "Same as find_file(), but for directories. The difference is\n"
+ "that this function adds a trailing slash to the result.";
+static PyObject *CnfFindDir(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ char *Default = 0;
+ if (PyArg_ParseTuple(Args,"s|s",&Name,&Default) == 0)
+ return 0;
+ return CppPyPath(GetSelf(Self).FindDir(Name,Default));
+}
+
+static const char *doc_FindI =
+ "find_i(key: str[, default: int = 0]) -> int\n\n"
+ "Same as find, but for integer values.";
+static PyObject *CnfFindI(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ int Default = 0;
+ if (PyArg_ParseTuple(Args,"s|i",&Name,&Default) == 0)
+ return 0;
+ return MkPyNumber(GetSelf(Self).FindI(Name,Default));
+}
+
+static const char *doc_FindB =
+ "find_i(key: str[, default: bool = False]) -> bool\n\n"
+ "Same as find, but for boolean values; returns False on unknown values.";
+static PyObject *CnfFindB(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ int Default = 0;
+ if (PyArg_ParseTuple(Args,"s|i",&Name,&Default) == 0)
+ return 0;
+ return PyBool_FromLong(GetSelf(Self).FindB(Name,(Default == 0?false:true)));
+}
+
+static const char *doc_Set =
+ "set(key: str, value: str)\n\n"
+ "Set the given key to the given value. To set int or bool values,\n"
+ "encode them using str(value) and then use find_i()/find_b()\n"
+ "to retrieve their value again.";
+static PyObject *CnfSet(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ char *Value = 0;
+ if (PyArg_ParseTuple(Args,"ss",&Name,&Value) == 0)
+ return 0;
+
+ GetSelf(Self).Set(Name,Value);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static const char *doc_Exists =
+ "exists(key: str) -> bool\n\n"
+ "Check whether the given key exists.";
+static PyObject *CnfExists(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ if (PyArg_ParseTuple(Args,"s",&Name) == 0)
+ return 0;
+ return PyBool_FromLong((int)GetSelf(Self).Exists(Name));
+}
+
+static int CnfContains(PyObject *Self,PyObject *Arg)
+{
+ return (int)GetSelf(Self).Exists(PyString_AsString(Arg));
+}
+
+static const char *doc_Clear =
+ "clear(key: str)\n\n"
+ "Remove the specified option and all sub-options.";
+static PyObject *CnfClear(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ if (PyArg_ParseTuple(Args,"s",&Name) == 0)
+ return 0;
+
+ GetSelf(Self).Clear(Name);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+// The amazing narrowing search ability!
+static const char *doc_SubTree =
+ "subtree(key: str) -> apt_pkg.Configuration\n\n"
+
+ "Return a new apt_pkg.Configuration object with the given option\n"
+ "as its root. Example:\n\n"
+ " apttree = config.subtree('APT')\n"
+ " apttree['Install-Suggests'] = config['APT::Install-Suggests']";
+static PyObject *CnfSubTree(PyObject *Self,PyObject *Args)
+{
+ char *Name;
+ if (PyArg_ParseTuple(Args,"s",&Name) == 0)
+ return 0;
+ const Configuration::Item *Itm = GetSelf(Self).Tree(Name);
+ if (Itm == 0)
+ {
+ PyErr_SetString(PyExc_KeyError,Name);
+ return 0;
+ }
+
+ return CppPyObject_NEW<Configuration*>(Self,&PyConfiguration_Type,
+ new Configuration(Itm));
+}
+
+// Return a list of items at a specific level
+static char *doc_List =
+ "list([root: str]) -> list\n\n"
+ "Return a list of all items at the given root, using their full\n"
+ "name. For example, in a configuration object where the options A,\n"
+ "B, and B::C are set, the following expressions evaluate to True:\n\n"
+ " conf.list() == ['A', 'B']\n"
+ " conf.list('A') == ['']\n"
+ " conf.list('B') == ['B::C']\n";
+static PyObject *CnfList(PyObject *Self,PyObject *Args)
+{
+ char *RootName = 0;
+ if (PyArg_ParseTuple(Args,"|s",&RootName) == 0)
+ return 0;
+
+ // Convert the whole configuration space into a list
+ PyObject *List = PyList_New(0);
+ const Configuration::Item *Top = GetSelf(Self).Tree(RootName);
+ if (!GetSelf(Self).Tree(0))
+ return List;
+ const Configuration::Item *Root = GetSelf(Self).Tree(0)->Parent;
+ if (Top != 0 && RootName != 0)
+ Top = Top->Child;
+ for (; Top != 0; Top = Top->Next)
+ {
+ PyObject *Obj;
+ PyList_Append(List,Obj = CppPyString(Top->FullTag(Root)));
+ Py_DECREF(Obj);
+ }
+
+ return List;
+}
+
+/* Return a list of values of items at a specific level.. This is used to
+ get out value lists */
+static char *doc_ValueList =
+ "value_list([root: str]) -> list\n\n"
+ "Same as list(), but instead of returning the keys, return the values.";
+static PyObject *CnfValueList(PyObject *Self,PyObject *Args)
+{
+ char *RootName = 0;
+ if (PyArg_ParseTuple(Args,"|s",&RootName) == 0)
+ return 0;
+
+ // Convert the whole configuration space into a list
+ PyObject *List = PyList_New(0);
+ const Configuration::Item *Top = GetSelf(Self).Tree(RootName);
+ if (Top != 0 && RootName != 0)
+ Top = Top->Child;
+ for (; Top != 0; Top = Top->Next)
+ {
+ PyObject *Obj;
+ PyList_Append(List,Obj = CppPyString(Top->Value));
+ Py_DECREF(Obj);
+ }
+
+ return List;
+}
+
+static char *doc_MyTag =
+ "my_tag() -> str\n\n"
+ "Return the tag of the root of this Configuration object. For the\n"
+ "default object, this is an empty string. For a subtree('APT') of\n"
+ "such an object, it would be 'APT' (given as an example).";
+static PyObject *CnfMyTag(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ const Configuration::Item *Top = GetSelf(Self).Tree(0);
+ if (Top == 0)
+ return Py_BuildValue("s","");
+ return CppPyString(Top->Parent->Tag);
+}
+
+static char *doc_Dump =
+ "dump() -> str\n\n"
+ "Return a string dump this Configuration object.";
+static PyObject *CnfDump(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ std::stringstream ss;
+ GetSelf(Self).Dump(ss);
+ return CppPyString(ss.str());
+}
+
+
+// Look like a mapping
+static char *doc_Keys =
+ "keys([root: str]) -> list\n\n"
+ "Return a list of all keys in the configuration object. If 'root'\n"
+ "is given, limit the list to those below the root.";
+static PyObject *CnfKeys(PyObject *Self,PyObject *Args)
+{
+ char *RootName = 0;
+ if (PyArg_ParseTuple(Args,"|s",&RootName) == 0)
+ return 0;
+
+ // Convert the whole configuration space into a list
+ PyObject *List = PyList_New(0);
+ const Configuration::Item *Top = GetSelf(Self).Tree(RootName);
+ const Configuration::Item *Stop = Top;
+ const Configuration::Item *Root = 0;
+ if (RootName == 0)
+ Stop = 0;
+ if (Top != 0 && GetSelf(Self).Tree(0))
+ Root = GetSelf(Self).Tree(0)->Parent;
+ for (; Top != 0;)
+ {
+ PyObject *Obj;
+ PyList_Append(List,Obj = CppPyString(Top->FullTag(Root)));
+ Py_DECREF(Obj);
+
+ if (Top->Child != 0)
+ {
+ Top = Top->Child;
+ continue;
+ }
+
+ while (Top != 0 && Top->Next == 0 && Top != Root &&
+ Top->Parent != Stop)
+ Top = Top->Parent;
+ if (Top != 0)
+ Top = Top->Next;
+ }
+
+ return List;
+}
+
+// Map access, operator []
+static PyObject *CnfMap(PyObject *Self,PyObject *Arg)
+{
+ if (PyString_Check(Arg) == 0)
+ {
+ PyErr_SetNone(PyExc_TypeError);
+ return 0;
+ }
+
+ if (GetSelf(Self).Exists(PyString_AsString(Arg)) == false)
+ {
+ PyErr_SetString(PyExc_KeyError,PyString_AsString(Arg));
+ return 0;
+ }
+
+ return CppPyString(GetSelf(Self).Find(PyString_AsString(Arg)));
+}
+
+// Assignment with operator []
+static int CnfMapSet(PyObject *Self,PyObject *Arg,PyObject *Val)
+{
+ if (PyString_Check(Arg) == 0 || (Val != NULL && PyString_Check(Val) == 0))
+ {
+ PyErr_SetNone(PyExc_TypeError);
+ return -1;
+ }
+
+ if (Val == NULL)
+ GetSelf(Self).Clear(PyString_AsString(Arg));
+ else
+ GetSelf(Self).Set(PyString_AsString(Arg),PyString_AsString(Val));
+ return 0;
+}
+ /*}}}*/
+// Config file loaders /*{{{*/
+char *doc_LoadConfig =
+ "read_config_file(configuration: apt_pkg.Configuration, filename: str)\n\n"
+ "Read the configuration file 'filename' and set the appropriate\n"
+ "options in the configuration object.";
+PyObject *LoadConfig(PyObject *Self,PyObject *Args)
+{
+ PyApt_Filename Name;
+ if (PyArg_ParseTuple(Args,"OO&",&Self,PyApt_Filename::Converter, &Name) == 0)
+ return 0;
+ if (PyConfiguration_Check(Self)== 0)
+ {
+ PyErr_SetString(PyExc_TypeError,"argument 1: expected Configuration.");
+ return 0;
+ }
+
+ if (ReadConfigFile(GetSelf(Self),Name,false) == false)
+ return HandleErrors();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+char *doc_LoadConfigISC =
+ "read_config_file_isc(configuration: apt_pkg.Configuration, filename: str)\n\n"
+ "Like read_config_file(), but for configuration files like bind's\n"
+ "named.conf. They have a slightly different format than APT\n"
+ "configuration files.";
+PyObject *LoadConfigISC(PyObject *Self,PyObject *Args)
+{
+ PyApt_Filename Name;
+ if (PyArg_ParseTuple(Args,"OO&",&Self,PyApt_Filename::Converter, &Name) == 0)
+ return 0;
+ if (PyConfiguration_Check(Self)== 0)
+ {
+ PyErr_SetString(PyExc_TypeError,"argument 1: expected Configuration.");
+ return 0;
+ }
+
+ if (ReadConfigFile(GetSelf(Self),Name,true) == false)
+ return HandleErrors();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+char *doc_LoadConfigDir =
+ "read_config_dir(configuration: apt_pkg.Configuration, dirname: str)\n\n"
+ "Read all configuration files in the dir given by 'dirname' in the\n"
+ "correct order.";
+PyObject *LoadConfigDir(PyObject *Self,PyObject *Args)
+{
+ PyApt_Filename Name;
+ if (PyArg_ParseTuple(Args,"OO&",&Self,PyApt_Filename::Converter, &Name) == 0)
+ return 0;
+ if (PyConfiguration_Check(Self)== 0)
+ {
+ PyErr_SetString(PyExc_TypeError,"argument 1: expected Configuration.");
+ return 0;
+ }
+
+ if (ReadConfigDir(GetSelf(Self),Name,false) == false)
+ return HandleErrors();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+ /*}}}*/
+
+// ParseCommandLine - Wrapper for the command line interface /*{{{*/
+// ---------------------------------------------------------------------
+char *doc_ParseCommandLine =
+"parse_commandLine(config: Configuration, options: list, argv: list) -> list\n"
+"\n"
+"Parse the command line in 'argv' into the configuration space. The\n"
+"list 'options' contains a list of 3-tuples or 4-tuples in the form:\n"
+"\n"
+" (short_option: str, long_option: str, variable: str[, type: str])\n"
+"\n"
+"The element 'short_option' is one character, the 'long_option' element\n"
+"is the name of the long option, the element 'variable' the name of the\n"
+"configuration option the result will be stored in and type is one of\n"
+"'HasArg', 'IntLevel', 'Boolean', 'InvBoolean', 'ConfigFile',\n"
+"'ArbItem'. The default type is 'Boolean'. Read the online documentation\n"
+"in python-apt-doc and its tutorial on writing an apt-cdrom clone for more\n"
+"details.";
+PyObject *ParseCommandLine(PyObject *Self,PyObject *Args)
+{
+ PyObject *POList;
+ PyObject *Pargv;
+ if (PyArg_ParseTuple(Args,"OO!O!",&Self,
+ &PyList_Type,&POList,&PyList_Type,&Pargv) == 0)
+ return 0;
+ if (PyConfiguration_Check(Self)== 0)
+ {
+ PyErr_SetString(PyExc_TypeError,"argument 1: expected Configuration.");
+ return 0;
+ }
+
+ if (PySequence_Length(Pargv) < 1) {
+ PyErr_SetString(PyExc_ValueError,"argv is an empty sequence");
+ return 0;
+ }
+ // Convert the option list
+ int Length = PySequence_Length(POList);
+ CommandLine::Args *OList = new CommandLine::Args[Length+1];
+ OList[Length].ShortOpt = 0;
+ OList[Length].LongOpt = 0;
+
+ for (int I = 0; I != Length; I++)
+ {
+ char *Type = 0;
+ #if PY_MAJOR_VERSION >= 3
+ if (PyArg_ParseTuple(PySequence_GetItem(POList,I),"Czs|s",
+ #else
+ if (PyArg_ParseTuple(PySequence_GetItem(POList,I),"czs|s",
+ #endif
+ &OList[I].ShortOpt,&OList[I].LongOpt,
+ &OList[I].ConfName,&Type) == 0)
+ {
+ delete [] OList;
+ return 0;
+ }
+ OList[I].Flags = 0;
+
+ // Convert the type over to flags..
+ if (Type != 0)
+ {
+ if (strcasecmp(Type,"HasArg") == 0)
+ OList[I].Flags = CommandLine::HasArg;
+ else if (strcasecmp(Type,"IntLevel") == 0)
+ OList[I].Flags = CommandLine::IntLevel;
+ else if (strcasecmp(Type,"Boolean") == 0)
+ OList[I].Flags = CommandLine::Boolean;
+ else if (strcasecmp(Type,"InvBoolean") == 0)
+ OList[I].Flags = CommandLine::InvBoolean;
+ else if (strcasecmp(Type,"ConfigFile") == 0)
+ OList[I].Flags = CommandLine::ConfigFile;
+ else if (strcasecmp(Type,"ArbItem") == 0)
+ OList[I].Flags = CommandLine::ArbItem;
+ }
+ }
+
+ // Convert the argument list into a char **
+ const char **argv = ListToCharChar(Pargv);
+ if (argv == 0)
+ {
+ delete [] OList;
+ return 0;
+ }
+
+ // Do the command line processing
+ PyObject *List = 0;
+ {
+ CommandLine CmdL(OList,&GetSelf(Self));
+ if (CmdL.Parse(PySequence_Length(Pargv),argv) == false)
+ {
+ delete [] argv;
+ delete [] OList;
+ return HandleErrors();
+ }
+
+ // Convert the file listing into a python sequence
+ for (Length = 0; CmdL.FileList[Length] != 0; Length++);
+ List = PyList_New(Length);
+ for (int I = 0; CmdL.FileList[I] != 0; I++)
+ {
+ PyList_SetItem(List,I,CppPyString(CmdL.FileList[I]));
+ }
+ }
+
+ delete [] argv;
+ delete [] OList;
+ return HandleErrors(List);
+}
+ /*}}}*/
+
+// Method table for the Configuration object
+static PyMethodDef CnfMethods[] =
+{
+ // Query
+ {"find",CnfFind,METH_VARARGS,doc_Find},
+ {"find_file",CnfFindFile,METH_VARARGS,doc_FindFile},
+ {"find_dir",CnfFindDir,METH_VARARGS,doc_FindDir},
+ {"find_i",CnfFindI,METH_VARARGS,doc_FindI},
+ {"find_b",CnfFindB,METH_VARARGS,doc_FindB},
+
+ // Others
+ {"set",CnfSet,METH_VARARGS,doc_Set},
+ {"exists",CnfExists,METH_VARARGS,doc_Exists},
+ {"subtree",CnfSubTree,METH_VARARGS,doc_SubTree},
+ {"list",CnfList,METH_VARARGS,doc_List},
+ {"value_list",CnfValueList,METH_VARARGS,doc_ValueList},
+ {"my_tag",CnfMyTag,METH_VARARGS,doc_MyTag},
+ {"clear",CnfClear,METH_VARARGS,doc_Clear},
+ {"dump",CnfDump,METH_VARARGS,doc_Dump},
+ // Python Special
+ {"keys",CnfKeys,METH_VARARGS,doc_Keys},
+ #if PY_MAJOR_VERSION < 3
+ {"has_key",CnfExists,METH_VARARGS,doc_Exists},
+ #endif
+ {"get",CnfFind,METH_VARARGS,doc_Find},
+ {}
+};
+
+static PyObject *CnfNew(PyTypeObject *type, PyObject *args, PyObject *kwds) {
+ char *kwlist[] = {NULL};
+ if (PyArg_ParseTupleAndKeywords(args,kwds,"",kwlist) == 0)
+ return 0;
+ return CppPyObject_NEW<Configuration*>(NULL, type, new Configuration());
+}
+
+// Type for a Normal Configuration object
+static PySequenceMethods ConfigurationSeq = {0,0,0,0,0,0,0,CnfContains,0,0};
+static PyMappingMethods ConfigurationMap = {0,CnfMap,CnfMapSet};
+
+static const char *configuration_doc =
+ "Configuration()\n\n"
+ "Represent the configuration of APT by mapping option keys to\n"
+ "values and storing configuration parsed from files like\n"
+ "/etc/apt/apt.conf. The most important Configuration object\n"
+ "is apt_pkg.config which points to the global configuration\n"
+ "object. Other top-level Configuration objects can be created\n"
+ "by calling the constructor, but there is usually no reason to.";
+
+PyTypeObject PyConfiguration_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Configuration", // tp_name
+ sizeof(CppPyObject<Configuration*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<Configuration*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &ConfigurationSeq, // tp_as_sequence
+ &ConfigurationMap, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE),
+ configuration_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ CnfMethods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ CnfNew, // tp_new
+};
+
diff --git a/python/depcache.cc b/python/depcache.cc
new file mode 100644
index 0000000..ed766c4
--- /dev/null
+++ b/python/depcache.cc
@@ -0,0 +1,1169 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: depcache.cc,v 1.5 2003/06/03 03:03:23 mdz Exp $
+/* ######################################################################
+
+ DepCache - Wrapper for the depcache related functions
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "generic.h"
+#include "apt_pkgmodule.h"
+
+#include <apt-pkg/pkgcache.h>
+#include <apt-pkg/cachefile.h>
+#include <apt-pkg/algorithms.h>
+#include <apt-pkg/policy.h>
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/sourcelist.h>
+#include <apt-pkg/pkgrecords.h>
+#include <apt-pkg/acquire-item.h>
+#include <apt-pkg/fileutl.h>
+#include <apt-pkg/upgrade.h>
+#include <Python.h>
+
+#include <iostream>
+#include "progress.h"
+
+#ifndef _
+#define _(x) (x)
+#endif
+
+
+#define VALIDATE_ITERATOR(I) do { \
+ if ((I).Cache() != &depcache->GetCache()) { \
+ PyErr_SetString(PyAptCacheMismatchError, "Object of different cache passed as argument to apt_pkg.DepCache method"); \
+ return nullptr; \
+ } \
+} while(0)
+
+
+// DepCache Class /*{{{*/
+// ---------------------------------------------------------------------
+
+
+
+static PyObject *PkgDepCacheInit(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *pyCallbackInst = 0;
+ if (PyArg_ParseTuple(Args, "|O", &pyCallbackInst) == 0)
+ return 0;
+
+ if(pyCallbackInst != 0) {
+ PyOpProgress progress;
+ progress.setCallbackInst(pyCallbackInst);
+ depcache->Init(&progress);
+ } else {
+ depcache->Init(0);
+ }
+
+ pkgApplyStatus(*depcache);
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static PyObject *PkgDepCacheCommit(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *pyInstallProgressInst = 0;
+ PyObject *pyFetchProgressInst = 0;
+ if (PyArg_ParseTuple(Args, "OO",
+ &pyFetchProgressInst, &pyInstallProgressInst) == 0) {
+ return 0;
+ }
+
+ pkgAcquire Fetcher;
+ if (Fetcher.GetLock(_config->FindDir("Dir::Cache::Archives")) == false) {
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+ }
+
+ pkgRecords Recs(*depcache);
+ if (_error->PendingError() == true)
+ HandleErrors(Py_None);
+
+ pkgSourceList List;
+ if(!List.ReadMainList())
+ return HandleErrors(Py_None);
+
+ PyFetchProgress progress;
+ progress.setCallbackInst(pyFetchProgressInst);
+
+ pkgPackageManager *PM;
+ PM = _system->CreatePM(depcache);
+
+ Fetcher.SetLog(&progress);
+
+ if(PM->GetArchives(&Fetcher, &List, &Recs) == false ||
+ _error->PendingError() == true) {
+ std::cerr << "Error in GetArchives" << std::endl;
+ return HandleErrors();
+ }
+
+ PyInstallProgress iprogress;
+ iprogress.setCallbackInst(pyInstallProgressInst);
+
+ // Run it
+ while (1)
+ {
+ bool Transient = false;
+
+ if (Fetcher.Run() == pkgAcquire::Failed)
+ return HandleErrors();
+
+ // Print out errors
+ bool Failed = false;
+ for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
+ {
+
+ if ((*I)->Status == pkgAcquire::Item::StatDone &&
+ (*I)->Complete == true)
+ continue;
+
+ if ((*I)->Status == pkgAcquire::Item::StatIdle)
+ {
+ Transient = true;
+ //Failed = true;
+ continue;
+ }
+
+ _error->Warning(_("Failed to fetch %s %s\n"),(*I)->DescURI().c_str(),
+ (*I)->ErrorText.c_str());
+ Failed = true;
+ }
+
+ if (Transient == true && Failed == true)
+ {
+ _error->Error(_("--fix-missing and media swapping is not currently supported"));
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+ }
+
+ // Try to deal with missing package files
+ if (Failed == true && PM->FixMissing() == false)
+ {
+ _error->Error("Aborting install.");
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+ }
+
+ // fail if something else went wrong
+ //FIXME: make this more flexible, e.g. with a failedDl handler
+ if(Failed)
+ Py_RETURN_FALSE;
+ _system->UnLockInner(true);
+
+ pkgPackageManager::OrderResult Res = iprogress.Run(PM);
+
+ if (Res == pkgPackageManager::Failed || _error->PendingError() == true) {
+ return HandleErrors(PyBool_FromLong(false));
+ }
+ if (Res == pkgPackageManager::Completed) {
+ Py_RETURN_TRUE;
+ }
+
+ // Reload the fetcher object and loop again for media swapping
+ Fetcher.Shutdown();
+ if (PM->GetArchives(&Fetcher,&List,&Recs) == false) {
+ Py_RETURN_FALSE;
+ }
+ _system->LockInner();
+ }
+
+ return HandleErrors(Py_None);
+}
+
+static PyObject *PkgDepCacheSetCandidateRelease(PyObject *Self,PyObject *Args)
+{
+ bool Success;
+ PyObject *PackageObj;
+ PyObject *VersionObj;
+ const char *target_rel;
+ std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> > Changed;
+ if (PyArg_ParseTuple(Args,"O!O!s",
+ &PyPackage_Type, &PackageObj,
+ &PyVersion_Type, &VersionObj,
+ &target_rel) == 0)
+ return 0;
+
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+ pkgCache::VerIterator &I = GetCpp<pkgCache::VerIterator>(VersionObj);
+ if(I.end()) {
+ return HandleErrors(PyBool_FromLong(false));
+ }
+ VALIDATE_ITERATOR(I);
+
+ Success = depcache->SetCandidateRelease(I, target_rel, Changed);
+
+ return HandleErrors(PyBool_FromLong(Success));
+}
+
+static PyObject *PkgDepCacheSetCandidateVer(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+ PyObject *PackageObj;
+ PyObject *VersionObj;
+ if (PyArg_ParseTuple(Args,"O!O!",
+ &PyPackage_Type, &PackageObj,
+ &PyVersion_Type, &VersionObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+
+ VALIDATE_ITERATOR(Pkg);
+
+ pkgCache::VerIterator &I = GetCpp<pkgCache::VerIterator>(VersionObj);
+ if(I.end()) {
+ return HandleErrors(PyBool_FromLong(false));
+ }
+ VALIDATE_ITERATOR(I);
+
+ if (I.ParentPkg() != Pkg) {
+ PyErr_SetString(PyExc_ValueError, "Version does not belong to package");
+ return nullptr;
+ }
+
+ depcache->SetCandidateVersion(I);
+
+ return HandleErrors(PyBool_FromLong(true));
+}
+
+static PyObject *PkgDepCacheGetCandidateVer(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+ PyObject *PackageObj;
+ PyObject *CandidateObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+
+ VALIDATE_ITERATOR(Pkg);
+
+ pkgDepCache::StateCache & State = (*depcache)[Pkg];
+ pkgCache::VerIterator I = State.CandidateVerIter(*depcache);
+
+ if(I.end()) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ CandidateObj = CppPyObject_NEW<pkgCache::VerIterator>(PackageObj,&PyVersion_Type,I);
+
+ return CandidateObj;
+}
+
+static PyObject *PkgDepCacheUpgrade(PyObject *Self,PyObject *Args)
+{
+ bool res;
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ char distUpgrade=0;
+ if (PyArg_ParseTuple(Args,"|b",&distUpgrade) == 0)
+ return 0;
+
+ Py_BEGIN_ALLOW_THREADS
+ if(distUpgrade)
+ res = APT::Upgrade::Upgrade(*depcache, 0);
+ else
+ res = APT::Upgrade::Upgrade(*depcache, APT::Upgrade::FORBID_REMOVE_PACKAGES |
+ APT::Upgrade::FORBID_INSTALL_NEW_PACKAGES);
+ Py_END_ALLOW_THREADS
+
+ Py_INCREF(Py_None);
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static PyObject *PkgDepCacheMinimizeUpgrade(PyObject *Self,PyObject *Args)
+{
+ bool res;
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ Py_BEGIN_ALLOW_THREADS
+ res = pkgMinimizeUpgrade(*depcache);
+ Py_END_ALLOW_THREADS
+
+ Py_INCREF(Py_None);
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+
+static PyObject *PkgDepCacheReadPinFile(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+
+ char *file=NULL;
+ if (PyArg_ParseTuple(Args,"|s",&file) == 0)
+ return 0;
+
+ if(file == NULL)
+ ReadPinFile((pkgPolicy&)depcache->GetPolicy());
+ else
+ ReadPinFile((pkgPolicy&)depcache->GetPolicy(), file);
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+
+static PyObject *PkgDepCacheFixBroken(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ bool res=true;
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ res &=pkgFixBroken(*depcache);
+ res &=pkgMinimizeUpgrade(*depcache);
+
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+
+static PyObject *PkgDepCacheMarkKeep(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache*>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ depcache->MarkKeep(Pkg);
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static PyObject *PkgDepCacheSetReInstall(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache*>(Self);
+
+ PyObject *PackageObj;
+ char value = 0;
+ if (PyArg_ParseTuple(Args,"O!b",&PyPackage_Type,&PackageObj, &value) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ depcache->SetReInstall(Pkg,value);
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+
+static PyObject *PkgDepCacheMarkDelete(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ char purge = 0;
+ if (PyArg_ParseTuple(Args,"O!|b",&PyPackage_Type,&PackageObj, &purge) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ depcache->MarkDelete(Pkg,purge);
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+
+static PyObject *PkgDepCacheMarkInstall(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ char autoInst=1;
+ char fromUser=1;
+ if (PyArg_ParseTuple(Args,"O!|bb",&PyPackage_Type,&PackageObj,
+ &autoInst, &fromUser) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+
+ Py_BEGIN_ALLOW_THREADS
+ depcache->MarkInstall(Pkg, autoInst, 0, fromUser);
+ Py_END_ALLOW_THREADS
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static PyObject *PkgDepCacheMarkAuto(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache*>(Self);
+
+ PyObject *PackageObj;
+ char value = 0;
+ if (PyArg_ParseTuple(Args,"O!b",&PyPackage_Type,&PackageObj, &value) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ depcache->MarkAuto(Pkg,value);
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static PyObject *PkgDepCacheIsUpgradable(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ return HandleErrors(PyBool_FromLong(state.Upgradable()));
+}
+
+static PyObject *PkgDepCacheIsGarbage(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ return HandleErrors(PyBool_FromLong(state.Garbage));
+}
+
+static PyObject *PkgDepCacheIsAutoInstalled(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ return HandleErrors(PyBool_FromLong(state.Flags & pkgCache::Flag::Auto));
+}
+
+static PyObject *PkgDepCacheIsNowBroken(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ return HandleErrors(PyBool_FromLong(state.NowBroken()));
+}
+
+static PyObject *PkgDepCacheIsInstBroken(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ return HandleErrors(PyBool_FromLong(state.InstBroken()));
+}
+
+
+static PyObject *PkgDepCacheMarkedInstall(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ return HandleErrors(PyBool_FromLong(state.NewInstall()));
+}
+
+
+static PyObject *PkgDepCacheMarkedUpgrade(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ return HandleErrors(PyBool_FromLong(state.Upgrade()));
+}
+
+static PyObject *PkgDepCacheMarkedDelete(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ return HandleErrors(PyBool_FromLong(state.Delete()));
+}
+
+static PyObject *PkgDepCacheMarkedKeep(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ return HandleErrors(PyBool_FromLong(state.Keep()));
+}
+
+static PyObject *PkgDepCacheMarkedDowngrade(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ return HandleErrors(PyBool_FromLong(state.Downgrade()));
+}
+
+static PyObject *PkgDepCacheMarkedReinstall(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ pkgDepCache::StateCache &state = (*depcache)[Pkg];
+
+ bool res = state.Install() && (state.iFlags & pkgDepCache::ReInstall);
+
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static PyObject *PkgDepCachePhasingApplied(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache *depcache = GetCpp<pkgDepCache *>(Self);
+
+ bool res=false;
+ PyObject *PackageObj;
+
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+
+ pkgCache::PkgIterator Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ res = depcache->PhasingApplied(Pkg);
+
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static PyMethodDef PkgDepCacheMethods[] =
+{
+ {"init",PkgDepCacheInit,METH_VARARGS,
+ "init(progress: apt.progress.base.OpProgress)\n\n"
+ "Initialize the depcache (done automatically when constructing\n"
+ "the object)."},
+ {"get_candidate_ver",PkgDepCacheGetCandidateVer,METH_VARARGS,
+ "get_candidate_ver(pkg: apt_pkg.Package) -> apt_pkg.Version\n\n"
+ "Return the candidate version for the package, normally the version\n"
+ "with the highest pin (changeable using set_candidate_ver)."},
+ {"set_candidate_ver",PkgDepCacheSetCandidateVer,METH_VARARGS,
+ "set_candidate_ver(pkg: apt_pkg.Package, ver: apt_pkg.Version) -> bool\n\n"
+ "Set the candidate version of 'pkg' to 'ver'."},
+ {"set_candidate_release",PkgDepCacheSetCandidateRelease,METH_VARARGS,
+ "set_candidate_release(pkg: apt_pkg.Package, ver: apt_pkg.Version, rel: string) -> bool\n\n"
+ "Sets not only the candidate version 'ver' for package 'pkg', "
+ "but walks also down the dependency tree and checks if it is required "
+ "to set the candidate of the dependency to a version from the given "
+ "release string 'rel', too."},
+
+ // global cache operations
+ {"upgrade",PkgDepCacheUpgrade,METH_VARARGS,
+ "upgrade([dist_upgrade: bool = True]) -> bool\n\n"
+ "Mark the packages for upgrade under the same conditions apt-get\n"
+ "upgrade does. If 'dist_upgrade' is True, also allow packages to\n"
+ "be upgraded if they require installation/removal of other packages;\n"
+ "just like apt-get dist-upgrade."},
+ {"fix_broken",PkgDepCacheFixBroken,METH_VARARGS,
+ "fix_broken() -> bool\n\n"
+ "Fix broken packages."},
+ {"read_pinfile",PkgDepCacheReadPinFile,METH_VARARGS,
+ "read_pinfile([file: str])\n\n"
+ "Read the pin policy"},
+ {"minimize_upgrade",PkgDepCacheMinimizeUpgrade, METH_VARARGS,
+ "minimize_upgrade() -> bool\n\n"
+ "Go over the entire set of packages and try to keep each package\n"
+ "marked for upgrade. If a conflict is generated then the package\n"
+ "is restored."},
+ // Policy
+ {"phasing_applied",PkgDepCachePhasingApplied,METH_VARARGS,
+ "phasing_applied(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check if the phased update is ready.\n"
+ "return false if this is a phased update that is not yet ready for us.\n"},
+ // Manipulators
+ {"mark_keep",PkgDepCacheMarkKeep,METH_VARARGS,
+ "mark_keep(pkg: apt_pkg.Package)\n\n"
+ "Mark package to be kept."},
+ {"mark_delete",PkgDepCacheMarkDelete,METH_VARARGS,
+ "mark_delete(pkg: apt_pkg.Package[, purge: bool = False])\n\n"
+ "Mark package for deletion, and if 'purge' is True also for purging."},
+ {"mark_install",PkgDepCacheMarkInstall,METH_VARARGS,
+ "mark_install(pkg: apt_pkg.Package[, auto_inst=True, from_user=True])\n\n"
+ "Mark the package for installation. The parameter 'auto_inst' controls\n"
+ "whether the dependencies of the package are marked for installation\n"
+ "as well. The parameter 'from_user' controls whether the package is\n"
+ "registered as NOT automatically installed."},
+ {"mark_auto",PkgDepCacheMarkAuto,METH_VARARGS,
+ "mark_auto(pkg: apt_pkg.Package, auto: bool)\n\n"
+ "Mark package as automatically installed (if auto=True),\n"
+ "or as not automatically installed (if auto=False)."},
+ {"set_reinstall",PkgDepCacheSetReInstall,METH_VARARGS,
+ "set_reinstall(pkg: apt_pkg.Package, reinstall: bool)\n\n"
+ "Set whether the package should be reinstalled (reinstall = True or False)."},
+ // state information
+ {"is_upgradable",PkgDepCacheIsUpgradable,METH_VARARGS,
+ "is_upgradable(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check whether the package is upgradable."},
+ {"is_now_broken",PkgDepCacheIsNowBroken,METH_VARARGS,
+ "is_now_broken(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check whether the package is broken, taking marked changes into account."},
+ {"is_inst_broken",PkgDepCacheIsInstBroken,METH_VARARGS,
+ "is_inst_broken(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check whether the package is broken, ignoring marked changes."},
+ {"is_garbage",PkgDepCacheIsGarbage,METH_VARARGS,
+ "is_garbage(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check whether the package is garbage, i.e. whether it is automatically\n"
+ "installed and the reverse dependencies are not installed anymore."},
+ {"is_auto_installed",PkgDepCacheIsAutoInstalled,METH_VARARGS,
+ "is_auto_installed(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check whether the package is marked as automatically installed."},
+ {"marked_install",PkgDepCacheMarkedInstall,METH_VARARGS,
+ "marked_install(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check whether the package is marked for installation."},
+ {"marked_upgrade",PkgDepCacheMarkedUpgrade,METH_VARARGS,
+ "marked_upgrade(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check whether the package is marked for upgrade."},
+ {"marked_delete",PkgDepCacheMarkedDelete,METH_VARARGS,
+ "marked_delete(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check whether the package is marked for removal."},
+ {"marked_keep",PkgDepCacheMarkedKeep,METH_VARARGS,
+ "marked_keep(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check whether the package should be kept."},
+ {"marked_reinstall",PkgDepCacheMarkedReinstall,METH_VARARGS,
+ "marked_reinstall(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check whether the package is marked for re-installation."},
+ {"marked_downgrade",PkgDepCacheMarkedDowngrade,METH_VARARGS,
+ "marked_downgrade(pkg: apt_pkg.Package) -> bool\n\n"
+ "Check whether the package is marked for downgrade."},
+ // Action
+ {"commit", PkgDepCacheCommit, METH_VARARGS,
+ "commit(acquire_progress, install_progress)\n\n"
+ "Commit all the marked changes. This method takes two arguments,\n"
+ "'acquire_progress' takes an apt.progress.base.AcquireProgress\n"
+ "object and 'install_progress' an apt.progress.base.InstallProgress\n"
+ "object."},
+ {}
+};
+
+#define depcache (GetCpp<pkgDepCache *>(Self))
+static PyObject *PkgDepCacheGetKeepCount(PyObject *Self,void*) {
+ return MkPyNumber(depcache->KeepCount());
+}
+static PyObject *PkgDepCacheGetInstCount(PyObject *Self,void*) {
+ return MkPyNumber(depcache->InstCount());
+}
+static PyObject *PkgDepCacheGetDelCount(PyObject *Self,void*) {
+ return MkPyNumber(depcache->DelCount());
+}
+static PyObject *PkgDepCacheGetBrokenCount(PyObject *Self,void*) {
+ return MkPyNumber(depcache->BrokenCount());
+}
+static PyObject *PkgDepCacheGetUsrSize(PyObject *Self,void*) {
+ return MkPyNumber(depcache->UsrSize());
+}
+static PyObject *PkgDepCacheGetDebSize(PyObject *Self,void*) {
+ return MkPyNumber(depcache->DebSize());
+}
+#undef depcache
+
+static PyObject *PkgDepCacheGetPolicy(PyObject *Self,void*) {
+ PyObject *Owner = GetOwner<pkgDepCache*>(Self);
+ pkgDepCache *DepCache = GetCpp<pkgDepCache*>(Self);
+ pkgPolicy *Policy = (pkgPolicy *)&DepCache->GetPolicy();
+ CppPyObject<pkgPolicy*> *PyPolicy =
+ CppPyObject_NEW<pkgPolicy*>(Owner,&PyPolicy_Type,Policy);
+ // Policy should not be deleted, it is managed by CacheFile.
+ PyPolicy->NoDelete = true;
+ return PyPolicy;
+}
+
+
+static PyGetSetDef PkgDepCacheGetSet[] = {
+ {"broken_count",PkgDepCacheGetBrokenCount,0,
+ "The number of packages with broken dependencies in the cache."},
+ {"deb_size",PkgDepCacheGetDebSize,0,
+ "The size of the packages which are needed for the changes to be\n"
+ "applied."},
+ {"del_count",PkgDepCacheGetDelCount,0,
+ "The number of packages marked for removal."},
+ {"inst_count",PkgDepCacheGetInstCount,0,
+ "The number of packages marked for installation."},
+ {"keep_count",PkgDepCacheGetKeepCount,0,
+ "The number of packages marked for keep."},
+ {"usr_size",PkgDepCacheGetUsrSize,0,
+ "The amount of space required for installing/removing the packages,\n"
+ "i.e. the Installed-Size of all packages marked for installation\n"
+ "minus the Installed-Size of all packages for removal."},
+ {"policy",PkgDepCacheGetPolicy,0,
+ "The apt_pkg.Policy object used by this cache."},
+ {}
+};
+
+static PyObject *PkgDepCacheNew(PyTypeObject *type,PyObject *Args,PyObject *kwds)
+{
+ PyObject *Owner;
+ char *kwlist[] = {"cache", 0};
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"O!",kwlist,&PyCache_Type,
+ &Owner) == 0)
+ return 0;
+
+
+ // the owner of the Python cache object is a cachefile object, get it
+ PyObject *CacheFilePy = GetOwner<pkgCache*>(Owner);
+ // get the pkgCacheFile from the cachefile
+ pkgCacheFile *CacheF = GetCpp<pkgCacheFile*>(CacheFilePy);
+ // and now the depcache
+ pkgDepCache *depcache = (pkgDepCache *)(*CacheF);
+
+ CppPyObject<pkgDepCache*> *DepCachePyObj;
+ DepCachePyObj = CppPyObject_NEW<pkgDepCache*>(Owner,type,depcache);
+
+ // Do not delete the underlying pointer, it is managed by the cachefile.
+ DepCachePyObj->NoDelete = true;
+
+ return HandleErrors(DepCachePyObj);
+}
+
+static char *doc_PkgDepCache = "DepCache(cache: apt_pkg.Cache)\n\n"
+ "A DepCache() holds extra information on the state of the packages.\n\n"
+ "The parameter 'cache' refers to an apt_pkg.Cache() object.";
+PyTypeObject PyDepCache_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.DepCache", // tp_name
+ sizeof(CppPyObject<pkgDepCache *>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<pkgDepCache *>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE |
+ Py_TPFLAGS_HAVE_GC),
+ doc_PkgDepCache, // tp_doc
+ CppTraverse<pkgDepCache *>, // tp_traverse
+ CppClear<pkgDepCache *>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PkgDepCacheMethods, // tp_methods
+ 0, // tp_members
+ PkgDepCacheGetSet, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ PkgDepCacheNew, // tp_new
+};
+
+
+
+
+ /*}}}*/
+
+#undef VALIDATE_ITERATOR
+#define VALIDATE_ITERATOR(I) (void) 0 // FIXME: Need access to depcache of pkgProblemResolver
+
+// pkgProblemResolver Class /*{{{*/
+// ---------------------------------------------------------------------
+static PyObject *PkgProblemResolverNew(PyTypeObject *type,PyObject *Args,PyObject *kwds)
+{
+ PyObject *Owner;
+ char *kwlist[] = {"depcache",0};
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"O!",kwlist,&PyDepCache_Type,
+ &Owner) == 0)
+ return 0;
+
+ pkgDepCache *depcache = GetCpp<pkgDepCache*>(Owner);
+ pkgProblemResolver *fixer = new pkgProblemResolver(depcache);
+ CppPyObject<pkgProblemResolver*> *PkgProblemResolverPyObj;
+ PkgProblemResolverPyObj = CppPyObject_NEW<pkgProblemResolver*>(Owner,
+ type,
+ fixer);
+ HandleErrors(PkgProblemResolverPyObj);
+
+ return PkgProblemResolverPyObj;
+}
+
+
+static PyObject *PkgProblemResolverResolve(PyObject *Self,PyObject *Args)
+{
+ bool res;
+ pkgProblemResolver *fixer = GetCpp<pkgProblemResolver *>(Self);
+
+ char brokenFix=1;
+ if (PyArg_ParseTuple(Args,"|b",&brokenFix) == 0)
+ return 0;
+
+ Py_BEGIN_ALLOW_THREADS
+ res = fixer->Resolve(brokenFix);
+ Py_END_ALLOW_THREADS
+
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static PyObject *PkgProblemResolverResolveByKeep(PyObject *Self,PyObject *Args)
+{
+ bool res;
+ pkgProblemResolver *fixer = GetCpp<pkgProblemResolver *>(Self);
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ Py_BEGIN_ALLOW_THREADS
+ res = fixer->ResolveByKeep();
+ Py_END_ALLOW_THREADS
+
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static PyObject *PkgProblemResolverProtect(PyObject *Self,PyObject *Args)
+{
+ pkgProblemResolver *fixer = GetCpp<pkgProblemResolver *>(Self);
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ fixer->Protect(Pkg);
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+
+}
+static PyObject *PkgProblemResolverRemove(PyObject *Self,PyObject *Args)
+{
+ pkgProblemResolver *fixer = GetCpp<pkgProblemResolver *>(Self);
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ fixer->Remove(Pkg);
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static PyObject *PkgProblemResolverClear(PyObject *Self,PyObject *Args)
+{
+ pkgProblemResolver *fixer = GetCpp<pkgProblemResolver *>(Self);
+ PyObject *PackageObj;
+ if (PyArg_ParseTuple(Args,"O!",&PyPackage_Type,&PackageObj) == 0)
+ return 0;
+ pkgCache::PkgIterator &Pkg = GetCpp<pkgCache::PkgIterator>(PackageObj);
+ VALIDATE_ITERATOR(Pkg);
+ fixer->Clear(Pkg);
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static PyObject *PkgProblemResolverKeepPhasedUpdates(PyObject *Self,PyObject *Args)
+{
+ bool res;
+ pkgProblemResolver *fixer = GetCpp<pkgProblemResolver *>(Self);
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ Py_BEGIN_ALLOW_THREADS
+ res = fixer->KeepPhasedUpdates();
+ Py_END_ALLOW_THREADS
+
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+
+static PyMethodDef PkgProblemResolverMethods[] =
+{
+ // config
+ {"protect", PkgProblemResolverProtect, METH_VARARGS,
+ "protect(pkg: apt_pkg.Package)\n\n"
+ "Mark the package as protected in the resolver, meaning that its\n"
+ "state will not be changed."},
+ {"remove", PkgProblemResolverRemove, METH_VARARGS,
+ "remove(pkg: apt_pkg.Package)\n\n"
+ "Mark the package for removal in the resolver."},
+ {"clear", PkgProblemResolverClear, METH_VARARGS,
+ "clear(pkg: apt_pkg.Package)\n\n"
+ "Revert the actions done by protect()/remove() on the package."},
+
+ // Actions
+ {"resolve", PkgProblemResolverResolve, METH_VARARGS,
+ "resolve([fix_broken: bool = True]) -> bool\n\n"
+ "Try to intelligently resolve problems by installing and removing\n"
+ "packages. If 'fix_broken' is True, apt will try to repair broken\n"
+ "dependencies of installed packages."},
+ {"resolve_by_keep", PkgProblemResolverResolveByKeep, METH_VARARGS,
+ "resolve_by_keep() -> bool\n\n"
+ "Try to resolve problems only by using keep."},
+ {"keep_phased_updates", PkgProblemResolverKeepPhasedUpdates, METH_VARARGS,
+ "keep_phased_updates() -> bool\n\n"
+ "Hold back upgrades to phased versions of already installed\n"
+ "packages, unless they are security updates."},
+ {}
+};
+
+static const char *problemresolver_doc =
+ "ProblemResolver(depcache: apt_pkg.DepCache)\n\n"
+ "ProblemResolver objects take care of resolving problems\n"
+ "with dependencies. They mark packages for installation/\n"
+ "removal and try to satisfy all dependencies.";
+PyTypeObject PyProblemResolver_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.ProblemResolver", // tp_name
+ sizeof(CppPyObject<pkgProblemResolver *>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<pkgProblemResolver *>,// tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE |
+ Py_TPFLAGS_HAVE_GC),
+ problemresolver_doc, // tp_doc
+ CppTraverse<pkgProblemResolver *>, // tp_traverse
+ CppClear<pkgProblemResolver *>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PkgProblemResolverMethods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ PkgProblemResolverNew, // tp_new
+};
+
+ /*}}}*/
+
+// pkgActionGroup Class /*{{{*/
+// ---------------------------------------------------------------------
+
+static const char *actiongroup_release_doc =
+ "release()\n\n"
+ "End the scope of this action group. If this is the only action\n"
+ "group bound to the cache, this will cause any deferred cleanup\n"
+ "actions to be performed.";
+static PyObject *PkgActionGroupRelease(PyObject *Self,PyObject *Args)
+{
+ pkgDepCache::ActionGroup *ag = GetCpp<pkgDepCache::ActionGroup*>(Self);
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+ ag->release();
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static const char *actiongroup__enter__doc =
+ "__enter__() -> ActionGroup\n\n"
+ "A dummy action which just returns the object itself, so it can\n"
+ "be used as a context manager.";
+static PyObject *PkgActionGroupEnter(PyObject *Self,PyObject *Args) {
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+ Py_INCREF(Self);
+ return Self;
+}
+
+static const char *actiongroup__exit__doc =
+ "__exit__(*excinfo) -> bool\n\n"
+ "Same as release(), but for use as a context manager.";
+static PyObject *PkgActionGroupExit(PyObject *Self,PyObject *Args) {
+ pkgDepCache::ActionGroup *ag = GetCpp<pkgDepCache::ActionGroup*>(Self);
+ if (ag != NULL)
+ ag->release();
+ Py_RETURN_FALSE;
+}
+
+static PyMethodDef PkgActionGroupMethods[] =
+{
+ {"release", PkgActionGroupRelease, METH_VARARGS, actiongroup_release_doc},
+ {"__enter__", PkgActionGroupEnter, METH_VARARGS, actiongroup__enter__doc},
+ {"__exit__", PkgActionGroupExit, METH_VARARGS, actiongroup__exit__doc},
+ {}
+};
+
+static PyObject *PkgActionGroupNew(PyTypeObject *type,PyObject *Args,PyObject *kwds)
+{
+ PyObject *Owner;
+ char *kwlist[] = {"depcache", 0};
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"O!",kwlist,&PyDepCache_Type,
+ &Owner) == 0)
+ return 0;
+
+ pkgDepCache *depcache = GetCpp<pkgDepCache*>(Owner);
+ pkgDepCache::ActionGroup *group = new pkgDepCache::ActionGroup(*depcache);
+ CppPyObject<pkgDepCache::ActionGroup*> *PkgActionGroupPyObj;
+ PkgActionGroupPyObj = CppPyObject_NEW<pkgDepCache::ActionGroup*>(Owner,
+ type,
+ group);
+ HandleErrors(PkgActionGroupPyObj);
+
+ return PkgActionGroupPyObj;
+
+}
+
+static char *doc_PkgActionGroup = "ActionGroup(depcache)\n\n"
+ "Create a new ActionGroup() object. The parameter *depcache* refers to an\n"
+ "apt_pkg.DepCache() object.\n\n"
+ "ActionGroups disable certain cleanup actions, so modifying many packages\n"
+ "is much faster.\n\n"
+ "ActionGroup() can also be used with the 'with' statement, but be aware\n"
+ "that the ActionGroup() is active as soon as it is created, and not just\n"
+ "when entering the context. This means you can write::\n\n"
+ " with apt_pkg.ActionGroup(depcache):\n"
+ " depcache.markInstall(pkg)\n\n"
+ "Once the block of the with statement is left, the action group is \n"
+ "automatically released from the cache.";
+
+
+PyTypeObject PyActionGroup_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.ActionGroup", // tp_name
+ sizeof(CppPyObject<pkgDepCache::ActionGroup*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<pkgDepCache::ActionGroup*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE |
+ Py_TPFLAGS_HAVE_GC),
+ doc_PkgActionGroup, // tp_doc
+ CppTraverse<pkgDepCache::ActionGroup*>, // tp_traverse
+ CppClear<pkgDepCache::ActionGroup*>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PkgActionGroupMethods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ PkgActionGroupNew, // tp_new
+};
+
+
+
+ /*}}}*/
diff --git a/python/generic.cc b/python/generic.cc
new file mode 100644
index 0000000..16f1cce
--- /dev/null
+++ b/python/generic.cc
@@ -0,0 +1,122 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: generic.cc,v 1.1.1.1 2001/02/20 06:32:01 jgg Exp $
+/* ######################################################################
+
+ generic - Some handy functions to make integration a tad simpler
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "generic.h"
+using namespace std;
+
+
+#include <apt-pkg/error.h>
+ /*}}}*/
+
+// HandleErrors - This moves errors from _error to Python Exceptions /*{{{*/
+// ---------------------------------------------------------------------
+/* We throw away all warnings and only propogate the first error. */
+PyObject *HandleErrors(PyObject *Res)
+{
+ string Err;
+ int errcnt = 0;
+ int wrncnt = 0;
+ while (_error->empty() == false)
+ {
+ string Msg;
+ bool Type = _error->PopMessage(Msg);
+ if (errcnt > 0 || wrncnt > 0)
+ Err.append(", ");
+ Err.append((Type == true ? "E:" : "W:"));
+ Err.append(Msg);
+ if (Type)
+ ++errcnt;
+ else
+ ++wrncnt;
+ }
+ if (errcnt > 0)
+ {
+ PyErr_SetString(PyAptError,Err.c_str());
+ goto err;
+ }
+ else if (wrncnt > 0)
+ {
+ if (PyErr_WarnEx(PyAptWarning, Err.c_str(), 1) == -1)
+ goto err;
+ }
+
+ return Res;
+err:
+ if (Res != 0)
+ Py_DECREF(Res);
+
+ return nullptr;
+}
+
+ /*}}}*/
+// ListToCharChar - Convert a list to an array of char char /*{{{*/
+// ---------------------------------------------------------------------
+/* Caller must free the result. 0 on error. */
+const char **ListToCharChar(PyObject *List,bool NullTerm)
+{
+ // Convert the argument list into a char **
+ int Length = PySequence_Length(List);
+ const char **Res = new const char *[Length + (NullTerm == true?1:0)];
+ for (int I = 0; I != Length; I++)
+ {
+ PyObject *Itm = PySequence_GetItem(List,I);
+ Res[I] = PyObject_AsString(Itm);
+ if (Res[I] == nullptr) {
+ delete [] Res;
+ return nullptr;
+ }
+ }
+ if (NullTerm == true)
+ Res[Length] = 0;
+ return Res;
+}
+ /*}}}*/
+// CharCharToList - Inverse of the above /*{{{*/
+// ---------------------------------------------------------------------
+/* Zero size indicates the list is Null terminated. */
+PyObject *CharCharToList(const char **List,unsigned long Size)
+{
+ if (Size == 0)
+ {
+ for (const char **I = List; *I != 0; I++)
+ Size++;
+ }
+
+ // Convert the whole configuration space into a list
+ PyObject *PList = PyList_New(Size);
+ for (unsigned long I = 0; I != Size; I++, List++)
+ PyList_SetItem(PList,I,CppPyString(*List));
+
+ return PList;
+}
+ /*}}}*/
+
+int PyApt_Filename::init(PyObject *object)
+{
+ this->object = NULL;
+ this->path = NULL;
+
+#if PY_MAJOR_VERSION < 3 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 2)
+ this->path = PyObject_AsString(object);
+ return this->path ? 1 : 0;
+#else
+ if (PyUnicode_Check(object)) {
+ object = PyUnicode_EncodeFSDefault(object);
+ } else if (PyBytes_Check(object)) {
+ Py_INCREF(object);
+ } else {
+ return 0;
+ }
+
+ this->object = object;
+ this->path = PyBytes_AS_STRING(this->object);
+ return 1;
+#endif
+}
diff --git a/python/generic.h b/python/generic.h
new file mode 100644
index 0000000..60f9531
--- /dev/null
+++ b/python/generic.h
@@ -0,0 +1,336 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: generic.h,v 1.4 2002/03/10 05:45:34 mdz Exp $
+/* ######################################################################
+
+ generic - Some handy functions to make integration a tad simpler
+
+ Python needs this little _HEAD tacked onto the front of the object..
+ This complicates the integration with C++. We use some templates to
+ make that quite transparent to us. It would have been nice if Python
+ internally used a page from the C++ ref counting book to hide its little
+ header from the world, but it doesn't.
+
+ The CppPyObject has the target object and the Python header, this is
+ needed to ensure proper alignment.
+ GetCpp returns the C++ object from a PyObject.
+ CppPyObject_NEW creates the Python object and then uses placement new
+ to init the C++ class.. This is good for simple situations and as an
+ example on how to do it in other more specific cases.
+ CppPyObject_Dealloc should be used in the Type as the destructor
+ function.
+ HandleErrors converts errors from the internal _error stack into Python
+ exceptions and makes sure the _error stack is empty.
+
+ ##################################################################### */
+ /*}}}*/
+#ifndef GENERIC_H
+#define GENERIC_H
+
+#include <Python.h>
+#include <string>
+#include <iostream>
+#include <new>
+#include <langinfo.h>
+
+/**
+ * Exception class for almost all Python errors
+ */
+extern PyObject *PyAptError;
+extern PyObject *PyAptWarning;
+/**
+ * Exception class for invalidated cache objects.
+ */
+extern PyObject *PyAptCacheMismatchError;
+
+#if PYTHON_API_VERSION < 1013
+typedef int Py_ssize_t;
+#endif
+
+/* Define compatibility for Python 3.
+ *
+ * We will use the names PyString_* to refer to the default string type
+ * of the current Python version (PyString on 2.X, PyUnicode on 3.X).
+ *
+ * When we really need unicode strings, we will use PyUnicode_* directly, as
+ * long as it exists in Python 2 and Python 3.
+ *
+ * When we want bytes in Python 3, we use PyBytes*_ instead of PyString_* and
+ * define aliases from PyBytes_* to PyString_* for Python 2.
+ */
+
+#if PY_MAJOR_VERSION >= 3
+#define PyString_Check PyUnicode_Check
+#define PyString_FromString PyUnicode_FromString
+#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
+#define PyString_AsString PyUnicode_AsString
+#define PyString_FromFormat PyUnicode_FromFormat
+#define PyString_Type PyUnicode_Type
+#define PyInt_Check PyLong_Check
+#define PyInt_AsLong PyLong_AsLong
+#define PyInt_FromLong PyLong_FromLong
+#endif
+
+static inline const char *PyUnicode_AsString(PyObject *op) {
+ // Convert to bytes object, using the default encoding.
+#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
+ return PyUnicode_AsUTF8(op);
+#else
+ // Use Python-internal API, there is no other way to do this
+ // without a memory leak.
+ PyObject *bytes = _PyUnicode_AsDefaultEncodedString(op, 0);
+ return bytes ? PyBytes_AS_STRING(bytes) : 0;
+#endif
+}
+
+// Convert any type of string based object to a const char.
+#if PY_MAJOR_VERSION < 3
+static inline const char *PyObject_AsString(PyObject *object) {
+ if (PyBytes_Check(object))
+ return PyBytes_AsString(object);
+ else if (PyUnicode_Check(object))
+ return PyUnicode_AsString(object);
+ else
+ PyErr_SetString(PyExc_TypeError, "Argument must be str.");
+ return 0;
+}
+#else
+static inline const char *PyObject_AsString(PyObject *object) {
+ if (PyUnicode_Check(object) == 0) {
+ PyErr_SetString(PyExc_TypeError, "Argument must be str.");
+ return 0;
+ }
+ return PyUnicode_AsString(object);
+}
+#endif
+
+template <class T> struct CppPyObject : public PyObject
+{
+ // We are only using CppPyObject and friends as dumb structs only, ie the
+ // c'tor is never called.
+ // However if T doesn't have a default c'tor C++ doesn't generate one for
+ // CppPyObject (since it can't know how it should initialize Object).
+ //
+ // This causes problems then in CppPyObject, for which C++ can't create
+ // a c'tor that calls the base class c'tor (which causes a compilation
+ // error).
+ // So basically having the c'tor here removes the need for T to have a
+ // default c'tor, which is not always desireable.
+ CppPyObject() { };
+
+ // The owner of the object. The object keeps a reference to it during its
+ // lifetime.
+ PyObject *Owner;
+
+ // Flag which causes the underlying object to not be deleted.
+ bool NoDelete;
+
+ // The underlying C++ object.
+ T Object;
+};
+
+template <class T>
+inline T &GetCpp(PyObject *Obj)
+{
+ return ((CppPyObject<T> *)Obj)->Object;
+}
+
+template <class T>
+inline PyObject *GetOwner(PyObject *Obj)
+{
+ return ((CppPyObject<T> *)Obj)->Owner;
+}
+
+
+template <class T>
+inline CppPyObject<T> *CppPyObject_NEW(PyObject *Owner,PyTypeObject *Type)
+{
+ #ifdef ALLOC_DEBUG
+ std::cerr << "=== ALLOCATING " << Type->tp_name << "+ ===\n";
+ #endif
+ CppPyObject<T> *New = (CppPyObject<T>*)Type->tp_alloc(Type, 0);
+ new (&New->Object) T;
+ New->Owner = Owner;
+ Py_XINCREF(Owner);
+ return New;
+}
+
+template <class T,class A>
+inline CppPyObject<T> *CppPyObject_NEW(PyObject *Owner, PyTypeObject *Type,A const &Arg)
+{
+ #ifdef ALLOC_DEBUG
+ std::cerr << "=== ALLOCATING " << Type->tp_name << "+ ===\n";
+ #endif
+ CppPyObject<T> *New = (CppPyObject<T>*)Type->tp_alloc(Type, 0);
+ new (&New->Object) T(Arg);
+ New->Owner = Owner;
+ Py_XINCREF(Owner);
+ return New;
+}
+
+// Traversal and Clean for objects
+template <class T>
+int CppTraverse(PyObject *self, visitproc visit, void* arg) {
+ Py_VISIT(((CppPyObject<T> *)self)->Owner);
+ return 0;
+}
+
+template <class T>
+int CppClear(PyObject *self) {
+ Py_CLEAR(((CppPyObject<T> *)self)->Owner);
+ return 0;
+}
+
+template <class T>
+void CppDealloc(PyObject *iObj)
+{
+ #ifdef ALLOC_DEBUG
+ std::cerr << "=== DEALLOCATING " << iObj->ob_type->tp_name << "+ ===\n";
+ #endif
+ if (iObj->ob_type->tp_flags & Py_TPFLAGS_HAVE_GC)
+ PyObject_GC_UnTrack(iObj);
+ CppPyObject<T> *Obj = (CppPyObject<T> *)iObj;
+ if (!((CppPyObject<T>*)Obj)->NoDelete)
+ Obj->Object.~T();
+ CppClear<T>(iObj);
+ iObj->ob_type->tp_free(iObj);
+}
+
+
+template <class T>
+void CppDeallocPtr(PyObject *iObj)
+{
+ #ifdef ALLOC_DEBUG
+ std::cerr << "=== DEALLOCATING " << iObj->ob_type->tp_name << "*+ ===\n";
+ #endif
+ if (iObj->ob_type->tp_flags & Py_TPFLAGS_HAVE_GC)
+ PyObject_GC_UnTrack(iObj);
+ CppPyObject<T> *Obj = (CppPyObject<T> *)iObj;
+ if (!((CppPyObject<T>*)Obj)->NoDelete) {
+ delete Obj->Object;
+ Obj->Object = NULL;
+ }
+ CppClear<T>(iObj);
+ iObj->ob_type->tp_free(iObj);
+}
+
+inline PyObject *CppPyString(const std::string &Str)
+{
+ return PyString_FromStringAndSize(Str.c_str(),Str.length());
+}
+
+inline PyObject *CppPyString(const char *Str)
+{
+ if (Str == 0)
+ return PyString_FromString("");
+ return PyString_FromString(Str);
+}
+
+inline PyObject *CppPyLocaleString(const std::string &Str)
+{
+ char const * const codeset = nl_langinfo(CODESET);
+ return PyUnicode_Decode(Str.c_str(), Str.length(), codeset, "replace");
+}
+
+#if PY_MAJOR_VERSION >= 3
+static inline PyObject *CppPyPath(const std::string &path)
+{
+ return PyUnicode_DecodeFSDefaultAndSize(path.c_str(), path.length());
+}
+
+static inline PyObject *CppPyPath(const char *path)
+{
+ if (path == nullptr)
+ path = "";
+ return PyUnicode_DecodeFSDefault(path);
+}
+#else
+template<typename T> static inline PyObject *CppPyPath(T path) {
+ return CppPyString(path);
+}
+#endif
+
+// Convert _error into Python exceptions
+PyObject *HandleErrors(PyObject *Res = 0);
+
+// Convert a list of strings to a char **
+const char **ListToCharChar(PyObject *List,bool NullTerm = false);
+PyObject *CharCharToList(const char **List,unsigned long Size = 0);
+
+/* Happy number conversion, thanks to overloading */
+inline PyObject *MkPyNumber(unsigned long long o) { return PyLong_FromUnsignedLongLong(o); }
+inline PyObject *MkPyNumber(unsigned long o) { return PyLong_FromUnsignedLong(o); }
+inline PyObject *MkPyNumber(unsigned int o) { return PyLong_FromUnsignedLong(o); }
+inline PyObject *MkPyNumber(unsigned short o) { return PyInt_FromLong(o); }
+inline PyObject *MkPyNumber(unsigned char o) { return PyInt_FromLong(o); }
+
+inline PyObject *MkPyNumber(long long o) { return PyLong_FromLongLong(o); }
+inline PyObject *MkPyNumber(long o) { return PyInt_FromLong(o); }
+inline PyObject *MkPyNumber(int o) { return PyInt_FromLong(o); }
+inline PyObject *MkPyNumber(short o) { return PyInt_FromLong(o); }
+inline PyObject *MkPyNumber(signed char o) { return PyInt_FromLong(o); }
+
+inline PyObject *MkPyNumber(double o) { return PyFloat_FromDouble(o); }
+
+# define _PyAptObject_getattro 0
+
+
+/**
+ * Magic class for file name handling
+ *
+ * This manages decoding file names from Python objects; bytes and unicode
+ * objects. On Python 2, this does the same conversion as PyObject_AsString,
+ * on Python3, it uses PyUnicode_EncodeFSDefault for unicode objects.
+ */
+class PyApt_Filename {
+public:
+ PyObject *object;
+ const char *path;
+
+ PyApt_Filename() {
+ object = NULL;
+ path = NULL;
+ }
+
+ int init(PyObject *object);
+
+ ~PyApt_Filename() {
+ Py_XDECREF(object);
+ }
+
+ static int Converter(PyObject *object, void *out) {
+ return static_cast<PyApt_Filename *>(out)->init(object);
+ }
+
+ operator const char *() {
+ return path;
+ }
+ operator const std::string() {
+ return path;
+ }
+
+ const char *operator=(const char *path) {
+ return this->path = path;
+ }
+};
+
+
+/**
+ * Basic smart pointer to hold initial objects.
+ *
+ * This is like a std::unique_ptr<PyObject, decltype(&Py_DecRef)> to some extend,
+ * but it is for initialization only, and hence will also clear out any members
+ * in case it deletes the instance (the error case).
+ */
+template <class T, bool clear=true> struct PyApt_UniqueObject {
+ T *self;
+ explicit PyApt_UniqueObject(T *self) : self(self) { }
+ ~PyApt_UniqueObject() { reset(NULL); }
+ void reset(T *newself) { if (clear && self && Py_TYPE(self)->tp_clear) Py_TYPE(self)->tp_clear(self); Py_XDECREF(self); self = newself; }
+ PyApt_UniqueObject<T> operator =(PyApt_UniqueObject<T>) = delete;
+ bool operator ==(void *other) { return self == other; }
+ T *operator ->() { return self; }
+ T *get() { return self; }
+ T *release() { T *ret = self; self = NULL; return ret; }
+};
+#endif
diff --git a/python/hashes.cc b/python/hashes.cc
new file mode 100644
index 0000000..9f3fb46
--- /dev/null
+++ b/python/hashes.cc
@@ -0,0 +1,135 @@
+/* hashes.cc - Wrapper around apt-pkg's Hashes.
+ *
+ * Copyright 2009 Julian Andres Klode <jak@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+#include <Python.h>
+#include "generic.h"
+#include "apt_pkgmodule.h"
+#include <apt-pkg/hashes.h>
+
+static PyObject *hashes_new(PyTypeObject *type,PyObject *args,
+ PyObject *kwds)
+{
+ return CppPyObject_NEW<Hashes>(NULL, type);
+}
+
+static int hashes_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *object = 0;
+ int Fd;
+ char *kwlist[] = {"object", NULL};
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "|O:__init__", kwlist,
+ &object) == 0)
+ return -1;
+ if (object == 0)
+ return 0;
+ Hashes &hashes = GetCpp<Hashes>(self);
+
+ if (PyBytes_Check(object) != 0) {
+ char *s;
+ Py_ssize_t len;
+ PyBytes_AsStringAndSize(object, &s, &len);
+ Py_BEGIN_ALLOW_THREADS
+ hashes.Add((const unsigned char*)s, len);
+ Py_END_ALLOW_THREADS
+ }
+ else if ((Fd = PyObject_AsFileDescriptor(object)) != -1) {
+ struct stat St;
+ bool err = false;
+ Py_BEGIN_ALLOW_THREADS
+ err = fstat(Fd, &St) != 0 || hashes.AddFD(Fd, St.st_size) == false;
+ Py_END_ALLOW_THREADS
+ if (err) {
+ PyErr_SetFromErrno(PyAptError);
+ return -1;
+ }
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError,
+ "__init__() only understand bytes and files");
+ return -1;
+ }
+ return 0;
+}
+
+static PyObject *hashes_get_hashes(PyObject *self, void*)
+{
+ auto py = CppPyObject_NEW<HashStringList>(nullptr, &PyHashStringList_Type);
+
+ py->Object = GetCpp<Hashes>(self).GetHashStringList();
+ return py;
+}
+
+
+static PyGetSetDef hashes_getset[] = {
+ {"hashes",hashes_get_hashes,0,
+ "A :class:`HashStringList` of all hashes.\n\n"
+ ".. versionadded:: 1.1"},
+ {}
+};
+
+static char *hashes_doc =
+ "Hashes([object: (bytes, file)])\n\n"
+ "Calculate hashes for the given object. It can be used to create all\n"
+ "supported hashes for a file.\n\n"
+ "The parameter *object* can be a bytestring, an object providing the\n"
+ "fileno() method, or an integer describing a file descriptor.";
+
+PyTypeObject PyHashes_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Hashes", // tp_name
+ sizeof(CppPyObject<Hashes>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<Hashes>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE,
+ hashes_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ hashes_getset, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ hashes_init, // tp_init
+ 0, // tp_alloc
+ hashes_new, // tp_new
+};
diff --git a/python/hashstring.cc b/python/hashstring.cc
new file mode 100644
index 0000000..01f14a0
--- /dev/null
+++ b/python/hashstring.cc
@@ -0,0 +1,182 @@
+/* hashstring.cc - Wrapper around HashString
+ *
+ * Copyright 2009 Julian Andres Klode <jak@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+#include <Python.h>
+#include "generic.h"
+#include "apt_pkgmodule.h"
+#include <apt-pkg/hashes.h>
+
+static PyObject *hashstring_new(PyTypeObject *type,PyObject *Args,
+ PyObject *kwds)
+{
+ char *Type = NULL;
+ char *Hash = NULL;
+ char *kwlist[] = {"type", "hash", NULL};
+ if (PyArg_ParseTupleAndKeywords(Args, kwds, "s|s:__new__", kwlist, &Type,
+ &Hash) == 0)
+ return 0;
+ CppPyObject<HashString*> *PyObj = CppPyObject_NEW<HashString*>(NULL, type);
+ if (Hash)
+ PyObj->Object = new HashString(Type,Hash);
+ else // Type is the combined form now (i.e. type:hash)
+ PyObj->Object = new HashString(Type);
+ return PyObj;
+}
+
+static PyObject *hashstring_repr(PyObject *self)
+{
+ HashString *hash = GetCpp<HashString*>(self);
+ return PyString_FromFormat("<%s object: \"%s\">", self->ob_type->tp_name,
+ hash->toStr().c_str());
+}
+
+static PyObject *hashstring_str(PyObject *self)
+{
+ const HashString *hash = GetCpp<HashString*>(self);
+ return CppPyString(hash->toStr());
+}
+
+static PyObject *hashstring_get_hashtype(PyObject *self)
+{
+ const HashString *hash = GetCpp<HashString*>(self);
+ return CppPyString(hash->HashType());
+}
+
+static PyObject *hashstring_get_usable(PyObject *self)
+{
+ const HashString *hash = GetCpp<HashString*>(self);
+ return PyBool_FromLong(hash->usable());
+}
+
+static PyObject *hashstring_get_hashvalue(PyObject *self)
+{
+ const HashString *hash = GetCpp<HashString*>(self);
+ return CppPyString(hash->HashValue());
+}
+
+static char *hashstring_verify_file_doc =
+ "verify_file(filename: str) -> bool\n\n"
+ "Verify that the file indicated by filename matches the hash.";
+
+static PyObject *hashstring_verify_file(PyObject *self,PyObject *args)
+{
+ const HashString *hash = GetCpp<HashString*>(self);
+ char *filename;
+ if (PyArg_ParseTuple(args, "s:verify_file", &filename) == 0)
+ return 0;
+ return PyBool_FromLong(hash->VerifyFile(filename));
+}
+
+static PyMethodDef hashstring_methods[] = {
+ {"verify_file",hashstring_verify_file,METH_VARARGS,
+ hashstring_verify_file_doc},
+ {NULL}
+};
+
+static PyGetSetDef hashstring_getset[] = {
+ {"hashtype",(getter)hashstring_get_hashtype,0,
+ "The type of the hash, as a string (possible: MD5Sum,SHA1,SHA256)."},
+ {"hashvalue",(getter)hashstring_get_hashvalue,0,
+ "The value of the hash, as a hexadecimal string\n"
+ "\n"
+ ".. versionadded:: 1.9.0"},
+ {"usable",(getter)hashstring_get_usable,0,
+ "True if the hashstring is a trusted hash type."},
+ {NULL}
+};
+
+static PyObject *hashstring_richcompare(PyObject *obj1, PyObject *obj2, int op)
+{
+ if (!PyObject_TypeCheck(obj1, &PyHashString_Type))
+ return PyErr_SetString(PyExc_TypeError, "Expected HashString"), nullptr;
+ if (!PyObject_TypeCheck(obj2, &PyHashString_Type))
+ return PyErr_SetString(PyExc_TypeError, "Expected HashString"), nullptr;
+
+ const HashString *a = GetCpp<HashString*>(obj1);
+ const HashString *b = GetCpp<HashString*>(obj2);
+ PyObject *result = Py_False;
+
+ switch (op) {
+ case Py_LT:
+ case Py_GT:
+ result = Py_False;
+ break;
+ case Py_LE:
+ case Py_GE:
+ case Py_EQ:
+ result = *a == *b ? Py_True : Py_False;
+ break;
+ case Py_NE:
+ result = *a != *b ? Py_True : Py_False;
+ break;
+ }
+
+ Py_INCREF(result);
+ return result;
+ }
+
+static char *hashstring_doc =
+ "HashString(type, hash) OR HashString('type:hash')\n\n"
+ "Create a new HashString object. The first form allows you to specify\n"
+ "a type and a hash, and the second form a single string where type and\n"
+ "hash are separated by a colon, e.g.::\n\n"
+ " HashString('MD5Sum', '6cc1b6e6655e3555ac47e5b5fe26d04e')\n\n"
+ "Valid options for 'type' are: MD5Sum, SHA1, SHA256.";
+PyTypeObject PyHashString_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.HashString", // tp_name
+ sizeof(CppPyObject<HashString*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<HashString*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ hashstring_repr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ hashstring_str, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE,
+ hashstring_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ hashstring_richcompare, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ hashstring_methods, // tp_methods
+ 0, // tp_members
+ hashstring_getset, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ hashstring_new, // tp_new
+};
diff --git a/python/hashstringlist.cc b/python/hashstringlist.cc
new file mode 100644
index 0000000..f25f502
--- /dev/null
+++ b/python/hashstringlist.cc
@@ -0,0 +1,220 @@
+/* hashstringlist.cc - Wrapper around apt-pkg's Hashes.
+ *
+ * Copyright 2015 Julian Andres Klode <jak@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+#include <Python.h>
+#include "generic.h"
+#include "apt_pkgmodule.h"
+#include <apt-pkg/hashes.h>
+
+static PyObject *hashstringlist_new(PyTypeObject *type, PyObject *args,
+ PyObject *kwds)
+{
+ return CppPyObject_NEW<HashStringList> (nullptr, type);
+}
+
+static int hashstringlist_init(PyObject *self, PyObject *args,
+ PyObject *kwds)
+{
+ char *kwlist[] = { NULL };
+
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist) == 0)
+ return -1;
+
+ return 0;
+}
+
+
+static const char hashstringlist_find_doc[] =
+ "find(type: str = \"\") -> HashString\n\n"
+ "Find a hash of the given type, or the best one, if the argument\n"
+ "is empty or not specified.";
+static PyObject *hashstringlist_find(PyObject *self, PyObject *args)
+{
+ char *type = "";
+
+ if (PyArg_ParseTuple(args, "|s", &type) == 0)
+ return 0;
+
+ const HashString *hsf = GetCpp<HashStringList>(self).find(type);
+ if (hsf == nullptr)
+ return PyErr_Format(PyExc_KeyError, "Could not find hash type %s", type);
+
+
+ return HandleErrors(PyHashString_FromCpp(new HashString(*hsf), true, nullptr));
+}
+
+static const char hashstringlist_append_doc[] =
+ "append(object: HashString)\n\n"
+ "Append the given HashString to this list.";
+static PyObject *hashstringlist_append(PyObject *self, PyObject *args)
+{
+ PyObject *o;
+
+ if (PyArg_ParseTuple(args, "O!", &PyHashString_Type, &o) == 0)
+ return 0;
+
+ GetCpp<HashStringList>(self).push_back(*PyHashString_ToCpp(o));
+ Py_RETURN_NONE;
+}
+
+static const char hashstringlist_verify_file_doc[] =
+ "verify_file(filename: str) -> bool\n\n"
+ "Verify that the file with the given name matches all hashes in\n"
+ "the list.";
+static PyObject *hashstringlist_verify_file(PyObject *self, PyObject *args)
+{
+ PyApt_Filename filename;
+
+ if (PyArg_ParseTuple(args, "O&", PyApt_Filename::Converter, &filename) == 0)
+ return 0;
+
+ bool res = GetCpp<HashStringList>(self).VerifyFile(filename);
+
+ PyObject *PyRes = PyBool_FromLong(res);
+ return HandleErrors(PyRes);
+}
+
+static PyObject *hashstringlist_get_file_size(PyObject *self, void*) {
+ return MkPyNumber(GetCpp<HashStringList>(self).FileSize());
+}
+static PyObject *hashstringlist_get_usable(PyObject *self, void*) {
+ return PyBool_FromLong(GetCpp<HashStringList>(self).usable());
+}
+
+static int hashstringlist_set_file_size(PyObject *self, PyObject *value, void *) {
+ if (PyLong_Check(value)) {
+ if (PyLong_AsUnsignedLongLong(value) == (unsigned long long) -1) {
+ return 1;
+ }
+ GetCpp<HashStringList>(self).FileSize(PyLong_AsUnsignedLongLong(value));
+ } else if (PyInt_Check(value)) {
+ if (PyInt_AsLong(value) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_OverflowError,
+ "The file_size value must be positive");
+ return 1;
+ }
+ GetCpp<HashStringList>(self).FileSize(PyInt_AsLong(value));
+ } else {
+ PyErr_SetString(PyExc_TypeError,
+ "The file_size value must be an integer or long");
+ return 1;
+ }
+
+ return 0;
+}
+
+/* The same for groups */
+static Py_ssize_t hashstringlist_len(PyObject *self)
+{
+ return GetCpp <HashStringList>(self).size();
+}
+
+static PyObject *hashstringlist_getitem(PyObject *iSelf, Py_ssize_t index)
+{
+ HashStringList &self = GetCpp<HashStringList>(iSelf);
+
+ if (index < 0 || (size_t) index >= self.size())
+ return PyErr_Format(PyExc_IndexError, "Out of range: %zd", index);
+
+ /* Copy over, safer than using a reference to the vector element */
+ HashString *hs = new HashString;
+ (*hs) = *(self.begin() + index);
+
+ return PyHashString_FromCpp(hs, true, nullptr);
+}
+
+static PySequenceMethods hashstringlist_seq_methods = {
+ hashstringlist_len,
+ 0, // concat
+ 0, // repeat
+ hashstringlist_getitem,
+ 0, // slice
+ 0, // assign item
+ 0 // assign slice
+};
+
+static PyMethodDef hashstringlist_methods[] =
+{
+ {"verify_file",hashstringlist_verify_file,METH_VARARGS,
+ hashstringlist_verify_file_doc},
+ {"find",hashstringlist_find,METH_VARARGS,
+ hashstringlist_find_doc},
+ {"append",hashstringlist_append,METH_VARARGS,
+ hashstringlist_append_doc},
+ {}
+};
+
+static PyGetSetDef hashstringlist_getset[] = {
+ {"file_size",hashstringlist_get_file_size,hashstringlist_set_file_size,
+ "If a file size is part of the list, return it, otherwise 0."},
+ {"usable",hashstringlist_get_usable,nullptr,
+ "True if at least one safe/trusted hash is in the list."},
+ {}
+};
+
+
+static char *hashstringlist_doc =
+ "HashStringList()\n\n"
+ "Manage a list of HashStrings.\n\n"
+ "The list knows which hash is the best and provides convenience\n"
+ "methods for file verification.\n\n"
+ ".. versionadded:: 1.1";
+
+PyTypeObject PyHashStringList_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.HashStringList", // tp_name
+ sizeof(CppPyObject<HashStringList>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<HashStringList>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &hashstringlist_seq_methods, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flags
+ hashstringlist_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ hashstringlist_methods, // tp_methods
+ 0, // tp_members
+ hashstringlist_getset, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ hashstringlist_init, // tp_init
+ 0, // tp_alloc
+ hashstringlist_new, // tp_new
+};
diff --git a/python/indexfile.cc b/python/indexfile.cc
new file mode 100644
index 0000000..423e2e3
--- /dev/null
+++ b/python/indexfile.cc
@@ -0,0 +1,130 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: indexfile.cc,v 1.2 2003/12/26 17:04:22 mdz Exp $
+/* ######################################################################
+
+ pkgIndexFile - Wrapper for the pkgIndexFilefunctions
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "generic.h"
+#include "apt_pkgmodule.h"
+
+#include <apt-pkg/indexfile.h>
+
+#include <Python.h>
+
+static PyObject *IndexFileArchiveURI(PyObject *Self,PyObject *Args)
+{
+ pkgIndexFile *File = GetCpp<pkgIndexFile*>(Self);
+ PyApt_Filename path;
+
+ if (PyArg_ParseTuple(Args, "O&", PyApt_Filename::Converter, &path) == 0)
+ return 0;
+ return HandleErrors(CppPyString(File->ArchiveURI(path).c_str()));
+}
+
+static PyMethodDef IndexFileMethods[] =
+{
+ {"archive_uri",IndexFileArchiveURI,METH_VARARGS,
+ "archive_uri(path: str) -> str\n\n"
+ "Return the URI to the given path in the archive."},
+ {}
+};
+
+#define File (GetCpp<pkgIndexFile*>(Self))
+static PyObject *IndexFileGetLabel(PyObject *Self,void*) {
+ return CppPyString(File->GetType()->Label);
+}
+static PyObject *IndexFileGetDescribe(PyObject *Self,void*) {
+ return CppPyString(File->Describe().c_str());
+}
+static PyObject *IndexFileGetExists(PyObject *Self,void*) {
+ return PyBool_FromLong((File->Exists()));
+}
+static PyObject *IndexFileGetHasPackages(PyObject *Self,void*) {
+ return PyBool_FromLong((File->HasPackages()));
+}
+static PyObject *IndexFileGetSize(PyObject *Self,void*) {
+ return MkPyNumber((File->Size()));
+}
+static PyObject *IndexFileGetIsTrusted(PyObject *Self,void*) {
+ return PyBool_FromLong((File->IsTrusted()));
+}
+#undef File
+
+#define S(x) (x ? x : "")
+static PyObject *IndexFileRepr(PyObject *Self)
+{
+ pkgIndexFile *File = GetCpp<pkgIndexFile*>(Self);
+ return PyString_FromFormat("<pkIndexFile object: "
+ "Label:'%s' Describe='%s' Exists='%i' "
+ "HasPackages='%i' Size='%lu' "
+ "IsTrusted='%i' ArchiveURI='%s'>",
+ S(File->GetType()->Label), File->Describe().c_str(), File->Exists(),
+ File->HasPackages(), File->Size(),
+ File->IsTrusted(), File->ArchiveURI("").c_str());
+}
+#undef S
+
+static PyGetSetDef IndexFileGetSet[] = {
+ {"describe",IndexFileGetDescribe,0,
+ "A string describing the index file."},
+ {"exists",IndexFileGetExists,0,
+ "A boolean value determining whether the index file exists."},
+ {"has_packages",IndexFileGetHasPackages,0,
+ "A boolean value determining whether the index file has packages."},
+ {"is_trusted",IndexFileGetIsTrusted,0,
+ "A boolean value determining whether the file can be trusted; e.g.\n"
+ "because it is from a source with a GPG signed Release file."},
+ {"label",IndexFileGetLabel,0,
+ "The label of the index file."},
+ {"size",IndexFileGetSize,0,
+ "The size of the files, measured in bytes."},
+ {}
+};
+
+static const char *indexfile_doc =
+ "Represent an index file, i.e. package indexes, translation indexes,\n"
+ "and source indexes.";
+
+PyTypeObject PyIndexFile_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.IndexFile", // tp_name
+ sizeof(CppPyObject<pkgIndexFile*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ // Not ..Ptr, because the pointer is managed somewhere else.
+ CppDeallocPtr<pkgIndexFile*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ IndexFileRepr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
+ indexfile_doc, // tp_doc
+ CppTraverse<pkgIndexFile*>, // tp_traverse
+ CppClear<pkgIndexFile*>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ IndexFileMethods, // tp_methods
+ 0, // tp_members
+ IndexFileGetSet, // tp_getset
+};
+
+
+
+
diff --git a/python/lock.cc b/python/lock.cc
new file mode 100644
index 0000000..009605e
--- /dev/null
+++ b/python/lock.cc
@@ -0,0 +1,268 @@
+/*
+ * lock.cc - Context managers for implementing locking.
+ *
+ * Copyright 2009 Julian Andres Klode <jak@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+#include <Python.h>
+#include <apt-pkg/init.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/fileutl.h>
+#include <apt-pkg/pkgsystem.h>
+#include "generic.h"
+
+static PyObject *systemlock_exit(PyObject *self, PyObject *args)
+{
+
+ PyObject *exc_type = 0;
+ PyObject *exc_value = 0;
+ PyObject *traceback = 0;
+ if (!PyArg_UnpackTuple(args, "__exit__", 3, 3, &exc_type, &exc_value,
+ &traceback)) {
+ return 0;
+ }
+
+ if (_system->UnLock() == 0) {
+ // The unlock failed. If no exception happened within the suite, we
+ // will raise an error here. Otherwise, we just display the error, so
+ // Python can handle the original exception instead.
+ HandleErrors();
+ if (exc_type == Py_None)
+ return NULL;
+ else
+ PyErr_WriteUnraisable(self);
+ }
+ // Return False, as required by the context manager protocol.
+ Py_RETURN_FALSE;
+}
+
+static PyObject *systemlock_enter(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+ if (!_system->Lock())
+ return HandleErrors();
+ Py_INCREF(self);
+ return self;
+}
+
+static PyObject *systemlock_new(PyTypeObject *type, PyObject *args,
+ PyObject *kwds)
+{
+ if (_system == 0) {
+ PyErr_SetString(PyExc_ValueError,"_system not initialized");
+ return 0;
+ }
+ return PyType_GenericNew(type,args,kwds);
+}
+
+static PyMethodDef systemlock_methods[] = {
+ {"__enter__",systemlock_enter,METH_VARARGS,"Lock the system."},
+ {"__exit__",systemlock_exit,METH_VARARGS,"Unlock the system."},
+ {NULL}
+};
+
+static char *systemlock_doc = "SystemLock()\n\n"
+ "Context manager for locking the package system. The lock is established\n"
+ "as soon as the method __enter__() is called. It is released when\n"
+ "__exit__() is called.\n\n"
+ "This should be used via the 'with' statement, for example:\n\n"
+ " with apt_pkg.SystemLock():\n"
+ " ...\n\n"
+ "Once the block is left, the lock is released automatically. The object\n"
+ "can be used multiple times:\n\n"
+ " lock = apt_pkg.SystemLock()\n"
+ " with lock:\n"
+ " ...\n"
+ " with lock:\n"
+ " ...\n\n";
+
+PyTypeObject PySystemLock_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.SystemLock", // tp_name
+ 0, // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ 0, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE),
+ systemlock_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ systemlock_methods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ systemlock_new, // tp_new
+};
+
+
+/**
+ * File Based locking.
+ *
+ * The counter is increased by every call to filelock_enter() and decreased by
+ * every call to filelock_exit(). When the counter reaches 0, the underlying
+ * file descriptor is closed.
+ *
+ * Members:
+ * @member char* filename The name of the file
+ * @member int lock_count How many times we have locked it.
+ * @member int fd The filedescriptor returned by GetLock() or 0.
+ */
+struct filelock_object {
+ PyObject_HEAD
+ char *filename;
+ int lock_count;
+ int fd;
+};
+
+static PyObject *filelock_enter(filelock_object *self, PyObject *args)
+{
+ self->lock_count++;
+ // If we have no lock yet, get a lock.
+ if (self->lock_count == 1) {
+ self->fd = GetLock(self->filename, true);
+ if (self->fd == -1) {
+ self->lock_count--;
+ return HandleErrors();
+ }
+ }
+ Py_INCREF(self);
+ return (PyObject *)self;
+}
+
+static PyObject *filelock_exit(filelock_object *self, PyObject *args)
+{
+ // Count down the lock_count, if it is less than 0, reset it to 0.
+ self->lock_count--;
+ if (self->lock_count < 0)
+ self->lock_count = 0;
+ if (self->lock_count == 0 && self->fd != 0 && close(self->fd) == -1) {
+ return PyErr_SetFromErrno(PyExc_OSError);
+ }
+ Py_RETURN_FALSE;
+}
+
+static PyObject *filelock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ PyApt_Filename filename;
+ char *kwlist[] = {"filename", NULL};
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O&:__init__", kwlist,
+ PyApt_Filename::Converter,
+ &filename) == 0) {
+ return NULL;
+ }
+ filelock_object *self = (filelock_object *)type->tp_alloc(type, 0);
+ // Copy the string into the object.
+ self->filename = new char[strlen(filename) + 1];
+ strcpy(self->filename, filename);
+ return (PyObject *)self;
+}
+
+static void filelock_dealloc(filelock_object *self)
+{
+ delete[] self->filename;
+ ((PyObject*)self)->ob_type->tp_free(self);
+}
+
+static PyMethodDef filelock_methods[] = {
+ {"__enter__",(PyCFunction)filelock_enter,METH_VARARGS,"Lock the system."},
+ {"__exit__",(PyCFunction)filelock_exit,METH_VARARGS,"Unlock the system."},
+ {NULL}
+};
+
+static char *filelock_doc = "FileLock(filename: str)\n\n"
+ "Context manager for locking using a file. The lock is established\n"
+ "as soon as the method __enter__() is called. It is released when\n"
+ "__exit__() is called.\n\n"
+ "This should be used via the 'with' statement, for example:\n\n"
+ " with apt_pkg.FileLock(filename):\n"
+ " ...\n\n"
+ "Once the block is left, the lock is released automatically. The object\n"
+ "can be used multiple times:\n\n"
+ " lock = apt_pkg.FileLock(filename)\n"
+ " with lock:\n"
+ " ...\n"
+ " with lock:\n"
+ " ...\n\n";
+
+PyTypeObject PyFileLock_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.FileLock", // tp_name
+ sizeof(filelock_object), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ destructor(filelock_dealloc), // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE),
+ filelock_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ filelock_methods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ filelock_new, // tp_new
+};
diff --git a/python/metaindex.cc b/python/metaindex.cc
new file mode 100644
index 0000000..abbcb8a
--- /dev/null
+++ b/python/metaindex.cc
@@ -0,0 +1,117 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: metaindex.cc,v 1.2 2003/12/26 17:04:22 mdz Exp $
+/* ######################################################################
+
+ metaindex - Wrapper for the metaIndex functions
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "generic.h"
+#include "apt_pkgmodule.h"
+
+#include <apt-pkg/metaindex.h>
+
+#include <Python.h>
+
+static PyObject *MetaIndexGetURI(PyObject *Self,void*) {
+ metaIndex *meta = GetCpp<metaIndex*>(Self);
+ return CppPyString(meta->GetURI().c_str());
+}
+
+static PyObject *MetaIndexGetDist(PyObject *Self,void*) {
+ metaIndex *meta = GetCpp<metaIndex*>(Self);
+ return CppPyString(meta->GetDist().c_str());
+}
+
+static PyObject *MetaIndexGetIsTrusted(PyObject *Self,void*) {
+ metaIndex *meta = GetCpp<metaIndex*>(Self);
+ return PyBool_FromLong((meta->IsTrusted()));
+}
+
+static PyObject *MetaIndexGetType(PyObject *Self,void*) {
+ metaIndex *meta = GetCpp<metaIndex*>(Self);
+ return CppPyString(meta->GetType());
+}
+
+static PyObject *MetaIndexGetIndexFiles(PyObject *Self,void*) {
+ metaIndex *meta = GetCpp<metaIndex*>(Self);
+ PyObject *List = PyList_New(0);
+ std::vector<pkgIndexFile *> *indexFiles = meta->GetIndexFiles();
+ for (std::vector<pkgIndexFile *>::const_iterator I = indexFiles->begin();
+ I != indexFiles->end(); I++)
+ {
+ CppPyObject<pkgIndexFile*> *Obj;
+ Obj = CppPyObject_NEW<pkgIndexFile*>(Self, &PyIndexFile_Type,*I);
+ // Do not delete pkgIndexFile*, they are managed by metaIndex.
+ Obj->NoDelete = true;
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+static PyGetSetDef MetaIndexGetSet[] = {
+ {"dist",MetaIndexGetDist,0,"The distribution, as a string."},
+ {"index_files",MetaIndexGetIndexFiles,0,
+ "A list of all IndexFile objects associated with this meta index."},
+ {"is_trusted",MetaIndexGetIsTrusted,0,
+ "A boolean value determining whether the file can be trusted."},
+ {"uri",MetaIndexGetURI,0,
+ "The uri the meta index is located at."},
+ {"type",MetaIndexGetType,0,
+ "The type of the meta index."},
+ {}
+};
+
+#define S(x) (x ? x : "")
+static PyObject *MetaIndexRepr(PyObject *Self)
+{
+ metaIndex *meta = GetCpp<metaIndex*>(Self);
+ return PyString_FromFormat("<%s object: type='%s', uri:'%s' dist='%s' "
+ "is_trusted='%i'>", Self->ob_type->tp_name,
+ S(meta->GetType()), meta->GetURI().c_str(),
+ meta->GetDist().c_str(), meta->IsTrusted());
+}
+#undef S
+
+
+static const char *metaindex_doc =
+ "Provide information on meta-indexes (i.e. Release files), such as\n"
+ "whether they are trusted or their URI.";
+
+PyTypeObject PyMetaIndex_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.MetaIndex", // tp_name
+ sizeof(CppPyObject<metaIndex*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<metaIndex*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ MetaIndexRepr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flags
+ metaindex_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ MetaIndexGetSet, // tp_getset
+};
diff --git a/python/orderlist.cc b/python/orderlist.cc
new file mode 100644
index 0000000..d0ea184
--- /dev/null
+++ b/python/orderlist.cc
@@ -0,0 +1,317 @@
+/*
+ * orderlist.cc - Wrapper around pkgOrderList
+ *
+ * Copyright 2011 Julian Andres Klode <jak@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <Python.h>
+#include "apt_pkgmodule.h"
+#include "generic.h"
+#include <apt-pkg/orderlist.h>
+
+struct PyOrderList : CppPyObject<pkgOrderList*> {
+ pkgCache::PkgIterator current;
+ int nextIndex;
+};
+
+static PyObject *order_list_new(PyTypeObject *type,PyObject *args,
+ PyObject *kwds)
+{
+ PyObject *pyDepCache = NULL;
+ char *kwlist[] = {"depcache", NULL};
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist,
+ &PyDepCache_Type, &pyDepCache)
+ == 0)
+ return 0;
+
+ pkgDepCache *depCache = PyDepCache_ToCpp(pyDepCache);
+ return PyOrderList_FromCpp(new pkgOrderList(depCache), true,
+ pyDepCache);
+}
+
+static const char order_list_append_doc[] =
+ "append(pkg: Package)\n\n"
+ "Append a package to the end of the list.";
+static PyObject *order_list_append(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ PyObject *pyPackage = NULL;
+ if (PyArg_ParseTuple(args, "O!", &PyPackage_Type, &pyPackage) == 0)
+ return 0;
+
+ list->push_back(PyPackage_ToCpp(pyPackage));
+ Py_RETURN_NONE;
+}
+
+static const char order_list_score_doc[] =
+ "score(pkg: Package) -> int\n\n"
+ "Return the score of the package.";
+static PyObject *order_list_score(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ PyObject *pyPackage = NULL;
+ if (PyArg_ParseTuple(args, "O!", &PyPackage_Type, &pyPackage) == 0)
+ return 0;
+
+ return MkPyNumber(list->Score(PyPackage_ToCpp(pyPackage)));
+}
+
+static const char order_list_order_critical_doc[] =
+ "order_critical()\n\n"
+ "Order by PreDepends only (critical unpack order).";
+static PyObject *order_list_order_critical(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ if (PyArg_ParseTuple(args, "") == 0)
+ return 0;
+
+ list->OrderCritical();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static const char order_list_order_unpack_doc[] =
+ "order_unpack()\n\n"
+ "Order the packages for unpacking (see Debian Policy).";
+static PyObject *order_list_order_unpack(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ if (PyArg_ParseTuple(args, "") == 0)
+ return 0;
+
+ list->OrderUnpack();
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static const char order_list_order_configure_doc[] =
+ "order_configure()\n\n"
+ "Order the packages for configuration (see Debian Policy).";
+static PyObject *order_list_order_configure(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ if (PyArg_ParseTuple(args, "") == 0)
+ return 0;
+
+ list->OrderConfigure();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static bool valid_flags(unsigned int flags) {
+ return (flags & ~pkgOrderList::Added
+ & ~pkgOrderList::AddPending
+ & ~pkgOrderList::Immediate
+ & ~pkgOrderList::Loop
+ & ~pkgOrderList::UnPacked
+ & ~pkgOrderList::Configured
+ & ~pkgOrderList::Removed
+ & ~pkgOrderList::InList
+ & ~pkgOrderList::After
+ & ~pkgOrderList::States) == 0;
+}
+
+static const char order_list_flag_doc[] =
+ "flag(pkg: Package, flag: int[, unset_flags: int])\n\n"
+ "Flag the package, set flags in 'flag' and remove flags in\n"
+ "'unset_flags'.";
+static PyObject *order_list_flag(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+
+ PyObject *pyPkg = NULL;
+ unsigned int flags = 0;
+ unsigned int unset_flags = 0;
+ if (PyArg_ParseTuple(args, "O!I|I", &PyPackage_Type, &pyPkg,
+ &flags, &unset_flags) == 0)
+ return 0;
+
+ if (!valid_flags(flags))
+ return PyErr_Format(PyExc_ValueError, "flags (%u) is"
+ " not a valid combination of flags.",
+ flags);
+ if (!valid_flags(unset_flags))
+ return PyErr_Format(PyExc_ValueError, "unset_flags (%u) is"
+ " not a valid combination of flags.",
+ unset_flags);
+
+ list->Flag(PyPackage_ToCpp(pyPkg), flags, unset_flags);
+
+ Py_RETURN_NONE;
+}
+
+static const char order_list_is_flag_doc[] =
+ "is_flag(pkg: Package, flag: int)\n\n"
+ "Check if the flag(s) are set.";
+static PyObject *order_list_is_flag(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ PyObject *pyPkg = NULL;
+ unsigned int flags = 0;
+ if (PyArg_ParseTuple(args, "O!I", &PyPackage_Type, &pyPkg,
+ &flags) == 0)
+ return 0;
+
+ if (!valid_flags(flags))
+ return PyErr_Format(PyExc_ValueError, "flags (%u) is"
+ " not a valid combination of flags.",
+ flags);
+
+ return PyBool_FromLong(list->IsFlag(PyPackage_ToCpp(pyPkg), flags));
+}
+
+static const char order_list_wipe_flags_doc[] =
+ "wipe_flags(flags: int)\n\n"
+ "Remove the flags in 'flags' from all packages in this list";
+static PyObject *order_list_wipe_flags(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ unsigned int flags = 0;
+ if (PyArg_ParseTuple(args, "I", &flags) == 0)
+ return 0;
+
+ if (!valid_flags(flags))
+ return PyErr_Format(PyExc_ValueError, "flags (%u) is"
+ " not a valid combination of flags.",
+ flags);
+
+ list->WipeFlags(flags);
+ Py_RETURN_NONE;
+}
+
+static const char order_list_is_now_doc[] =
+ "is_now(pkg: Package)\n\n"
+ "Check if the package is flagged for any state but removal.";
+static PyObject *order_list_is_now(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ PyObject *pyPkg = NULL;
+ if (PyArg_ParseTuple(args, "O!", &PyPackage_Type, &pyPkg) == 0)
+ return 0;
+
+ return PyBool_FromLong(list->IsNow(PyPackage_ToCpp(pyPkg)));
+}
+
+static const char order_list_is_missing_doc[] =
+ "is_now(pkg: Package)\n\n"
+ "Check if the package is marked for install.";
+static PyObject *order_list_is_missing(PyObject *self,PyObject *args)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ PyObject *pyPkg = NULL;
+ if (PyArg_ParseTuple(args, "O!", &PyPackage_Type, &pyPkg) == 0)
+ return 0;
+
+ return PyBool_FromLong(list->IsMissing(PyPackage_ToCpp(pyPkg)));
+}
+
+
+#define METHOD(name) {#name, order_list_##name, METH_VARARGS,\
+ order_list_##name##_doc}
+
+static PyMethodDef order_list_methods[] = {
+ METHOD(append),
+ METHOD(score),
+ METHOD(order_critical),
+ METHOD(order_unpack),
+ METHOD(order_configure),
+ METHOD(flag),
+ METHOD(is_flag),
+ METHOD(is_now),
+ METHOD(is_missing),
+ METHOD(wipe_flags),
+ {}
+};
+
+static PyObject *order_list_seq_item(PyObject *self,Py_ssize_t index)
+{
+ pkgOrderList *list = GetCpp<pkgOrderList*>(self);
+ PyObject *owner = GetOwner<pkgOrderList*>(self);
+ PyObject *pycache = GetOwner<pkgOrderList*>(owner);
+ pkgCache *cache = PyCache_ToCpp(pycache);
+
+ if (index < 0 || index >= list->size())
+ return PyErr_Format(PyExc_IndexError, "Out of range: %zd", index);
+
+ return PyPackage_FromCpp(pkgCache::PkgIterator(*cache,
+ *(list->begin() + index)),
+ true, owner);
+}
+
+Py_ssize_t order_list_seq_length(PyObject *self)
+{
+ return GetCpp<pkgOrderList*>(self)->size();
+}
+
+static PySequenceMethods order_list_as_sequence =
+{
+ order_list_seq_length, // sq_length
+ 0, // sq_concat
+ 0, // sq_repeat
+ order_list_seq_item, // sq_item
+ 0, // sq_ass_item
+ 0, // sq_contains
+ 0, // sq_inplace_concat
+ 0 // sq_inplace_repeat
+};
+
+static const char order_list_doc[] = "OrderList(depcache: DepCache)\n\n"
+ "Sequence type for packages with special ordering methods.";
+PyTypeObject PyOrderList_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.OrderList", // tp_name
+ sizeof(CppPyObject<pkgOrderList*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<pkgOrderList*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &order_list_as_sequence, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flags
+ order_list_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ order_list_methods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ order_list_new, // tp_new
+};
diff --git a/python/pkgmanager.cc b/python/pkgmanager.cc
new file mode 100644
index 0000000..2fb8e71
--- /dev/null
+++ b/python/pkgmanager.cc
@@ -0,0 +1,375 @@
+// Description /*{{{*/
+// $Id: acquire.cc,v 1.1 2003/06/03 03:03:23 mvo Exp $
+/* ######################################################################
+
+ PkgManager - Wrapper for the pkgPackageManager code
+
+ ##################################################################### */
+
+#include "generic.h"
+#include "apt_pkgmodule.h"
+#include "pkgrecords.h"
+
+#include <apt-pkg/packagemanager.h>
+#include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/sourcelist.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/acquire.h>
+#include <apt-pkg/init.h>
+#include <apt-pkg/install-progress.h>
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/dpkgpm.h>
+
+#include <iostream>
+
+static PyObject *PkgManagerGetArchives(PyObject *Self,PyObject *Args)
+{
+ pkgPackageManager *pm = GetCpp<pkgPackageManager*>(Self);
+ PyObject *fetcher, *list, *recs;
+
+ if (PyArg_ParseTuple(Args, "O!O!O!",
+ &PyAcquire_Type,&fetcher,
+ &PySourceList_Type, &list,
+ &PyPackageRecords_Type, &recs) == 0)
+ return 0;
+
+ pkgAcquire *s_fetcher = GetCpp<pkgAcquire*>(fetcher);
+ pkgSourceList *s_list = GetCpp<pkgSourceList*>(list);
+ PkgRecordsStruct &s_records = GetCpp<PkgRecordsStruct>(recs);
+
+ bool res = pm->GetArchives(s_fetcher, s_list,
+ &s_records.Records);
+
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static PyObject *PkgManagerDoInstall(PyObject *Self,PyObject *Args)
+{
+ //PkgManagerStruct &Struct = GetCpp<PkgManagerStruct>(Self);
+ pkgPackageManager *pm = GetCpp<pkgPackageManager*>(Self);
+ int status_fd = -1;
+
+ if (PyArg_ParseTuple(Args, "|i", &status_fd) == 0)
+ return 0;
+
+ APT::Progress::PackageManagerProgressFd progress(status_fd);
+
+ pkgPackageManager::OrderResult res = pm->DoInstall(&progress);
+
+ return HandleErrors(MkPyNumber(res));
+}
+
+static PyObject *PkgManagerFixMissing(PyObject *Self,PyObject *Args)
+{
+ //PkgManagerStruct &Struct = GetCpp<PkgManagerStruct>(Self);
+ pkgPackageManager *pm = GetCpp<pkgPackageManager*>(Self);
+
+ if (PyArg_ParseTuple(Args, "") == 0)
+ return 0;
+
+ bool res = pm->FixMissing();
+
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static PyMethodDef PkgManagerMethods[] =
+{
+ {"get_archives",PkgManagerGetArchives,METH_VARARGS,
+ "get_archives(fetcher: Acquire, list: SourceList, recs: PackageRecords) -> bool\n\n"
+ "Download the packages marked for installation via the Acquire object\n"
+ "'fetcher', using the information found in 'list' and 'recs'."},
+ {"do_install",PkgManagerDoInstall,METH_VARARGS,
+ "do_install(status_fd: int) -> int\n\n"
+ "Install the packages and return one of the class constants\n"
+ "RESULT_COMPLETED, RESULT_FAILED, RESULT_INCOMPLETE. The argument\n"
+ "status_fd can be used to specify a file descriptor that APT will\n"
+ "write status information on (see README.progress-reporting in the\n"
+ "apt source code for information on what will be written there)."},
+ {"fix_missing",PkgManagerFixMissing,METH_VARARGS,
+ "fix_missing() -> bool\n\n"
+ "Fix the installation if a package could not be downloaded."},
+ {}
+};
+
+static const char *packagemanager_doc =
+ "_PackageManager objects allow the fetching of packages marked for\n"
+ "installation and the installation of those packages.\n"
+ "This is an abstract base class that cannot be subclassed\n"
+ "in Python. The only subclass is apt_pkg.PackageManager. This\n"
+ "class is an implementation-detail and not part of the API.";
+PyTypeObject PyPackageManager_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg._PackageManager", // tp_name
+ sizeof(CppPyObject<pkgPackageManager*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<pkgPackageManager*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flag,
+ packagemanager_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PkgManagerMethods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ 0, // tp_new
+};
+
+
+struct CppPyRef {
+ PyObject *o;
+ CppPyRef(const CppPyRef &o) { Py_XINCREF(o); this->o = o; }
+ CppPyRef(PyObject *o) : o(o) {}
+ ~CppPyRef() { Py_XDECREF(o); }
+ operator PyObject *() const { return o; }
+ PyObject *operator->() const { return o; }
+};
+
+class PyPkgManager : public pkgDPkgPM {
+ bool res(CppPyRef result, const char* funcname) {
+ if (result == NULL) {
+ std::cerr << "Error in function: " << funcname << std::endl;
+ PyErr_Print();
+ PyErr_Clear();
+ return false;
+ }
+ return (result != NULL &&
+ (result == Py_None || PyObject_IsTrue(result) == 1));
+ }
+
+
+ PyObject *GetPyPkg(const PkgIterator &Pkg) {
+ PyObject *depcache = NULL;
+ PyObject *cache = NULL;
+
+ depcache = GetOwner<PyPkgManager*>(pyinst);
+ if (depcache != NULL && PyDepCache_Check(depcache))
+ cache = GetOwner<pkgDepCache*>(depcache);
+
+ return PyPackage_FromCpp(Pkg, true, cache);
+ }
+
+ /* Call through to Python */
+ virtual bool Install(PkgIterator Pkg,std::string File) {
+ return res(PyObject_CallMethod(pyinst, "install", "(NN)",
+ GetPyPkg(Pkg),
+ CppPyString(File)),
+ "install");
+ }
+ virtual bool Configure(PkgIterator Pkg) {
+ return res(PyObject_CallMethod(pyinst, "configure", "(N)",
+ GetPyPkg(Pkg)),
+ "configure");
+ }
+ virtual bool Remove(PkgIterator Pkg,bool Purge = false) {
+ return res(PyObject_CallMethod(pyinst, "remove", "(NN)",
+ GetPyPkg(Pkg),
+ PyBool_FromLong(Purge)),
+ "remove"
+ );
+ }
+ virtual bool Go(int StatusFd=-1) {
+ return res(PyObject_CallMethod(pyinst, "go", "(i)",
+ StatusFd),
+ "go");
+ }
+ virtual void Reset() {
+ Py_XDECREF(PyObject_CallMethod(pyinst, "reset", NULL));
+ }
+
+public:
+ /* Those call the protected functions from the parent class */
+ bool callInstall(PkgIterator Pkg,std::string File) { return pkgDPkgPM::Install(Pkg, File); }
+ bool callRemove(PkgIterator Pkg, bool Purge) { return pkgDPkgPM::Remove(Pkg, Purge); }
+ bool callGo(int StatusFd=-1) {
+ APT::Progress::PackageManagerProgressFd progress(StatusFd);
+ return pkgDPkgPM::Go(&progress);
+ }
+ void callReset() { return pkgDPkgPM::Reset(); }
+ bool callConfigure(PkgIterator Pkg) { return pkgDPkgPM::Configure(Pkg); }
+ pkgOrderList *getOrderList() { return pkgPackageManager::List; }
+
+ PyPkgManager(pkgDepCache *Cache) : pkgDPkgPM(Cache),pyinst(NULL) {};
+ PyObject *pyinst;
+};
+
+static PyObject *PkgManagerNew(PyTypeObject *type,PyObject *Args,PyObject *kwds)
+{
+ PyObject *Owner;
+ char *kwlist[] = {"depcache",0};
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"O!",kwlist,&PyDepCache_Type,
+ &Owner) == 0)
+ return 0;
+
+ PyPkgManager *pm = new PyPkgManager(GetCpp<pkgDepCache*>(Owner));
+
+ CppPyObject<PyPkgManager*> *PkgManagerObj =
+ CppPyObject_NEW<PyPkgManager*>(NULL, type,pm);
+
+ pm->pyinst = PkgManagerObj;
+
+ return PkgManagerObj;
+}
+
+
+static PyObject *PkgManagerInstall(PyObject *Self,PyObject *Args)
+{
+ PyPkgManager *pm = GetCpp<PyPkgManager*>(Self);
+ PyObject *pkg;
+ PyApt_Filename file;
+
+ if (PyArg_ParseTuple(Args, "O!O&", &PyPackage_Type,&pkg, PyApt_Filename::Converter, &file) == 0)
+ return 0;
+
+ return HandleErrors(PyBool_FromLong(pm->callInstall(PyPackage_ToCpp(pkg), file)));
+}
+
+
+static PyObject *PkgManagerConfigure(PyObject *Self,PyObject *Args)
+{
+ PyPkgManager *pm = GetCpp<PyPkgManager*>(Self);
+ PyObject *pkg;
+
+ if (PyArg_ParseTuple(Args, "O!", &PyPackage_Type,&pkg) == 0)
+ return 0;
+
+ return HandleErrors(PyBool_FromLong(pm->callConfigure(PyPackage_ToCpp(pkg))));
+}
+
+static PyObject *PkgManagerRemove(PyObject *Self,PyObject *Args)
+{
+ PyPkgManager *pm = GetCpp<PyPkgManager*>(Self);
+ PyObject *pkg;
+ char purge;
+
+ if (PyArg_ParseTuple(Args, "O!b", &PyPackage_Type,&pkg, &purge) == 0)
+ return 0;
+
+ return HandleErrors(PyBool_FromLong(pm->callRemove(PyPackage_ToCpp(pkg), purge)));
+}
+
+static PyObject *PkgManagerGo(PyObject *Self,PyObject *Args)
+{
+ PyPkgManager *pm = GetCpp<PyPkgManager*>(Self);
+ int fd;
+
+ if (PyArg_ParseTuple(Args, "i", &fd) == 0)
+ return 0;
+
+ return HandleErrors(PyBool_FromLong(pm->callGo(fd)));
+}
+
+static PyObject *PkgManagerReset(PyObject *Self,PyObject *Args)
+{
+ PyPkgManager *pm = GetCpp<PyPkgManager*>(Self);
+
+ pm->callReset();
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static PyMethodDef PkgManager2Methods[] =
+{
+ {"install",PkgManagerInstall,METH_VARARGS,
+ "install(pkg: Package, filename: str) -> bool \n\n"
+ "Add a install action. Can be overridden in subclasses.\n\n"
+ "New in version 0.8.0."},
+ {"configure",PkgManagerConfigure,METH_VARARGS,
+ "configure(pkg: Package) -> bool \n\n"
+ "Add a configure action. Can be overridden in subclasses.\n\n"
+ "New in version 0.8.0."},
+ {"remove",PkgManagerRemove,METH_VARARGS,
+ "remove(pkg: Package, purge: bool) -> bool \n\n"
+ "Add a removal action. Can be overridden in subclasses.\n\n"
+ "New in version 0.8.0."},
+ {"go",PkgManagerGo,METH_VARARGS,
+ "go(status_fd: int) -> bool \n\n"
+ "Start dpkg. Can be overridden in subclasses.\n\n"
+ "New in version 0.8.0."},
+ {"reset",PkgManagerReset,METH_VARARGS,
+ "reset()\n\n"
+ "Reset the package manager for a new round.\n"
+ "Can be overridden in subclasses.\n\n"
+ "New in version 0.8.0."},
+ {}
+};
+
+static const char *packagemanager2_doc =
+ "PackageManager(depcache: apt_pkg.DepCache)\n\n"
+ "PackageManager objects allow the fetching of packages marked for\n"
+ "installation and the installation of those packages. The parameter\n"
+ "'depcache' specifies an apt_pkg.DepCache object where information\n"
+ "about the package selections is retrieved from.\n\n"
+ "Methods in this class can be overridden in sub classes\n"
+ "to implement behavior different from APT's dpkg implementation.";
+PyTypeObject PyPackageManager2_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.PackageManager", // tp_name
+ sizeof(CppPyObject<PyPkgManager*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<PyPkgManager*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE),
+ packagemanager2_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PkgManager2Methods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ &PyPackageManager_Type, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ PkgManagerNew, // tp_new
+};
+
+
+ /*}}}*/
diff --git a/python/pkgrecords.cc b/python/pkgrecords.cc
new file mode 100644
index 0000000..13c2b9a
--- /dev/null
+++ b/python/pkgrecords.cc
@@ -0,0 +1,280 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: pkgrecords.cc,v 1.3 2002/02/26 01:36:15 mdz Exp $
+/* ######################################################################
+
+ Package Records - Wrapper for the package records functions
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "generic.h"
+#include "apt_pkgmodule.h"
+#include "pkgrecords.h"
+
+
+#include <Python.h>
+ /*}}}*/
+
+
+// PkgRecords Class /*{{{*/
+// ---------------------------------------------------------------------
+
+
+static PyObject *PkgRecordsLookup(PyObject *Self,PyObject *Args)
+{
+ PkgRecordsStruct &Struct = GetCpp<PkgRecordsStruct>(Self);
+
+ PyObject *PkgFObj;
+ long int Index;
+ if (PyArg_ParseTuple(Args,"(O!l)",&PyPackageFile_Type,&PkgFObj,&Index) == 0)
+ return 0;
+
+ // Get the index and check to make sure it is reasonable
+ pkgCache::PkgFileIterator &PkgF = GetCpp<pkgCache::PkgFileIterator>(PkgFObj);
+ pkgCache *Cache = PkgF.Cache();
+ if (Cache->DataEnd() <= Cache->VerFileP + Index + 1 ||
+ Cache->VerFileP[Index].File != PkgF.MapPointer())
+ {
+ PyErr_SetNone(PyExc_IndexError);
+ return 0;
+ }
+
+ // Do the lookup
+ Struct.Last = &Struct.Records.Lookup(pkgCache::VerFileIterator(*Cache,Cache->VerFileP+Index));
+
+ // always return true (to make it consistent with the pkgsrcrecords object
+ return PyBool_FromLong(1);
+}
+
+static PyMethodDef PkgRecordsMethods[] =
+{
+ {"lookup",PkgRecordsLookup,METH_VARARGS,
+ "lookup((packagefile: apt_pkg.PackageFile, index: int)) -> bool\n\n"
+ "Changes to a new package"},
+ {}
+};
+
+/**
+ * Get the PkgSrcRecordsStruct from a PyObject. If no package has been looked
+ * up, set an AttributeError using the given name.
+ */
+static inline PkgRecordsStruct &GetStruct(PyObject *Self,char *name) {
+ PkgRecordsStruct &Struct = GetCpp<PkgRecordsStruct>(Self);
+ if (Struct.Last == 0)
+ PyErr_SetString(PyExc_AttributeError,name);
+ return Struct;
+}
+
+static PyObject *PkgRecordsGetFileName(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"FileName");
+ return (Struct.Last != 0) ? CppPyPath(Struct.Last->FileName()) : 0;
+}
+static PyObject *PkgRecordsGetHashes(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"Hashes");
+ if (Struct.Last == 0)
+ return 0;
+
+ auto py = CppPyObject_NEW<HashStringList> (nullptr, &PyHashStringList_Type);
+ py->Object = Struct.Last->Hashes();
+ return py;
+}
+static PyObject *PkgRecordsGetMD5Hash(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"MD5Hash");
+ if (Struct.Last == NULL)
+ return 0;
+ auto hashes = Struct.Last->Hashes();
+ auto hash = hashes.find("md5sum");
+ if (hash == NULL)
+ return 0;
+ return CppPyString(hash->HashValue());
+}
+static PyObject *PkgRecordsGetSHA1Hash(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"SHA1Hash");
+ if (Struct.Last == NULL)
+ return 0;
+ auto hashes = Struct.Last->Hashes();
+ auto hash = hashes.find("sha1");
+ if (hash == NULL)
+ return 0;
+ return CppPyString(hash->HashValue());
+}
+static PyObject *PkgRecordsGetSHA256Hash(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"SHA256Hash");
+ if (Struct.Last == NULL)
+ return 0;
+ auto hashes = Struct.Last->Hashes();
+ auto hash = hashes.find("sha256");
+ if (hash == NULL)
+ return 0;
+ return CppPyString(hash->HashValue());
+}
+static PyObject *PkgRecordsGetSourcePkg(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"SourcePkg");
+ return (Struct.Last != 0) ? CppPyString(Struct.Last->SourcePkg()) : 0;
+}
+static PyObject *PkgRecordsGetSourceVer(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"SourceVer");
+ return (Struct.Last != 0) ? CppPyString(Struct.Last->SourceVer()) : 0;
+}
+static PyObject *PkgRecordsGetMaintainer(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"Maintainer");
+ return (Struct.Last != 0) ? CppPyString(Struct.Last->Maintainer()) : 0;
+}
+static PyObject *PkgRecordsGetShortDesc(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"ShortDesc");
+ return (Struct.Last != 0) ? CppPyLocaleString(Struct.Last->ShortDesc()) : 0;
+}
+static PyObject *PkgRecordsGetLongDesc(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"LongDesc");
+ return (Struct.Last != 0) ? CppPyLocaleString(Struct.Last->LongDesc()) : 0;
+}
+static PyObject *PkgRecordsGetName(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"Name");
+ return (Struct.Last != 0) ? CppPyString(Struct.Last->Name()) : 0;
+}
+static PyObject *PkgRecordsGetHomepage(PyObject *Self,void*) {
+ PkgRecordsStruct &Struct = GetStruct(Self,"Homepage");
+ return (Struct.Last != 0) ? CppPyString(Struct.Last->Homepage()) : 0;
+}
+static PyObject *PkgRecordsGetRecord(PyObject *Self,void*) {
+ const char *start, *stop;
+ PkgRecordsStruct &Struct = GetStruct(Self,"Record");
+ if (Struct.Last == 0)
+ return 0;
+ Struct.Last->GetRec(start, stop);
+ return PyString_FromStringAndSize(start,stop-start);
+}
+static PyGetSetDef PkgRecordsGetSet[] = {
+ {"filename",PkgRecordsGetFileName,0,
+ "The filename of the package, as stored in the 'Filename' field."},
+ {"homepage",PkgRecordsGetHomepage,0,
+ "The homepage of the package, as stored in the 'Homepage' field."},
+ {"long_desc",PkgRecordsGetLongDesc,0,
+ "The long description of the packages; i.e. all lines in the\n"
+ "'Description' field except for the first one."},
+ {"hashes",PkgRecordsGetHashes,0,
+ "The hashes of the packages, as a HashStringList"},
+ {"md5_hash",PkgRecordsGetMD5Hash,0,
+ "The MD5 hash value of the package, as stored in the 'MD5Sum' field."},
+ {"maintainer",PkgRecordsGetMaintainer,0,
+ "The maintainer of the package, as stored in the 'Maintainer' field."},
+ {"name",PkgRecordsGetName,0,
+ "The name of the package, as stored in the 'Package' field."},
+ {"record",PkgRecordsGetRecord,0,
+ "The raw record, suitable for parsing by apt_pkg.TagSection."},
+ {"sha1_hash",PkgRecordsGetSHA1Hash,0,
+ "The SHA1 hash value, as stored in the 'SHA1' field."},
+ {"sha256_hash",PkgRecordsGetSHA256Hash,0,
+ "The SHA256 hash value, as stored in the 'SHA256' field."},
+ {"short_desc",PkgRecordsGetShortDesc,0,
+ "The short description of the package, i.e. the first line of the\n"
+ "'Description' field."},
+ {"source_pkg",PkgRecordsGetSourcePkg,0,
+ "The name of the source package, if different from the name of the\n"
+ "binary package. This information is retrieved from the 'Source' field."},
+ {"source_ver",PkgRecordsGetSourceVer,0,
+ "The version of the source package, if it differs from the version\n"
+ "of the binary package. Just like 'source_pkg', this information\n"
+ "is retrieved from the 'Source' field."},
+ {}
+};
+
+static int PkgRecordsContains(PyObject *Self,PyObject *Arg)
+{
+ PkgRecordsStruct &Struct = GetStruct(Self,"__contains__");
+ if (Struct.Last == nullptr)
+ return -1;
+ const char *Name = PyObject_AsString(Arg);
+
+ if (Name == nullptr)
+ return -1;
+
+ return !Struct.Last->RecordField(Name).empty();
+}
+
+static PyObject *PkgRecordsMap(PyObject *Self,PyObject *Arg)
+{
+ PkgRecordsStruct &Struct = GetStruct(Self,"__contains__");
+ if (Struct.Last == nullptr)
+ return nullptr;
+
+ const char *Name = PyObject_AsString(Arg);
+ if (Name == nullptr)
+ return nullptr;
+
+ return CppPyString(Struct.Last->RecordField(Name));
+}
+
+
+
+PySequenceMethods PkgRecordsSeqMeth = {0,0,0,0,0,0,0,PkgRecordsContains,0,0};
+PyMappingMethods PkgRecordsMapMeth = {0,PkgRecordsMap,0};
+
+static PyObject *PkgRecordsNew(PyTypeObject *type,PyObject *Args,PyObject *kwds)
+{
+ PyObject *Owner;
+ char *kwlist[] = {"cache",0};
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"O!",kwlist,&PyCache_Type,
+ &Owner) == 0)
+ return 0;
+
+ return HandleErrors(CppPyObject_NEW<PkgRecordsStruct>(Owner,type,
+ GetCpp<pkgCache *>(Owner)));
+}
+
+static const char *packagerecords_doc =
+ "PackageRecords(cache: apt_pkg.Cache)\n\n"
+ "Package Records contain information about packages. Those objects\n"
+ "can be used to retrieve information such as maintainer or filename\n"
+ "of a package. They can also be used to retrieve the raw records\n"
+ "of the packages (i.e. those stanzas stored in Packages files).";
+
+PyTypeObject PyPackageRecords_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.PackageRecords", // tp_name
+ sizeof(CppPyObject<PkgRecordsStruct>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<PkgRecordsStruct>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &PkgRecordsSeqMeth, // tp_as_sequence
+ &PkgRecordsMapMeth, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE |
+ Py_TPFLAGS_HAVE_GC),
+ packagerecords_doc, // tp_doc
+ CppTraverse<PkgRecordsStruct>, // tp_traverse
+ CppClear<PkgRecordsStruct>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PkgRecordsMethods, // tp_methods
+ 0, // tp_members
+ PkgRecordsGetSet, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ PkgRecordsNew, // tp_new
+};
+
+ /*}}}*/
+
+
diff --git a/python/pkgrecords.h b/python/pkgrecords.h
new file mode 100644
index 0000000..1e26c8c
--- /dev/null
+++ b/python/pkgrecords.h
@@ -0,0 +1,10 @@
+#include <apt-pkg/pkgrecords.h>
+
+struct PkgRecordsStruct
+{
+ pkgRecords Records;
+ pkgRecords::Parser *Last;
+
+ PkgRecordsStruct(pkgCache *Cache) : Records(*Cache), Last(0) {};
+ PkgRecordsStruct() : Records(*(pkgCache *)0) {abort();}; // G++ Bug..
+};
diff --git a/python/pkgsrcrecords.cc b/python/pkgsrcrecords.cc
new file mode 100644
index 0000000..e813c6e
--- /dev/null
+++ b/python/pkgsrcrecords.cc
@@ -0,0 +1,438 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: pkgsrcrecords.cc,v 1.2 2003/12/26 17:04:22 mdz Exp $
+/* ######################################################################
+
+ Package Records - Wrapper for the package records functions
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "generic.h"
+#include "apt_pkgmodule.h"
+
+#include <apt-pkg/sourcelist.h>
+
+#include <Python.h>
+ /*}}}*/
+
+// PkgSrcRecordFiles Class /*{{{*/
+// ---------------------------------------------------------------------
+typedef pkgSrcRecords::File PkgSrcRecordFilesStruct;
+
+// compat with the old API that provided a tuple (md5,size,path,type)
+static Py_ssize_t pkgSrcRecordFiles_length(PyObject *Self) {
+ return 4;
+}
+
+// compat with the old API that provided a tuple (md5,size,path,type)
+static PyObject* pkgSrcRecordFiles_item(PyObject *Self, Py_ssize_t i) {
+ APT_IGNORE_DEPRECATED_PUSH
+ PkgSrcRecordFilesStruct f = GetCpp<PkgSrcRecordFilesStruct>(Self);
+ switch (i) {
+ case 0:
+ Py_INCREF(Py_None);
+ return Py_None;
+ case 1:
+ return Py_BuildValue("N", MkPyNumber(f.FileSize));
+ case 2:
+ return Py_BuildValue("s", f.Path.c_str());
+ case 3:
+ return Py_BuildValue("s", f.Type.c_str());
+ }
+
+ PyErr_Format(PyExc_IndexError, "index %d out of range, consider using the properties instead", i);
+ return NULL;
+ APT_IGNORE_DEPRECATED_POP
+}
+
+static PySequenceMethods pkgsrcrecordfiles_as_sequence = {
+ pkgSrcRecordFiles_length,0,0,pkgSrcRecordFiles_item,0,0,0,0,0,0
+};
+
+static PyObject *PkgSrcRecordFilesNew(PyTypeObject *type,PyObject *args,PyObject *kwds) {
+ char *kwlist[] = {0};
+ if (PyArg_ParseTupleAndKeywords(args,kwds,"",kwlist) == 0)
+ return 0;
+
+ return HandleErrors(CppPyObject_NEW<PkgSrcRecordFilesStruct>(NULL, type));
+}
+
+static const char *sourcerecordfile_doc =
+ "SourceRecordFile()\n\n"
+ "Provide an easy way to look up the src records of a source package.\n";
+
+static PyObject *PkgSrcRecordFilesGetPath(PyObject *Self,void*) {
+ PkgSrcRecordFilesStruct f = GetCpp<PkgSrcRecordFilesStruct>(Self);
+ return CppPyString(f.Path.c_str());
+}
+
+static PyObject *PkgSrcRecordFilesGetType(PyObject *Self,void*) {
+ PkgSrcRecordFilesStruct f = GetCpp<PkgSrcRecordFilesStruct>(Self);
+ return CppPyString(f.Type.c_str());
+}
+
+static PyObject *PkgSrcRecordFilesGetSize(PyObject *Self,void*) {
+ PkgSrcRecordFilesStruct f = GetCpp<PkgSrcRecordFilesStruct>(Self);
+ return Py_BuildValue("N", MkPyNumber(f.FileSize));
+}
+
+static PyObject *PkgSrcRecordFilesGetHashes(PyObject *Self,void*) {
+ PkgSrcRecordFilesStruct f = GetCpp<PkgSrcRecordFilesStruct>(Self);
+ auto py = CppPyObject_NEW<HashStringList> (nullptr, &PyHashStringList_Type);
+ py->Object = f.Hashes;
+ return py;
+}
+
+static PyGetSetDef PkgSrcRecordFilesGetSet[] = {
+ {"path",PkgSrcRecordFilesGetPath,0,
+ "The remote path of the source package file."},
+ {"type",PkgSrcRecordFilesGetType,0,
+ "The type of the source package file."},
+ {"size",PkgSrcRecordFilesGetSize,0,
+ "The size of the source package file."},
+ {"hashes",PkgSrcRecordFilesGetHashes,0,
+ "The hashes of the source package file."},
+ {}
+};
+
+PyTypeObject PySourceRecordFiles_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.SourceRecordFiles", // tp_name
+ sizeof(CppPyObject<PkgSrcRecordFilesStruct>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<PkgSrcRecordFilesStruct>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &pkgsrcrecordfiles_as_sequence, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE),
+ sourcerecordfile_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ PkgSrcRecordFilesGetSet, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ PkgSrcRecordFilesNew, // tp_new
+};
+// ---------------------------------------------------------------------
+
+struct PkgSrcRecordsStruct
+{
+ pkgSourceList List;
+ pkgSrcRecords *Records;
+ pkgSrcRecords::Parser *Last;
+
+ PkgSrcRecordsStruct() : Last(0) {
+ List.ReadMainList();
+ Records = new pkgSrcRecords(List);
+ };
+ ~PkgSrcRecordsStruct() {
+ delete Records;
+ };
+};
+
+
+// PkgSrcRecords Class /*{{{*/
+// ---------------------------------------------------------------------
+
+static char *doc_PkgSrcRecordsLookup =
+ "lookup(name: str) -> bool\n\n"
+ "Look up the source package with the given name. Each call moves\n"
+ "the position of the records parser forward. If there are no\n"
+ "more records, return None. If the lookup failed this way,\n"
+ "access to any of the attributes will result in an AttributeError.";
+static PyObject *PkgSrcRecordsLookup(PyObject *Self,PyObject *Args)
+{
+ PkgSrcRecordsStruct &Struct = GetCpp<PkgSrcRecordsStruct>(Self);
+
+ char *Name = 0;
+ if (PyArg_ParseTuple(Args,"s",&Name) == 0)
+ return 0;
+
+ Struct.Last = Struct.Records->Find(Name, false);
+ if (Struct.Last == 0) {
+ Struct.Records->Restart();
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+ }
+
+ return PyBool_FromLong(1);
+}
+
+static char *doc_PkgSrcRecordsRestart =
+ "restart()\n\n"
+ "Restart the lookup process. This moves the parser to the first\n"
+ "package and lookups can now be made just like on a new object.";
+static PyObject *PkgSrcRecordsRestart(PyObject *Self,PyObject *Args)
+{
+ PkgSrcRecordsStruct &Struct = GetCpp<PkgSrcRecordsStruct>(Self);
+
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ Struct.Records->Restart();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static char *doc_PkgSrcRecordsStep =
+ "step() -> bool\n\n"
+ "Go to the source package. Each call moves\n"
+ "the position of the records parser forward. If there are no\n"
+ "more records, return None. If the lookup failed this way,\n"
+ "access to any of the attributes will result in an AttributeError.";
+static PyObject *PkgSrcRecordsStep(PyObject *Self,PyObject *Args)
+{
+ PkgSrcRecordsStruct &Struct = GetCpp<PkgSrcRecordsStruct>(Self);
+
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ Struct.Last = (pkgSrcRecords::Parser*)Struct.Records->Step();
+ if (Struct.Last == 0) {
+ Struct.Records->Restart();
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+ }
+
+ return PyBool_FromLong(1);
+}
+
+static PyMethodDef PkgSrcRecordsMethods[] =
+{
+ {"lookup",PkgSrcRecordsLookup,METH_VARARGS,doc_PkgSrcRecordsLookup},
+ {"restart",PkgSrcRecordsRestart,METH_VARARGS,doc_PkgSrcRecordsRestart},
+ {"step",PkgSrcRecordsStep,METH_VARARGS,doc_PkgSrcRecordsStep},
+ {}
+};
+
+/**
+ * Get the PkgSrcRecordsStruct from a PyObject. If no package has been looked
+ * up, set an AttributeError using the given name.
+ */
+static inline PkgSrcRecordsStruct &GetStruct(PyObject *Self,char *name) {
+ PkgSrcRecordsStruct &Struct = GetCpp<PkgSrcRecordsStruct>(Self);
+ if (Struct.Last == 0)
+ PyErr_SetString(PyExc_AttributeError,name);
+ return Struct;
+}
+
+static PyObject *PkgSrcRecordsGetPackage(PyObject *Self,void*) {
+ PkgSrcRecordsStruct &Struct = GetStruct(Self,"Package");
+ return (Struct.Last != 0) ? CppPyString(Struct.Last->Package()) : 0;
+}
+static PyObject *PkgSrcRecordsGetVersion(PyObject *Self,void*) {
+ PkgSrcRecordsStruct &Struct = GetStruct(Self,"Version");
+ return (Struct.Last != 0) ? CppPyString(Struct.Last->Version()) : 0;
+}
+static PyObject *PkgSrcRecordsGetMaintainer(PyObject *Self,void*) {
+ PkgSrcRecordsStruct &Struct = GetStruct(Self,"Maintainer");
+ return (Struct.Last != 0) ? CppPyString(Struct.Last->Maintainer()) : 0;
+}
+static PyObject *PkgSrcRecordsGetSection(PyObject *Self,void*) {
+ PkgSrcRecordsStruct &Struct = GetStruct(Self,"Section");
+ return (Struct.Last != 0) ? CppPyString(Struct.Last->Section()) : 0;
+}
+static PyObject *PkgSrcRecordsGetRecord(PyObject *Self,void*) {
+ PkgSrcRecordsStruct &Struct = GetStruct(Self,"Record");
+ return (Struct.Last != 0) ? CppPyString(Struct.Last->AsStr()) : 0;
+}
+static PyObject *PkgSrcRecordsGetBinaries(PyObject *Self,void*) {
+ PkgSrcRecordsStruct &Struct = GetStruct(Self,"Binaries");
+ if (Struct.Last == 0)
+ return 0;
+ PyObject *List = PyList_New(0);
+ for(const char **b = Struct.Last->Binaries(); *b != 0; ++b)
+ PyList_Append(List, CppPyString(*b));
+ return List; // todo
+}
+static PyObject *PkgSrcRecordsGetIndex(PyObject *Self,void*) {
+ PkgSrcRecordsStruct &Struct = GetStruct(Self,"Index");
+ if (Struct.Last == 0)
+ return 0;
+ const pkgIndexFile &tmp = Struct.Last->Index();
+ CppPyObject<pkgIndexFile*> *PyObj;
+ PyObj = CppPyObject_NEW<pkgIndexFile*>(Self,&PyIndexFile_Type,
+ (pkgIndexFile*)&tmp);
+ // Do not delete the pkgIndexFile*, it is managed by PkgSrcRecords::Parser.
+ PyObj->NoDelete=true;
+ return PyObj;
+}
+
+static PyObject *PkgSrcRecordsGetFiles(PyObject *Self,void*) {
+ PkgSrcRecordsStruct &Struct = GetStruct(Self,"Files");
+ if (Struct.Last == 0)
+ return 0;
+ PyObject *List = PyList_New(0);
+
+ std::vector<pkgSrcRecords::File> f;
+ if(!Struct.Last->Files(f))
+ return NULL; // error
+
+ PyObject *v;
+ for(unsigned int i=0;i<f.size();i++) {
+ v = CppPyObject_NEW<PkgSrcRecordFilesStruct>(Self, &PySourceRecordFiles_Type, f[i]);
+ PyList_Append(List, v);
+ Py_DECREF(v);
+ }
+ return List;
+}
+
+static PyObject *PkgSrcRecordsGetBuildDepends(PyObject *Self,void*) {
+ PkgSrcRecordsStruct &Struct = GetStruct(Self,"BuildDepends");
+ if (Struct.Last == 0)
+ return 0;
+
+ PyObject *Dict = PyDict_New();
+ PyObject *Dep = 0;
+ PyObject *LastDep = 0;
+ PyObject *OrGroup = 0;
+
+ std::vector<pkgSrcRecords::Parser::BuildDepRec> bd;
+ if(!Struct.Last->BuildDepends(bd, false /* arch-only*/))
+ return NULL; // error
+
+ PyObject *v;
+ for(unsigned int i=0;i<bd.size();i++) {
+
+ Dep = CppPyString(pkgSrcRecords::Parser::BuildDepType(bd[i].Type));
+
+ LastDep = PyDict_GetItem(Dict,Dep);
+ if (LastDep == 0)
+ {
+ LastDep = PyList_New(0);
+ PyDict_SetItem(Dict,Dep,LastDep);
+ Py_DECREF(LastDep);
+ }
+ Py_DECREF(Dep);
+ OrGroup = PyList_New(0);
+ PyList_Append(LastDep, OrGroup);
+ Py_DECREF(OrGroup);
+
+ // Add at least one package to the group, add more if Or is set.
+ while (i < bd.size())
+ {
+ v = Py_BuildValue("(sss)", bd[i].Package.c_str(),
+ bd[i].Version.c_str(), pkgCache::CompType(bd[i].Op));
+ PyList_Append(OrGroup, v);
+ Py_DECREF(v);
+ if (pkgCache::Dep::Or != (bd[i].Op & pkgCache::Dep::Or))
+ break;
+ i++;
+ }
+
+ }
+ return Dict;
+}
+
+
+static PyGetSetDef PkgSrcRecordsGetSet[] = {
+ {"binaries",PkgSrcRecordsGetBinaries,0,
+ "A list of the names of the binaries produced by this source package."},
+ {"build_depends",PkgSrcRecordsGetBuildDepends,0,
+ "A dictionary describing the build-time dependencies of the package;\n"
+ "the format is the same as used for apt_pkg.Version.depends_list_str."},
+ {"files",PkgSrcRecordsGetFiles,0,
+ "A list of :class:`SourceRecordFiles` objects."},
+ {"index",PkgSrcRecordsGetIndex,0,
+ "The index file associated with this record as a list of\n"
+ "apt_pkg.IndexFile objects."},
+ {"maintainer",PkgSrcRecordsGetMaintainer,0,
+ "The maintainer of the package."},
+ {"package",PkgSrcRecordsGetPackage,0,
+ "The name of the source package."},
+ {"record",PkgSrcRecordsGetRecord,0,
+ "The raw record, suitable for parsing using apt_pkg.TagSection."},
+ {"section",PkgSrcRecordsGetSection,0,
+ "The section of the source package."},
+ {"version",PkgSrcRecordsGetVersion,0,
+ "The version of the source package."},
+ {}
+};
+
+static PyObject *PkgSrcRecordsNew(PyTypeObject *type,PyObject *args,PyObject *kwds) {
+ char *kwlist[] = {0};
+ if (PyArg_ParseTupleAndKeywords(args,kwds,"",kwlist) == 0)
+ return 0;
+
+ return HandleErrors(CppPyObject_NEW<PkgSrcRecordsStruct>(NULL, type));
+}
+
+static const char *sourcerecords_doc =
+ "SourceRecords()\n\n"
+ "Provide an easy way to look up the records of source packages and\n"
+ "provide easy attributes for some widely used fields of the record.";
+
+PyTypeObject PySourceRecords_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.SourceRecords", // tp_name
+ sizeof(CppPyObject<PkgSrcRecordsStruct>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<PkgSrcRecordsStruct>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE),
+ sourcerecords_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PkgSrcRecordsMethods, // tp_methods
+ 0, // tp_members
+ PkgSrcRecordsGetSet, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ PkgSrcRecordsNew, // tp_new
+};
+
+
+ /*}}}*/
+
diff --git a/python/policy.cc b/python/policy.cc
new file mode 100644
index 0000000..037a530
--- /dev/null
+++ b/python/policy.cc
@@ -0,0 +1,243 @@
+/*
+ * policy.cc - Wrapper around pkgPolicy
+ *
+ * Copyright 2009 Julian Andres Klode <jak@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+#include <Python.h>
+#include "apt_pkgmodule.h"
+#include "generic.h"
+#include <apt-pkg/policy.h>
+
+static PyObject *policy_new(PyTypeObject *type,PyObject *Args,
+ PyObject *kwds) {
+ PyObject *cache;
+ char *kwlist[] = {"cache", NULL};
+ if (PyArg_ParseTupleAndKeywords(Args, kwds, "O", kwlist, &cache) == 0)
+ return 0;
+ if (!PyObject_TypeCheck(cache, &PyCache_Type)) {
+ PyErr_SetString(PyExc_TypeError,"`cache` must be a apt_pkg.Cache().");
+ return 0;
+ }
+ pkgPolicy *policy = new pkgPolicy(GetCpp<pkgCache *>(cache));
+ return CppPyObject_NEW<pkgPolicy*>(cache,&PyPolicy_Type,policy);
+}
+
+static char *policy_get_priority_doc =
+ "get_priority(package: Union[apt_pkg.Package, apt_pkg.Version, apt_pkg.PackageFile]) -> int\n\n"
+ "Return the priority of the package.";
+
+PyObject *policy_get_priority(PyObject *self, PyObject *arg) {
+ pkgPolicy *policy = GetCpp<pkgPolicy *>(self);
+ if (PyObject_TypeCheck(arg, &PyVersion_Type)) {
+ auto ver = GetCpp<pkgCache::VerIterator>(arg);
+ return MkPyNumber(policy->GetPriority(ver));
+ } else if (PyObject_TypeCheck(arg, &PyPackageFile_Type)) {
+ pkgCache::PkgFileIterator pkgfile = GetCpp<pkgCache::PkgFileIterator>(arg);
+ return MkPyNumber(policy->GetPriority(pkgfile));
+ } else {
+ PyErr_SetString(PyExc_TypeError,"Argument must be of Version or PackageFile.");
+ return 0;
+ }
+}
+
+
+static char *policy_set_priority_doc =
+ "set_priority(which: Union[apt_pkg.Version, apt_pkg.PackageFile], priority: int) -> None\n\n"
+ "Override priority for the given package/file. Behavior is undefined if"
+ "a preferences file is read after that, or :meth:`init_defaults` is called.";
+static PyObject *policy_set_priority(PyObject *self, PyObject *args) {
+ PyObject *which;
+ signed short priority;
+ if (PyArg_ParseTuple(args, "Oh", &which, &priority) == 0)
+ return 0;
+ pkgPolicy *policy = GetCpp<pkgPolicy *>(self);
+
+ if (PyObject_TypeCheck(which, &PyVersion_Type)) {
+ auto ver = GetCpp<pkgCache::VerIterator>(which);
+ policy->SetPriority(ver, priority);
+ } else if (PyObject_TypeCheck(which, &PyPackageFile_Type)) {
+ auto pkgfile = GetCpp<pkgCache::PkgFileIterator>(which);
+ policy->SetPriority(pkgfile, priority);
+ } else {
+ PyErr_SetString(PyExc_TypeError,"Argument must be of Version or PackageFile.");
+ return 0;
+ }
+
+ HandleErrors();
+ Py_RETURN_NONE;
+}
+
+static char *policy_get_candidate_ver_doc =
+ "get_match(package: apt_pkg.Package) -> Optional[apt_pkg.Version]\n\n"
+ "Get the best package for the job.";
+
+PyObject *policy_get_candidate_ver(PyObject *self, PyObject *arg) {
+ if (PyObject_TypeCheck(arg, &PyPackage_Type)) {
+ pkgPolicy *policy = GetCpp<pkgPolicy *>(self);
+ pkgCache::PkgIterator pkg = GetCpp<pkgCache::PkgIterator>(arg);
+ pkgCache::VerIterator ver = policy->GetCandidateVer(pkg);
+ if (ver.end()) {
+ HandleErrors();
+ Py_RETURN_NONE;
+ }
+ return CppPyObject_NEW<pkgCache::VerIterator>(arg,&PyVersion_Type,
+ ver);
+ } else {
+ PyErr_SetString(PyExc_TypeError,"Argument must be of Package().");
+ return 0;
+ }
+}
+
+static char *policy_read_pinfile_doc =
+ "read_pinfile(filename: str) -> bool\n\n"
+ "Read the pin file given by filename (e.g. '/etc/apt/preferences')\n"
+ "and add it to the policy.";
+
+static PyObject *policy_read_pinfile(PyObject *self, PyObject *arg) {
+ PyApt_Filename name;
+ if (!name.init(arg))
+ return 0;
+ pkgPolicy *policy = GetCpp<pkgPolicy *>(self);
+
+ return PyBool_FromLong(ReadPinFile(*policy, name));
+}
+
+#if (APT_PKG_MAJOR > 4 || (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 8))
+static char *policy_read_pindir_doc =
+ "read_pindir(dirname: str) -> bool\n\n"
+ "Read the pin files in the given dir (e.g. '/etc/apt/preferences.d')\n"
+ "and add them to the policy.";
+
+static PyObject *policy_read_pindir(PyObject *self, PyObject *arg) {
+ PyApt_Filename name;
+ if (!name.init(arg))
+ return 0;
+ pkgPolicy *policy = GetCpp<pkgPolicy *>(self);
+
+ return PyBool_FromLong(ReadPinDir(*policy, name));
+}
+#endif
+
+static char *policy_create_pin_doc =
+ "create_pin(type: str, pkg: str, data: str, priority: int)\n\n"
+ "Create a pin for the policy. The parameter 'type' refers to one of the\n"
+ "strings 'Version', 'Release', or 'Origin'. The argument 'pkg' is the\n"
+ "name of the package. The parameter 'data' refers to the value\n"
+ "(e.g. 'unstable' for type='Release') and the other possible options.\n"
+ "The parameter 'priority' gives the priority of the pin.";
+
+static PyObject *policy_create_pin(PyObject *self, PyObject *args) {
+ pkgVersionMatch::MatchType match_type;
+ const char *type, *pkg, *data;
+ signed short priority;
+ if (PyArg_ParseTuple(args, "sssh", &type, &pkg, &data, &priority) == 0)
+ return 0;
+ pkgPolicy *policy = GetCpp<pkgPolicy *>(self);
+ if (strcmp(type,"Version") == 0 || strcmp(type, "version") == 0)
+ match_type = pkgVersionMatch::Version;
+ else if (strcmp(type,"Release") == 0 || strcmp(type, "release") == 0)
+ match_type = pkgVersionMatch::Release;
+ else if (strcmp(type,"Origin") == 0 || strcmp(type, "origin") == 0)
+ match_type = pkgVersionMatch::Origin;
+ else
+ match_type = pkgVersionMatch::None;
+ policy->CreatePin(match_type,pkg,data,priority);
+ HandleErrors();
+ Py_RETURN_NONE;
+}
+
+static char *policy_init_defaults_doc =
+ "init_defaults()\n\n"
+ "Initialize defaults. Needed after calling :meth:`create_pin()`\n"
+ "with an empty `pkg` argument";
+static PyObject *policy_init_defaults(PyObject *self, PyObject *args) {
+ if (PyArg_ParseTuple(args, "") == 0)
+ return 0;
+ pkgPolicy *policy = GetCpp<pkgPolicy *>(self);
+ policy->InitDefaults();
+ HandleErrors();
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef policy_methods[] = {
+ {"get_priority",(PyCFunction)policy_get_priority,METH_O,
+ policy_get_priority_doc},
+ {"set_priority",policy_set_priority,METH_VARARGS,policy_set_priority_doc},
+ {"get_candidate_ver",(PyCFunction)policy_get_candidate_ver,METH_O,
+ policy_get_candidate_ver_doc},
+ {"read_pinfile",(PyCFunction)policy_read_pinfile,METH_O,
+ policy_read_pinfile_doc},
+#if (APT_PKG_MAJOR > 4 || (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 8))
+ {"read_pindir",(PyCFunction)policy_read_pindir,METH_O,
+ policy_read_pindir_doc},
+#endif
+ {"create_pin",policy_create_pin,METH_VARARGS,policy_create_pin_doc},
+ {"init_defaults",policy_init_defaults,METH_VARARGS,policy_init_defaults_doc},
+ {}
+};
+
+static char *policy_doc =
+ "Policy(cache)\n\n"
+ "Representation of the policy of the Cache object given by cache. This\n"
+ "provides a superset of policy-related functionality compared to the\n"
+ "DepCache class. The DepCache can be used for most purposes, but there\n"
+ "may be some cases where a special policy class is needed.";
+
+PyTypeObject PyPolicy_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Policy", // tp_name
+ sizeof(CppPyObject<pkgPolicy*>),// tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<pkgPolicy*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE |
+ Py_TPFLAGS_HAVE_GC),
+ policy_doc, // tp_doc
+ CppTraverse<pkgPolicy*>, // tp_traverse
+ CppClear<pkgPolicy*>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ policy_methods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ policy_new, // tp_new
+};
diff --git a/python/progress.cc b/python/progress.cc
new file mode 100644
index 0000000..f4ed8e6
--- /dev/null
+++ b/python/progress.cc
@@ -0,0 +1,473 @@
+// Description /*{{{*/
+// $Id: progress.cc,v 1.5 2003/06/03 03:03:23 mvo Exp $
+/* ######################################################################
+
+ Progress - Wrapper for the progress related functions
+
+ ##################################################################### */
+#include <Python.h>
+#include <iostream>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <map>
+#include <utility>
+#include <apt-pkg/acquire-item.h>
+#include <apt-pkg/acquire-worker.h>
+#include <apt-pkg/install-progress.h>
+#include "progress.h"
+#include "generic.h"
+#include "apt_pkgmodule.h"
+
+/**
+ * Set an attribute on an object, after creating the value with
+ * Py_BuildValue(fmt, arg). Afterwards, decrease its refcount and return
+ * whether setting the attribute was successful.
+ */
+template<class T>
+inline bool setattr(PyObject *object, const char *attr, const char *fmt, T arg)
+{
+ if (!object)
+ return false;
+ PyObject *value = Py_BuildValue(fmt, arg);
+ if (value == NULL)
+ return false;
+
+ int result = PyObject_SetAttrString(object, attr, value);
+ Py_DECREF(value);
+ return result != -1;
+}
+
+inline PyObject *TUPLEIZE(PyObject *op) {
+ PyObject *ret = Py_BuildValue("(O)", op);
+ Py_DECREF(op);
+ return ret;
+}
+
+// generic
+bool PyCallbackObj::RunSimpleCallback(const char* method_name,
+ PyObject *arglist,
+ PyObject **res)
+{
+ if(callbackInst == 0) {
+ Py_XDECREF(arglist);
+ return false;
+ }
+
+ PyObject *method = PyObject_GetAttrString(callbackInst,(char*) method_name);
+ if(method == NULL) {
+ Py_XDECREF(arglist);
+ if (res) {
+ Py_INCREF(Py_None);
+ *res = Py_None;
+ }
+ return false;
+ }
+
+ PyObject *result = PyObject_CallObject(method, arglist);
+ Py_XDECREF(arglist);
+
+ if(result == NULL) {
+ // exception happend
+ std::cerr << "Error in function " << method_name << std::endl;
+ PyErr_Print();
+ PyErr_Clear();
+
+ return false;
+ }
+ if(res != NULL)
+ *res = result;
+ else
+ Py_XDECREF(result);
+ Py_XDECREF(method);
+
+ return true;
+}
+
+
+// OpProgress interface
+void PyOpProgress::Update()
+{
+ // Build up the argument list...
+ if(!CheckChange(0.7))
+ return;
+
+ setattr(callbackInst, "op", "s", Op.c_str());
+ setattr(callbackInst, "subop", "s", SubOp.c_str());
+ setattr(callbackInst, "major_change", "b", MajorChange);
+ setattr(callbackInst, "percent", "N", MkPyNumber(Percent));
+ RunSimpleCallback("update");
+}
+
+void PyOpProgress::Done()
+{
+ RunSimpleCallback("done");
+}
+
+
+
+// fetcher interface
+
+
+
+// apt interface
+
+PyObject *PyFetchProgress::GetDesc(pkgAcquire::ItemDesc *item) {
+ if (!pyAcquire && item->Owner && item->Owner->GetOwner()) {
+ pyAcquire = PyAcquire_FromCpp(item->Owner->GetOwner(), false, NULL);
+ }
+ PyObject *pyItem = PyAcquireItem_FromCpp(item->Owner, false, pyAcquire);
+ PyObject *pyDesc = PyAcquireItemDesc_FromCpp(item, false, pyItem);
+ Py_DECREF(pyItem);
+ return pyDesc;
+}
+
+bool PyFetchProgress::MediaChange(std::string Media, std::string Drive)
+{
+ PyCbObj_END_ALLOW_THREADS
+ PyObject *arglist = Py_BuildValue("(ss)", Media.c_str(), Drive.c_str());
+ PyObject *result = NULL;
+
+ if(PyObject_HasAttrString(callbackInst, "mediaChange"))
+ RunSimpleCallback("mediaChange", arglist, &result);
+ else
+ RunSimpleCallback("media_change", arglist, &result);
+
+ bool res = true;
+ if(!PyArg_Parse(result, "b", &res)) {
+ // no return value or None, assume false
+ PyCbObj_BEGIN_ALLOW_THREADS
+ return false;
+ }
+
+ PyCbObj_BEGIN_ALLOW_THREADS
+ return res;
+}
+
+void PyFetchProgress::UpdateStatus(pkgAcquire::ItemDesc &Itm, int status)
+{
+ // Added object file size and object partial size to
+ // parameters that are passed to updateStatus.
+ // -- Stephan
+ PyObject *arglist = Py_BuildValue("(sssNNN)", Itm.URI.c_str(),
+ Itm.Description.c_str(),
+ Itm.ShortDesc.c_str(),
+ MkPyNumber(status),
+ MkPyNumber(Itm.Owner->FileSize),
+ MkPyNumber(Itm.Owner->PartialSize));
+
+ RunSimpleCallback("update_status_full", arglist);
+
+ // legacy version of the interface
+
+ arglist = Py_BuildValue("(sssN)", Itm.URI.c_str(), Itm.Description.c_str(),
+ Itm.ShortDesc.c_str(), MkPyNumber(status));
+
+ if(PyObject_HasAttrString(callbackInst, "updateStatus"))
+ RunSimpleCallback("updateStatus", arglist);
+ else
+ RunSimpleCallback("update_status", arglist);
+}
+
+void PyFetchProgress::IMSHit(pkgAcquire::ItemDesc &Itm)
+{
+ PyCbObj_END_ALLOW_THREADS
+ if (PyObject_HasAttrString(callbackInst, "ims_hit"))
+ RunSimpleCallback("ims_hit", TUPLEIZE(GetDesc(&Itm)));
+ else
+ UpdateStatus(Itm, DLHit);
+ PyCbObj_BEGIN_ALLOW_THREADS
+}
+
+void PyFetchProgress::Fetch(pkgAcquire::ItemDesc &Itm)
+{
+ PyCbObj_END_ALLOW_THREADS
+ if (PyObject_HasAttrString(callbackInst, "fetch"))
+ RunSimpleCallback("fetch", TUPLEIZE(GetDesc(&Itm)));
+ else
+ UpdateStatus(Itm, DLQueued);
+ PyCbObj_BEGIN_ALLOW_THREADS
+}
+
+void PyFetchProgress::Done(pkgAcquire::ItemDesc &Itm)
+{
+ PyCbObj_END_ALLOW_THREADS
+ if (PyObject_HasAttrString(callbackInst, "done"))
+ RunSimpleCallback("done", TUPLEIZE(GetDesc(&Itm)));
+ else
+ UpdateStatus(Itm, DLDone);
+ PyCbObj_BEGIN_ALLOW_THREADS
+}
+
+void PyFetchProgress::Fail(pkgAcquire::ItemDesc &Itm)
+{
+ PyCbObj_END_ALLOW_THREADS
+ if (PyObject_HasAttrString(callbackInst, "fail")) {
+ RunSimpleCallback("fail", TUPLEIZE(GetDesc(&Itm)));
+ PyCbObj_BEGIN_ALLOW_THREADS
+ return;
+ }
+
+ // Ignore certain kinds of transient failures (bad code)
+ if (Itm.Owner->Status == pkgAcquire::Item::StatIdle) {
+ PyCbObj_BEGIN_ALLOW_THREADS
+ return;
+ }
+
+ if (Itm.Owner->Status == pkgAcquire::Item::StatDone)
+ {
+ UpdateStatus(Itm, DLIgnored);
+ }
+
+
+ if (PyObject_HasAttrString(callbackInst, "fail"))
+ RunSimpleCallback("fail", TUPLEIZE(GetDesc(&Itm)));
+ else
+ UpdateStatus(Itm, DLFailed);
+ PyCbObj_BEGIN_ALLOW_THREADS
+}
+
+void PyFetchProgress::Start()
+{
+ pkgAcquireStatus::Start();
+
+
+ RunSimpleCallback("start");
+ /* After calling the start method we can safely allow
+ * other Python threads to do their work for now.
+ */
+ PyCbObj_BEGIN_ALLOW_THREADS
+}
+
+
+void PyFetchProgress::Stop()
+{
+ /* After the stop operation occurred no other threads
+ * are allowed. This is done so we have a matching
+ * PyCbObj_END_ALLOW_THREADS to our previous
+ * PyCbObj_BEGIN_ALLOW_THREADS (Python requires this!).
+ */
+
+ PyCbObj_END_ALLOW_THREADS
+ pkgAcquireStatus::Stop();
+ RunSimpleCallback("stop");
+}
+
+bool PyFetchProgress::Pulse(pkgAcquire * Owner)
+{
+ PyCbObj_END_ALLOW_THREADS
+ pkgAcquireStatus::Pulse(Owner);
+
+ if(callbackInst == 0) {
+ PyCbObj_BEGIN_ALLOW_THREADS
+ return false;
+ }
+
+ setattr(callbackInst, "last_bytes", "N", MkPyNumber(LastBytes));
+ setattr(callbackInst, "current_cps", "N", MkPyNumber(CurrentCPS));
+ setattr(callbackInst, "current_bytes", "N", MkPyNumber(CurrentBytes));
+ setattr(callbackInst, "total_bytes", "N", MkPyNumber(TotalBytes));
+ setattr(callbackInst, "fetched_bytes", "N", MkPyNumber(FetchedBytes));
+ setattr(callbackInst, "elapsed_time", "N", MkPyNumber(ElapsedTime));
+ setattr(callbackInst, "current_items", "N", MkPyNumber(CurrentItems));
+ setattr(callbackInst, "total_items", "N", MkPyNumber(TotalItems));
+
+ // New style
+ if (!PyObject_HasAttrString(callbackInst, "updateStatus")) {
+ PyObject *result1;
+ bool res1 = true;
+
+ if (pyAcquire == NULL) {
+ pyAcquire = PyAcquire_FromCpp(Owner, false, NULL);
+ }
+ Py_INCREF(pyAcquire);
+
+ if (RunSimpleCallback("pulse", TUPLEIZE(pyAcquire) , &result1)) {
+ if (result1 != NULL &&
+ result1 != Py_None &&
+ PyArg_Parse(result1, "b", &res1) &&
+ res1 == false) {
+ // the user returned a explicit false here, stop
+ PyCbObj_BEGIN_ALLOW_THREADS
+ return false;
+ }
+ }
+ PyCbObj_BEGIN_ALLOW_THREADS
+ return true;
+ }
+ return false;
+}
+
+
+
+// install progress
+
+void PyInstallProgress::StartUpdate()
+{
+ RunSimpleCallback("start_update");
+ PyCbObj_BEGIN_ALLOW_THREADS
+}
+
+void PyInstallProgress::UpdateInterface()
+{
+ PyCbObj_END_ALLOW_THREADS
+ RunSimpleCallback("update_interface");
+ PyCbObj_BEGIN_ALLOW_THREADS
+}
+
+void PyInstallProgress::FinishUpdate()
+{
+ PyCbObj_END_ALLOW_THREADS
+ RunSimpleCallback("finish_update");
+}
+
+pkgPackageManager::OrderResult PyInstallProgress::Run(pkgPackageManager *pm)
+{
+ pkgPackageManager::OrderResult res;
+ int ret;
+ pid_t child_id;
+
+#if 0 // FIXME: this needs to be merged into apt to support medium swaping
+ res = pm->DoInstallPreFork();
+ if (res == pkgPackageManager::Failed)
+ return res;
+#endif
+
+ // support custom fork methods
+ if(PyObject_HasAttrString(callbackInst, "fork")) {
+ PyObject *method = PyObject_GetAttrString(callbackInst, "fork");
+ PyObject *arglist = Py_BuildValue("()");
+ PyObject *result = PyObject_CallObject(method, arglist);
+ Py_DECREF(arglist);
+ if (result == NULL) {
+ std::cerr << "fork method invalid" << std::endl;
+ PyErr_Print();
+ return pkgPackageManager::Failed;
+ }
+ if(!PyArg_Parse(result, "i", &child_id) ) {
+ std::cerr << "custom fork() result could not be parsed?"<< std::endl;
+ return pkgPackageManager::Failed;
+ }
+ } else {
+ child_id = fork();
+ }
+
+ PyObject *child_o = MkPyNumber(child_id);
+ PyObject_SetAttrString(callbackInst, "child_pid", child_o);
+ Py_DECREF(child_o);
+
+#if 0 // FIXME: this needs to be merged into apt to support medium swaping
+ if (child_id == 0) {
+ res = pm->DoInstallPostFork();
+ _exit(res);
+ }
+#endif
+ if (child_id == 0) {
+ PyObject *v = PyObject_GetAttrString(callbackInst, "writefd");
+ if(v) {
+ int fd = PyObject_AsFileDescriptor(v);
+
+ APT::Progress::PackageManagerProgressFd progress(fd);
+ res = pm->DoInstall(&progress);
+ } else {
+ APT::Progress::PackageManagerProgressFd progress(-1);
+ res = pm->DoInstall(&progress);
+ }
+ _exit(res);
+ }
+
+ StartUpdate();
+
+
+ PyCbObj_END_ALLOW_THREADS
+ if(PyObject_HasAttrString(callbackInst, "waitChild") ||
+ PyObject_HasAttrString(callbackInst, "wait_child")) {
+ PyObject *method;
+ if (PyObject_HasAttrString(callbackInst, "waitChild"))
+ method = PyObject_GetAttrString(callbackInst, "waitChild");
+ else
+ method = PyObject_GetAttrString(callbackInst, "wait_child");
+ PyObject *result = PyObject_CallObject(method, NULL);
+ if (result == NULL) {
+ std::cerr << "waitChild method invalid" << std::endl;
+ PyErr_Print();
+ PyCbObj_BEGIN_ALLOW_THREADS
+ return pkgPackageManager::Failed;
+ }
+ if(!PyArg_Parse(result, "i", &res) ) {
+ std::cerr << "custom waitChild() result could not be parsed?"<< std::endl;
+ PyCbObj_BEGIN_ALLOW_THREADS
+ return pkgPackageManager::Failed;
+ }
+ PyCbObj_BEGIN_ALLOW_THREADS
+ } else {
+ PyCbObj_BEGIN_ALLOW_THREADS
+ while (waitpid(child_id, &ret, WNOHANG) == 0) {
+ PyCbObj_END_ALLOW_THREADS
+ UpdateInterface();
+ PyCbObj_BEGIN_ALLOW_THREADS
+ }
+
+ res = (pkgPackageManager::OrderResult) WEXITSTATUS(ret);
+ }
+
+ FinishUpdate();
+
+ return res;
+}
+
+
+//-----------------------------------------------------------------------------
+// apt-cdrom interface
+
+void PyCdromProgress::Update(std::string text, int current)
+{
+ PyObject *arglist = Py_BuildValue("(si)", text.c_str(), current);
+ setattr(callbackInst, "total_steps", "i", totalSteps);
+ RunSimpleCallback("update", arglist);
+}
+
+bool PyCdromProgress::ChangeCdrom()
+{
+ PyObject *arglist = Py_BuildValue("()");
+ PyObject *result = NULL;
+ if (PyObject_HasAttrString(callbackInst, "changeCdrom"))
+ RunSimpleCallback("changeCdrom", arglist, &result);
+ else
+ RunSimpleCallback("change_cdrom", arglist, &result);
+
+ bool res = true;
+ if(!PyArg_Parse(result, "b", &res))
+ std::cerr << "ChangeCdrom: result could not be parsed" << std::endl;
+
+ return res;
+}
+
+
+bool PyCdromProgress::AskCdromName(std::string &Name)
+{
+ PyObject *arglist = Py_BuildValue("()");
+ const char *new_name;
+ bool res;
+ PyObject *result = NULL;
+
+ // Old style: (True, name) on success, (False, name) on failure.
+ if (PyObject_HasAttrString(callbackInst, "askAdromName")) {
+ RunSimpleCallback("askAdromName", arglist, &result);
+ if(!PyArg_Parse(result, "(bs)", &res, &new_name))
+ std::cerr << "AskCdromName: result could not be parsed" << std::endl;
+ // set the new name
+ Name =std:: string(new_name);
+ return res;
+ }
+ // New style: String on success, None on failure.
+ else {
+ RunSimpleCallback("ask_cdrom_name", arglist, &result);
+ if(result == Py_None)
+ return false;
+ if(!PyArg_Parse(result, "s", &new_name))
+ std::cerr << "ask_cdrom_name: result could not be parsed" << std::endl;
+ else
+ Name = std::string(new_name);
+ return true;
+ }
+}
diff --git a/python/progress.h b/python/progress.h
new file mode 100644
index 0000000..b46ac98
--- /dev/null
+++ b/python/progress.h
@@ -0,0 +1,120 @@
+// Description /*{{{*/
+// $Id: progress.h,v 1.5 2003/06/03 03:03:23 mdz Exp $
+/* ######################################################################
+
+ Progress - Wrapper for the progress related functions
+
+ ##################################################################### */
+
+#ifndef PROGRESS_H
+#define PROGRESS_H
+
+#include <apt-pkg/progress.h>
+#include <apt-pkg/acquire.h>
+#include <apt-pkg/packagemanager.h>
+#include <apt-pkg/cdrom.h>
+#include <Python.h>
+
+/* PyCbObj_BEGIN_ALLOW_THREADS and PyCbObj_END_ALLOW_THREADS are sligthly
+ * modified versions of Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS.
+ * Instead of storing the thread state in a function-local variable these
+ * use a class attribute (with the same) name, allowing blocking and
+ * unblocking from different class methods.
+ * Py_BLOCK_THREADS and Py_UNBLOCK_THREADS do not define their own
+ * local variable but use the one provided by PyCbObj_BEGIN_ALLOW_THREADS
+ * and thus are the same as Py_BLOCK_THREADS and Py_UNBLOCK_THREADS.
+ */
+#define PyCbObj_BEGIN_ALLOW_THREADS \
+ _save = PyEval_SaveThread();
+#define PyCbObj_END_ALLOW_THREADS \
+ PyEval_RestoreThread(_save); \
+ _save = NULL;
+#define PyCbObj_BLOCK_THREADS Py_BLOCK_THREADS
+#define PyCbObj_UNBLOCK_THREADS Py_UNBLOCK_THREADS
+
+class PyCallbackObj {
+ protected:
+ PyObject *callbackInst;
+ PyThreadState *_save;
+
+ public:
+ void setCallbackInst(PyObject *o) {
+ Py_INCREF(o);
+ callbackInst = o;
+ }
+
+ bool RunSimpleCallback(const char *method, PyObject *arglist=NULL,
+ PyObject **result=NULL);
+
+ PyCallbackObj() : callbackInst(0), _save(0) {};
+ ~PyCallbackObj() {Py_DECREF(callbackInst); };
+};
+
+struct PyOpProgress : public OpProgress, public PyCallbackObj
+{
+
+ virtual void Update();
+ virtual void Done();
+
+ PyOpProgress() : OpProgress(), PyCallbackObj() {};
+};
+
+
+struct PyFetchProgress : public pkgAcquireStatus, public PyCallbackObj
+{
+ protected:
+ PyObject *pyAcquire;
+ PyObject *GetDesc(pkgAcquire::ItemDesc *item);
+ public:
+ enum {
+ DLDone, DLQueued, DLFailed, DLHit, DLIgnored
+ };
+
+ void UpdateStatus(pkgAcquire::ItemDesc & Itm, int status);
+
+ virtual bool MediaChange(std::string Media, std::string Drive);
+
+ void setPyAcquire(PyObject *o) {
+ Py_CLEAR(pyAcquire);
+ Py_INCREF(o);
+ pyAcquire = o;
+ }
+
+ /* apt stuff */
+ virtual void IMSHit(pkgAcquire::ItemDesc &Itm);
+ virtual void Fetch(pkgAcquire::ItemDesc &Itm);
+ virtual void Done(pkgAcquire::ItemDesc &Itm);
+ virtual void Fail(pkgAcquire::ItemDesc &Itm);
+ virtual void Start();
+ virtual void Stop();
+
+ bool Pulse(pkgAcquire * Owner);
+ PyFetchProgress() : PyCallbackObj(), pyAcquire(0) {};
+ ~PyFetchProgress() { Py_XDECREF(pyAcquire); };
+};
+
+struct PyInstallProgress : public PyCallbackObj
+{
+ void StartUpdate();
+ void UpdateInterface();
+ void FinishUpdate();
+
+ pkgPackageManager::OrderResult Run(pkgPackageManager *pm);
+
+ PyInstallProgress() : PyCallbackObj() {};
+};
+
+struct PyCdromProgress : public pkgCdromStatus, public PyCallbackObj
+{
+ // update steps, will be called regularly as a "pulse"
+ virtual void Update(std::string text="", int current=0);
+ // ask for cdrom insert
+ virtual bool ChangeCdrom();
+ // ask for cdrom name
+ virtual bool AskCdromName(std::string &Name);
+
+ PyCdromProgress() : PyCallbackObj() {};
+};
+
+
+#endif
diff --git a/python/python-apt-helpers.cc b/python/python-apt-helpers.cc
new file mode 100644
index 0000000..bc58d93
--- /dev/null
+++ b/python/python-apt-helpers.cc
@@ -0,0 +1,69 @@
+/*
+ * python-apt.h - Common object creation functions for the public API
+ *
+ * Copyright 2010 Julian Andres Klode <jak@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include "apt_pkgmodule.h"
+
+/**
+ * Short macro to be used for the generic FromCpp functions.
+ *
+ */
+#define NEW_FROM(NAME,TYPE,Cpp) \
+PyObject* NAME(Cpp const &obj, bool Delete, PyObject *Owner) \
+{ \
+ CppPyObject<Cpp> *Obj = CppPyObject_NEW<Cpp>(Owner, TYPE, obj); \
+ Obj->NoDelete = (!Delete); \
+ return Obj; \
+}
+
+// Create all those functions
+NEW_FROM(PyAcquireFile_FromCpp,&PyAcquireFile_Type,pkgAcqFile*)
+NEW_FROM(PyAcquireItem_FromCpp,&PyAcquireItem_Type,pkgAcquire::Item*)
+NEW_FROM(PyAcquireItemDesc_FromCpp,&PyAcquireItemDesc_Type,pkgAcquire::ItemDesc*)
+NEW_FROM(PyAcquireWorker_FromCpp,&PyAcquireWorker_Type,pkgAcquire::Worker*)
+NEW_FROM(PyActionGroup_FromCpp,&PyActionGroup_Type,pkgDepCache::ActionGroup*)
+NEW_FROM(PyCache_FromCpp,&PyCache_Type,pkgCache*)
+NEW_FROM(PyCacheFile_FromCpp,&PyCacheFile_Type,pkgCacheFile*)
+NEW_FROM(PyCdrom_FromCpp,&PyCdrom_Type,pkgCdrom)
+NEW_FROM(PyConfiguration_FromCpp,&PyConfiguration_Type,Configuration*)
+NEW_FROM(PyDepCache_FromCpp,&PyDepCache_Type,pkgDepCache*)
+NEW_FROM(PyDependency_FromCpp,&PyDependency_Type,pkgCache::DepIterator)
+//NEW_FROM(PyDependencyList_FromCpp,&PyDependencyList_Type,RDepListStruct)
+NEW_FROM(PyDescription_FromCpp,&PyDescription_Type,pkgCache::DescIterator)
+NEW_FROM(PyHashes_FromCpp,&PyHashes_Type,Hashes)
+NEW_FROM(PyHashString_FromCpp,&PyHashString_Type,HashString*)
+NEW_FROM(PyMetaIndex_FromCpp,&PyMetaIndex_Type,metaIndex*)
+NEW_FROM(PyPackage_FromCpp,&PyPackage_Type,pkgCache::PkgIterator)
+NEW_FROM(PyGroup_FromCpp,&PyGroup_Type,pkgCache::GrpIterator)
+NEW_FROM(PyIndexFile_FromCpp,&PyIndexFile_Type,pkgIndexFile*)
+NEW_FROM(PyOrderList_FromCpp,&PyOrderList_Type,pkgOrderList*)
+NEW_FROM(PyPackageFile_FromCpp,&PyPackageFile_Type,pkgCache::PkgFileIterator)
+//NEW_FROM(PyPackageList_FromCpp,&PyPackageList_Type,PkgListStruct)
+NEW_FROM(PyPackageManager_FromCpp,&PyPackageManager_Type,pkgPackageManager*)
+//NEW_FROM(PyPackageRecords_FromCpp,&PyPackageRecords_Type,PkgRecordsStruct)
+NEW_FROM(PyPolicy_FromCpp,&PyPolicy_Type,pkgPolicy*)
+NEW_FROM(PyProblemResolver_FromCpp,&PyProblemResolver_Type,pkgProblemResolver*)
+NEW_FROM(PySourceList_FromCpp,&PySourceList_Type,pkgSourceList*)
+//NEW_FROM(PySourceRecords_FromCpp,&PySourceRecords_Type,PkgSrcRecordsStruct)
+NEW_FROM(PyTagFile_FromCpp,&PyTagFile_Type,pkgTagFile)
+NEW_FROM(PyTagSection_FromCpp,&PyTagSection_Type,pkgTagSection)
+NEW_FROM(PyVersion_FromCpp,&PyVersion_Type,pkgCache::VerIterator)
+
+#undef NEW_FROM
diff --git a/python/python-apt.h b/python/python-apt.h
new file mode 100644
index 0000000..e3c81b0
--- /dev/null
+++ b/python/python-apt.h
@@ -0,0 +1,368 @@
+/*
+ * python-apt.h - Header file for the public interface.
+ *
+ * Copyright 2009-2010 Julian Andres Klode <jak@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifndef PYTHON_APT_H
+#define PYTHON_APT_H
+#include <Python.h>
+#include "generic.h"
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/acquire-item.h>
+#include <apt-pkg/packagemanager.h>
+#include <apt-pkg/version.h>
+#include <apt-pkg/deblistparser.h>
+#include <apt-pkg/pkgcache.h>
+#include <apt-pkg/cachefile.h>
+#include <apt-pkg/tagfile.h>
+#include <apt-pkg/init.h>
+#include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/cdrom.h>
+#include <apt-pkg/algorithms.h>
+#include <apt-pkg/hashes.h>
+
+typedef PyObject *ActionGroupF(pkgDepCache::ActionGroup *);
+typedef pkgDepCache::ActionGroup*& ActionGroupT(PyObject *self);
+
+struct _PyAptPkgAPIStruct {
+ // apt_pkg.Acquire (pkgAcquire*)
+ PyTypeObject *acquire_type;
+ PyObject* (*acquire_fromcpp)(pkgAcquire *acquire, bool Delete, PyObject*);
+ pkgAcquire*& (*acquire_tocpp)(PyObject *self);
+ // apt_pkg.AcquireFile
+ PyTypeObject *acquirefile_type;
+ PyObject* (*acquirefile_fromcpp)(pkgAcqFile* const &obj, bool Delete, PyObject *Owner);
+ pkgAcqFile*& (*acquirefile_tocpp)(PyObject *self);
+
+ // apt_pkg.AcquireItem
+ PyTypeObject *acquireitem_type;
+ PyObject* (*acquireitem_fromcpp)(pkgAcquire::Item* const &obj, bool Delete, PyObject *Owner);
+ pkgAcquire::Item*& (*acquireitem_tocpp)(PyObject *self);
+ // apt_pkg.AcquireItemDesc
+ PyTypeObject *acquireitemdesc_type;
+ PyObject* (*acquireitemdesc_fromcpp)(pkgAcquire::ItemDesc* const &obj, bool Delete, PyObject *Owner);
+ pkgAcquire::ItemDesc*& (*acquireitemdesc_tocpp)(PyObject *self);
+
+ PyTypeObject *acquireworker_type;
+ PyObject* (*acquireworker_fromcpp)(pkgAcquire::Worker* const &obj, bool Delete, PyObject *Owner);
+ pkgAcquire::Worker*& (*acquireworker_tocpp)(PyObject *self);
+
+ PyTypeObject *actiongroup_type;
+ PyObject* (*actiongroup_fromcpp)(pkgDepCache::ActionGroup* const &obj, bool Delete, PyObject *Owner);
+ pkgDepCache::ActionGroup*& (*actiongroup_tocpp)(PyObject *self);
+
+ PyTypeObject *cache_type;
+ PyObject* (*cache_fromcpp)(pkgCache* const &obj, bool Delete, PyObject *Owner);
+ pkgCache*& (*cache_tocpp)(PyObject *self);
+
+ PyTypeObject *cachefile_type;
+ PyObject* (*cachefile_fromcpp)(pkgCacheFile* const &obj, bool Delete, PyObject *Owner);
+ pkgCacheFile*& (*cachefile_tocpp)(PyObject *self);
+
+ PyTypeObject *cdrom_type;
+ PyObject* (*cdrom_fromcpp)(pkgCdrom const &obj, bool Delete, PyObject *Owner);
+ pkgCdrom& (*cdrom_tocpp)(PyObject *self);
+
+ PyTypeObject *configuration_type;
+ PyObject* (*configuration_fromcpp)(Configuration* const &obj, bool Delete, PyObject *Owner);
+ Configuration*& (*configuration_tocpp)(PyObject *self);
+
+ PyTypeObject *depcache_type;
+ PyObject* (*depcache_fromcpp)(pkgDepCache* const &obj, bool Delete, PyObject *Owner);
+ pkgDepCache*& (*depcache_tocpp)(PyObject *self);
+
+ PyTypeObject *dependency_type;
+ PyObject* (*dependency_fromcpp)(pkgCache::DepIterator const &obj, bool Delete, PyObject *Owner);
+ pkgCache::DepIterator& (*dependency_tocpp)(PyObject *self);
+
+ PyTypeObject *dependencylist_type;
+ void *dependencylist_fromcpp; // FIXME: need dependencylist_fromcpp
+ void *dependencylist_tocpp; // FIXME: need dependencylist_tocpp
+
+ PyTypeObject *description_type;
+ PyObject* (*description_fromcpp)(pkgCache::DescIterator const &obj, bool Delete, PyObject *Owner);
+ pkgCache::DescIterator& (*description_tocpp)(PyObject *self);
+
+ PyTypeObject *hashes_type;
+ PyObject* (*hashes_fromcpp)(Hashes const &obj, bool Delete, PyObject *Owner);
+ Hashes& (*hashes_tocpp)(PyObject *self);
+
+ PyTypeObject *hashstring_type;
+ PyObject* (*hashstring_fromcpp)(HashString* const &obj, bool Delete, PyObject *Owner);
+ HashString*& (*hashstring_tocpp)(PyObject *self);
+
+ PyTypeObject *metaindex_type;
+ PyObject* (*metaindex_fromcpp)(metaIndex* const &obj, bool Delete, PyObject *Owner);
+ metaIndex*& (*metaindex_tocpp)(PyObject *self);
+
+ PyTypeObject *package_type;
+ PyObject* (*package_fromcpp)(pkgCache::PkgIterator const &obj, bool Delete, PyObject *Owner);
+ pkgCache::PkgIterator& (*package_tocpp)(PyObject *self);
+
+ PyTypeObject *packagefile_type;
+ PyObject* (*packagefile_fromcpp)(pkgCache::PkgFileIterator const &obj, bool Delete, PyObject *Owner);
+ pkgCache::PkgFileIterator& (*packagefile_tocpp)(PyObject *self);
+
+ PyTypeObject *packageindexfile_type;
+ PyObject* (*indexfile_fromcpp)(pkgIndexFile* const &obj, bool Delete, PyObject *Owner);
+ pkgIndexFile*& (*packageindexfile_tocpp)(PyObject *self);
+
+ PyTypeObject *packagelist_type;
+ void *packagelist_fromcpp; // FIXME: need packagelist_fromcpp
+ void *packagelist_tocpp; // FIXME: need packagelist_tocpp
+
+ PyTypeObject *packagemanager_type;
+ PyObject* (*packagemanager_fromcpp)(pkgPackageManager* const &obj, bool Delete, PyObject *Owner);
+ pkgPackageManager*& (*packagemanager_tocpp)(PyObject *self);
+
+ PyTypeObject *packagerecords_type;
+ void *packagerecords_fromcpp; // FIXME: need packagerecords_fromcpp
+ void *packagerecords_tocpp; // FIXME: need packagerecords_tocpp
+
+ PyTypeObject *policy_type;
+ PyObject* (*policy_fromcpp)(pkgPolicy* const &obj, bool Delete, PyObject *Owner);
+ pkgPolicy*& (*policy_tocpp)(PyObject *self);
+
+ PyTypeObject *problemresolver_type;
+ PyObject* (*problemresolver_fromcpp)(pkgProblemResolver* const &obj, bool Delete, PyObject *Owner);
+ pkgProblemResolver*& (*problemresolver_tocpp)(PyObject *self);
+
+ PyTypeObject *sourcelist_type;
+ PyObject* (*sourcelist_fromcpp)(pkgSourceList* const &obj, bool Delete, PyObject *Owner);
+ pkgSourceList*& (*sourcelist_tocpp)(PyObject *self);
+
+ PyTypeObject *sourcerecords_type;
+ void *sourcerecords_fromcpp; // FIXME: need sourcerecords_fromcpp
+ void *sourcerecords_tocpp; // FIXME: need sourcerecords_tocpp
+
+ PyTypeObject *tagfile_type;
+ PyObject* (*tagfile_fromcpp)(pkgTagFile const &obj, bool Delete, PyObject *Owner);
+ pkgTagFile& (*tagfile_tocpp)(PyObject *self);
+
+ PyTypeObject *tagsection_type;
+ PyObject* (*tagsection_fromcpp)(pkgTagSection const &obj, bool Delete, PyObject *Owner);
+ pkgTagSection& (*tagsection_tocpp)(PyObject *self);
+
+ PyTypeObject *version_type;
+ PyObject* (*version_fromcpp)(pkgCache::VerIterator const &obj, bool Delete, PyObject *Owner);
+ pkgCache::VerIterator& (*version_tocpp)(PyObject *self);
+
+ PyTypeObject *group_type;
+ PyObject* (*group_fromcpp)(pkgCache::GrpIterator const &obj, bool Delete, PyObject *Owner);
+ pkgCache::GrpIterator& (*group_tocpp)(PyObject *self);
+
+ PyTypeObject *orderlist_type;
+ PyObject* (*orderlist_fromcpp)(pkgOrderList* const &obj, bool Delete, PyObject *Owner);
+ pkgOrderList*& (*orderlist_tocpp)(PyObject *self);
+
+ PyTypeObject *sourcerecordfiles_type;
+ void *sourcerecordfiles_fromcpp; // FIXME: need sourcerecordfiles_fromcpp
+ void *sourcerecordfiles_tocpp; // FIXME: need sourcerecordfiles_tocpp
+};
+
+// Checking macros.
+# define PyAcquire_Check(op) PyObject_TypeCheck(op, &PyAcquire_Type)
+# define PyAcquireFile_Check(op) PyObject_TypeCheck(op, &PyAcquireFile_Type)
+# define PyAcquireItem_Check(op) PyObject_TypeCheck(op, &PyAcquireItem_Type)
+# define PyAcquireItemDesc_Check(op) PyObject_TypeCheck(op, &PyAcquireItemDesc_Type)
+# define PyAcquireWorker_Check(op) PyObject_TypeCheck(op, &PyAcquireWorker_Type)
+# define PyActionGroup_Check(op) PyObject_TypeCheck(op, &PyActionGroup_Type)
+# define PyCache_Check(op) PyObject_TypeCheck(op, &PyCache_Type)
+# define PyCacheFile_Check(op) PyObject_TypeCheck(op, &PyCacheFile_Type)
+# define PyCdrom_Check(op) PyObject_TypeCheck(op, &PyCdrom_Type)
+# define PyConfiguration_Check(op) PyObject_TypeCheck(op, &PyConfiguration_Type)
+# define PyDepCache_Check(op) PyObject_TypeCheck(op, &PyDepCache_Type)
+# define PyDependency_Check(op) PyObject_TypeCheck(op, &PyDependency_Type)
+# define PyDependencyList_Check(op) PyObject_TypeCheck(op, &PyDependencyList_Type)
+# define PyDescription_Check(op) PyObject_TypeCheck(op, &PyDescription_Type)
+# define PyGroup_Check(op) PyObject_TypeCheck(op, &PyGroup_Type)
+# define PyHashes_Check(op) PyObject_TypeCheck(op, &PyHashes_Type)
+# define PyHashString_Check(op) PyObject_TypeCheck(op, &PyHashString_Type)
+# define PyIndexRecords_Check(op) PyObject_TypeCheck(op, &PyIndexRecords_Type)
+# define PyMetaIndex_Check(op) PyObject_TypeCheck(op, &PyMetaIndex_Type)
+# define PyPackage_Check(op) PyObject_TypeCheck(op, &PyPackage_Type)
+# define PyPackageFile_Check(op) PyObject_TypeCheck(op, &PyPackageFile_Type)
+# define PyIndexFile_Check(op) PyObject_TypeCheck(op, &PyIndexFile_Type)
+# define PyPackageList_Check(op) PyObject_TypeCheck(op, &PyPackageList_Type)
+# define PyPackageManager_Check(op) PyObject_TypeCheck(op, &PyPackageManager_Type)
+# define PyPackageRecords_Check(op) PyObject_TypeCheck(op, &PyPackageRecords_Type)
+# define PyPolicy_Check(op) PyObject_TypeCheck(op, &PyPolicy_Type)
+# define PyProblemResolver_Check(op) PyObject_TypeCheck(op, &PyProblemResolver_Type)
+# define PySourceList_Check(op) PyObject_TypeCheck(op, &PySourceList_Type)
+# define PySourceRecords_Check(op) PyObject_TypeCheck(op, &PySourceRecords_Type)
+# define PySourceRecordFiles_Check(op) PyObject_TypeCheck(op, &PySourceRecordFiles_Type)
+# define PyTagFile_Check(op) PyObject_TypeCheck(op, &PyTagFile_Type)
+# define PyTagSection_Check(op) PyObject_TypeCheck(op, &PyTagSection_Type)
+# define PyVersion_Check(op) PyObject_TypeCheck(op, &PyVersion_Type)
+// Exact check macros.
+# define PyAcquire_CheckExact(op) (op->op_type == &PyAcquire_Type)
+# define PyAcquireFile_CheckExact(op) (op->op_type == &PyAcquireFile_Type)
+# define PyAcquireItem_CheckExact(op) (op->op_type == &PyAcquireItem_Type)
+# define PyAcquireItemDesc_CheckExact(op) (op->op_type == &PyAcquireItemDesc_Type)
+# define PyAcquireWorker_CheckExact(op) (op->op_type == &PyAcquireWorker_Type)
+# define PyActionGroup_CheckExact(op) (op->op_type == &PyActionGroup_Type)
+# define PyCache_CheckExact(op) (op->op_type == &PyCache_Type)
+# define PyCacheFile_CheckExact(op) (op->op_type == &PyCacheFile_Type)
+# define PyCdrom_CheckExact(op) (op->op_type == &PyCdrom_Type)
+# define PyConfiguration_CheckExact(op) (op->op_type == &PyConfiguration_Type)
+# define PyDepCache_CheckExact(op) (op->op_type == &PyDepCache_Type)
+# define PyDependency_CheckExact(op) (op->op_type == &PyDependency_Type)
+# define PyDependencyList_CheckExact(op) (op->op_type == &PyDependencyList_Type)
+# define PyDescription_CheckExact(op) (op->op_type == &PyDescription_Type)
+# define PyHashes_CheckExact(op) (op->op_type == &PyHashes_Type)
+# define PyGroup_CheckExact(op) (op->op_type == &PyGroup_Type)
+# define PyHashString_CheckExact(op) (op->op_type == &PyHashString_Type)
+# define PyIndexRecords_CheckExact(op) (op->op_type == &PyIndexRecords_Type)
+# define PyMetaIndex_CheckExact(op) (op->op_type == &PyMetaIndex_Type)
+# define PyPackage_CheckExact(op) (op->op_type == &PyPackage_Type)
+# define PyPackageFile_CheckExact(op) (op->op_type == &PyPackageFile_Type)
+# define PyIndexFile_CheckExact(op) (op->op_type == &PyIndexFile_Type)
+# define PyOrderList_CheckExact(op) (op->op_type == &PyOrderList_Type)
+# define PyPackageList_CheckExact(op) (op->op_type == &PyPackageList_Type)
+# define PyPackageManager_CheckExact(op) (op->op_type == &PyPackageManager_Type)
+# define PyPackageRecords_CheckExact(op) (op->op_type == &PyPackageRecords_Type)
+# define PyPolicy_CheckExact(op) (op->op_type == &PyPolicy_Type)
+# define PyProblemResolver_CheckExact(op) (op->op_type == &PyProblemResolver_Type)
+# define PySourceList_CheckExact(op) (op->op_type == &PySourceList_Type)
+# define PySourceRecords_CheckExact(op) (op->op_type == &PySourceRecords_Type)
+# define PySourceRecordFiles_CheckExact(op) (op->op_type == &PySourceRecordFiles_Type)
+# define PyTagFile_CheckExact(op) (op->op_type == &PyTagFile_Type)
+# define PyTagSection_CheckExact(op) (op->op_type == &PyTagSection_Type)
+# define PyVersion_CheckExact(op) (op->op_type == &PyVersion_Type)
+
+# ifndef APT_PKGMODULE_H
+static struct _PyAptPkgAPIStruct *_PyAptPkg_API;
+
+static int import_apt_pkg(void) {
+# if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 1
+ _PyAptPkg_API = (_PyAptPkgAPIStruct *)PyCapsule_Import("apt_pkg._C_API", 0);
+# else
+ _PyAptPkg_API = (_PyAptPkgAPIStruct *)PyCObject_Import("apt_pkg", "_C_API");
+# endif // PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 1
+ return (_PyAptPkg_API != NULL) ? 0 : -1;
+}
+
+# define PyAcquire_Type *(_PyAptPkg_API->acquire_type)
+# define PyAcquireFile_Type *(_PyAptPkg_API->acquirefile_type)
+# define PyAcquireItem_Type *(_PyAptPkg_API->acquireitem_type)
+# define PyAcquireItemDesc_Type *(_PyAptPkg_API->acquireitemdesc_type)
+# define PyAcquireWorker_Type *(_PyAptPkg_API->acquireworker_type)
+# define PyActionGroup_Type *(_PyAptPkg_API->actiongroup_type)
+# define PyCache_Type *(_PyAptPkg_API->cache_type)
+# define PyCacheFile_Type *(_PyAptPkg_API->cachefile_type)
+# define PyCdrom_Type *(_PyAptPkg_API->cdrom_type)
+# define PyConfiguration_Type *(_PyAptPkg_API->configuration_type)
+# define PyDepCache_Type *(_PyAptPkg_API->depcache_type)
+# define PyDependency_Type *(_PyAptPkg_API->dependency_type)
+# define PyDependencyList_Type *(_PyAptPkg_API->dependencylist_type)
+# define PyDescription_Type *(_PyAptPkg_API->description_type)
+# define PyGroup_Type *(_PyAptPkg_API->group_type)
+# define PyHashes_Type *(_PyAptPkg_API->hashes_type)
+# define PyHashString_Type *(_PyAptPkg_API->hashstring_type)
+# define PyIndexRecords_Type *(_PyAptPkg_API->indexrecords_type)
+# define PyMetaIndex_Type *(_PyAptPkg_API->metaindex_type)
+# define PyPackage_Type *(_PyAptPkg_API->package_type)
+# define PyPackageFile_Type *(_PyAptPkg_API->packagefile_type)
+# define PyIndexFile_Type *(_PyAptPkg_API->packageindexfile_type)
+# define PyOrderList_Type *(_PyAptPkg_API->orderlist_type)
+# define PyPackageList_Type *(_PyAptPkg_API->packagelist_type)
+# define PyPackageManager_Type *(_PyAptPkg_API->packagemanager_type)
+# define PyPackageRecords_Type *(_PyAptPkg_API->packagerecords_type)
+# define PyPolicy_Type *(_PyAptPkg_API->policy_type)
+# define PyProblemResolver_Type *(_PyAptPkg_API->problemresolver_type)
+# define PySourceList_Type *(_PyAptPkg_API->sourcelist_type)
+# define PySourceRecords_Type *(_PyAptPkg_API->sourcerecords_type)
+# define PySourceRecordFiles_Type *(_PyAptPkg_API->sourcerecordfiles_type)
+# define PyTagFile_Type *(_PyAptPkg_API->tagfile_type)
+# define PyTagSection_Type *(_PyAptPkg_API->tagsection_type)
+# define PyVersion_Type *(_PyAptPkg_API->version_type)
+// Code
+# define PyAcquire_ToCpp _PyAptPkg_API->acquire_tocpp
+# define PyAcquireFile_ToCpp _PyAptPkg_API->acquirefile_tocpp
+# define PyAcquireItem_ToCpp _PyAptPkg_API->acquireitem_tocpp
+# define PyAcquireItemDesc_ToCpp _PyAptPkg_API->acquireitemdesc_tocpp
+# define PyAcquireWorker_ToCpp _PyAptPkg_API->acquireworker_tocpp
+# define PyActionGroup_ToCpp _PyAptPkg_API->actiongroup_tocpp
+# define PyCache_ToCpp _PyAptPkg_API->cache_tocpp
+# define PyCacheFile_ToCpp _PyAptPkg_API->cachefile_tocpp
+# define PyCdrom_ToCpp _PyAptPkg_API->cdrom_tocpp
+# define PyConfiguration_ToCpp _PyAptPkg_API->configuration_tocpp
+# define PyDepCache_ToCpp _PyAptPkg_API->depcache_tocpp
+# define PyDependency_ToCpp _PyAptPkg_API->dependency_tocpp
+# define PyDependencyList_ToCpp _PyAptPkg_API->dependencylist_tocpp // NULL
+# define PyDescription_ToCpp _PyAptPkg_API->description_tocpp
+# define PyGroup_ToCpp _PyAptPkg_API->group_tocpp
+# define PyHashes_ToCpp _PyAptPkg_API->hashes_tocpp
+# define PyHashString_ToCpp _PyAptPkg_API->hashstring_tocpp
+# define PyIndexRecords_ToCpp _PyAptPkg_API->indexrecords_tocpp
+# define PyMetaIndex_ToCpp _PyAptPkg_API->metaindex_tocpp
+# define PyPackage_ToCpp _PyAptPkg_API->package_tocpp
+# define PyPackageFile_ToCpp _PyAptPkg_API->packagefile_tocpp
+# define PyIndexFile_ToCpp _PyAptPkg_API->packageindexfile_tocpp
+# define PyOrderList_ToCpp _PyAptPkg_API->orderlist_tocpp // NULL
+# define PyPackageList_ToCpp _PyAptPkg_API->packagelist_tocpp // NULL
+# define PyPackageManager_ToCpp _PyAptPkg_API->packagemanager_tocpp
+# define PyPackageRecords_ToCpp _PyAptPkg_API->packagerecords_tocpp
+# define PyPolicy_ToCpp _PyAptPkg_API->policy_tocpp
+# define PyProblemResolver_ToCpp _PyAptPkg_API->problemresolver_tocpp
+# define PySourceList_ToCpp _PyAptPkg_API->sourcelist_tocpp
+# define PySourceRecords_ToCpp _PyAptPkg_API->sourcerecords_tocpp // NULL
+# define PySourceRecordFiles_ToCpp _PyAptPkg_API->sourcerecordfiles_tocpp // NULL
+# define PyTagFile_ToCpp _PyAptPkg_API->tagfile_tocpp
+# define PyTagSection_ToCpp _PyAptPkg_API->tagsection_tocpp
+# define PyVersion_ToCpp _PyAptPkg_API->version_tocpp
+// Get the C++ object
+# define PyAcquire_FromCpp _PyAptPkg_API->acquire_fromcpp
+# define PyAcquireFile_FromCpp _PyAptPkg_API->acquirefile_fromcpp
+# define PyAcquireItem_FromCpp _PyAptPkg_API->acquireitem_fromcpp
+# define PyAcquireItemDesc_FromCpp _PyAptPkg_API->acquireitemdesc_fromcpp
+# define PyAcquireWorker_FromCpp _PyAptPkg_API->acquireworker_fromcpp
+# define PyActionGroup_FromCpp _PyAptPkg_API->actiongroup_fromcpp
+# define PyCache_FromCpp _PyAptPkg_API->cache_fromcpp
+# define PyCacheFile_FromCpp _PyAptPkg_API->cachefile_fromcpp
+# define PyCdrom_FromCpp _PyAptPkg_API->cdrom_fromcpp
+# define PyConfiguration_FromCpp _PyAptPkg_API->configuration_fromcpp
+# define PyDepCache_FromCpp _PyAptPkg_API->depcache_fromcpp
+# define PyDependency_FromCpp _PyAptPkg_API->dependency_fromcpp
+# define PyDependencyList_FromCpp _PyAptPkg_API->dependencylist_fromcpp // NULL
+# define PyDescription_FromCpp _PyAptPkg_API->description_fromcpp
+# define PyGroup_FromCpp _PyAptPkg_API->group_fromcpp
+# define PyHashes_FromCpp _PyAptPkg_API->hashes_fromcpp
+# define PyHashString_FromCpp _PyAptPkg_API->hashstring_fromcpp
+# define PyIndexRecords_FromCpp _PyAptPkg_API->indexrecords_fromcpp
+# define PyMetaIndex_FromCpp _PyAptPkg_API->metaindex_fromcpp
+# define PyPackage_FromCpp _PyAptPkg_API->package_fromcpp
+# define PyPackageFile_FromCpp _PyAptPkg_API->packagefile_fromcpp
+# define PyIndexFile_FromCpp _PyAptPkg_API->packageindexfile_fromcpp
+# define PyOrderList_FromCpp _PyAptPkg_API->orderlist_fromcpp // NULL
+# define PyPackageList_FromCpp _PyAptPkg_API->packagelist_fromcpp // NULL
+# define PyPackageManager_FromCpp _PyAptPkg_API->packagemanager_fromcpp
+# define PyPackageRecords_FromCpp _PyAptPkg_API->packagerecords_fromcpp
+# define PyPolicy_FromCpp _PyAptPkg_API->policy_fromcpp
+# define PyProblemResolver_FromCpp _PyAptPkg_API->problemresolver_fromcpp
+# define PySourceList_FromCpp _PyAptPkg_API->sourcelist_fromcpp
+# define PySourceRecords_FromCpp _PyAptPkg_API->sourcerecords_fromcpp // NULL
+# define PySourceRecordFiles_FromCpp _PyAptPkg_API->sourcerecordfiles_fromcpp // NULL
+# define PyTagFile_FromCpp _PyAptPkg_API->tagfile_fromcpp
+# define PyTagSection_FromCpp _PyAptPkg_API->tagsection_fromcpp
+# define PyVersion_FromCpp _PyAptPkg_API->version_fromcpp
+# endif // APT_PKGMODULE_H
+
+#endif
+
diff --git a/python/sourcelist.cc b/python/sourcelist.cc
new file mode 100644
index 0000000..3c1d49c
--- /dev/null
+++ b/python/sourcelist.cc
@@ -0,0 +1,170 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: sourcelist.cc,v 1.2 2003/12/26 17:04:22 mdz Exp $
+/* ######################################################################
+
+ SourcesList - Wrapper for the SourcesList functions
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "generic.h"
+#include "apt_pkgmodule.h"
+
+#include <apt-pkg/sourcelist.h>
+
+#include <Python.h>
+ /*}}}*/
+
+
+
+// PkgsourceList Class /*{{{*/
+// ---------------------------------------------------------------------
+
+static char *doc_PkgSourceListFindIndex =
+ "find_index(pkgfile: apt_pkg.PackageFile) -> apt_pkg.IndexFile\n\n"
+ "Return the index file for the given package file, or None if none\n"
+ "could be found.";
+static PyObject *PkgSourceListFindIndex(PyObject *Self,PyObject *Args)
+{
+ pkgSourceList *list = GetCpp<pkgSourceList*>(Self);
+ PyObject *pyPkgFileIter;
+ CppPyObject<pkgIndexFile*> *pyPkgIndexFile;
+
+ if (PyArg_ParseTuple(Args, "O!", &PyPackageFile_Type,&pyPkgFileIter) == 0)
+ return 0;
+
+ pkgCache::PkgFileIterator &i = GetCpp<pkgCache::PkgFileIterator>(pyPkgFileIter);
+ pkgIndexFile *index;
+ if(list->FindIndex(i, index))
+ {
+ pyPkgIndexFile = CppPyObject_NEW<pkgIndexFile*>(pyPkgFileIter,&PyIndexFile_Type,index);
+ // Do not delete the pkgIndexFile*, it is managed by pkgSourceList.
+ pyPkgIndexFile->NoDelete = true;
+ return pyPkgIndexFile;
+ }
+
+ //&PyIndexFile_Type,&pyPkgIndexFile)
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static char *doc_PkgSourceListReadMainList =
+ "read_main_list() -> bool\n\n"
+ "Read /etc/apt/sources.list and similar files to populate the list\n"
+ "of indexes.";
+static PyObject *PkgSourceListReadMainList(PyObject *Self,PyObject *Args)
+{
+ pkgSourceList *list = GetCpp<pkgSourceList*>(Self);
+ bool res = list->ReadMainList();
+
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static char *doc_PkgSourceListGetIndexes =
+ "get_indexes(acquire: apt_pkg.Acquire[, all: bool=False]) -> bool\n\n"
+ "Add all indexes (i.e. stuff like Release files, Packages files)\n"
+ "to the Acquire object 'acquire'. If 'all' is True, all indexes\n"
+ "will be added, otherwise only changed indexes will be added.";
+static PyObject *PkgSourceListGetIndexes(PyObject *Self,PyObject *Args)
+{
+ pkgSourceList *list = GetCpp<pkgSourceList*>(Self);
+
+ PyObject *pyFetcher;
+ char all = 0;
+ if (PyArg_ParseTuple(Args, "O!|b",&PyAcquire_Type,&pyFetcher, &all) == 0)
+ return 0;
+
+ pkgAcquire *fetcher = GetCpp<pkgAcquire*>(pyFetcher);
+ bool res = list->GetIndexes(fetcher, all);
+
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static PyMethodDef PkgSourceListMethods[] =
+{
+ {"find_index",PkgSourceListFindIndex,METH_VARARGS,doc_PkgSourceListFindIndex},
+ {"read_main_list",PkgSourceListReadMainList,METH_VARARGS,doc_PkgSourceListReadMainList},
+ {"get_indexes",PkgSourceListGetIndexes,METH_VARARGS,doc_PkgSourceListGetIndexes},
+ {}
+};
+
+static PyObject *PkgSourceListGetList(PyObject *Self,void*)
+{
+ pkgSourceList *list = GetCpp<pkgSourceList*>(Self);
+ PyObject *List = PyList_New(0);
+ for (std::vector<metaIndex *>::const_iterator I = list->begin();
+ I != list->end(); I++)
+ {
+ CppPyObject<metaIndex*> *Obj;
+ Obj = CppPyObject_NEW<metaIndex*>(Self, &PyMetaIndex_Type,*I);
+ // Never delete metaIndex*, they are managed by the pkgSourceList.
+ Obj->NoDelete = true;
+ PyList_Append(List,Obj);
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+static PyGetSetDef PkgSourceListGetSet[] = {
+ {"list",PkgSourceListGetList,0,"A list of MetaIndex() objects.",0},
+ {}
+};
+
+static PyObject *PkgSourceListNew(PyTypeObject *type,PyObject *args,PyObject *kwds)
+{
+ char *kwlist[] = {0};
+ if (PyArg_ParseTupleAndKeywords(args,kwds,"",kwlist) == 0)
+ return 0;
+ return CppPyObject_NEW<pkgSourceList*>(NULL, type,new pkgSourceList());
+}
+
+static const char *sourcelist_doc =
+ "SourceList()\n\n"
+ "Represent the list of sources stored in /etc/apt/sources.list and\n"
+ "similar files.";
+PyTypeObject PySourceList_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.SourceList", // tp_name
+ sizeof(CppPyObject<pkgSourceList*>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDeallocPtr<pkgSourceList*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE),
+ sourcelist_doc, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ PkgSourceListMethods, // tp_methods
+ 0, // tp_members
+ PkgSourceListGetSet, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ PkgSourceListNew, // tp_new
+};
+
diff --git a/python/string.cc b/python/string.cc
new file mode 100644
index 0000000..7cfaa70
--- /dev/null
+++ b/python/string.cc
@@ -0,0 +1,142 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: string.cc,v 1.3 2002/01/08 06:53:04 jgg Exp $
+/* ######################################################################
+
+ string - Mappings for the string functions that are worthwile for
+ Python users
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#include "apt_pkgmodule.h"
+#include "generic.h"
+
+#include <apt-pkg/strutl.h>
+
+#include <Python.h>
+ /*}}}*/
+
+// Templated function /*{{{*/
+/* Macro for the generic string in string out function */
+#define MkStr(Python,CFunc) \
+PyObject *Python(PyObject *Self,PyObject *Args) \
+{ \
+ char *Str = 0; \
+ if (PyArg_ParseTuple(Args,"s",&Str) == 0) \
+ return 0; \
+ return CppPyString(CFunc(Str)); \
+}
+
+#define MkInt(Python,CFunc, ctype, pytype, ...) \
+PyObject *Python(PyObject *Self,PyObject *Args) \
+{ \
+ ctype Val = 0; \
+ if (PyArg_ParseTuple(Args,pytype,&Val) == 0) \
+ return 0; \
+ return CppPyString(CFunc(Val, ##__VA_ARGS__)); \
+}
+
+MkStr(StrDeQuote,DeQuoteString);
+
+/*
+ * Input bytes(Py3k)/str(Py2), output str.
+ */
+PyObject *StrBase64Encode(PyObject *Self,PyObject *Args) {
+ char *Str = 0;
+ #if PY_MAJOR_VERSION >= 3
+ if (PyArg_ParseTuple(Args,"y",&Str) == 0)
+ #else
+ if (PyArg_ParseTuple(Args,"s",&Str) == 0)
+ #endif
+ return 0;
+ return CppPyString(Base64Encode(Str));
+}
+
+PyObject *StrURItoFileName(PyObject *Self,PyObject *Args)
+{
+ char *Str = 0;
+ if (PyArg_ParseTuple(Args,"s",&Str) == 0)
+ return 0;
+ return CppPyPath(URItoFileName(Str));
+}
+
+//MkFloat(StrSizeToStr,SizeToStr);
+MkInt(StrTimeToStr,TimeToStr, unsigned long, "k");
+MkInt(StrTimeRFC1123,TimeRFC1123, long long, "L", false);
+ /*}}}*/
+
+// Other String functions /*{{{*/
+PyObject *StrSizeToStr(PyObject *Self,PyObject *Args)
+{
+ PyObject *Obj;
+ double value;
+
+ if (PyArg_ParseTuple(Args,"O",&Obj) == 0)
+ return 0;
+ // In Python 3, PyInt_Check is aliased to PyLong_Check and PyInt_AsLong is
+ // aliased to PyLong_AsLong. Therefore we do the actual long checks first
+ // so that if it is a long in Python 3, the value will be converted to a
+ // double rather than a long. This avoids OverflowError regressions in
+ // Python 3. LP: #1030278
+ if (PyLong_Check(Obj))
+ value = PyLong_AsDouble(Obj);
+ else if (PyInt_Check(Obj))
+ value = PyInt_AsLong(Obj);
+ else if (PyFloat_Check(Obj))
+ value = PyFloat_AsDouble(Obj);
+ else {
+ PyErr_SetString(PyExc_TypeError,"Only understand integers and floats");
+ return 0;
+ }
+ // Check for OverflowErrors or other exceptions during conversion.
+ if (PyErr_Occurred())
+ return 0;
+ return CppPyString(SizeToStr(value));
+}
+
+PyObject *StrQuoteString(PyObject *Self,PyObject *Args)
+{
+ char *Str = 0;
+ char *Bad = 0;
+ if (PyArg_ParseTuple(Args,"ss",&Str,&Bad) == 0)
+ return 0;
+ return CppPyString(QuoteString(Str,Bad));
+}
+
+PyObject *StrStringToBool(PyObject *Self,PyObject *Args)
+{
+ char *Str = 0;
+ if (PyArg_ParseTuple(Args,"s",&Str) == 0)
+ return 0;
+ return MkPyNumber(StringToBool(Str));
+}
+
+PyObject *StrStrToTime(PyObject *Self,PyObject *Args)
+{
+ char *Str = 0;
+ if (PyArg_ParseTuple(Args,"s",&Str) == 0)
+ return 0;
+
+ time_t Result;
+APT_IGNORE_DEPRECATED_PUSH
+ if (RFC1123StrToTime(Str,Result) == false)
+ {
+APT_IGNORE_DEPRECATED_POP
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ return MkPyNumber(Result);
+}
+
+PyObject *StrCheckDomainList(PyObject *Self,PyObject *Args)
+{
+ char *Host = 0;
+ char *List = 0;
+ if (PyArg_ParseTuple(Args,"ss",&Host,&List) == 0)
+ return 0;
+ return PyBool_FromLong(CheckDomainList(Host,List));
+}
+
+ /*}}}*/
diff --git a/python/tag.cc b/python/tag.cc
new file mode 100644
index 0000000..691b67f
--- /dev/null
+++ b/python/tag.cc
@@ -0,0 +1,1063 @@
+// -*- mode: cpp; mode: fold -*-
+// Description /*{{{*/
+// $Id: tag.cc,v 1.3 2002/02/26 01:36:15 mdz Exp $
+/* ######################################################################
+
+ Tag - Binding for the RFC 822 tag file parser
+
+ Upon reflection I have make the TagSection wrapper look like a map..
+ The other option was to use a sequence (which nicely matches the internal
+ storage) but really makes no sense to a Python Programmer.. One
+ specialized lookup is provided, the FindFlag lookup - as well as the
+ usual set of duplicate things to match the C++ interface.
+
+ The TagFile interface is also slightly different, it has a built in
+ internal TagSection object that is used. Do not hold onto a reference
+ to a TagSection and let TagFile go out of scope! The underlying storage
+ for the section will go away and it will seg.
+
+ ##################################################################### */
+ /*}}}*/
+// Include Files /*{{{*/
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include "generic.h"
+#include "apt_pkgmodule.h"
+
+#include <apt-pkg/tagfile.h>
+#include <apt-pkg/fileutl.h>
+
+#include <stdio.h>
+#include <iostream>
+#include <Python.h>
+
+using namespace std;
+ /*}}}*/
+/* We need to keep a private copy of the data.. */
+struct TagSecData : public CppPyObject<pkgTagSection>
+{
+ char *Data;
+ bool Bytes;
+#if PY_MAJOR_VERSION >= 3
+ PyObject *Encoding;
+#endif
+};
+
+// The owner of the TagFile is a Python file object.
+struct TagFileData : public CppPyObject<pkgTagFile>
+{
+ TagSecData *Section;
+ FileFd Fd;
+ bool Bytes;
+#if PY_MAJOR_VERSION >= 3
+ PyObject *Encoding;
+#endif
+};
+
+// Traversal and Clean for owned objects
+int TagFileTraverse(PyObject *self, visitproc visit, void* arg) {
+ Py_VISIT(((TagFileData *)self)->Section);
+ Py_VISIT(((TagFileData *)self)->Owner);
+ return 0;
+}
+
+int TagFileClear(PyObject *self) {
+ Py_CLEAR(((TagFileData *)self)->Section);
+ Py_CLEAR(((TagFileData *)self)->Owner);
+ return 0;
+}
+
+// Helpers to return Unicode or bytes as appropriate.
+#if PY_MAJOR_VERSION < 3
+#define TagSecString_FromStringAndSize(self, v, len) \
+ PyString_FromStringAndSize((v), (len))
+#define TagSecString_FromString(self, v) CppPyString(v)
+#else
+static PyObject *TagSecString_FromStringAndSize(PyObject *self, const char *v,
+ Py_ssize_t len) {
+ TagSecData *Self = (TagSecData *)self;
+ if (Self->Bytes)
+ return PyBytes_FromStringAndSize(v, len);
+ else if (Self->Encoding)
+ return PyUnicode_Decode(v, len, PyUnicode_AsString(Self->Encoding), 0);
+ else
+ return PyUnicode_FromStringAndSize(v, len);
+}
+
+static PyObject *TagSecString_FromString(PyObject *self, const char *v) {
+ TagSecData *Self = (TagSecData *)self;
+ if (Self->Bytes)
+ return PyBytes_FromString(v);
+ else if (Self->Encoding)
+ return PyUnicode_Decode(v, strlen(v),
+ PyUnicode_AsString(Self->Encoding), 0);
+ else
+ return PyUnicode_FromString(v);
+}
+#endif
+
+
+ /*}}}*/
+// TagSecFree - Free a Tag Section /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void TagSecFree(PyObject *Obj)
+{
+ TagSecData *Self = (TagSecData *)Obj;
+ delete [] Self->Data;
+ CppDealloc<pkgTagSection>(Obj);
+}
+ /*}}}*/
+// TagFileFree - Free a Tag File /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void TagFileFree(PyObject *Obj)
+{
+ #ifdef ALLOC_DEBUG
+ std::cerr << "=== DEALLOCATING " << Obj->ob_type->tp_name << "^ ===\n";
+ #endif
+ PyObject_GC_UnTrack(Obj);
+ TagFileData *Self = (TagFileData *)Obj;
+ Py_CLEAR(Self->Section);
+ Self->Object.~pkgTagFile();
+ Self->Fd.~FileFd();
+ Py_CLEAR(Self->Owner);
+ Obj->ob_type->tp_free(Obj);
+}
+ /*}}}*/
+
+// Tag Section Wrappers /*{{{*/
+static char *doc_Find =
+ "find(name: str[, default = None]) -> str\n\n"
+ "Find the key given by 'name' and return the value. If the key can\n"
+ "not be found, return 'default'.";
+static PyObject *TagSecFind(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ char *Default = 0;
+ if (PyArg_ParseTuple(Args,"s|z",&Name,&Default) == 0)
+ return 0;
+
+ const char *Start;
+ const char *Stop;
+ if (GetCpp<pkgTagSection>(Self).Find(Name,Start,Stop) == false)
+ {
+ if (Default == 0)
+ Py_RETURN_NONE;
+ return TagSecString_FromString(Self,Default);
+ }
+ return TagSecString_FromStringAndSize(Self,Start,Stop-Start);
+}
+
+static char *doc_FindRaw =
+ "find_raw(name: str[, default = None] -> str\n\n"
+ "Same as find(), but returns the complete 'key: value' field; instead of\n"
+ "just the value.";
+static PyObject *TagSecFindRaw(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ char *Default = 0;
+ if (PyArg_ParseTuple(Args,"s|z",&Name,&Default) == 0)
+ return 0;
+
+ unsigned Pos;
+ if (GetCpp<pkgTagSection>(Self).Find(Name,Pos) == false)
+ {
+ if (Default == 0)
+ Py_RETURN_NONE;
+ return TagSecString_FromString(Self,Default);
+ }
+
+ const char *Start;
+ const char *Stop;
+ GetCpp<pkgTagSection>(Self).Get(Start,Stop,Pos);
+
+ return TagSecString_FromStringAndSize(Self,Start,Stop-Start);
+}
+
+static char *doc_FindFlag =
+ "find_flag(name: str) -> int\n\n"
+ "Return 1 if the key's value is 'yes' or a similar value describing\n"
+ "a boolean true. If the field does not exist, or does not have such a\n"
+ "value, return 0.";
+static PyObject *TagSecFindFlag(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ if (PyArg_ParseTuple(Args,"s",&Name) == 0)
+ return 0;
+
+ unsigned long Flag = 0;
+ if (GetCpp<pkgTagSection>(Self).FindFlag(Name,Flag,1) == false)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ return PyBool_FromLong(Flag);
+}
+
+static char *doc_Write =
+ "write(file: int, order: List[str], rewrite: List[Tag]) -> None\n\n"
+ "Rewrites the section into the given file descriptor, which should be\n"
+ "a file descriptor or an object providing a fileno() method.\n"
+ "\n"
+ ".. versionadded:: 1.9.0";
+static PyObject *TagSecWrite(PyObject *Self, PyObject *Args, PyObject *kwds)
+{
+ char *kwlist[] = {"file", "order", "rewrite", nullptr};
+ PyObject *pFile;
+ PyObject *pOrder;
+ PyObject *pRewrite;
+ if (PyArg_ParseTupleAndKeywords(Args,kwds, "OO!O!",kwlist, &pFile,&PyList_Type,&pOrder, &PyList_Type, &pRewrite) == 0)
+ return nullptr;
+
+ int fileno = PyObject_AsFileDescriptor(pFile);
+ // handle invalid arguments
+ if (fileno == -1)
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "Argument must be string, fd or have a fileno() method");
+ return 0;
+ }
+
+ FileFd file(fileno);
+ const char **order = ListToCharChar(pOrder,true);
+ if (order == nullptr)
+ return nullptr;
+ std::vector<pkgTagSection::Tag> rewrite;
+ for (int I = 0; I != PySequence_Length(pRewrite); I++) {
+ PyObject *item = PySequence_GetItem(pRewrite, I);
+ if (!PyObject_TypeCheck(item, &PyTag_Type))
+ return PyErr_SetString(PyExc_TypeError, "Wrong type for tag in list"), nullptr;
+ rewrite.push_back(GetCpp<pkgTagSection::Tag>(item));
+ }
+
+ return HandleErrors(PyBool_FromLong(GetCpp<pkgTagSection>(Self).Write(file, order, rewrite)));
+}
+
+
+// Map access, operator []
+static PyObject *TagSecMap(PyObject *Self,PyObject *Arg)
+{
+ const char *Name = PyObject_AsString(Arg);
+ if (Name == 0)
+ return 0;
+ const char *Start;
+ const char *Stop;
+ if (GetCpp<pkgTagSection>(Self).Find(Name,Start,Stop) == false)
+ {
+ PyErr_SetString(PyExc_KeyError,Name);
+ return 0;
+ }
+
+ return TagSecString_FromStringAndSize(Self,Start,Stop-Start);
+}
+
+// len() operation
+static Py_ssize_t TagSecLength(PyObject *Self)
+{
+ pkgTagSection &Sec = GetCpp<pkgTagSection>(Self);
+ return Sec.Count();
+}
+
+// Look like a mapping
+static char *doc_Keys =
+ "keys() -> list\n\n"
+ "Return a list of all keys.";
+static PyObject *TagSecKeys(PyObject *Self,PyObject *Args)
+{
+ pkgTagSection &Tags = GetCpp<pkgTagSection>(Self);
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ // Convert the whole configuration space into a list
+ PyObject *List = PyList_New(0);
+ for (unsigned int I = 0; I != Tags.Count(); I++)
+ {
+ const char *Start;
+ const char *Stop;
+ Tags.Get(Start,Stop,I);
+ const char *End = Start;
+ for (; End < Stop && *End != ':'; End++);
+
+ PyObject *Obj;
+ PyList_Append(List,Obj = PyString_FromStringAndSize(Start,End-Start));
+ Py_DECREF(Obj);
+ }
+ return List;
+}
+
+#if PY_MAJOR_VERSION < 3
+static char *doc_Exists =
+ "has_key(name: str) -> bool\n\n"
+ "Return True if the key given by 'name' exists, False otherwise.";
+static PyObject *TagSecExists(PyObject *Self,PyObject *Args)
+{
+ char *Name = 0;
+ if (PyArg_ParseTuple(Args,"s",&Name) == 0)
+ return 0;
+
+ const char *Start;
+ const char *Stop;
+ return PyBool_FromLong(GetCpp<pkgTagSection>(Self).Find(Name,Start,Stop));
+}
+#endif
+
+static int TagSecContains(PyObject *Self,PyObject *Arg)
+{
+ const char *Name = PyObject_AsString(Arg);
+ if (Name == 0)
+ return 0;
+ const char *Start;
+ const char *Stop;
+ if (GetCpp<pkgTagSection>(Self).Find(Name,Start,Stop) == false)
+ return 0;
+ return 1;
+}
+
+static char *doc_Bytes =
+ "bytes() -> int\n\n"
+ "Return the number of bytes this section is large.";
+static PyObject *TagSecBytes(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ return MkPyNumber(GetCpp<pkgTagSection>(Self).size());
+}
+
+static PyObject *TagSecStr(PyObject *Self)
+{
+ const char *Start;
+ const char *Stop;
+ GetCpp<pkgTagSection>(Self).GetSection(Start,Stop);
+ return TagSecString_FromStringAndSize(Self,Start,Stop-Start);
+}
+ /*}}}*/
+// TagFile Wrappers /*{{{*/
+static char *doc_Step =
+ "step() -> bool\n\n"
+ "Step forward in the file";
+static PyObject *TagFileStep(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+
+ TagFileData &Obj = *(TagFileData *)Self;
+ if (Obj.Object.Step(Obj.Section->Object) == false)
+ return HandleErrors(PyBool_FromLong(0));
+
+ return HandleErrors(PyBool_FromLong(1));
+}
+
+// TagFile Wrappers /*{{{*/
+static PyObject *TagFileNext(PyObject *Self)
+{
+ TagFileData &Obj = *(TagFileData *)Self;
+ // Replace the section.
+ Py_CLEAR(Obj.Section);
+ Obj.Section = (TagSecData*)(&PyTagSection_Type)->tp_alloc(&PyTagSection_Type, 0);
+ new (&Obj.Section->Object) pkgTagSection();
+ Obj.Section->Owner = Self;
+ Py_INCREF(Obj.Section->Owner);
+ Obj.Section->Data = 0;
+ Obj.Section->Bytes = Obj.Bytes;
+#if PY_MAJOR_VERSION >= 3
+ // We don't need to incref Encoding as the previous Section object already
+ // held a reference to it.
+ Obj.Section->Encoding = Obj.Encoding;
+#endif
+ if (Obj.Object.Step(Obj.Section->Object) == false)
+ return HandleErrors(NULL);
+
+ // Bug-Debian: http://bugs.debian.org/572596
+ // Duplicate the data here and scan the duplicated section data; in order
+ // to not use any shared storage.
+ // TODO: Provide an API in apt-pkg to do this; this is really ugly.
+
+ // Fetch old section data
+ const char *Start;
+ const char *Stop;
+ Obj.Section->Object.GetSection(Start,Stop);
+ // Duplicate the data and
+ // append a \n because GetSection() will only give us a single \n
+ // but Scan() needs \n\n to work
+ Obj.Section->Data = new char[Stop-Start+2];
+
+ memcpy(Obj.Section->Data, Start, Stop - Start);
+ Obj.Section->Data[Stop-Start] = '\n';
+ Obj.Section->Data[Stop-Start+1] = '\0';
+ // Rescan it
+ if(Obj.Section->Object.Scan(Obj.Section->Data, Stop-Start+2) == false)
+ return HandleErrors(NULL);
+
+ Py_INCREF(Obj.Section);
+ return HandleErrors(Obj.Section);
+}
+
+static PyObject *TagFileIter(PyObject *Self) {
+ Py_INCREF(Self);
+ return Self;
+}
+
+static char *doc_Offset =
+ "offset() -> int\n\n"
+ "Return the current offset.";
+static PyObject *TagFileOffset(PyObject *Self,PyObject *Args)
+{
+ if (PyArg_ParseTuple(Args,"") == 0)
+ return 0;
+ return MkPyNumber(((TagFileData *)Self)->Object.Offset());
+
+}
+
+static char *doc_Jump =
+ "jump(offset: int) -> bool\n\n"
+ "Jump to the given offset; return True on success. Note that jumping to\n"
+ "an offset is not very reliable, and the 'section' attribute may point\n"
+ "to an unexpected section.";
+static PyObject *TagFileJump(PyObject *Self,PyObject *Args)
+{
+ int Offset;
+ if (PyArg_ParseTuple(Args,"i",&Offset) == 0)
+ return 0;
+
+ TagFileData &Obj = *(TagFileData *)Self;
+ if (Obj.Object.Jump(Obj.Section->Object,Offset) == false)
+ return HandleErrors(PyBool_FromLong(0));
+
+ return HandleErrors(PyBool_FromLong(1));
+}
+
+static char *doc_Close =
+ "close()\n\n"
+ "Close the file.";
+static PyObject *TagFileClose(PyObject *self, PyObject *args)
+{
+ if (args != NULL && !PyArg_ParseTuple(args, ""))
+ return NULL;
+
+ TagFileData &Obj = *(TagFileData *) self;
+
+ Obj.Fd.Close();
+
+ Py_INCREF(Py_None);
+ return HandleErrors(Py_None);
+}
+
+static PyObject *TagFileExit(PyObject *self, PyObject *args)
+{
+
+ PyObject *exc_type = 0;
+ PyObject *exc_value = 0;
+ PyObject *traceback = 0;
+ if (!PyArg_UnpackTuple(args, "__exit__", 3, 3, &exc_type, &exc_value,
+ &traceback)) {
+ return 0;
+ }
+
+ PyObject *res = TagFileClose(self, NULL);
+
+ if (res == NULL) {
+ // The close failed. If no exception happened within the suite, we
+ // will raise an error here. Otherwise, we just display the error, so
+ // Python can handle the original exception instead.
+ if (exc_type == Py_None)
+ return NULL;
+
+ PyErr_WriteUnraisable(self);
+ } else {
+ Py_DECREF(res);
+ }
+ // Return False, as required by the context manager protocol.
+ Py_RETURN_FALSE;
+}
+
+static PyObject *TagFileEnter(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+
+ Py_INCREF(self);
+
+ return self;
+}
+
+ /*}}}*/
+// ParseSection - Parse a single section from a tag file /*{{{*/
+// ---------------------------------------------------------------------
+static PyObject *TagSecNew(PyTypeObject *type,PyObject *Args,PyObject *kwds) {
+ char *Data;
+ Py_ssize_t Len;
+ char Bytes = 0;
+ char *kwlist[] = {"text", "bytes", 0};
+
+ // this allows reading "byte" types from python3 - but we don't
+ // make (much) use of it yet
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"s#|b",kwlist,&Data,&Len,&Bytes) == 0)
+ return 0;
+ if (memchr(Data, 0, Len) != nullptr) {
+ PyErr_SetString(PyExc_ValueError, "Input contains NUL byte");
+ return 0;
+ }
+ if (Data[Len] != 0) {
+ PyErr_SetString(PyExc_ValueError, "Input is not terminated by NUL byte");
+ return 0;
+ }
+
+ // Create the object..
+ TagSecData *New = (TagSecData*)type->tp_alloc(type, 0);
+ new (&New->Object) pkgTagSection();
+ New->Data = new char[strlen(Data)+2];
+ snprintf(New->Data,strlen(Data)+2,"%s\n",Data);
+ New->Bytes = Bytes;
+#if PY_MAJOR_VERSION >= 3
+ New->Encoding = 0;
+#endif
+
+ if (New->Object.Scan(New->Data,strlen(New->Data)) == false)
+ {
+ cerr << New->Data << endl;
+ Py_DECREF((PyObject *)New);
+ PyErr_SetString(PyExc_ValueError,"Unable to parse section data");
+ return 0;
+ }
+
+ New->Object.Trim();
+
+ return New;
+}
+
+ /*}}}*/
+// ParseTagFile - Parse a tagd file /*{{{*/
+// ---------------------------------------------------------------------
+/* This constructs the parser state. */
+
+static PyObject *TagFileNew(PyTypeObject *type,PyObject *Args,PyObject *kwds)
+{
+ PyObject *File = 0;
+ char Bytes = 0;
+
+ char *kwlist[] = {"file", "bytes", 0};
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"O|b",kwlist,&File,&Bytes) == 0)
+ return 0;
+
+ // check if we got a filename or a file object
+ int fileno = -1;
+ PyApt_Filename filename;
+ if (!filename.init(File)) {
+ PyErr_Clear();
+ fileno = PyObject_AsFileDescriptor(File);
+ }
+
+ // handle invalid arguments
+ if (fileno == -1 && filename == NULL)
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "Argument must be string, fd or have a fileno() method");
+ return 0;
+ }
+
+ PyApt_UniqueObject<TagFileData> New((TagFileData*)type->tp_alloc(type, 0));
+ if (fileno != -1)
+ {
+#ifdef APT_HAS_GZIP
+ new (&New->Fd) FileFd();
+ New->Fd.OpenDescriptor(fileno, FileFd::ReadOnlyGzip, false);
+#else
+ new (&New->Fd) FileFd(fileno,false);
+#endif
+ }
+ else
+ {
+ // FileFd::Extension got added in this revision
+#if (APT_PKG_MAJOR > 4 || (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 12))
+ new (&New->Fd) FileFd(filename, FileFd::ReadOnly, FileFd::Extension, false);
+#else
+ new (&New->Fd) FileFd(filename, FileFd::ReadOnly, false);
+#endif
+ }
+ New->Bytes = Bytes;
+ New->Owner = File;
+ Py_INCREF(New->Owner);
+#if PY_MAJOR_VERSION >= 3
+ if (fileno != -1) {
+ New->Encoding = PyObject_GetAttr(File, PyUnicode_FromString("encoding"));
+ if (!New->Encoding)
+ PyErr_Clear();
+ if (New->Encoding && !PyUnicode_Check(New->Encoding))
+ New->Encoding = 0;
+ } else
+ New->Encoding = 0;
+ Py_XINCREF(New->Encoding);
+#endif
+ new (&New->Object) pkgTagFile(&New->Fd);
+
+ // Create the section
+ New->Section = (TagSecData*)(&PyTagSection_Type)->tp_alloc(&PyTagSection_Type, 0);
+ new (&New->Section->Object) pkgTagSection();
+ New->Section->Owner = New.get();
+ Py_INCREF(New->Section->Owner);
+ New->Section->Data = 0;
+ New->Section->Bytes = Bytes;
+#if PY_MAJOR_VERSION >= 3
+ New->Section->Encoding = New->Encoding;
+ Py_XINCREF(New->Section->Encoding);
+#endif
+
+ return HandleErrors(New.release());
+}
+ /*}}}*/
+
+// Method table for the Tag Section object
+static PyMethodDef TagSecMethods[] =
+{
+ // Query
+ {"find",TagSecFind,METH_VARARGS,doc_Find},
+ {"find_raw",TagSecFindRaw,METH_VARARGS,doc_FindRaw},
+ {"find_flag",TagSecFindFlag,METH_VARARGS,doc_FindFlag},
+ {"bytes",TagSecBytes,METH_VARARGS,doc_Bytes},
+ {"write",(PyCFunction) TagSecWrite,METH_VARARGS|METH_KEYWORDS,doc_Write},
+
+ // Python Special
+ {"keys",TagSecKeys,METH_VARARGS,doc_Keys},
+#if PY_MAJOR_VERSION < 3
+ {"has_key",TagSecExists,METH_VARARGS,doc_Exists},
+#endif
+ {"get",TagSecFind,METH_VARARGS,doc_Find},
+ {}
+};
+
+
+PySequenceMethods TagSecSeqMeth = {0,0,0,0,0,0,0,TagSecContains,0,0};
+PyMappingMethods TagSecMapMeth = {TagSecLength,TagSecMap,0};
+
+
+static char *doc_TagSec = "TagSection(text: str, [bytes: bool = False])\n\n"
+ "Provide methods to access RFC822-style header sections, like those\n"
+ "found in debian/control or Packages files.\n\n"
+ "TagSection() behave like read-only dictionaries and also provide access\n"
+ "to the functions provided by the C++ class (e.g. find).\n\n"
+ "By default, text read from files is treated as strings (binary data in\n"
+ "Python 2, Unicode strings in Python 3). Use bytes=True to cause all\n"
+ "header values read from this TagSection to be bytes even in Python 3.\n"
+ "Header names are always treated as Unicode.";
+PyTypeObject PyTagSection_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.TagSection", // tp_name
+ sizeof(TagSecData), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ TagSecFree, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ &TagSecSeqMeth, // tp_as_sequence
+ &TagSecMapMeth, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ TagSecStr, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE |
+ Py_TPFLAGS_HAVE_GC),
+ doc_TagSec, // tp_doc
+ CppTraverse<pkgTagSection>, // tp_traverse
+ CppClear<pkgTagSection>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ TagSecMethods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ TagSecNew, // tp_new
+};
+
+// Method table for the Tag File object
+static PyMethodDef TagFileMethods[] =
+{
+ // Query
+ {"step",TagFileStep,METH_VARARGS,doc_Step},
+ {"offset",TagFileOffset,METH_VARARGS,doc_Offset},
+ {"jump",TagFileJump,METH_VARARGS,doc_Jump},
+ {"close",TagFileClose,METH_VARARGS,doc_Close},
+ {"__enter__",TagFileEnter,METH_VARARGS,"Context manager entry, return self."},
+ {"__exit__",TagFileExit,METH_VARARGS,"Context manager exit, calls close."},
+
+ {}
+};
+
+// Return the current section.
+static PyObject *TagFileGetSection(PyObject *Self,void*) {
+ PyObject *Obj = ((TagFileData *)Self)->Section;
+ Py_INCREF(Obj);
+ return Obj;
+}
+
+static PyGetSetDef TagFileGetSet[] = {
+ {"section",TagFileGetSection,0,
+ "The current section, as a TagSection object.",0},
+ {}
+};
+
+
+static char *doc_TagFile = "TagFile(file, [bytes: bool = False])\n\n"
+ "TagFile() objects provide access to debian control files, which consist\n"
+ "of multiple RFC822-style sections.\n\n"
+ "To provide access to those sections, TagFile objects provide an iterator\n"
+ "which yields TagSection objects for each section.\n\n"
+ "TagFile objects also provide another API which uses a shared TagSection\n"
+ "object in the 'section' member. The functions step() and jump() can be\n"
+ "used to navigate within the file; offset() returns the current\n"
+ "position.\n\n"
+ "It is important to not mix the use of both APIs, because this can have\n"
+ "unwanted effects.\n\n"
+ "The parameter 'file' refers to an object providing a fileno() method or\n"
+ "a file descriptor (an integer).\n\n"
+ "By default, text read from files is treated as strings (binary data in\n"
+ "Python 2, Unicode strings in Python 3). Use bytes=True to cause all\n"
+ "header values read from this TagFile to be bytes even in Python 3.\n"
+ "Header names are always treated as Unicode.";
+
+// Type for a Tag File
+PyTypeObject PyTagFile_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.TagFile", // tp_name
+ sizeof(TagFileData), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ TagFileFree, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ _PyAptObject_getattro, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_BASETYPE |
+ Py_TPFLAGS_HAVE_GC),
+ doc_TagFile, // tp_doc
+ TagFileTraverse, // tp_traverse
+ TagFileClear, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ TagFileIter, // tp_iter
+ TagFileNext, // tp_iternext
+ TagFileMethods, // tp_methods
+ 0, // tp_members
+ TagFileGetSet, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ TagFileNew, // tp_new
+
+};
+
+
+// Return the current section.
+static PyObject *TagGetAction(PyObject *Self,void*) {
+ return MkPyNumber(GetCpp<pkgTagSection::Tag>(Self).Action);
+}
+
+static PyObject *TagGetName(PyObject *Self,void*) {
+ return CppPyString(GetCpp<pkgTagSection::Tag>(Self).Name);
+}
+
+static PyObject *TagGetData(PyObject *Self,void*) {
+ return CppPyString(GetCpp<pkgTagSection::Tag>(Self).Data);
+}
+
+static PyObject *PyTagRename_New(PyTypeObject *type,PyObject *Args,PyObject *kwds) {
+ char *oldName;
+ char *newName;
+ char *kwlist[] = {"old_name", "new_name", 0};
+
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"ss",kwlist, &oldName, &newName) == 0)
+ return nullptr;
+ if (oldName[0] == '\0') {
+ PyErr_SetString(PyExc_ValueError, "Old tag name may not be empty.");
+ return nullptr;
+ }
+ if (newName[0] == '\0') {
+ PyErr_SetString(PyExc_ValueError, "New tag name may not be empty.");
+ return nullptr;
+ }
+
+ auto tag = pkgTagSection::Tag::Rename(oldName, newName);
+ return CppPyObject_NEW<pkgTagSection::Tag>(nullptr, type, tag);
+}
+
+static PyObject *PyTagRewrite_New(PyTypeObject *type,PyObject *Args,PyObject *kwds) {
+ char *name;
+ char *data;
+ char *kwlist[] = {"name", "data", 0};
+
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"ss",kwlist, &name, &data) == 0)
+ return nullptr;
+ if (name[0] == '\0') {
+ PyErr_SetString(PyExc_ValueError, "Tag name may not be empty.");
+ return nullptr;
+ }
+ if (data[0] == '\0') {
+ PyErr_SetString(PyExc_ValueError, "New value may not be empty.");
+ return nullptr;
+ }
+
+ auto tag = pkgTagSection::Tag::Rewrite(name, data);
+ return CppPyObject_NEW<pkgTagSection::Tag>(nullptr, type, tag);
+}
+
+static PyObject *PyTagRemove_New(PyTypeObject *type,PyObject *Args,PyObject *kwds) {
+ char *name;
+ char *kwlist[] = {"name", nullptr};
+
+ if (PyArg_ParseTupleAndKeywords(Args,kwds,"s",kwlist, &name) == 0)
+ return nullptr;
+ if (name[0] == '\0') {
+ PyErr_SetString(PyExc_ValueError, "Tag name may not be empty.");
+ return nullptr;
+ }
+
+ auto tag = pkgTagSection::Tag::Remove(name);
+ return CppPyObject_NEW<pkgTagSection::Tag>(nullptr, type, tag);
+}
+
+static PyGetSetDef TagGetSet[] = {
+ {"action",TagGetAction,0,
+ "The action to perform.",0},
+ {"name",TagGetName,0,
+ "The name of the tag to perform the action on.",0},
+ {"data",TagGetData,0,
+ "The data to write instead (for REWRITE), or the new tag name (RENAME)",0},
+ {}
+};
+
+static char doc_Tag[] = "Tag\n\n"
+ "Identify actions to be executed on a task\n"
+ "\n"
+ "This is used in conjunction with :meth:`TagSection.write` to rewrite\n"
+ "a tag section into a new one.\n"
+ "\n"
+ "This class is abstract, use one of the subclasses:\n"
+ ":class:`TagRewrite`, :class:`TagRemove`, :class:`TagRename`\n"
+ "\n"
+ ".. versionadded:: 1.1";
+
+static char doc_TagRewrite[] = "TagRewrite(name: str, data: str)\n\n"
+ "Change the value of the tag to the string passed in *data*\n"
+ "\n"
+ ".. versionadded:: 1.1";
+static char doc_TagRename[] = "TagRename(old_name: str, new_name: str)\n\n"
+ "Rename the tag *old_name* to *new_name*\n"
+ "\n"
+ ".. versionadded:: 1.1";
+
+static char doc_TagRemove[] = "TagRemove(name: str)\n\n"
+ "Remove the tag *name* from the tag section\n"
+ "\n"
+ ".. versionadded:: 1.1";
+
+
+// Type for a Tag File
+PyTypeObject PyTag_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.Tag", // tp_name
+ sizeof(CppPyObject<pkgTagSection::Tag>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgTagSection::Tag>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ (Py_TPFLAGS_DEFAULT // tp_flags
+ | Py_TPFLAGS_BASETYPE),
+ doc_Tag, // tp_doc
+ CppTraverse<pkgTagSection::Tag>, // tp_traverse
+ CppClear<pkgTagSection::Tag>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ TagGetSet, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ 0, // tp_new
+};
+
+// Type for a Tag File
+PyTypeObject PyTagRewrite_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.TagRewrite", // tp_name
+ sizeof(CppPyObject<pkgTagSection::Tag>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgTagSection::Tag>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flags
+ doc_TagRewrite, // tp_doc
+ CppTraverse<pkgTagSection::Tag>, // tp_traverse
+ CppClear<pkgTagSection::Tag>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ &PyTag_Type, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ PyTagRewrite_New, // tp_new
+};
+
+// Type for a Tag File
+PyTypeObject PyTagRemove_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.TagRemove", // tp_name
+ sizeof(CppPyObject<pkgTagSection::Tag>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgTagSection::Tag>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flags
+ doc_TagRemove, // tp_doc
+ CppTraverse<pkgTagSection::Tag>, // tp_traverse
+ CppClear<pkgTagSection::Tag>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ &PyTag_Type, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ PyTagRemove_New, // tp_new
+};
+
+// Type for a Tag File
+PyTypeObject PyTagRename_Type =
+{
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_pkg.TagRename", // tp_name
+ sizeof(CppPyObject<pkgTagSection::Tag>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<pkgTagSection::Tag>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flags
+ doc_TagRename, // tp_doc
+ CppTraverse<pkgTagSection::Tag>, // tp_traverse
+ CppClear<pkgTagSection::Tag>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ &PyTag_Type, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ PyTagRename_New, // tp_new
+};
diff --git a/python/tarfile.cc b/python/tarfile.cc
new file mode 100644
index 0000000..b87fa71
--- /dev/null
+++ b/python/tarfile.cc
@@ -0,0 +1,521 @@
+/*
+ * arfile.cc - Wrapper around ExtractTar which behaves like Python's tarfile.
+ *
+ * Copyright 2009 Julian Andres Klode <jak@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include "generic.h"
+#include "apt_instmodule.h"
+#include <apt-pkg/extracttar.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/dirstream.h>
+
+/**
+ * A subclass of pkgDirStream which calls a Python callback.
+ *
+ * This calls a Python callback in FinishedFile() with the Item as the first
+ * argument and the data as the second argument.
+ *
+ * It can also work without a callback, in which case it just sets the
+ * 'py_member' and 'py_data' members. This can be combined with setting
+ * 'member' to extract a single member into the memory.
+ */
+class PyDirStream : public pkgDirStream
+{
+
+public:
+ PyObject *callback;
+ PyObject *py_data;
+ // The requested member or NULL.
+ const char *member;
+ // Set to true if an error occurred in the Python callback, or a file
+ // was too large to read in extractdata.
+ bool error;
+ // Place where the copy of the data is stored.
+ char *copy;
+ // The size of the copy
+ size_t copy_size;
+
+ virtual bool DoItem(Item &Itm,int &Fd);
+ virtual bool FinishedFile(Item &Itm,int Fd);
+#if (APT_PKG_MAJOR >= 5)
+ virtual bool Process(Item &Itm,const unsigned char *Data,
+ unsigned long long Size,unsigned long long Pos);
+#else
+ virtual bool Process(Item &Itm,const unsigned char *Data,
+ unsigned long Size,unsigned long Pos);
+#endif
+ PyDirStream(PyObject *callback, const char *member=0) : callback(callback),
+ py_data(0), member(member), error(false), copy(0), copy_size(0)
+ {
+ Py_XINCREF(callback);
+ }
+
+ virtual ~PyDirStream() {
+ Py_XDECREF(callback);
+ Py_XDECREF(py_data);
+ delete[] copy;
+ }
+};
+
+bool PyDirStream::DoItem(Item &Itm, int &Fd)
+{
+ if (!member || strcmp(Itm.Name, member) == 0) {
+ // Allocate a new buffer if the old one is too small.
+ if (Itm.Size > SIZE_MAX)
+ goto to_large;
+ if (copy == NULL || copy_size < Itm.Size) {
+ delete[] copy;
+ copy = new (std::nothrow) char[Itm.Size];
+ if (copy == NULL)
+ goto to_large;
+ copy_size = Itm.Size;
+ }
+ Fd = -2;
+ } else {
+ Fd = -1;
+ }
+ return true;
+to_large:
+ delete[] copy;
+ copy = NULL;
+ copy_size = 0;
+ /* If we are looking for a specific member, abort reading now */
+ if (member) {
+ error = true;
+ PyErr_Format(PyExc_MemoryError,
+ "The member %s was too large to read into memory",
+ Itm.Name);
+ return false;
+ }
+ return true;
+}
+
+#if (APT_PKG_MAJOR >= 5)
+bool PyDirStream::Process(Item &Itm,const unsigned char *Data,
+ unsigned long long Size,unsigned long long Pos)
+#else
+bool PyDirStream::Process(Item &Itm,const unsigned char *Data,
+ unsigned long Size,unsigned long Pos)
+#endif
+{
+ if (copy != NULL)
+ memcpy(copy + Pos, Data,Size);
+ return true;
+}
+
+bool PyDirStream::FinishedFile(Item &Itm,int Fd)
+{
+ if (member && strcmp(Itm.Name, member) != 0)
+ // Skip non-matching Items, if a specific one is requested.
+ return true;
+
+ Py_XDECREF(py_data);
+ if (copy == NULL) {
+ Py_INCREF(Py_None);
+ py_data = Py_None;
+ } else {
+ py_data = PyBytes_FromStringAndSize(copy, Itm.Size);
+ }
+
+ if (!callback)
+ return true;
+
+ // The current member and data.
+ CppPyObject<Item> *py_member;
+ py_member = CppPyObject_NEW<Item>(0, &PyTarMember_Type);
+ // Clone our object, including the strings in it.
+ py_member->Object = Itm;
+ py_member->Object.Name = new char[strlen(Itm.Name)+1];
+ py_member->Object.LinkTarget = new char[strlen(Itm.LinkTarget)+1];
+ strcpy(py_member->Object.Name, Itm.Name);
+ strcpy(py_member->Object.LinkTarget,Itm.LinkTarget);
+ py_member->NoDelete = true;
+ error = PyObject_CallFunctionObjArgs(callback, py_member, py_data, 0) == 0;
+ // Clear the old objects and create new ones.
+ Py_XDECREF(py_member);
+ return (!error);
+}
+
+void tarmember_dealloc(PyObject *self) {
+ // We cloned those strings, delete them again.
+ delete[] GetCpp<pkgDirStream::Item>(self).Name;
+ delete[] GetCpp<pkgDirStream::Item>(self).LinkTarget;
+ CppDealloc<pkgDirStream::Item>(self);
+}
+
+// The tarfile.TarInfo interface for our TarMember class.
+static PyObject *tarmember_isblk(PyObject *self, PyObject *args)
+{
+ return PyBool_FromLong(GetCpp<pkgDirStream::Item>(self).Type ==
+ pkgDirStream::Item::BlockDevice);
+}
+static PyObject *tarmember_ischr(PyObject *self, PyObject *args)
+{
+ return PyBool_FromLong(GetCpp<pkgDirStream::Item>(self).Type ==
+ pkgDirStream::Item::CharDevice);
+}
+static PyObject *tarmember_isdev(PyObject *self, PyObject *args)
+{
+ pkgDirStream::Item::Type_t type = GetCpp<pkgDirStream::Item>(self).Type;
+ return PyBool_FromLong(type == pkgDirStream::Item::CharDevice ||
+ type == pkgDirStream::Item::BlockDevice ||
+ type == pkgDirStream::Item::FIFO);
+}
+
+static PyObject *tarmember_isdir(PyObject *self, PyObject *args)
+{
+ return PyBool_FromLong(GetCpp<pkgDirStream::Item>(self).Type ==
+ pkgDirStream::Item::Directory);
+}
+
+static PyObject *tarmember_isfifo(PyObject *self, PyObject *args)
+{
+ return PyBool_FromLong(GetCpp<pkgDirStream::Item>(self).Type ==
+ pkgDirStream::Item::FIFO);
+}
+
+static PyObject *tarmember_isfile(PyObject *self, PyObject *args)
+{
+ return PyBool_FromLong(GetCpp<pkgDirStream::Item>(self).Type ==
+ pkgDirStream::Item::File);
+}
+static PyObject *tarmember_islnk(PyObject *self, PyObject *args)
+{
+ return PyBool_FromLong(GetCpp<pkgDirStream::Item>(self).Type ==
+ pkgDirStream::Item::HardLink);
+}
+static PyObject *tarmember_isreg(PyObject *self, PyObject *args)
+{
+ return tarmember_isfile(self, NULL);
+}
+static PyObject *tarmember_issym(PyObject *self, PyObject *args)
+{
+ return PyBool_FromLong(GetCpp<pkgDirStream::Item>(self).Type ==
+ pkgDirStream::Item::SymbolicLink);
+}
+
+static PyObject *tarmember_get_name(PyObject *self, void *closure)
+{
+ return CppPyPath(GetCpp<pkgDirStream::Item>(self).Name);
+}
+
+static PyObject *tarmember_get_linkname(PyObject *self, void *closure)
+{
+ return CppPyPath(GetCpp<pkgDirStream::Item>(self).LinkTarget);
+}
+
+static PyObject *tarmember_get_mode(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<pkgDirStream::Item>(self).Mode);
+}
+
+static PyObject *tarmember_get_uid(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<pkgDirStream::Item>(self).UID);
+}
+static PyObject *tarmember_get_gid(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<pkgDirStream::Item>(self).GID);
+}
+static PyObject *tarmember_get_size(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<pkgDirStream::Item>(self).Size);
+}
+
+static PyObject *tarmember_get_mtime(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<pkgDirStream::Item>(self).MTime);
+}
+
+static PyObject *tarmember_get_major(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<pkgDirStream::Item>(self).Major);
+}
+
+static PyObject *tarmember_get_minor(PyObject *self, void *closure)
+{
+ return MkPyNumber(GetCpp<pkgDirStream::Item>(self).Minor);
+}
+
+static PyObject *tarmember_repr(PyObject *self)
+{
+ return PyString_FromFormat("<%s object: name:'%s'>",
+ self->ob_type->tp_name,
+ GetCpp<pkgDirStream::Item>(self).Name);
+
+}
+
+
+static PyMethodDef tarmember_methods[] = {
+ {"isblk",tarmember_isblk,METH_NOARGS,
+ "Determine whether the member is a block device."},
+ {"ischr",tarmember_ischr,METH_NOARGS,
+ "Determine whether the member is a character device."},
+ {"isdev",tarmember_isdev,METH_NOARGS,
+ "Determine whether the member is a device (block, character or FIFO)."},
+ {"isdir",tarmember_isdir,METH_NOARGS,
+ "Determine whether the member is a directory."},
+ {"isfifo",tarmember_isfifo,METH_NOARGS,
+ "Determine whether the member is a FIFO."},
+ {"isfile",tarmember_isfile,METH_NOARGS,
+ "Determine whether the member is a regular file."},
+ {"islnk",tarmember_islnk,METH_NOARGS,
+ "Determine whether the member is a hardlink."},
+ {"isreg",tarmember_isreg,METH_NOARGS,
+ "Determine whether the member is a regular file, same as isfile()."},
+ {"issym",tarmember_issym,METH_NOARGS,
+ "Determine whether the member is a symbolic link."},
+ {NULL}
+};
+
+static PyGetSetDef tarmember_getset[] = {
+ {"gid",tarmember_get_gid,0,"The owner's group ID."},
+ {"linkname",tarmember_get_linkname,0,"The target of the link."},
+ {"major",tarmember_get_major,0,"The major ID of the device."},
+ {"minor",tarmember_get_minor,0,"The minor ID of the device."},
+ {"mode",tarmember_get_mode,0,"The mode (permissions)."},
+ {"mtime",tarmember_get_mtime,0,"Last time of modification."},
+ {"name",tarmember_get_name,0,"The name of the file."},
+ {"size",tarmember_get_size,0,"The size of the file."},
+ {"uid",tarmember_get_uid,0,"The owner's user ID."},
+ {NULL}
+};
+
+static const char *tarmember_doc =
+ "Represent a single member of a 'tar' archive.\n\n"
+ "This class, which has been modelled after 'tarfile.TarInfo', represents\n"
+ "information about a given member in an archive.";
+PyTypeObject PyTarMember_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_inst.TarMember", // tp_name
+ sizeof(CppPyObject<pkgDirStream::Item>), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ tarmember_dealloc, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ tarmember_repr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_HAVE_GC,
+ tarmember_doc, // tp_doc
+ CppTraverse<pkgDirStream::Item>, // tp_traverse
+ CppClear<pkgDirStream::Item>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ tarmember_methods, // tp_methods
+ 0, // tp_members
+ tarmember_getset // tp_getset
+};
+
+
+
+static PyObject *tarfile_new(PyTypeObject *type,PyObject *args,PyObject *kwds)
+{
+ PyObject *file;
+ PyApt_Filename filename;
+ int fileno;
+ int min = 0;
+ int max = 0xFFFFFFFF;
+ char *comp = "gzip";
+
+ static char *kwlist[] = {"file","min","max","comp",NULL};
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O|iis", kwlist, &file, &min,
+ &max,&comp) == 0)
+ return 0;
+
+ PyApt_UniqueObject<PyTarFileObject> self((PyTarFileObject*)CppPyObject_NEW<ExtractTar*>(file,type));
+
+ // We receive a filename.
+ if (filename.init(file))
+ new (&self->Fd) FileFd((const char *) filename,FileFd::ReadOnly);
+ else if ((fileno = PyObject_AsFileDescriptor(file)) != -1) {
+ // clear the error set by PyObject_AsString().
+ PyErr_Clear();
+ new (&self->Fd) FileFd(fileno,false);
+ }
+ else {
+ return 0;
+ }
+
+ self->min = min;
+ self->Object = new ExtractTar(self->Fd,max,comp);
+ if (_error->PendingError() == true)
+ return HandleErrors(self.release());
+ return self.release();
+}
+
+static const char *tarfile_extractall_doc =
+ "extractall([rootdir: str]) -> True\n\n"
+ "Extract the archive in the current directory. The argument 'rootdir'\n"
+ "can be used to change the target directory.";
+static PyObject *tarfile_extractall(PyObject *self, PyObject *args)
+{
+ std::string cwd = SafeGetCWD();
+ PyApt_Filename rootdir;
+ if (PyArg_ParseTuple(args,"|O&:extractall", PyApt_Filename::Converter, &rootdir) == 0)
+ return 0;
+
+ if (rootdir) {
+ if (chdir(rootdir) == -1)
+ return PyErr_SetFromErrnoWithFilename(PyExc_OSError, rootdir);
+ }
+
+ pkgDirStream Extract;
+
+ ((PyTarFileObject*)self)->Fd.Seek(((PyTarFileObject*)self)->min);
+ bool res = GetCpp<ExtractTar*>(self)->Go(Extract);
+
+
+
+ if (rootdir) {
+ if (chdir(cwd.c_str()) == -1)
+ return PyErr_SetFromErrnoWithFilename(PyExc_OSError,
+ (char*)cwd.c_str());
+ }
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static const char *tarfile_go_doc =
+ "go(callback: callable[, member: str]) -> True\n\n"
+ "Go through the archive and call the callable 'callback' for each\n"
+ "member with 2 arguments. The first argument is the TarMember and\n"
+ "the second one is the data, as bytes.\n\n"
+ "The optional parameter 'member' can be used to specify the member for\n"
+ "which to call the callback. If not specified, it will be called for all\n"
+ "members. If specified and not found, LookupError will be raised.";
+static PyObject *tarfile_go(PyObject *self, PyObject *args)
+{
+ PyObject *callback;
+ PyApt_Filename member;
+ if (PyArg_ParseTuple(args,"O|O&",&callback, PyApt_Filename::Converter, &member) == 0)
+ return 0;
+ if (member && strcmp(member, "") == 0)
+ member = 0;
+ pkgDirStream Extract;
+ PyDirStream stream(callback, member);
+ ((PyTarFileObject*)self)->Fd.Seek(((PyTarFileObject*)self)->min);
+ bool res = GetCpp<ExtractTar*>(self)->Go(stream);
+ if (stream.error)
+ return 0;
+ if (member && !stream.py_data)
+ return PyErr_Format(PyExc_LookupError, "There is no member named '%s'",
+ member.path);
+ return HandleErrors(PyBool_FromLong(res));
+}
+
+static const char *tarfile_extractdata_doc =
+ "extractdata(member: str) -> bytes\n\n"
+ "Return the contents of the member, as a bytes object. Raise\n"
+ "LookupError if there is no member with the given name.";
+static PyObject *tarfile_extractdata(PyObject *self, PyObject *args)
+{
+ PyApt_Filename member;
+ if (PyArg_ParseTuple(args,"O&", PyApt_Filename::Converter, &member) == 0)
+ return 0;
+ PyDirStream stream(NULL, member);
+ ((PyTarFileObject*)self)->Fd.Seek(((PyTarFileObject*)self)->min);
+ // Go through the stream.
+ GetCpp<ExtractTar*>(self)->Go(stream);
+
+ if (stream.error)
+ return 0;
+
+ if (!stream.py_data)
+ return PyErr_Format(PyExc_LookupError, "There is no member named '%s'",
+ member.path);
+ return Py_INCREF(stream.py_data), stream.py_data;
+}
+
+static PyMethodDef tarfile_methods[] = {
+ {"extractdata",tarfile_extractdata,METH_VARARGS,tarfile_extractdata_doc},
+ {"extractall",tarfile_extractall,METH_VARARGS,tarfile_extractall_doc},
+ {"go",tarfile_go,METH_VARARGS,tarfile_go_doc},
+ {NULL}
+};
+
+static PyObject *tarfile_repr(PyObject *self)
+{
+ return PyString_FromFormat("<%s object: %s>", self->ob_type->tp_name,
+ PyString_AsString(PyObject_Repr(GetOwner<ExtractTar*>(self))));
+}
+
+static const char *tarfile_doc =
+ "TarFile(file: str/int/file[, min: int, max: int, comp: str])\n\n"
+ "The parameter 'file' may be a string specifying the path of a file, or\n"
+ "a file-like object providing the fileno() method. It may also be an int\n"
+ "specifying a file descriptor (returned by e.g. os.open()).\n\n"
+ "The parameter 'min' describes the offset in the file where the archive\n"
+ "begins and the parameter 'max' is the size of the archive.\n\n"
+ "The compression of the archive is set by the parameter 'comp'. It can\n"
+ "be set to any program supporting the -d switch, the default being gzip.";
+PyTypeObject PyTarFile_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "apt_inst.TarFile", // tp_name
+ sizeof(PyTarFileObject), // tp_basicsize
+ 0, // tp_itemsize
+ // Methods
+ CppDealloc<ExtractTar*>, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ tarfile_repr, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT | // tp_flags
+ Py_TPFLAGS_HAVE_GC,
+ tarfile_doc, // tp_doc
+ CppTraverse<ExtractTar*>, // tp_traverse
+ CppClear<ExtractTar*>, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ tarfile_methods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ tarfile_new // tp_new
+};
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..c0c0440
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,5 @@
+[build_l10n]
+domain=python-apt
+
+[sdist]
+formats = bztar
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..522de24
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,159 @@
+#!/usr/bin/python3
+# Builds on python2.X and python3
+# $Id: setup.py,v 1.2 2002/01/08 07:13:21 jgg Exp $
+import glob
+import os
+import shutil
+import subprocess
+import sys
+
+from setuptools import Extension, setup
+from setuptools.command.install import install
+
+cmdclass = {}
+
+try:
+ from DistUtilsExtra.auto import clean_build_tree
+ from DistUtilsExtra.command import build_extra, build_i18n
+except ImportError:
+ print("W: [python%s] DistUtilsExtra import error." % sys.version[:3])
+else:
+ cmdclass["build"] = build_extra.build_extra
+ cmdclass["build_i18n"] = build_i18n.build_i18n
+ cmdclass["clean"] = clean_build_tree
+
+
+class InstallTypeinfo(install):
+ def run(self):
+ install.run(self)
+ for pyi in glob.glob("typehinting/*.pyi"):
+ stubs = os.path.basename(pyi).split(".")[0] + "-stubs"
+ stubs = os.path.join(self.install_purelib, stubs)
+ if not os.path.exists(stubs):
+ os.makedirs(stubs)
+ shutil.copy(pyi, os.path.join(stubs, "__init__.pyi"))
+
+
+cmdclass["install"] = InstallTypeinfo
+
+
+def get_version():
+ """Get a PEP 0440 compatible version string"""
+ version = os.environ.get("DEBVER")
+ if not version:
+ proc = subprocess.Popen(
+ ["dpkg-parsechangelog", "-SVersion"],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
+ out, _ = proc.communicate()
+ if proc.returncode == 0:
+ version = out.decode("utf-8")
+
+ version = version.strip()
+
+ if not version:
+ return version
+
+ version = version.replace("~alpha", ".a")
+ version = version.replace("~beta", ".b")
+ version = version.replace("~rc", ".rc")
+ version = version.replace("~exp", ".dev")
+ version = version.replace("ubuntu", "+ubuntu")
+ version = version.replace("tanglu", "+tanglu")
+ version = version.split("build")[0]
+
+ return version
+
+
+# The apt_pkg module.
+files = [
+ "apt_pkgmodule.cc",
+ "acquire.cc",
+ "cache.cc",
+ "cdrom.cc",
+ "configuration.cc",
+ "depcache.cc",
+ "generic.cc",
+ "hashes.cc",
+ "hashstring.cc",
+ "indexfile.cc",
+ "metaindex.cc",
+ "pkgmanager.cc",
+ "pkgrecords.cc",
+ "pkgsrcrecords.cc",
+ "policy.cc",
+ "progress.cc",
+ "sourcelist.cc",
+ "string.cc",
+ "tag.cc",
+ "lock.cc",
+ "acquire-item.cc",
+ "python-apt-helpers.cc",
+ "cachegroup.cc",
+ "orderlist.cc",
+ "hashstringlist.cc",
+]
+files = sorted(["python/" + fname for fname in files], key=lambda s: s[:-3])
+apt_pkg = Extension(
+ "apt_pkg",
+ files,
+ libraries=["apt-pkg"],
+ extra_compile_args=[
+ "-std=c++11",
+ "-Wno-write-strings",
+ "-DAPT_8_CLEANER_HEADERS",
+ "-DAPT_9_CLEANER_HEADERS",
+ "-DAPT_10_CLEANER_HEADERS",
+ "-DPY_SSIZE_T_CLEAN",
+ ],
+)
+
+# The apt_inst module
+files = [
+ "python/apt_instmodule.cc",
+ "python/generic.cc",
+ "python/arfile.cc",
+ "python/tarfile.cc",
+]
+apt_inst = Extension(
+ "apt_inst",
+ files,
+ libraries=["apt-pkg"],
+ extra_compile_args=["-std=c++11", "-Wno-write-strings", "-DPY_SSIZE_T_CLEAN"],
+)
+
+# Replace the leading _ that is used in the templates for translation
+if len(sys.argv) > 1 and sys.argv[1] == "build":
+ if not os.path.exists("build/data/templates/"):
+ os.makedirs("build/data/templates")
+ for template in glob.glob("data/templates/*.info.in"):
+ source = open(template)
+ build = open("build/" + template[:-3], "w")
+ for line in source:
+ build.write(line.lstrip("_"))
+ source.close()
+ build.close()
+ for template in glob.glob("data/templates/*.mirrors"):
+ shutil.copy(template, os.path.join("build", template))
+
+
+setup(
+ name="python-apt",
+ description="Python bindings for APT",
+ version=get_version(),
+ author="APT Development Team",
+ author_email="deity@lists.debian.org",
+ ext_modules=[apt_pkg, apt_inst],
+ packages=["apt", "apt.progress", "aptsources"],
+ package_data={
+ "apt": ["*.pyi", "py.typed"],
+ },
+ data_files=[
+ ("share/python-apt/templates", glob.glob("build/data/templates/*.info")),
+ ("share/python-apt/templates", glob.glob("data/templates/*.mirrors")),
+ ],
+ cmdclass=cmdclass,
+ license="GNU GPL",
+ platforms="posix",
+)
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..792d600
--- /dev/null
+++ b/tests/__init__.py
@@ -0,0 +1 @@
+#
diff --git a/tests/data/aptsources/lsb-release b/tests/data/aptsources/lsb-release
new file mode 100644
index 0000000..c4b5944
--- /dev/null
+++ b/tests/data/aptsources/lsb-release
@@ -0,0 +1,4 @@
+DISTRIB_ID=Ubuntu
+DISTRIB_RELEASE=16.04
+DISTRIB_CODENAME=xenial
+DISTRIB_DESCRIPTION="Ubuntu 16.04.1 LTS"
diff --git a/tests/data/aptsources/os-release b/tests/data/aptsources/os-release
new file mode 100644
index 0000000..95a5bcd
--- /dev/null
+++ b/tests/data/aptsources/os-release
@@ -0,0 +1,10 @@
+NAME="KDE neon"
+VERSION="16.04 LTS"
+ID=neon
+ID_LIKE="ubuntu debian"
+PRETTY_NAME="KDE neon User Edition on 16.04 LTS"
+VERSION_ID="16.04"
+HOME_URL="http://neon.kde.org/"
+SUPPORT_URL="http://neon.kde.org/"
+BUG_REPORT_URL="http://bugs.kde.org/"
+UBUNTU_CODENAME=xenial
diff --git a/tests/data/aptsources/sources.list b/tests/data/aptsources/sources.list
new file mode 100644
index 0000000..8ca6807
--- /dev/null
+++ b/tests/data/aptsources/sources.list
@@ -0,0 +1,10 @@
+# comment 1
+deb http://de.archive.ubuntu.com/ubuntu/ edgy main
+# comment 2
+deb http://de.archive.ubuntu.com/ubuntu/ edgy restricted
+# comment 3
+deb http://de.archive.ubuntu.com/ubuntu/ edgy universe
+
+# multi-arch
+deb [arch=amd64,i386] http://de.archive.ubuntu.com/ubuntu/ natty main
+deb [arch=amd64,i386 trusted=yes] http://de.archive.ubuntu.com/ubuntu/ natty main
diff --git a/tests/data/aptsources/sources.list.d.testDistribution/main.sources b/tests/data/aptsources/sources.list.d.testDistribution/main.sources
new file mode 100644
index 0000000..ccdda20
--- /dev/null
+++ b/tests/data/aptsources/sources.list.d.testDistribution/main.sources
@@ -0,0 +1,74 @@
+Types: deb
+URIs: http://de.archive.ubuntu.com/ubuntu/
+Suites: hardy
+Components: main
+
+Types: deb
+URIs: http://de.archive.ubuntu.com/ubuntu/
+Suites: hardy
+Components: restricted
+
+Types: deb
+URIs: http://de.archive.ubuntu.com/ubuntu/
+Suites: hardy
+Components: universe
+
+Types: deb
+URIs: http://de.archive.ubuntu.com/ubuntu/
+Suites: hardy-updates
+Components: universe multiverse
+
+Types: deb
+URIs: http://de.archive.ubuntu.com/ubuntu/
+Suites: hardy-updates
+Components: restricted
+
+Types: deb
+URIs: http://de.archive.ubuntu.com/ubuntu/
+Suites: hardy-security
+Components: main
+
+Types: deb
+URIs: http://de.archive.ubuntu.com/ubuntu/
+Suites: hardy-security
+Components: multiverse
+
+Types: deb
+URIs: http://de.archive.ubuntu.com/ubuntu/
+Suites: hardy-security
+Components: multiverse
+
+Types: deb
+URIs: http://ftp.debian.org/debian
+Suites: sid
+Components: main
+
+Types: deb
+URIs: http://archive.tanglu.org/tanglu
+Suites: aequorea
+Components: main
+
+Types: deb
+URIs: http://ftp.hosteurope.de/mirror/archive.ubuntu.com/
+Suites: hardy
+Components: main
+
+Types: deb
+URIs: http://ftp.hosteurope.de/mirror/archive.ubuntu.com/
+Suites: hardy-backports
+Components: main
+
+Types: deb
+URIs: http://archive.ubuntu.com/ubuntu/
+Suites: intrepid
+Components: main
+
+Types: deb
+URIs: cdrom:[Ubuntu 8.10 _Intrepid Ibex_ - Alpha]/
+Suites: intrepid
+Components: main
+
+Types: deb
+URIs: cdrom:[Ubuntu 8.04 _Hardy Heron_]
+Suites: hardy
+Components: main
diff --git a/tests/data/aptsources/sources.list.d.testDuplication/main.sources b/tests/data/aptsources/sources.list.d.testDuplication/main.sources
new file mode 100644
index 0000000..5b7765b
--- /dev/null
+++ b/tests/data/aptsources/sources.list.d.testDuplication/main.sources
@@ -0,0 +1,10 @@
+Types: deb
+URIs: http://ppa.launchpad.net/me/myproject/ubuntu
+Suites: xenial
+Components: main
+
+Types: deb-src
+URIs: http://ppa.launchpad.net/me/myproject/ubuntu
+Suites: xenial
+Components: main
+Enabled: no
diff --git a/tests/data/aptsources/sources.list.d/main.sources b/tests/data/aptsources/sources.list.d/main.sources
new file mode 100644
index 0000000..2495f06
--- /dev/null
+++ b/tests/data/aptsources/sources.list.d/main.sources
@@ -0,0 +1,32 @@
+# comment 1
+# note that we have deliberate case typos in each paragraph to test case-insensitivity
+TyPes: deb
+URIs: http://de.archive.ubuntu.com/ubuntu/
+Suites: edgy
+Components: main
+
+# comment 2
+Types: deb
+uRIs: http://de.archive.ubuntu.com/ubuntu/
+Suites: edgy
+Components: restricted
+
+# comment 3
+Types: deb
+URIs: http://de.archive.ubuntu.com/ubuntu/
+SuiTes: edgy
+Components: universe
+
+# multi-arch
+Types: deb
+URIs: http://de.archive.ubuntu.com/ubuntu/
+Suites: natty
+ComPonents: main
+Architectures: amd64 i386
+
+Types: deb
+URIs: http://de.archive.ubuntu.com/ubuntu/
+Suites: natty
+Components: main
+ArchiTectures: amd64 i386
+Trusted: yes
diff --git a/tests/data/aptsources/sources.list.testDistribution b/tests/data/aptsources/sources.list.testDistribution
new file mode 100644
index 0000000..021ee87
--- /dev/null
+++ b/tests/data/aptsources/sources.list.testDistribution
@@ -0,0 +1,14 @@
+deb http://de.archive.ubuntu.com/ubuntu/ hardy main
+deb http://de.archive.ubuntu.com/ubuntu/ hardy restricted
+deb http://de.archive.ubuntu.com/ubuntu/ hardy universe
+deb http://de.archive.ubuntu.com/ubuntu/ hardy-updates universe multiverse
+deb http://de.archive.ubuntu.com/ubuntu/ hardy-updates restricted
+deb http://de.archive.ubuntu.com/ubuntu/ hardy-security main
+deb http://de.archive.ubuntu.com/ubuntu/ hardy-security multiverse
+deb http://ftp.debian.org/debian sid main
+deb http://archive.tanglu.org/tanglu aequorea main
+deb http://ftp.hosteurope.de/mirror/archive.ubuntu.com/ hardy main
+deb http://ftp.hosteurope.de/mirror/archive.ubuntu.com/ hardy-backports main
+deb http://archive.ubuntu.com/ubuntu/ intrepid main
+deb cdrom:[Ubuntu 8.10 _Intrepid Ibex_ - Alpha]/ intrepid main
+deb cdrom:[Ubuntu 8.04 _Hardy Heron_] hardy main
diff --git a/tests/data/aptsources/sources.list.testDuplication b/tests/data/aptsources/sources.list.testDuplication
new file mode 100644
index 0000000..28a4db2
--- /dev/null
+++ b/tests/data/aptsources/sources.list.testDuplication
@@ -0,0 +1,2 @@
+deb http://ppa.launchpad.net/me/myproject/ubuntu xenial main
+# deb-src http://ppa.launchpad.net/me/myproject/ubuntu xenial main
diff --git a/tests/data/aptsources_ports/sources.list b/tests/data/aptsources_ports/sources.list
new file mode 100644
index 0000000..0efa282
--- /dev/null
+++ b/tests/data/aptsources_ports/sources.list
@@ -0,0 +1,52 @@
+#
+# deb cdrom:[Ubuntu-Server 8.04.1 _Hardy Heron_ - Release powerpc (20080703)]/ hardy main restricted
+
+# deb cdrom:[Ubuntu-Server 8.04.1 _Hardy Heron_ - Release powerpc (20080703)]/ hardy main restricted
+# See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
+# newer versions of the distribution.
+
+deb http://ports.ubuntu.com/ubuntu-ports/ hardy main restricted
+deb-src http://ports.ubuntu.com/ubuntu-ports/ hardy main restricted
+
+## Major bug fix updates produced after the final release of the
+## distribution.
+deb http://ports.ubuntu.com/ubuntu-ports/ hardy-updates main restricted
+deb-src http://ports.ubuntu.com/ubuntu-ports/ hardy-updates main restricted
+
+## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
+## team, and may not be under a free licence. Please satisfy yourself as to
+## your rights to use the software. Also, please note that software in
+## universe WILL NOT receive any review or updates from the Ubuntu security
+## team.
+deb http://ports.ubuntu.com/ubuntu-ports/ hardy universe
+deb-src http://ports.ubuntu.com/ubuntu-ports/ hardy universe
+deb http://ports.ubuntu.com/ubuntu-ports/ hardy-updates universe
+deb-src http://ports.ubuntu.com/ubuntu-ports/ hardy-updates universe
+
+## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
+## team, and may not be under a free licence. Please satisfy yourself as to
+## your rights to use the software. Also, please note that software in
+## multiverse WILL NOT receive any review or updates from the Ubuntu
+## security team.
+deb http://ports.ubuntu.com/ubuntu-ports/ hardy multiverse
+deb-src http://ports.ubuntu.com/ubuntu-ports/ hardy multiverse
+deb http://ports.ubuntu.com/ubuntu-ports/ hardy-updates multiverse
+deb-src http://ports.ubuntu.com/ubuntu-ports/ hardy-updates multiverse
+
+## Uncomment the following two lines to add software from the 'backports'
+## repository.
+## N.B. software from this repository may not have been tested as
+## extensively as that contained in the main release, although it includes
+## newer versions of some applications which may provide useful features.
+## Also, please note that software in backports WILL NOT receive any review
+## or updates from the Ubuntu security team.
+# deb http://ports.ubuntu.com/ubuntu-ports/ hardy-backports main restricted universe multiverse
+# deb-src http://ports.ubuntu.com/ubuntu-ports/ hardy-backports main restricted universe multiverse
+
+deb http://ports.ubuntu.com/ubuntu-ports/ hardy-security main restricted
+deb-src http://ports.ubuntu.com/ubuntu-ports/ hardy-security main restricted
+deb http://ports.ubuntu.com/ubuntu-ports/ hardy-security universe
+deb-src http://ports.ubuntu.com/ubuntu-ports/ hardy-security universe
+deb http://ports.ubuntu.com/ubuntu-ports/ hardy-security multiverse
+deb-src http://ports.ubuntu.com/ubuntu-ports/ hardy-security multiverse
+deb-src http://ports.ubuntu.com/ubuntu-ports/ hardy-proposed restricted main multiverse universe
diff --git a/tests/data/fake-packages/Packages b/tests/data/fake-packages/Packages
new file mode 100644
index 0000000..9fbab95
--- /dev/null
+++ b/tests/data/fake-packages/Packages
@@ -0,0 +1,21 @@
+Package: 2vcard
+Priority: optional
+Section: universe/utils
+Installed-Size: 108
+Maintainer: Arvind Autar <Autar022@planet.nl>
+Architecture: amd64
+Version: 0.5-1ubuntu1
+Filename: pool/universe/2/2vcard/2vcard_0.5-1ubuntu1_amd64.deb
+Size: 14164
+MD5sum: 105ea91f0a75417d0f9e8e9624513b2a
+SHA1: d55beee01c08efc33cd131e106330dca72ee14be
+SHA256: 4a72edaf87cdb826e5508b85311fcf0bec9b7e019a55740ded7feb1b9e197f11
+Description: A little perl script to convert an adressbook to VCARD file format
+ 2vcard is a little perl script that you can use to convert the popular vcard
+ file format. Currently 2vcard can only convert adressbooks and alias files from
+ the following formats: abook,eudora,juno,ldif,mutt,mh and pine.
+ .
+ The VCARD format is used by gnomecard, for example, which is turn is used by
+ the balsa email client.
+Bugs: mailto:ubuntu-users@lists.ubuntu.com
+Origin: Ubuntu
diff --git a/tests/data/fake-packages/Packages.gz b/tests/data/fake-packages/Packages.gz
new file mode 100644
index 0000000..506bc8d
--- /dev/null
+++ b/tests/data/fake-packages/Packages.gz
Binary files differ
diff --git a/tests/data/hashsums/hashsum_test.data b/tests/data/hashsums/hashsum_test.data
new file mode 100644
index 0000000..1910281
--- /dev/null
+++ b/tests/data/hashsums/hashsum_test.data
@@ -0,0 +1 @@
+foo \ No newline at end of file
diff --git a/tests/data/hashsums/hashsum_test_with_zero.data b/tests/data/hashsums/hashsum_test_with_zero.data
new file mode 100644
index 0000000..2ec9a6d
--- /dev/null
+++ b/tests/data/hashsums/hashsum_test_with_zero.data
Binary files differ
diff --git a/tests/data/misc/foo_Release b/tests/data/misc/foo_Release
new file mode 100644
index 0000000..0f42220
--- /dev/null
+++ b/tests/data/misc/foo_Release
@@ -0,0 +1,492 @@
+Origin: Ubuntu
+Label: Ubuntu
+Suite: precise
+Version: 12.04
+Codename: precise
+Date: Wed, 25 Apr 2012 22:49:23 UTC
+Architectures: amd64 armel armhf i386 powerpc
+Components: main restricted universe multiverse
+Description: Ubuntu Precise 12.04
+MD5Sum:
+ 6a815674c5b3178152d449a9396cb2e5 1640344 main/binary-amd64/Packages.gz
+ 98140fa3444c9e945f6944acbb9ddcff 7818931 main/binary-amd64/Packages
+ 846e0e856bcbf9b64d9119c8727cda8c 97 main/binary-amd64/Release
+ cfd5f57de107941bbe661ffada4dce88 1272844 main/binary-amd64/Packages.bz2
+ 5b220aea8056a900c8eaf28e79cdd64a 97 main/binary-armel/Release
+ 92e3160bbb664f8b5d7d4f2d161dd81c 1619078 main/binary-armel/Packages.gz
+ 28fbf69ee965639c92c8a54256cd6ba1 1257389 main/binary-armel/Packages.bz2
+ 4e3ba67129f73f8afe28186b31eb3112 7743353 main/binary-armel/Packages
+ 81cfd32bf54d2b007542e14e09953bae 97 main/binary-armhf/Release
+ ed404b1123d1497cb09aceae8850fc06 7620333 main/binary-armhf/Packages
+ 64156d29df19fdaa36fa4eafd4c17dc1 1257653 main/binary-armhf/Packages.bz2
+ 3d3238bd89cb1e8e23a1a4a5bf574739 1617483 main/binary-armhf/Packages.gz
+ dc2fe62f05e29f36ffe4e58499796ae6 1273857 main/binary-i386/Packages.bz2
+ 7c678c50ce682e9f5cc5ba8f8eb2d6ad 1641082 main/binary-i386/Packages.gz
+ b6aa9a96c765bbd4202dae7dbaf18cc2 96 main/binary-i386/Release
+ eb3b4870b877863fecf1d3307c3beb54 7816415 main/binary-i386/Packages
+ 54658d89b612a38592431fe6b8a780a1 1627734 main/binary-powerpc/Packages.gz
+ 4185aca6984f00fd65aa0c0de12367d4 99 main/binary-powerpc/Release
+ fc9bf1959082733fc42c682285bf46e7 1263942 main/binary-powerpc/Packages.bz2
+ c32afd79c9163cffe013f98669deb727 7661552 main/binary-powerpc/Packages
+ ff5434612595a569236f7ba4990a3b63 62166 main/debian-installer/binary-amd64/Packages.gz
+ 7dd470290bacbacc7bec24830100aade 234592 main/debian-installer/binary-amd64/Packages
+ 013d9839e9c8f8c102daf6eb77841bf7 48784 main/debian-installer/binary-amd64/Packages.bz2
+ 08608ef832f2410970d07fdd802fc4e4 47964 main/debian-installer/binary-armel/Packages.bz2
+ 0a0a559023aac4096a38e2fb51870ddf 230310 main/debian-installer/binary-armel/Packages
+ f79f29b841a05b971ac318a9e0a396e0 61118 main/debian-installer/binary-armel/Packages.gz
+ 20a72276b6607fa58f52fcc5b7742ff4 62777 main/debian-installer/binary-armhf/Packages.gz
+ 8da4a15400cec4b06e2aa1bba6cfc2c3 49051 main/debian-installer/binary-armhf/Packages.bz2
+ 49f9f82a7c7e9e13c399d15df43148f1 238862 main/debian-installer/binary-armhf/Packages
+ 3dd181be504206f7abb41039dc508ed9 52279 main/debian-installer/binary-i386/Packages.bz2
+ 5c2c6ca586bb6ffb2de414e2cd063c70 259996 main/debian-installer/binary-i386/Packages
+ ca1b7db323ebef593617ef0a7c833dfb 67180 main/debian-installer/binary-i386/Packages.gz
+ 876f115ee26518319458fc26ec785485 246636 main/debian-installer/binary-powerpc/Packages
+ 49402b5b12b10804abfae14629d23f1c 50309 main/debian-installer/binary-powerpc/Packages.bz2
+ 29010a7ba3ac1e60a0efaef04f6f2e42 64468 main/debian-installer/binary-powerpc/Packages.gz
+ adf74189a01512a8f68d4bfc411dc692 3706 main/i18n/Index
+ 2f2ddab9be4ecc2c9e190bb639304943 4356187 main/source/Sources
+ 5c2893c352ebbf3ee380ebdab6b5e487 933770 main/source/Sources.bz2
+ 323e5ca1ba86c7a503c4c7b0772749b1 1174967 main/source/Sources.gz
+ 3c3104465b2c7e54f4b8f566ac825339 98 main/source/Release
+ f75f8a98e9e952194046da388a11c42a 119109 multiverse/binary-amd64/Packages.bz2
+ c2df9a9ff319486e3d6f46d9c35a8530 151924 multiverse/binary-amd64/Packages.gz
+ ece719c6a770134150f158cdb65ca6fc 581550 multiverse/binary-amd64/Packages
+ d3f34ec2fc86c95e4d3bc4606d751c66 103 multiverse/binary-amd64/Release
+ f296954282382f88b12dd8c64d813f5c 136295 multiverse/binary-armel/Packages.gz
+ d0da88f8a408fba12d44d5b6e107cfc0 519605 multiverse/binary-armel/Packages
+ 6d0c32b1cae4bdcfd6f18fd2d6fbf31f 103 multiverse/binary-armel/Release
+ 6744aaa8a3457d139348ea18379781ce 106873 multiverse/binary-armel/Packages.bz2
+ 1cc2613becf46fd578aa6d52ab12db94 104529 multiverse/binary-armhf/Packages.bz2
+ b0f8df0c9d700a1f7d295be4d4c03788 505901 multiverse/binary-armhf/Packages
+ 73cb5bc3d0c5021e5a4a413a73bcefce 103 multiverse/binary-armhf/Release
+ 00c07f1601226b8387fe4c9afaf2b044 133117 multiverse/binary-armhf/Packages.gz
+ bf0237c8c5d06a6df172db28710b8a36 121196 multiverse/binary-i386/Packages.bz2
+ cf110f58668bf5731e593ed78af54c27 591662 multiverse/binary-i386/Packages
+ 8a915986a504c0f3eb95b61ae909c9a4 102 multiverse/binary-i386/Release
+ c6d89a2752d1154a219c295e6d70b697 154762 multiverse/binary-i386/Packages.gz
+ ae93681c6b316c95207091b3c91042a7 105 multiverse/binary-powerpc/Release
+ ec463c2070c515de099f8baa3a4b5993 107209 multiverse/binary-powerpc/Packages.bz2
+ 675204a2b4aabeb9e99e406070b2af9b 520882 multiverse/binary-powerpc/Packages
+ c806ea7584c782d57363df12ddb28839 136930 multiverse/binary-powerpc/Packages.gz
+ d41d8cd98f00b204e9800998ecf8427e 0 multiverse/debian-installer/binary-amd64/Packages
+ 4a4dd3598707603b3f76a2378a4504aa 20 multiverse/debian-installer/binary-amd64/Packages.gz
+ 4059d198768f9f8dc9372dc1c54bc3c3 14 multiverse/debian-installer/binary-amd64/Packages.bz2
+ 4059d198768f9f8dc9372dc1c54bc3c3 14 multiverse/debian-installer/binary-armel/Packages.bz2
+ d41d8cd98f00b204e9800998ecf8427e 0 multiverse/debian-installer/binary-armel/Packages
+ 4a4dd3598707603b3f76a2378a4504aa 20 multiverse/debian-installer/binary-armel/Packages.gz
+ 4a4dd3598707603b3f76a2378a4504aa 20 multiverse/debian-installer/binary-armhf/Packages.gz
+ d41d8cd98f00b204e9800998ecf8427e 0 multiverse/debian-installer/binary-armhf/Packages
+ 4059d198768f9f8dc9372dc1c54bc3c3 14 multiverse/debian-installer/binary-armhf/Packages.bz2
+ 4059d198768f9f8dc9372dc1c54bc3c3 14 multiverse/debian-installer/binary-i386/Packages.bz2
+ 4a4dd3598707603b3f76a2378a4504aa 20 multiverse/debian-installer/binary-i386/Packages.gz
+ d41d8cd98f00b204e9800998ecf8427e 0 multiverse/debian-installer/binary-i386/Packages
+ 4a4dd3598707603b3f76a2378a4504aa 20 multiverse/debian-installer/binary-powerpc/Packages.gz
+ d41d8cd98f00b204e9800998ecf8427e 0 multiverse/debian-installer/binary-powerpc/Packages
+ 4059d198768f9f8dc9372dc1c54bc3c3 14 multiverse/debian-installer/binary-powerpc/Packages.bz2
+ a2bcfa86da39328db94629011506a877 2676 multiverse/i18n/Index
+ c2ffda2a848000b71573dbc3dc7d4402 154990 multiverse/source/Sources.bz2
+ f1d64bb88933686a71108de73b1f2262 628753 multiverse/source/Sources
+ 3d35747578528fa13640b98184120e51 188325 multiverse/source/Sources.gz
+ c9828946b46ac900fec682369c52bfa7 104 multiverse/source/Release
+ 5644835af0d1ed82cc7c14e34c2a543f 9098 restricted/binary-amd64/Packages.gz
+ d3058923c862e74c2c08b9a4ad7ec51e 134705 restricted/binary-amd64/Packages
+ 97ecff09a695f1460177843ff5d2b3e6 103 restricted/binary-amd64/Release
+ f8ed966e5400930411a32a7183357810 8452 restricted/binary-amd64/Packages.bz2
+ 60e74c701a6e40b7f869dd83b335ec5c 103 restricted/binary-armel/Release
+ 4a4dd3598707603b3f76a2378a4504aa 20 restricted/binary-armel/Packages.gz
+ 4059d198768f9f8dc9372dc1c54bc3c3 14 restricted/binary-armel/Packages.bz2
+ d41d8cd98f00b204e9800998ecf8427e 0 restricted/binary-armel/Packages
+ 55c08a48fc4b3370acc95a391bde1189 103 restricted/binary-armhf/Release
+ ce2da4621bbbaf55d858ae4243e17715 1103 restricted/binary-armhf/Packages.bz2
+ b26814493282faf0c5b269c44b799653 2477 restricted/binary-armhf/Packages
+ 784050b4fd16ea71e10cf130e47132d9 941 restricted/binary-armhf/Packages.gz
+ c4280a67444afbb8e2564d6f2249d397 9108 restricted/binary-i386/Packages.gz
+ 6dfd90555b37a912f82894b4ec3b63a0 8431 restricted/binary-i386/Packages.bz2
+ 48d3e36bf54be9b3fc7576cfcd0aac79 134582 restricted/binary-i386/Packages
+ e49b38cbf4dc409e8c25f6ab4b32fbe4 102 restricted/binary-i386/Release
+ 4a4dd3598707603b3f76a2378a4504aa 20 restricted/binary-powerpc/Packages.gz
+ 4059d198768f9f8dc9372dc1c54bc3c3 14 restricted/binary-powerpc/Packages.bz2
+ d41d8cd98f00b204e9800998ecf8427e 0 restricted/binary-powerpc/Packages
+ edb68a453747a9faa9e98389787fb79d 105 restricted/binary-powerpc/Release
+ d41d8cd98f00b204e9800998ecf8427e 0 restricted/debian-installer/binary-amd64/Packages
+ 4059d198768f9f8dc9372dc1c54bc3c3 14 restricted/debian-installer/binary-amd64/Packages.bz2
+ 4a4dd3598707603b3f76a2378a4504aa 20 restricted/debian-installer/binary-amd64/Packages.gz
+ 4a4dd3598707603b3f76a2378a4504aa 20 restricted/debian-installer/binary-armel/Packages.gz
+ 4059d198768f9f8dc9372dc1c54bc3c3 14 restricted/debian-installer/binary-armel/Packages.bz2
+ d41d8cd98f00b204e9800998ecf8427e 0 restricted/debian-installer/binary-armel/Packages
+ 4059d198768f9f8dc9372dc1c54bc3c3 14 restricted/debian-installer/binary-armhf/Packages.bz2
+ 4a4dd3598707603b3f76a2378a4504aa 20 restricted/debian-installer/binary-armhf/Packages.gz
+ d41d8cd98f00b204e9800998ecf8427e 0 restricted/debian-installer/binary-armhf/Packages
+ 4a4dd3598707603b3f76a2378a4504aa 20 restricted/debian-installer/binary-i386/Packages.gz
+ 4059d198768f9f8dc9372dc1c54bc3c3 14 restricted/debian-installer/binary-i386/Packages.bz2
+ d41d8cd98f00b204e9800998ecf8427e 0 restricted/debian-installer/binary-i386/Packages
+ 4a4dd3598707603b3f76a2378a4504aa 20 restricted/debian-installer/binary-powerpc/Packages.gz
+ 4059d198768f9f8dc9372dc1c54bc3c3 14 restricted/debian-installer/binary-powerpc/Packages.bz2
+ d41d8cd98f00b204e9800998ecf8427e 0 restricted/debian-installer/binary-powerpc/Packages
+ 39ef6c1d54f83252b07406f9cc3e9204 2596 restricted/i18n/Index
+ a76089a7a653d4f2196c38093058d1aa 19001 restricted/source/Sources
+ 3990b36e6ef2846251b58a58cde3768d 5470 restricted/source/Sources.bz2
+ f0a32107aaf12daf3e64b4dc3ee11321 5306 restricted/source/Sources.gz
+ 7871a3f6f83e033ab93c06bf886e305d 104 restricted/source/Release
+ 3464b1b15950e714151f8bb43982951e 25546870 universe/binary-amd64/Packages
+ 9340d5c4051da92820bb5bd5ba05f7a7 4785960 universe/binary-amd64/Packages.bz2
+ 1f6974aea9904921afdb4d1c5d0e8578 6166988 universe/binary-amd64/Packages.gz
+ 75ea366982b4862a41d9640687778dd2 101 universe/binary-amd64/Release
+ 5492f7f7183461d52f8d58871026c3e8 101 universe/binary-armel/Release
+ 420abe7ca02b5cb2abcd1b273efcfea9 4667308 universe/binary-armel/Packages.bz2
+ 4da3448f54e710222b26646b0bee14e8 6009219 universe/binary-armel/Packages.gz
+ e99405db74ba425a3f898fdda0a42113 24901082 universe/binary-armel/Packages
+ d0545845bbcff572a5c852b80582b269 5948128 universe/binary-armhf/Packages.gz
+ 8f0d262f1eb03fc3523cd80b3112a7e0 101 universe/binary-armhf/Release
+ a10169d0cc23f526bcee5769d27778b0 4618508 universe/binary-armhf/Packages.bz2
+ 952259d2cdb2c85df177702ac92075a0 24642528 universe/binary-armhf/Packages
+ df43c3b4ec37e79a00023475a09e2bfa 6179579 universe/binary-i386/Packages.gz
+ cc44a3e2ad759febb38ef2bec15ab29e 25568759 universe/binary-i386/Packages
+ 826b1d8609f0944a6d2ae95617e4d05a 100 universe/binary-i386/Release
+ 50690005918dd03ad9b71ffffa678d6f 4795820 universe/binary-i386/Packages.bz2
+ 8a1f21204f4178574251a2238c00f317 25188905 universe/binary-powerpc/Packages
+ 7409876b9e1238d5a147720b41233a26 6080488 universe/binary-powerpc/Packages.gz
+ 9bcc15c59aa3fbbd15f0d187fe90b353 4716652 universe/binary-powerpc/Packages.bz2
+ c3bdb05d2be1efa2dca9d2bac4e85b13 103 universe/binary-powerpc/Release
+ f8259410f0e1ad66324dbce895fdde2d 15255 universe/debian-installer/binary-amd64/Packages.bz2
+ ce60affbf23a069735c29951bfb0b818 17243 universe/debian-installer/binary-amd64/Packages.gz
+ 13ce59ecd4540ddef3670dbbed73cdbc 61801 universe/debian-installer/binary-amd64/Packages
+ 988da583db40ce21d400926641fe6ed8 113584 universe/debian-installer/binary-armel/Packages
+ 75381e3ed15a3a2fa1480fdea72cfd24 23193 universe/debian-installer/binary-armel/Packages.bz2
+ 4a8e6a98277f254660e8690fd050b232 27397 universe/debian-installer/binary-armel/Packages.gz
+ 02e7128ef42cd61e66c768520961fb11 20065 universe/debian-installer/binary-armhf/Packages.gz
+ 851afb686177a6819b291a714fa15813 17619 universe/debian-installer/binary-armhf/Packages.bz2
+ ce3b6645e37226c4047546a40675ecdd 76034 universe/debian-installer/binary-armhf/Packages
+ 229235ad9979a343e3bea9aedb5af8da 17260 universe/debian-installer/binary-i386/Packages.gz
+ 8065c9994844e578af00ef8794709b18 15272 universe/debian-installer/binary-i386/Packages.bz2
+ f28d6328611ab1e382fb0d0e798aca97 61718 universe/debian-installer/binary-i386/Packages
+ 60f54adbd38213dbbfe5d638f98a17e9 61121 universe/debian-installer/binary-powerpc/Packages
+ 1d48a07b3f4214200ff3eb1c5894e4a1 15024 universe/debian-installer/binary-powerpc/Packages.bz2
+ 51eb13c4b9baf089e4e8b0e85556b90e 16860 universe/debian-installer/binary-powerpc/Packages.gz
+ 155e0b646671f37a7fe235c4579e59f2 2922 universe/i18n/Index
+ 2ef7ccbe106edb394dc69d8511775122 21256524 universe/source/Sources
+ e52b7cb491cc6a950cd11fa6263d7330 5019105 universe/source/Sources.bz2
+ c722166709cfe9c398643b9c1a443610 102 universe/source/Release
+ 5ddd8bd0dda063b203d1a1da150983a0 6238766 universe/source/Sources.gz
+SHA1:
+ 0b326daa3b2ac8748ca10942aaec15ebdcc78b36 1640344 main/binary-amd64/Packages.gz
+ 8a6068a75feb86e12b088dad2478600f6670f2d7 7818931 main/binary-amd64/Packages
+ 19655f20d48d9819ad95f2c9ecc59e5b1d94c3d0 97 main/binary-amd64/Release
+ f9761ecf8536859ef38b670a7f17d83febec4a37 1272844 main/binary-amd64/Packages.bz2
+ a3a5faadbdf0a49d1587f07181b9eca870cb24ce 97 main/binary-armel/Release
+ 3c5d8f3a401427110adfd7f7d65513bfa47b933a 1619078 main/binary-armel/Packages.gz
+ 4d54e387978fdf829b4ff7336ed4d02e61c54d6a 1257389 main/binary-armel/Packages.bz2
+ 969dfd243cc3f514eea9914de571db28621cd9bd 7743353 main/binary-armel/Packages
+ f8f33265eab2ff9fd8a6353e014e36a9d318a54d 97 main/binary-armhf/Release
+ 1d210f8ad3547b771bc8c8d2a9eb5ee99d437d81 7620333 main/binary-armhf/Packages
+ 5057a8b2d11d2325bb2546ad6613517b208fff18 1257653 main/binary-armhf/Packages.bz2
+ 25fc010c2789028727308fbf6132a8da387423b8 1617483 main/binary-armhf/Packages.gz
+ 79369a31bc481f7f9f71f666906c3bdb356c44d8 1273857 main/binary-i386/Packages.bz2
+ aaadaa6eaf0b7e73b0d371cdebae573f28833a43 1641082 main/binary-i386/Packages.gz
+ 6f8e5e9dd04a2379a7c6d8dc23b4ff8df5584741 96 main/binary-i386/Release
+ 8509eead0c5e9410e23d4226ee5d190220db1275 7816415 main/binary-i386/Packages
+ 7da3fd8ad7102912a4cc9882c66fbb1b65edd4c0 1627734 main/binary-powerpc/Packages.gz
+ 8a0c3b7757b738a89644e8c5a3b9afed806d2f83 99 main/binary-powerpc/Release
+ 4063338a28f6504f7bc2f9c00fc34ac26fc5a1fa 1263942 main/binary-powerpc/Packages.bz2
+ 81844e44aaf0ed255ca200e7316bc9279ef238b6 7661552 main/binary-powerpc/Packages
+ d17439034551742aaa4762b4c174c1d72881f49f 62166 main/debian-installer/binary-amd64/Packages.gz
+ 05e024776b06a40253b9e252caad6dc4a13a90b9 234592 main/debian-installer/binary-amd64/Packages
+ fa692a307ecab69c106a5253107f980527cf58a9 48784 main/debian-installer/binary-amd64/Packages.bz2
+ fb8be98ef08265d2f101cf265b9bf37654d750ac 47964 main/debian-installer/binary-armel/Packages.bz2
+ 8953964fd2b54539e8276237cd5e4e2d4f9dc2ab 230310 main/debian-installer/binary-armel/Packages
+ cfdde60bbcbfb25c66fa474d28217e03a4c06789 61118 main/debian-installer/binary-armel/Packages.gz
+ 468306dc06acc828c50196427ba324c8ce225c79 62777 main/debian-installer/binary-armhf/Packages.gz
+ 17e7331a837675de31c365529ea9454cc48baf98 49051 main/debian-installer/binary-armhf/Packages.bz2
+ 3404140163a5acece9a054912abf72d11a5591d0 238862 main/debian-installer/binary-armhf/Packages
+ 2bb7e052999eadc333a9f6481bdc20acb238d4c1 52279 main/debian-installer/binary-i386/Packages.bz2
+ b2ad69cd6759724461c3566d91c1c5ec209eba07 259996 main/debian-installer/binary-i386/Packages
+ ebd0ab3923b3df4eca53eb863773bf0a9a4c3a67 67180 main/debian-installer/binary-i386/Packages.gz
+ eff551b62b72a1c0b183d4903a1452f2be08f3da 246636 main/debian-installer/binary-powerpc/Packages
+ 5c8aa09d48d7a792d555e7b16f4c89733e8441af 50309 main/debian-installer/binary-powerpc/Packages.bz2
+ 582a86208e89e77a7f284e10a50b9cceaf4358ee 64468 main/debian-installer/binary-powerpc/Packages.gz
+ f426621b1015147e766dc003d1d2f140dc9c062d 3706 main/i18n/Index
+ b22a946cdae39d29535a63b020c0f2ad74c3c992 4356187 main/source/Sources
+ 711225fd252e77d85c7bb992aeb5aa5e45414ae1 933770 main/source/Sources.bz2
+ a8807bf20dbaceb9d408f959840951131fd7d9f9 1174967 main/source/Sources.gz
+ cc2d2f6ce53597666df1a5ab216a08f08995f43f 98 main/source/Release
+ 06b070fc1ae771806c65e791742832320cc588e7 119109 multiverse/binary-amd64/Packages.bz2
+ ae591617f4b6f988d6534270d4c32e3f0876166b 151924 multiverse/binary-amd64/Packages.gz
+ a28786a87a6136fb74a005c480c78a152123b9c0 581550 multiverse/binary-amd64/Packages
+ 3860a3ce6d87bb8a43803a1048cc96d4de3ae8a7 103 multiverse/binary-amd64/Release
+ 4bae80c3f5270e45f825141bcadb94d7dd82cd0e 136295 multiverse/binary-armel/Packages.gz
+ 9534dfc2e4a40386f48eff79062ee1742212b7d3 519605 multiverse/binary-armel/Packages
+ 92d1536ae99c958afd74299ffe30bdc6800cd8d0 103 multiverse/binary-armel/Release
+ 8e3ec557dc8f750e82e8ed5cbb0c509182feba79 106873 multiverse/binary-armel/Packages.bz2
+ 009531e7cfb08701883a9e7a5f50235325e109cd 104529 multiverse/binary-armhf/Packages.bz2
+ 596a666233560852574d9bca0109f4933a12c949 505901 multiverse/binary-armhf/Packages
+ eca4ab620c41d76c00a9615d8530db5a9c918fe8 103 multiverse/binary-armhf/Release
+ 53916a24cff0523e218bfee2c5464866d2099042 133117 multiverse/binary-armhf/Packages.gz
+ a7518b6b3e693d840a49b125020785d2049e75b9 121196 multiverse/binary-i386/Packages.bz2
+ 84069f1643bd0092f4ec1b24eb921310532d72b2 591662 multiverse/binary-i386/Packages
+ 1d42b054d297b33cf69af011fa91f601c6b1a1b9 102 multiverse/binary-i386/Release
+ 8eae892b29234e9aac4c58a7098b097fe5ebde16 154762 multiverse/binary-i386/Packages.gz
+ 873bc8f864de428a4a47a3afaf53bc3a3a6e81c0 105 multiverse/binary-powerpc/Release
+ 665942774934afa56721d082a398735a067afe91 107209 multiverse/binary-powerpc/Packages.bz2
+ c965416be0f7bf88c78394becf4a72aee342b829 520882 multiverse/binary-powerpc/Packages
+ e304951d28df0b75065fd3ef8166c65415a3cad2 136930 multiverse/binary-powerpc/Packages.gz
+ da39a3ee5e6b4b0d3255bfef95601890afd80709 0 multiverse/debian-installer/binary-amd64/Packages
+ a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 multiverse/debian-installer/binary-amd64/Packages.gz
+ 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 multiverse/debian-installer/binary-amd64/Packages.bz2
+ 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 multiverse/debian-installer/binary-armel/Packages.bz2
+ da39a3ee5e6b4b0d3255bfef95601890afd80709 0 multiverse/debian-installer/binary-armel/Packages
+ a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 multiverse/debian-installer/binary-armel/Packages.gz
+ a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 multiverse/debian-installer/binary-armhf/Packages.gz
+ da39a3ee5e6b4b0d3255bfef95601890afd80709 0 multiverse/debian-installer/binary-armhf/Packages
+ 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 multiverse/debian-installer/binary-armhf/Packages.bz2
+ 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 multiverse/debian-installer/binary-i386/Packages.bz2
+ a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 multiverse/debian-installer/binary-i386/Packages.gz
+ da39a3ee5e6b4b0d3255bfef95601890afd80709 0 multiverse/debian-installer/binary-i386/Packages
+ a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 multiverse/debian-installer/binary-powerpc/Packages.gz
+ da39a3ee5e6b4b0d3255bfef95601890afd80709 0 multiverse/debian-installer/binary-powerpc/Packages
+ 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 multiverse/debian-installer/binary-powerpc/Packages.bz2
+ 09a8aff01c419e0eae19749acf3b223e1f95eccc 2676 multiverse/i18n/Index
+ a088c61bca210afebf4c53904049e2a969d8ece3 154990 multiverse/source/Sources.bz2
+ df4078a91645024ce93b1ee363003c83ffa2aa84 628753 multiverse/source/Sources
+ e6ec0430d594fa7fa2c98cb9a5fa8ac7ed0d506d 188325 multiverse/source/Sources.gz
+ 0750588f28b1c2cf6a005501c7d027cfa663cce1 104 multiverse/source/Release
+ 200fdeee1984ac78b6fdabfad34d2b485512ca2d 9098 restricted/binary-amd64/Packages.gz
+ 0e7ebd3d2690c7f89d19f8b337cf292cac913c18 134705 restricted/binary-amd64/Packages
+ c968d68baa554ffc7009688ee7d0d3e70663243c 103 restricted/binary-amd64/Release
+ 4185a5b6c2e702ea4754437ebfef23d828ec67a0 8452 restricted/binary-amd64/Packages.bz2
+ 27886dcc6c7d08369cc65d4c35f26b806f57be56 103 restricted/binary-armel/Release
+ a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 restricted/binary-armel/Packages.gz
+ 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 restricted/binary-armel/Packages.bz2
+ da39a3ee5e6b4b0d3255bfef95601890afd80709 0 restricted/binary-armel/Packages
+ d83803a5f6c2f5c7321d68d126733b6015c8e2a9 103 restricted/binary-armhf/Release
+ 6607111b78dcd3de05cb88692c1e2142abf9a4c1 1103 restricted/binary-armhf/Packages.bz2
+ b9f55d161632f89b5125a638ca6ad4fe5e9d11fe 2477 restricted/binary-armhf/Packages
+ d0c0a616aeac580d13256693cfbd507ae7c9b280 941 restricted/binary-armhf/Packages.gz
+ f3e483bbe77cbf0f64accbd0291df19b4e4d694b 9108 restricted/binary-i386/Packages.gz
+ 48d76b03a19e4d66d6f7a20339dab91acebaba99 8431 restricted/binary-i386/Packages.bz2
+ 3ca46ea8f32b7cbc49ce76dd1c1ab91589900fd7 134582 restricted/binary-i386/Packages
+ 2aad61f5084ecdd64ff520520d77e980e8b21f81 102 restricted/binary-i386/Release
+ a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 restricted/binary-powerpc/Packages.gz
+ 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 restricted/binary-powerpc/Packages.bz2
+ da39a3ee5e6b4b0d3255bfef95601890afd80709 0 restricted/binary-powerpc/Packages
+ 6b0a230bbf47463e3d7e88f535e210aaa96a1251 105 restricted/binary-powerpc/Release
+ da39a3ee5e6b4b0d3255bfef95601890afd80709 0 restricted/debian-installer/binary-amd64/Packages
+ 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 restricted/debian-installer/binary-amd64/Packages.bz2
+ a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 restricted/debian-installer/binary-amd64/Packages.gz
+ a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 restricted/debian-installer/binary-armel/Packages.gz
+ 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 restricted/debian-installer/binary-armel/Packages.bz2
+ da39a3ee5e6b4b0d3255bfef95601890afd80709 0 restricted/debian-installer/binary-armel/Packages
+ 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 restricted/debian-installer/binary-armhf/Packages.bz2
+ a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 restricted/debian-installer/binary-armhf/Packages.gz
+ da39a3ee5e6b4b0d3255bfef95601890afd80709 0 restricted/debian-installer/binary-armhf/Packages
+ a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 restricted/debian-installer/binary-i386/Packages.gz
+ 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 restricted/debian-installer/binary-i386/Packages.bz2
+ da39a3ee5e6b4b0d3255bfef95601890afd80709 0 restricted/debian-installer/binary-i386/Packages
+ a0fddd5458378c1bf3c10dd2f5c060d1347741ed 20 restricted/debian-installer/binary-powerpc/Packages.gz
+ 64a543afbb5f4bf728636bdcbbe7a2ed0804adc2 14 restricted/debian-installer/binary-powerpc/Packages.bz2
+ da39a3ee5e6b4b0d3255bfef95601890afd80709 0 restricted/debian-installer/binary-powerpc/Packages
+ d59f5ac2532dcc7cb2f1e5b788c700bf8ab13b66 2596 restricted/i18n/Index
+ 8a80cdcf50cdcabcf4f47c772d7b252587cc9dc1 19001 restricted/source/Sources
+ ff7d82cf1d965953c745d224a1d4adc67b586528 5470 restricted/source/Sources.bz2
+ f64da9da2038712c5d73ce3337e91d92ee39cd30 5306 restricted/source/Sources.gz
+ 5c963f5f4d4720afa5fbb914375d0033bcd50078 104 restricted/source/Release
+ 10c6989f4a241aabe00146905e776391fc4d9ac0 25546870 universe/binary-amd64/Packages
+ f6900616102430e0eafa8ac89795efff7edc0710 4785960 universe/binary-amd64/Packages.bz2
+ 4f938bde9dff32a49bccd917613666017185882d 6166988 universe/binary-amd64/Packages.gz
+ 9d6cba1ed46b5eee1f6c065934e5f4854b3efee5 101 universe/binary-amd64/Release
+ 3573e863c714c0a083f9c962ea9136916f796e92 101 universe/binary-armel/Release
+ bb8f53ead3723737c13950e5343327884f737da9 4667308 universe/binary-armel/Packages.bz2
+ 43d9a98706b6e50c21092ce35313b5b034f30d01 6009219 universe/binary-armel/Packages.gz
+ 7f97dcbe710882d281efcfd2f8d70ca7d4e47265 24901082 universe/binary-armel/Packages
+ 8f6d42d7f8178a51a7065d7bf3234eecbca12810 5948128 universe/binary-armhf/Packages.gz
+ ea648f433d0edd47de820582fa6a1cd89ef66681 101 universe/binary-armhf/Release
+ e6ad9bdb18ce9e09e262b9e6f85b0b307a3456f1 4618508 universe/binary-armhf/Packages.bz2
+ ba55530da6c3a9604977ea4a37b4b4d8943ff994 24642528 universe/binary-armhf/Packages
+ 05de59263866a33c104787943347164e7b124aba 6179579 universe/binary-i386/Packages.gz
+ 286a3dd2fda0d98d2ff14eafee0bba5c912d6df2 25568759 universe/binary-i386/Packages
+ 839529b6f6e2a64465e4a825fa5ad46a36f1c73d 100 universe/binary-i386/Release
+ 70c27be4d8bc87dc26bbe6f21fbb7328dc1c4d01 4795820 universe/binary-i386/Packages.bz2
+ 06af7fdef1a54920a7667728a7b810553d00a9c8 25188905 universe/binary-powerpc/Packages
+ 4df1b07075b25ccae6e60d26d5a5761444ece689 6080488 universe/binary-powerpc/Packages.gz
+ 15d041ad1284527b07f75218cf6eb32322092f84 4716652 universe/binary-powerpc/Packages.bz2
+ 42d6a46ed2e525b219f8f6dc076dadbd06fc7f1b 103 universe/binary-powerpc/Release
+ 92c3bef6ad40051021a4e9dadb16e5edc7410b57 15255 universe/debian-installer/binary-amd64/Packages.bz2
+ 31d8725b0d238c282d9b572bb56b7e45c0ff53f8 17243 universe/debian-installer/binary-amd64/Packages.gz
+ e334a7c80e14dae3055950d9e45213db65d4087b 61801 universe/debian-installer/binary-amd64/Packages
+ 1fd1ae2b87eb85525b173ea982d15f3c98e6e33d 113584 universe/debian-installer/binary-armel/Packages
+ c56579feb77b5aac2d261abbbb6c89a1458ca4d9 23193 universe/debian-installer/binary-armel/Packages.bz2
+ e4b08e57397f3ab0599e0bf6a2fbcba3aed438b5 27397 universe/debian-installer/binary-armel/Packages.gz
+ 5a9608213061eab983392258288e8aec36d006f0 20065 universe/debian-installer/binary-armhf/Packages.gz
+ dc558d56aef72991a3188909a14f752aabdee325 17619 universe/debian-installer/binary-armhf/Packages.bz2
+ c6afa0e14c706aceea60aad033b6a067320fc165 76034 universe/debian-installer/binary-armhf/Packages
+ f359cf916a19055133546a7b7f3e35c7c260488e 17260 universe/debian-installer/binary-i386/Packages.gz
+ 23920ee4974d88ba824b0e884f8df6e2711a20db 15272 universe/debian-installer/binary-i386/Packages.bz2
+ 21cfd020eefc848307fac14b8f0efe0d6cd9c6ea 61718 universe/debian-installer/binary-i386/Packages
+ f2ff72c8f1fe4ce40ccf44f8ccd6623cedf4e6f0 61121 universe/debian-installer/binary-powerpc/Packages
+ bd9c731941b261b22c022d97ca139bfeb1ad70ba 15024 universe/debian-installer/binary-powerpc/Packages.bz2
+ e173071bda799068783c9192bff6536db9790a27 16860 universe/debian-installer/binary-powerpc/Packages.gz
+ 59a86abaed7cab292600b6766b18752b7e7c3d49 2922 universe/i18n/Index
+ 4b0ed5f327b0fa9b3f9d9410933a3d2afe467a7e 21256524 universe/source/Sources
+ d0525203f9ad5ec9183996e6765d0ef9a024691f 5019105 universe/source/Sources.bz2
+ 00847d46051ba44d436000b0394b218503de125b 102 universe/source/Release
+ d9706a8ab2ffeadb51b50d042712536a95dc4343 6238766 universe/source/Sources.gz
+SHA256:
+ 0d61aacd269015c0abfe01fe7f90a4f534c368e9c513f7e90d3111af82656b3d 1640344 main/binary-amd64/Packages.gz
+ a1bc8d839ca9966a0b924e4a4c60f1c23b4d431deb81e1bc529edf95f30fc29d 7818931 main/binary-amd64/Packages
+ a55d3b2e6e2a175529d73e6ca92989018cf57745e705f7ff675b05f80e5141f7 97 main/binary-amd64/Release
+ cc0d3a19c51188b4b4acb80e3013264462c6e0f60759bfd46206c60681bd4ba9 1272844 main/binary-amd64/Packages.bz2
+ a841750f49bd11f99b9dae6941d2fa6ec1fd87906139d0ceeacf0d4df57a87cf 97 main/binary-armel/Release
+ e80eaf12c1aa520b353de8ad97e79364779e82ef011cb93db372edc900eb7be9 1619078 main/binary-armel/Packages.gz
+ 0ab0929c3c44837886e532f8ec4bee77f3664bdcc2cc3192a02b991c52b156ce 1257389 main/binary-armel/Packages.bz2
+ ea400cf67f84c12265e4bf419de442a38880fab37d76999985972fc6df3e13b3 7743353 main/binary-armel/Packages
+ f3c40f057bb085f28ef2ed950f62366483d2a418571435c355dc27c0912dccff 97 main/binary-armhf/Release
+ cde037224f43e4619213c5195f2ea5c2f91d078f449579652dbd4128793d5062 7620333 main/binary-armhf/Packages
+ 7c6ea67e609b96dec6f2185df4cd81160e37ba467f9132a9bfb101da3f9a0468 1257653 main/binary-armhf/Packages.bz2
+ 2b83bf5501ecae3347e5c96658edae7d48eef42108b4786471a3de241e75e7d3 1617483 main/binary-armhf/Packages.gz
+ 4d74c53917b84d37cb3277e2b755672a8733e2cfaf949f6e644e6e88094cdaa2 1273857 main/binary-i386/Packages.bz2
+ 07f33bddfefdb4a0c44ddee59fd3eca497df2ad0456e0eeade136e4f0302ee3c 1641082 main/binary-i386/Packages.gz
+ 5182e22f799fe66c8db6dfb073fb040e9e583d88bb9d4d77e058b2afb87e9479 96 main/binary-i386/Release
+ 4cecfc8c0d2113d51b03afa8fdcdcc963d9ad74474696472ec1cdbdb38b856e2 7816415 main/binary-i386/Packages
+ 2795904625f466b4a2fb96d41c00b000ab7f2bdc7f288b0c9ef1283d7e110f87 1627734 main/binary-powerpc/Packages.gz
+ a9247e6d8b0c5977bc1e72be09b1f42a83b5f5a6a70b17f4fef35a0657e3c206 99 main/binary-powerpc/Release
+ 6e745b7edcd67755fa09f54cc3afdd0ffbd0475302a74293472e97e46ba75ddc 1263942 main/binary-powerpc/Packages.bz2
+ 8b953dbae4a14e7ab47151044a47c7b0f0e1dd2a6480170b8172e00d9dad7a2a 7661552 main/binary-powerpc/Packages
+ a5bdf4116ecfeda052d5b3751138c6153e814ac58b2f551503f3ed90e6c3510c 62166 main/debian-installer/binary-amd64/Packages.gz
+ 6a9a4837a4a7df3e7e0566b354b7f1dd2dcf46254335ae3d06a72538f85e410a 234592 main/debian-installer/binary-amd64/Packages
+ 0da4f8190eebfef22103f1f6f7051adbe9489d454ab7224f09d05646407881e8 48784 main/debian-installer/binary-amd64/Packages.bz2
+ ea01244357deb22c2a4bd7eaa34a1635c0915b89ce174f312c0e0a4b081eaf30 47964 main/debian-installer/binary-armel/Packages.bz2
+ 4177b0519c75f7f950e5a0f0d72d40cc0c4ccf29ebe89fbb9bc1f11a80874526 230310 main/debian-installer/binary-armel/Packages
+ 2b6f81ef9fa687bfb2eb56bb3e90faef0c012351d096b141caa710fd50846043 61118 main/debian-installer/binary-armel/Packages.gz
+ 52c834247ff3a5475466e647802f6eff393f85589e5da5fd3e5b497669b8b49c 62777 main/debian-installer/binary-armhf/Packages.gz
+ 7090f1ad1307a012fbfff883885f16099ed66ebffdeece356f837e632b177a4f 49051 main/debian-installer/binary-armhf/Packages.bz2
+ 4bae13f507993e977c279937406fc03e37fede7805a92508f6d3cba76f1aaf95 238862 main/debian-installer/binary-armhf/Packages
+ d1d23926ff15cfaa6160c5fd0327d181721093fbd2f2e8125be5559a991a81a8 52279 main/debian-installer/binary-i386/Packages.bz2
+ 30e0ec7a2c3d47d5501de8414b436482ff523e9c4983b536b2c9911a30618b98 259996 main/debian-installer/binary-i386/Packages
+ 7a4dcb001ed4bb5fa2458af901de312e11a745bc86a0f877e47567d0f911bc0d 67180 main/debian-installer/binary-i386/Packages.gz
+ 30c2f590c2dedc9f78dfc7f0026b51bc9baa712ac8c9310404d9d6577af77d90 246636 main/debian-installer/binary-powerpc/Packages
+ 6c53fab780cf774c5cabb1788eea1e3446c528cde4352d106907f4ec22449370 50309 main/debian-installer/binary-powerpc/Packages.bz2
+ b003f3fbf2fa6dbf7d47cf3fbd029ecd86b316ec497a9ac4eea3614cf4ec76af 64468 main/debian-installer/binary-powerpc/Packages.gz
+ fefed230e286d832ab6eb0fb7b72442165b50df23a68402ae6e9d265a31920a2 3706 main/i18n/Index
+ bb618cebb361a2a7148be0bad9af012c8d9de23dbc32d6d9ba035fa6ee0078ab 4356187 main/source/Sources
+ 0aeef2c2258136f9f774c36a158cf759389acf6a35a3153a03d3fa41d4f346d5 933770 main/source/Sources.bz2
+ 4a058ba65244e8eaf17d159b72edebe4e621d54c274a82d4a973b358b4af9a28 1174967 main/source/Sources.gz
+ 864ba9a26e348c6297c08c047d8c228e5ed031ec3d46ef7aad93c3fa550395a8 98 main/source/Release
+ 85477d2b2e7ea2f46b6a059f7526cf52d75fea1a5120aa3b256c576e904d40ff 119109 multiverse/binary-amd64/Packages.bz2
+ 2967ae6c1cc065bec03225d808b4511b138cc13b8de801a0562fec6e30710f36 151924 multiverse/binary-amd64/Packages.gz
+ 18fcf61bb74ef2a01c3d4a8d4646a75836f43244168b43d6ae202f368167b224 581550 multiverse/binary-amd64/Packages
+ fbc4931ef84d50a39da65d110f787aee274df8819a758a3c0aa1ff13f0ba6ee0 103 multiverse/binary-amd64/Release
+ 49f48a34696d08a13a0fdc19a0f6896af2cb477e72860a8880954926c7d45e60 136295 multiverse/binary-armel/Packages.gz
+ f20d7f0bc32b5b2fbcb442f7c128aaad7e18aece3781d53f560932bb191d6830 519605 multiverse/binary-armel/Packages
+ f7ea72b2c07af81f2e342414025dce7a658a6a9915c4d8adc13b992cb3b9fd2f 103 multiverse/binary-armel/Release
+ dd3d4e8a6ec9055d5b553af49822de74648f071ceb0fd314d6cd1aaf7ad6882b 106873 multiverse/binary-armel/Packages.bz2
+ 567c1f9d30a4d6650552d66c5fb43d2d8910d3fed69793daed622d2c699f4bc8 104529 multiverse/binary-armhf/Packages.bz2
+ a47ef2c0a68adeb70a0bc6b22c94b08402396ff6f5c77664e06c2fb7ee0e7ab0 505901 multiverse/binary-armhf/Packages
+ 6b95e8edaa2bb799f6e15a4a6aaf223da0faea670cd03340395bdcea90205afc 103 multiverse/binary-armhf/Release
+ 14721b333f19a6344addb185f161d1cd14e04ac284c8fa9d726064ec228269a8 133117 multiverse/binary-armhf/Packages.gz
+ 454436f374186007075445c1f206ba5c926f30609baa732c495f1ba456d71e59 121196 multiverse/binary-i386/Packages.bz2
+ 9fabd7bfdbfd216968f7a17265e5609cdd72f1ea7c8f50941e294694e76b180d 591662 multiverse/binary-i386/Packages
+ 7141881b898ac6a78f1ca6f3e81481ee6657f6762fa22768816ab39f6b17e695 102 multiverse/binary-i386/Release
+ 3f4cae31df741f55d523ecea758d05a7e012a205bb03974ee20eb09e3f4fa63b 154762 multiverse/binary-i386/Packages.gz
+ 332dde644a8467496eb5f45ffd2d735ca61ea781da21cd205b3267cd83fa0563 105 multiverse/binary-powerpc/Release
+ 99ef0a611aa32ffa4f16a006d641fbd8dd9e3e73bde3c93b831cd6583746e64b 107209 multiverse/binary-powerpc/Packages.bz2
+ 60f2431dab7bd02fe2c2428bf400c3535be49641cc9d5645a8f1b4fd44f5086f 520882 multiverse/binary-powerpc/Packages
+ cacfd10b40992a617ce32c479f9505531c8cc57e4cf964687d663a5f41f8dcbd 136930 multiverse/binary-powerpc/Packages.gz
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 multiverse/debian-installer/binary-amd64/Packages
+ f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 multiverse/debian-installer/binary-amd64/Packages.gz
+ d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 multiverse/debian-installer/binary-amd64/Packages.bz2
+ d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 multiverse/debian-installer/binary-armel/Packages.bz2
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 multiverse/debian-installer/binary-armel/Packages
+ f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 multiverse/debian-installer/binary-armel/Packages.gz
+ f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 multiverse/debian-installer/binary-armhf/Packages.gz
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 multiverse/debian-installer/binary-armhf/Packages
+ d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 multiverse/debian-installer/binary-armhf/Packages.bz2
+ d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 multiverse/debian-installer/binary-i386/Packages.bz2
+ f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 multiverse/debian-installer/binary-i386/Packages.gz
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 multiverse/debian-installer/binary-i386/Packages
+ f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 multiverse/debian-installer/binary-powerpc/Packages.gz
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 multiverse/debian-installer/binary-powerpc/Packages
+ d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 multiverse/debian-installer/binary-powerpc/Packages.bz2
+ f0b16a5cfd2d633c9ddecfadfa6742544b18c23ed30023286e2b20ef29f33c73 2676 multiverse/i18n/Index
+ faa0360612fc00453dfdd55b6a1bb20e4f876e041ad6fca410d5da65608ab31e 154990 multiverse/source/Sources.bz2
+ 2f0deae62e2cf7e5257bbd858cb0bf2a94122c4eb82be13e13768d0b9ce84c9e 628753 multiverse/source/Sources
+ 28f6d95fcba03e442cf24dc547653d5ec60177a29d7cfea771efcc5501077747 188325 multiverse/source/Sources.gz
+ f35f721bf16691842cc916c3563fab535f6bb83329f40c33ac02f4ba637707d3 104 multiverse/source/Release
+ 3e872fa356cbce4dfd75a88caa4fc6b47616e1fc7d224f4fc2123650fd7f4be3 9098 restricted/binary-amd64/Packages.gz
+ 459a26c3ef3cb5db8c8355ea6abfa8cfe0a7a266a197929d86d37686daf8a337 134705 restricted/binary-amd64/Packages
+ ea47572182da041b46543e471cb7a6fcc4e001fbe19a27740085ebf5d77252a9 103 restricted/binary-amd64/Release
+ adb08d7f0fa444f2869e8d932db7adb1515839f11af6032284cf1e20060e2dd6 8452 restricted/binary-amd64/Packages.bz2
+ 65a5ac0820d61383f7dcf33699aa029b5965b7906bc8341f94f8f7f354cdcd83 103 restricted/binary-armel/Release
+ f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 restricted/binary-armel/Packages.gz
+ d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 restricted/binary-armel/Packages.bz2
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 restricted/binary-armel/Packages
+ ee447ce81793bd3bc8c127d4e065c6ec24e5901573dffb7cc5abedfbcb86592c 103 restricted/binary-armhf/Release
+ d88ed7df97cd60cdce35c3ca81de66e2bedf0f22e67ec8922dbd5eca545b5e50 1103 restricted/binary-armhf/Packages.bz2
+ 9ade66f4a49598fb371705a79244e5f3abb74c04467f9f9954641ae5acec6766 2477 restricted/binary-armhf/Packages
+ 03d8b64c445f327ce9e369bca815652844bd6aafb344d0287fb4e71f321d0414 941 restricted/binary-armhf/Packages.gz
+ 07e344ed07234876c3fddd9aa763e04bfc2e013fc18428738be71abfb9e1ca77 9108 restricted/binary-i386/Packages.gz
+ 8061335b923c49e72a2b60b437d5bbad1b98a45ac178a68fd8359cec9fad27ec 8431 restricted/binary-i386/Packages.bz2
+ 122336146860047af3d5817dbc423f01d57a90cbf41db1ee0ad9235c0559a43e 134582 restricted/binary-i386/Packages
+ 58634ed42b6fadb280d48f419b960e28151320a62b4486e520ca327719db554a 102 restricted/binary-i386/Release
+ f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 restricted/binary-powerpc/Packages.gz
+ d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 restricted/binary-powerpc/Packages.bz2
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 restricted/binary-powerpc/Packages
+ d9bce398e46f0eac57d1d33fd8a6caa0bd7ab6334508c0640956cb7adbe1eba1 105 restricted/binary-powerpc/Release
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 restricted/debian-installer/binary-amd64/Packages
+ d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 restricted/debian-installer/binary-amd64/Packages.bz2
+ f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 restricted/debian-installer/binary-amd64/Packages.gz
+ f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 restricted/debian-installer/binary-armel/Packages.gz
+ d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 restricted/debian-installer/binary-armel/Packages.bz2
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 restricted/debian-installer/binary-armel/Packages
+ d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 restricted/debian-installer/binary-armhf/Packages.bz2
+ f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 restricted/debian-installer/binary-armhf/Packages.gz
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 restricted/debian-installer/binary-armhf/Packages
+ f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 restricted/debian-installer/binary-i386/Packages.gz
+ d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 restricted/debian-installer/binary-i386/Packages.bz2
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 restricted/debian-installer/binary-i386/Packages
+ f61f27bd17de546264aa58f40f3aafaac7021e0ef69c17f6b1b4cd7664a037ec 20 restricted/debian-installer/binary-powerpc/Packages.gz
+ d3dda84eb03b9738d118eb2be78e246106900493c0ae07819ad60815134a8058 14 restricted/debian-installer/binary-powerpc/Packages.bz2
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 restricted/debian-installer/binary-powerpc/Packages
+ 17dde58abfdb4dfdad9c8a82db09c9dbc3d8a7cd84b51dd9167579d6899e9ff5 2596 restricted/i18n/Index
+ ee3655459e45778fdfa06fb649565e66b25d2dd0870c75890005fb3597bb71d7 19001 restricted/source/Sources
+ cff18d2ad74ead8712f1b77a23b32e84e54269b03ba2a409ae4227860d1181f5 5470 restricted/source/Sources.bz2
+ cf085bdcb323dd2c2a599ddb7a9b3ae7bd37121f42024d68b367a4f735df900f 5306 restricted/source/Sources.gz
+ 9137393fc24cf64808d55ca7665bc5a7bd46b48918e6720a95ba239a8fab092e 104 restricted/source/Release
+ 901469729d2354891be94c192dabd8c1d0bc31e1497ea8360b70d2e847c1f3c1 25546870 universe/binary-amd64/Packages
+ 799347395d4e011a215aa5ce0c9006449d8af884795ffbce7a35767a55f99074 4785960 universe/binary-amd64/Packages.bz2
+ 68b08847604c4efe7d6f56ba79f923ce0ab82127dfcc6e8cffaf12af25d7adba 6166988 universe/binary-amd64/Packages.gz
+ 52ffdd1777a886edc5e1e1ef430b03a72937920f9722fd453ee8243cb0aac860 101 universe/binary-amd64/Release
+ a78a1304e105b2fe4c950c77c1794f715c1256d14d8541cca8f5cd13db48119e 101 universe/binary-armel/Release
+ d6d4bfa5d0891086f5a4f2aabfaecd7a1e0c0d8b46aef33b3470e349e7a9210e 4667308 universe/binary-armel/Packages.bz2
+ 374d50d0335c655da46f9cd54cd00d9a20058d2fe7c56989aa121b49883cfb88 6009219 universe/binary-armel/Packages.gz
+ ab5073e90417b729d1fe3b68052e6a8e66e48986c35470944f6a58676e967450 24901082 universe/binary-armel/Packages
+ af74034d1a3e1f90745dc48b996a98c471d997b12a1d810eb8754088540591d7 5948128 universe/binary-armhf/Packages.gz
+ 6697d196b35850817476e884fdc013d9670b4bac73310c54a4d62cd810f02c70 101 universe/binary-armhf/Release
+ 1ca17d3aecec2325cba53e1c299aeb6a1fed01d7acbc40163595de9e651abdeb 4618508 universe/binary-armhf/Packages.bz2
+ 2b422ffa77d4374650d4cc543c5a1123b2535effb2c8cdaf25fd77d1dde632c4 24642528 universe/binary-armhf/Packages
+ cd6b5cb8165553482abee1bf85e5cd3288abadccb6acf34239ec45f79a090784 6179579 universe/binary-i386/Packages.gz
+ 8ef7db20ba08cf1b4d98a618189c615c69865f4da025ac654e3e6b8a4382a3ae 25568759 universe/binary-i386/Packages
+ 06af492500145bd64762d885417d167269db6ea03022c6968f1a5d0515ac55dd 100 universe/binary-i386/Release
+ 530a2efb8051a63ed17431ae0c7243df79ecb418acf1dadc2487cd6fd79fb420 4795820 universe/binary-i386/Packages.bz2
+ 1e8fa52a64292d2c73cee0645d0eed5583ea7cc1138af4744838c6833716d638 25188905 universe/binary-powerpc/Packages
+ 5d2b8e23e0a16f13e25595b63807fb64afd9074aadf7a37b8e238b2011e894b8 6080488 universe/binary-powerpc/Packages.gz
+ eb482b008c8c882b349230abaa812ed6e545a2ef9132bb0d3d3bffa74da0c6c7 4716652 universe/binary-powerpc/Packages.bz2
+ 98d44cc7544f79c18b8e8ea697d476e9b85d91088385b643c82d4064b21f4657 103 universe/binary-powerpc/Release
+ 3da2d1e57aaca628148e2688a951cbb784a9a54b7f6b1f84d530add1b66fcceb 15255 universe/debian-installer/binary-amd64/Packages.bz2
+ 43f891ac590f44fde5854de9ba15222c088b70562f5dc4ff26064909e60cf62e 17243 universe/debian-installer/binary-amd64/Packages.gz
+ 3084a8a441e961eeb3865ff411557166ec105be86a55df268cdb6725f49e1f67 61801 universe/debian-installer/binary-amd64/Packages
+ a1ff01f18766744f36d0774a68d8a89355246c585c4b28ee18e5e139fafae530 113584 universe/debian-installer/binary-armel/Packages
+ e0713f86f5f5121deb60ce61d774951468625184a7ae9576f81d70202ef585b7 23193 universe/debian-installer/binary-armel/Packages.bz2
+ 5a8411e2b0648e553fa25ac82ea83fb17dd2d2a77bd10cec14cab12f5582d4c4 27397 universe/debian-installer/binary-armel/Packages.gz
+ b79c86d926c3129f5c27e50185157a78d85abde8ada90a9910338e660c4318be 20065 universe/debian-installer/binary-armhf/Packages.gz
+ b2113b25380423be8f6202a4860479e44a00072e46fa035f0da2f3a5a280de20 17619 universe/debian-installer/binary-armhf/Packages.bz2
+ 3f023d2cc55d6ebab883f6f2d7305a4e3564f918f63ca4f745d6fd1318e67ab7 76034 universe/debian-installer/binary-armhf/Packages
+ 5ea61a62a3e8fc755c22e23c9d87b20924707c0986a490458472a3d7e9cbe117 17260 universe/debian-installer/binary-i386/Packages.gz
+ 7a90b014c655311e92de1ea4cf24e100665c564a2ed699df63d17c82ad9e1349 15272 universe/debian-installer/binary-i386/Packages.bz2
+ 7e39417ce073e3a35d048847a29a0414af69c4e923c018dc22438319c79adea5 61718 universe/debian-installer/binary-i386/Packages
+ cdf17a791544d0c522fa853a23b317deffa76ac643e88bec0b84b0aa5afe957b 61121 universe/debian-installer/binary-powerpc/Packages
+ b470146da791dc4f4593d2bb00ea4e305d6f55f346a5f3ac6755d890a3318080 15024 universe/debian-installer/binary-powerpc/Packages.bz2
+ 810d1590d1cd7298e1fd5465f85ba49b6ae79780b42d8e8b68aebb42283785ea 16860 universe/debian-installer/binary-powerpc/Packages.gz
+ 563a55a892e1ec8bf565e3294c033b4e8dbbbe4651e73733eac7338db77282f7 2922 universe/i18n/Index
+ 7bc01d4f10bbcf882ce6931aa9371b2de6b35277efc2ae52e233280dcd12a18d 21256524 universe/source/Sources
+ 95135631873f4dce05ba657478475033d02462bbb8f7263832585d1decb5c9b8 5019105 universe/source/Sources.bz2
+ 0fd2ae580be352cb8ab4bb87e5504b78f78bcb7249b644719b3c2db3b5d3ca8c 102 universe/source/Release
+ d1dd96015e24dd369ea22413a2b876686a60c5d9d91958a5df3745a66289910f 6238766 universe/source/Sources.gz
diff --git a/tests/data/tagfile/history.1.log.gz b/tests/data/tagfile/history.1.log.gz
new file mode 100644
index 0000000..4174e02
--- /dev/null
+++ b/tests/data/tagfile/history.1.log.gz
Binary files differ
diff --git a/tests/data/tagfile/history.log b/tests/data/tagfile/history.log
new file mode 100644
index 0000000..f1d7266
--- /dev/null
+++ b/tests/data/tagfile/history.log
@@ -0,0 +1,15 @@
+
+Start-Date: 2012-02-01 13:54:52
+Commandline: apt-get install chromium-browser
+Install: chromium-browser:amd64 (16.0.912.77~r118311-0ubuntu1), chromium-browser-l10n:amd64 (16.0.912.77~r118311-0ubuntu1, automatic), chromium-codecs-ffmpeg:amd64 (16.0.912.77~r118311-0ubuntu1, automatic)
+End-Date: 2012-02-01 13:55:01
+
+Start-Date: 2012-02-02 10:39:04
+Commandline: apt-get install python-geoclue
+Install: python-geoclue:amd64 (0.1.0-4build1)
+End-Date: 2012-02-02 10:39:08
+
+Start-Date: 2012-02-03 10:20:50
+Commandline: apt-get install python-qt4
+Install: python-qt4:amd64 (4.9-3ubuntu1)
+End-Date: 2012-02-03 10:20:55
diff --git a/tests/data/test-provides/etc/apt/sources.list b/tests/data/test-provides/etc/apt/sources.list
new file mode 100644
index 0000000..2955b5c
--- /dev/null
+++ b/tests/data/test-provides/etc/apt/sources.list
@@ -0,0 +1 @@
+deb http://archive.ubuntu.com/ubuntu oneiric main
diff --git a/tests/data/test-provides/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_oneiric_main_binary-i386_Packages b/tests/data/test-provides/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_oneiric_main_binary-i386_Packages
new file mode 100644
index 0000000..f991cb9
--- /dev/null
+++ b/tests/data/test-provides/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_oneiric_main_binary-i386_Packages
@@ -0,0 +1,75 @@
+Package: exim4-daemon-light
+Priority: extra
+Section: mail
+Installed-Size: 1092
+Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
+Original-Maintainer: Exim4 Maintainers <pkg-exim4-maintainers@lists.alioth.debian.org>
+Architecture: all
+Source: exim4
+Version: 4.76-2ubuntu1
+Replaces: mail-transport-agent
+Provides: mail-transport-agent
+Conflicts: mail-transport-agent
+Filename: pool/main/e/exim4/exim4-daemon-light_4.76-2ubuntu1_i386.deb
+Size: 451088
+MD5sum: 81795887e233ecfb3471e8a3da4c4b8b
+SHA1: da0202f7da88b9e9c5ee326a24c3fdd640543a5d
+SHA256: 5ffa03674b5198d1c0e9e0d9e3442cdd7fbe13226c7df91aa53def1f8b6c0d86
+Description: lightweight Exim MTA (v4) daemon
+ Exim (v4) is a mail transport agent. This package contains the exim4
+ daemon with only basic features enabled. It works well with the
+ standard setups that are provided by Debian and includes support for
+ TLS encryption and the dlopen patch to allow dynamic loading of a
+ local_scan function.
+ .
+ The Debian exim4 packages have their own web page,
+ http://pkg-exim4.alioth.debian.org/. There is also a Debian-specific
+ FAQ list. Information about the way the Debian packages are
+ configured can be found in
+ /usr/share/doc/exim4-base/README.Debian.gz, which additionally contains
+ information about the way the Debian binary packages are built. The
+ very extensive upstream documentation is shipped in
+ /usr/share/doc/exim4-base/spec.txt.gz. To repeat the debconf-driven
+ configuration process in a standard setup, invoke dpkg-reconfigure
+ exim4-config. There is a Debian-centered mailing list,
+ pkg-exim4-users@lists.alioth.debian.org. Please ask Debian-specific
+ questions there, and only write to the upstream exim-users mailing
+ list if you are sure that your question is not Debian-specific. You
+ can find the subscription web page on
+ http://lists.alioth.debian.org/mailman/listinfo/pkg-exim4-users
+Homepage: http://www.exim.org/
+Bugs: https://bugs.launchpad.net/ubuntu/+filebug
+Origin: Ubuntu
+Supported: 18m
+
+Package: postfix
+Priority: optional
+Section: mail
+Installed-Size: 3472
+Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
+Original-Maintainer: LaMont Jones <lamont@debian.org>
+Architecture: all
+Version: 2.8.3-1ubuntu1
+Replaces: mail-transport-agent
+Provides: default-mta, mail-transport-agent
+Recommends: python
+Suggests: procmail, postfix-mysql, postfix-pgsql, postfix-ldap, postfix-pcre, sasl2-bin, libsasl2-modules, dovecot-common, resolvconf, postfix-cdb, mail-reader, ufw
+Conflicts: libnss-db (<< 2.2-3), mail-transport-agent, smail
+Filename: pool/main/p/postfix/postfix_2.8.3-1ubuntu1_i386.deb
+Size: 1221834
+MD5sum: c4575f03ef0711cc744d394ae36f4a8c
+SHA1: f0f636c942981782cf23cee3d8a95aee188081b9
+SHA256: 13a4bfaf10c8addfc7dce01c0ea65bfbd6a759c4a2aaaafbae5855d099925fe0
+Description: High-performance mail transport agent
+ Postfix is Wietse Venema's mail transport agent that started life as an
+ alternative to the widely-used Sendmail program. Postfix attempts to
+ be fast, easy to administer, and secure, while at the same time being
+ sendmail compatible enough to not upset existing users. Thus, the outside
+ has a sendmail-ish flavor, but the inside is completely different.
+Homepage: http://www.postfix.org
+Bugs: https://bugs.launchpad.net/ubuntu/+filebug
+Origin: Ubuntu
+Supported: 18m
+Task: mail-server
+
+
diff --git a/tests/data/test-provides/var/lib/dpkg/status b/tests/data/test-provides/var/lib/dpkg/status
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/data/test-provides/var/lib/dpkg/status
diff --git a/tests/data/test-repo/Packages.gz b/tests/data/test-repo/Packages.gz
new file mode 100644
index 0000000..81daf2b
--- /dev/null
+++ b/tests/data/test-repo/Packages.gz
Binary files differ
diff --git a/tests/data/test-repo2/Packages.gz b/tests/data/test-repo2/Packages.gz
new file mode 100644
index 0000000..81daf2b
--- /dev/null
+++ b/tests/data/test-repo2/Packages.gz
Binary files differ
diff --git a/tests/data/test-signed-usable-repo/key.gpg.base64 b/tests/data/test-signed-usable-repo/key.gpg.base64
new file mode 100644
index 0000000..3bdec88
--- /dev/null
+++ b/tests/data/test-signed-usable-repo/key.gpg.base64
@@ -0,0 +1,62 @@
+mQGNBFzn06EBDADLLuONxlOlbDVZjkYPY6dJw16v5mSIL7r7BQ42ssUtO2V+B8bjTUCp3zRttadb
+tWigfz/Pqz5u6XLz+NPn3Nby6wMVrpfjxgKqjGF4kQ3Wi4ThHlsvgL12KoIOOxhmIJ3E8uLklza8
+lkYVPtzP1bgRjRx1QKLvdVAIy6iWVfQ9Xa8OtVBs7XZArSZ57mR37deaMOtvBdk9SOPQ939BimmN
+J9IuLSlzsaqTVtxYcT/F85U/EWSFa6s6BvoDwbOZfGTxjsSeADMgh7DuvcYhYB+1HtJAjUNurnrq
+92Ymx/i5k4lULJ0C8T2P7jqc437q1kAMoxhr8VwmtrfwDYTGiRHR0x5LA0wekP1HPHHJfmemQcCm
+2StjnMDEX16xuQsfwvkzbJvjULh1USR9Z7SPfWGcx28cUv71+34Us1YLUAvaaobjhX+zpcI1mn+o
+ljxu56uuW6ZRsyHvbWFdTTKB8TWggkmMnHL8EowlBtvRQItgJllWfCs16Ga4UbR/7Qia6BMAEQEA
+AbQjdGVzdEBleGFtcGxlLmNvbSA8dGVzdEBleGFtcGxlLmNvbT6JAc4EEwEKADgCGwMFCwkIBwMF
+FQoJCAsFFgIDAQACHgECF4AWIQQkgGw+FXEYW1oehsQ03un1nJNh+QUCXfelQwAKCRA03un1nJNh
++YsJC/0b3Y3d6Esy1O8r30EBcv6XKsHG8bRm4jGFm5bfGHPoNefgJStWtoTSFtY6QKbdTJFx7Ucp
+KuEPIFEaBw70RMUpO3OhYjmFTev13DQQyelhuzzDx7+Kxqq1FiqL14xFnTVLp5kVfEU9pZ5pZtWz
+LvJYwtNhTLCth+9i6jaWzVOwTtQHxEEau2FC5Mwk/KwTOmEn9Bnt3WPjdoGzyitcvgOjga50T1mm
+2Cjj8O5pDSG+Fwt5ZVbHBvEXxx+RI7QqEraD9QCjHauak0+ORnCBcFzoetBHCBZpA7t/Rr9FdGmt
+9G5zSFUUU4Bgrm/kJyIL/RQWleuxny1+/PjUY/Hwpa6XBK5yzkSNuO+6xCJfaZekG2z3GNL5KaO4
+c0O50FFj/pxUKMZj+dyc9aSYvQI2dccxvSLpPSezGMXDLMeNyR5R+J15Ld3NpFwp/wLZzoBpT+OA
+R2BKW+E+eoe1545naV4RM1fuN55oBTN6bJLLigsIaum7t3qZyRrMZGltZKRUqI65AY0EXOfToQEM
+AKQhepnHxSE0Z39H2AKUg8fUuqvs7qCdm8fqooPX+pqBt+030AD8e2dsgXurqMK9cMXTXvsfWd58
+0ZwMowwDc6QsXdtU1v4HrUIE3wH/7q8CE9q9giXEXlOkJcvHLhLiczAXzZ0cRmotgNIAhMKGNfMK
+CL3qZBOUphljuauNOklcHL0AcpU6NlDrzkNVaW4inmjkbAfQS8u+vEMx2sKcCBEJ8UOEcYEl4CaS
+dHwGFboklHtRDVHJpCqdgdEkXylriPy1XId/jjRhHDQ5MYRFPg+cDNpmGAn4irj8nGlDhR106ole
+QEcHyzsuoBMVRBC5EubQDjW7b0S5fV2ZXfs0gGOe/XDy+YMR/2XwNBNAlI+eZaBLxEoPdJSPiIr1
+VCvYVxke9oKC5gFd1gQ0O17OY1TjbeuXxx6RbOY8Rl14E/Y5YURhyAY84nQ7ibbUStsOR/YxL+2t
+8mrNI1ljWj+Knp3EdVXSq1bfrzB+IiDO35ziw3zAJpdgG9hLiHWsBICLZwARAQABiQG2BBgBCgAg
+AhsMFiEEJIBsPhVxGFtaHobENN7p9ZyTYfkFAl33pU8ACgkQNN7p9ZyTYflBoAv/de2tzgcWzksE
+4OMNaQggXbYtUxOmgLRy8Hrd+oAYuz9xozdsGFJoMdJlJ6i+XAGaGVUd1313isdkuS5aC47pEpuL
+G1V9qMQzAbY0oHyB5h+lZZVnLz1y3TZZDgvLY57xrYP6hTrwKkxxQ5ATkMhcxRBTRidxs9kJkx8j
+eeH+kYXeA3dS6Vk1IBiiDxJ/jb7qJfU+yb+hAbK3iBKh/FNYQ2Qd/EeYq37PeIVdegMliKslbRX7
+fBs83P5ssy1Hci3T4l5ZKRppIRRdniD4cislFzAxCQefcVrF1Su2+cg+5tvYmSIH2OuY/rxJX6lp
+IPcnzI0hwTQNAQIEOmtdUrOvJVRoLPCioi5G7pe1d5gssnyqrpILS+mFZvT+bSXFlfeMDC/eh6gz
+1/WIO9ENqZ7/Tf23Fvt3shjg4EJ+IkwvjUZ+rTs0FPQ1xznjD82FPcSM6HX/jNpXnfwnYjjukdZh
+4c3YFkkevPTmjTiV2m28vbl8V8mP3gjD3v8Tbjw0CbHGmQGNBF3zoc8BDADEOhWcVTKIFUEx+NaA
+VEVwMk7z1F+61CBPjxLckA0izRP67AmqQ1ULulSF0mxI6xXC1tc3mmyKkYYJg8pIVx+gwIZlBgkH
+FvzBFYIckuiALeYZstIi+3XzmO/bKgSWpsj1eD3qLjlao5hwz4cz9F6vco0Z+KXJc9l8EyHSjuzx
+yDmiGMDA29kZq1WJmUag2Ft6F67/RnFwpiYTVVwK9jrJUT3hqoBaoSobJNCFFM/atvDYgwjgmBhY
+Km936bkm0tTqGOHIxnHqFu+qQ5e60UE2cxASw5j/CIW8h+nm/BdW6MokIYr50b47KvIrDWACwPnq
+tsj3kInmHByTJ+pstDFxdoQlbELjehusPEmhhUKmbsL36MyT/q6CuitiBHOJpZi1s2w/0FTnAHhV
+xPLhxjd+E0DmPgrNJSdYrJtDo7nejUM46yMyLzB4gQQAt6HpSanva4U7UbJLZOPDunO4+svVFyOH
+9SDJwbqkr3kXDICCIgjLVJMotTkKxeZcQd8RMC0AEQEAAbQXVGVzdCBLZXkgPHRlc3RAZXhhbXBs
+ZT6JAdQEEwEKAD4WIQTU7y2+6XtyA9QVrHVH+cEvgOk5jQUCXfOhzwIbAwUJA8JnAAULCQgHAwUV
+CgkICwUWAgMBAAIeAQIXgAAKCRBH+cEvgOk5jSroC/9RAhS2wB4srbjtBYcQIyx0TtB3oQcztSDI
+gPcod7dUpLlsARJcX710SDCslTZxmBFuZEsXnNMy9Tld5Y9CuwWObNfGAWNWK+GE+GDaUJEVDCHp
+gcQm1WLeQ1I3bcl5sQ0Lg9uI6JUX6rFSdjvnfsx1JohR5Nd0YJIVfnxnR3Oz+NAT1BwwDzxGaO97
+Gir7nb0/ZSxvYiN24R2bArIt9hPvojUcY02FSSNXx09xNxAe+XDPFyYbj28OLSeN4LR2EfDnKVxi
+Qpiy+Feg96vOukmT9XojT0JNGvTypgUjMz/aRcGG+aXx/ubvc7dJ6uXcldR+u8rgn4AKZa7QRchW
+Sfy9NM4YJGO2my5TtIc76ippsS6XymJ8dDw8NFjr2J2Nc5/XY/n8ppC2CJaPs2vkiCxDxBlKk/+E
+0w4Zt9QBCjk1KIVjWDTKn7X7MnYAZ+28D4sXe2MSR8oXcMK1po61B3x6N+JfgV6Po1fTosTnkGYH
+xmiRzORFqAMtg6ydLq/AFEi5AY0EXfOhzwEMALbGPWBHhYcKdotMKKX05IQm4WRHcMfa413pdPh8
+ZZYfRUP/unEi+Gaygu6wnERPo69czqBXn9jiX4mNQ2timsBWcXSCYG79wfReAem0lTdti48bjoz1
+nsjS4y0hJ2eOaH1w2FUa7mkGL10dhjs15asrVw2z7klQCV/ZeJMmWlts6+nTL2qFA5az13Apg2d3
+AqFgeKHLAACgU+QDG/2m8TiyeKslnZPRa0ASnE9S/3R9cgwnCtIcN330dcmGbiqkLE3ABfxSHpn+
+Ztiggdy6i4drqeSKp2wVtUKK5nhLg+sBvfXRZnrm80mIYI/7SQiF8V4oSycNierr9krQ2yGTRWik
+pOyWXHW/AadEH3MOhQHI414sFHYtMOHRjC1A99v7cK3weTZxom1G9W37zTJozdzkRB3IPavDKQf7
+Xm8FEPmceK/Gx4CZwKEL20b8T3XTYOrdDqyPaIhxT5ACwH2UDD24Va2PRiqRhBPIyGBpNV8twtHu
+7sUVEpWVVxO29GX1uQARAQABiQG8BBgBCgAmFiEE1O8tvul7cgPUFax1R/nBL4DpOY0FAl3zoc8C
+GwwFCQPCZwAACgkQR/nBL4DpOY2Uwgv/SoBpYtV7nTYCByGl3h6a3iKSrntyUfaGYIgGXlTBJ8kO
+o85MxD3VxxudY2414Sdd3Pg0lpYgSgmmHo3Wouv2ZLU7Hrrn3VwQccdCCqbiO01P8Y/byCawE2GZ
+QGKkk6f6AMzlk9hM2mhmdmz+6gFU0ziYCTMM+mIsza8KI0PIeqU+vkN4gxlwkEmaUBsPukzpnQmd
+zMoSD/njC7PO+nnmoN1hY7onOxRUnuqgEKBYjk4GL7Jw4rfBR8rSvyANGUeEkDlDoHa0Mg3MRF1b
+a97Q4LQ2jZNrOUB2hj2zlPk4ZsH0zukcKUB45O1VgCSOlcPC7247QDZQl1xlNhMOk+2H9XumW9Gf
+dgaJJbcXJg5jAfsQ31pqw3KrFXzGJvn2EM7oov6Lq0Vazayl6Xx0260+iOTQAFDKB7kWbpbJGduW
+0e3yEHiNUEZnIdcuDuLD8Cm0EC4EW5RtExt70DTDeo/S1K4dsl1/KXwNl5P5L/e1cLDLUm2iLu9x
+qipSuMIYrosA
diff --git a/tests/data/test-signed-usable-repo/seckey.asc b/tests/data/test-signed-usable-repo/seckey.asc
new file mode 100644
index 0000000..bcbf153
--- /dev/null
+++ b/tests/data/test-signed-usable-repo/seckey.asc
@@ -0,0 +1,158 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+
+lQVXBFzn06EBDADLLuONxlOlbDVZjkYPY6dJw16v5mSIL7r7BQ42ssUtO2V+B8bj
+TUCp3zRttadbtWigfz/Pqz5u6XLz+NPn3Nby6wMVrpfjxgKqjGF4kQ3Wi4ThHlsv
+gL12KoIOOxhmIJ3E8uLklza8lkYVPtzP1bgRjRx1QKLvdVAIy6iWVfQ9Xa8OtVBs
+7XZArSZ57mR37deaMOtvBdk9SOPQ939BimmNJ9IuLSlzsaqTVtxYcT/F85U/EWSF
+a6s6BvoDwbOZfGTxjsSeADMgh7DuvcYhYB+1HtJAjUNurnrq92Ymx/i5k4lULJ0C
+8T2P7jqc437q1kAMoxhr8VwmtrfwDYTGiRHR0x5LA0wekP1HPHHJfmemQcCm2Stj
+nMDEX16xuQsfwvkzbJvjULh1USR9Z7SPfWGcx28cUv71+34Us1YLUAvaaobjhX+z
+pcI1mn+oljxu56uuW6ZRsyHvbWFdTTKB8TWggkmMnHL8EowlBtvRQItgJllWfCs1
+6Ga4UbR/7Qia6BMAEQEAAQAL9iC9Eg0zwa0BI9CkDCyh0zMxtwC39ANKrQXevXad
+UrZkwp4qQAA4u/k0qyV1pqsEgkCpZGmzPE1INn+PP0I3F8ANB2/Jqb24rvRaW5e1
+SZTiseyjul3ucx96VKJGrxirMm/c3Rtx8KoGH0iJcmEoVyC6SmIOGBBphY+GZWRp
+tL4feuQ77yyj9anDz7n1q4/BUalvMgI02+mGNM8pnyqes4W7CT6Msh/Tvfw3MebG
+FMkFKDu5VikTRX8oTrRWfskMuttAqI4jASPZv8uRXMf8FOopDD6Q5B9tK84kd3DD
+dQJiqxXReiINViXj3HICbwAZYDxf4KNen4jjdPLaShjy/26XqqsD483um/r/uQNK
+xDrAgWhWssxh0rf1UCfw8IpZ4NQ6MIqsMkR59SrbwTXvNUXac6ngNB6zV0YTTrio
+0k+++kOLA7Uz6IbVAzz1gVtdSecMo3CpcJpk3fvJEWLWU/+3b+wul/WaUW8hCNuP
+DSJjzGpQeQadWY/3wubhWkfxBgDaohrURKeQ5Oi3PnPJz9ua3dg8iq9ThDD2vIzs
+C7VUb6qYkzfBK9BLe6Xpnii1bDp+eOn5FPnadyVO7BNNa7kzxWBsDgOfDBV9Xsbm
+621l+F7sxNcRt+eO+9Uk9sJv+sOOPVd8VhrkLZBgFTu4IBtvArmujsl+VVxScoby
+VV+fJ7lVajSTsx2COx4OQExtfc0/lXiOEvhy2F3b216BWgS02ryjxNy1QXfITg1T
+sT36GYclxYd5xyzyBl9iGhBa/sMGAO3oy4OdGrveEYmc/sppTLdyKMspOm29200V
+POhx4GwbswIWF4nMAvIc++nzGiZ0GucuUaJHAO63xqyWvPSFSTz90rAc8ZhOPSjV
+jBTvZo4P6vUNFHX26lpKXaOtwkjMXA0D0Ck16Z7qdN7n8sPM/68l1CHoBdSuw1SO
+0oBypi3tL8lDfKraDUcLK9wWb/FawbKYsrMl5RpyDwS/XCVYRUtUqSFFS80EDQGD
+PHD6vLHKYaakT5kbejnSQc+O0i58cQYAo4OEASZrxV/a8Kl0afoAntRqu2BZg1tP
++j51HYGykZI/erKcq05as0o/vVe3VPNI/hskgmEVFggKiTYAs4OGGfNhOvP2j/Uv
+jyzPNmEMEGemPoEP5OmTCfrkDOJi0Y5xh83EOyB9H00GHNsxf66gTwOcvjHV2ze9
+Ihkwbll692rfYqiK7pKfP/VayBFsxmnNFNKMTcbP06W+ozjkIaUneqA3B+k8Uu0t
+U1Ut2to0Y9/khw1CAYRxuwJ/aIlFPTqd2se0I3Rlc3RAZXhhbXBsZS5jb20gPHRl
+c3RAZXhhbXBsZS5jb20+iQHOBBMBCgA4AhsDBQsJCAcDBRUKCQgLBRYCAwEAAh4B
+AheAFiEEJIBsPhVxGFtaHobENN7p9ZyTYfkFAl33pUMACgkQNN7p9ZyTYfmLCQv9
+G92N3ehLMtTvK99BAXL+lyrBxvG0ZuIxhZuW3xhz6DXn4CUrVraE0hbWOkCm3UyR
+ce1HKSrhDyBRGgcO9ETFKTtzoWI5hU3r9dw0EMnpYbs8w8e/isaqtRYqi9eMRZ01
+S6eZFXxFPaWeaWbVsy7yWMLTYUywrYfvYuo2ls1TsE7UB8RBGrthQuTMJPysEzph
+J/QZ7d1j43aBs8orXL4Do4GudE9Zptgo4/DuaQ0hvhcLeWVWxwbxF8cfkSO0KhK2
+g/UAox2rmpNPjkZwgXBc6HrQRwgWaQO7f0a/RXRprfRuc0hVFFOAYK5v5CciC/0U
+FpXrsZ8tfvz41GPx8KWulwSucs5EjbjvusQiX2mXpBts9xjS+SmjuHNDudBRY/6c
+VCjGY/ncnPWkmL0CNnXHMb0i6T0nsxjFwyzHjckeUfideS3dzaRcKf8C2c6AaU/j
+gEdgSlvhPnqHteeOZ2leETNX7jeeaAUzemySy4oLCGrpu7d6mckazGRpbWSkVKiO
+nQVYBFzn06EBDACkIXqZx8UhNGd/R9gClIPH1Lqr7O6gnZvH6qKD1/qagbftN9AA
+/HtnbIF7q6jCvXDF0177H1nefNGcDKMMA3OkLF3bVNb+B61CBN8B/+6vAhPavYIl
+xF5TpCXLxy4S4nMwF82dHEZqLYDSAITChjXzCgi96mQTlKYZY7mrjTpJXBy9AHKV
+OjZQ685DVWluIp5o5GwH0EvLvrxDMdrCnAgRCfFDhHGBJeAmknR8BhW6JJR7UQ1R
+yaQqnYHRJF8pa4j8tVyHf440YRw0OTGERT4PnAzaZhgJ+Iq4/JxpQ4UddOqJXkBH
+B8s7LqATFUQQuRLm0A41u29EuX1dmV37NIBjnv1w8vmDEf9l8DQTQJSPnmWgS8RK
+D3SUj4iK9VQr2FcZHvaCguYBXdYENDtezmNU423rl8cekWzmPEZdeBP2OWFEYcgG
+POJ0O4m21ErbDkf2MS/trfJqzSNZY1o/ip6dxHVV0qtW368wfiIgzt+c4sN8wCaX
+YBvYS4h1rASAi2cAEQEAAQAL/AhVWNO5BGXIst6QB8QtxTkesHGtQHpwNioi3CiE
+jUlN/8gwFsQODbf1FufwEcv9cV3h+wcWEuqMfNoG/DpObI8v334U4yuXuTDKbYY8
+9+Hz4Y0wJQ0E2OM3SOH9VXYJAF83Pi3Vcy/N6qX+976msNOLtWDrJzSlTf+pBBLV
+Q1nZLu5buPWhtINMTbc2fXllkZRy0Jde+JI6N3XT8K8D3Bb9Yb4TWe38PdLHidmI
+N48xb0aJmXsHGWo+gApd5eUE/CU5L9mfvKkLaQAigOIyWzv92Tt20t+33Oxk4UO0
+RZFRBq3jju4MUngH3bU1R3v1ZYNuw1owdzZYZplXOIWuBWbmvYSQihM2drbfOkbg
+dVghJF1K5xuWMiyQBsEWo9SxA4zzkfE+3lZzdbHPHcZxSd6oPDkdQDZgC0mqi3jf
+yi2vEiUYbEOzGryb/QP4NUcX3rX71kr5yQZE7gT5GOI7TjwAsGAr8jCkQcYBPrP8
+HLkDHeNAxHE4qR5CipinYoxrFQYAwGsqg/WR6xEAAW6PJ0Cr1Jz2ifrm7ZaEFvRm
+OJx6fN4aQyqDM0LG3sAArv6fHhAUQ6fkfu9URLsSiXzf8H2XXd1trKhi/Auq3qnA
+nLBYgEv57DpOrGV1ZX6GXganBl586JqXqiee5W3ziBMPFLVC5jnd0D6Ctmoa6YHy
+Sdsn2ne+Ax+YQEczfe5E83rWUvLpf4LZkBOgEP5InU5S1gC6DIbzbfVMGslbRoQc
+AgMkP7aY4QnUuZ0IIGg5bjUiJXOtBgDaXWxiH5n7EKK3FJEnLwGHMZ2x7dbdAk7u
+hS4HTB9Q4KvQUekw6I89SUp85p9QOMmke2JhTGbLjd3AFWzHFesRNVq8P05rmDQw
+prkoaw7keG1JG8a+h72ndCciPx4jS5iRIz+pjm7SP87/7uPGJn1CEhZ8GJQZ9+Cl
+dViLiK83eN7nqbaDzlYWDvr8avBVtA+UEPwY5OjoXxWskiK8uphXAbM7Ro1jhTJ3
+OivgpZhFrmyqqf7HGMtn5u+Jywj9/eMGAI5JjOyJQ5bdzfPeKECusKqwS+0dkkup
+BQonT49jjmW1G2e+RY7l0xTG+DbUu4CRKGhMSgP11yjvT3kIW2A+AIEMfiitToET
+4XCjyVoPlCN7vNneLbVPzpSBfvRwv7x3g96DLcLkssbDU2HDldwWDRhu+7e8gQYK
+BC+13u3Cd14tD+d3VRCXMB9udnNNfZ9sHDb0YjZBbWsBhQgKrg5uscDw3XfOOZPv
+Jj7t6NcsNVwaQQwPvutcCPZUsNNbSXWmctXViQG2BBgBCgAgAhsMFiEEJIBsPhVx
+GFtaHobENN7p9ZyTYfkFAl33pU8ACgkQNN7p9ZyTYflBoAv/de2tzgcWzksE4OMN
+aQggXbYtUxOmgLRy8Hrd+oAYuz9xozdsGFJoMdJlJ6i+XAGaGVUd1313isdkuS5a
+C47pEpuLG1V9qMQzAbY0oHyB5h+lZZVnLz1y3TZZDgvLY57xrYP6hTrwKkxxQ5AT
+kMhcxRBTRidxs9kJkx8jeeH+kYXeA3dS6Vk1IBiiDxJ/jb7qJfU+yb+hAbK3iBKh
+/FNYQ2Qd/EeYq37PeIVdegMliKslbRX7fBs83P5ssy1Hci3T4l5ZKRppIRRdniD4
+cislFzAxCQefcVrF1Su2+cg+5tvYmSIH2OuY/rxJX6lpIPcnzI0hwTQNAQIEOmtd
+UrOvJVRoLPCioi5G7pe1d5gssnyqrpILS+mFZvT+bSXFlfeMDC/eh6gz1/WIO9EN
+qZ7/Tf23Fvt3shjg4EJ+IkwvjUZ+rTs0FPQ1xznjD82FPcSM6HX/jNpXnfwnYjju
+kdZh4c3YFkkevPTmjTiV2m28vbl8V8mP3gjD3v8Tbjw0CbHGlQVYBF3zoc8BDADE
+OhWcVTKIFUEx+NaAVEVwMk7z1F+61CBPjxLckA0izRP67AmqQ1ULulSF0mxI6xXC
+1tc3mmyKkYYJg8pIVx+gwIZlBgkHFvzBFYIckuiALeYZstIi+3XzmO/bKgSWpsj1
+eD3qLjlao5hwz4cz9F6vco0Z+KXJc9l8EyHSjuzxyDmiGMDA29kZq1WJmUag2Ft6
+F67/RnFwpiYTVVwK9jrJUT3hqoBaoSobJNCFFM/atvDYgwjgmBhYKm936bkm0tTq
+GOHIxnHqFu+qQ5e60UE2cxASw5j/CIW8h+nm/BdW6MokIYr50b47KvIrDWACwPnq
+tsj3kInmHByTJ+pstDFxdoQlbELjehusPEmhhUKmbsL36MyT/q6CuitiBHOJpZi1
+s2w/0FTnAHhVxPLhxjd+E0DmPgrNJSdYrJtDo7nejUM46yMyLzB4gQQAt6HpSanv
+a4U7UbJLZOPDunO4+svVFyOH9SDJwbqkr3kXDICCIgjLVJMotTkKxeZcQd8RMC0A
+EQEAAQAL/iwdOM2IE8+nI5yF6kc4atHx5XEInirk1Iy+SAnA8ssPmr3PAc8+yuhT
+j/vz1fdArog6f3DXLS6rz5vk/n1r5MbhcXVVuYLYBqOr36/n0RA8AV5mprpJmPdW
+Oxok5Jovzb7ttNGoaal4XOWDqkwiVIUR9inQDglvm4W60WBCVH94uYg5E2BoLHMK
+YzUHeergKRSWLXfjUM5389hl2Mb4Gzg2JPjOOYPmdo5apOw+RQpRFW0/bCf92X88
+rwmgyEizndhND6qREOQ/yt6TaY6jW5NMz0rXZuzzh8AN7QJ8Vnf+vl6yvhml/6Fv
+PI/rjtjMIM6F4+eyQxyEBt70KOxa5zKbBkndr8vU9vBIF5+c62IwtD6jlFekUvU9
+G3RUZN4BecGp61FSovWYy7+Pct9s1NvI+704nQRi9j7HbYzXsY0UF4mjVUsY9nOW
+0hYp5Z97Wpo8NZHS7uDFN6GG7AMWug7vwQiKawK70JtvfwPiNAwb7QEDlQY1cxlS
+tGxptevCmwYA1arblASyI8C3PbQWfryuUfK/+xtknKe7TDapOL+wfnJBUA1WcKpO
+jXDSPP+UShkIAueTCz3gNiQGN4zmbAL80QzHI605laceIYSC7hESNkT8wrjv3Mpt
+J7Sle2bJfGHcV5J88G8kszt6uw0T/Gm84wjGP3jlWPJsklZAsoRpRcLi3zyRUYgY
+6rsrHIgk0+ax4uUktqGterh8jpFn2IR4lwoeIBXwLlfnIVB/TQ85ahvlcFqnZAiU
+5TfIX7Dx/yffBgDrGqYrkeXogJRZyk84BBkmOb2+6LKF+OicDowpJuaIB1xL3xeb
+j8DL9C0HOFN4CZe7wDDditCPWCzTE/n1oIqrVpnm27hi9ylFeft5oL1eK2HyJ+VY
+7CeLGRxEtMUkSij+/tYB4Kqdx+dZWUNRrzcrd75iwbyRRrV/ROCLLPt/CaoElGCu
+LnZwlg/ZlAAI/Vs3oLZ5Q2JuGfBvH6eB/zJzxSPF1Hog2b5l0ogPhZR6cn0rccaN
+yToeEdyQ94EimXMF/iszgPjfN+ZM7W926BXiCQfKsEu5NRpZgH3IYybBmqAkofgB
+RqGisL+5WlOCfroDo34qaexq2AsmYQdypAgwFL2l/uNjsIfWu9+9Q5Aai2SBtO1A
+oPTQGPzMQtUWTIFsk3+xpoocj75jzpOXlL14tpHl2yNpy9wittLFUXcFrAst1/AQ
+/zNq9BASyZEYwM35VhXxy+//ZK6LgwI3MiSspQSB5K/eUNIxt+hVfV34iMlPtNQT
+JaaeMU09NC3/pcxwQu1ItBdUZXN0IEtleSA8dGVzdEBleGFtcGxlPokB1AQTAQoA
+PhYhBNTvLb7pe3ID1BWsdUf5wS+A6TmNBQJd86HPAhsDBQkDwmcABQsJCAcDBRUK
+CQgLBRYCAwEAAh4BAheAAAoJEEf5wS+A6TmNKugL/1ECFLbAHiytuO0FhxAjLHRO
+0HehBzO1IMiA9yh3t1SkuWwBElxfvXRIMKyVNnGYEW5kSxec0zL1OV3lj0K7BY5s
+18YBY1Yr4YT4YNpQkRUMIemBxCbVYt5DUjdtyXmxDQuD24jolRfqsVJ2O+d+zHUm
+iFHk13RgkhV+fGdHc7P40BPUHDAPPEZo73saKvudvT9lLG9iI3bhHZsCsi32E++i
+NRxjTYVJI1fHT3E3EB75cM8XJhuPbw4tJ43gtHYR8OcpXGJCmLL4V6D3q866SZP1
+eiNPQk0a9PKmBSMzP9pFwYb5pfH+5u9zt0nq5dyV1H67yuCfgAplrtBFyFZJ/L00
+zhgkY7abLlO0hzvqKmmxLpfKYnx0PDw0WOvYnY1zn9dj+fymkLYIlo+za+SILEPE
+GUqT/4TTDhm31AEKOTUohWNYNMqftfsydgBn7bwPixd7YxJHyhdwwrWmjrUHfHo3
+4l+BXo+jV9OixOeQZgfGaJHM5EWoAy2DrJ0ur8AUSJ0FWARd86HPAQwAtsY9YEeF
+hwp2i0wopfTkhCbhZEdwx9rjXel0+Hxllh9FQ/+6cSL4ZrKC7rCcRE+jr1zOoFef
+2OJfiY1Da2KawFZxdIJgbv3B9F4B6bSVN22LjxuOjPWeyNLjLSEnZ45ofXDYVRru
+aQYvXR2GOzXlqytXDbPuSVAJX9l4kyZaW2zr6dMvaoUDlrPXcCmDZ3cCoWB4ocsA
+AKBT5AMb/abxOLJ4qyWdk9FrQBKcT1L/dH1yDCcK0hw3ffR1yYZuKqQsTcAF/FIe
+mf5m2KCB3LqLh2up5IqnbBW1QormeEuD6wG99dFmeubzSYhgj/tJCIXxXihLJw2J
+6uv2StDbIZNFaKSk7JZcdb8Bp0Qfcw6FAcjjXiwUdi0w4dGMLUD32/twrfB5NnGi
+bUb1bfvNMmjN3OREHcg9q8MpB/tebwUQ+Zx4r8bHgJnAoQvbRvxPddNg6t0OrI9o
+iHFPkALAfZQMPbhVrY9GKpGEE8jIYGk1Xy3C0e7uxRUSlZVXE7b0ZfW5ABEBAAEA
+C/4soEuFEgFyvuXBzicQmjIfaCTZKK5LRdEE8Yb7Utg05s6xMyPREuJGpOheIiYN
+ccp7+zOCJ9LiECeWfLTM5+bz9kc+VMT55KByK2/ZIZvbTDZqiyZrmV8bFo6cSr+F
+w9oUYrSXVvuGDhoLaLWJCHhaqjrXoCqaoN2hFwafGxqtvvL9BPDLV83QAnokKyan
+4QF16Imbq2aFQKArCG1Rqey01LKsywLmABhpLQIYRiIUTbrGZ9P3CCeua71EpruI
+UswKx0Fo2KUvggZ0CyjF0YSL6nr1iBStlrYbUxjmuUmwlxSq/t/5A7zZll0vMmya
+wIyyNqeV8cPz5MTtQN5xLPWqry+KP688IhpVB8F9/7vzpTImyFyQTQK84T5FjHP7
+Z4XB61doY7Coedi2EQ0Nql+93l9rvuaweNBGA0M09RjqBfz8zv0yKbomcSUWXkSS
+vZYIVQMjA4UjnPuWwbST5UavopQ4UyF4kXo5XTvsGgIUkORtbst+ze/0xHq30Pog
+4nkGANK+jmIeMtkUGlz1zYleS/TVsxRakxB0Zxq2n/QL7Qwv2FUOjv9Ts1sfdbhz
+UXF5RPSAQGPfFLyuUJrV1VWx+pFAnIm99wN6RdXxbIhusGXBzTeZJ0yfcsr+du+b
+XoeJ0zcffjyc4dBMArwDsEado3AfwuIFCs3eCKEOD0CQkhT9BljSUxjKFw2nzveS
+57muKXOfCf3hOAPkTIKYYv9it75SugoAg/PUy5MhqnbIDb7/YDrOqHm0l95nQAN8
+yL5+nQYA3gYQUoliZ2ybb0ALmxXAyyXnlRzanduPinb16ThLn5bqFRPXt2oKLdtB
+GMuWhjmAimZU14akozv6bl2wtSnriTdoy0vA8+QUS5UJS9wOwgmqYItWa/6IBiNu
+2gtrwJ4atZW5hbhrFSMNo1elZpt1rY07vfgZSYZfHGfIRUWlaFL1J5d6tuiz+uV5
+uUawfOy80pXBKxMCdsYv9NQ+9Uu+BnGqR3DQDq2CbBJHOS7j/akuhJy8bwvuXYyq
+W1piZzrNBgDdRVVAp7mco51ZdyHH2hdFyL2Qpv9hLketkS0mkBVU9ETObZ6kuWbv
+MQc5ob7i8vfK+0Pmg1L4H6kLp+DAiNoM+Zb+xxuQdkM3QB3MUzc//tOGJS8F92S3
+FOw96gg4rxUhOM6sDjxw+rb1SxlJkmvKpLwPqd4mu+tWTMd6MHomj9sdDLaf9Ast
+wWK6uZ46+5DaHetIACDleI6HTX/e5mHUOPnY19rdBNooZOpDPZbh82YIN5RI47zq
+Rf4hmWoy4Pnk1okBvAQYAQoAJhYhBNTvLb7pe3ID1BWsdUf5wS+A6TmNBQJd86HP
+AhsMBQkDwmcAAAoJEEf5wS+A6TmNlMIL/0qAaWLVe502Agchpd4emt4ikq57clH2
+hmCIBl5UwSfJDqPOTMQ91ccbnWNuNeEnXdz4NJaWIEoJph6N1qLr9mS1Ox66591c
+EHHHQgqm4jtNT/GP28gmsBNhmUBipJOn+gDM5ZPYTNpoZnZs/uoBVNM4mAkzDPpi
+LM2vCiNDyHqlPr5DeIMZcJBJmlAbD7pM6Z0JnczKEg/54wuzzvp55qDdYWO6JzsU
+VJ7qoBCgWI5OBi+ycOK3wUfK0r8gDRlHhJA5Q6B2tDINzERdW2ve0OC0No2TazlA
+doY9s5T5OGbB9M7pHClAeOTtVYAkjpXDwu9uO0A2UJdcZTYTDpPth/V7plvRn3YG
+iSW3FyYOYwH7EN9aasNyqxV8xib59hDO6KL+i6tFWs2spel8dNutPojk0ABQyge5
+Fm6WyRnbltHt8hB4jVBGZyHXLg7iw/AptBAuBFuUbRMbe9A0w3qP0tSuHbJdfyl8
+DZeT+S/3tXCwy1Jtoi7vcaoqUrjCGK6LAA==
+=mcY/
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/data/test-signed-usable-repo/signed/Packages b/tests/data/test-signed-usable-repo/signed/Packages
new file mode 100644
index 0000000..3ca29c9
--- /dev/null
+++ b/tests/data/test-signed-usable-repo/signed/Packages
@@ -0,0 +1,26 @@
+Package: signed-not-usable
+Architecture: all
+Version: 1.0
+Multi-Arch: foreign
+Priority: optional
+Section: misc
+Maintainer: Julian Andres Klode <juliank@ubuntu.com>
+Installed-Size: 9
+Filename: ./signed-not-usable_1.0_all.deb
+Size: 35
+MD5sum: f3034b91e355ba6046ff535ed044dcb5
+Description: Dummy package
+
+Package: signed-usable
+Architecture: all
+Version: 1.0
+Multi-Arch: foreign
+Priority: optional
+Section: misc
+Maintainer: Julian Andres Klode <juliank@ubuntu.com>
+Installed-Size: 9
+Filename: ./signed-usable_1.0_all.deb
+Size: 31
+MD5sum: 2d5166c110423c2d7c016642af4bd2eb
+SHA256: 20edddf30a1bedf669f19caffa347299239b2a700ff428e33abc75e902f1d737
+Description: Dummy package
diff --git a/tests/data/test-signed-usable-repo/signed/Release b/tests/data/test-signed-usable-repo/signed/Release
new file mode 100644
index 0000000..135ce78
--- /dev/null
+++ b/tests/data/test-signed-usable-repo/signed/Release
@@ -0,0 +1,17 @@
+Date: Fri, 13 Dec 2019 16:11:05 +0000
+MD5Sum:
+ 21b1df48cfe01053dd2245763423cefb 668 Packages
+ 6715b0d77e7ea43fb252c78f1f826096 38 Release
+ 30432690119177a7f0c822c12f96e665 579 Sources
+SHA1:
+ 910742c214560ce8ecdcb89c86fb1c0afa5a5373 668 Packages
+ 4a252d8c4ebc30d7330938a7dee06288877c4e3f 38 Release
+ 3147ec4b880bbb2cfa2a3f903b86d1dd2249488d 579 Sources
+SHA256:
+ 445d75ee95443b89849b17f73ae434423d01c603f03c894a7be7851d36a5365d 668 Packages
+ c0ac431b6ea236c4d12e904b556bbb1f8d0abc733041cab4d65bfd3fd9704183 38 Release
+ 99140dde6468a8e073d8830faaf90e40c374957b98c1be446308dc8296ce5934 579 Sources
+SHA512:
+ fdc2f7552c06ea197c8c40a44602218703a08d1b6a86f9319cc13a56ea8e7f7103c10aea6ee221b0bc88432ebb2651e3d2e5a93a3900fec5630db2e41684c57b 668 Packages
+ 5800d40647c79881b15119bbc576b12926151a2df37b96e18abc5fb04986663fa01867a83a1919225365b590a15e22032d12175eaf76336f167688c5a817ca13 38 Release
+ d0dd2a03687df03e4728219b9b149d514f8a734fcdeee8e45cb31229fc0f915eab634a50f934a60df42682e6dfbc65b962109bda616af642d6ee4cf821a877a1 579 Sources
diff --git a/tests/data/test-signed-usable-repo/signed/Release.gpg b/tests/data/test-signed-usable-repo/signed/Release.gpg
new file mode 100644
index 0000000..6b853bf
--- /dev/null
+++ b/tests/data/test-signed-usable-repo/signed/Release.gpg
@@ -0,0 +1,14 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQHFBAABCgAvFiEEJIBsPhVxGFtaHobENN7p9ZyTYfkFAl3zuBkRHHRlc3RAZXhh
+bXBsZS5jb20ACgkQNN7p9ZyTYfkkrwv9HBgaZjSf3Bib9FH2alGZkBHKRcE2gWKf
+d4PBXKLGgUutCy2g1Dn+FyBYB4OCf3H7ZsD6JFqrYSmLyGHAo+5QTMaPcRlVGoN8
+GL/fxJOEkRJruyC3k36toZTgXI/DGvSv1882syHTG0jOm8to95wiaQKDysTKOOTp
+p1HJbX5DX+Wf2rXA/CL8KdH7rHzkIdhjdL4hucDw+JvNSywPEn0RSfvjtUS04d7G
+Rw8H2PXyEnreO6OmMdwEmtImouIVxNZDFEEWUhdwujMnDtxM16uIIRLXa1sWQAzZ
+M7RHNIhQHP1EvPuQRnKknacKUwchpg/IklxxruaRtjELSUMF5UOXJdnJFb3t6+pT
+HBaW/c5piLfMsIV5U/bjQA76Ta4NccH5hah8x6+SjEZiP5RxSfQ9wpblYQeOmaUB
+xi0tF6Ukqp5zfPi1RblziWZbN2/ty5zXpPOYbDT2geWo+8bVEhG6HwtHvpzuVymR
+qtjOlCujLlkNZKG5jBHoOhuQjNPm+8RY
+=wnyK
+-----END PGP SIGNATURE-----
diff --git a/tests/data/test-signed-usable-repo/signed/Sources b/tests/data/test-signed-usable-repo/signed/Sources
new file mode 100644
index 0000000..52a8ee0
--- /dev/null
+++ b/tests/data/test-signed-usable-repo/signed/Sources
@@ -0,0 +1,21 @@
+Package: signed-not-usable
+Format: 3.0 (native)
+Binary: signed-not-usable
+Architecture: any all
+Version: 1.0
+Package-List:
+ signed-not-usable deb admin important arch=all
+Files:
+ f2ae6d320641e8e241efcba02b5540fb 323 signed-not-usable_1.0.dsc
+
+Package: signed-usable
+Format: 3.0 (native)
+Binary: signed-usable
+Architecture: any all
+Version: 1.0
+Package-List:
+ signed-usable deb admin important arch=all
+Files:
+ 491c58f65f493e838880a6ff30064c57 311 signed-usable_1.0.dsc
+Checksums-Sha256:
+ 7a277156805101ce917dbb8d443d7087cc0ad333d25304f284976dba36339487 311 signed-usable_1.0.dsc
diff --git a/tests/data/test-signed-usable-repo/signed/signed-not-usable_1.0.dsc b/tests/data/test-signed-usable-repo/signed/signed-not-usable_1.0.dsc
new file mode 100644
index 0000000..2ebb766
--- /dev/null
+++ b/tests/data/test-signed-usable-repo/signed/signed-not-usable_1.0.dsc
@@ -0,0 +1,11 @@
+Format: 3.0 (native)
+Source: signed-not-usable
+Binary: signed-not-usable
+Architecture: any all
+Version: 1.0
+Package-List:
+ signed-not-usable deb admin important arch=all
+Checksums-Sha256:
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 test.tar.xz
+Files:
+ d41d8cd98f00b204e9800998ecf8427e 0 test.tar.xz
diff --git a/tests/data/test-signed-usable-repo/signed/signed-not-usable_1.0_all.deb b/tests/data/test-signed-usable-repo/signed/signed-not-usable_1.0_all.deb
new file mode 100644
index 0000000..e098ca5
--- /dev/null
+++ b/tests/data/test-signed-usable-repo/signed/signed-not-usable_1.0_all.deb
@@ -0,0 +1 @@
+i am signed-not-usable_1.0_all.deb
diff --git a/tests/data/test-signed-usable-repo/signed/signed-usable_1.0.dsc b/tests/data/test-signed-usable-repo/signed/signed-usable_1.0.dsc
new file mode 100644
index 0000000..04b4f64
--- /dev/null
+++ b/tests/data/test-signed-usable-repo/signed/signed-usable_1.0.dsc
@@ -0,0 +1,11 @@
+Format: 3.0 (native)
+Source: signed-usable
+Binary: signed-usable
+Architecture: any all
+Version: 1.0
+Package-List:
+ signed-usable deb admin important arch=all
+Checksums-Sha256:
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 test.tar.xz
+Files:
+ d41d8cd98f00b204e9800998ecf8427e 0 test.tar.xz
diff --git a/tests/data/test-signed-usable-repo/signed/signed-usable_1.0_all.deb b/tests/data/test-signed-usable-repo/signed/signed-usable_1.0_all.deb
new file mode 100644
index 0000000..cd58831
--- /dev/null
+++ b/tests/data/test-signed-usable-repo/signed/signed-usable_1.0_all.deb
@@ -0,0 +1 @@
+i am signed-usable_1.0_all.deb
diff --git a/tests/data/test-signed-usable-repo/unsigned/Packages b/tests/data/test-signed-usable-repo/unsigned/Packages
new file mode 100644
index 0000000..22f4fff
--- /dev/null
+++ b/tests/data/test-signed-usable-repo/unsigned/Packages
@@ -0,0 +1,26 @@
+Package: unsigned-unusable
+Architecture: all
+Version: 1.0
+Multi-Arch: foreign
+Priority: optional
+Section: misc
+Maintainer: Julian Andres Klode <juliank@ubuntu.com>
+Installed-Size: 9
+Filename: ./unsigned-unusable_1.0_all.deb
+Size: 35
+MD5sum: 368e155b22e873eb71ae43b80379c0ea
+Description: Dummy package
+
+Package: unsigned-usable
+Architecture: all
+Version: 1.0
+Multi-Arch: foreign
+Priority: optional
+Section: misc
+Maintainer: Julian Andres Klode <juliank@ubuntu.com>
+Installed-Size: 9
+Filename: ./unsigned-usable_1.0_all.deb
+Size: 33
+MD5sum: 0a0bb7636879ae8a38b679bc3d09b627
+SHA256: ddc71095223eb039cce782e813782b917502e0f3c99a1142ea2d92b34737a243
+Description: Dummy package
diff --git a/tests/data/test-signed-usable-repo/unsigned/Release b/tests/data/test-signed-usable-repo/unsigned/Release
new file mode 100644
index 0000000..18552a2
--- /dev/null
+++ b/tests/data/test-signed-usable-repo/unsigned/Release
@@ -0,0 +1,17 @@
+Date: Fri, 13 Dec 2019 16:04:58 +0000
+MD5Sum:
+ dd9db6eb770d950241fc5dfd1b94d4c5 672 Packages
+ 808b5c1ee28bdae1ffe98a8ee632a4ff 38 Release
+ bb3efd66e75fa995971ddf8d3bdcd6cb 592 Sources
+SHA1:
+ 4b83e0112704ce4aa20d5833dfad0617404cb48f 672 Packages
+ 9cba73573f2824f5691293802046a707d1493cdf 38 Release
+ 4e4a503ec704e11c963c042f44a3ad9da7f30b88 592 Sources
+SHA256:
+ e7a1760be467c66c570e3a5feddfb8d82a14cb4a201382353e4d9bf4c8fb530a 672 Packages
+ b7efc8e49608e74fefd10f93081843b66200cf9b3d12af7e7772138d8d9fd514 38 Release
+ f1bea3fd5e27e0a2b606ef23690a611b6a1b60baf42284d5469431dfae4c316a 592 Sources
+SHA512:
+ 4d951a837afed5be1aa89e594587b34f533408b28e4f3b0ffd2c69e5edf45873e24ace59126b12c8f83734ca5daa1d901f2f51170ac325b2787b3674e7226d93 672 Packages
+ 31d2d8013ee14aa414abf831819f2896f2d9c323fbfcfbc24bf7d602e1855a97ae049125397afd909e8a78aa0c016469731742f7dded416680fced49cce4b088 38 Release
+ e476cf4357f0f5ec00529dd96b782d9ed52e94db06020ad64ec976f4be6f3783151267fd9916857bedd1c3b693a338f53501d09200a0834c004da54f5acbfca0 592 Sources
diff --git a/tests/data/test-signed-usable-repo/unsigned/Sources b/tests/data/test-signed-usable-repo/unsigned/Sources
new file mode 100644
index 0000000..9eaf48b
--- /dev/null
+++ b/tests/data/test-signed-usable-repo/unsigned/Sources
@@ -0,0 +1,22 @@
+Package: unsigned-unusable
+Format: 3.0 (native)
+Binary: unsigned-unusable
+Architecture: any all
+Version: 1.0
+Package-List:
+ unsigned-unusable deb admin important arch=all
+Files:
+ c9c8d679a878ca08faca12baf5e2398d 323 unsigned-not-usable_1.0.dsc
+
+
+Package: unsigned-usable
+Format: 3.0 (native)
+Binary: unsigned-usable
+Architecture: any all
+Version: 1.0
+Package-List:
+ unsigned-usable deb admin important arch=all
+Files:
+ 864f4834dabbd30e6472902b000d7a76 317 unsigned-usable_1.0.dsc
+Checksums-Sha256:
+ eb6c1ebc468b4687bb6bffe25afd5ab1e1812beb9577fac7560396bcb7775939 317 unsigned-usable_1.0.dsc
diff --git a/tests/data/test-signed-usable-repo/unsigned/unsigned-not-usable_1.0.dsc b/tests/data/test-signed-usable-repo/unsigned/unsigned-not-usable_1.0.dsc
new file mode 100644
index 0000000..f8156c1
--- /dev/null
+++ b/tests/data/test-signed-usable-repo/unsigned/unsigned-not-usable_1.0.dsc
@@ -0,0 +1,11 @@
+Format: 3.0 (native)
+Source: unsigned-unusable
+Binary: unsigned-unusable
+Architecture: any all
+Version: 1.0
+Package-List:
+ unsigned-unusable deb admin important arch=all
+Checksums-Sha256:
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 test.tar.xz
+Files:
+ d41d8cd98f00b204e9800998ecf8427e 0 test.tar.xz
diff --git a/tests/data/test-signed-usable-repo/unsigned/unsigned-unusable_1.0_all.deb b/tests/data/test-signed-usable-repo/unsigned/unsigned-unusable_1.0_all.deb
new file mode 100644
index 0000000..7465ec1
--- /dev/null
+++ b/tests/data/test-signed-usable-repo/unsigned/unsigned-unusable_1.0_all.deb
@@ -0,0 +1 @@
+i am unsigned-unusable_1.0_all.deb
diff --git a/tests/data/test-signed-usable-repo/unsigned/unsigned-usable_1.0.dsc b/tests/data/test-signed-usable-repo/unsigned/unsigned-usable_1.0.dsc
new file mode 100644
index 0000000..a625bb6
--- /dev/null
+++ b/tests/data/test-signed-usable-repo/unsigned/unsigned-usable_1.0.dsc
@@ -0,0 +1,11 @@
+Format: 3.0 (native)
+Source: unsigned-usable
+Binary: unsigned-usable
+Architecture: any all
+Version: 1.0
+Package-List:
+ unsigned-usable deb admin important arch=all
+Checksums-Sha256:
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 test.tar.xz
+Files:
+ d41d8cd98f00b204e9800998ecf8427e 0 test.tar.xz
diff --git a/tests/data/test-signed-usable-repo/unsigned/unsigned-usable_1.0_all.deb b/tests/data/test-signed-usable-repo/unsigned/unsigned-usable_1.0_all.deb
new file mode 100644
index 0000000..2f748b0
--- /dev/null
+++ b/tests/data/test-signed-usable-repo/unsigned/unsigned-usable_1.0_all.deb
@@ -0,0 +1 @@
+i am unsigned-usable_1.0_all.deb
diff --git a/tests/data/test-source-repo/Sources b/tests/data/test-source-repo/Sources
new file mode 100644
index 0000000..4758871
--- /dev/null
+++ b/tests/data/test-source-repo/Sources
@@ -0,0 +1,25 @@
+Package: dh-autoreconf
+Format: 3.0 (native)
+Binary: dh-autoreconf
+Architecture: all
+Version: 16
+Maintainer: Julian Andres Klode <jak@debian.org>
+Standards-Version: 4.1.1
+Build-Depends: debhelper (>= 9)
+Vcs-Browser: https://anonscm.debian.org/git/collab-maint/dh-autoreconf.git
+Vcs-Git: https://anonscm.debian.org/git/collab-maint/dh-autoreconf.git
+Package-List:
+ dh-autoreconf deb devel optional arch=all
+Files:
+ 6576a28fe1918ce10bd31543ba545901 1578 dh-autoreconf_16.dsc
+ 302c8bf43db02412e3f2197fd0f2ee0f 7372 dh-autoreconf_16.tar.xz
+Checksums-Sha1:
+ c9bf7a920013021dad5fbd898dfd5a79c7a150f9 1578 dh-autoreconf_16.dsc
+ 58459600164398ad6807ddd877a6f814c799c62c 7372 dh-autoreconf_16.tar.xz
+Checksums-Sha256:
+ 1c1b2ab5f1ae5496bd50dbb3c30e9b7d181a06c8d02ee8d7e9c35ed6f2a69b5f 1578 dh-autoreconf_16.dsc
+ 5c6a6a362907327bec77a867ff3fd0eceba8015d1b881b48275aff7e4ce0f629 7372 dh-autoreconf_16.tar.xz
+Checksums-Sha512:
+ 4b1a3299f2a8b01b0c75db97fd16cb39919949c74d19ea6cf28e1bbd4891d3515b3e2b90b96a64df665cebf6d95409e704e670909ae91fcfe92409ee1339bffc 1578 dh-autoreconf_16.dsc
+ 10448dd179ec12bf4310a9a514110a85f56e51893aa36a97ac3a6f8d7ce99d099e62cfdb78e271e2d94431e8832da0f643de821b6643b80e3f0b0f5d682cf9a9 7372 dh-autoreconf_16.tar.xz
+
diff --git a/tests/data/test_debs/data-tar-broken.deb b/tests/data/test_debs/data-tar-broken.deb
new file mode 100644
index 0000000..4fd42e0
--- /dev/null
+++ b/tests/data/test_debs/data-tar-broken.deb
Binary files differ
diff --git a/tests/data/test_debs/data-tar-xz.deb b/tests/data/test_debs/data-tar-xz.deb
new file mode 100644
index 0000000..9dd4d67
--- /dev/null
+++ b/tests/data/test_debs/data-tar-xz.deb
Binary files differ
diff --git a/tests/data/test_debs/data-tar.deb b/tests/data/test_debs/data-tar.deb
new file mode 100644
index 0000000..d8e4a98
--- /dev/null
+++ b/tests/data/test_debs/data-tar.deb
Binary files differ
diff --git a/tests/data/test_debs/etc/apt/sources.list b/tests/data/test_debs/etc/apt/sources.list
new file mode 100644
index 0000000..3cc95c7
--- /dev/null
+++ b/tests/data/test_debs/etc/apt/sources.list
@@ -0,0 +1 @@
+deb http://archive.ubuntu.com/ubuntu maverick main
diff --git a/tests/data/test_debs/gdebi-test1.deb b/tests/data/test_debs/gdebi-test1.deb
new file mode 100644
index 0000000..ea9991a
--- /dev/null
+++ b/tests/data/test_debs/gdebi-test1.deb
Binary files differ
diff --git a/tests/data/test_debs/gdebi-test10.deb b/tests/data/test_debs/gdebi-test10.deb
new file mode 100644
index 0000000..ca43ace
--- /dev/null
+++ b/tests/data/test_debs/gdebi-test10.deb
Binary files differ
diff --git a/tests/data/test_debs/gdebi-test11.deb b/tests/data/test_debs/gdebi-test11.deb
new file mode 100644
index 0000000..af9b441
--- /dev/null
+++ b/tests/data/test_debs/gdebi-test11.deb
Binary files differ
diff --git a/tests/data/test_debs/gdebi-test12.deb b/tests/data/test_debs/gdebi-test12.deb
new file mode 100644
index 0000000..36544cc
--- /dev/null
+++ b/tests/data/test_debs/gdebi-test12.deb
Binary files differ
diff --git a/tests/data/test_debs/gdebi-test13.deb b/tests/data/test_debs/gdebi-test13.deb
new file mode 100644
index 0000000..4e7a828
--- /dev/null
+++ b/tests/data/test_debs/gdebi-test13.deb
Binary files differ
diff --git a/tests/data/test_debs/gdebi-test2.deb b/tests/data/test_debs/gdebi-test2.deb
new file mode 100644
index 0000000..307ac68
--- /dev/null
+++ b/tests/data/test_debs/gdebi-test2.deb
Binary files differ
diff --git a/tests/data/test_debs/gdebi-test3.deb b/tests/data/test_debs/gdebi-test3.deb
new file mode 100644
index 0000000..436b925
--- /dev/null
+++ b/tests/data/test_debs/gdebi-test3.deb
Binary files differ
diff --git a/tests/data/test_debs/gdebi-test4.deb b/tests/data/test_debs/gdebi-test4.deb
new file mode 100644
index 0000000..9eb92d1
--- /dev/null
+++ b/tests/data/test_debs/gdebi-test4.deb
Binary files differ
diff --git a/tests/data/test_debs/gdebi-test5.deb b/tests/data/test_debs/gdebi-test5.deb
new file mode 100644
index 0000000..0c98c03
--- /dev/null
+++ b/tests/data/test_debs/gdebi-test5.deb
Binary files differ
diff --git a/tests/data/test_debs/gdebi-test6.deb b/tests/data/test_debs/gdebi-test6.deb
new file mode 100644
index 0000000..8ceacad
--- /dev/null
+++ b/tests/data/test_debs/gdebi-test6.deb
Binary files differ
diff --git a/tests/data/test_debs/gdebi-test7.deb b/tests/data/test_debs/gdebi-test7.deb
new file mode 100644
index 0000000..c041499
--- /dev/null
+++ b/tests/data/test_debs/gdebi-test7.deb
Binary files differ
diff --git a/tests/data/test_debs/gdebi-test8.deb b/tests/data/test_debs/gdebi-test8.deb
new file mode 100644
index 0000000..439f8ca
--- /dev/null
+++ b/tests/data/test_debs/gdebi-test8.deb
Binary files differ
diff --git a/tests/data/test_debs/gdebi-test9.deb b/tests/data/test_debs/gdebi-test9.deb
new file mode 100644
index 0000000..9901d90
--- /dev/null
+++ b/tests/data/test_debs/gdebi-test9.deb
Binary files differ
diff --git a/tests/data/test_debs/hello_2.5-1.dsc b/tests/data/test_debs/hello_2.5-1.dsc
new file mode 100644
index 0000000..d00db52
--- /dev/null
+++ b/tests/data/test_debs/hello_2.5-1.dsc
@@ -0,0 +1,34 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA256
+
+Format: 1.0
+Source: hello
+Binary: hello, bello,
+ cello
+Architecture: any
+Version: 2.5-1
+Maintainer: Santiago Vila <sanvila@debian.org>
+Homepage: http://www.gnu.org/software/hello
+Standards-Version: 3.8.4
+Build-Depends: autotools-dev
+Checksums-Sha1:
+ dfaf92bfc8144141bcd5ffb4a30777cd57501bfa 582535 hello_2.5.orig.tar.gz
+ a98ab19072b35295ded3560721662131933f7c05 5965 hello_2.5-1.diff.gz
+Checksums-Sha256:
+ 22934a7d3a62f247ce3b5a77a2c7f7dd095ad8aef305efa2d0d15e0fef31c446 582535 hello_2.5.orig.tar.gz
+ c2f17c08a6a94bdab4f4316beb4687e8468de03a5162f1d694a0bab4b90e5962 5965 hello_2.5-1.diff.gz
+Files:
+ cf4b73d837692b93676ccd723bf6f797 582535 hello_2.5.orig.tar.gz
+ fa6c41ce60b975294781ed00d67f32fe 5965 hello_2.5-1.diff.gz
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.10 (GNU/Linux)
+
+iQEcBAEBCAAGBQJLeDJTAAoJEEHOfwufG4syQSAH/0S9vYKRbs71bfGNmKTmRQy6
+TJM1oj3hdjJoE9HBvCBoBhRSB7l5Iz+TDVyvKTcFOnXTWrZfhnNRCoErtOxP8Z0R
+MOEeLDTPf3JEvpwaRbfzngp+dRkAXTJSI+equqOvj4jjPd1lrNegWtwTF6VIlXAX
+5s+onfBp29/MesxzTGAdviobMYCdazmi2XceC+t5ZEJzEsMMPO6i/v22SrvE/Jkg
+LiD/U6gea3/1dovsUY6I7/VyzMhHgdcuUW4dzovr2daLwE+uRp9R90XDtKN5aWUM
+oBzk8vBIsw/3EV5kjCKdMtqFGdHBjn4nTKvyoXmJ1SvEzeEd21WvLsBFpcJVKaw=
+=YMqG
+-----END PGP SIGNATURE-----
diff --git a/tests/data/test_debs/impossible-build-depends_2.5-1.dsc b/tests/data/test_debs/impossible-build-depends_2.5-1.dsc
new file mode 100644
index 0000000..7f7364a
--- /dev/null
+++ b/tests/data/test_debs/impossible-build-depends_2.5-1.dsc
@@ -0,0 +1,33 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA256
+
+Format: 1.0
+Source: hello
+Binary: hello
+Architecture: any
+Version: 2.5-1
+Maintainer: Santiago Vila <sanvila@debian.org>
+Homepage: http://www.gnu.org/software/hello
+Standards-Version: 3.8.4
+Build-Depends: debhelper (>> 101)
+Checksums-Sha1:
+ dfaf92bfc8144141bcd5ffb4a30777cd57501bfa 582535 hello_2.5.orig.tar.gz
+ a98ab19072b35295ded3560721662131933f7c05 5965 hello_2.5-1.diff.gz
+Checksums-Sha256:
+ 22934a7d3a62f247ce3b5a77a2c7f7dd095ad8aef305efa2d0d15e0fef31c446 582535 hello_2.5.orig.tar.gz
+ c2f17c08a6a94bdab4f4316beb4687e8468de03a5162f1d694a0bab4b90e5962 5965 hello_2.5-1.diff.gz
+Files:
+ cf4b73d837692b93676ccd723bf6f797 582535 hello_2.5.orig.tar.gz
+ fa6c41ce60b975294781ed00d67f32fe 5965 hello_2.5-1.diff.gz
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.10 (GNU/Linux)
+
+iQEcBAEBCAAGBQJLeDJTAAoJEEHOfwufG4syQSAH/0S9vYKRbs71bfGNmKTmRQy6
+TJM1oj3hdjJoE9HBvCBoBhRSB7l5Iz+TDVyvKTcFOnXTWrZfhnNRCoErtOxP8Z0R
+MOEeLDTPf3JEvpwaRbfzngp+dRkAXTJSI+equqOvj4jjPd1lrNegWtwTF6VIlXAX
+5s+onfBp29/MesxzTGAdviobMYCdazmi2XceC+t5ZEJzEsMMPO6i/v22SrvE/Jkg
+LiD/U6gea3/1dovsUY6I7/VyzMhHgdcuUW4dzovr2daLwE+uRp9R90XDtKN5aWUM
+oBzk8vBIsw/3EV5kjCKdMtqFGdHBjn4nTKvyoXmJ1SvEzeEd21WvLsBFpcJVKaw=
+=YMqG
+-----END PGP SIGNATURE-----
diff --git a/tests/data/test_debs/large-package-content_1.0_all.deb b/tests/data/test_debs/large-package-content_1.0_all.deb
new file mode 100644
index 0000000..56bdce3
--- /dev/null
+++ b/tests/data/test_debs/large-package-content_1.0_all.deb
Binary files differ
diff --git a/tests/data/test_debs/multiarch-test1_i386.deb b/tests/data/test_debs/multiarch-test1_i386.deb
new file mode 100644
index 0000000..439a9f4
--- /dev/null
+++ b/tests/data/test_debs/multiarch-test1_i386.deb
Binary files differ
diff --git a/tests/data/test_debs/testdep-allowed-any_1.0-1_i386.deb b/tests/data/test_debs/testdep-allowed-any_1.0-1_i386.deb
new file mode 100644
index 0000000..c56f819
--- /dev/null
+++ b/tests/data/test_debs/testdep-allowed-any_1.0-1_i386.deb
Binary files differ
diff --git a/tests/data/test_debs/testdep-same-arch_1.0-1_i386.deb b/tests/data/test_debs/testdep-same-arch_1.0-1_i386.deb
new file mode 100644
index 0000000..872f3b6
--- /dev/null
+++ b/tests/data/test_debs/testdep-same-arch_1.0-1_i386.deb
Binary files differ
diff --git a/tests/data/test_debs/utf8-package_1.0-1_all.deb b/tests/data/test_debs/utf8-package_1.0-1_all.deb
new file mode 100644
index 0000000..e0339c2
--- /dev/null
+++ b/tests/data/test_debs/utf8-package_1.0-1_all.deb
Binary files differ
diff --git a/tests/data/test_debs/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_maverick_main_binary-i386_Packages b/tests/data/test_debs/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_maverick_main_binary-i386_Packages
new file mode 100644
index 0000000..b3b30d0
--- /dev/null
+++ b/tests/data/test_debs/var/lib/apt/lists/archive.ubuntu.com_ubuntu_dists_maverick_main_binary-i386_Packages
@@ -0,0 +1,31 @@
+Package: autotools-dev
+Priority: optional
+Section: devel
+Installed-Size: 216
+Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
+Original-Maintainer: Henrique de Moraes Holschuh <hmh@debian.org>
+Architecture: all
+Version: 20100122.1
+Filename: pool/main/a/autotools-dev/autotools-dev_20100122.1_all.deb
+Size: 70700
+MD5sum: dc25cef0035a3fc7c64b9f2eeddac5d2
+SHA1: 40bcffb6bc2ec7aeaae747c300a0ad70ef3bb38c
+SHA256: 290aaf1d5d5a6c560a128b6fe5557fe981ebb85e105410f3bca2e468ce54aaac
+Description: Update infrastructure for config.{guess,sub} files
+ This package installs an up-to-date version of config.guess and
+ config.sub, used by the automake and libtool packages. It provides
+ the canonical copy of those files for other packages as well.
+ .
+ It also documents in /usr/share/doc/autotools-dev/README.Debian.gz
+ best practices and guidelines for using autoconf, automake and
+ friends on Debian packages. This is a must-read for any developers
+ packaging software that uses the GNU autotools, or GNU gettext.
+ .
+ Additionally this package provides seamless integration into Debhelper
+ or CDBS, allowing maintainers to easily update config.{guess,sub} files
+ in their packages.
+Enhances: cdbs, debhelper
+Homepage: http://savannah.gnu.org/projects/config/
+Bugs: https://bugs.launchpad.net/ubuntu/+filebug
+Origin: Ubuntu
+Supported: 18m
diff --git a/tests/data/test_debs/var/lib/dpkg/status b/tests/data/test_debs/var/lib/dpkg/status
new file mode 100644
index 0000000..5c2c48a
--- /dev/null
+++ b/tests/data/test_debs/var/lib/dpkg/status
@@ -0,0 +1,92 @@
+Package: apt
+Status: install ok installed
+Priority: important
+Section: admin
+Installed-Size: 5456
+Maintainer: APT Development Team <deity@lists.debian.org>
+Architecture: i386
+Version: 0.7.25.3
+Replaces: libapt-pkg-dev (<< 0.3.7), libapt-pkg-doc (<< 0.3.7)
+Provides: libapt-pkg-libc6.10-6-4.8
+Description: Advanced front-end for dpkg
+ This is Debian's next generation front-end for the dpkg package manager.
+ It provides the apt-get utility and APT dselect method that provides a
+ simpler, safer way to install and upgrade packages.
+ .
+ APT features complete installation ordering, multiple source capability
+ and several other unique features, see the Users Guide in apt-doc.
+
+Package: postfix
+Status: install ok installed
+Priority: extra
+Section: mail
+Installed-Size: 3488
+Maintainer: LaMont Jones <lamont@debian.org>
+Architecture: i386
+Version: 2.7.0-1
+Replaces: mail-transport-agent, postfix-tls
+Provides: default-mta, mail-transport-agent, postfix-tls
+Recommends: python
+Conflicts: libnss-db (<< 2.2-3), mail-transport-agent, postfix-tls, smail
+Description: High-performance mail transport agent
+ Postfix is Wietse Venema's mail transport agent that started life as an
+ alternative to the widely-used Sendmail program. Postfix attempts to
+ be fast, easy to administer, and secure, while at the same time being
+ sendmail compatible enough to not upset existing users. Thus, the outside
+ has a sendmail-ish flavor, but the inside is completely different.
+
+Package: debconf
+Status: install ok installed
+Priority: important
+Section: admin
+Installed-Size: 924
+Maintainer: Debconf Developers <debconf-devel@lists.alioth.debian.org>
+Architecture: all
+Version: 1.5.28
+Replaces: debconf-tiny
+Provides: debconf-2.0
+Recommends: apt-utils (>= 0.5.1)
+Conflicts: apt (<< 0.3.12.1), cdebconf (<< 0.96), debconf-tiny, debconf-utils (<< 1.3.22), dialog (<< 0.9b-20020814-1), menu (<= 2.1.3-1), whiptail (<< 0.51.4-11), whiptail-utf8 (<= 0.50.17-13)
+Description: Debian configuration management system
+ Debconf is a configuration management system for debian packages. Packages
+ use Debconf to ask questions when they are installed.
+Python-Version: 2.6, 3.1
+
+Package: testdep-same
+Status: install ok installed
+Source: testdep
+Version: 1.0-1
+Architecture: amd64
+Maintainer: Francois Gouget <fgouget@codeweavers.com>
+Installed-Size: 25
+Provides: testdep-virtual-same
+Section: unknown
+Priority: extra
+Multi-Arch: same
+Description: Multi-arch = same package, no dependency
+ This is a multiarch package that can only satisfy dependencies for the same
+ architecture. But multiple instances of this package can be co-installed,
+ one for each architecture.
+ .
+ Library and development packages typically fall into this category.
+
+Package: testdep-allowed
+Status: install ok installed
+Source: testdep
+Version: 1.0-1
+Architecture: amd64
+Maintainer: Francois Gouget <fgouget@codeweavers.com>
+Installed-Size: 25
+Provides: testdep-virtual-allowed
+Section: unknown
+Priority: extra
+Multi-Arch: allowed
+Description: Multi-arch = allowed package, no dependency
+ This is a multiarch package. By default it can only satisfy dependencies for
+ packages of the same architecture but that can be changed with ':any'
+ dependencies.
+ .
+ It can only be installed for one architecture at a time. Trying to install the
+ same package for another architecture will remove the first one.
+ .
+ Packages providing tools or shells typically fall into this category.
diff --git a/tests/fakeroot-apt-key b/tests/fakeroot-apt-key
new file mode 100755
index 0000000..997161a
--- /dev/null
+++ b/tests/fakeroot-apt-key
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec fakeroot /usr/bin/apt-key $*
diff --git a/tests/helper_install_progress_run.py b/tests/helper_install_progress_run.py
new file mode 100755
index 0000000..02e601d
--- /dev/null
+++ b/tests/helper_install_progress_run.py
@@ -0,0 +1,15 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2019 Colomban Wendling <cwendling@hypra.fr>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+"""Helper checking argv[1] is a valid, writable, file descriptor"""
+
+import os
+from sys import argv
+
+assert len(argv) == 2
+with os.fdopen(int(argv[1]), "w") as f:
+ assert f.write("test") == 4
diff --git a/tests/old/__init__.py b/tests/old/__init__.py
new file mode 100644
index 0000000..5311641
--- /dev/null
+++ b/tests/old/__init__.py
@@ -0,0 +1,11 @@
+import os
+import unittest
+
+if __name__ == "__main__":
+ os.chdir(os.path.dirname(__file__))
+ print(os.getcwd())
+
+ for path in os.listdir("."):
+ if path.endswith(".py"):
+ exec("from %s import *" % path[:-3])
+ unittest.main()
diff --git a/tests/old/apt-test.py b/tests/old/apt-test.py
new file mode 100644
index 0000000..8c66aeb
--- /dev/null
+++ b/tests/old/apt-test.py
@@ -0,0 +1,27 @@
+import warnings
+
+warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning)
+import apt
+
+if __name__ == "__main__":
+ progress = apt.progress.OpTextProgress()
+ cache = apt.Cache(progress)
+ print(cache)
+ for pkg in cache:
+ if pkg.is_upgradable:
+ pkg.mark_install()
+ for pkg in cache.get_changes():
+ # print pkg.name()
+ pass
+ print("Broken: %s " % cache._depcache.broken_count)
+ print("inst_count: %s " % cache._depcache.inst_count)
+
+ # get a new cache
+ cache = apt.Cache(progress)
+ for name in cache.keys():
+ import random
+
+ if random.randint(0, 1) == 1:
+ cache[name].mark_delete()
+ print("Broken: %s " % cache._depcache.broken_count)
+ print("del_count: %s " % cache._depcache.del_count)
diff --git a/tests/old/cache.py b/tests/old/cache.py
new file mode 100644
index 0000000..3f4aa0c
--- /dev/null
+++ b/tests/old/cache.py
@@ -0,0 +1,51 @@
+#!/usr/bin/python3
+#
+# Test for the pkgCache code
+#
+
+import sys
+
+import apt_pkg
+
+
+def main():
+ apt_pkg.init()
+ cache = apt_pkg.Cache()
+ depcache = apt_pkg.DepCache(cache)
+ depcache.init()
+ i = 0
+ all = cache.package_count
+ print("Running Cache test on all packages:")
+ # first, get all pkgs
+ for pkg in cache.packages:
+ i += 1
+ pkg.name
+ # then get each version
+ for ver in pkg.version_list:
+ # get some version information
+ ver.file_list
+ ver.ver_str
+ ver.arch
+ ver.depends_listStr
+ dl = ver.depends_list
+ # get all dependencies (a dict of string->list,
+ # e.g. "depends:" -> [ver1,ver2,..]
+ for dep in dl.keys():
+ # get the list of each dependency object
+ for depVerList in dl[dep]:
+ for z in depVerList:
+ # get all TargetVersions of
+ # the dependency object
+ for j in z.all_targets():
+ j.file_list
+ ver.ver_str
+ ver.arch
+ ver.depends_listStr
+ j = ver.depends_list
+
+ print("\r%i/%i=%.3f%% " % (i, all, (float(i) / float(all) * 100)))
+
+
+if __name__ == "__main__":
+ main()
+ sys.exit(0)
diff --git a/tests/old/depcache.py b/tests/old/depcache.py
new file mode 100644
index 0000000..81ca574
--- /dev/null
+++ b/tests/old/depcache.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python2.4
+#
+# Test for the DepCache code
+#
+
+import sys
+
+import apt_pkg
+
+
+def main():
+ apt_pkg.init()
+ cache = apt_pkg.Cache()
+ depcache = apt_pkg.DepCache(cache)
+ depcache.init()
+ i = 0
+ all = cache.package_count
+ print("Running DepCache test on all packages")
+ print("(trying to install each and then mark it keep again):")
+ # first, get all pkgs
+ for pkg in cache.packages:
+ i += 1
+ x = pkg.name
+ # then get each version
+ ver = depcache.get_candidate_ver(pkg)
+ if ver is not None:
+ depcache.mark_install(pkg)
+ if depcache.inst_count == 0:
+ if depcache.is_upgradable(pkg):
+ print("Error marking %s for install" % x)
+ for p in cache.packages:
+ if depcache.marked_install(p):
+ depcache.mark_keep(p)
+ if depcache.inst_count != 0:
+ print(
+ "Error undoing the selection for %s (inst_count: %s)"
+ % (x, depcache.inst_count)
+ )
+ print("\r%i/%i=%.3f%% " % (i, all, (float(i) / float(all) * 100)))
+
+ print()
+ print("Trying upgrade:")
+ depcache.upgrade()
+ print("To install: %s " % depcache.inst_count)
+ print("To remove: %s " % depcache.del_count)
+ print("Kept back: %s " % depcache.keep_count)
+
+ print("Trying DistUpgrade:")
+ depcache.upgrade(True)
+ print("To install: %s " % depcache.inst_count)
+ print("To remove: %s " % depcache.del_count)
+ print("Kept back: %s " % depcache.keep_count)
+
+
+if __name__ == "__main__":
+ main()
+ sys.exit(0)
diff --git a/tests/old/lock.py b/tests/old/lock.py
new file mode 100644
index 0000000..c09983c
--- /dev/null
+++ b/tests/old/lock.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python2.4
+#
+# Test for the pkgCache code
+#
+
+import os
+import sys
+
+import apt_pkg
+
+if __name__ == "__main__":
+ lock = "/tmp/test.lck"
+
+ apt_pkg.init()
+
+ # system-lock
+ apt_pkg.pkgsystem_lock()
+
+ pid = os.fork()
+ if pid == 0:
+ try:
+ apt_pkg.pkgsystem_lock()
+ except SystemError as s:
+ print("Can't get lock: (error text:\n%s)" % s)
+ sys.exit(0)
+
+ apt_pkg.pkgsystem_unlock()
+
+ # low-level lock
+ fd = apt_pkg.get_lock(lock, True)
+ print("Lockfile fd: %s" % fd)
+
+ # try to get lock without error flag
+ pid = os.fork()
+ if pid == 0:
+ # child
+ fd = apt_pkg.get_lock(lock, False)
+ print("Lockfile fd (child): %s" % fd)
+ sys.exit(0)
+
+ # try to get lock with error flag
+ pid = os.fork()
+ if pid == 0:
+ # child
+ fd = apt_pkg.get_lock(lock, True)
+ print("Lockfile fd (child): %s" % fd)
+ sys.exit(0)
diff --git a/tests/old/memleak.py b/tests/old/memleak.py
new file mode 100644
index 0000000..44b123e
--- /dev/null
+++ b/tests/old/memleak.py
@@ -0,0 +1,45 @@
+#!/usr/bin/python3
+
+import gc
+import time
+
+import apt_pkg
+
+import apt
+
+cache = apt.Cache()
+
+# memleak
+for i in range(100):
+ cache.open(None)
+ print(cache["apt"].name)
+ time.sleep(1)
+ gc.collect()
+ f = open("%s" % i, "w")
+ for obj in gc.get_objects():
+ f.write("%s\n" % str(obj))
+ f.close()
+
+# memleak
+# for i in range(100):
+# cache = apt.Cache()
+# time.sleep(1)
+# cache = None
+# gc.collect()
+
+# no memleak, but more or less the apt.Cache.open() code
+for i in range(100):
+ cache = apt_pkg.Cache()
+ depcache = apt_pkg.DepCache(cache)
+ records = apt_pkg.PackageRecords(cache)
+ list = apt_pkg.SourceList()
+ list.read_main_list()
+ dict = {}
+ for pkg in cache.packages:
+ if len(pkg.version_list) > 0:
+ dict[pkg.name] = apt.package(cache, depcache, records, list, None, pkg)
+
+ print(cache["apt"])
+ time.sleep(1)
+
+ gc.collect()
diff --git a/tests/old/pkgproblemresolver.py b/tests/old/pkgproblemresolver.py
new file mode 100644
index 0000000..89190cf
--- /dev/null
+++ b/tests/old/pkgproblemresolver.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python2.4
+#
+# Test for the DepCache code
+#
+
+import sys
+
+import apt_pkg
+
+
+def main():
+ apt_pkg.init()
+ cache = apt_pkg.Cache()
+ depcache = apt_pkg.DepCache(cache)
+ depcache.init()
+ i = 0
+ all = cache.package_count
+ print("Running DepCache test on all packages")
+ print("(trying to install each and then mark it keep again):")
+ # first, get all pkgs
+ for pkg in cache.packages:
+ i += 1
+ x = pkg.name
+ # then get each version
+ ver = depcache.get_candidate_ver(pkg)
+ if ver is not None:
+ depcache.mark_install(pkg)
+ if depcache.broken_count > 0:
+ fixer = apt_pkg.ProblemResolver(depcache)
+ fixer.clear(pkg)
+ fixer.protect(pkg)
+ # we first try to resolve the problem
+ # with the package that should be installed
+ # protected
+ try:
+ fixer.resolve(True)
+ except SystemError:
+ # the pkg seems to be broken, the
+ # returns a exception
+ fixer.clear(pkg)
+ fixer.resolve(True)
+ if not depcache.marked_install(pkg):
+ print("broken in archive: %s " % pkg.name)
+ fixer = None
+ if depcache.inst_count == 0:
+ if depcache.is_upgradable(pkg):
+ print("Error marking %s for install" % x)
+ for p in cache.packages:
+ if depcache.marked_install(p) or depcache.marked_upgrade(p):
+ depcache.mark_keep(p)
+ if depcache.inst_count != 0:
+ print("Error undoing the selection for %s" % x)
+ print("\r%i/%i=%.3f%% " % (i, all, (float(i) / float(all) * 100)))
+
+ print()
+ print("Trying upgrade:")
+ depcache.upgrade()
+ print("To install: %s " % depcache.inst_count)
+ print("To remove: %s " % depcache.del_count)
+ print("Kept back: %s " % depcache.keep_count)
+
+ print("Trying DistUpgrade:")
+ depcache.upgrade(True)
+ print("To install: %s " % depcache.inst_count)
+ print("To remove: %s " % depcache.del_count)
+ print("Kept back: %s " % depcache.keep_count)
+
+
+if __name__ == "__main__":
+ main()
+ sys.exit(0)
diff --git a/tests/old/pkgrecords.py b/tests/old/pkgrecords.py
new file mode 100644
index 0000000..b6be005
--- /dev/null
+++ b/tests/old/pkgrecords.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python2.4
+#
+# Test for the PkgSrcRecords code
+# it segfaults for python-apt < 0.5.37
+#
+
+import sys
+
+import apt_pkg
+
+
+def main():
+ apt_pkg.init()
+ cache = apt_pkg.Cache()
+ depcache = apt_pkg.DepCache(cache)
+ depcache.init()
+ i = 0
+ print("Running PkgRecords test on all packages:")
+ for pkg in cache.packages:
+ i += 1
+ records = apt_pkg.PackageRecords(cache)
+ if len(pkg.version_list) == 0:
+ # print "no available version, cruft"
+ continue
+ version = depcache.get_candidate_ver(pkg)
+ if not version:
+ continue
+ file, index = version.file_list.pop(0)
+ if records.lookup((file, index)):
+ # print records.filename
+ records.filename
+ records.long_desc
+ print(
+ "\r%i/%i=%.3f%% "
+ % (i, cache.package_count, (float(i) / float(cache.package_count) * 100))
+ )
+
+
+if __name__ == "__main__":
+ main()
+ sys.exit(0)
diff --git a/tests/old/pkgsrcrecords.py b/tests/old/pkgsrcrecords.py
new file mode 100644
index 0000000..ccf791f
--- /dev/null
+++ b/tests/old/pkgsrcrecords.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python2.4
+#
+# Test for the PkgSrcRecords code
+# it segfaults for python-apt < 0.5.37
+#
+
+import sys
+
+import apt_pkg
+
+
+def main():
+ apt_pkg.init()
+ cache = apt_pkg.Cache()
+ i = 0
+ print("Running PkgSrcRecords test on all packages:")
+ for x in cache.packages:
+ i += 1
+ src = apt_pkg.SourceRecords()
+ if src.lookup(x.name):
+ # print src.package
+ pass
+ print(
+ "\r%i/%i=%.3f%% "
+ % (i, cache.package_count, (float(i) / float(cache.package_count) * 100))
+ )
+
+
+if __name__ == "__main__":
+ main()
+ sys.exit(0)
diff --git a/tests/old/refcount.py b/tests/old/refcount.py
new file mode 100755
index 0000000..0fad676
--- /dev/null
+++ b/tests/old/refcount.py
@@ -0,0 +1,54 @@
+#!/usr/bin/python-dbg
+
+import gc
+import sys
+from pprint import pprint
+
+import apt
+
+# get initial cache
+print(sys.gettotalrefcount())
+progress = apt.progress.OpTextProgress()
+c = apt.Cache(progress)
+print("refcount after first cache instance: ", sys.gettotalrefcount())
+
+# test open()
+c.open(progress)
+print("refcount after cache open: ", sys.gettotalrefcount())
+# pprint(sys.getobjects(10))
+
+c.open(apt.progress.OpProgress())
+print("refcount after seconf cache open: ", sys.gettotalrefcount())
+# pprint(sys.getobjects(10))
+
+# FIXME: find a way to get a efficient diff
+# before = gc.get_objects()
+# c.open(apt.progress.OpProgress())
+# after = gc.get_objects()
+
+
+# test update()
+print("refcount before cache.update(): ", sys.gettotalrefcount())
+c.update()
+gc.collect()
+print("refcount after cache.update(): ", sys.gettotalrefcount())
+c.update()
+gc.collect()
+print("refcount after second cache.update(): ", sys.gettotalrefcount())
+# pprint(sys.getobjects(20))
+
+
+# test install()
+c.open(apt.progress.OpProgress())
+gc.collect()
+print("refcount before cache['hello'].mark_install(): ", sys.gettotalrefcount())
+c["hello"].mark_install()
+c.commit(apt.progress.FetchProgress(), apt.progress.InstallProgress())
+gc.collect()
+print("refcount after: ", sys.gettotalrefcount())
+c.open(apt.progress.OpProgress())
+c["hello"].mark_delete()
+c.commit(apt.progress.FetchProgress(), apt.progress.InstallProgress())
+gc.collect()
+print("refcount after: ", sys.gettotalrefcount())
+pprint(sys.getobjects(10))
diff --git a/tests/old/test_enhances.py b/tests/old/test_enhances.py
new file mode 100644
index 0000000..79aad9a
--- /dev/null
+++ b/tests/old/test_enhances.py
@@ -0,0 +1,16 @@
+#!/usr/bin/python3
+
+import apt
+
+cache = apt.Cache()
+
+for pkg in cache:
+ if pkg.installed and pkg.installed.enhances:
+ s = "%s enhances:" % pkg.name
+ for or_list in pkg.installed.enhances:
+ for enhances in or_list.or_dependencies:
+ s += " %s" % enhances.name
+ if enhances.name in cache and not cache[enhances.name].is_installed:
+ s += "(*missing*) "
+ s += ","
+ print(s[:-1])
diff --git a/tests/test_all.py b/tests/test_all.py
new file mode 100644
index 0000000..c97ed5d
--- /dev/null
+++ b/tests/test_all.py
@@ -0,0 +1,63 @@
+#!/usr/bin/python3
+# Copyright (C) 2009 Julian Andres Klode <jak@debian.org>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+"""Run all available unit tests."""
+import os
+import sys
+import unittest
+import unittest.runner
+
+# Python 3 only provides abiflags since 3.2
+if not hasattr(sys, "pydebug"):
+ if sys.abiflags.startswith("d"):
+ sys.pydebug = True
+ else:
+ sys.pydebug = False
+
+
+def get_library_dir():
+ # Find the path to the built apt_pkg and apt_inst extensions
+ if not os.path.exists("../build"):
+ return None
+ from sysconfig import get_platform, get_python_version
+
+ # Set the path to the build directory.
+ plat_specifier = f".{get_platform()}-{get_python_version()}"
+ library_dir = "../build/lib{}{}".format(
+ plat_specifier,
+ (sys.pydebug and "-pydebug" or ""),
+ )
+ return os.path.abspath(library_dir)
+
+
+class MyTestRunner(unittest.runner.TextTestRunner):
+ def __init__(self, *args, **kwargs):
+ kwargs["stream"] = sys.stdout
+ super().__init__(*args, **kwargs)
+
+
+if __name__ == "__main__":
+ if not os.access("/etc/apt/sources.list", os.R_OK):
+ sys.stdout.write("[tests] Skipping because sources.list is not readable\n")
+ sys.exit(0)
+
+ sys.stdout.write("[tests] Running on %s\n" % sys.version.replace("\n", ""))
+ dirname = os.path.dirname(__file__)
+ if dirname:
+ os.chdir(dirname)
+ library_dir = get_library_dir()
+ if "pybuild" in os.getenv("PYTHONPATH", ""):
+ # pybuild already supplied us with a path to check for
+ sys.stdout.write("Using pybuild supplied build dir\n")
+ elif library_dir:
+ sys.stdout.write("Using library_dir: '%s'\n" % library_dir)
+ sys.path.insert(0, os.path.abspath(library_dir))
+
+ for path in os.listdir("."):
+ if path.endswith(".py") and os.path.isfile(path) and path.startswith("test_"):
+ exec("from %s import *" % path[:-3])
+
+ unittest.main(testRunner=MyTestRunner)
diff --git a/tests/test_apt_cache.py b/tests/test_apt_cache.py
new file mode 100644
index 0000000..cc52400
--- /dev/null
+++ b/tests/test_apt_cache.py
@@ -0,0 +1,400 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2010 Julian Andres Klode <jak@debian.org>
+# 2010 Michael Vogt <mvo@ubuntu.com>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+"""Unit tests for verifying the correctness of check_dep, etc in apt_pkg."""
+
+import glob
+import logging
+import os
+import shutil
+import sys
+import tempfile
+import unittest
+
+from test_all import get_library_dir
+
+libdir = get_library_dir()
+if libdir:
+ sys.path.insert(0, libdir)
+
+import apt_pkg
+import testcommon
+
+import apt
+
+
+def if_sources_list_is_readable(f):
+ def wrapper(*args, **kwargs):
+ if os.access("/etc/apt/sources.list", os.R_OK):
+ f(*args, **kwargs)
+ else:
+ logging.warning("skipping '%s' because sources.list is not readable" % f)
+
+ return wrapper
+
+
+def get_open_file_descriptors():
+ try:
+ fds = os.listdir("/proc/self/fd")
+ except OSError:
+ logging.warning("failed to list /proc/self/fd")
+ return set()
+ return set(map(int, fds))
+
+
+class TestAptCache(testcommon.TestCase):
+ """test the apt cache"""
+
+ def setUp(self):
+ testcommon.TestCase.setUp(self)
+ apt_pkg.config.clear("APT::Update::Post-Invoke")
+ apt_pkg.config.clear("APT::Update::Post-Invoke-Success")
+
+ @if_sources_list_is_readable
+ def test_apt_cache(self):
+ """cache: iterate all packages and all dependencies"""
+ cache = apt.Cache()
+ # number is not meaningful and just need to be "big enough",
+ # the important bit is the test against __len__
+ self.assertTrue(len(cache) > 100)
+ # go over the cache and all dependencies, just to see if
+ # that is possible and does not crash
+ for pkg in cache:
+ if pkg.candidate:
+ for or_deps in pkg.candidate.dependencies:
+ for dep in or_deps:
+ self.assertTrue(dep.name)
+ self.assertTrue(isinstance(dep.relation, str))
+ self.assertTrue(dep.pre_depend in (True, False))
+
+ # accessing record should take a reasonable time; in
+ # particular, when using compressed indexes, it should not use
+ # tons of seek operations
+ r = pkg.candidate.record
+ self.assertEqual(r["Package"], pkg.shortname)
+ self.assertTrue("Version" in r)
+ self.assertTrue(len(r["Description"]) > 0)
+ self.assertTrue(str(r).startswith("Package: %s\n" % pkg.shortname))
+
+ @if_sources_list_is_readable
+ def test_cache_close_leak_fd(self):
+ fds_before_open = get_open_file_descriptors()
+ cache = apt.Cache()
+ opened_fd = get_open_file_descriptors().difference(fds_before_open)
+ cache.close()
+ fds_after_close = get_open_file_descriptors()
+ unclosed_fd = opened_fd.intersection(fds_after_close)
+ self.assertEqual(fds_before_open, fds_after_close)
+ self.assertEqual(unclosed_fd, set())
+
+ def test_cache_open_twice_leaks_fds(self):
+ cache = apt.Cache()
+ fds_before_open = get_open_file_descriptors()
+ cache.open()
+ fds_after_open_twice = get_open_file_descriptors()
+ self.assertEqual(fds_before_open, fds_after_open_twice)
+
+ @if_sources_list_is_readable
+ def test_cache_close_download_fails(self):
+ cache = apt.Cache()
+ self.assertEqual(cache.required_download, 0)
+ cache.close()
+ with self.assertRaises(apt.cache.CacheClosedException):
+ cache.required_download
+
+ def test_get_provided_packages(self):
+ apt.apt_pkg.config.set("Apt::architecture", "i386")
+ cache = apt.Cache(rootdir="./data/test-provides/")
+ cache.open()
+ if len(cache) == 0:
+ logging.warning("skipping test_get_provided_packages, cache empty?!?")
+ return
+ # a true virtual pkg
+ li = cache.get_providing_packages("mail-transport-agent")
+ self.assertTrue(len(li) > 0)
+ self.assertTrue("postfix" in [p.name for p in li])
+ self.assertTrue("mail-transport-agent" in cache["postfix"].candidate.provides)
+
+ def test_low_level_pkg_provides(self):
+ apt.apt_pkg.config.set("Apt::architecture", "i386")
+ # create highlevel cache and get the lowlevel one from it
+ highlevel_cache = apt.Cache(rootdir="./data/test-provides")
+ if len(highlevel_cache) == 0:
+ logging.warning("skipping test_log_level_pkg_provides, cache empty?!?")
+ return
+ # low level cache provides list of the pkg
+ cache = highlevel_cache._cache
+ li = cache["mail-transport-agent"].provides_list
+ # arbitrary number, just needs to be higher enough
+ self.assertEqual(len(li), 2)
+ for providesname, providesver, version in li:
+ self.assertEqual(providesname, "mail-transport-agent")
+ if version.parent_pkg.name == "postfix":
+ break
+ else:
+ self.assertNotReached()
+
+ @if_sources_list_is_readable
+ def test_dpkg_journal_dirty(self):
+ # create tmp env
+ tmpdir = tempfile.mkdtemp()
+ dpkg_dir = os.path.join(tmpdir, "var", "lib", "dpkg")
+ os.makedirs(os.path.join(dpkg_dir, "updates"))
+ open(os.path.join(dpkg_dir, "status"), "w").close()
+ apt_pkg.config.set("Dir::State::status", os.path.join(dpkg_dir, "status"))
+ cache = apt.Cache()
+ # test empty
+ self.assertFalse(cache.dpkg_journal_dirty)
+ # that is ok, only [0-9] are dpkg jounral entries
+ open(os.path.join(dpkg_dir, "updates", "xxx"), "w").close()
+ self.assertFalse(cache.dpkg_journal_dirty)
+ # that is a dirty journal
+ open(os.path.join(dpkg_dir, "updates", "000"), "w").close()
+ self.assertTrue(cache.dpkg_journal_dirty)
+
+ @if_sources_list_is_readable
+ def test_apt_update(self):
+ rootdir = "./data/tmp"
+ if os.path.exists(rootdir):
+ shutil.rmtree(rootdir)
+ try:
+ os.makedirs(os.path.join(rootdir, "var/lib/apt/lists/partial"))
+ except OSError:
+ pass
+ state_dir = os.path.join(rootdir, "var/lib/apt")
+ lists_dir = os.path.join(rootdir, "var/lib/apt/lists")
+ old_state = apt_pkg.config.find("dir::state")
+ apt_pkg.config.set("dir::state", state_dir)
+ # set a local sources.list that does not need the network
+ base_sources = os.path.abspath(os.path.join(rootdir, "sources.list"))
+ old_source_list = apt_pkg.config.find("dir::etc::sourcelist")
+ old_source_parts = apt_pkg.config.find("dir::etc::sourceparts")
+ apt_pkg.config.set("dir::etc::sourcelist", base_sources)
+ # TODO: /dev/null is not a dir, perhaps find something better
+ apt_pkg.config.set("dir::etc::sourceparts", "/dev/null")
+ # main sources.list
+ sources_list = base_sources
+ with open(sources_list, "w") as f:
+ repo = os.path.abspath("./data/test-repo2")
+ f.write("deb [allow-insecure=yes] copy:%s /\n" % repo)
+
+ # test single sources.list fetching
+ sources_list = os.path.join(rootdir, "test.list")
+ with open(sources_list, "w") as f:
+ repo_dir = os.path.abspath("./data/test-repo")
+ f.write("deb [allow-insecure=yes] copy:%s /\n" % repo_dir)
+
+ self.assertTrue(os.path.exists(sources_list))
+ # write marker to ensure listcleaner is not run
+ open("./data/tmp/var/lib/apt/lists/marker", "w").close()
+
+ # update a single sources.list
+ cache = apt.Cache()
+ cache.update(sources_list=sources_list)
+ # verify we just got the excpected package file
+ needle_packages = glob.glob(lists_dir + "/*tests_data_test-repo_Packages*")
+ self.assertEqual(len(needle_packages), 1)
+ # verify that we *only* got the Packages file from a single source
+ all_packages = glob.glob(lists_dir + "/*_Packages*")
+ self.assertEqual(needle_packages, all_packages)
+ # verify that the listcleaner was not run and the marker file is
+ # still there
+ self.assertTrue("marker" in os.listdir(lists_dir))
+ # now run update again (without the "normal" sources.list that
+ # contains test-repo2 and verify that we got the normal sources.list
+ cache.update()
+ needle_packages = glob.glob(lists_dir + "/*tests_data_test-repo2_Packages*")
+ self.assertEqual(len(needle_packages), 1)
+ all_packages = glob.glob(lists_dir + "/*_Packages*")
+ self.assertEqual(needle_packages, all_packages)
+
+ # and another update with a single source only
+ cache = apt.Cache()
+ cache.update(sources_list=sources_list)
+ all_packages = glob.glob(lists_dir + "/*_Packages*")
+ self.assertEqual(len(all_packages), 2)
+ apt_pkg.config.set("dir::state", old_state)
+ apt_pkg.config.set("dir::etc::sourcelist", old_source_list)
+ apt_pkg.config.set("dir::etc::sourceparts", old_source_parts)
+
+ def test_package_cmp(self):
+ cache = apt.Cache(rootdir="/")
+ li = []
+ li.append(cache["intltool"])
+ li.append(cache["python3"])
+ li.append(cache["apt"])
+ li.sort()
+ self.assertEqual([p.name for p in li], ["apt", "intltool", "python3"])
+
+ def test_get_architectures(self):
+ main_arch = apt.apt_pkg.config.get("APT::Architecture")
+ arches = apt_pkg.get_architectures()
+ self.assertTrue(main_arch in arches)
+
+ def test_phasing_applied(self):
+ """checks the return type of phasing_applied."""
+ cache = apt.Cache()
+ pkg = cache["apt"]
+ self.assertIsInstance(pkg.phasing_applied, bool)
+
+ def test_is_security_update(self):
+ """checks the return type of is_security_update."""
+ cache = apt.Cache()
+ pkg = cache["apt"]
+ self.assertIsInstance(pkg.installed.is_security_update, bool)
+
+ def test_apt_cache_reopen_is_safe(self):
+ """cache: check that we cannot use old package objects after reopen"""
+ cache = apt.Cache()
+ old_depcache = cache._depcache
+ old_package = cache["apt"]
+ old_pkg = old_package._pkg
+ old_version = old_package.candidate
+ old_ver = old_version._cand
+
+ cache.open()
+ new_depcache = cache._depcache
+ new_package = cache["apt"]
+ new_pkg = new_package._pkg
+ new_version = new_package.candidate
+ new_ver = new_version._cand
+
+ # get candidate
+ self.assertRaises(ValueError, old_depcache.get_candidate_ver, new_pkg)
+ self.assertRaises(ValueError, new_depcache.get_candidate_ver, old_pkg)
+ self.assertEqual(new_ver, new_depcache.get_candidate_ver(new_pkg))
+ self.assertEqual(old_package.candidate._cand, old_ver) # Remap success
+ self.assertEqual(
+ old_package.candidate._cand, new_depcache.get_candidate_ver(new_pkg)
+ )
+
+ # set candidate
+ new_package.candidate = old_version
+ old_depcache.set_candidate_ver(old_pkg, old_ver)
+ self.assertRaises(ValueError, old_depcache.set_candidate_ver, old_pkg, new_ver)
+ self.assertRaises(ValueError, new_depcache.set_candidate_ver, old_pkg, old_ver)
+ self.assertRaises(ValueError, new_depcache.set_candidate_ver, old_pkg, new_ver)
+ self.assertRaises(ValueError, new_depcache.set_candidate_ver, new_pkg, old_ver)
+ new_depcache.set_candidate_ver(new_pkg, new_ver)
+
+ @staticmethod
+ def write_status_file(packages):
+ with open(apt_pkg.config["Dir::State::Status"], "w") as fobj:
+ for package in packages:
+ print("Package:", package, file=fobj)
+ print("Status: install ok installed", file=fobj)
+ print("Priority: optional", file=fobj)
+ print("Section: admin", file=fobj)
+ print("Installed-Size: 1", file=fobj)
+ print("Maintainer: X <x@x.invalid>", file=fobj)
+ print("Architecture: all", file=fobj)
+ print("Version: 1", file=fobj)
+ print("Description: blah", file=fobj)
+ print("", file=fobj)
+
+ def test_apt_cache_reopen_is_safe_out_of_bounds(self):
+ """Check that out of bounds access is remapped correctly."""
+ with tempfile.NamedTemporaryFile() as status:
+ apt_pkg.config["Dir::Etc::SourceList"] = "/dev/null"
+ apt_pkg.config["Dir::Etc::SourceParts"] = "/dev/null"
+ apt_pkg.config["Dir::State::Status"] = status.name
+ apt_pkg.init_system()
+
+ self.write_status_file("abcdefghijklmnopqrstuvwxyz")
+ c = apt.Cache()
+ p = c["z"]
+ p_id = p.id
+ self.write_status_file("az")
+ apt_pkg.init_system()
+ c.open()
+ self.assertNotEqual(p.id, p_id)
+ self.assertLess(p.id, 2)
+ p.mark_delete()
+ self.assertEqual([p], c.get_changes())
+
+ def test_apt_cache_reopen_is_safe_out_of_bounds_no_match(self):
+ """Check that installing gone package raises correct exception"""
+ with tempfile.NamedTemporaryFile() as status:
+ apt_pkg.config["Dir::Etc::SourceList"] = "/dev/null"
+ apt_pkg.config["Dir::Etc::SourceParts"] = "/dev/null"
+ apt_pkg.config["Dir::State::Status"] = status.name
+ apt_pkg.init_system()
+
+ self.write_status_file("abcdefghijklmnopqrstuvwxyz")
+ c = apt.Cache()
+ p = c["z"]
+ p_id = p.id
+ self.write_status_file("a")
+ apt_pkg.init_system()
+ c.open()
+ self.assertEqual(p.id, p_id) # Could not be remapped
+ self.assertRaises(apt_pkg.CacheMismatchError, p.mark_delete)
+
+ def test_apt_cache_reopen_is_safe_swap(self):
+ """Check that swapping a and b does not mark the wrong package."""
+ with tempfile.NamedTemporaryFile() as status:
+ apt_pkg.config["Dir::Etc::SourceList"] = "/dev/null"
+ apt_pkg.config["Dir::Etc::SourceParts"] = "/dev/null"
+ apt_pkg.config["Dir::State::Status"] = status.name
+ apt_pkg.init_system()
+
+ self.write_status_file("abcdefghijklmnopqrstuvwxyz")
+ c = apt.Cache()
+ p = c["a"]
+ a_id = p.id
+ p_hash = hash(p)
+ set_of_p = {p}
+ self.write_status_file("baz")
+ apt_pkg.init_system()
+ c.open()
+ # b now has the same id as a in the old cache
+ self.assertEqual(c["b"].id, a_id)
+ self.assertNotEqual(p.id, a_id)
+ # Marking a should still mark a, not b.
+ p.mark_delete()
+ self.assertEqual([p], c.get_changes())
+
+ # Ensure that p can still be found in a set of it, as a test
+ # for bug https://bugs.launchpad.net/bugs/1780099
+ self.assertEqual(hash(p), p_hash)
+ self.assertIn(p, set_of_p)
+
+ def test_apt_cache_iteration_safe(self):
+ """Check that iterating does not produce different results.
+
+ This failed in 1.7.0~alpha2, because one part of the code
+ looked up packages in the weak dict using the pretty name,
+ and the other using the full name."""
+
+ with tempfile.NamedTemporaryFile() as status:
+ apt_pkg.config["Dir::Etc::SourceList"] = "/dev/null"
+ apt_pkg.config["Dir::Etc::SourceParts"] = "/dev/null"
+ apt_pkg.config["Dir::State::Status"] = status.name
+ apt_pkg.init_system()
+
+ self.write_status_file("abcdefghijklmnopqrstuvwxyz")
+
+ c = apt.Cache()
+ c["a"].mark_delete()
+ self.assertEqual([c["a"]], [p for p in c if p.marked_delete])
+
+ def test_problemresolver_keep_phased_updates(self):
+ """Check that the c++ function can be called."""
+ with tempfile.NamedTemporaryFile() as status:
+ apt_pkg.config["Dir::Etc::SourceList"] = "/dev/null"
+ apt_pkg.config["Dir::Etc::SourceParts"] = "/dev/null"
+ apt_pkg.config["Dir::State::Status"] = status.name
+ apt_pkg.init_system()
+
+ cache = apt.Cache()
+ problemresolver = apt.ProblemResolver(cache)
+ self.assertIsNone(problemresolver.keep_phased_updates())
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_aptsources.py b/tests/test_aptsources.py
new file mode 100644
index 0000000..1e04552
--- /dev/null
+++ b/tests/test_aptsources.py
@@ -0,0 +1,1573 @@
+#!/usr/bin/python3
+
+import copy
+import os
+import tempfile
+import unittest
+
+import apt_pkg
+import testcommon
+
+import aptsources.distro
+import aptsources.sourceslist
+
+
+class TestAptSources(testcommon.TestCase):
+ def setUp(self):
+ testcommon.TestCase.setUp(self)
+ if apt_pkg.config["APT::Architecture"] not in ("i386", "amd64"):
+ apt_pkg.config.set("APT::Architecture", "i386")
+ apt_pkg.config.set("Dir::Etc", os.getcwd())
+ apt_pkg.config.set("Dir::Etc::sourceparts", tempfile.mkdtemp())
+ if os.path.exists("./build/data/templates"):
+ self.templates = os.path.abspath("./build/data/templates")
+ elif os.path.exists("../build/data/templates"):
+ self.templates = os.path.abspath("../build/data/templates")
+ else:
+ self.templates = "/usr/share/python-apt/templates/"
+
+ def tearDown(self):
+ aptsources.distro._OSRelease.OS_RELEASE_FILE = (
+ aptsources.distro._OSRelease.DEFAULT_OS_RELEASE_FILE
+ )
+ if "LSB_ETC_LSB_RELEASE" in os.environ:
+ del os.environ["LSB_ETC_LSB_RELEASE"]
+
+ def testIsMirror(self):
+ """aptsources: Test mirror detection."""
+ yes = aptsources.sourceslist.is_mirror(
+ "http://archive.ubuntu.com", "http://de.archive.ubuntu.com"
+ )
+ no = aptsources.sourceslist.is_mirror(
+ "http://archive.ubuntu.com", "http://ftp.debian.org"
+ )
+ self.assertTrue(yes)
+ self.assertFalse(no)
+
+ def testSourcesListReading(self):
+ """aptsources: Test sources.list parsing."""
+ apt_pkg.config.set("Dir::Etc::sourcelist", "data/aptsources/" "sources.list")
+ sources = aptsources.sourceslist.SourcesList(True, self.templates)
+ self.assertEqual(len(sources.list), 10)
+ # test load
+ sources.list = []
+ sources.load("data/aptsources/sources.list")
+ self.assertEqual(len(sources.list), 10)
+
+ def testSourcesListReading_deb822(self):
+ """aptsources: Test sources.list parsing."""
+ apt_pkg.config.set("Dir::Etc::sourceparts", "data/aptsources/" "sources.list.d")
+ sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True)
+ self.assertEqual(len(sources.list), 5)
+ # test load
+ sources.list = []
+ sources.load("data/aptsources/sources.list.d/main.sources")
+ self.assertEqual(len(sources.list), 5)
+
+ for entry in sources.list:
+ self.assertFalse(entry.invalid)
+ self.assertFalse(entry.disabled)
+ self.assertEqual(entry.types, ["deb"])
+ self.assertEqual(entry.type, "deb")
+ self.assertEqual(entry.uris, ["http://de.archive.ubuntu.com/ubuntu/"])
+ self.assertEqual(entry.uri, "http://de.archive.ubuntu.com/ubuntu/")
+
+ self.assertEqual(sources.list[0].comps, ["main"])
+ self.assertEqual(sources.list[1].comps, ["restricted"])
+ self.assertEqual(sources.list[2].comps, ["universe"])
+ self.assertEqual(sources.list[3].comps, ["main"])
+ self.assertEqual(sources.list[4].comps, ["main"])
+
+ for entry in sources.list[:-1]:
+ self.assertIsNone(entry.trusted)
+
+ self.assertTrue(sources.list[-1].trusted)
+
+ for entry in sources.list[:-2]:
+ self.assertEqual(entry.architectures, [])
+ self.assertEqual(entry.suites, ["edgy"])
+ self.assertEqual(entry.dist, "edgy")
+
+ for entry in sources.list[-2:]:
+ self.assertEqual(entry.suites, ["natty"])
+ self.assertEqual(entry.dist, "natty")
+ self.assertEqual(entry.architectures, ["amd64", "i386"])
+
+ def testSourcesListWriting_deb822(self):
+ """aptsources: Test sources.list parsing."""
+ apt_pkg.config.set("Dir::Etc::sourceparts", "data/aptsources/" "sources.list.d")
+ sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True)
+ with tempfile.TemporaryDirectory() as tmpdir:
+ for entry in sources.list:
+ entry.file = os.path.join(tmpdir, os.path.basename(entry.file))
+
+ sources.save()
+
+ maxDiff = self.maxDiff
+ self.maxDiff = None
+ for file in os.listdir("data/aptsources/sources.list.d"):
+ with open(os.path.join("data/aptsources/sources.list.d", file)) as a:
+ with open(os.path.join(tmpdir, file)) as b:
+ self.assertEqual(a.read(), b.read(), f"file {file}")
+ self.maxDiff = maxDiff
+
+ def testSourcesListAdding(self):
+ """aptsources: Test additions to sources.list"""
+ apt_pkg.config.set("Dir::Etc::sourcelist", "data/aptsources/" "sources.list")
+ sources = aptsources.sourceslist.SourcesList(True, self.templates)
+ # test to add something that is already there (main)
+ before = copy.deepcopy(sources)
+ sources.add("deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["main"])
+ self.assertTrue(sources.list == before.list)
+ # test to add something that is already there (restricted)
+ before = copy.deepcopy(sources)
+ sources.add(
+ "deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["restricted"]
+ )
+ self.assertTrue(sources.list == before.list)
+
+ before = copy.deepcopy(sources)
+ sources.add(
+ "deb",
+ "http://de.archive.ubuntu.com/ubuntu/",
+ "natty",
+ ["main"],
+ architectures=["amd64", "i386"],
+ )
+ self.assertTrue(sources.list == before.list)
+
+ # test to add something new: multiverse
+ sources.add(
+ "deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["multiverse"]
+ )
+ found = False
+ for entry in sources:
+ if (
+ entry.type == "deb"
+ and entry.uri == "http://de.archive.ubuntu.com/ubuntu/"
+ and entry.dist == "edgy"
+ and "multiverse" in entry.comps
+ ):
+ found = True
+ break
+ self.assertTrue(found)
+
+ # add a new natty entry without architecture specification
+ sources.add(
+ "deb", "http://de.archive.ubuntu.com/ubuntu/", "natty", ["multiverse"]
+ )
+ found = False
+ for entry in sources:
+ if (
+ entry.type == "deb"
+ and entry.uri == "http://de.archive.ubuntu.com/ubuntu/"
+ and entry.dist == "natty"
+ and entry.architectures == []
+ and "multiverse" in entry.comps
+ ):
+ found = True
+ break
+ self.assertTrue(found)
+
+ # Add universe to existing multi-arch line
+ sources.add(
+ "deb",
+ "http://de.archive.ubuntu.com/ubuntu/",
+ "natty",
+ ["universe"],
+ architectures=["i386", "amd64"],
+ )
+ found = False
+ for entry in sources:
+ if (
+ entry.type == "deb"
+ and entry.uri == "http://de.archive.ubuntu.com/ubuntu/"
+ and entry.dist == "natty"
+ and set(entry.architectures) == {"amd64", "i386"}
+ and set(entry.comps) == {"main", "universe"}
+ ):
+ found = True
+ break
+ self.assertTrue(found)
+ # test to add something new: multiverse *and*
+ # something that is already there
+ before = copy.deepcopy(sources)
+ sources.add(
+ "deb",
+ "http://de.archive.ubuntu.com/ubuntu/",
+ "edgy",
+ ["universe", "something"],
+ )
+ found_universe = 0
+ found_something = 0
+ for entry in sources:
+ if (
+ entry.type == "deb"
+ and entry.uri == "http://de.archive.ubuntu.com/ubuntu/"
+ and entry.dist == "edgy"
+ ):
+ for c in entry.comps:
+ if c == "universe":
+ found_universe += 1
+ if c == "something":
+ found_something += 1
+ # print "\n".join([s.str() for s in sources])
+ self.assertEqual(found_something, 1)
+ self.assertEqual(found_universe, 1)
+
+ def testSourcesListAdding_deb822(self):
+ """aptsources: Test additions to sources.list"""
+ apt_pkg.config.set("Dir::Etc::sourceparts", "data/aptsources/" "sources.list.d")
+
+ sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True)
+ # test to add something that is already there (main)
+ before = copy.deepcopy(sources)
+ sources.add("deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["main"])
+ self.assertEqual(sources.list, before.list)
+ # test to add something that is already there (restricted)
+ before = copy.deepcopy(sources)
+ sources.add(
+ "deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["restricted"]
+ )
+ self.assertTrue(sources.list == before.list)
+
+ before = copy.deepcopy(sources)
+ sources.add(
+ "deb",
+ "http://de.archive.ubuntu.com/ubuntu/",
+ "natty",
+ ["main"],
+ architectures=["amd64", "i386"],
+ )
+ self.assertEqual(
+ [e.str() for e in sources.list], [e.str() for e in before.list]
+ )
+
+ # test to add something new: multiverse
+ sources.add(
+ "deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["multiverse"]
+ )
+ found = False
+ for entry in sources:
+ if (
+ entry.type == "deb"
+ and entry.uri == "http://de.archive.ubuntu.com/ubuntu/"
+ and entry.dist == "edgy"
+ and "multiverse" in entry.comps
+ ):
+ found = True
+ break
+ self.assertTrue(found)
+
+ # add a new natty entry without architecture specification
+ sources.add(
+ "deb", "http://de.archive.ubuntu.com/ubuntu/", "natty", ["multiverse"]
+ )
+ found = False
+ for entry in sources:
+ if (
+ entry.type == "deb"
+ and entry.uri == "http://de.archive.ubuntu.com/ubuntu/"
+ and entry.dist == "natty"
+ and entry.architectures == []
+ and "multiverse" in entry.comps
+ ):
+ found = True
+ break
+ self.assertTrue(found)
+
+ # Add universe to existing multi-arch line
+ sources.add(
+ "deb",
+ "http://de.archive.ubuntu.com/ubuntu/",
+ "natty",
+ ["universe"],
+ architectures=["i386", "amd64"],
+ )
+ found = False
+ for entry in sources:
+ if (
+ entry.type == "deb"
+ and entry.uri == "http://de.archive.ubuntu.com/ubuntu/"
+ and entry.dist == "natty"
+ and set(entry.architectures) == {"amd64", "i386"}
+ and set(entry.comps) == {"main", "universe"}
+ ):
+ found = True
+ break
+ self.assertTrue(found)
+ # test to add something new: multiverse *and*
+ # something that is already there
+ before = copy.deepcopy(sources)
+ sources.add(
+ "deb",
+ "http://de.archive.ubuntu.com/ubuntu/",
+ "edgy",
+ ["universe", "something"],
+ )
+ found_universe = 0
+ found_something = 0
+ for entry in sources:
+ if (
+ entry.type == "deb"
+ and entry.uri == "http://de.archive.ubuntu.com/ubuntu/"
+ and entry.dist == "edgy"
+ ):
+ for c in entry.comps:
+ if c == "universe":
+ found_universe += 1
+ if c == "something":
+ found_something += 1
+ # print "\n".join([s.str() for s in sources])
+ self.assertEqual(found_something, 1)
+ self.assertEqual(found_universe, 1)
+
+ def testAddingWithComment_deb822(self):
+ apt_pkg.config.set("Dir::Etc::sourceparts", "data/aptsources/" "sources.list.d")
+ self._commonTestAddingWithComment()
+
+ def testAddingWithComment_short(self):
+ apt_pkg.config.set("Dir::Etc::sourcelist", "data/aptsources/" "sources.list")
+ self._commonTestAddingWithComment()
+
+ def _commonTestAddingWithComment(self):
+ sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True)
+
+ # test to add something that is already there (main); loses comment
+ before = copy.deepcopy(sources)
+ sources.add(
+ "deb",
+ "http://de.archive.ubuntu.com/ubuntu/",
+ "edgy",
+ ["main"],
+ comment="this will be lost",
+ )
+ self.assertTrue(sources.list == before.list)
+ for entry in sources:
+ self.assertNotEqual(entry.comment, "this will be lost")
+
+ # test to add component to existing entry: multiverse; loses comment
+ sources.add(
+ "deb",
+ "http://de.archive.ubuntu.com/ubuntu/",
+ "edgy",
+ ["multiverse"],
+ comment="this will be lost",
+ )
+ for entry in sources:
+ self.assertNotEqual(entry.comment, "this will be lost")
+
+ before = copy.deepcopy(sources)
+ # test to add entirely new entry; retains comment
+ sources.add(
+ "deb-src",
+ "http://de.archive.ubuntu.com/ubuntu/",
+ "edgy",
+ ["main"],
+ comment="this will appear",
+ file=sources.list[0].file, # make sure we test the deb822 code path
+ )
+ self.assertNotEqual(sources.list, before.list)
+ self.assertEqual(len(sources.list), len(before.list) + 1)
+ found = False
+ for entry in sources:
+ if (
+ entry.type == "deb-src"
+ and entry.uri == "http://de.archive.ubuntu.com/ubuntu/"
+ and entry.dist == "edgy"
+ and entry.comment == "this will appear"
+ and "main" in entry.comps
+ ):
+ found = True
+ break
+ self.assertTrue(found)
+
+ def testInsertion_deb822(self):
+ apt_pkg.config.set("Dir::Etc::sourceparts", "data/aptsources/" "sources.list.d")
+ sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True)
+
+ # test to insert something that is already there (universe); does not
+ # move existing entry (remains at index 2)
+ before = copy.deepcopy(sources)
+ sources.add(
+ "deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["universe"], pos=0
+ )
+ self.assertTrue(sources.list == before.list)
+ entry = list(sources)[2]
+ self.assertEqual(entry.type, "deb")
+ self.assertEqual(entry.uri, "http://de.archive.ubuntu.com/ubuntu/")
+ self.assertEqual(entry.dist, "edgy")
+ self.assertIn("universe", entry.comps)
+
+ # test add component to existing entry: multiverse; does not move
+ # entry to which it is appended (remains at index 0)
+ sources.add(
+ "deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["multiverse"], pos=2
+ )
+ entry = list(sources)[0]
+ self.assertTrue(
+ entry.type == "deb"
+ and entry.uri == "http://de.archive.ubuntu.com/ubuntu/"
+ and entry.dist == "edgy"
+ and {"main", "multiverse"} <= set(entry.comps)
+ )
+
+ # test to add entirely new entry; inserted at 0
+ sources.add(
+ "deb-src", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["main"], pos=0
+ )
+ entry = list(sources)[0]
+ self.assertTrue(
+ entry.type == "deb-src"
+ and entry.uri == "http://de.archive.ubuntu.com/ubuntu/"
+ and entry.dist == "edgy"
+ and "main" in entry.comps
+ )
+
+ def testInsertion(self):
+ apt_pkg.config.set("Dir::Etc::sourcelist", "data/aptsources/" "sources.list")
+ sources = aptsources.sourceslist.SourcesList(True, self.templates)
+
+ # test to insert something that is already there (universe); does not
+ # move existing entry (remains at index 2)
+ before = copy.deepcopy(sources)
+ sources.add(
+ "deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["universe"], pos=0
+ )
+ self.assertTrue(sources.list == before.list)
+ entry = list(sources)[5]
+ self.assertTrue(
+ entry.type == "deb"
+ and entry.uri == "http://de.archive.ubuntu.com/ubuntu/"
+ and entry.dist == "edgy"
+ and "universe" in entry.comps
+ )
+
+ # test add component to existing entry: multiverse; does not move
+ # entry to which it is appended (remains at index 0)
+ sources.add(
+ "deb", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["multiverse"], pos=2
+ )
+ entry = list(sources)[1]
+ self.assertTrue(
+ entry.type == "deb"
+ and entry.uri == "http://de.archive.ubuntu.com/ubuntu/"
+ and entry.dist == "edgy"
+ and {"main", "multiverse"} <= set(entry.comps)
+ )
+
+ # test to add entirely new entry; inserted at 0
+ sources.add(
+ "deb-src", "http://de.archive.ubuntu.com/ubuntu/", "edgy", ["main"], pos=0
+ )
+ entry = list(sources)[0]
+ self.assertTrue(
+ entry.type == "deb-src"
+ and entry.uri == "http://de.archive.ubuntu.com/ubuntu/"
+ and entry.dist == "edgy"
+ and "main" in entry.comps
+ )
+
+ def testDuplication_short(self):
+ apt_pkg.config.set(
+ "Dir::Etc::sourcelist", "data/aptsources/sources.list.testDuplication"
+ )
+ return self.commonTestDuplication()
+
+ def testDuplication_deb822(self):
+ apt_pkg.config.set(
+ "Dir::Etc::sourceparts", "data/aptsources/sources.list.d.testDuplication"
+ )
+ return self.commonTestDuplication()
+
+ def commonTestDuplication(self):
+ sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True)
+ test_url = "http://ppa.launchpad.net/me/myproject/ubuntu"
+ # test to add something that is already there (enabled)
+ before = copy.deepcopy(sources)
+ sources.add("deb", test_url, "xenial", ["main"])
+ self.assertEqual(sources.list, before.list)
+ # test to add something that is already there (disabled)
+ sources.add("# deb-src", test_url, "xenial", ["main"])
+ self.assertEqual(sources.list, before.list)
+ # test to enable something that is already there
+ sources.add("deb-src", test_url, "xenial", ["main"])
+ found = False
+ self.assertEqual(len(sources.list), 2)
+ for entry in sources:
+ if (
+ entry.type == "deb-src"
+ and not entry.disabled
+ and entry.uri == test_url
+ and entry.dist == "xenial"
+ and entry.architectures == []
+ and entry.comps == ["main"]
+ ):
+ found = True
+ break
+ self.assertTrue(found)
+
+ def testMatcher_short(self):
+ """aptsources: Test matcher"""
+ apt_pkg.config.set(
+ "Dir::Etc::sourcelist", "data/aptsources/" "sources.list.testDistribution"
+ )
+ return self.commonTestMatcher()
+
+ def testMatcher_deb822(self):
+ """aptsources: Test matcher"""
+ apt_pkg.config.set(
+ "Dir::Etc::sourceparts",
+ "data/aptsources/" "sources.list.d.testDistribution",
+ )
+ return self.commonTestMatcher()
+
+ def commonTestMatcher(self):
+ """aptsources: Test matcher"""
+ sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True)
+ distro = aptsources.distro.get_distro(
+ id="Ubuntu",
+ codename="bionic",
+ description="Ubuntu 18.04 LTS",
+ release="18.04",
+ )
+ distro.get_sources(sources)
+ # test if all suits of the current distro were detected correctly
+ self.assertNotEqual(sources.list, [])
+ for s in sources:
+ if not s.template:
+ self.fail("source entry '%s' has no matcher" % s)
+
+ # Hack in a check for splitting of fields here.
+ if sources.list[-1].file.endswith(".sources"):
+ self.assertEqual(
+ sources.list[-1].uris, ["cdrom:[Ubuntu 8.04 _Hardy Heron_]"]
+ )
+ self.assertEqual(sources.list[-1].uri, "cdrom:[Ubuntu 8.04 _Hardy Heron_]")
+
+ def testMultiArch(self):
+ """aptsources: Test multi-arch parsing"""
+
+ apt_pkg.config.set("Dir::Etc::sourcelist", "data/aptsources/" "sources.list")
+ sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True)
+ assert not sources.list[8].invalid
+ assert sources.list[8].type == "deb"
+ assert sources.list[8].architectures == ["amd64", "i386"]
+ assert sources.list[8].uri == "http://de.archive.ubuntu.com/ubuntu/"
+ assert sources.list[8].dist == "natty"
+ assert sources.list[8].comps == ["main"]
+ assert sources.list[8].line.strip() == str(sources.list[8])
+ assert sources.list[8].trusted is None
+
+ def testMultiArch_deb822(self):
+ """aptsources: Test multi-arch parsing"""
+
+ apt_pkg.config.set("Dir::Etc::sourceparts", "data/aptsources/" "sources.list.d")
+ sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True)
+ assert not sources.list[3].invalid
+ assert sources.list[3].type == "deb"
+ assert sources.list[3].architectures == ["amd64", "i386"]
+ assert sources.list[3].uri == "http://de.archive.ubuntu.com/ubuntu/"
+ assert sources.list[3].dist == "natty"
+ assert sources.list[3].comps == ["main"]
+ self.assertEqual(sources.list[3].line.strip(), str(sources.list[3]))
+ self.assertIsNone(sources.list[3].trusted)
+
+ def testMultipleOptions(self):
+ """aptsources: Test multi-arch parsing"""
+
+ apt_pkg.config.set("Dir::Etc::sourcelist", "data/aptsources/" "sources.list")
+ sources = aptsources.sourceslist.SourcesList(True, self.templates)
+ assert sources.list[9].invalid is False
+ assert sources.list[9].type == "deb"
+ assert sources.list[9].architectures == ["amd64", "i386"]
+ self.assertEqual(sources.list[9].uri, "http://de.archive.ubuntu.com/ubuntu/")
+ assert sources.list[9].dist == "natty"
+ assert sources.list[9].comps == ["main"]
+ assert sources.list[9].trusted
+ assert sources.list[9].line.strip() == str(sources.list[9])
+
+ def testMultipleOptions_deb822(self):
+ """aptsources: Test multi-arch parsing"""
+
+ apt_pkg.config.set("Dir::Etc::sourceparts", "data/aptsources/" "sources.list.d")
+ sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True)
+ assert sources.list[4].invalid is False
+ assert sources.list[4].type == "deb"
+ assert sources.list[4].architectures == ["amd64", "i386"]
+ self.assertEqual(sources.list[4].uri, "http://de.archive.ubuntu.com/ubuntu/")
+ assert sources.list[4].dist == "natty"
+ assert sources.list[4].comps == ["main"]
+ assert sources.list[4].trusted
+ assert sources.list[4].line.strip() == str(sources.list[4])
+
+ def test_enable_component(self):
+ target = "./data/aptsources/sources.list.enable_comps"
+ line = "deb http://archive.ubuntu.com/ubuntu lucid main\n"
+ with open(target, "w") as target_file:
+ target_file.write(line)
+ apt_pkg.config.set("Dir::Etc::sourcelist", target)
+ sources = aptsources.sourceslist.SourcesList(True, self.templates)
+ distro = aptsources.distro.get_distro(
+ id="Ubuntu", codename="lucid", release="10.04", description="Ubuntu 10.04"
+ )
+ # and get the sources
+ distro.get_sources(sources)
+ # test enable_component
+ comp = "multiverse"
+ distro.enable_component(comp)
+ comps = set()
+ for entry in sources:
+ comps = comps.union(set(entry.comps))
+ self.assertTrue("multiverse" in comps)
+ self.assertTrue("universe" in comps)
+
+ def test_enable_component_deb822(self):
+ target = (
+ apt_pkg.config.find_dir("dir::etc::sourceparts") + "enable_comps.sources"
+ )
+ line = "Types: deb\nURIs: http://archive.ubuntu.com/ubuntu\nSuites: lucid\nComponents: main\n"
+ with open(target, "w") as target_file:
+ target_file.write(line)
+ sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True)
+ distro = aptsources.distro.get_distro(
+ id="Ubuntu", codename="lucid", release="10.04", description="Ubuntu 10.04"
+ )
+ # and get the sources
+ distro.get_sources(sources)
+ # test enable_component
+ comp = "multiverse"
+ distro.enable_component(comp)
+ comps = set()
+ for entry in sources:
+ comps = comps.union(set(entry.comps))
+ self.assertTrue("multiverse" in comps)
+ self.assertTrue("universe" in comps)
+
+ def test_enable_component_deb822_multi(self):
+ apt_pkg.config.set("Dir::Etc::sourcelist", "/dev/null")
+
+ target = (
+ apt_pkg.config.find_dir("dir::etc::sourceparts") + "enable_comps.sources"
+ )
+ line = "Types: deb\nURIs: http://archive.ubuntu.com/ubuntu\nSuites: lucid lucid-updates\nComponents: main\n"
+ with open(target, "w") as target_file:
+ target_file.write(line)
+ sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True)
+ distro = aptsources.distro.get_distro(
+ id="Ubuntu", codename="lucid", release="10.04", description="Ubuntu 10.04"
+ )
+ # and get the sources
+ distro.get_sources(sources)
+ self.assertEqual(len(distro.main_sources), 1)
+ self.assertEqual(len(sources.list), 1)
+ # test enable_component
+ comp = "multiverse"
+ distro.enable_component(comp)
+ self.assertEqual(len(sources.list), 2) # split into two
+
+ self.assertEqual(
+ "Types: deb\n"
+ "URIs: http://archive.ubuntu.com/ubuntu\n"
+ "Suites: lucid\n"
+ "Components: main multiverse universe",
+ str(sources.list[0]),
+ )
+ self.assertEqual(
+ "Types: deb\n"
+ "URIs: http://archive.ubuntu.com/ubuntu\n"
+ "Suites: lucid-updates\n"
+ "Components: main multiverse universe",
+ str(sources.list[1]),
+ )
+
+ comps = set()
+ for entry in sources:
+ comps = comps.union(set(entry.comps))
+ self.assertTrue("multiverse" in comps)
+ self.assertTrue("universe" in comps)
+
+ sources.save()
+ self.assertEqual(
+ "Types: deb\n"
+ "URIs: http://archive.ubuntu.com/ubuntu\n"
+ "Suites: lucid lucid-updates\n"
+ "Components: main multiverse universe",
+ str(sources.list[0]),
+ )
+
+ def test_enable_component_deb822_multi_mixed_origin(self):
+ apt_pkg.config.set("Dir::Etc::sourcelist", "/dev/null")
+
+ target = (
+ apt_pkg.config.find_dir("dir::etc::sourceparts") + "enable_comps.sources"
+ )
+ line = "Types: deb\nURIs: http://archive.ubuntu.com/ubuntu http://example.com/\nSuites: lucid\nComponents: main\n"
+ with open(target, "w") as target_file:
+ target_file.write(line)
+ sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True)
+ distro = aptsources.distro.get_distro(
+ id="Ubuntu", codename="lucid", release="10.04", description="Ubuntu 10.04"
+ )
+ # and get the sources
+ distro.get_sources(sources)
+ self.assertEqual(len(distro.main_sources), 2)
+ self.assertEqual(len(sources.list), 1)
+ # test enable_component
+ comp = "multiverse"
+ distro.enable_component(comp)
+ self.assertEqual(len(sources.list), 2) # split into two
+
+ self.assertEqual(
+ "Types: deb\n"
+ "URIs: http://archive.ubuntu.com/ubuntu\n"
+ "Suites: lucid\n"
+ "Components: main multiverse universe",
+ str(sources.list[0]),
+ )
+ self.assertEqual(
+ "Types: deb\n"
+ "URIs: http://example.com/\n"
+ "Suites: lucid\n"
+ "Components: main",
+ str(sources.list[1]),
+ )
+
+ sources.save()
+ self.assertEqual(
+ "Types: deb\n"
+ "URIs: http://archive.ubuntu.com/ubuntu\n"
+ "Suites: lucid\n"
+ "Components: main multiverse universe",
+ str(sources.list[0]),
+ )
+ self.assertEqual(
+ "Types: deb\n"
+ "URIs: http://example.com/\n"
+ "Suites: lucid\n"
+ "Components: main",
+ str(sources.list[1]),
+ )
+
+ def test_enable_component_deb822_multi_mixed_ultimate(self):
+ apt_pkg.config.set("Dir::Etc::sourcelist", "/dev/null")
+
+ target = (
+ apt_pkg.config.find_dir("dir::etc::sourceparts") + "enable_comps.sources"
+ )
+ line = "Types: deb deb-src\nURIs: http://archive.ubuntu.com/ubuntu http://example.com/\nSuites: lucid lucid-updates notalucid\nComponents: main\n"
+ with open(target, "w") as target_file:
+ target_file.write(line)
+ sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True)
+ distro = aptsources.distro.get_distro(
+ id="Ubuntu", codename="lucid", release="10.04", description="Ubuntu 10.04"
+ )
+ # and get the sources
+ distro.get_sources(sources)
+ self.assertEqual(len(distro.main_sources), 1)
+ self.assertEqual(len(sources.list), 1)
+ self.assertEqual(len(sources.exploded_list()), 12)
+ # test enable_component
+ comp = "multiverse"
+ distro.enable_component(comp)
+ self.assertEqual(len(sources.list), 12) # split into two
+
+ expected = []
+ for typ in "deb", "deb-src":
+ for uri in "http://archive.ubuntu.com/ubuntu", "http://example.com/":
+ for suite in "lucid", "lucid-updates", "notalucid":
+ comps = "main multiverse universe"
+ # unofficial source ends up without enablement
+ if uri == "http://example.com/" or suite == "notalucid":
+ comps = "main"
+ expected.append(
+ f"Types: {typ}\n"
+ f"URIs: {uri}\n"
+ f"Suites: {suite}\n"
+ f"Components: {comps}"
+ )
+
+ self.maxDiff = None
+ self.assertEqual(expected, list(map(str, sources.list)))
+ sources.save()
+
+ expected = [
+ "Types: deb deb-src\n"
+ "URIs: http://archive.ubuntu.com/ubuntu\n"
+ "Suites: lucid lucid-updates\n"
+ "Components: main multiverse universe",
+ # unofficial suite
+ "Types: deb deb-src\n"
+ "URIs: http://archive.ubuntu.com/ubuntu http://example.com/\n"
+ "Suites: notalucid\n"
+ "Components: main",
+ # unofficial mirror, FIXME: We'd rather merge the notalucid into here
+ "Types: deb deb-src\n"
+ "URIs: http://example.com/\n"
+ "Suites: lucid lucid-updates\n"
+ "Components: main",
+ ]
+ self.maxDiff = None
+ self.assertEqual(expected, list(map(str, sources.list)))
+
+ def test_deb822_explode(self):
+ apt_pkg.config.set("Dir::Etc::sourcelist", "/dev/null")
+ target = (
+ apt_pkg.config.find_dir("dir::etc::sourceparts") + "enable_comps.sources"
+ )
+ line = "Types: deb\nURIs: http://archive.ubuntu.com/ubuntu\nSuites: lucid\nComponents: main\n"
+ with open(target, "w") as target_file:
+ target_file.write(line)
+ sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True)
+
+ self.assertEqual(len(sources.list), 1)
+ self.assertEqual(len(sources.exploded_list()), 1)
+ self.assertIsInstance(
+ sources.exploded_list()[0], aptsources.sourceslist.Deb822SourceEntry
+ )
+
+ sources.list[0].suites += ["fakesuite"]
+ self.assertEqual(len(sources.list), 1)
+ self.assertEqual(len(sources.exploded_list()), 2)
+ self.assertIsInstance(
+ sources.exploded_list()[0], aptsources.sourceslist.ExplodedDeb822SourceEntry
+ )
+ self.assertIsInstance(
+ sources.exploded_list()[1], aptsources.sourceslist.ExplodedDeb822SourceEntry
+ )
+ self.assertEqual(sources.list[0].suites, ["lucid", "fakesuite"])
+ sources.remove(sources.exploded_list()[1])
+ self.assertEqual(len(sources.list), 1)
+ self.assertEqual(len(sources.exploded_list()), 1)
+ self.assertEqual(sources.list[0].suites, ["lucid"])
+
+ sources.list[0].types += ["deb-src"]
+ self.assertEqual(len(sources.list), 1)
+ self.assertEqual(len(sources.exploded_list()), 2)
+ self.assertIsInstance(
+ sources.exploded_list()[0], aptsources.sourceslist.ExplodedDeb822SourceEntry
+ )
+ self.assertIsInstance(
+ sources.exploded_list()[1], aptsources.sourceslist.ExplodedDeb822SourceEntry
+ )
+ self.assertEqual(sources.list[0].types, ["deb", "deb-src"])
+ sources.remove(sources.exploded_list()[1])
+ self.assertEqual(len(sources.list), 1)
+ self.assertEqual(len(sources.exploded_list()), 1)
+ self.assertEqual(sources.list[0].types, ["deb"])
+
+ sources.list[0].uris += ["http://example.com"]
+ self.assertEqual(len(sources.list), 1)
+ self.assertEqual(len(sources.exploded_list()), 2)
+ self.assertIsInstance(
+ sources.exploded_list()[0], aptsources.sourceslist.ExplodedDeb822SourceEntry
+ )
+ self.assertIsInstance(
+ sources.exploded_list()[1], aptsources.sourceslist.ExplodedDeb822SourceEntry
+ )
+ self.assertEqual(
+ sources.list[0].uris,
+ ["http://archive.ubuntu.com/ubuntu", "http://example.com"],
+ )
+ sources.remove(sources.exploded_list()[1])
+ self.assertEqual(len(sources.list), 1)
+ self.assertEqual(len(sources.exploded_list()), 1)
+ self.assertEqual(sources.list[0].uris, ["http://archive.ubuntu.com/ubuntu"])
+
+ # test setting attributes
+ sources.list[0].uris += ["http://example.com"]
+ with self.assertRaises(AttributeError):
+ sources.exploded_list()[0].types = ["does not work"]
+ with self.assertRaises(AttributeError):
+ sources.exploded_list()[0].uris = ["does not work"]
+ with self.assertRaises(AttributeError):
+ sources.exploded_list()[0].suites = ["does not work"]
+ with self.assertRaises(AttributeError):
+ sources.exploded_list()[0].doesnotexist = ["does not work"]
+
+ # test overriding
+ sources.exploded_list()[0].type = "faketype"
+ self.assertEqual(sources.list[0].type, "faketype")
+ self.assertEqual(sources.list[1].type, "deb")
+ sources.exploded_list()[0].type = "deb"
+ self.assertEqual(sources.list[0].type, "deb")
+ self.assertEqual(sources.list[1].type, "deb")
+ sources.save()
+ self.assertEqual(len(sources.list), 1)
+
+ def testDistribution_short(self):
+ """aptsources: Test distribution detection."""
+ apt_pkg.config.set(
+ "Dir::Etc::sourcelist", "data/aptsources/" "sources.list.testDistribution"
+ )
+ return self.commonTestDistribution()
+
+ def testDistribution_deb822(self):
+ """aptsources: Test distribution detection."""
+ apt_pkg.config.set(
+ "Dir::Etc::sourceparts",
+ "data/aptsources/" "sources.list.d.testDistribution",
+ )
+ return self.commonTestDistribution()
+
+ def commonTestDistribution(self):
+ """aptsources: Test distribution detection."""
+ sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True)
+ distro = aptsources.distro.get_distro(
+ id="Ubuntu",
+ codename="bionic",
+ description="Ubuntu 18.04 LTS",
+ release="18.04",
+ )
+ distro.get_sources(sources)
+ # test if all suits of the current distro were detected correctly
+ dist_templates = set()
+ for s in sources:
+ if s.template:
+ dist_templates.add(s.template.name)
+ # print dist_templates
+ for d in (
+ "hardy",
+ "hardy-security",
+ "hardy-updates",
+ "intrepid",
+ "hardy-backports",
+ ):
+ self.assertTrue(d in dist_templates)
+ # test enable
+ comp = "restricted"
+ distro.enable_component(comp)
+ found = {}
+ for entry in sources:
+ if (
+ entry.type == "deb"
+ and entry.uri == "http://de.archive.ubuntu.com/ubuntu/"
+ and "edgy" in entry.dist
+ ):
+ for c in entry.comps:
+ if c == comp:
+ if entry.dist not in found:
+ found[entry.dist] = 0
+ found[entry.dist] += 1
+ # print "".join([s.str() for s in sources])
+ for key in found:
+ self.assertEqual(found[key], 1)
+
+ # add a not-already available component
+ comp = "multiverse"
+ distro.enable_component(comp)
+ found = {}
+ for entry in sources:
+ if entry.type == "deb" and entry.template and entry.template.name == "edgy":
+ for c in entry.comps:
+ if c == comp:
+ if entry.dist not in found.has_key:
+ found[entry.dist] = 0
+ found[entry.dist] += 1
+ # print "".join([s.str() for s in sources])
+ for key in found:
+ self.assertEqual(found[key], 1)
+
+ @unittest.skip("lsb-release test broken when it was added")
+ def test_os_release_distribution(self):
+ """os-release file can be read and is_like is populated accordingly"""
+ os.environ["LSB_ETC_LSB_RELEASE"] = os.path.abspath(
+ "./data/aptsources/lsb-release"
+ )
+ aptsources.distro._OSRelease.OS_RELEASE_FILE = os.path.abspath(
+ "./data/aptsources/os-release"
+ )
+ distro = aptsources.distro.get_distro()
+ # Everything but is_like comes from lsb_release, see TODO in
+ # get_distro.
+ self.assertEqual("Ubuntu", distro.id)
+ self.assertEqual("xenial", distro.codename)
+ self.assertEqual("Ubuntu 16.04.1 LTS", distro.description)
+ self.assertEqual("16.04", distro.release)
+ self.assertEqual(["ubuntu", "debian"], distro.is_like)
+
+ def test_enable_disabled_short(self):
+ """LP: #1042916: Test enabling disabled entry."""
+ apt_pkg.config.set("Dir::Etc::sourcelist", "data/aptsources/" "sources.list")
+ return self.common_test_enable_disabled()
+
+ def test_enable_disabled_deb822(self):
+ """LP: #1042916: Test enabling disabled entry."""
+ apt_pkg.config.set("Dir::Etc::sourceparts", "data/aptsources/" "sources.list.d")
+ return self.common_test_enable_disabled()
+
+ def common_test_enable_disabled(self):
+ """LP: #1042916: Test enabling disabled entry."""
+ sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True)
+ disabled = sources.add(
+ "deb",
+ "http://fi.archive.ubuntu.com/ubuntu/",
+ "precise",
+ ["main"],
+ file=sources.list[0].file, # if we use deb822, enable deb822
+ )
+ disabled.set_enabled(False)
+ enabled = sources.add(
+ "deb",
+ "http://fi.archive.ubuntu.com/ubuntu/",
+ "precise",
+ ["main"],
+ file=sources.list[0].file, # if we use deb822, enable deb822
+ )
+ self.assertEqual(disabled, enabled)
+ self.assertFalse(disabled.disabled)
+
+ def test_duplicate_uri_with_trailing_slash_short(self):
+ """Test replacing entry with same uri except trailing slash"""
+ apt_pkg.config.set("Dir::Etc::sourcelist", "data/aptsources/" "sources.list")
+ return self.common_test_duplicate_uri_with_trailing_slash()
+
+ def test_duplicate_uri_with_trailing_slash_deb822(self):
+ """Test replacing entry with same uri except trailing slash"""
+ apt_pkg.config.set("Dir::Etc::sourceparts", "data/aptsources/" "sources.list.d")
+ return self.common_test_duplicate_uri_with_trailing_slash()
+
+ def common_test_duplicate_uri_with_trailing_slash(self):
+ """Test replacing entry with same uri except trailing slash"""
+ sources = aptsources.sourceslist.SourcesList(True, self.templates, deb822=True)
+ line_wslash = "deb http://rslash.ubuntu.com/ubuntu/ precise main"
+ line_woslash = "deb http://rslash.ubuntu.com/ubuntu precise main"
+ entry_wslash = aptsources.sourceslist.SourceEntry(line_wslash)
+ entry_woslash = aptsources.sourceslist.SourceEntry(line_woslash)
+ self.assertEqual(entry_wslash, entry_woslash)
+ count = len(sources.list)
+ sourceslist_wslash = sources.add(
+ entry_wslash.type, entry_wslash.uri, entry_wslash.dist, entry_wslash.comps
+ )
+ self.assertEqual(count + 1, len(sources.list))
+ count = len(sources.list)
+ sourceslist_woslash = sources.add(
+ entry_woslash.type,
+ entry_woslash.uri,
+ entry_woslash.dist,
+ entry_woslash.comps,
+ )
+ self.assertEqual(count, len(sources.list))
+ self.assertEqual(sourceslist_wslash, sourceslist_woslash)
+
+ def test_deb822_distro_enable_disable_component(self):
+ """Test enabling and disabling a component in the distro sources.
+
+ This ensures reasonable behavior when enabling and then disabling a component"""
+ with tempfile.NamedTemporaryFile("w", suffix=".sources") as file:
+ file.write(
+ "# main archive\n"
+ "Types: deb deb-src\n"
+ "URIs: http://archive.ubuntu.com/ubuntu/\n"
+ "Suites: noble noble-updates\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ "\n"
+ "# security\n"
+ "Types: deb deb-src\n"
+ "URIs: http://security.ubuntu.com/ubuntu/\n"
+ "Suites: noble-security\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ )
+ file.flush()
+
+ apt_pkg.config.set("Dir::Etc::sourcelist", file.name)
+ sources = aptsources.sourceslist.SourcesList(
+ True, self.templates, deb822=True
+ )
+ distro = aptsources.distro.get_distro(
+ id="Ubuntu",
+ codename="noble",
+ description="Ubuntu 24.04 LTS",
+ release="24.04",
+ )
+
+ self.assertEqual(len(sources.list), 2)
+ distro.get_sources(sources)
+ distro.enable_component("multiverse")
+ sources.save()
+
+ with open(file.name) as readonly:
+ self.maxDiff = None
+ self.assertEqual(
+ readonly.read(),
+ "# main archive\n"
+ "Types: deb deb-src\n"
+ "URIs: http://archive.ubuntu.com/ubuntu/\n"
+ "Suites: noble noble-updates\n"
+ "Components: main universe multiverse\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ "\n"
+ "# security\n"
+ "Types: deb deb-src\n"
+ "URIs: http://security.ubuntu.com/ubuntu/\n"
+ "Suites: noble-security\n"
+ "Components: main universe multiverse\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n",
+ )
+
+ # Disable it again
+ # FIXME: The child entries will no longer be valid at this point, so we have to call
+ # get_sources(), but it's not clear whether this should be considered a bug -
+ # there may have been other changes rendering entries no longer valid that distro
+ # is holding on to.
+ distro.get_sources(sources)
+ distro.disable_component("multiverse")
+ sources.save()
+
+ with open(file.name) as readonly:
+ self.maxDiff = None
+ self.assertEqual(
+ readonly.read(),
+ "# main archive\n"
+ "Types: deb deb-src\n"
+ "URIs: http://archive.ubuntu.com/ubuntu/\n"
+ "Suites: noble noble-updates\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ "\n"
+ "# security\n"
+ "Types: deb deb-src\n"
+ "URIs: http://security.ubuntu.com/ubuntu/\n"
+ "Suites: noble-security\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n",
+ )
+
+ # Disable universe as well
+ distro.get_sources(sources)
+ distro.disable_component("universe")
+ sources.save()
+
+ with open(file.name) as readonly:
+ self.maxDiff = None
+ self.assertEqual(
+ readonly.read(),
+ "# main archive\n"
+ "Types: deb deb-src\n"
+ "URIs: http://archive.ubuntu.com/ubuntu/\n"
+ "Suites: noble noble-updates\n"
+ "Components: main\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ "\n"
+ "# security\n"
+ "Types: deb deb-src\n"
+ "URIs: http://security.ubuntu.com/ubuntu/\n"
+ "Suites: noble-security\n"
+ "Components: main\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n",
+ )
+
+ def test_deb822_distro_enable_disable_component_mixed_origin(self):
+ """Test enabling and disabling a component in the distro sources, with mixed origin
+
+ Here we ensure that we still get idempotent behavior of disable after enable even if the
+ entry we were modifying also had a non-official repository in it."""
+ with tempfile.NamedTemporaryFile("w", suffix=".sources") as file:
+ file.write(
+ "# main archive\n"
+ "Types: deb deb-src\n"
+ "URIs: http://archive.ubuntu.com/ubuntu/ http://unofficial.example.com/\n"
+ "Suites: noble noble-updates\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ "\n"
+ "# security\n"
+ "Types: deb deb-src\n"
+ "URIs: http://security.ubuntu.com/ubuntu/\n"
+ "Suites: noble-security\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ )
+ file.flush()
+
+ apt_pkg.config.set("Dir::Etc::sourcelist", file.name)
+ sources = aptsources.sourceslist.SourcesList(
+ True, self.templates, deb822=True
+ )
+ distro = aptsources.distro.get_distro(
+ id="Ubuntu",
+ codename="noble",
+ description="Ubuntu 24.04 LTS",
+ release="24.04",
+ )
+
+ self.assertEqual(len(sources.list), 2)
+ distro.get_sources(sources)
+ distro.enable_component("multiverse")
+ sources.save()
+
+ with open(file.name) as readonly:
+ self.maxDiff = None
+ self.assertEqual(
+ readonly.read(),
+ "# main archive\n"
+ "Types: deb deb-src\n"
+ "URIs: http://archive.ubuntu.com/ubuntu/\n"
+ "Suites: noble noble-updates\n"
+ "Components: main universe multiverse\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ "\n"
+ "# main archive\n"
+ "Types: deb deb-src\n"
+ "URIs: http://unofficial.example.com/\n"
+ "Suites: noble noble-updates\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ "\n"
+ "# security\n"
+ "Types: deb deb-src\n"
+ "URIs: http://security.ubuntu.com/ubuntu/\n"
+ "Suites: noble-security\n"
+ "Components: main universe multiverse\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n",
+ )
+
+ # Disable it again
+ # FIXME: The child entries will no longer be valid at this point, so we have to call
+ # get_sources(), but it's not clear whether this should be considered a bug -
+ # there may have been other changes rendering entries no longer valid that distro
+ # is holding on to.
+ distro.get_sources(sources)
+ distro.disable_component("multiverse")
+ sources.save()
+
+ with open(file.name) as readonly:
+ self.maxDiff = None
+ self.assertEqual(
+ readonly.read(),
+ "# main archive\n"
+ "Types: deb deb-src\n"
+ "URIs: http://archive.ubuntu.com/ubuntu/ http://unofficial.example.com/\n"
+ "Suites: noble noble-updates\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ "\n"
+ "# security\n"
+ "Types: deb deb-src\n"
+ "URIs: http://security.ubuntu.com/ubuntu/\n"
+ "Suites: noble-security\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n",
+ )
+
+ # Disable universe too. The behaviour here is interesting: Distro only disables
+ # universe for the official source, so we end up with the non-official source split out.
+ distro.get_sources(sources)
+ distro.disable_component("universe")
+ sources.save()
+
+ with open(file.name) as readonly:
+ self.maxDiff = None
+ self.assertEqual(
+ readonly.read(),
+ "# main archive\n"
+ "Types: deb deb-src\n"
+ "URIs: http://archive.ubuntu.com/ubuntu/\n"
+ "Suites: noble noble-updates\n"
+ "Components: main\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ "\n"
+ "# main archive\n" # note it keeps the comment on the split out child
+ "Types: deb deb-src\n"
+ "URIs: http://unofficial.example.com/\n"
+ "Suites: noble noble-updates\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ "\n"
+ "# security\n"
+ "Types: deb deb-src\n"
+ "URIs: http://security.ubuntu.com/ubuntu/\n"
+ "Suites: noble-security\n"
+ "Components: main\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n",
+ )
+
+ def test_deb822_distro_enable_disable_child_source_mixed_origins(self):
+ """Test enabling and disabling a child source (proposed) in the distro sources, with mixed origin
+
+ Here we ensure that we still get idempotent behavior of disable after enable even if the
+ entry we were modifying also had a non-official repository in it."""
+ with tempfile.NamedTemporaryFile("w", suffix=".sources") as file:
+ file.write(
+ "# main archive\n"
+ "Types: deb deb-src\n"
+ "URIs: http://archive.ubuntu.com/ubuntu/ http://unofficial.example.com/\n"
+ "Suites: noble noble-updates\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ "\n"
+ "# security\n"
+ "Types: deb deb-src\n"
+ "URIs: http://security.ubuntu.com/ubuntu/\n"
+ "Suites: noble-security\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ )
+ file.flush()
+
+ apt_pkg.config.set("Dir::Etc::sourcelist", file.name)
+ sources = aptsources.sourceslist.SourcesList(
+ True, self.templates, deb822=True
+ )
+ distro = aptsources.distro.get_distro(
+ id="Ubuntu",
+ codename="noble",
+ description="Ubuntu 24.04 LTS",
+ release="24.04",
+ )
+
+ self.assertEqual(len(sources.list), 2)
+ distro.get_sources(sources)
+ distro.get_source_code = True
+ distro.add_source(dist="noble-proposed")
+
+ # FIXME: Component ordering is not stable right now
+ for entry in sources.list:
+ entry.comps = sorted(entry.comps)
+ sources.save()
+
+ with open(file.name) as readonly:
+ self.maxDiff = None
+
+ # FIXME: In an optimal world it would look like this
+ self.assertNotEqual(
+ readonly.read(),
+ "# main archive\n"
+ "Types: deb deb-src\n"
+ "URIs: http://archive.ubuntu.com/ubuntu/\n"
+ "Suites: noble noble-updates noble-proposed\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ "\n"
+ "# main archive\n"
+ "Types: deb deb-src\n"
+ "URIs: http://unofficial.example.com/\n"
+ "Suites: noble noble-updates\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ "\n"
+ "# security\n"
+ "Types: deb deb-src\n"
+ "URIs: http://security.ubuntu.com/ubuntu/\n"
+ "Suites: noble-security\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n",
+ )
+
+ with open(file.name) as readonly:
+ self.maxDiff = None
+ # Sadly our merge algorithm does not always produce optimal merges, because it merges the unofficial entry first
+ self.assertEqual(
+ readonly.read(),
+ "# main archive\n"
+ "Types: deb deb-src\n"
+ "URIs: http://archive.ubuntu.com/ubuntu/ http://unofficial.example.com/\n"
+ "Suites: noble noble-updates\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ "\n"
+ "# security\n"
+ "Types: deb deb-src\n"
+ "URIs: http://security.ubuntu.com/ubuntu/\n"
+ "Suites: noble-security\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ "\n"
+ "Types: deb deb-src\n"
+ "URIs: http://archive.ubuntu.com/ubuntu/\n"
+ "Suites: noble-proposed\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n",
+ )
+
+ # Disable it again
+ # FIXME: The child entries will no longer be valid at this point, so we have to call
+ # get_sources(), but it's not clear whether this should be considered a bug -
+ # there may have been other changes rendering entries no longer valid that distro
+ # is holding on to.
+ distro.get_sources(sources)
+ for child in distro.child_sources + distro.source_code_sources:
+ if child.dist.endswith("proposed"):
+ sources.remove(child)
+ sources.save()
+
+ with open(file.name) as readonly:
+ self.maxDiff = None
+ self.assertEqual(
+ readonly.read(),
+ "# main archive\n"
+ "Types: deb deb-src\n"
+ "URIs: http://archive.ubuntu.com/ubuntu/ http://unofficial.example.com/\n"
+ "Suites: noble noble-updates\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ "\n"
+ "# security\n"
+ "Types: deb deb-src\n"
+ "URIs: http://security.ubuntu.com/ubuntu/\n"
+ "Suites: noble-security\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n",
+ )
+
+ def test_deb822_distro_enable_disable_child_source_mixed_origins_no_source_code(
+ self,
+ ):
+ """Test enabling and disabling a child source (proposed) in the distro sources, with mixed origin
+
+ Here we ensure that we still get idempotent behavior of disable after enable even if the
+ entry we were modifying also had a non-official repository in it."""
+ with tempfile.NamedTemporaryFile("w", suffix=".sources") as file:
+ file.write(
+ "# main archive\n"
+ "Types: deb\n"
+ "URIs: http://archive.ubuntu.com/ubuntu/ http://unofficial.example.com/\n"
+ "Suites: noble noble-updates\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ "\n"
+ "# security\n"
+ "Types: deb\n"
+ "URIs: http://security.ubuntu.com/ubuntu/\n"
+ "Suites: noble-security\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ )
+ file.flush()
+
+ apt_pkg.config.set("Dir::Etc::sourcelist", file.name)
+ sources = aptsources.sourceslist.SourcesList(
+ True, self.templates, deb822=True
+ )
+ distro = aptsources.distro.get_distro(
+ id="Ubuntu",
+ codename="noble",
+ description="Ubuntu 24.04 LTS",
+ release="24.04",
+ )
+
+ self.assertEqual(len(sources.list), 2)
+ distro.get_sources(sources)
+ self.assertEqual(
+ [(s.type, s.uri, s.dist, s.comps) for s in distro.main_sources]
+ + ["separator"]
+ + [(s.type, s.uri, s.dist, s.comps) for s in distro.child_sources],
+ [
+ (
+ "deb",
+ "http://archive.ubuntu.com/ubuntu/",
+ "noble",
+ ["main", "universe"],
+ ),
+ "separator",
+ (
+ "deb",
+ "http://archive.ubuntu.com/ubuntu/",
+ "noble-updates",
+ ["main", "universe"],
+ ),
+ (
+ "deb",
+ "http://security.ubuntu.com/ubuntu/",
+ "noble-security",
+ ["main", "universe"],
+ ),
+ ],
+ )
+ distro.add_source(dist="noble-proposed")
+
+ # FIXME: Component ordering is not stable right now
+ for entry in sources.list:
+ entry.comps = sorted(entry.comps)
+ sources.save()
+
+ with open(file.name) as readonly:
+ self.maxDiff = None
+
+ # FIXME: In an optimal world it would look like this
+ self.assertNotEqual(
+ readonly.read(),
+ "# main archive\n"
+ "Types: deb\n"
+ "URIs: http://archive.ubuntu.com/ubuntu/\n"
+ "Suites: noble noble-updates noble-proposed\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ "\n"
+ "# main archive\n"
+ "Types: deb\n"
+ "URIs: http://unofficial.example.com/\n"
+ "Suites: noble noble-updates\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ "\n"
+ "# security\n"
+ "Types: deb\n"
+ "URIs: http://security.ubuntu.com/ubuntu/\n"
+ "Suites: noble-security\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n",
+ )
+
+ with open(file.name) as readonly:
+ self.maxDiff = None
+ # Sadly our merge algorithm does not always produce optimal merges, because it merges the unofficial entry first
+ self.assertEqual(
+ readonly.read(),
+ "# main archive\n"
+ "Types: deb\n"
+ "URIs: http://archive.ubuntu.com/ubuntu/ http://unofficial.example.com/\n"
+ "Suites: noble noble-updates\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ "\n"
+ "# security\n"
+ "Types: deb\n"
+ "URIs: http://security.ubuntu.com/ubuntu/\n"
+ "Suites: noble-security\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ "\n"
+ "Types: deb\n"
+ "URIs: http://archive.ubuntu.com/ubuntu/\n"
+ "Suites: noble-proposed\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n",
+ )
+
+ # Disable it again
+ # FIXME: The child entries will no longer be valid at this point, so we have to call
+ # get_sources(), but it's not clear whether this should be considered a bug -
+ # there may have been other changes rendering entries no longer valid that distro
+ # is holding on to.
+ distro.get_sources(sources)
+ for child in distro.child_sources + distro.source_code_sources:
+ if child.dist.endswith("proposed"):
+ sources.remove(child)
+ sources.save()
+
+ with open(file.name) as readonly:
+ self.maxDiff = None
+ self.assertEqual(
+ readonly.read(),
+ "# main archive\n"
+ "Types: deb\n"
+ "URIs: http://archive.ubuntu.com/ubuntu/ http://unofficial.example.com/\n"
+ "Suites: noble noble-updates\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n"
+ "\n"
+ "# security\n"
+ "Types: deb\n"
+ "URIs: http://security.ubuntu.com/ubuntu/\n"
+ "Suites: noble-security\n"
+ "Components: main universe\n"
+ "Signed-By: /usr/share/keyrings/ubuntu-archive-keyrings.gpg\n",
+ )
+
+
+if __name__ == "__main__":
+ os.chdir(os.path.dirname(__file__))
+ unittest.main()
diff --git a/tests/test_aptsources_deb822.py b/tests/test_aptsources_deb822.py
new file mode 100755
index 0000000..6a1bb61
--- /dev/null
+++ b/tests/test_aptsources_deb822.py
@@ -0,0 +1,63 @@
+#!/usr/bin/python3
+
+import io
+import os
+import tempfile
+import unittest
+
+import apt_pkg
+import testcommon
+
+import aptsources.distro
+import aptsources.sourceslist
+
+
+class TestAptSources(testcommon.TestCase):
+ def setUp(self):
+ testcommon.TestCase.setUp(self)
+ self.tempfile = tempfile.NamedTemporaryFile(suffix=".sources")
+ apt_pkg.config.set("Dir::Etc::sourcelist", self.tempfile.name)
+ apt_pkg.config.set("Dir::Etc::sourceparts", "/dev/null")
+
+ def tearDown(self):
+ self.tempfile.close()
+
+ def testEmptyDeb822(self):
+ """aptsources: Test sources.list parsing."""
+ sources = aptsources.sourceslist.SourcesList(True)
+ self.assertListEqual(sources.list, [])
+
+ def testDeb822SectionRecognizedWithoutEndLine(self):
+ """aptsources: Test sources.list parsing."""
+ section = aptsources._deb822.Section("key: value\notherkey: othervalue")
+
+ # Writing it back out gives us an extra newline at the end
+ self.assertEqual(section["key"], "value")
+ self.assertEqual(section["otherkey"], "othervalue")
+ self.assertEqual(str(section), "key: value\notherkey: othervalue\n")
+
+ file = aptsources._deb822.File(io.StringIO("key: value\notherkey: othervalue"))
+ self.assertEqual(len(file.sections), 1)
+
+ section = next(iter(file))
+ self.assertEqual(section["key"], "value")
+ self.assertEqual(section["otherkey"], "othervalue")
+ self.assertEqual(str(section), "key: value\notherkey: othervalue\n")
+
+ def testDeb822MultipleLinesSeparator(self):
+ """aptsources: Test sources.list parsing."""
+ for separator in "\n\n\n\n", "\n\n\n", "\n\n":
+ with self.subTest(f"{len(separator)} separators"):
+ file = aptsources._deb822.File(
+ io.StringIO("key: value" + separator + "otherkey: othervalue\n")
+ )
+ self.assertEqual(len(file.sections), 2)
+
+ self.assertEqual(file.sections[0]["key"], "value")
+ self.assertEqual(file.sections[1]["otherkey"], "othervalue")
+ self.assertEqual(str(file), "key: value\n\notherkey: othervalue\n")
+
+
+if __name__ == "__main__":
+ os.chdir(os.path.dirname(__file__))
+ unittest.main()
diff --git a/tests/test_aptsources_ports.py b/tests/test_aptsources_ports.py
new file mode 100644
index 0000000..234135b
--- /dev/null
+++ b/tests/test_aptsources_ports.py
@@ -0,0 +1,41 @@
+#!/usr/bin/python3
+import os
+import tempfile
+import unittest
+
+import apt_pkg
+import testcommon
+
+import aptsources.distro
+import aptsources.sourceslist
+
+
+class TestAptSourcesPorts(testcommon.TestCase):
+ """Test aptsources on ports.ubuntu.com."""
+
+ def setUp(self):
+ testcommon.TestCase.setUp(self)
+ apt_pkg.config.set("APT::Architecture", "powerpc")
+ apt_pkg.config.set("Dir::Etc", os.path.abspath("data/aptsources_ports"))
+ apt_pkg.config.set("Dir::Etc::sourceparts", tempfile.mkdtemp())
+ if os.path.exists("../build/data/templates"):
+ self.templates = os.path.abspath("../build/data/templates")
+ else:
+ self.templates = "/usr/share/python-apt/templates/"
+
+ def testMatcher(self):
+ """aptsources_ports: Test matcher."""
+ apt_pkg.config.set("Dir::Etc::sourcelist", "sources.list")
+ sources = aptsources.sourceslist.SourcesList(True, self.templates)
+ distro = aptsources.distro.get_distro("Ubuntu", "hardy", "desc", "8.04")
+ distro.get_sources(sources)
+ # test if all suits of the current distro were detected correctly
+ for s in sources:
+ if not s.line.strip() or s.line.startswith("#"):
+ continue
+ if not s.template:
+ self.fail("source entry '%s' has no matcher" % s)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_auth.py b/tests/test_auth.py
new file mode 100644
index 0000000..811cbb9
--- /dev/null
+++ b/tests/test_auth.py
@@ -0,0 +1,314 @@
+#!/usr/bin/python3
+
+import contextlib
+import errno
+import itertools
+import os
+import shutil
+import sys
+import tempfile
+import time
+import unittest
+from http.server import HTTPServer
+from http.server import SimpleHTTPRequestHandler as HTTPRequestHandler
+
+import apt_pkg
+import testcommon
+
+import apt.auth
+
+WHEEZY_KEYID = "8B48AD6246925553"
+WHEEZY_KEYDATE = "1335553717"
+WHEEZY_KEY = """-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.12 (GNU/Linux)
+
+mQINBE+a7rUBEADQiEKtLOgqiq8YY/p7IFODMqGPR+o1vtXaksie8iTOh3Vxab38
+cA3kK1iB5XYElbZ5b/x3vWiufHK2semOpn5MG2GRJUwmKxZbt3HLZiHtAadkby2l
+rnMxeIzfxcTxloxsQ02TMRalq89Xvy6P7lgedcW5ujcMR6JbE6uL1c/jNlkIPNuN
+9paZsNJWXnZ03R+NrAJLjOPUZKZRPYgIwEci2sVNA/autsJL+HuW6X8PfldvMe5h
+SdWelOoXMsZMX04JP8Efq8a09yIgKBfuXjoHJbtK0rTr9tjFKt/VM6MejLdJf4Dl
+r6Zhx2ygmjcvj+FlWFoxDlPHdqfZ6mGsKR4eWDRu3bZtalDNvhZKvecwf0KaAWVU
+M+GxkR+Ol3TsQ0tLbjbwZhWMioipR8Lsp6kZ1tLUjM0aOR3Mw/csyFJYKFiCo3GR
+QSGY0++cDrfhQRwOJ9s2eeGGS1/I95vJZA5zZnx1ksnO0W2fHVBavICR821EBAEZ
+slLzr+IOrbB16YE/aN2iA9nTcQVk69XeEh5gaeiCZ7JhA2nkAg8a/H1r4BVBC/cL
+egzhUvP90kk94MmL1D2gY6UlyK4yTnHgVfjsQw6u2sPDlramyXBZehnKabIndM1P
+368IbW8GTNo0gNwg/oC/vENwYnAuX+S96/O/1XfQoBNr+epTVdS4VQHICQARAQAB
+tEhEZWJpYW4gQXJjaGl2ZSBBdXRvbWF0aWMgU2lnbmluZyBLZXkgKDcuMC93aGVl
+enkpIDxmdHBtYXN0ZXJAZGViaWFuLm9yZz6JAj4EEwEIACgFAk+a7rUCGwMFCQ8J
+nAAGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEItIrWJGklVTdQEQAMLCmMQr
+7SxFULYgprbr5eO6uAs/8nkIBhJBzUnenOUnwsOR3Io9/sHc8Cq/xv1DTsY5G5Qj
+ojywslbeF44TxBZ0j3UwPU437bfNs7yTRkgPVhHK/rZ9ApbnZdCmud+BUkDOChLV
+8fzCZ17Pa5eMr5E4WI0bLM5AA3vVFLBgHFqJUgE7mSn95vA1S881/xOQ4lT1WHfa
+O9K96X6ekn2zpPu/G8aq+oDyVGfo1AKQCPBJ3OCX0WB3GNWbcCb850gy9vtKlWDu
+yAh1a9Cl5OPHlYqz8q+Hqj4ZeRgJiDgCgm8YAlKEooEG/vJzswaY+C3nz6uNfBeq
+60QhPfgaO8qGlriChGAFqzD68ZQ53NApJw/OuwV2p5CgnkyGAVGZ1WuYcXz/wHyU
+awnXq3Bf69RJssbab6SqptJyYuiY8T/2vWRgQxej18KAZ0v1Vr/MC1azp6TWgfSl
+s2fvGvPf9vEbKyBR3YFa5msRKGpRauv4wWmcLfZ+jMLbSAWBfILPK+fGLtRGz4AX
+hRht9rX7c4neQvlBNDDgR3tuaE3s0B1B6gTcvq7EhuuP4pAzkBLhpuzolvw+ZFOV
+5mElfScYi8QbQgT9t2XjUDU1oz1ewviNhynpsxh51t5qxP5ETDGKvEx7RMv4S08p
+5VGG4Y+kjcsQWfAdVAGuLqWOI0sGzUzKYZppiEYEExECAAYFAk+a8vAACgkQcV7W
+oH57isk7FACcCIOIMr39LUSv16Ec9V102uheqlsAnRqdAADYF7iJIrfqyb72s/54
+3JFaiQJGBBMBCAAwBQJPmvMiBxpzdHJpbmchGmh0dHA6Ly9ncGcuZ2FubmVmZi5k
+ZS9wb2xpY3kudHh0AAoJENsWz1uxJSXEhEYP/in+rib86H2vPG+ALZ35o4eh1+9P
+KLtUwgHB3Wr/rmPuPY5uB02H/p3PxgJHXUXUPAleN6uajZvReO1wWLTYspPAK8ZF
+6p52vuyHgOZl+VmGkLgYKOG/cckqQqTTaHwQj0O8pllJjOJYVdt5iWAHkf1N1UAA
+nXC2GdxV+ZVGvZjjCDL8WFWCfoY4HznslcEHQKxg7vzZvVMTjY6L+8NmWkVoD4JL
+kYtQOrId1wWYInJiQRtilyn7n9mJ+rTBSETB9Evs3x+zmNa3ntY1/U8XINgxVA5U
+GYyUfUug2DjZ90LfXyZUOXVLE5yM1x7oOpyg/1mMtl5xkmuqJHOTeVEjQBYfMRHi
+sS4ainR5AoD1Z5KV4S0opt198LDMXGLNjUdJEG24QEK5tfgTFRgFRJYiufxDelI3
+Aq5uGVRrBJygjwaQiJLUVlMqBGHJi++zeWr767pHVWB1XqdmPRvvOqH2v/ez4bSW
+zIkUDTr947qmjyAqNNmCv/jgV5viqbj5LNslBkFg8OS+6O7na2gU5ldXfBoC0nso
+3pdsCuOYUIrHyP/GjT1gvG0m+jZ/15bvoWvUv4Buh+3gYVyLwrgbq7UISRfwQEah
+yzIrO5MvgS0MTIlOgO7Lxog2XMEkQ1ZCbLu5Rvm/8LC0UlSxW9aOIKBSC3hi7U8E
+BuA24Mv5Iz7QvO+giQEcBBABAgAGBQJPmwDBAAoJEF7K+wCjrkSkkq8H/3M/M+Xb
+vI0cY3MOkFMtyG7xmxPcny1/arnQDvjvpv1BhRBnVTstMxHWzAFQf3M8KttARWo4
+C6U5Cbc0Jx6avqXZwop91a8tQORErC9Kcrr27FJfNAOP5AVzXAofpZyXvouFYBig
+ikHdRJlFrn9rydvK9Z5vg63ZzsRB7hTtHi/j1o7d0IpVmR2iTnbWGiUxpnRdLhEF
+AnUU+TDFVg6EoJ6aeKsLa43UPHizq12WZPd72cJNSLMk/u+UZvg4sa7pOrkJNYN1
+jL7BSphwKCuA8vBc2lLO14uYDO8LHjd4opatMWCEEvnJQS98JytIkYcwJhJ/IgCz
+tqAUo44SUcOodNGJAhwEEAECAAYFAk+bA/IACgkQvDciUsoc+WRWgA/9FYi1aqas
+fJyRV4pfe90KhJ4uOO17ivnjULIDU4QFSdJpkCPznxadlDeyRbX/FhVu3RMzldIu
+ZVly+VPqWwubudj9SVnqJxGkua2kEz8u3X96zif+nSB4wQuWLi4GOG9AYTnuNnZI
+hO4RctYpEi9duBsPeewNi2zjUe8akhJacMhJflbW/XGsRf4goeL3WrB+k5DiDphm
+nw2dge96uhZhM+Ih4hSoD9d+YLZbTqXX4L93jELE72UF4qnrZjYJtx8TSto9W2bj
+sGFmpUB41viFtdnABLv5MhMsvlM37w8HTbKzzCYImgzBJNZ8Wr+VAeeQ/uB+izVv
+Ls6aVKcwH2r8D+MMvh5d160lAJSUDXvZ0kdzawtBMzaNOIEYuQqoQxQGXvSAMRDV
+2xFEn/XRT4iRl1stLvX86SMpLksbBfxZnrV9Q+OfTpar5O21sb1dpkgfWoF6W0kc
+rjuAAsI3EbMuX3eK8r5SjWCLfIaU9ton+CdeJjJipEsEox7Rlq075t+6S4LL4wqq
+dJPX4Rcuwx4LPXi9NKZAuQHisp1nuVV4luXttMdYfFq5QtokhjUaedAOORDy4gsC
+mAMyLWgU/2r0grK7+AVLfn1p9wFb9FoBGFILcjVMAiY3OE5tNVPay9wGoD6n/h0O
+cteh2rBrB7kEpXjRqasNfRl8vvlz7nWhTIKJAhwEEAEIAAYFAk+bAq8ACgkQEbTl
+/xWw/YKuew/9Fub3t/nejgJ5KkjhfFppQQkE1yg2VJP3cbnrrhrAYZX6E6jN7dAI
+MlpKqm4YR6FFe5bkra61TeXd2CI5E/MDdW4Q+AD66tA0xKRm5RzVuPvWoR9vyCx/
+fPlRuVZptwczeV5bKTFyflICV3Z/R5llq2aT6M+MZdBL4AHs5yuspkYa5f8EESi6
+pTJW0sXacjRSZyznQOZ2fMKn0LZnefSWjWoAB252hS27WW9kwpniJhUOzrrLuAWF
+wnv6jfahNH14BCbNB7Q0DhcCeYnFocRv/NH8oipTrwfJ+IIMDDOcJvCbgv23w9DJ
+Ynv2BaaJrbk04jux71vhaZUC0xTkE/b+rNZGnPaFnjqWBGN3s+RVZ0SHMQUzdl73
+dH3lL98mULzmf1uD7fPIrF/EYrSvFcsV7mnpFmHOd3ApY6QugmakQOLVaIpi18N4
+hJoEPBwSQ91eriieobRhjGs7LRnfmvkuQIlsQx82eycd1IV6Gp2cqzAb1qPzcaYh
+TskU93Mj9OwmlqETB9FH7w7OvumQUjhHQCASeCGDeFJacZkwohWcxWkB0DUPWGgh
+jnsiInTBzE/+nFsUthVlkh0Bki0BLy3gOUAgldvq3apw73OCsxjd2ORdGpFvvU2v
+Xzogb+aanfTVniIfYDaJ3KHq+rF5WiVogJrK3TxsyuTAh3jFjEKNjVqJAhwEEAEI
+AAYFAk+bo7wACgkQwktlomcsixJuOg/+PZqllY05fJhC5F8UzGpHDIsrokHNAc4L
+xMgcudYoMwsK3NDxfXdKhfBgQqAsToSNpSYE4eNFcUF8yetdJbgoCWJOBIP1LCiy
+dKXpH5mKy1PCQ+2FBb1mtKiGl1nIu1hgOx29R2ATGGSpGwbgm1Q8+cpM/nRVv7Hl
+5e6uPZWkAu0MBUL9RbVSMQRpK6DUCKhLX4Loc3OS4rNjQkGnWyPtqlmU4bmRZ3R2
+INaONb4tnLkjdBhAqhgaMneEGt07nI2GBaVhdTKoI2/aDBADhuSkHomD/euiDLAF
+/gqvG6ir6akBaKiaZlDyFSAdI62gQ4DZqZF0ddGcyUfyWCgAIWxBLf6RX7yDsu5L
+uCT7ppkogHYpxjGdRlUhu9tBukZNqN1BEDbywUu2oHus+XjCr+AKThY2eglRTiVw
+SUo6KX8xBmRoo1W32pk5t9I8uMWMVc3cVh4QhqlKmcjtTJkRIVCNCXZl5JN2Uw8q
+uP6thFNCsJx6g8UwaHRXJZNKyANfe8CFGuNO0/9i8sMP/lRxmhxb5+CgZQKmCBjq
+eL/TOavRJVXbilVsU4j9OFlqx9ptGHfPlfjnIq2Bf9VWJQyS6E64ecqaqc+yqaVf
+hd0FMz9hq067VITuG50JeVnmSJK/EVjSgMvxWlSNinMgUjNetrkQTO9OQ0caAGFq
+DHcut3Yey8o=
+=id4q
+-----END PGP PUBLIC KEY BLOCK-----"""
+
+
+def normalize_key(keystr):
+ """Remove the Version: header from a key block"""
+ lines = keystr.split("\n")
+ if lines[1].startswith("Version:"):
+ return lines[:1] + lines[2:]
+ return lines
+
+
+class TestAuthKeys(testcommon.TestCase):
+
+ """Test handling of keys for signed repositories."""
+
+ def setUp(self):
+ testcommon.TestCase.setUp(self)
+
+ self.tmpdir = tempfile.mkdtemp()
+ self.addCleanup(shutil.rmtree, self.tmpdir)
+ apt_pkg.config.set("Dir", self.tmpdir)
+ apt_pkg.config.set("Dir::Bin::Apt-key", "fakeroot-apt-key")
+ apt_pkg.config.set("Dir::Etc", "etc/apt/")
+ trustedparts_dir = apt_pkg.config.find_dir("Dir::Etc::Trustedparts")
+ confparts_dir = apt_pkg.config.find_dir("Dir::Etc::parts")
+ self.assertTrue(trustedparts_dir.startswith(self.tmpdir))
+ os.makedirs(trustedparts_dir)
+ os.makedirs(confparts_dir)
+ shutil.copy("fakeroot-apt-key", self.tmpdir)
+
+ @contextlib.contextmanager
+ def _discard_stderr(self):
+ stderr_fd = sys.stderr.fileno()
+ stderr_save = os.dup(stderr_fd)
+ try:
+ devnull = os.open("/dev/null", os.O_WRONLY)
+ try:
+ os.dup2(devnull, stderr_fd)
+ yield
+ finally:
+ os.close(devnull)
+ finally:
+ os.dup2(stderr_save, stderr_fd)
+ os.close(stderr_save)
+
+ def testAddAndExportKey(self):
+ """Add an example key."""
+ apt.auth.add_key(WHEEZY_KEY)
+ # Strip the headers from the keys to avoid test errors because
+ # the exported key used a differenct GnuPG version than the
+ # original example key
+ self.assertEqual(
+ normalize_key(apt.auth.export_key(WHEEZY_KEYID)), normalize_key(WHEEZY_KEY)
+ )
+
+ def testAddAndListKey(self):
+ """Add an example key and test if it is correctly returned by
+ list_keys()
+ """
+ apt.auth.add_key(WHEEZY_KEY)
+ ret = apt.auth.list_keys()
+ self.assertEqual(len(ret), 1)
+ key = ret[0]
+ self.assertEqual(
+ key.name,
+ "Debian Archive Automatic Signing Key (7.0/wheezy) "
+ "<ftpmaster@debian.org>",
+ )
+ self.assertEqual(key.keyid, WHEEZY_KEYID)
+ self.assertEqual(key.date, WHEEZY_KEYDATE)
+
+ def testAddKeyFromFile(self):
+ """Test adding a key from file."""
+ keyfd, keyname = tempfile.mkstemp()
+ self.addCleanup(os.close, keyfd)
+ os.write(keyfd, WHEEZY_KEY.encode("UTF-8"))
+
+ apt.auth.add_key_from_file(keyname)
+
+ ret = apt.auth.list_keys()
+ self.assertEqual(len(ret), 1)
+ key = ret[0]
+ self.assertEqual(
+ key.name,
+ "Debian Archive Automatic Signing Key (7.0/wheezy) "
+ "<ftpmaster@debian.org>",
+ )
+ self.assertEqual(key.keyid, WHEEZY_KEYID)
+ self.assertEqual(key.date, WHEEZY_KEYDATE)
+
+ def test_add_key_from_keyserver_too_short(self):
+ """Ensure that short keyids are not imported"""
+ with self.assertRaises(apt.auth.AptKeyIDTooShortError):
+ apt.auth.add_key_from_keyserver(WHEEZY_KEYID, "hkp://localhost:19191")
+ with self.assertRaises(apt.auth.AptKeyIDTooShortError):
+ apt.auth.add_key_from_keyserver(
+ "0101010178F7FE5C3E65D8AF8B48AD624692555", "hkp://localhost:19191"
+ )
+ with self.assertRaises(apt.auth.AptKeyIDTooShortError):
+ apt.auth.add_key_from_keyserver(
+ "0x0101010178F7FE5C3E65D8AF8B48AD624692555", "hkp://localhost:19191"
+ )
+ with self.assertRaises(apt.auth.AptKeyIDTooShortError):
+ apt.auth.add_key_from_keyserver(
+ "0101 0101 78F7 FE5C 3E65 D8AF 8B48 AD62 4692 555",
+ "hkp://localhost:19191",
+ )
+
+ def test_add_key_from_server_mitm(self):
+ """Verify that the key fingerprint is verified after download"""
+ self._start_keyserver()
+ self.addCleanup(self._stop_keyserver)
+ with self.assertRaises(apt.auth.AptKeyError) as cm:
+ with self._discard_stderr():
+ apt.auth.add_key_from_keyserver(
+ "0101010178F7FE5C3E65D8AF8B48AD6246925553",
+ "hkp://localhost:%d" % self.keyserver_port,
+ )
+ self.assertTrue(
+ str(cm.exception).startswith(
+ "recv from 'hkp://localhost:%d' failed for '%s'"
+ % (self.keyserver_port, "0101010178F7FE5C3E65D8AF8B48AD6246925553")
+ ),
+ cm.exception,
+ )
+
+ def testAddKeyFromServer(self):
+ """Install a GnuPG key from a remote server."""
+ self._start_keyserver()
+ self.addCleanup(self._stop_keyserver)
+
+ with self._discard_stderr():
+ apt.auth.add_key_from_keyserver(
+ "0xa1bD8E9D78F7FE5C3E65D8AF8B48AD6246925553",
+ "hkp://localhost:%d" % self.keyserver_port,
+ )
+
+ ret = apt.auth.list_keys()
+ self.assertEqual(len(ret), 1)
+ key = ret[0]
+ self.assertEqual(
+ key.name,
+ "Debian Archive Automatic Signing Key (7.0/wheezy) "
+ "<ftpmaster@debian.org>",
+ )
+ self.assertEqual(key.keyid, WHEEZY_KEYID)
+ self.assertEqual(key.date, WHEEZY_KEYDATE)
+
+ def _start_keyserver(self):
+ """Start a fake keyserver on http://localhost:19191
+ If port 19191 is unavailable, try successive ports until one is.
+ Store the port actually in use in self.keyserver_port.
+ Thanks pitti.
+ """
+ dir = tempfile.mkdtemp()
+ self.addCleanup(shutil.rmtree, dir)
+ os.mkdir(os.path.join(dir, "pks"))
+ with open(os.path.join(dir, "pks", "lookup"), "w") as key_file:
+ key_file.write(WHEEZY_KEY)
+
+ keyserver_pipe = os.pipe()
+ self.keyserver_pid = os.fork()
+ if self.keyserver_pid == 0:
+ os.close(keyserver_pipe[0])
+ # quiesce server log
+ os.dup2(os.open("/dev/null", os.O_WRONLY), sys.stderr.fileno())
+ os.chdir(dir)
+ for port in itertools.count(19191):
+ try:
+ httpd = HTTPServer(("localhost", port), HTTPRequestHandler)
+ break
+ except OSError as e:
+ if e.errno != errno.EADDRINUSE:
+ raise
+ keyserver_write = os.fdopen(keyserver_pipe[1], "w")
+ print(port, file=keyserver_write)
+ keyserver_write.close()
+ httpd.serve_forever()
+ os._exit(0)
+
+ os.close(keyserver_pipe[1])
+ keyserver_read = os.fdopen(keyserver_pipe[0])
+ self.keyserver_port = int(keyserver_read.readline())
+ keyserver_read.close()
+
+ # temporarily disable proxy, as gnupg does not get along with that
+ # (LP #789049)
+ self.orig_proxy = os.environ.get("http_proxy")
+ try:
+ del os.environ["http_proxy"]
+ except KeyError:
+ pass
+
+ # wait a bit until server is ready
+ time.sleep(0.5)
+
+ def _stop_keyserver(self):
+ """Stop fake keyserver"""
+ assert self.keyserver_pid
+
+ os.kill(self.keyserver_pid, 15)
+ os.wait()
+
+ # restore proxy
+ if self.orig_proxy is not None:
+ os.environ["http_proxy"] = self.orig_proxy
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_cache_invocation.py b/tests/test_cache_invocation.py
new file mode 100644
index 0000000..a608034
--- /dev/null
+++ b/tests/test_cache_invocation.py
@@ -0,0 +1,31 @@
+#!/usr/bin/python3
+import unittest
+
+import apt_pkg
+import testcommon
+
+import apt.progress.base
+
+
+class TestCache(testcommon.TestCase):
+ """Test invocation of apt_pkg.Cache()"""
+
+ def test_wrong_invocation(self):
+ """cache_invocation: Test wrong invocation."""
+ apt_cache = apt_pkg.Cache(progress=None)
+
+ self.assertRaises(ValueError, apt_pkg.Cache, apt_cache)
+ self.assertRaises(
+ ValueError, apt_pkg.Cache, apt.progress.base.AcquireProgress()
+ )
+ self.assertRaises(ValueError, apt_pkg.Cache, 0)
+
+ def test_proper_invocation(self):
+ """cache_invocation: Test correct invocation."""
+ apt_cache = apt_pkg.Cache(progress=None)
+ apt_depcache = apt_pkg.DepCache(apt_cache)
+ self.assertNotEqual(apt_depcache, None)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_configuration.py b/tests/test_configuration.py
new file mode 100644
index 0000000..c59acfa
--- /dev/null
+++ b/tests/test_configuration.py
@@ -0,0 +1,31 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2011 Julian Andres Klode <jak@debian.org>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+"""Unit tests for verifying the correctness of apt_pkg.Configuration"""
+import unittest
+
+import apt_pkg
+import testcommon
+
+
+class TestConfiguration(testcommon.TestCase):
+ """Test various configuration things"""
+
+ def test_lp707416(self):
+ """configuration: Test empty arguments (LP: #707416)"""
+ self.assertRaises(ValueError, apt_pkg.parse_commandline, apt_pkg.config, [], [])
+ self.assertRaises(
+ SystemError,
+ apt_pkg.parse_commandline,
+ apt_pkg.config,
+ [],
+ ["cmd", "--arg0"],
+ )
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_cve_2020_27351.py b/tests/test_cve_2020_27351.py
new file mode 100644
index 0000000..1ec1c76
--- /dev/null
+++ b/tests/test_cve_2020_27351.py
@@ -0,0 +1,149 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2020 Canonical Ltd
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+"""Unit tests for verifying the correctness of DebFile descriptor handling."""
+import os
+import sys
+import unittest
+
+from test_all import get_library_dir
+
+libdir = get_library_dir()
+if libdir:
+ sys.path.insert(0, libdir)
+import gc
+import subprocess
+import tempfile
+import warnings
+
+import apt_inst
+
+
+@unittest.skipIf(not os.path.exists("/proc/self/fd"), "no /proc/self/fd available")
+class TestCVE_2020_27351(unittest.TestCase):
+ """test the debfile"""
+
+ GOOD_DEB = "data/test_debs/utf8-package_1.0-1_all.deb"
+
+ def test_success(self):
+ """opening package successfully should not leak fd"""
+ before = os.listdir("/proc/self/fd")
+ apt_inst.DebFile(self.GOOD_DEB)
+ after = os.listdir("/proc/self/fd")
+ self.assertEqual(before, after)
+
+ def test_regression_bug_977000(self):
+ """opening with a file handle should work correctly"""
+ with open(self.GOOD_DEB) as good_deb:
+ apt_inst.DebFile(good_deb).control.extractdata("control")
+
+ def test_regression_bug_977000_2(self):
+ """file object <-> debfile cycles should be collected by gc."""
+
+ class Cycle:
+ def __init__(self, fname):
+ self.file = open(fname)
+ self.deb = apt_inst.DebFile(self)
+
+ def fileno(self):
+ return self.file.fileno()
+
+ before = os.listdir("/proc/self/fd")
+ Cycle(self.GOOD_DEB).deb.control.extractdata("control")
+ warnings.filterwarnings("ignore", category=ResourceWarning)
+ gc.collect()
+ warnings.resetwarnings()
+ after = os.listdir("/proc/self/fd")
+ self.assertEqual(before, after)
+
+ def test_regression_bug_977000_2_ar(self):
+ """file object <-> debfile cycles should be collected by gc."""
+
+ class Cycle:
+ def __init__(self, fname):
+ self.file = open(fname)
+ self.deb = apt_inst.ArArchive(self)
+
+ def fileno(self):
+ return self.file.fileno()
+
+ before = os.listdir("/proc/self/fd")
+ Cycle(self.GOOD_DEB).deb.gettar("control.tar.gz", "gzip").extractdata("control")
+ warnings.filterwarnings("ignore", category=ResourceWarning)
+ gc.collect()
+ warnings.resetwarnings()
+ after = os.listdir("/proc/self/fd")
+ self.assertEqual(before, after)
+
+ def test_success_a_member(self):
+ """fd should be kept around as long as a tarfile member"""
+ before = os.listdir("/proc/self/fd")
+ data = apt_inst.DebFile(self.GOOD_DEB).data
+ after = os.listdir("/proc/self/fd")
+ self.assertEqual(len(before), len(after) - 1)
+ del data
+ after = os.listdir("/proc/self/fd")
+ self.assertEqual(before, after)
+
+ def _create_deb_without(self, member):
+ temp = tempfile.NamedTemporaryFile(mode="wb")
+ try:
+ with open(self.GOOD_DEB, "rb") as deb:
+ temp.write(deb.read())
+ temp.flush()
+ subprocess.check_call(["ar", "d", temp.name, member])
+ return temp
+ except Exception as e:
+ temp.close()
+ raise e
+
+ def test_nocontrol(self):
+ """opening package without control.tar.gz should not leak fd"""
+ before = os.listdir("/proc/self/fd")
+ with self._create_deb_without("control.tar.gz") as temp:
+ try:
+ apt_inst.DebFile(temp.name)
+ except SystemError as e:
+ self.assertIn("control.tar", str(e))
+ else:
+ self.fail("Did not raise an exception")
+
+ after = os.listdir("/proc/self/fd")
+ self.assertEqual(before, after)
+
+ def test_nodata(self):
+ """opening package without data.tar.gz should not leak fd"""
+ before = os.listdir("/proc/self/fd")
+ with self._create_deb_without("data.tar.gz") as temp:
+ try:
+ apt_inst.DebFile(temp.name)
+ except SystemError as e:
+ self.assertIn("data.tar", str(e))
+ else:
+ self.fail("Did not raise an exception")
+
+ after = os.listdir("/proc/self/fd")
+ self.assertEqual(before, after)
+
+ def test_no_debian_binary(self):
+ """opening package without debian-binary should not leak fd"""
+ before = os.listdir("/proc/self/fd")
+ with self._create_deb_without("debian-binary") as temp:
+ try:
+ apt_inst.DebFile(temp.name)
+ except SystemError as e:
+ self.assertIn("missing debian-binary", str(e))
+ else:
+ self.fail("Did not raise an exception")
+
+ after = os.listdir("/proc/self/fd")
+ self.assertEqual(before, after)
+
+
+if __name__ == "__main__":
+ # logging.basicConfig(level=logging.DEBUG)
+ unittest.main()
diff --git a/tests/test_debfile.py b/tests/test_debfile.py
new file mode 100644
index 0000000..bb65a94
--- /dev/null
+++ b/tests/test_debfile.py
@@ -0,0 +1,192 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2010 Michael Vogt <mvo@ubuntu.com>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+"""Unit tests for verifying the correctness of DebPackage in apt.debfile."""
+import logging
+import os
+import sys
+import unittest
+
+from test_all import get_library_dir
+
+libdir = get_library_dir()
+if libdir:
+ sys.path.insert(0, libdir)
+import apt_pkg
+import testcommon
+
+import apt.debfile
+
+
+class TestDebfile(testcommon.TestCase):
+ """test the debfile"""
+
+ TEST_DEBS = [
+ # conflicts with apt
+ ("gdebi-test1.deb", False),
+ # impossible dependency
+ ("gdebi-test2.deb", False),
+ # or-group (impossible-dependency|apt)
+ ("gdebi-test3.deb", True),
+ # Conflicts: apt (<= 0.1)
+ ("gdebi-test4.deb", True),
+ # Conflicts: apt (>= 0.1)
+ ("gdebi-test5.deb", False),
+ # invalid unicode in descr
+ ("gdebi-test6.deb", True),
+ # provides/conflicts against "foobarbaz"
+ ("gdebi-test7.deb", True),
+ # provides/conflicts/replaces against "mail-transport-agent"
+ # (should fails if mail-transport-agent is installed)
+ ("gdebi-test8.deb", False),
+ # provides/conflicts against real pkg
+ ("gdebi-test9.deb", True),
+ # provides debconf-tiny and the real debconf conflicts with
+ ("gdebi-test10.deb", False),
+ ]
+
+ def setUp(self):
+ testcommon.TestCase.setUp(self)
+ apt_pkg.config.set("APT::Architecture", "i386")
+ # FIXME: When run via test_all.py, the tests fail without this if it
+ # is set in the system.
+ apt_pkg.config.clear("APT::Architectures")
+ apt_pkg.config.set("Dir::State::status", "./data/test_debs/var/lib/dpkg/status")
+ apt_pkg.config.set("Dir::State::lists", "./data/test_debs/var/lib/apt/lists")
+ apt_pkg.config.set(
+ "Dir::Etc::sourcelist", "./data/test_debs/etc/apt/sources.list"
+ )
+ apt_pkg.init_system()
+ self.cache = apt.Cache()
+
+ def test_dsc_file(self):
+ filename = "hello_2.5-1.dsc"
+ deb = apt.debfile.DscSrcPackage(cache=self.cache)
+ deb.open(os.path.join("data", "test_debs", filename))
+ self.assertTrue(deb.check(), "got failure '%s'" % deb._failure_string)
+ missing = {"autotools-dev"}
+ self.assertEqual(set(deb.missing_deps), missing)
+ # specialized properties
+ self.assertEqual(deb.pkgname, "hello")
+ self.assertEqual(deb.binaries, ["hello", "bello", "cello"])
+ self.assertEqual(deb.filelist, ["hello_2.5.orig.tar.gz", "hello_2.5-1.diff.gz"])
+ self.assertEqual(deb.depends, [[("autotools-dev", "", "")]])
+ # tag fields are available as a dict
+ self.assertEqual(deb["Format"], "1.0")
+ self.assertEqual(deb["Source"], "hello")
+ self.assertEqual(deb["Binary"], "hello, bello,\n cello")
+ self.assertEqual(deb["Architecture"], "any")
+ self.assertEqual(deb["Version"], "2.5-1")
+ self.assertEqual(deb["Maintainer"], "Santiago Vila <sanvila@debian.org>")
+ self.assertEqual(deb["Homepage"], "http://www.gnu.org/software/hello")
+ self.assertEqual(deb["Standards-Version"], "3.8.4")
+
+ def test_dsc_file_with_impossible_build_dep(self):
+ filename = "impossible-build-depends_2.5-1.dsc"
+ deb = apt.debfile.DscSrcPackage(cache=self.cache)
+ deb.open(os.path.join("data", "test_debs", filename))
+ self.assertFalse(deb.check())
+ self.assertEqual(deb.depends, [[("debhelper", "101", ">")]])
+
+ def test_deb_file(self):
+ deb = apt.debfile.DebPackage(cache=self.cache)
+ for filename, expected_res in self.TEST_DEBS:
+ logging.debug(f"testing {filename}, expecting {expected_res}")
+ deb.open(os.path.join("data", "test_debs", filename))
+ res = deb.check()
+ self.assertEqual(
+ res,
+ expected_res,
+ "Unexpected result for package '%s' (got %s wanted %s)\n%s"
+ % (filename, res, expected_res, deb._failure_string),
+ )
+
+ def test_utf8_sections(self):
+ deb = apt.debfile.DebPackage(cache=self.cache)
+ deb.open(os.path.join("data", "test_debs", "utf8-package_1.0-1_all.deb"))
+ self.assertEqual(deb["Maintainer"], "Samuel Lidén Borell <samuel@slbdata.se>")
+
+ def test_content(self):
+ # normal
+ deb = apt.debfile.DebPackage(cache=self.cache)
+ deb.open(os.path.join("data", "test_debs", "gdebi-test11.deb"))
+ self.assertEqual('#!/bin/sh\necho "test"\n', deb.data_content("usr/bin/test"))
+ # binary
+ deb = apt.debfile.DebPackage(cache=self.cache)
+ deb.open(os.path.join("data", "test_debs", "gdebi-test12.deb"))
+ content = deb.data_content("usr/bin/binary")
+ self.assertTrue(
+ content.startswith("Automatically converted to printable ascii:\n\x7fELF ")
+ )
+ # control file
+ needle = """Package: gdebi-test12
+Version: 1.0
+Architecture: all
+Description: testpackage for gdebi - contains usr/bin/binary for file reading
+ This tests the binary file reading for debfile.py
+"""
+ content = deb.control_content("./control")
+ self.assertEqual(content, needle)
+ content = deb.control_content("control")
+ self.assertEqual(content, needle)
+
+ def test_xz_data(self):
+ deb = apt.debfile.DebPackage("./data/test_debs/data-tar-xz.deb")
+ self.assertEqual(deb.filelist, ["./", "usr/", "usr/bin/"])
+
+ @unittest.skipIf(
+ apt_pkg.version_compare(apt_pkg.VERSION, "0.9.15.4~") < 0,
+ "APT too old for uncompressed control.tar/data.tar",
+ )
+ def test_uncompressed_data(self):
+ deb = apt.debfile.DebPackage("./data/test_debs/data-tar.deb")
+ self.assertEqual(deb.filelist, ["./", "usr/", "usr/bin/"])
+
+ def test_check_exception(self):
+ deb = apt.debfile.DebPackage("./data/test_debs/data-tar-xz.deb")
+ self.assertRaises(AttributeError, lambda: deb.missing_deps)
+ deb.check()
+ deb.missing_deps
+
+ def test_no_supported_data_tar(self):
+ with self.assertRaises(SystemError):
+ apt.debfile.DebPackage("./data/test_debs/data-tar-broken.deb")
+
+ def test_contains(self):
+ deb = apt.debfile.DebPackage("./data/test_debs/data-tar-xz.deb")
+ self.assertTrue("Package" in deb)
+
+ def test_multi_arch_allowed(self):
+ apt_pkg.config["APT::Architectures::"] = "i386"
+ apt_pkg.config["APT::Architectures::"] = "amd64"
+ apt_pkg.config["APT::Architecture"] = "amd64"
+ apt_pkg.init_system()
+
+ allowed_any = apt.debfile.DebPackage(
+ "./data/test_debs/testdep-allowed-any_1.0-1_i386.deb"
+ )
+ self.assertTrue(allowed_any.check(), allowed_any._failure_string)
+
+ def test_multi_arch_same(self):
+ apt_pkg.config["APT::Architectures::"] = "i386"
+ apt_pkg.config["APT::Architectures::"] = "amd64"
+ apt_pkg.config["APT::Architecture"] = "amd64"
+ apt_pkg.init_system()
+ same = apt.debfile.DebPackage(
+ "./data/test_debs/testdep-same-arch_1.0-1_i386.deb"
+ )
+ self.assertTrue(same.check(), same._failure_string)
+
+ def test_get_content_gzip_data(self):
+ deb = apt.debfile.DebPackage("./data/test_debs/gdebi-test13.deb")
+ data = deb.data_content("./lala.gz")
+ self.assertEqual(data, "Automatically decompressed:\n\nlala\n")
+
+
+if __name__ == "__main__":
+ # logging.basicConfig(level=logging.DEBUG)
+ unittest.main()
diff --git a/tests/test_debfile_multiarch.py b/tests/test_debfile_multiarch.py
new file mode 100644
index 0000000..24f0265
--- /dev/null
+++ b/tests/test_debfile_multiarch.py
@@ -0,0 +1,63 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2010 Michael Vogt <mvo@ubuntu.com>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+"""Unit tests for verifying the correctness of DebPackage in apt.debfile."""
+import sys
+import unittest
+
+from test_all import get_library_dir
+
+libdir = get_library_dir()
+if libdir:
+ sys.path.insert(0, libdir)
+import apt_pkg
+import testcommon
+
+import apt
+import apt.debfile
+
+
+class TestDebfileMultiarch(testcommon.TestCase):
+ """test the multiarch debfile"""
+
+ def test_multiarch_deb_check(self):
+ if apt_pkg.get_architectures() != ["amd64", "i386"]:
+ # TODO: use unittest.skip
+ # logging.warning("skipping test because running on a "
+ # "non-multiarch system")
+ return
+ deb = apt.debfile.DebPackage("./data/test_debs/multiarch-test1_i386.deb")
+ deb.check()
+ missing = deb.missing_deps
+ # print missing
+ self.assertFalse("dpkg:i386" in missing)
+
+ @unittest.skip("BROKEN, lib3ds-1-3 is m-a now")
+ def test_multiarch_conflicts(self):
+ cache = apt.Cache()
+ # WARNING: this assumes that lib3ds-1-3 is a non-multiarch lib
+ # use "lib3ds-1-3" as a test to see if non-multiach lib conflicts work
+ canary = "lib3ds-1-3"
+ if canary not in cache:
+ # TODO: use unittest.skip
+ # logging.warning("skipping test because %s is missing" % canary)
+ return
+ cache[canary].mark_install()
+ deb = apt.debfile.DebPackage(
+ "./data/test_debs/multiarch-test1_i386.deb", cache=cache
+ )
+ # this deb should now not be installable
+ installable = deb.check()
+ # print deb._failure_string
+ self.assertFalse(installable)
+ self.assertEqual(
+ deb._failure_string, "Conflicts with the installed package 'lib3ds-1-3'"
+ )
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_deps.py b/tests/test_deps.py
new file mode 100644
index 0000000..860856c
--- /dev/null
+++ b/tests/test_deps.py
@@ -0,0 +1,142 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2010 Julian Andres Klode <jak@debian.org>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+"""Unit tests for verifying the correctness of check_dep, etc in apt_pkg."""
+import itertools
+import unittest
+
+import apt_pkg
+import testcommon
+
+import apt.package
+
+
+class TestDependencies(testcommon.TestCase):
+ def testCheckDep(self):
+ """dependencies: Test apt_pkg.CheckDep() for '<' and '>'
+
+ The CheckDep function should treat '<' as '<=' and '>' as '>=', for
+ compatibility reasons."""
+ if not hasattr(apt_pkg, "CheckDep"):
+ return
+ self.assertFalse(apt_pkg.CheckDep("1", "<", "0"))
+ self.assertTrue(apt_pkg.CheckDep("1", "<", "1"))
+ self.assertTrue(apt_pkg.CheckDep("1", "<", "2"))
+
+ self.assertFalse(apt_pkg.CheckDep("0", ">", "1"))
+ self.assertTrue(apt_pkg.CheckDep("1", ">", "1"))
+ self.assertTrue(apt_pkg.CheckDep("2", ">", "1"))
+
+ def test_check_dep(self):
+ "dependencies: Test apt_pkg.check_dep()"
+ self.assertFalse(apt_pkg.check_dep("1", "<<", "0"))
+ self.assertFalse(apt_pkg.check_dep("1", "<<", "1"))
+ self.assertTrue(apt_pkg.check_dep("1", "<<", "2"))
+
+ self.assertFalse(apt_pkg.check_dep("1", "<", "0"))
+ self.assertFalse(apt_pkg.check_dep("1", "<", "1"))
+ self.assertTrue(apt_pkg.check_dep("1", "<", "2"))
+
+ self.assertFalse(apt_pkg.check_dep("1", "<=", "0"))
+ self.assertTrue(apt_pkg.check_dep("1", "<=", "1"))
+ self.assertTrue(apt_pkg.check_dep("1", "<=", "2"))
+
+ self.assertFalse(apt_pkg.check_dep("0", "=", "1"))
+ self.assertTrue(apt_pkg.check_dep("1", "=", "1"))
+ self.assertFalse(apt_pkg.check_dep("2", "=", "1"))
+
+ self.assertFalse(apt_pkg.check_dep("0", ">=", "1"))
+ self.assertTrue(apt_pkg.check_dep("1", ">=", "1"))
+ self.assertTrue(apt_pkg.check_dep("2", ">=", "1"))
+
+ self.assertFalse(apt_pkg.check_dep("0", ">", "1"))
+ self.assertFalse(apt_pkg.check_dep("1", ">", "1"))
+ self.assertTrue(apt_pkg.check_dep("2", ">", "1"))
+
+ self.assertFalse(apt_pkg.check_dep("0", ">>", "1"))
+ self.assertFalse(apt_pkg.check_dep("1", ">>", "1"))
+ self.assertTrue(apt_pkg.check_dep("2", ">>", "1"))
+
+ def test_parse_depends_multiarch(self):
+ # strip multiarch
+ deps = apt_pkg.parse_depends("po4a:native", True)
+ self.assertEqual(deps[0][0][0], "po4a")
+ # do not strip multiarch
+ deps = apt_pkg.parse_depends("po4a:native", False)
+ self.assertEqual(deps[0][0][0], "po4a:native")
+
+ def test_parse_depends(self):
+ """dependencies: Test apt_pkg.parse_depends()"""
+ deps = apt_pkg.parse_depends("p1a (<< 1a) | p1b (>> 1b)")
+ self.assertTrue(isinstance(deps, list))
+ self.assertEqual(len(deps), 1)
+ self.assertTrue(isinstance(deps[0], list))
+ self.assertEqual(len(deps[0]), 2)
+ self.assertEqual(len(deps[0][0]), 3)
+ self.assertEqual(len(deps[0][1]), 3)
+ self.assertEqual(deps[0][0][0], "p1a")
+ self.assertEqual(deps[0][0][1], "1a")
+ self.assertEqual(deps[0][0][2], "<")
+ self.assertEqual(deps[0][1][0], "p1b")
+ self.assertEqual(deps[0][1][1], "1b")
+ self.assertEqual(deps[0][1][2], ">")
+
+ # Check that the type of comparison is parsed correctly.
+ self.assertEqual("<", apt_pkg.parse_depends("p1 (<< 1)")[0][0][2])
+ self.assertEqual("<=", apt_pkg.parse_depends("p1 (< 1)")[0][0][2])
+ self.assertEqual("<=", apt_pkg.parse_depends("p1 (<= 1)")[0][0][2])
+ self.assertEqual("=", apt_pkg.parse_depends("p1 (= 1)")[0][0][2])
+ self.assertEqual(">=", apt_pkg.parse_depends("p1 (>= 1)")[0][0][2])
+ self.assertEqual(">=", apt_pkg.parse_depends("p1 (> 1)")[0][0][2])
+ self.assertEqual(">", apt_pkg.parse_depends("p1 (>> 1)")[0][0][2])
+
+ def test_parse_src_depends(self):
+ """dependencies: Test apt_pkg.parse_src_depends()."""
+ # Check that architecture exclusion works
+ # depends_this: Current architecture is included
+ # depends_this_too: Another architecture is excluded
+ # depends_other: The current architecture is excluded
+ # depends_other: Another architecture is requested.
+ architecture = apt_pkg.config["APT::Architecture"]
+ depends_this = apt_pkg.parse_src_depends("p [%s]" % architecture)
+ depends_this_too = apt_pkg.parse_src_depends("p [!not-existing-arch]")
+ depends_other = apt_pkg.parse_src_depends("p [!%s]" % architecture)
+ depends_other_too = apt_pkg.parse_src_depends("p [not-existing-arch]")
+
+ self.assertEqual(len(depends_this), len(depends_this_too), 1)
+ self.assertEqual(len(depends_other), len(depends_other_too), 0)
+
+ def test_dstr(self):
+ """Test apt.package.BaseDependency.__dstr"""
+ dstr = apt.package.BaseDependency._BaseDependency__dstr
+ equal = {"<": {"<<", "<"}, "=": {"==", "="}, ">": {">>", ">"}}
+ operators = ["<<", "<", "<=", "!=", "=", "==", ">=", ">", ">>"]
+
+ for a, b in itertools.product(equal.keys(), operators):
+ if b in equal[a]:
+ self.assertEqual(dstr(a), b)
+ self.assertEqual(b, dstr(a))
+ else:
+ self.assertNotEqual(dstr(a), b)
+ self.assertNotEqual(b, dstr(a))
+
+ def testParseDepends(self):
+ """dependencies: Test apt_pkg.ParseDepends()."""
+ if not hasattr(apt_pkg, "ParseDepends"):
+ return
+ # Check that the type of comparison is parsed correctly.
+ self.assertEqual("<<", apt_pkg.ParseDepends("p1 (<< 1)")[0][0][2])
+ self.assertEqual("<=", apt_pkg.ParseDepends("p1 (< 1)")[0][0][2])
+ self.assertEqual("<=", apt_pkg.ParseDepends("p1 (<= 1)")[0][0][2])
+ self.assertEqual("=", apt_pkg.ParseDepends("p1 (= 1)")[0][0][2])
+ self.assertEqual(">=", apt_pkg.ParseDepends("p1 (>= 1)")[0][0][2])
+ self.assertEqual(">=", apt_pkg.ParseDepends("p1 (> 1)")[0][0][2])
+ self.assertEqual(">>", apt_pkg.ParseDepends("p1 (>> 1)")[0][0][2])
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_group.py b/tests/test_group.py
new file mode 100644
index 0000000..d08ed06
--- /dev/null
+++ b/tests/test_group.py
@@ -0,0 +1,31 @@
+import unittest
+
+import apt_pkg
+import testcommon
+
+
+class TestGroup(testcommon.TestCase):
+ def setUp(self):
+ testcommon.TestCase.setUp(self)
+ self.cache = apt_pkg.Cache(progress=None)
+
+ def test_pkgingroup(self):
+ """Check that each package belongs to the corresponding group"""
+ for pkg in self.cache.packages:
+ group = apt_pkg.Group(self.cache, pkg.name)
+ assert any(pkg.id == p.id for p in group)
+
+ def test_iteration(self):
+ """Check that iteration works correctly."""
+ for pkg in self.cache.packages:
+ group = apt_pkg.Group(self.cache, pkg.name)
+
+ list(group) == list(group)
+
+ def test_cache_groups(self):
+ """group: Iterate over all groups"""
+ assert len(list(self.cache.groups)) == self.cache.group_count
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_hashes.py b/tests/test_hashes.py
new file mode 100644
index 0000000..d322a1f
--- /dev/null
+++ b/tests/test_hashes.py
@@ -0,0 +1,206 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2009 Julian Andres Klode <jak@debian.org>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+"""Unit tests for verifying the correctness of hashsums in apt_pkg.
+
+Unit tests to verify the correctness of Hashes, HashString and the various
+functions like md5sum."""
+import hashlib
+import unittest
+import warnings
+
+import apt_pkg
+import testcommon
+
+
+class TestHashes(testcommon.TestCase):
+ """Test apt_pkg.Hashes() and the various apt_pkg.*sum() functions."""
+
+ def setUp(self):
+ """Prepare the tests, create reference values..."""
+ testcommon.TestCase.setUp(self)
+ self.file = open(apt_pkg.__file__, "rb")
+ self.value = self.file.read()
+ self.hashes = apt_pkg.Hashes(self.value)
+ self.file.seek(0)
+ self.fhashes = apt_pkg.Hashes(self.file)
+ # Reference values.
+ self.md5 = hashlib.md5(self.value).hexdigest()
+ self.sha1 = hashlib.sha1(self.value).hexdigest()
+ self.sha256 = hashlib.sha256(self.value).hexdigest()
+ self.file.seek(0)
+
+ warnings.filterwarnings("ignore", category=DeprecationWarning)
+
+ def tearDown(self):
+ """Cleanup, Close the file object used for the tests."""
+ testcommon.TestCase.tearDown(self)
+ warnings.resetwarnings()
+ self.file.close()
+
+ def test_md5sum(self):
+ """hashes: Test apt_pkg.md5sum()"""
+ self.assertEqual(apt_pkg.md5sum(self.value), self.md5)
+ self.assertEqual(apt_pkg.md5sum(self.file), self.md5)
+
+ def test_sha1sum(self):
+ """hashes: Test apt_pkg.sha1sum()"""
+ self.assertEqual(apt_pkg.sha1sum(self.value), self.sha1)
+ self.assertEqual(apt_pkg.sha1sum(self.file), self.sha1)
+
+ def test_sha256sum(self):
+ """hashes: Test apt_pkg.sha256sum()"""
+ self.assertEqual(apt_pkg.sha256sum(self.value), self.sha256)
+ self.assertEqual(apt_pkg.sha256sum(self.file), self.sha256)
+
+ def test_bytes(self):
+ """hashes: Test apt_pkg.Hashes(bytes)"""
+ self.assertEqual(self.hashes.hashes.find("md5sum").hashvalue, self.md5)
+ self.assertEqual(
+ self.hashes.hashes.find("md5sum"), apt_pkg.HashString("MD5Sum", self.md5)
+ )
+ self.assertEqual(
+ self.hashes.hashes.find("sha1"), apt_pkg.HashString("SHA1", self.sha1)
+ )
+ self.assertEqual(
+ self.hashes.hashes.find("sha256"), apt_pkg.HashString("SHA256", self.sha256)
+ )
+ self.assertRaises(KeyError, self.hashes.hashes.find, "md5")
+
+ def test_file(self):
+ """hashes: Test apt_pkg.Hashes(file)."""
+ self.assertEqual(self.fhashes.hashes.find("md5sum").hashvalue, self.md5)
+ self.assertEqual(
+ self.fhashes.hashes.find("md5sum"), apt_pkg.HashString("MD5Sum", self.md5)
+ )
+ self.assertEqual(
+ self.fhashes.hashes.find("sha1"), apt_pkg.HashString("SHA1", self.sha1)
+ )
+ self.assertEqual(
+ self.fhashes.hashes.find("sha256"),
+ apt_pkg.HashString("SHA256", self.sha256),
+ )
+
+ def test_unicode(self):
+ """hashes: Test apt_pkg.Hashes(unicode)."""
+ self.assertRaises(TypeError, apt_pkg.Hashes, "D")
+ self.assertRaises(TypeError, apt_pkg.md5sum, "D")
+ self.assertRaises(TypeError, apt_pkg.sha1sum, "D")
+ self.assertRaises(TypeError, apt_pkg.sha256sum, "D")
+
+
+class TestHashString(testcommon.TestCase):
+ """Test apt_pkg.HashString()."""
+
+ def setUp(self):
+ """Prepare the test by reading the file."""
+ testcommon.TestCase.setUp(self)
+ self.file = open(apt_pkg.__file__)
+ self.hashes = apt_pkg.Hashes(self.file)
+
+ self.md5 = self.hashes.hashes.find("md5sum")
+ self.sha1 = self.hashes.hashes.find("sha1")
+ self.sha256 = self.hashes.hashes.find("sha256")
+
+ def tearDown(self):
+ """Cleanup, Close the file object used for the tests."""
+ self.file.close()
+
+ def test_md5(self):
+ """hashes: Test apt_pkg.HashString().md5"""
+ self.assertIn("MD5Sum:", str(self.md5))
+ self.assertTrue(self.md5.verify_file(apt_pkg.__file__))
+
+ def test_sha1(self):
+ """hashes: Test apt_pkg.HashString().sha1"""
+ self.assertIn("SHA1:", str(self.sha1))
+ self.assertTrue(self.sha1.verify_file(apt_pkg.__file__))
+
+ def test_sha256(self):
+ """hashes: Test apt_pkg.HashString().sha256"""
+ self.assertIn("SHA256:", str(self.sha256))
+ self.assertTrue(self.sha256.verify_file(apt_pkg.__file__))
+
+ def test_wrong(self):
+ """hashes: Test apt_pkg.HashString(wrong_type)."""
+ self.assertRaises(TypeError, apt_pkg.HashString, 0)
+ self.assertRaises(TypeError, apt_pkg.HashString, b"")
+
+
+class TestHashStringList(testcommon.TestCase):
+ """Test apt_pkg.HashStringList()"""
+
+ def test_file_size(self):
+ hsl = apt_pkg.HashStringList()
+ self.assertEqual(hsl.file_size, 0)
+ hsl.file_size = 42
+ self.assertEqual(hsl.file_size, 42)
+ self.assertEqual(len(hsl), 1)
+
+ # Verify that I can re-assign value (this handles the long case on
+ # Python 2).
+ hsl.file_size = hsl.file_size
+
+ with self.assertRaises(OverflowError):
+ hsl.file_size = -1
+
+ hsl.file_size = 0
+
+ def test_append(self):
+ """Testing whether append works correctly."""
+ hs1 = apt_pkg.HashString("MD5Sum", "a60599e6200b60050d7a30721e3532ed")
+ hs2 = apt_pkg.HashString("SHA1", "ef113338e654b1ada807a939ad47b3a67633391b")
+
+ hsl = apt_pkg.HashStringList()
+ hsl.append(hs1)
+ hsl.append(hs2)
+ self.assertEqual(len(hsl), 2)
+ self.assertEqual(hsl[0].hashtype, "MD5Sum")
+ self.assertEqual(hsl[1].hashtype, "SHA1")
+ self.assertEqual(str(hsl[0]), str(hs1))
+ self.assertEqual(str(hsl[1]), str(hs2))
+
+ def test_find(self):
+ """Testing whether append works correctly."""
+ hs1 = apt_pkg.HashString("MD5Sum", "a60599e6200b60050d7a30721e3532ed")
+ hs2 = apt_pkg.HashString("SHA1", "ef113338e654b1ada807a939ad47b3a67633391b")
+
+ hsl = apt_pkg.HashStringList()
+ hsl.append(hs1)
+ hsl.append(hs2)
+
+ self.assertEqual(hsl.find("MD5Sum").hashtype, "MD5Sum")
+ self.assertEqual(hsl.find("SHA1").hashtype, "SHA1")
+ self.assertEqual(hsl.find().hashtype, "SHA1")
+
+ def test_verify_file(self):
+ with open(apt_pkg.__file__) as fobj:
+ hashes = apt_pkg.Hashes(fobj)
+ with warnings.catch_warnings(record=True):
+ warnings.simplefilter("always")
+ sha1 = hashes.hashes.find("sha1")
+ sha256 = hashes.hashes.find("sha256")
+
+ hsl = apt_pkg.HashStringList()
+ hsl.append(sha1)
+ hsl.append(sha256)
+
+ self.assertTrue(hsl.verify_file(apt_pkg.__file__))
+
+ md5sum = apt_pkg.HashString("MD5Sum", "a60599e6200b60050d7a30721e3532ed")
+ hsl.append(md5sum)
+
+ self.assertFalse(hsl.verify_file(apt_pkg.__file__))
+
+ hsl2 = hashes.hashes
+ self.assertIsInstance(hsl2, apt_pkg.HashStringList)
+ self.assertGreater(len(hsl2), 0)
+ self.assertTrue(hsl2.verify_file(apt_pkg.__file__))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_hashsums.py b/tests/test_hashsums.py
new file mode 100644
index 0000000..1d7cc0e
--- /dev/null
+++ b/tests/test_hashsums.py
@@ -0,0 +1,106 @@
+#!/usr/bin/python3
+
+import unittest
+import warnings
+
+import apt_pkg
+import testcommon
+
+
+class testHashes(testcommon.TestCase):
+ "test the hashsum functions against strings and files"
+
+ DATA_PATH = "data/hashsums/hashsum_test.data"
+ DATA_WITH_ZERO_PATH = "data/hashsums/hashsum_test_with_zero.data"
+
+ def setUp(self):
+ testcommon.TestCase.setUp(self)
+ warnings.filterwarnings("ignore", category=DeprecationWarning)
+
+ def tearDown(self):
+ testcommon.TestCase.tearDown(self)
+ warnings.resetwarnings()
+
+ def testMD5(self):
+ # simple
+ s = b"foo"
+ s_md5 = "acbd18db4cc2f85cedef654fccc4a4d8"
+ res = apt_pkg.md5sum(s)
+ self.assertEqual(res, s_md5)
+ # file
+ with open(self.DATA_PATH) as fobj:
+ self.assertEqual(apt_pkg.md5sum(fobj), s_md5)
+ # with zero (\0) in the string
+ s = b"foo\0bar"
+ s_md5 = "f6f5f8cd0cb63668898ba29025ae824e"
+ res = apt_pkg.md5sum(s)
+ self.assertEqual(res, s_md5)
+ # file
+ with open(self.DATA_WITH_ZERO_PATH) as fobj:
+ self.assertEqual(apt_pkg.md5sum(fobj), s_md5)
+
+ def testSHA1(self):
+ # simple
+ s = b"foo"
+ s_hash = "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"
+ res = apt_pkg.sha1sum(s)
+ self.assertEqual(res, s_hash)
+ # file
+ with open(self.DATA_PATH) as fobj:
+ self.assertEqual(apt_pkg.sha1sum(fobj), s_hash)
+ # with zero (\0) in the string
+ s = b"foo\0bar"
+ s_hash = "e2c300a39311a2dfcaff799528415cb74c19317f"
+ res = apt_pkg.sha1sum(s)
+ self.assertEqual(res, s_hash)
+ # file
+ with open(self.DATA_WITH_ZERO_PATH) as fobj:
+ self.assertEqual(apt_pkg.sha1sum(fobj), s_hash)
+
+ def testSHA256(self):
+ # simple
+ s = b"foo"
+ s_hash = "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"
+ res = apt_pkg.sha256sum(s)
+ self.assertEqual(res, s_hash)
+ # file
+ with open(self.DATA_PATH) as fobj:
+ self.assertEqual(apt_pkg.sha256sum(fobj), s_hash)
+ # with zero (\0) in the string
+ s = b"foo\0bar"
+ s_hash = "d6b681bfce7155d44721afb79c296ef4f0fa80a9dd6b43c5cf74dd0f64c85512"
+ res = apt_pkg.sha256sum(s)
+ self.assertEqual(res, s_hash)
+ # file
+ with open(self.DATA_WITH_ZERO_PATH) as fobj:
+ self.assertEqual(apt_pkg.sha256sum(fobj), s_hash)
+
+ def testSHA512(self):
+ # simple
+ s = b"foo"
+ s_hash = (
+ "f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d"
+ "0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19"
+ "594a7eb539453e1ed7"
+ )
+ res = apt_pkg.sha512sum(s)
+ self.assertEqual(res, s_hash)
+ # file
+ with open(self.DATA_PATH) as fobj:
+ self.assertEqual(apt_pkg.sha512sum(fobj), s_hash)
+ # with zero (\0) in the string
+ s = b"foo\0bar"
+ s_hash = (
+ "8c5e791db8f6bfb40eba884f70c9ac52231f01a393e4e55b4576d45"
+ "9a827f34f77e41e7fac806724517b9e96bb42387c5f9bbf325d2f99"
+ "ed52a4aa6abebc3350"
+ )
+ res = apt_pkg.sha512sum(s)
+ self.assertEqual(res, s_hash)
+ # file
+ with open(self.DATA_WITH_ZERO_PATH) as fobj:
+ self.assertEqual(apt_pkg.sha512sum(fobj), s_hash)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_install_progress_exec.py b/tests/test_install_progress_exec.py
new file mode 100644
index 0000000..064eb81
--- /dev/null
+++ b/tests/test_install_progress_exec.py
@@ -0,0 +1,43 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2019 Colomban Wendling <cwendling@hypra.fr>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+"""Unit tests for verifying InstallProgress works when spawning dpkg directly
+(i.e. when installing standalone .debs)."""
+import os
+import sys
+import unittest
+
+from test_all import get_library_dir
+
+libdir = get_library_dir()
+if libdir:
+ sys.path.insert(0, libdir)
+import testcommon
+
+from apt.progress.base import InstallProgress
+
+
+class RunHelper:
+ def __init__(self):
+ self.script = "helper_install_progress_run.py"
+
+ def do_install(self, fd):
+ return os.spawnl(os.P_WAIT, self.script, self.script, str(fd))
+
+
+class TestInstallProgressExec(testcommon.TestCase):
+ """test that InstallProgress.run() passes a valid file descriptor to
+ a child process"""
+
+ def test_run(self):
+ with InstallProgress() as prog:
+ self.assertEqual(prog.run(RunHelper()), 0)
+
+
+if __name__ == "__main__":
+ os.chdir(os.path.dirname(__file__))
+ unittest.main()
diff --git a/tests/test_large_file.py b/tests/test_large_file.py
new file mode 100644
index 0000000..87bc9b6
--- /dev/null
+++ b/tests/test_large_file.py
@@ -0,0 +1,25 @@
+#!/usr/bin/python3
+
+import sys
+import unittest
+
+import apt_inst
+import testcommon
+
+IS_NOT_32BIT = sys.maxsize > 2**32
+
+
+@unittest.skipIf(IS_NOT_32BIT, "Large File support is for 32 bit systems")
+class testHashes(testcommon.TestCase):
+ "test the hashsum functions against strings and files"
+
+ LARGE_PACKAGE_CONTENT = "data/test_debs/large-package-content_1.0_all.deb"
+
+ def testExtractData(self):
+ deb = apt_inst.DebFile(self.LARGE_PACKAGE_CONTENT)
+
+ self.assertRaises(MemoryError, deb.data.extractdata, "large-file")
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_lfs.py b/tests/test_lfs.py
new file mode 100644
index 0000000..d82e762
--- /dev/null
+++ b/tests/test_lfs.py
@@ -0,0 +1,19 @@
+#!/usr/bin/python3
+import unittest
+
+import apt_pkg
+import testcommon
+
+
+class TestLargeFileSupport(testcommon.TestCase):
+ """Test large file support"""
+
+ def test_acquire_file(self):
+ """Test apt_pkg.AcquireFile() accepts large file size"""
+ acq = apt_pkg.Acquire()
+ fil = apt_pkg.AcquireFile(acq, "http://foo", "foo", size=2875204834)
+ self.assertEqual(fil.filesize, 2875204834)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_lp659438.py b/tests/test_lp659438.py
new file mode 100644
index 0000000..21ad061
--- /dev/null
+++ b/tests/test_lp659438.py
@@ -0,0 +1,80 @@
+#!/usr/bin/python3
+"""Regression test for LP: #981896, LP: #659438"""
+# Copyright (C) 2012 Sebastian Heinlein <devel@glatzor.de>
+#
+# Licensed under the GNU General Public License Version 2
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# Licensed under the GNU General Public License Version 2
+
+__author__ = "Sebastian Heinlein <devel@glatzor.de>"
+
+import os
+import shutil
+import tempfile
+import unittest
+
+import apt_pkg
+import testcommon
+
+import apt
+
+
+class RegressionTestCase(testcommon.TestCase):
+
+ """Test suite for LP: #981896, LP: #659438
+ 'Cannot locate a file for package X'
+ """
+
+ def setUp(self):
+ testcommon.TestCase.setUp(self)
+ apt_pkg.config.clear("APT::Update::Post-Invoke")
+ apt_pkg.config.clear("APT::Update::Post-Invoke-Success")
+ self.chroot_path = chroot_path = tempfile.mkdtemp()
+ # Create a damaged status file
+ self.cache = apt.cache.Cache(rootdir=chroot_path)
+ with open(apt_pkg.config.find_file("Dir::State::status"), "a") as status:
+ status.write(
+ """Package: abrowser
+Status: install reinstreq half-installed
+Priority: optional
+Section: admin
+Version: 3.6.9+build1+nobinonly-0ubuntu1
+Architecture: all"""
+ )
+ sources_list_path = apt_pkg.config.find_file("Dir::Etc::sourcelist")
+ repo_path = os.path.abspath("./data/test-repo")
+ with open(sources_list_path, "w") as sources_list:
+ sources_list.write("deb [allow-insecure=yes] copy:%s /\n" % repo_path)
+ # os.makedirs(os.path.join(chroot_path, "etc/apt/sources.list.d/"))
+ self.cache.update(sources_list=sources_list_path)
+ self.cache.open()
+
+ def tearDown(self):
+ # this resets the rootdir apt_pkg.config to ensure it does not
+ # "pollute" the later tests
+ apt.cache.Cache(rootdir="/")
+ shutil.rmtree(self.chroot_path)
+
+ def test_survive_reqreinst(self):
+ """Test that we survive a package in require reinstallation state"""
+ # this should be 82324L but python3.2 gets unhappy about the "L"
+ self.assertEqual(self.cache.required_download, 82324)
+
+
+if __name__ == "__main__":
+ unittest.main()
+
+# vim: ts=4 et sts=4
diff --git a/tests/test_paths.py b/tests/test_paths.py
new file mode 100644
index 0000000..4920a25
--- /dev/null
+++ b/tests/test_paths.py
@@ -0,0 +1,158 @@
+#
+# Test that both unicode and bytes path names work
+#
+import os
+import shutil
+import unittest
+
+import apt_inst
+import apt_pkg
+import testcommon
+
+
+class TestPath(testcommon.TestCase):
+ dir_unicode = "data/tmp"
+ dir_bytes = b"data/tmp"
+ file_unicode = "data/tmp/python-apt-test"
+ file_bytes = b"data/tmp/python-apt-test"
+
+ def setUp(self):
+ testcommon.TestCase.setUp(self)
+ if os.path.exists(self.dir_bytes):
+ shutil.rmtree(self.dir_bytes)
+
+ os.mkdir(self.dir_bytes)
+
+ def tearDown(self):
+ apt_pkg.config["dir"] = "/"
+ shutil.rmtree(self.dir_bytes)
+
+ def test_acquire(self):
+ apt_pkg.AcquireFile(
+ apt_pkg.Acquire(),
+ "http://example.com",
+ destdir=self.file_bytes,
+ destfile=self.file_bytes,
+ )
+ apt_pkg.AcquireFile(
+ apt_pkg.Acquire(),
+ "http://example.com",
+ destdir=self.file_unicode,
+ destfile=self.file_unicode,
+ )
+
+ def test_acquire_hashes(self):
+ hs = apt_pkg.HashString("d41d8cd98f00b204e9800998ecf8427e")
+ hsl = apt_pkg.HashStringList()
+ hsl.append(hs)
+ apt_pkg.AcquireFile(
+ apt_pkg.Acquire(),
+ "http://example.com",
+ hash=hsl,
+ destdir=self.file_unicode,
+ destfile=self.file_unicode,
+ )
+ apt_pkg.AcquireFile(
+ apt_pkg.Acquire(),
+ "http://example.com",
+ hash=str(hs),
+ destdir=self.file_unicode,
+ destfile=self.file_unicode,
+ )
+ self.assertRaises(
+ TypeError,
+ apt_pkg.AcquireFile,
+ apt_pkg.Acquire(),
+ "http://example.com",
+ hash=hs,
+ destdir=self.file_unicode,
+ destfile=self.file_unicode,
+ )
+
+ def test_ararchive(self):
+ archive = apt_inst.ArArchive("data/test_debs/data-tar-xz.deb")
+
+ apt_inst.ArArchive(b"data/test_debs/data-tar-xz.deb")
+
+ archive.extract("debian-binary", "data/tmp")
+ archive.extract(b"debian-binary", b"data/tmp")
+ archive.extractall("data/tmp")
+ archive.extractall(b"data/tmp")
+ self.assertEqual(archive.extractdata("debian-binary"), b"2.0\n")
+ self.assertEqual(archive.extractdata(b"debian-binary"), b"2.0\n")
+ self.assertTrue(archive.getmember("debian-binary"))
+ self.assertTrue(archive.getmember(b"debian-binary"))
+ self.assertTrue("debian-binary" in archive)
+ self.assertTrue(b"debian-binary" in archive)
+ self.assertTrue(archive[b"debian-binary"])
+ self.assertTrue(archive["debian-binary"])
+
+ tar = archive.gettar("control.tar.xz", "xz")
+ tar = archive.gettar(b"control.tar.xz", "xz")
+
+ tar.extractall(self.dir_unicode)
+ tar.extractall(self.dir_bytes)
+ self.assertRaises(LookupError, tar.extractdata, "Do-not-exist")
+ self.assertRaises(LookupError, tar.extractdata, b"Do-not-exist")
+ tar.extractdata(b"control")
+ tar.extractdata("control")
+
+ apt_inst.TarFile(os.path.join(self.dir_unicode, "control.tar.xz"))
+ apt_inst.TarFile(os.path.join(self.dir_bytes, b"control.tar.xz"))
+
+ def test_configuration(self):
+ with open(self.file_unicode, "w") as config:
+ config.write("Hello { World 1; };")
+ apt_pkg.read_config_file(apt_pkg.config, self.file_bytes)
+ apt_pkg.read_config_file(apt_pkg.config, self.file_unicode)
+ apt_pkg.read_config_file_isc(apt_pkg.config, self.file_bytes)
+ apt_pkg.read_config_file_isc(apt_pkg.config, self.file_unicode)
+ apt_pkg.read_config_dir(apt_pkg.config, self.dir_unicode)
+ apt_pkg.read_config_dir(apt_pkg.config, b"/etc/apt/apt.conf.d")
+
+ def test_index_file(self):
+ apt_pkg.config["dir"] = "data/test_debs"
+ slist = apt_pkg.SourceList()
+ slist.read_main_list()
+
+ for meta in slist.list:
+ for index in meta.index_files:
+ index.archive_uri(self.file_bytes)
+ index.archive_uri(self.file_unicode)
+
+ def test_lock(self):
+ apt_pkg.get_lock(self.file_unicode, True)
+ apt_pkg.get_lock(self.file_bytes, True)
+
+ with apt_pkg.FileLock(self.file_unicode):
+ pass
+ with apt_pkg.FileLock(self.file_bytes):
+ pass
+
+ def test_policy(self):
+ apt_pkg.config["dir"] = "data/test_debs"
+ cache = apt_pkg.Cache(None)
+ policy = apt_pkg.Policy(cache)
+ file_unicode = os.path.join(self.dir_unicode, "test.prefs")
+ file_bytes = os.path.join(self.dir_bytes, b"test.prefs")
+
+ self.assertTrue(policy.read_pinfile(file_unicode))
+ self.assertTrue(policy.read_pinfile(file_bytes))
+ self.assertTrue(policy.read_pindir(self.dir_unicode))
+ self.assertTrue(policy.read_pindir(self.dir_bytes))
+
+ def test_tag(self):
+ with open(self.file_bytes, "w") as tag:
+ tag.write("Key: value\n")
+ tag1 = apt_pkg.TagFile(self.file_unicode)
+ tag2 = apt_pkg.TagFile(self.file_bytes)
+
+ self.assertEqual(next(tag1)["Key"], "value")
+ self.assertEqual(next(tag2)["Key"], "value")
+
+ self.assertRaises(StopIteration, next, tag1)
+ self.assertRaises(StopIteration, next, tag2)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_pep484.py b/tests/test_pep484.py
new file mode 100644
index 0000000..01711dc
--- /dev/null
+++ b/tests/test_pep484.py
@@ -0,0 +1,28 @@
+#!/usr/bin/python3
+
+import os
+import subprocess
+import unittest
+
+
+def hasMyPy():
+ try:
+ subprocess.check_call(["mypy", "--version"])
+ except Exception:
+ return False
+ return True
+
+
+class PackagePep484TestCase(unittest.TestCase):
+ @unittest.skipIf(not hasMyPy(), "no mypy available")
+ def test_pep484_clean(self):
+ # FIXME: check all of it
+ top_src_dir = os.path.join(os.path.dirname(__file__), "..", "apt")
+ os.environ["MYPYPATH"] = os.path.join(
+ os.path.dirname(__file__), "..", "typehinting"
+ )
+ self.assertEqual(subprocess.call(["mypy", "--strict", top_src_dir]), 0)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_policy.py b/tests/test_policy.py
new file mode 100644
index 0000000..ad0032c
--- /dev/null
+++ b/tests/test_policy.py
@@ -0,0 +1,70 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2012 Michael Vogt <mvo@ubuntu.com>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+
+import unittest
+
+import apt_pkg
+import testcommon
+
+import apt
+
+
+class TestAptPolicy(testcommon.TestCase):
+ def test_apt_policy_lowlevel(self):
+ return # TODO: Make tests independent of system state
+ # get a policy
+ cache = apt.Cache()
+ policy = cache._depcache.policy
+ self.assertNotEqual(policy, None)
+ # basic tests
+ pkg = cache["apt"]
+ self.assertEqual(policy.get_priority(pkg._pkg), 0)
+ # get priority for all pkgfiles
+ for ver in pkg.versions:
+ lowlevel_ver = ver._cand
+ for pkgfile, i in lowlevel_ver.file_list:
+ # print pkgfile, i, policy.get_priority(pkgfile)
+ self.assertTrue(policy.get_priority(pkgfile) >= 1)
+ self.assertTrue(policy.get_priority(pkgfile) < 1001)
+
+ def test_apt_policy_lowlevel_files(self):
+ cache = apt_pkg.Cache()
+ depcache = apt_pkg.DepCache(cache)
+ policy = cache.policy
+ dpolicy = depcache.policy
+ self.assertNotEqual(policy, None)
+ self.assertNotEqual(dpolicy, None)
+
+ for f in cache.file_list:
+ policy.get_priority(f)
+ dpolicy.get_priority(f)
+
+ def test_apt_policy_lowlevel_versions(self):
+ cache = apt_pkg.Cache()
+ depcache = apt_pkg.DepCache(cache)
+ policy = cache.policy
+ dpolicy = depcache.policy
+ self.assertNotEqual(policy, None)
+ self.assertNotEqual(dpolicy, None)
+
+ for pkg in cache.packages:
+ for ver in pkg.version_list:
+ policy.get_priority(ver)
+ dpolicy.get_priority(ver)
+
+ def test_apt_policy_highlevel(self):
+ return # TODO: Make tests independent of system state
+ cache = apt.Cache()
+ pkg = cache["apt"]
+ self.assertTrue(
+ pkg.candidate.policy_priority > 1 and pkg.candidate.policy_priority < 1001
+ )
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_progress.py b/tests/test_progress.py
new file mode 100644
index 0000000..c823019
--- /dev/null
+++ b/tests/test_progress.py
@@ -0,0 +1,56 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2010 Michael Vogt <mvo@ubuntu.com>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+"""Unit tests for verifying the correctness of apt.progress"""
+import os
+import unittest
+
+import apt_pkg
+import testcommon
+
+import apt
+
+
+class TestAcquireProgress(apt.progress.base.AcquireProgress):
+ def pulse(self, owner):
+ self.pulsed = True
+ # there should be a return value here, either (True,False)
+ # but often this is forgoten (and causes odd error messages)
+ # so the lib supports it. we test the lack of support value here
+
+
+class TestProgress(testcommon.TestCase):
+ def setUp(self):
+ testcommon.TestCase.setUp(self)
+ basedir = os.path.abspath(os.path.dirname(__file__))
+ # setup apt_pkg config
+ apt_pkg.init()
+ apt_pkg.config.set("APT::Architecture", "amd64")
+ apt_pkg.config.set("Dir::Etc", basedir)
+ # TODO: /dev/null is not a dir, perhaps find something better
+ apt_pkg.config.set("Dir::Etc::sourceparts", "/dev/null")
+ # setup lists dir
+ if not os.path.exists("./tmp/partial"):
+ os.makedirs("./tmp/partial")
+ apt_pkg.config.set("Dir::state::lists", "./tmp")
+ # create artifical line
+ deb_line = "deb [allow-insecure=yes] file:%s/data/fake-packages/ /\n" % basedir
+ with open("fetch_sources.list", "w") as fobj:
+ fobj.write(deb_line)
+ apt_pkg.config.set("Dir::Etc::sourcelist", "fetch_sources.list")
+ apt_pkg.config.clear("APT::Update::Post-Invoke")
+ apt_pkg.config.clear("APT::Update::Post-Invoke-Success")
+
+ def test_acquire_progress(self):
+ progress = TestAcquireProgress()
+ cache = apt.Cache()
+ cache.update(progress)
+ self.assertTrue(progress.pulsed)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_pyflakes.py b/tests/test_pyflakes.py
new file mode 100644
index 0000000..f26433a
--- /dev/null
+++ b/tests/test_pyflakes.py
@@ -0,0 +1,43 @@
+#!/usr/bin/python3
+
+import os
+import subprocess
+import unittest
+
+import testcommon
+
+
+class TestPyflakesClean(testcommon.TestCase):
+ EXCLUDES = ["build", "tests/old", ".pybuild"]
+ TOPLEVEL = os.path.normpath(
+ os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
+ )
+
+ def is_excluded_path(self, path):
+ for exclude in self.EXCLUDES:
+ if path.startswith(os.path.join(self.TOPLEVEL, exclude)):
+ return True
+ return False
+
+ def get_py_files(self, toplevel):
+ files = []
+ for path, dirnames, filenames in os.walk(self.TOPLEVEL):
+ if self.is_excluded_path(path):
+ continue
+ for filename in filenames:
+ if os.path.splitext(filename)[1] == ".py":
+ files.append(os.path.join(path, filename))
+ return files
+
+ def test_pyflakes_clean(self):
+ cmd = ["pyflakes3"] + self.get_py_files(self.TOPLEVEL)
+ res = subprocess.call(cmd)
+ if res != 0:
+ self.fail("pyflakes failed with: %s" % res)
+
+
+if __name__ == "__main__":
+ import logging
+
+ logging.basicConfig(level=logging.DEBUG)
+ unittest.main()
diff --git a/tests/test_signed_usable.py b/tests/test_signed_usable.py
new file mode 100644
index 0000000..1bd5087
--- /dev/null
+++ b/tests/test_signed_usable.py
@@ -0,0 +1,403 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2019 Canonical Ltd
+#
+# SPDX-License-Identifier: GPL-2.0+
+
+
+import base64
+import os
+import shutil
+import tempfile
+import unittest
+
+import apt_pkg
+import testcommon
+
+import apt
+import apt.progress.base
+import apt.progress.text
+
+# A change in APT to early fail acquire items with weak hashes caused it
+# to call progress methods before calling Start(), which confused python-apt's
+# locking handling. Hence we need to skip such tests for now, until we can test
+# against an apt version with the fix:
+#
+# https://salsa.debian.org/apt-team/apt/commit/84176f6c
+#
+RUN_CRASHING_TESTS = False
+
+# Message APT gives us when hashes are too weak
+CACHE_MSG_WEAK_HASH = (
+ "Insufficient information available to perform this download securely"
+)
+
+
+class TestSignedUsable(testcommon.TestCase):
+ """Test fetch_binary() and fetch_source() signature checking."""
+
+ def setUp(self):
+ testcommon.TestCase.setUp(self)
+ apt_pkg.config.clear("APT::Update::Post-Invoke")
+ apt_pkg.config.clear("APT::Update::Post-Invoke-Success")
+ self.chroot_path = chroot_path = tempfile.mkdtemp()
+ repo_path = os.path.abspath("./data/test-signed-usable-repo/")
+ # Inits the dirs for us
+ apt.cache.Cache(rootdir=chroot_path)
+ # Change directory
+ self.cwd = os.getcwd()
+ os.chdir(chroot_path)
+ with open(
+ os.path.join(self.chroot_path, "etc/apt/sources.list"), "w"
+ ) as sources_list:
+ sources_list.write("deb copy:%s/signed/ /\n" % repo_path)
+ sources_list.write("deb copy:%s/unsigned/ /\n" % repo_path)
+ sources_list.write("deb-src copy:%s/signed/ /\n" % repo_path)
+ sources_list.write("deb-src copy:%s/unsigned/ /\n" % repo_path)
+
+ with open(os.path.join(repo_path, "key.gpg.base64"), "rb") as pubkey64:
+ with open(
+ os.path.join(self.chroot_path, "etc/apt/trusted.gpg"), "wb"
+ ) as tgt:
+ tgt.write(base64.b64decode(pubkey64.read()))
+
+ self.cache = apt.cache.Cache(rootdir=chroot_path)
+ apt_pkg.config["Acquire::AllowInsecureRepositories"] = "true"
+ self.cache.update()
+ apt_pkg.config["Acquire::AllowInsecureRepositories"] = "false"
+ self.cache.open()
+
+ self.progress = apt.progress.text.AcquireProgress
+ apt.progress.text.AcquireProgress = apt.progress.base.AcquireProgress
+
+ # Disable actual installation of downloaded items
+ self.cache.install_archives = (
+ lambda *a, **b: apt_pkg.PackageManager.RESULT_COMPLETED
+ )
+
+ def tearDown(self):
+ # this resets the rootdir apt_pkg.config to ensure it does not
+ # "pollute" the later tests
+ apt.cache.Cache(rootdir="/")
+ os.chdir(self.cwd)
+ shutil.rmtree(self.chroot_path)
+
+ apt.progress.text.AcquireProgress = self.progress
+
+ def doInstall(self, name, bargs):
+ self.cache[name].mark_install()
+ try:
+ with apt.progress.base.InstallProgress() as ip:
+ self.cache.commit(install_progress=ip, **bargs)
+ finally:
+ for fname in os.listdir(
+ os.path.join(self.chroot_path, "var/cache/apt/archives")
+ ):
+ if os.path.isfile(
+ os.path.join(self.chroot_path, "var/cache/apt/archives", fname)
+ ):
+ os.unlink(
+ os.path.join(self.chroot_path, "var/cache/apt/archives", fname)
+ )
+ self.cache[name].mark_keep()
+
+ def doFetchArchives(self, name, bargs):
+ fetcher = apt_pkg.Acquire()
+ self.cache[name].mark_install()
+ try:
+ self.cache.fetch_archives(fetcher=fetcher, **bargs)
+ finally:
+ for fname in os.listdir(
+ os.path.join(self.chroot_path, "var/cache/apt/archives")
+ ):
+ if fname.endswith(".deb"):
+ os.unlink(
+ os.path.join(self.chroot_path, "var/cache/apt/archives", fname)
+ )
+ self.cache[name].mark_keep()
+
+ def testDefaultDenyButExplicitAllowUnauthenticated(self):
+ """Deny by config (default), but pass allow_unauthenticated=True"""
+
+ bargs = dict(allow_unauthenticated=True)
+ sargs = dict(allow_unauthenticated=True, unpack=False)
+
+ self.doInstall("signed-usable", bargs)
+ if RUN_CRASHING_TESTS:
+ self.assertRaisesRegex(
+ apt.cache.FetchFailedException,
+ CACHE_MSG_WEAK_HASH,
+ self.doInstall,
+ "signed-not-usable",
+ bargs,
+ )
+
+ self.doInstall("unsigned-usable", bargs)
+ if RUN_CRASHING_TESTS:
+ self.assertRaisesRegex(
+ apt.cache.FetchFailedException,
+ CACHE_MSG_WEAK_HASH,
+ self.doInstall,
+ "unsigned-unusable",
+ bargs,
+ )
+
+ self.doFetchArchives("signed-usable", bargs)
+ self.doFetchArchives("unsigned-usable", bargs)
+ self.assertRaisesRegex(
+ apt.cache.FetchFailedException,
+ CACHE_MSG_WEAK_HASH,
+ self.doFetchArchives,
+ "signed-not-usable",
+ bargs,
+ )
+ self.assertRaisesRegex(
+ apt.cache.FetchFailedException,
+ CACHE_MSG_WEAK_HASH,
+ self.doFetchArchives,
+ "unsigned-unusable",
+ bargs,
+ )
+
+ self.cache["signed-usable"].candidate.fetch_binary(**bargs)
+ self.cache["signed-usable"].candidate.fetch_source(**sargs)
+ self.cache["signed-not-usable"].candidate.fetch_binary(**bargs)
+ self.cache["signed-not-usable"].candidate.fetch_source(**sargs)
+ self.cache["unsigned-usable"].candidate.fetch_binary(**bargs)
+ self.cache["unsigned-usable"].candidate.fetch_source(**sargs)
+ self.cache["unsigned-unusable"].candidate.fetch_binary(**bargs)
+ self.cache["unsigned-unusable"].candidate.fetch_source(**sargs)
+
+ def testDefaultAllow(self):
+ """Allow by config APT::Get::AllowUnauthenticated = True"""
+ apt_pkg.config["APT::Get::AllowUnauthenticated"] = "true"
+
+ bargs = dict()
+ sargs = dict(unpack=False)
+
+ self.doInstall("signed-usable", bargs)
+ if RUN_CRASHING_TESTS:
+ self.assertRaisesRegex(
+ apt.cache.FetchFailedException,
+ CACHE_MSG_WEAK_HASH,
+ self.doInstall,
+ "signed-not-usable",
+ bargs,
+ )
+ self.doInstall("unsigned-usable", bargs)
+ if RUN_CRASHING_TESTS:
+ self.assertRaisesRegex(
+ apt.cache.FetchFailedException,
+ CACHE_MSG_WEAK_HASH,
+ self.doInstall,
+ "unsigned-unusable",
+ bargs,
+ )
+
+ self.doFetchArchives("signed-usable", bargs)
+ self.doFetchArchives("unsigned-usable", bargs)
+ self.assertRaisesRegex(
+ apt.cache.FetchFailedException,
+ CACHE_MSG_WEAK_HASH,
+ self.doFetchArchives,
+ "signed-not-usable",
+ bargs,
+ )
+ self.assertRaisesRegex(
+ apt.cache.FetchFailedException,
+ CACHE_MSG_WEAK_HASH,
+ self.doFetchArchives,
+ "unsigned-unusable",
+ bargs,
+ )
+
+ self.cache["signed-usable"].candidate.fetch_binary(**bargs)
+ self.cache["signed-usable"].candidate.fetch_source(**sargs)
+ self.cache["signed-not-usable"].candidate.fetch_binary(**bargs)
+ self.cache["signed-not-usable"].candidate.fetch_source(**sargs)
+ self.cache["unsigned-usable"].candidate.fetch_binary(**bargs)
+ self.cache["unsigned-usable"].candidate.fetch_source(**sargs)
+ self.cache["unsigned-unusable"].candidate.fetch_binary(**bargs)
+ self.cache["unsigned-unusable"].candidate.fetch_source(**sargs)
+
+ def testDefaultDeny(self):
+ """Test APT::Get::AllowUnauthenticated = False (default)"""
+ self.doInstall("signed-usable", {})
+ if RUN_CRASHING_TESTS:
+ self.assertRaisesRegex(
+ apt.cache.FetchFailedException,
+ CACHE_MSG_WEAK_HASH,
+ self.doInstall,
+ "signed-not-usable",
+ {},
+ )
+ self.assertRaisesRegex(
+ apt.cache.UntrustedException,
+ "Untrusted packages:",
+ self.doInstall,
+ "unsigned-usable",
+ {},
+ )
+ self.assertRaisesRegex(
+ apt.cache.UntrustedException,
+ "Untrusted packages:",
+ self.doInstall,
+ "unsigned-unusable",
+ {},
+ )
+
+ self.doFetchArchives("signed-usable", {})
+ self.assertRaisesRegex(
+ apt.cache.FetchFailedException,
+ CACHE_MSG_WEAK_HASH,
+ self.doFetchArchives,
+ "signed-not-usable",
+ {},
+ )
+ self.assertRaisesRegex(
+ apt.cache.UntrustedException,
+ "Untrusted packages:",
+ self.doFetchArchives,
+ "unsigned-usable",
+ {},
+ )
+ self.assertRaisesRegex(
+ apt.cache.UntrustedException,
+ "Untrusted packages:",
+ self.doFetchArchives,
+ "unsigned-unusable",
+ {},
+ )
+
+ self.cache["signed-usable"].candidate.fetch_binary()
+ self.cache["signed-usable"].candidate.fetch_source(unpack=False)
+ self.assertRaisesRegex(
+ apt.package.UntrustedError,
+ ": No trusted hash",
+ self.cache["signed-not-usable"].candidate.fetch_binary,
+ )
+ self.assertRaisesRegex(
+ apt.package.UntrustedError,
+ ": No trusted hash",
+ self.cache["signed-not-usable"].candidate.fetch_source,
+ unpack=False,
+ )
+ self.assertRaisesRegex(
+ apt.package.UntrustedError,
+ ": Source",
+ self.cache["unsigned-usable"].candidate.fetch_binary,
+ )
+ self.assertRaisesRegex(
+ apt.package.UntrustedError,
+ ": Source",
+ self.cache["unsigned-usable"].candidate.fetch_source,
+ unpack=False,
+ )
+ self.assertRaisesRegex(
+ apt.package.UntrustedError,
+ ": Source",
+ self.cache["unsigned-unusable"].candidate.fetch_binary,
+ )
+ self.assertRaisesRegex(
+ apt.package.UntrustedError,
+ ": Source",
+ self.cache["unsigned-unusable"].candidate.fetch_source,
+ unpack=False,
+ )
+
+ def testDefaultAllowButExplicitDeny(self):
+ """Allow by config, but pass allow_unauthenticated=False"""
+ apt_pkg.config["APT::Get::AllowUnauthenticated"] = "true"
+
+ bargs = dict(allow_unauthenticated=False)
+ sargs = dict(allow_unauthenticated=False, unpack=False)
+
+ self.doInstall("signed-usable", bargs)
+ if RUN_CRASHING_TESTS:
+ self.assertRaisesRegex(
+ apt.cache.FetchFailedException,
+ CACHE_MSG_WEAK_HASH,
+ self.doInstall,
+ "signed-not-usable",
+ bargs,
+ )
+ self.assertRaisesRegex(
+ apt.cache.UntrustedException,
+ "Untrusted packages:",
+ self.doInstall,
+ "unsigned-usable",
+ bargs,
+ )
+ self.assertRaisesRegex(
+ apt.cache.UntrustedException,
+ "Untrusted packages:",
+ self.doInstall,
+ "unsigned-unusable",
+ bargs,
+ )
+
+ self.doFetchArchives("signed-usable", bargs)
+ self.assertRaisesRegex(
+ apt.cache.FetchFailedException,
+ CACHE_MSG_WEAK_HASH,
+ self.doFetchArchives,
+ "signed-not-usable",
+ bargs,
+ )
+ self.assertRaisesRegex(
+ apt.cache.UntrustedException,
+ "Untrusted packages:",
+ self.doFetchArchives,
+ "unsigned-usable",
+ bargs,
+ )
+ self.assertRaisesRegex(
+ apt.cache.UntrustedException,
+ "Untrusted packages:",
+ self.doFetchArchives,
+ "unsigned-unusable",
+ bargs,
+ )
+
+ self.cache["signed-usable"].candidate.fetch_binary(**bargs)
+ self.cache["signed-usable"].candidate.fetch_source(**sargs)
+ self.assertRaisesRegex(
+ apt.package.UntrustedError,
+ ": No trusted hash",
+ self.cache["signed-not-usable"].candidate.fetch_binary,
+ **bargs
+ )
+ self.assertRaisesRegex(
+ apt.package.UntrustedError,
+ ": No trusted hash",
+ self.cache["signed-not-usable"].candidate.fetch_source,
+ **sargs
+ )
+ self.assertRaisesRegex(
+ apt.package.UntrustedError,
+ ": Source",
+ self.cache["unsigned-usable"].candidate.fetch_binary,
+ **bargs
+ )
+ self.assertRaisesRegex(
+ apt.package.UntrustedError,
+ ": Source",
+ self.cache["unsigned-usable"].candidate.fetch_source,
+ **sargs
+ )
+ self.assertRaisesRegex(
+ apt.package.UntrustedError,
+ ": Source",
+ self.cache["unsigned-unusable"].candidate.fetch_binary,
+ **bargs
+ )
+ self.assertRaisesRegex(
+ apt.package.UntrustedError,
+ ": Source",
+ self.cache["unsigned-unusable"].candidate.fetch_source,
+ **sargs
+ )
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_size_to_str.py b/tests/test_size_to_str.py
new file mode 100644
index 0000000..6320e39
--- /dev/null
+++ b/tests/test_size_to_str.py
@@ -0,0 +1,104 @@
+#!/usr/bin/python3
+
+__author__ = "Barry Warsaw <barry@ubuntu.com>, James Hunt, Michael Vogt"
+
+import unittest
+
+import apt_pkg
+import testcommon
+
+
+class SizeToStrTestCase(testcommon.TestCase):
+ """Test apt_pkg.size_to_str"""
+
+ DATA = {
+ # XXX: note the trailing spaces for some of these entries!
+ 10**1: "10 ",
+ 10**2: "100 ",
+ 10**3: "1000 ",
+ 10**4: "10.0 k",
+ 10**5: "100 k",
+ 10**6: "1000 k",
+ 10**7: "10.0 M",
+ 10**8: "100 M",
+ 10**9: "1000 M",
+ 10**10: "10.0 G",
+ 10**11: "100 G",
+ 10**12: "1000 G",
+ 10**13: "10.0 T",
+ 10**14: "100 T",
+ 10**15: "1000 T",
+ 10**16: "10.0 P",
+ 10**17: "100 P",
+ 10**18: "1000 P",
+ 10**19: "10.0 E",
+ 10**20: "100 E",
+ 10**21: "1000 E",
+ 10**22: "10.0 Z",
+ 10**23: "100.0 Z",
+ 10**24: "1000 Z",
+ # 10 ** 25: "10.0 Y",
+ 10**26: "100 Y",
+ 10**27: "1000 Y",
+ # That's our limit :)
+ 10**28: "10000 Y",
+ 0: "0 ",
+ 1: "1 ",
+ 1024: "1024 ",
+ 10240: "10.2 k",
+ 102400: "102 k",
+ 1024000: "1024 k",
+ 10240000: "10.2 M",
+ 102400000: "102 M",
+ 2147483647: "2147 M",
+ 2147483648: "2147 M",
+ 1024000000: "1024 M",
+ 10240000000: "10.2 G",
+ 9: "9 ",
+ 99: "99 ",
+ 999: "999 ",
+ 9999: "9999 ",
+ 99999: "100.0 k",
+ 999999: "1000 k",
+ 9999999: "10000 k",
+ 99999999: "100.0 M",
+ 999999999: "1000 M",
+ 9999999999: "10000 M",
+ 99999999999: "100.0 G",
+ 999999999999: "1000 G",
+ 9999999999999: "10000 G",
+ 99999999999999: "100.0 T",
+ 999999999999999: "1000 T",
+ 9999999999999999: "10.0 P",
+ 99999999999999999: "100 P",
+ 999999999999999999: "1000 P",
+ 9999999999999999999: "10.0 E",
+ 99999999999999999999: "100 E",
+ 999999999999999999999: "1000 E",
+ 9999999999999999999999: "10.0 Z",
+ 999999999999999999999999: "1000 Z",
+ }
+
+ def test_from_data(self):
+ for k, v in self.DATA.items():
+ size = apt_pkg.size_to_str(k)
+ msg = f"size_to_str({k}) returned '{size}', expected '{v}'"
+ self.assertEqual(size, v, msg)
+
+ def test_raise_on_unsupported(self):
+ for v in ["hello", None, {}, [], ()]:
+ with self.assertRaises(TypeError):
+ apt_pkg.size_to_str(v)
+
+
+class RegressionTestCase(testcommon.TestCase):
+ """Regression test for LP: #1030278"""
+
+ def test_no_overflow_error(self):
+ # LP: #1030278 produces an overflow error in size_to_str() with a big
+ # value under Python 3.
+ self.assertEqual(apt_pkg.size_to_str(2147483648000000000000), "2147 E")
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_sourcerecords.py b/tests/test_sourcerecords.py
new file mode 100644
index 0000000..4b0e6fb
--- /dev/null
+++ b/tests/test_sourcerecords.py
@@ -0,0 +1,129 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2018 Michael Vogt <mvo@ubuntu.com>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+"""Unit tests for verifying the correctness of source records in apt_pkg."""
+
+import os
+import shutil
+import sys
+import unittest
+
+from test_all import get_library_dir
+
+libdir = get_library_dir()
+if libdir:
+ sys.path.insert(0, libdir)
+
+import apt_pkg
+import testcommon
+
+import apt
+
+
+class TestSourceRecords(testcommon.TestCase):
+ def setUp(self):
+ testcommon.TestCase.setUp(self)
+
+ rootdir = "./data/tmp"
+ if os.path.exists(rootdir):
+ shutil.rmtree(rootdir)
+ try:
+ os.makedirs(os.path.join(rootdir, "etc", "apt"))
+ except OSError:
+ pass
+
+ for k in apt_pkg.config.keys():
+ apt_pkg.config.clear(k)
+
+ apt_pkg.config["Dir"] = os.path.abspath(rootdir)
+ apt_pkg.init_config()
+
+ # set a local sources.list that does not need the network
+ base_sources = os.path.abspath(
+ os.path.join(rootdir, "etc", "apt", "sources.list")
+ )
+ # main sources.list
+ sources_list = base_sources
+ with open(sources_list, "w") as f:
+ repo = os.path.abspath("./data/test-source-repo")
+ f.write("deb-src [trusted=yes] copy:%s /\n" % repo)
+
+ self.assertTrue(os.path.exists(sources_list))
+
+ # update a single sources.list
+ cache = apt.Cache(rootdir=rootdir)
+ cache.update(sources_list=sources_list)
+
+ def test_source_records_smoke(self):
+ src = apt_pkg.SourceRecords()
+ self.assertTrue(src.step())
+
+ self.assertEqual(src.maintainer, "Julian Andres Klode <jak@debian.org>") # noqa
+ self.assertEqual(src.binaries, ["dh-autoreconf"])
+ self.assertEqual(src.package, "dh-autoreconf")
+
+ self.assertEqual(2, len(src.files))
+
+ # unpacking as a tuple works as before
+ md5, size, path, type_ = f = src.files[0]
+ self.assertEqual(md5, None)
+ self.assertEqual(size, 1578)
+ self.assertEqual(path, "dh-autoreconf_16.dsc")
+ self.assertEqual(type_, "dsc")
+ # access using getters
+ self.assertTrue(isinstance(f.hashes, apt_pkg.HashStringList))
+ self.assertEqual(
+ str(f.hashes[0]),
+ "SHA512:4b1a3299f2a8b01b0c75db97fd16cb39919949c74d19ea6cf28e1bbd4891d3515b3e2b90b96a64df665cebf6d95409e704e670909ae91fcfe92409ee1339bffc",
+ ) # noqa
+ self.assertEqual(str(f.hashes[1]), "Checksum-FileSize:1578")
+ self.assertEqual(
+ str(f.hashes[2]),
+ "SHA256:1c1b2ab5f1ae5496bd50dbb3c30e9b7d181a06c8d02ee8d7e9c35ed6f2a69b5f",
+ ) # noqa
+ self.assertEqual(
+ str(f.hashes[3]), "SHA1:c9bf7a920013021dad5fbd898dfd5a79c7a150f9"
+ ) # noqa
+ self.assertEqual(
+ str(f.hashes[4]), "MD5Sum:6576a28fe1918ce10bd31543ba545901"
+ ) # noqa
+ self.assertEqual(f.size, 1578)
+ self.assertEqual(f.path, "dh-autoreconf_16.dsc")
+ self.assertEqual(f.type, "dsc")
+
+ # unpacking as a tuple works as before
+ md5, size, path, type_ = f = src.files[1]
+ self.assertEqual(md5, None)
+ self.assertEqual(size, 7372)
+ self.assertEqual(path, "dh-autoreconf_16.tar.xz")
+ self.assertEqual(type_, "tar")
+ # access using getters
+ self.assertTrue(isinstance(f.hashes, apt_pkg.HashStringList))
+ self.assertEqual(
+ str(f.hashes[0]),
+ "SHA512:10448dd179ec12bf4310a9a514110a85f56e51893aa36a97ac3a6f8d7ce99d099e62cfdb78e271e2d94431e8832da0f643de821b6643b80e3f0b0f5d682cf9a9",
+ ) # noqa
+ self.assertEqual(str(f.hashes[1]), "Checksum-FileSize:7372") # noqa
+ self.assertEqual(
+ str(f.hashes[2]),
+ "SHA256:5c6a6a362907327bec77a867ff3fd0eceba8015d1b881b48275aff7e4ce0f629",
+ ) # noqa
+ self.assertEqual(
+ str(f.hashes[3]), "SHA1:58459600164398ad6807ddd877a6f814c799c62c"
+ ) # noqa
+ self.assertEqual(
+ str(f.hashes[4]), "MD5Sum:302c8bf43db02412e3f2197fd0f2ee0f"
+ ) # noqa
+ self.assertEqual(f.size, 7372)
+ self.assertEqual(f.path, "dh-autoreconf_16.tar.xz")
+ self.assertEqual(f.type, "tar")
+
+ self.assertFalse(src.step())
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_tagfile.py b/tests/test_tagfile.py
new file mode 100644
index 0000000..29bf9e8
--- /dev/null
+++ b/tests/test_tagfile.py
@@ -0,0 +1,186 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2010 Michael Vogt <mvo@ubuntu.com>
+# Copyright (C) 2012 Canonical Ltd.
+# Author: Colin Watson <cjwatson@ubuntu.com>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+"""Unit tests for verifying the correctness of apt_pkg.TagFile"""
+
+import glob
+import os
+import shutil
+import sys
+import tempfile
+import unittest
+
+from test_all import get_library_dir
+
+libdir = get_library_dir()
+if libdir:
+ sys.path.insert(0, libdir)
+
+import apt_pkg
+import testcommon
+
+
+class TestOpenMaybeClearSigned(testcommon.TestCase):
+ def test_open_trivial(self):
+ basepath = os.path.dirname(__file__)
+ fd = apt_pkg.open_maybe_clear_signed_file(
+ os.path.join(basepath, "./data/test_debs/hello_2.5-1.dsc")
+ )
+ with os.fdopen(fd) as f:
+ data = f.read()
+ self.assertTrue(data.startswith("Format: 1.0\n"))
+
+ def test_open_normal(self):
+ basepath = os.path.dirname(__file__)
+ fd = apt_pkg.open_maybe_clear_signed_file(
+ os.path.join(basepath, "./data/misc/foo_Release")
+ )
+ with os.fdopen(fd) as f:
+ data = f.read()
+ self.assertTrue(data.startswith("Origin: Ubuntu\n"))
+
+ def xtest_open_does_not_exit(self):
+ with self.assertRaises(SystemError):
+ apt_pkg.open_maybe_clear_signed_file("does-not-exists")
+
+
+class TestTagFile(testcommon.TestCase):
+ """test the apt_pkg.TagFile"""
+
+ def setUp(self):
+ testcommon.TestCase.setUp(self)
+ self.temp_dir = tempfile.mkdtemp()
+
+ def tearDown(self):
+ shutil.rmtree(self.temp_dir)
+
+ def test_tag_file(self):
+ basepath = os.path.dirname(__file__)
+ tagfilepath = os.path.join(basepath, "./data/tagfile/*")
+ # test once for compressed and uncompressed
+ for testfile in glob.glob(tagfilepath):
+ # test once using the open() method and once using the path
+ tagfile = apt_pkg.TagFile(testfile)
+ for i, stanza in enumerate(tagfile):
+ pass
+ self.assertEqual(i, 2)
+ with open(testfile) as f:
+ tagfile = apt_pkg.TagFile(f)
+ for i, stanza in enumerate(tagfile):
+ pass
+ self.assertEqual(i, 2)
+
+ def test_errors(self):
+ # Raises SystemError via lbiapt
+ self.assertRaises(SystemError, apt_pkg.TagFile, "not-there-no-no")
+ # Raises Type error
+ self.assertRaises(TypeError, apt_pkg.TagFile, object())
+
+ def test_utf8(self):
+ value = "Tést Persön <test@example.org>"
+ packages = os.path.join(self.temp_dir, "Packages")
+ with open(packages, "w", encoding="UTF-8") as packages_file:
+ print("Maintainer: %s" % value, file=packages_file)
+ print("", file=packages_file)
+ with open(packages, encoding="UTF-8") as packages_file:
+ tagfile = apt_pkg.TagFile(packages_file)
+ tagfile.step()
+ self.assertEqual(value, tagfile.section["Maintainer"])
+
+ def test_latin1(self):
+ value = "Tést Persön <test@example.org>"
+ packages = os.path.join(self.temp_dir, "Packages")
+ with open(packages, "w", encoding="ISO-8859-1") as packages_file:
+ print("Maintainer: %s" % value, file=packages_file)
+ print("", file=packages_file)
+ with open(packages) as packages_file:
+ tagfile = apt_pkg.TagFile(packages_file, bytes=True)
+ tagfile.step()
+ self.assertEqual(value.encode("ISO-8859-1"), tagfile.section["Maintainer"])
+ with open(packages, encoding="ISO-8859-1") as packages_file:
+ tagfile = apt_pkg.TagFile(packages_file)
+ tagfile.step()
+ self.assertEqual(value, tagfile.section["Maintainer"])
+
+ def test_mixed(self):
+ value = "Tést Persön <test@example.org>"
+ packages = os.path.join(self.temp_dir, "Packages")
+ with open(packages, "w", encoding="UTF-8") as packages_file:
+ print("Maintainer: %s" % value, file=packages_file)
+ print("", file=packages_file)
+ with open(packages, "a", encoding="ISO-8859-1") as packages_file:
+ print("Maintainer: %s" % value, file=packages_file)
+ print("", file=packages_file)
+ with open(packages) as packages_file:
+ tagfile = apt_pkg.TagFile(packages_file, bytes=True)
+ tagfile.step()
+ self.assertEqual(value.encode("UTF-8"), tagfile.section["Maintainer"])
+ tagfile.step()
+ self.assertEqual(value.encode("ISO-8859-1"), tagfile.section["Maintainer"])
+
+
+class TestTagSection(testcommon.TestCase):
+ """test the apt_pkg.TagFile"""
+
+ def setUp(self):
+ testcommon.TestCase.setUp(self)
+ self.temp_dir = tempfile.mkdtemp()
+
+ def tearDown(self):
+ shutil.rmtree(self.temp_dir)
+
+ def test_write(self):
+ ts = apt_pkg.TagSection("a: 1\nb: 2\nc: 3\n")
+ outpath = os.path.join(self.temp_dir, "test")
+ with open(outpath, "w") as outfile:
+ ts.write(outfile, [], [])
+ with open(outpath) as outfile:
+ self.assertEqual(outfile.read(), "a: 1\nb: 2\nc: 3\n")
+
+ def test_write_order(self):
+ ts = apt_pkg.TagSection("a: 1\nb: 2\nc: 3\n")
+ outpath = os.path.join(self.temp_dir, "test")
+ with open(outpath, "w") as outfile:
+ ts.write(outfile, ["a", "c", "b"], [])
+ with open(outpath) as outfile:
+ self.assertEqual(outfile.read(), "a: 1\nc: 3\nb: 2\n")
+
+ def test_write_invalid_order(self):
+ ts = apt_pkg.TagSection("a: 1\nb: 2\nc: 3\n")
+ outpath = os.path.join(self.temp_dir, "test")
+ with open(outpath, "w") as outfile:
+ self.assertRaises(TypeError, ts.write, outfile, ["a", 1, "b"], [])
+
+ def test_write_remove(self):
+ ts = apt_pkg.TagSection("a: 1\nb: 2\nc: 3\n")
+ outpath = os.path.join(self.temp_dir, "test")
+ with open(outpath, "w") as outfile:
+ ts.write(outfile, ["a", "c", "b"], [apt_pkg.TagRemove("a")])
+ with open(outpath) as outfile:
+ self.assertEqual(outfile.read(), "c: 3\nb: 2\n")
+
+ def test_write_rewrite(self):
+ ts = apt_pkg.TagSection("a: 1\nb: 2\nc: 3\n")
+ outpath = os.path.join(self.temp_dir, "test")
+ with open(outpath, "w") as outfile:
+ ts.write(outfile, ["a", "c", "b"], [apt_pkg.TagRewrite("a", "AA")])
+ with open(outpath) as outfile:
+ self.assertEqual(outfile.read(), "a: AA\nc: 3\nb: 2\n")
+
+ def test_write_rename(self):
+ ts = apt_pkg.TagSection("a: 1\nb: 2\nc: 3\n")
+ outpath = os.path.join(self.temp_dir, "test")
+ with open(outpath, "w") as outfile:
+ ts.write(outfile, ["a", "z", "b"], [apt_pkg.TagRename("c", "z")])
+ with open(outpath) as outfile:
+ self.assertEqual(outfile.read(), "a: 1\nz: 3\nb: 2\n")
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_utils.py b/tests/test_utils.py
new file mode 100644
index 0000000..6f582bb
--- /dev/null
+++ b/tests/test_utils.py
@@ -0,0 +1,74 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2010 Michael Vogt <michael.vogt@ubuntu.com>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+
+import datetime
+import os
+import unittest
+
+import testcommon
+
+from apt.utils import get_maintenance_end_date, get_release_date_from_release_file
+
+
+class TestUtils(testcommon.TestCase):
+ def test_get_release_date_from_release_file(self):
+ path = os.path.join(os.path.dirname(__file__), "data", "misc", "foo_Release")
+ t = get_release_date_from_release_file(path)
+ self.assertEqual(
+ str(datetime.datetime.fromtimestamp(t, datetime.UTC)),
+ "2012-04-25 22:49:23+00:00",
+ )
+
+ def test_maintenance_time(self):
+ months_of_support = 18
+ # test historic releases, jaunty
+ release_date = datetime.datetime(2009, 4, 23)
+ (end_year, end_month) = get_maintenance_end_date(
+ release_date, months_of_support
+ )
+ self.assertEqual(end_year, 2010)
+ self.assertEqual(end_month, 10)
+ # test historic releases, karmic
+ release_date = datetime.datetime(2009, 10, 29)
+ (end_year, end_month) = get_maintenance_end_date(
+ release_date, months_of_support
+ )
+ self.assertEqual(end_year, 2011)
+ self.assertEqual(end_month, 4)
+ # test maverick
+ release_date = datetime.datetime(2010, 10, 10)
+ (end_year, end_month) = get_maintenance_end_date(
+ release_date, months_of_support
+ )
+ self.assertEqual(end_year, 2012)
+ self.assertEqual(end_month, 4)
+
+ # test with modulo zero
+ release_date = datetime.datetime(2010, 6, 10)
+ (end_year, end_month) = get_maintenance_end_date(
+ release_date, months_of_support
+ )
+ self.assertEqual(end_year, 2011)
+ self.assertEqual(end_month, 12)
+
+ # test dapper
+ months_of_support = 60
+ release_date = datetime.datetime(2008, 4, 24)
+ (end_year, end_month) = get_maintenance_end_date(
+ release_date, months_of_support
+ )
+ self.assertEqual(end_year, 2013)
+ self.assertEqual(end_month, 4)
+
+ # what datetime says
+ # d = datetime.timedelta(18*30)
+ # print "end date: ", release_date + d
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/testcommon.py b/tests/testcommon.py
new file mode 100644
index 0000000..29917a7
--- /dev/null
+++ b/tests/testcommon.py
@@ -0,0 +1,30 @@
+"""Common testing stuff"""
+
+import os
+import unittest
+
+import apt_pkg
+
+
+class TestCase(unittest.TestCase):
+ """Base class for python-apt unittests"""
+
+ def setUp(self):
+ self.resetConfig()
+
+ def resetConfig(self):
+ apt_pkg.config.clear("")
+ for key in apt_pkg.config.list():
+ apt_pkg.config.clear(key)
+
+ # Avoid loading any host config files
+ os.unsetenv("APT_CONFIG")
+ apt_pkg.config["Dir::Etc::main"] = "/dev/null"
+ apt_pkg.config["Dir::Etc::parts"] = "/dev/null"
+
+ apt_pkg.init_config()
+ apt_pkg.init_system()
+
+ # Restore default values
+ apt_pkg.config["Dir::Etc::main"] = "apt.conf"
+ apt_pkg.config["Dir::Etc::parts"] = "apt.conf.d"
diff --git a/typehinting/apt_inst.pyi b/typehinting/apt_inst.pyi
new file mode 100644
index 0000000..5d6a118
--- /dev/null
+++ b/typehinting/apt_inst.pyi
@@ -0,0 +1,37 @@
+from typing import *
+
+class ArArchive:
+ def extract(self) -> None: ...
+
+class DebFile:
+ def __init__(self, file: object) -> None: ...
+ control: TarFile
+ data: TarFile
+
+class TarMember:
+ def isblk(self) -> bool: ...
+ def ischr(self) -> bool: ...
+ def isdev(self) -> bool: ...
+ def isdir(self) -> bool: ...
+ def isfifo(self) -> bool: ...
+ def isfile(self) -> bool: ...
+ def islnk(self) -> bool: ...
+ def isreg(self) -> bool: ...
+ def issym(self) -> bool: ...
+
+ gid: int
+ linkname: str
+ major: int
+ minor: int
+ mode: int
+ mtime: int
+ name: str
+ size: int
+ uid: int
+
+class TarFile:
+ def extractall(self, rootdir: str = "") -> None: ...
+ def extractdata(self, member: str) -> bytes: ...
+ def go(
+ self, callback: Callable[[TarMember, bytes], None], member: str = ""
+ ) -> None: ...
diff --git a/typehinting/apt_pkg.pyi b/typehinting/apt_pkg.pyi
new file mode 100644
index 0000000..756d724
--- /dev/null
+++ b/typehinting/apt_pkg.pyi
@@ -0,0 +1,390 @@
+from typing import *
+
+from apt.progress.base import (
+ AcquireProgress,
+ CdromProgress,
+ InstallProgress,
+ OpProgress,
+)
+
+class FileLike(Protocol):
+ def fileno(self) -> int: ...
+
+class Cdrom:
+ def add(self, progress: CdromProgress) -> bool: ...
+ def ident(self, progress: CdromProgress) -> str: ...
+
+@overload
+def gettext(msg: str, domain: str) -> str: ...
+@overload
+def gettext(msg: str) -> str: ...
+
+class Configuration(Mapping[str, str]):
+ def find_file(self, key: str, default: str = "") -> str: ...
+ def find_dir(self, key: str, default: str = "") -> str: ...
+ def dump(self) -> str: ...
+ def find(self, key: str, default: object = None) -> str: ...
+ def find_b(self, key: str, default: bool = False) -> bool: ...
+ def set(self, key: str, value: str) -> None: ...
+ def value_list(self, key: str) -> List[str]: ...
+ def clear(self, root: object = None) -> None: ...
+ def __getitem__(self, key: str) -> str: ...
+ def __iter__(self) -> Iterator[str]: ...
+ def __len__(self) -> int: ...
+
+config = Configuration()
+
+def init() -> None: ...
+def init_config() -> None: ...
+def init_system() -> None: ...
+
+# FIXME: this is really a file-like object
+def md5sum(o: Any) -> str: ...
+
+class Dependency:
+ comp_type: str
+ comp_type_deb: str
+ target_pkg: Package
+ target_ver: str
+ dep_type_untranslated: str
+ def all_targets(self) -> List[Version]: ...
+
+# This is really a SystemError, but we don't want to expose that
+class Error(Exception):
+ pass
+
+class Package:
+ name: str
+ version_list: List[Version]
+ architecture: str
+ id: int
+ current_ver: Version
+ essential: bool
+ current_state: int
+ inst_state: int
+ selected_state: int
+ has_versions: bool
+ has_provides: bool
+ provides_list: List[Tuple[str, str, Version]]
+ def get_fullname(self, pretty: bool = False) -> str: ...
+
+class ProblemResolver:
+ def __init__(self, cache: DepCache) -> None: ...
+ def clear(self, pkg: Package) -> None: ...
+ def protect(self, pkg: Package) -> None: ...
+ def remove(self, pkg: Package) -> None: ...
+ def resolve(self, fix_broken: bool = True) -> bool: ...
+ def resolve_by_keep(self) -> bool: ...
+ def keep_phased_updates(self) -> bool: ...
+
+CURSTATE_CONFIG_FILES: int
+INSTSTATE_REINSTREQ: int
+INSTSTATE_HOLD_REINSTREQ: int
+
+class Version:
+ ver_str: str
+ hash: int
+ file_list: List[Tuple[PackageFile, int]]
+ translated_description: Description
+ installed_size: int
+ size: int
+ arch: str
+ downloadable: bool
+ is_security_update: bool
+ id: int
+ section: str
+ priority: int
+ priority_str: str
+ provides_list: List[Tuple[str, str, str]]
+ depends_list: Dict[str, List[List[Dependency]]]
+ parent_pkg: Package
+ multi_arch: int
+ MULTI_ARCH_ALL: int
+ MULTI_ARCH_ALLOWED: int
+ MULTI_ARCH_ALL_ALLOWED: int
+ MULTI_ARCH_ALL_FOREIGN: int
+ MULTI_ARCH_FOREIGN: int
+ MULTI_ARCH_NO: int
+ MULTI_ARCH_NONE: int
+ MULTI_ARCH_SAME: int
+
+class Description:
+ file_list: List[Tuple[PackageFile, int]]
+
+class PackageRecords:
+ homepage: str
+ short_desc: str
+ long_desc: str
+ source_pkg: str
+ source_ver: str
+ record: str
+ filename: str
+ md5_hash: str
+ sha1_hash: str
+ sha256_hash: str
+ hashes: HashStringList
+ def __init__(self, cache: Cache) -> None: ...
+ def lookup(self, packagefile: Tuple[PackageFile, int], index: int = 0) -> bool: ...
+
+class PackageFile:
+ architecture: str
+ archive: str
+ codename: str
+ component: str
+ filename: str
+ id: int
+ index_type: str
+ label: str
+ not_automatic: bool
+ not_source: bool
+ origin: str
+ site: str
+ size: int
+ version: str
+
+T = TypeVar("T")
+
+class TagFile(Iterator[TagSection[AnyStr]]):
+ @overload
+ def __new__(cls, file: object) -> TagFile[str]: ...
+ @overload
+ def __new__(cls, file: object, bytes: Literal[True]) -> TagFile[bytes]: ...
+ @overload
+ def __new__(cls, file: object, bytes: Literal[False]) -> TagFile[str]: ...
+ def __iter__(self) -> Iterator[TagSection[AnyStr]]: ...
+ def __enter__(self: T) -> T: ...
+ def __exit__(self, typ: object, value: object, traceback: object) -> None: ...
+ def __next__(self) -> TagSection[AnyStr]: ...
+
+class TagSection(Mapping[str, AnyStr]):
+ @overload
+ def __new__(cls, str: Union[str, bytes]) -> TagSection[str]: ...
+ @overload
+ def __new__(
+ cls, str: Union[str, bytes], bytes: Literal[True]
+ ) -> TagSection[bytes]: ...
+ @overload
+ def __new__(
+ cls, str: Union[str, bytes], bytes: Literal[False]
+ ) -> TagSection[str]: ...
+ def __getitem__(self, key: str) -> AnyStr: ...
+ def get(self, key: str, default: Optional[object] = None) -> AnyStr: ...
+ def find(self, key: str, default: Optional[object] = None) -> AnyStr: ...
+ def find_raw(self, key: str, default: Optional[object] = None) -> AnyStr: ...
+ def __contains__(self, key: object) -> bool: ...
+ def __len__(self) -> int: ...
+ def __iter__(self) -> Iterator[str]: ...
+
+def version_compare(a: str, b: str) -> int: ...
+def get_lock(file: str, errors: bool = False) -> int: ...
+def pkgsystem_lock() -> None: ...
+def pkgsystem_unlock() -> None: ...
+def read_config_file(configuration: Configuration, path: str) -> None: ...
+def read_config_dir(configuration: Configuration, path: str) -> None: ...
+def pkgsystem_lock_inner() -> None: ...
+def pkgsystem_unlock_inner() -> None: ...
+def pkgsystem_is_locked() -> bool: ...
+
+SELSTATE_HOLD: int
+
+class Acquire:
+ fetch_needed: int
+ items: List[AcquireItem]
+ partial_present: int
+ total_needed: int
+ workers: List[AcquireWorker]
+ RESULT_CANCELLED: int
+ RESULT_FAILED: int
+ RESULT_CONTINUE: int
+ def __init__(self, progress: Optional[AcquireProgress] = None) -> None: ...
+ def run(self) -> int: ...
+ def shutdown(self) -> None: ...
+ def get_lock(self, path: str) -> None: ...
+
+class AcquireWorker:
+ current_item: AcquireItemDesc
+ current_size: int
+ total_size: int
+ status: str
+
+class AcquireItem:
+ active_subprocess: str
+ complete: bool
+ desc_uri: str
+ destfile: str
+ error_text: str
+ filesize: int
+ id: int
+ is_trusted: bool
+ local: bool
+ mode: str
+ partialsize: int
+ status: int
+
+ STAT_IDLE: int
+ STAT_FETCHING: int
+ STAT_DONE: int
+ STAT_ERROR: int
+ STAT_AUTH_ERROR: int
+ STAT_TRANSIENT_NETWORK_ERROR: int
+
+class AcquireItemDesc:
+ description: str
+ owner: AcquireItem
+ shortdesc: str
+ uri: str
+
+class Hashes:
+ def __init__(self, object: Union[bytes, FileLike, int]) -> None: ...
+ hashes: HashStringList
+
+class HashString:
+ def __init__(self, type: str, hash: Optional[str] = None) -> None: ...
+ def verify_file(self, filename: str) -> bool: ...
+
+ hashtype: str
+ hashvalue: str
+ usable: bool
+
+class HashStringList:
+ def append(self, object: HashString) -> None: ...
+ def find(self, type: str = "") -> HashString: ...
+ def verify_file(self, filename: str) -> bool: ...
+
+ file_size: int
+ usable: bool
+
+class AcquireFile(AcquireItem):
+ def __init__(
+ self,
+ owner: Acquire,
+ uri: str,
+ hash: Optional[Union[HashStringList, str]],
+ size: int = 0,
+ descr: str = "",
+ short_descr: str = "",
+ destdir: str = "",
+ destfile: str = "",
+ ) -> None: ...
+
+class IndexFile:
+ def archive_uri(self, path: str) -> str: ...
+ describe: str
+ exists: bool
+ has_packages: bool
+ is_trusted: bool
+ label: str
+ size: int
+
+class SourceRecordFiles:
+ hashes: HashStringList
+ path: str
+ size: int
+ type: str
+
+class SourceRecords:
+ def lookup(self, name: str) -> bool: ...
+ def restart(self) -> None: ...
+ def step(self) -> bool: ...
+ binaries: List[str]
+ version: str
+ files: List[SourceRecordFiles]
+ index: IndexFile
+ package: str
+ section: str
+
+class ActionGroup:
+ def __init__(self, depcache: DepCache) -> None: ...
+
+class MetaIndex:
+ dist: str
+ index_files: List[IndexFile]
+ is_trusted: bool
+ uri: str
+
+class SourceList:
+ list: List[MetaIndex]
+ def read_main_list(self) -> None: ...
+ def find_index(self, pf: PackageFile) -> IndexFile: ...
+
+class PackageManager:
+ RESULT_FAILED: int
+ RESULT_COMPLETED: int
+ RESULT_INCOMPLETE: int
+ def __init__(self, depcache: DepCache) -> None: ...
+ def get_archives(
+ self, fetcher: Acquire, list: SourceList, recs: PackageRecords
+ ) -> bool: ...
+
+class Cache:
+ packages: List[Package]
+ def __init__(self, progress: Optional[OpProgress] = None) -> None: ...
+ def __contains__(self, name: Union[str, Tuple[str, str]]) -> Package: ...
+ def __getitem__(self, name: Union[str, Tuple[str, str]]) -> Package: ...
+ def __len__(self) -> int: ...
+ def update(
+ self, progress: AcquireProgress, sources: SourceList, pulse_interval: int
+ ) -> int: ...
+
+class DepCache:
+ broken_count: int
+ inst_count: int
+ del_count: int
+ keep_count: int
+ usr_size: int
+ policy: Policy
+ def __init__(self, cache: Cache) -> None: ...
+ def init(self, progress: Optional[OpProgress] = None) -> None: ...
+ def get_candidate_ver(self, pkg: Package) -> Optional[Version]: ...
+ def set_candidate_ver(self, pkg: Package, ver: Version) -> bool: ...
+ def marked_install(self, pkg: Package) -> bool: ...
+ def marked_upgrade(self, pkg: Package) -> bool: ...
+ def marked_keep(self, pkg: Package) -> bool: ...
+ def marked_downgrade(self, pkg: Package) -> bool: ...
+ def marked_delete(self, pkg: Package) -> bool: ...
+ def marked_reinstall(self, pkg: Package) -> bool: ...
+ def is_upgradable(self, pkg: Package) -> bool: ...
+ def is_garbage(self, pkg: Package) -> bool: ...
+ def is_auto_installed(self, pkg: Package) -> bool: ...
+ def is_inst_broken(self, pkg: Package) -> bool: ...
+ def is_now_broken(self, pkg: Package) -> bool: ...
+ def mark_keep(self, pkg: Package) -> None: ...
+ def mark_install(
+ self, pkg: Package, auto_inst: bool = True, from_user: bool = True
+ ) -> None: ...
+ def mark_delete(self, pkg: Package, purge: bool = False) -> None: ...
+ def mark_auto(self, pkg: Package, auto: bool) -> None: ...
+ def commit(
+ self, acquire_progress: AcquireProgress, install_progress: InstallProgress
+ ) -> None: ...
+ def upgrade(self, dist_upgrade: bool = True) -> bool: ...
+ def fix_broken(self) -> bool: ...
+ def phasing_applied(self, pkg: Package) -> bool: ...
+
+class Policy:
+ def get_priority(self, pkg: Union[PackageFile, Version]) -> int: ...
+
+class SystemLock:
+ def __enter__(self) -> None: ...
+ def __exit__(self, typ: object, value: object, traceback: object) -> None: ...
+
+class FileLock:
+ def __init__(self, path: str) -> None: ...
+ def __enter__(self) -> None: ...
+ def __exit__(self, typ: object, value: object, traceback: object) -> None: ...
+
+def upstream_version(ver: str) -> str: ...
+def get_architectures() -> List[str]: ...
+def check_dep(pkg_ver: str, dep_op: str, dep_ver: str) -> bool: ...
+def uri_to_filename(uri: str) -> str: ...
+def str_to_time(rfc_time: str) -> int: ...
+def time_to_str(time: int) -> str: ...
+def size_to_str(size: Union[float, int]) -> str: ...
+def open_maybe_clear_signed_file(file: str) -> int: ...
+def parse_depends(
+ s: str, strip_multi_arch: bool = True, architecture: str = ""
+) -> List[List[Tuple[str, str, str]]]: ...
+def parse_src_depends(
+ s: str, strip_multi_arch: bool = True, architecture: str = ""
+) -> List[List[Tuple[str, str, str]]]: ...
+def string_to_bool(s: str) -> bool: ...
diff --git a/utils/expand_info.py b/utils/expand_info.py
new file mode 100755
index 0000000..787b1f0
--- /dev/null
+++ b/utils/expand_info.py
@@ -0,0 +1,11 @@
+#!/usr/bin/python3
+#
+# usage: ./utils/expand_info.py build/data/templates/Debian.info \
+# /usr/share/distro-info/debian.csv
+
+import sys
+
+import aptsources.distinfo
+
+for line in aptsources.distinfo._expand_template(sys.argv[1], sys.argv[2]):
+ print(line)
diff --git a/utils/get_debian_mirrors.py b/utils/get_debian_mirrors.py
new file mode 100755
index 0000000..408968c
--- /dev/null
+++ b/utils/get_debian_mirrors.py
@@ -0,0 +1,47 @@
+#!/usr/bin/python3
+# get_debian_mirrors.py - Parse Mirrors.masterlist and create a mirror list.
+#
+# Copyright (c) 2010-2011 Julian Andres Klode <jak@debian.org>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+import collections
+import sys
+import urllib.request
+
+from debian import deb822
+
+mirrors = collections.defaultdict(set)
+masterlist = urllib.request.urlopen(
+ "https://mirror-master.debian.org/" "status/Mirrors.masterlist"
+)
+
+for mirror in deb822.Deb822.iter_paragraphs(masterlist):
+ if "Country" not in mirror:
+ continue
+ country = mirror["Country"].split(None, 1)[0]
+ site = mirror["Site"]
+ for proto in "http", "ftp":
+ if "Archive-%s" % proto in mirror:
+ mirrors[country].add(
+ "{}://{}{}".format(proto, site, mirror["Archive-%s" % proto])
+ )
+
+if len(mirrors) == 0:
+ sys.stderr.write("E: Could not read the mirror list due to " "some unknown issue\n")
+ sys.exit(1)
+for country in sorted(mirrors):
+ print("#LOC:%s" % country)
+ print("\n".join(sorted(mirrors[country])))
diff --git a/utils/get_ubuntu_mirrors_from_lp.py b/utils/get_ubuntu_mirrors_from_lp.py
new file mode 100755
index 0000000..b3253de
--- /dev/null
+++ b/utils/get_ubuntu_mirrors_from_lp.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python3
+#
+# get_ubuntu_lp_mirrors.py
+#
+# Download the latest list with available Ubuntu mirrors from Launchpad.net
+# and extract the hosts from the raw page
+#
+# Copyright (c) 2006 Free Software Foundation Europe
+#
+# Author: Sebastian Heinlein <glatzor@ubuntu.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
+import sys
+
+import feedparser
+
+d = feedparser.parse("https://launchpad.net/ubuntu/+archivemirrors-rss")
+# d = feedparser.parse(open("+archivemirrors-rss"))
+
+countries = {}
+
+for entry in d.entries:
+ countrycode = entry.mirror_countrycode
+ if countrycode not in countries:
+ countries[countrycode] = set()
+ for link in entry.links:
+ countries[countrycode].add(link.href)
+
+
+keys = sorted(countries)
+
+if len(keys) == 0:
+ sys.stderr.write(
+ "E: Could not read the mirror list due to some issue"
+ " -- status code: %s\n" % d.status
+ )
+ sys.exit(1)
+
+print("mirror://mirrors.ubuntu.com/mirrors.txt")
+for country in keys:
+ print("#LOC:%s" % country)
+ print("\n".join(sorted(countries[country])))
diff --git a/utils/mirrortest b/utils/mirrortest
new file mode 100755
index 0000000..54dcfe7
--- /dev/null
+++ b/utils/mirrortest
@@ -0,0 +1,108 @@
+#!/usr/bin/env python3
+import os
+import queue
+import random
+import re
+import socket
+import threading
+import time
+import urllib.error
+import urllib.parse
+import urllib.request
+
+import aptsources.distro
+import aptsources.sourceslist
+
+socket.setdefaulttimeout(2)
+
+
+class MirrorTest:
+ class PingWorker(threading.Thread):
+ def __init__(self, jobs, results, id):
+ self.id = id
+ self.jobs = jobs
+ self.results = results
+ self.match_result = re.compile(r"^rtt .* = [\.\d]+/([\.\d]+)/.*")
+ threading.Thread.__init__(self)
+
+ def run(self):
+ result = None
+ while MirrorTest.completed_pings < MirrorTest.todo:
+ try:
+ mirror = self.jobs.get(True, 1)
+ host = mirror.hostname
+ except:
+ continue
+ print(
+ "Pinging (Worker %s) %s (%s) ..."
+ % (self.id, host, MirrorTest.completed_pings)
+ )
+ commando = os.popen("ping -q -c 4 -W 2 -i 0.3 %s" % host, "r")
+ while True:
+ line = commando.readline()
+ if not line:
+ break
+ result = re.findall(self.match_result, line)
+ MirrorTest.completed_pings_lock.acquire()
+ MirrorTest.completed_pings += 1
+ if result:
+ self.results.append([float(result[0]), host, mirror])
+ MirrorTest.completed_pings_lock.release()
+
+ def speed_test(self, mirror):
+ url = f"{mirror.get_repo_urls()[0]}/{self.test_file}"
+ print("Downloading %s ..." % url)
+ start = time.time()
+ try:
+ urllib.request.urlopen(url).read(51200)
+ return 50 / (time.time() - start)
+ except:
+ return 0
+
+ def __init__(self, hosts, test_file):
+ self.test_file = test_file
+ jobs = queue.Queue()
+ results = []
+ for h in hosts:
+ jobs.put(h)
+ self.threads = []
+ MirrorTest.completed_pings = 0
+ MirrorTest.completed_pings_lock = threading.Lock()
+ MirrorTest.todo = len(hosts)
+
+ for i in range(10):
+ t = MirrorTest.PingWorker(jobs, results, i)
+ self.threads.append(t)
+ t.start()
+
+ for t in self.threads:
+ t.join()
+
+ results.sort()
+ print("\n\nTop ten RTTs:")
+ for r in results[0:10]:
+ print(f"{r[1]}: {r[0]}")
+ print("\n\n")
+
+ results.insert(0, [0, "rand", hosts[random.randint(1, len(hosts))]])
+ results.insert(0, [0, "rand", hosts[random.randint(1, len(hosts))]])
+
+ final = [(self.speed_test(r[2]), r[2]) for r in results[0:12]]
+ final.sort()
+ final.reverse()
+ print("\n\nBest mirrors:")
+ for f in final:
+ print(f"{f[1].hostname}: {int(f[0])} KByte/s")
+
+
+if __name__ == "__main__":
+ distro = aptsources.distro.get_distro()
+ distro.get_sources(aptsources.sourceslist.SourcesList())
+ pipe = os.popen("dpkg --print-architecture")
+ arch = pipe.read().strip()
+ test_file = "dists/{}/{}/binary-{}/Packages.gz".format(
+ distro.source_template.name,
+ distro.source_template.components[0].name,
+ arch,
+ )
+ app = MirrorTest(distro.source_template.mirror_set.values(), test_file)