Merge lp:~snappy-dev/snapcraft/more-apt into lp:~snappy-dev/snapcraft/core

Proposed by Sergio Schvezov
Status: Merged
Approved by: Sergio Schvezov
Approved revision: 191
Merged at revision: 186
Proposed branch: lp:~snappy-dev/snapcraft/more-apt
Merge into: lp:~snappy-dev/snapcraft/core
Diff against target: 277 lines (+97/-59)
4 files modified
snapcraft/__init__.py (+5/-1)
snapcraft/manifest.txt (+13/-0)
snapcraft/repo.py (+79/-49)
snapcraft/tests/test_repo.py (+0/-9)
To merge this branch: bzr merge lp:~snappy-dev/snapcraft/more-apt
Reviewer Review Type Date Requested Status
Michael Vogt (community) Approve
Review via email: mp+271817@code.launchpad.net

Commit message

Improving stage-package handling

To post a comment you must log in.
lp:~snappy-dev/snapcraft/more-apt updated
190. By Sergio Schvezov

Remove tests that doesn't make sense as a unit test

191. By Sergio Schvezov

merge trunk

Revision history for this message
Michael Vogt (mvo) wrote :

Good stuff!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'snapcraft/__init__.py'
--- snapcraft/__init__.py 2015-09-17 14:14:14 +0000
+++ snapcraft/__init__.py 2015-09-21 15:29:20 +0000
@@ -31,6 +31,10 @@
31 def PLUGIN_STAGE_PACKAGES(self):31 def PLUGIN_STAGE_PACKAGES(self):
32 return getattr(self, '_PLUGIN_STAGE_PACKAGES', [])32 return getattr(self, '_PLUGIN_STAGE_PACKAGES', [])
3333
34 @property
35 def PLUGIN_STAGE_SOURCES(self):
36 return getattr(self, '_PLUGIN_STAGE_SOURCES', [])
37
34 def __init__(self, name, options):38 def __init__(self, name, options):
35 self.name = name39 self.name = name
36 self.options = options40 self.options = options
@@ -99,9 +103,9 @@
99 os.makedirs(d, exist_ok=True)103 os.makedirs(d, exist_ok=True)
100104
101 def setup_stage_packages(self):105 def setup_stage_packages(self):
102 ubuntu = snapcraft.repo.Ubuntu(self.ubuntudir)
103 part_stage_packages = getattr(self.options, 'stage_packages', []) or []106 part_stage_packages = getattr(self.options, 'stage_packages', []) or []
104 if self.PLUGIN_STAGE_PACKAGES or part_stage_packages:107 if self.PLUGIN_STAGE_PACKAGES or part_stage_packages:
108 ubuntu = snapcraft.repo.Ubuntu(self.ubuntudir, sources=self.PLUGIN_STAGE_SOURCES)
105 ubuntu.get(self.PLUGIN_STAGE_PACKAGES + part_stage_packages)109 ubuntu.get(self.PLUGIN_STAGE_PACKAGES + part_stage_packages)
106 ubuntu.unpack(self.installdir)110 ubuntu.unpack(self.installdir)
107111
108112
=== modified file 'snapcraft/manifest.txt'
--- snapcraft/manifest.txt 2015-09-01 19:04:49 +0000
+++ snapcraft/manifest.txt 2015-09-21 15:29:20 +0000
@@ -1,5 +1,6 @@
1adduser1adduser
2apt2apt
3apt-utils
3base-files4base-files
4base-passwd5base-passwd
5bash6bash
@@ -7,12 +8,14 @@
7coreutils8coreutils
8dash9dash
9debconf10debconf
11debconf-i18n
10debianutils12debianutils
11diffutils13diffutils
12dmsetup14dmsetup
13dpkg15dpkg
14e2fslibs16e2fslibs
15e2fsprogs17e2fsprogs
18file
16findutils19findutils
17gcc-4.9-base20gcc-4.9-base
18gcc-5-base21gcc-5-base
@@ -26,6 +29,8 @@
26insserv29insserv
27libacl130libacl1
28libapparmor131libapparmor1
32libapt
33libapt-inst1.5
29libapt-pkg4.1234libapt-pkg4.12
30libattr135libattr1
31libaudit-common36libaudit-common
@@ -44,8 +49,11 @@
44libgcc149libgcc1
45libgcrypt2050libgcrypt20
46libgpg-error051libgpg-error0
52libgpm2
47libkmod253libkmod2
54liblocale-gettext-perl
48liblzma555liblzma5
56libmagic1
49libmount157libmount1
50libncurses558libncurses5
51libncursesw559libncursesw5
@@ -65,6 +73,9 @@
65libss273libss2
66libstdc++674libstdc++6
67libsystemd075libsystemd0
76libtext-charwidth-perl
77libtext-iconv-perl
78libtext-wrapi18n-perl
68libtinfo579libtinfo5
69libudev180libudev1
70libusb-0.1-481libusb-0.1-4
@@ -74,6 +85,8 @@
74login85login
75lsb-base86lsb-base
76makedev87makedev
88manpages
89manpages-dev
77mawk90mawk
78mount91mount
79multiarch-support92multiarch-support
8093
=== modified file 'snapcraft/repo.py'
--- snapcraft/repo.py 2015-09-07 20:23:57 +0000
+++ snapcraft/repo.py 2015-09-21 15:29:20 +0000
@@ -14,11 +14,28 @@
14# You should have received a copy of the GNU General Public License14# You should have received a copy of the GNU General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.15# along with this program. If not, see <http://www.gnu.org/licenses/>.
1616
17import apt
18import glob17import glob
19import itertools18import itertools
20import os19import os
20import string
21import subprocess21import subprocess
22import urllib
23import urllib.request
24
25import apt
26from xml.etree import ElementTree
27
28_DEFAULT_SOURCES = '''deb http://${mirror}archive.ubuntu.com/ubuntu/ vivid main restricted
29deb http://${mirror}archive.ubuntu.com/ubuntu/ vivid-updates main restricted
30deb http://${mirror}archive.ubuntu.com/ubuntu/ vivid universe
31deb http://${mirror}archive.ubuntu.com/ubuntu/ vivid-updates universe
32deb http://${mirror}archive.ubuntu.com/ubuntu/ vivid multiverse
33deb http://${mirror}archive.ubuntu.com/ubuntu/ vivid-updates multiverse
34deb http://security.ubuntu.com/ubuntu vivid-security main restricted
35deb http://security.ubuntu.com/ubuntu vivid-security universe
36deb http://security.ubuntu.com/ubuntu vivid-security multiverse
37'''
38_GEOIP_SERVER = "http://geoip.ubuntu.com/lookup"
2239
2340
24class PackageNotFoundError(Exception):41class PackageNotFoundError(Exception):
@@ -43,33 +60,47 @@
4360
44class Ubuntu:61class Ubuntu:
4562
46 def __init__(self, download_dir, recommends=False):63 def __init__(self, rootdir, recommends=False, sources=_DEFAULT_SOURCES):
47 self.apt_cache = apt.Cache()64 sources = sources or _DEFAULT_SOURCES
48 self.manifest_dep_names = self._manifest_dep_names()65 self.downloaddir = os.path.join(rootdir, 'download')
66 self.rootdir = rootdir
67 self.apt_cache = _setup_apt_cache(rootdir, sources)
49 self.recommends = recommends68 self.recommends = recommends
50 self.download_dir = download_dir
5169
52 def get(self, package_names):70 def get(self, package_names):
53 # TODO cleanup download_dir for clean gets and unpacks71 os.makedirs(self.downloaddir, exist_ok=True)
54 self.all_dep_names = set()72
5573 manifest_dep_names = self._manifest_dep_names()
56 all_package_names = self._compute_deps(package_names)74
5775 for name in package_names:
58 for pkg in all_package_names:76 try:
59 self.apt_cache[pkg].candidate.fetch_binary(destdir=self.download_dir)77 self.apt_cache[name].mark_install()
6078 except KeyError:
61 return all_package_names79 raise PackageNotFoundError(name)
6280
63 def unpack(self, root_dir):81 for pkg in self.apt_cache:
64 pkgs_abs_path = glob.glob(os.path.join(self.download_dir, '*.deb'))82 # those should be already on each system, it also prevents
83 # diving into downloading libc6
84 if (pkg.candidate.priority in 'essential' and
85 pkg.name not in package_names):
86 print('Skipping priority essential/imporant %s' % pkg.name)
87 continue
88 if (pkg.name in manifest_dep_names and pkg.name not in package_names):
89 print('Skipping blacklisted from manifest package %s' % pkg.name)
90 continue
91 if pkg.marked_install:
92 pkg.candidate.fetch_binary(destdir=self.downloaddir)
93
94 def unpack(self, rootdir):
95 pkgs_abs_path = glob.glob(os.path.join(self.downloaddir, '*.deb'))
65 for pkg in pkgs_abs_path:96 for pkg in pkgs_abs_path:
66 # TODO needs elegance and error control97 # TODO needs elegance and error control
67 try:98 try:
68 subprocess.check_call(['dpkg-deb', '--extract', pkg, root_dir])99 subprocess.check_call(['dpkg-deb', '--extract', pkg, rootdir])
69 except subprocess.CalledProcessError:100 except subprocess.CalledProcessError:
70 raise UnpackError(pkg)101 raise UnpackError(pkg)
71102
72 _fix_symlinks(root_dir)103 _fix_symlinks(rootdir)
73104
74 def _manifest_dep_names(self):105 def _manifest_dep_names(self):
75 manifest_dep_names = set()106 manifest_dep_names = set()
@@ -82,36 +113,35 @@
82113
83 return manifest_dep_names114 return manifest_dep_names
84115
85 def _compute_deps(self, package_names):116
86 self._add_deps(package_names)117def get_geoip_country_code_prefix():
87118 try:
88 for pkg in package_names:119 with urllib.request.urlopen(_GEOIP_SERVER) as f:
89 if pkg not in self.all_dep_names:120 xml_data = f.read()
90 raise PackageNotFoundError(pkg)121 et = ElementTree.fromstring(xml_data)
91122 cc = et.find("CountryCode")
92 return sorted(self.all_dep_names)123 if cc is None:
93124 return ""
94 def _add_deps(self, package_names):125 return cc.text.lower() + "."
95 def add_deps(packages):126 except (ElementTree.ParseError, urllib.error.URLError):
96 for pkg in packages:127 pass
97 # Remove the :any in packages128 return ""
98 # TODO support multiarch129
99 pkg = pkg.rsplit(':', 1)[0]130
100 if pkg in self.all_dep_names:131def _setup_apt_cache(rootdir, sources):
101 continue132 os.makedirs(os.path.join(rootdir, 'etc', 'apt'), exist_ok=True)
102 if pkg in self.manifest_dep_names and pkg not in package_names:133 srcfile = os.path.join(rootdir, 'etc', 'apt', 'sources.list')
103 continue134 with open(srcfile, 'w') as f:
104 deps = set()135 mirror_prefix = get_geoip_country_code_prefix()
105 try:136 sources_list = string.Template(sources).substitute(
106 candidate_pkg = self.apt_cache[pkg].candidate137 {"mirror": mirror_prefix})
107 except KeyError:138 f.write(sources_list)
108 raise PackageNotFoundError(pkg)139 progress = apt.progress.text.AcquireProgress()
109 deps = candidate_pkg.dependencies140 apt_cache = apt.Cache(rootdir=rootdir, memonly=True)
110 if self.recommends:141 apt_cache.update(fetch_progress=progress, sources_list=srcfile)
111 deps += candidate_pkg.recommends142 apt_cache.open()
112 self.all_dep_names.add(pkg)143
113 add_deps([x[0].name for x in deps])144 return apt_cache
114 add_deps(package_names)
115145
116146
117def _fix_symlinks(debdir):147def _fix_symlinks(debdir):
118148
=== modified file 'snapcraft/tests/test_repo.py'
--- snapcraft/tests/test_repo.py 2015-09-01 19:04:49 +0000
+++ snapcraft/tests/test_repo.py 2015-09-21 15:29:20 +0000
@@ -23,15 +23,6 @@
2323
24class UbuntuTestCase(tests.TestCase):24class UbuntuTestCase(tests.TestCase):
2525
26 def test_unrecognized_package_raises_exception(self):
27 ubuntu = repo.Ubuntu('download_dir')
28
29 with self.assertRaises(repo.PackageNotFoundError) as raised:
30 ubuntu.get(['test_package'])
31
32 expected_message = 'The Ubuntu package \'test_package\' was not found'
33 self.assertEqual(raised.exception.message, expected_message)
34
35 def test_fix_symlinks(self):26 def test_fix_symlinks(self):
36 tempdirObj = tempfile.TemporaryDirectory()27 tempdirObj = tempfile.TemporaryDirectory()
37 self.addCleanup(tempdirObj.cleanup)28 self.addCleanup(tempdirObj.cleanup)

Subscribers

People subscribed via source and target branches

to all changes: