Merge lp:~milo/linaro-image-tools/hwpack-handler into lp:linaro-image-tools/11.11
- hwpack-handler
- Merge into trunk
Proposed by
Milo Casagrande
Status: | Merged |
---|---|
Approved by: | Данило Шеган |
Approved revision: | 591 |
Merged at revision: | 589 |
Proposed branch: | lp:~milo/linaro-image-tools/hwpack-handler |
Merge into: | lp:linaro-image-tools/11.11 |
Diff against target: |
658 lines (+305/-270) 6 files modified
linaro_image_tools/hwpack/handler.py (+292/-0) linaro_image_tools/hwpack/hwpack_fields.py (+8/-3) linaro_image_tools/hwpack/hwpack_reader.py (+1/-1) linaro_image_tools/media_create/boards.py (+2/-264) linaro_image_tools/media_create/chroot_utils.py (+1/-1) linaro_image_tools/media_create/tests/test_media_create.py (+1/-1) |
To merge this branch: | bzr merge lp:~milo/linaro-image-tools/hwpack-handler |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Данило Шеган (community) | Approve | ||
Review via email:
|
Commit message
Hardwarepack handler refactoring.
Description of the change
First merge request towards addition of Android hwpack support to linaro-
The proposed branch contains some refactoring to clean and organize better the code, in this
case the class HardwarepackHandler has been moved into a separate module.
To post a comment you must log in.
- 591. By Milo Casagrande
-
Fixed copyright year, fixed indentation.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file 'linaro_image_tools/hwpack/handler.py' |
2 | --- linaro_image_tools/hwpack/handler.py 1970-01-01 00:00:00 +0000 |
3 | +++ linaro_image_tools/hwpack/handler.py 2012-12-07 09:40:34 +0000 |
4 | @@ -0,0 +1,292 @@ |
5 | +# Copyright (C) 2010, 2011, 2012 Linaro |
6 | +# |
7 | +# Author: Guilherme Salgado <guilherme.salgado@linaro.org> |
8 | +# |
9 | +# This file is part of Linaro Image Tools. |
10 | +# |
11 | +# Linaro Image Tools is free software: you can redistribute it and/or modify |
12 | +# it under the terms of the GNU General Public License as published by |
13 | +# the Free Software Foundation, either version 3 of the License, or |
14 | +# (at your option) any later version. |
15 | +# |
16 | +# Linaro Image Tools is distributed in the hope that it will be useful, |
17 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
19 | +# GNU General Public License for more details. |
20 | +# |
21 | +# You should have received a copy of the GNU General Public License |
22 | +# along with Linaro Image Tools. If not, see <http://www.gnu.org/licenses/>. |
23 | + |
24 | +from StringIO import StringIO |
25 | +import ConfigParser |
26 | +import logging |
27 | +import os |
28 | +import re |
29 | +import shutil |
30 | +import tarfile |
31 | +import tempfile |
32 | + |
33 | +from linaro_image_tools.hwpack.config import Config |
34 | +from linaro_image_tools.hwpack.builder import PackageUnpacker |
35 | +from linaro_image_tools.utils import DEFAULT_LOGGER_NAME |
36 | + |
37 | + |
38 | +logger = logging.getLogger(DEFAULT_LOGGER_NAME) |
39 | + |
40 | + |
41 | +class HardwarepackHandler(object): |
42 | + FORMAT_1 = '1.0' |
43 | + FORMAT_2 = '2.0' |
44 | + FORMAT_3 = '3.0' |
45 | + FORMAT_MIXED = '1.0and2.0' |
46 | + metadata_filename = 'metadata' |
47 | + format_filename = 'FORMAT' |
48 | + main_section = 'main' |
49 | + hwpack_tarfiles = [] |
50 | + tempdir = None |
51 | + |
52 | + def __init__(self, hwpacks, bootloader=None, board=None): |
53 | + self.hwpacks = hwpacks |
54 | + self.hwpack_tarfiles = [] |
55 | + self.bootloader = bootloader |
56 | + self.board = board |
57 | + self.tempdirs = {} |
58 | + # Used to store the config created from the metadata. |
59 | + self.config = None |
60 | + |
61 | + class FakeSecHead(object): |
62 | + """ Add a fake section header to the metadata file. |
63 | + |
64 | + This is done so we can use ConfigParser to parse the file. |
65 | + """ |
66 | + def __init__(self, fp): |
67 | + self.fp = fp |
68 | + self.sechead = '[%s]\n' % HardwarepackHandler.main_section |
69 | + |
70 | + def readline(self): |
71 | + if self.sechead: |
72 | + try: |
73 | + return self.sechead |
74 | + finally: |
75 | + self.sechead = None |
76 | + else: |
77 | + return self.fp.readline() |
78 | + |
79 | + def __enter__(self): |
80 | + self.tempdir = tempfile.mkdtemp() |
81 | + for hwpack in self.hwpacks: |
82 | + hwpack_tarfile = tarfile.open(hwpack, mode='r:gz') |
83 | + self.hwpack_tarfiles.append(hwpack_tarfile) |
84 | + return self |
85 | + |
86 | + def __exit__(self, type, value, traceback): |
87 | + for hwpack_tarfile in self.hwpack_tarfiles: |
88 | + if hwpack_tarfile is not None: |
89 | + hwpack_tarfile.close() |
90 | + self.hwpack_tarfiles = [] |
91 | + if self.tempdir is not None and os.path.exists(self.tempdir): |
92 | + shutil.rmtree(self.tempdir) |
93 | + |
94 | + for name in self.tempdirs: |
95 | + tempdir = self.tempdirs[name] |
96 | + if tempdir is not None and os.path.exists(tempdir): |
97 | + shutil.rmtree(tempdir) |
98 | + |
99 | + def _get_config_from_metadata(self, metadata): |
100 | + """ |
101 | + Retrieves a Config object associated with the metadata. |
102 | + |
103 | + :param metadata: The metadata to parse. |
104 | + :return: A Config instance. |
105 | + """ |
106 | + if not self.config: |
107 | + lines = metadata.readlines() |
108 | + if re.search("=", lines[0]) and not re.search(":", lines[0]): |
109 | + # Probably V2 hardware pack without [hwpack] on the first line |
110 | + lines = ["[hwpack]\n"] + lines |
111 | + self.config = Config(StringIO("".join(lines))) |
112 | + self.config.set_board(self.board) |
113 | + self.config.set_bootloader(self.bootloader) |
114 | + return self.config |
115 | + |
116 | + def get_field(self, field, return_keys=False): |
117 | + data = None |
118 | + hwpack_with_data = None |
119 | + keys = None |
120 | + for hwpack_tarfile in self.hwpack_tarfiles: |
121 | + metadata = hwpack_tarfile.extractfile(self.metadata_filename) |
122 | + parser = self._get_config_from_metadata(metadata) |
123 | + try: |
124 | + new_data = parser.get_option(field) |
125 | + if new_data is not None: |
126 | + assert data is None, "The metadata field '%s' is set to " \ |
127 | + "'%s' and new value '%s' is found" % (field, data, |
128 | + new_data) |
129 | + data = new_data |
130 | + hwpack_with_data = hwpack_tarfile |
131 | + if return_keys: |
132 | + keys = parser.get_last_used_keys() |
133 | + except ConfigParser.NoOptionError: |
134 | + continue |
135 | + |
136 | + if return_keys: |
137 | + return data, hwpack_with_data, keys |
138 | + return data, hwpack_with_data |
139 | + |
140 | + def get_format(self): |
141 | + format = None |
142 | + supported_formats = [self.FORMAT_1, self.FORMAT_2, self.FORMAT_3] |
143 | + for hwpack_tarfile in self.hwpack_tarfiles: |
144 | + format_file = hwpack_tarfile.extractfile(self.format_filename) |
145 | + format_string = format_file.read().strip() |
146 | + if not format_string in supported_formats: |
147 | + raise AssertionError( |
148 | + "Format version '%s' is not supported." % format_string) |
149 | + if format is None: |
150 | + format = format_string |
151 | + elif format != format_string: |
152 | + return self.FORMAT_MIXED |
153 | + return format |
154 | + |
155 | + def get_file(self, file_alias): |
156 | + """Get file(s) from a hwpack. |
157 | + :param file_alias: Property name (not field name) which contains |
158 | + file reference(s) |
159 | + :return: path to a file or list of paths to files |
160 | + """ |
161 | + file_names, hwpack_tarfile, keys = self.get_field(file_alias, |
162 | + return_keys=True) |
163 | + if not file_names: |
164 | + return file_names |
165 | + single = False |
166 | + if not isinstance(file_names, list): |
167 | + single = True |
168 | + file_names = [file_names] |
169 | + out_files = [] |
170 | + |
171 | + # Depending on if board and/or bootloader were used to look up the |
172 | + # file we are getting, we need to prepend those names to the path |
173 | + # to get the correct extracted file from the hardware pack. |
174 | + config_names = [("board", "boards"), ("bootloader", "bootloaders")] |
175 | + base_path = "" |
176 | + if keys: |
177 | + # If keys is non-empty, we have a V3 config option that was |
178 | + # modified by the bootloader and/or boot option... |
179 | + for name, key in config_names: |
180 | + if self.get_field(name): |
181 | + value = self.get_field(name)[0] |
182 | + if keys[0] == key: |
183 | + base_path = os.path.join(base_path, value) |
184 | + keys = keys[1:] |
185 | + |
186 | + for f in file_names: |
187 | + # Check that the base path is needed. If the file doesn't exist, |
188 | + # try without it (this provides fallback to V2 style directory |
189 | + # layouts with a V3 config). |
190 | + path_inc_board_and_bootloader = os.path.join(base_path, f) |
191 | + if path_inc_board_and_bootloader in hwpack_tarfile.getnames(): |
192 | + f = path_inc_board_and_bootloader |
193 | + hwpack_tarfile.extract(f, self.tempdir) |
194 | + f = os.path.join(self.tempdir, f) |
195 | + out_files.append(f) |
196 | + if single: |
197 | + return out_files[0] |
198 | + return out_files |
199 | + |
200 | + def list_packages(self): |
201 | + """Return list of (package names, TarFile object containing them)""" |
202 | + packages = [] |
203 | + for tf in self.hwpack_tarfiles: |
204 | + for name in tf.getnames(): |
205 | + if name.startswith("pkgs/") and name.endswith(".deb"): |
206 | + packages.append((tf, name)) |
207 | + return packages |
208 | + |
209 | + def find_package_for(self, name, version=None, revision=None, |
210 | + architecture=None): |
211 | + """Find a package that matches the name, version, rev and arch given. |
212 | + |
213 | + Packages are named according to the debian specification: |
214 | + http://www.debian.org/doc/manuals/debian-faq/ch-pkg_basics.en.html |
215 | + <name>_<Version>-<DebianRevisionNumber>_<DebianArchitecture>.deb |
216 | + DebianRevisionNumber seems to be optional. |
217 | + Use this spec to return a package matching the requirements given. |
218 | + """ |
219 | + for tar_file, package in self.list_packages(): |
220 | + file_name = os.path.basename(package) |
221 | + dpkg_chunks = re.search("^(.+)_(.+)_(.+)\.deb$", |
222 | + file_name) |
223 | + assert dpkg_chunks, "Could not split package file name into"\ |
224 | + "<name>_<Version>_<DebianArchitecture>.deb" |
225 | + |
226 | + pkg_name = dpkg_chunks.group(1) |
227 | + pkg_version = dpkg_chunks.group(2) |
228 | + pkg_architecture = dpkg_chunks.group(3) |
229 | + |
230 | + ver_chunks = re.search("^(.+)-(.+)$", pkg_version) |
231 | + if ver_chunks: |
232 | + pkg_version = ver_chunks.group(1) |
233 | + pkg_revision = ver_chunks.group(2) |
234 | + else: |
235 | + pkg_revision = None |
236 | + |
237 | + if name != pkg_name: |
238 | + continue |
239 | + if version != None and str(version) != pkg_version: |
240 | + continue |
241 | + if revision != None and str(revision) != pkg_revision: |
242 | + continue |
243 | + if (architecture != None and |
244 | + str(architecture) != pkg_architecture): |
245 | + continue |
246 | + |
247 | + # Got a matching package - return its path inside the tarball |
248 | + return tar_file, package |
249 | + |
250 | + # Failed to find a matching package - return None |
251 | + return None |
252 | + |
253 | + def get_file_from_package(self, file_path, package_name, |
254 | + package_version=None, package_revision=None, |
255 | + package_architecture=None): |
256 | + """Extract named file from package specified by name, ver, rev, arch. |
257 | + |
258 | + File is extracted from the package matching the given specification |
259 | + to a temporary directory. The absolute path to the extracted file is |
260 | + returned. |
261 | + """ |
262 | + |
263 | + package_info = self.find_package_for(package_name, |
264 | + package_version, |
265 | + package_revision, |
266 | + package_architecture) |
267 | + if package_info is None: |
268 | + return None |
269 | + tar_file, package = package_info |
270 | + |
271 | + # Avoid unpacking hardware pack more than once by assigning each one |
272 | + # its own tempdir to unpack into. |
273 | + # TODO: update logic that uses self.tempdir so we can get rid of this |
274 | + # by sharing nicely. |
275 | + if not package in self.tempdirs: |
276 | + self.tempdirs[package] = tempfile.mkdtemp() |
277 | + tempdir = self.tempdirs[package] |
278 | + |
279 | + # We extract everything in the hardware pack so we don't have to worry |
280 | + # about chasing links (extract a link, find where it points to, extract |
281 | + # that...). This is slower, but more reliable. |
282 | + tar_file.extractall(tempdir) |
283 | + package_path = os.path.join(tempdir, package) |
284 | + |
285 | + with PackageUnpacker() as self.package_unpacker: |
286 | + extracted_file = self.package_unpacker.get_file(package_path, |
287 | + file_path) |
288 | + after_tmp = re.sub(self.package_unpacker.tempdir, "", |
289 | + extracted_file).lstrip("/\\") |
290 | + extract_dir = os.path.join(tempdir, "extracted", |
291 | + os.path.dirname(after_tmp)) |
292 | + os.makedirs(extract_dir) |
293 | + shutil.move(extracted_file, extract_dir) |
294 | + extracted_file = os.path.join(extract_dir, |
295 | + os.path.basename(extracted_file)) |
296 | + return extracted_file |
297 | |
298 | === modified file 'linaro_image_tools/hwpack/hwpack_fields.py' |
299 | --- linaro_image_tools/hwpack/hwpack_fields.py 2012-10-02 14:53:56 +0000 |
300 | +++ linaro_image_tools/hwpack/hwpack_fields.py 2012-12-07 09:40:34 +0000 |
301 | @@ -86,10 +86,15 @@ |
302 | METADATA_VERSION_FIELD = 'version' |
303 | |
304 | # The allowed partition layouts. |
305 | +BOOTFS16 = 'bootfs16_rootfs' |
306 | +BOOTFS = 'bootfs_rootfs' |
307 | +RESERVED_BOOTFS = 'reserved_bootfs_rootfs' |
308 | + |
309 | DEFINED_PARTITION_LAYOUTS = [ |
310 | - 'bootfs16_rootfs', |
311 | - 'bootfs_rootfs', |
312 | - 'reserved_bootfs_rootfs', ] |
313 | + BOOTFS16, |
314 | + BOOTFS, |
315 | + RESERVED_BOOTFS, |
316 | + ] |
317 | |
318 | # Supported bootloaders |
319 | U_BOOT = 'u_boot' |
320 | |
321 | === modified file 'linaro_image_tools/hwpack/hwpack_reader.py' |
322 | --- linaro_image_tools/hwpack/hwpack_reader.py 2012-07-25 13:05:16 +0000 |
323 | +++ linaro_image_tools/hwpack/hwpack_reader.py 2012-12-07 09:40:34 +0000 |
324 | @@ -17,7 +17,7 @@ |
325 | # You should have received a copy of the GNU General Public License |
326 | # along with Linaro Image Tools. If not, see <http://www.gnu.org/licenses/>. |
327 | |
328 | -from linaro_image_tools.media_create.boards import HardwarepackHandler |
329 | +from linaro_image_tools.hwpack.handler import HardwarepackHandler |
330 | from linaro_image_tools.hwpack.hwpack_fields import ( |
331 | FORMAT_FIELD, |
332 | NAME_FIELD, |
333 | |
334 | === modified file 'linaro_image_tools/media_create/boards.py' |
335 | --- linaro_image_tools/media_create/boards.py 2012-10-22 06:57:20 +0000 |
336 | +++ linaro_image_tools/media_create/boards.py 2012-12-07 09:40:34 +0000 |
337 | @@ -31,13 +31,8 @@ |
338 | import tempfile |
339 | import struct |
340 | from binascii import crc32 |
341 | -import tarfile |
342 | -import ConfigParser |
343 | -import shutil |
344 | import string |
345 | import logging |
346 | -from linaro_image_tools.hwpack.config import Config |
347 | -from linaro_image_tools.hwpack.builder import PackageUnpacker |
348 | |
349 | from parted import Device |
350 | |
351 | @@ -45,7 +40,8 @@ |
352 | |
353 | from linaro_image_tools.media_create.partitions import ( |
354 | partition_mounted, SECTOR_SIZE, register_loopback) |
355 | -from StringIO import StringIO |
356 | + |
357 | +from linaro_image_tools.hwpack.handler import HardwarepackHandler |
358 | |
359 | logger = logging.getLogger(__name__) |
360 | |
361 | @@ -115,264 +111,6 @@ |
362 | return self.getter(cls) |
363 | |
364 | |
365 | -class HardwarepackHandler(object): |
366 | - FORMAT_1 = '1.0' |
367 | - FORMAT_2 = '2.0' |
368 | - FORMAT_3 = '3.0' |
369 | - FORMAT_MIXED = '1.0and2.0' |
370 | - metadata_filename = 'metadata' |
371 | - format_filename = 'FORMAT' |
372 | - main_section = 'main' |
373 | - hwpack_tarfiles = [] |
374 | - tempdir = None |
375 | - |
376 | - def __init__(self, hwpacks, bootloader=None, board=None): |
377 | - self.hwpacks = hwpacks |
378 | - self.hwpack_tarfiles = [] |
379 | - self.bootloader = bootloader |
380 | - self.board = board |
381 | - self.tempdirs = {} |
382 | - # Used to store the config created from the metadata. |
383 | - self.config = None |
384 | - |
385 | - class FakeSecHead(object): |
386 | - """ Add a fake section header to the metadata file. |
387 | - |
388 | - This is done so we can use ConfigParser to parse the file. |
389 | - """ |
390 | - def __init__(self, fp): |
391 | - self.fp = fp |
392 | - self.sechead = '[%s]\n' % HardwarepackHandler.main_section |
393 | - |
394 | - def readline(self): |
395 | - if self.sechead: |
396 | - try: |
397 | - return self.sechead |
398 | - finally: |
399 | - self.sechead = None |
400 | - else: |
401 | - return self.fp.readline() |
402 | - |
403 | - def __enter__(self): |
404 | - self.tempdir = tempfile.mkdtemp() |
405 | - for hwpack in self.hwpacks: |
406 | - hwpack_tarfile = tarfile.open(hwpack, mode='r:gz') |
407 | - self.hwpack_tarfiles.append(hwpack_tarfile) |
408 | - return self |
409 | - |
410 | - def __exit__(self, type, value, traceback): |
411 | - for hwpack_tarfile in self.hwpack_tarfiles: |
412 | - if hwpack_tarfile is not None: |
413 | - hwpack_tarfile.close() |
414 | - self.hwpack_tarfiles = [] |
415 | - if self.tempdir is not None and os.path.exists(self.tempdir): |
416 | - shutil.rmtree(self.tempdir) |
417 | - |
418 | - for name in self.tempdirs: |
419 | - tempdir = self.tempdirs[name] |
420 | - if tempdir is not None and os.path.exists(tempdir): |
421 | - shutil.rmtree(tempdir) |
422 | - |
423 | - def _get_config_from_metadata(self, metadata): |
424 | - """ |
425 | - Retrieves a Config object associated with the metadata. |
426 | - |
427 | - :param metadata: The metadata to parse. |
428 | - :return: A Config instance. |
429 | - """ |
430 | - if not self.config: |
431 | - lines = metadata.readlines() |
432 | - if re.search("=", lines[0]) and not re.search(":", lines[0]): |
433 | - # Probably V2 hardware pack without [hwpack] on the first line |
434 | - lines = ["[hwpack]\n"] + lines |
435 | - self.config = Config(StringIO("".join(lines))) |
436 | - self.config.set_board(self.board) |
437 | - self.config.set_bootloader(self.bootloader) |
438 | - return self.config |
439 | - |
440 | - def get_field(self, field, return_keys=False): |
441 | - data = None |
442 | - hwpack_with_data = None |
443 | - keys = None |
444 | - for hwpack_tarfile in self.hwpack_tarfiles: |
445 | - metadata = hwpack_tarfile.extractfile(self.metadata_filename) |
446 | - parser = self._get_config_from_metadata(metadata) |
447 | - try: |
448 | - new_data = parser.get_option(field) |
449 | - if new_data is not None: |
450 | - assert data is None, "The metadata field '%s' is set to " \ |
451 | - "'%s' and new value '%s' is found" % (field, data, |
452 | - new_data) |
453 | - data = new_data |
454 | - hwpack_with_data = hwpack_tarfile |
455 | - if return_keys: |
456 | - keys = parser.get_last_used_keys() |
457 | - except ConfigParser.NoOptionError: |
458 | - continue |
459 | - |
460 | - if return_keys: |
461 | - return data, hwpack_with_data, keys |
462 | - return data, hwpack_with_data |
463 | - |
464 | - def get_format(self): |
465 | - format = None |
466 | - supported_formats = [self.FORMAT_1, self.FORMAT_2, self.FORMAT_3] |
467 | - for hwpack_tarfile in self.hwpack_tarfiles: |
468 | - format_file = hwpack_tarfile.extractfile(self.format_filename) |
469 | - format_string = format_file.read().strip() |
470 | - if not format_string in supported_formats: |
471 | - raise AssertionError( |
472 | - "Format version '%s' is not supported." % format_string) |
473 | - if format is None: |
474 | - format = format_string |
475 | - elif format != format_string: |
476 | - return self.FORMAT_MIXED |
477 | - return format |
478 | - |
479 | - def get_file(self, file_alias): |
480 | - """Get file(s) from a hwpack. |
481 | - :param file_alias: Property name (not field name) which contains |
482 | - file reference(s) |
483 | - :return: path to a file or list of paths to files |
484 | - """ |
485 | - file_names, hwpack_tarfile, keys = self.get_field(file_alias, |
486 | - return_keys=True) |
487 | - if not file_names: |
488 | - return file_names |
489 | - single = False |
490 | - if not isinstance(file_names, list): |
491 | - single = True |
492 | - file_names = [file_names] |
493 | - out_files = [] |
494 | - |
495 | - # Depending on if board and/or bootloader were used to look up the |
496 | - # file we are getting, we need to prepend those names to the path |
497 | - # to get the correct extracted file from the hardware pack. |
498 | - config_names = [("board", "boards"), ("bootloader", "bootloaders")] |
499 | - base_path = "" |
500 | - if keys: |
501 | - # If keys is non-empty, we have a V3 config option that was |
502 | - # modified by the bootloader and/or boot option... |
503 | - for name, key in config_names: |
504 | - if self.get_field(name): |
505 | - value = self.get_field(name)[0] |
506 | - if keys[0] == key: |
507 | - base_path = os.path.join(base_path, value) |
508 | - keys = keys[1:] |
509 | - |
510 | - for f in file_names: |
511 | - # Check that the base path is needed. If the file doesn't exist, |
512 | - # try without it (this provides fallback to V2 style directory |
513 | - # layouts with a V3 config). |
514 | - path_inc_board_and_bootloader = os.path.join(base_path, f) |
515 | - if path_inc_board_and_bootloader in hwpack_tarfile.getnames(): |
516 | - f = path_inc_board_and_bootloader |
517 | - hwpack_tarfile.extract(f, self.tempdir) |
518 | - f = os.path.join(self.tempdir, f) |
519 | - out_files.append(f) |
520 | - if single: |
521 | - return out_files[0] |
522 | - return out_files |
523 | - |
524 | - def list_packages(self): |
525 | - """Return list of (package names, TarFile object containing them)""" |
526 | - packages = [] |
527 | - for tf in self.hwpack_tarfiles: |
528 | - for name in tf.getnames(): |
529 | - if name.startswith("pkgs/") and name.endswith(".deb"): |
530 | - packages.append((tf, name)) |
531 | - return packages |
532 | - |
533 | - def find_package_for(self, name, version=None, revision=None, |
534 | - architecture=None): |
535 | - """Find a package that matches the name, version, rev and arch given. |
536 | - |
537 | - Packages are named according to the debian specification: |
538 | - http://www.debian.org/doc/manuals/debian-faq/ch-pkg_basics.en.html |
539 | - <name>_<Version>-<DebianRevisionNumber>_<DebianArchitecture>.deb |
540 | - DebianRevisionNumber seems to be optional. |
541 | - Use this spec to return a package matching the requirements given. |
542 | - """ |
543 | - for tar_file, package in self.list_packages(): |
544 | - file_name = os.path.basename(package) |
545 | - dpkg_chunks = re.search("^(.+)_(.+)_(.+)\.deb$", |
546 | - file_name) |
547 | - assert dpkg_chunks, "Could not split package file name into"\ |
548 | - "<name>_<Version>_<DebianArchitecture>.deb" |
549 | - |
550 | - pkg_name = dpkg_chunks.group(1) |
551 | - pkg_version = dpkg_chunks.group(2) |
552 | - pkg_architecture = dpkg_chunks.group(3) |
553 | - |
554 | - ver_chunks = re.search("^(.+)-(.+)$", pkg_version) |
555 | - if ver_chunks: |
556 | - pkg_version = ver_chunks.group(1) |
557 | - pkg_revision = ver_chunks.group(2) |
558 | - else: |
559 | - pkg_revision = None |
560 | - |
561 | - if name != pkg_name: |
562 | - continue |
563 | - if version != None and str(version) != pkg_version: |
564 | - continue |
565 | - if revision != None and str(revision) != pkg_revision: |
566 | - continue |
567 | - if (architecture != None and |
568 | - str(architecture) != pkg_architecture): |
569 | - continue |
570 | - |
571 | - # Got a matching package - return its path inside the tarball |
572 | - return tar_file, package |
573 | - |
574 | - # Failed to find a matching package - return None |
575 | - return None |
576 | - |
577 | - def get_file_from_package(self, file_path, package_name, |
578 | - package_version=None, package_revision=None, |
579 | - package_architecture=None): |
580 | - """Extract named file from package specified by name, ver, rev, arch. |
581 | - |
582 | - File is extracted from the package matching the given specification |
583 | - to a temporary directory. The absolute path to the extracted file is |
584 | - returned. |
585 | - """ |
586 | - |
587 | - package_info = self.find_package_for(package_name, |
588 | - package_version, |
589 | - package_revision, |
590 | - package_architecture) |
591 | - if package_info is None: |
592 | - return None |
593 | - tar_file, package = package_info |
594 | - |
595 | - # Avoid unpacking hardware pack more than once by assigning each one |
596 | - # its own tempdir to unpack into. |
597 | - # TODO: update logic that uses self.tempdir so we can get rid of this |
598 | - # by sharing nicely. |
599 | - if not package in self.tempdirs: |
600 | - self.tempdirs[package] = tempfile.mkdtemp() |
601 | - tempdir = self.tempdirs[package] |
602 | - |
603 | - # We extract everything in the hardware pack so we don't have to worry |
604 | - # about chasing links (extract a link, find where it points to, extract |
605 | - # that...). This is slower, but more reliable. |
606 | - tar_file.extractall(tempdir) |
607 | - package_path = os.path.join(tempdir, package) |
608 | - |
609 | - with PackageUnpacker() as self.package_unpacker: |
610 | - extracted_file = self.package_unpacker.get_file(package_path, |
611 | - file_path) |
612 | - after_tmp = re.sub(self.package_unpacker.tempdir, "", |
613 | - extracted_file).lstrip("/\\") |
614 | - extract_dir = os.path.join(tempdir, "extracted", |
615 | - os.path.dirname(after_tmp)) |
616 | - os.makedirs(extract_dir) |
617 | - shutil.move(extracted_file, extract_dir) |
618 | - extracted_file = os.path.join(extract_dir, |
619 | - os.path.basename(extracted_file)) |
620 | - return extracted_file |
621 | - |
622 | - |
623 | class BoardConfig(object): |
624 | board = None |
625 | """The configuration used when building an image for a board.""" |
626 | |
627 | === modified file 'linaro_image_tools/media_create/chroot_utils.py' |
628 | --- linaro_image_tools/media_create/chroot_utils.py 2012-10-04 09:12:57 +0000 |
629 | +++ linaro_image_tools/media_create/chroot_utils.py 2012-12-07 09:40:34 +0000 |
630 | @@ -25,7 +25,7 @@ |
631 | is_arm_host, |
632 | find_command, |
633 | ) |
634 | -from linaro_image_tools.media_create.boards import HardwarepackHandler |
635 | +from linaro_image_tools.hwpack.handler import HardwarepackHandler |
636 | |
637 | # It'd be nice if we could use atexit here, but all the things we need to undo |
638 | # have to happen right after install_hwpacks completes and the atexit |
639 | |
640 | === modified file 'linaro_image_tools/media_create/tests/test_media_create.py' |
641 | --- linaro_image_tools/media_create/tests/test_media_create.py 2012-10-17 08:59:25 +0000 |
642 | +++ linaro_image_tools/media_create/tests/test_media_create.py 2012-12-07 09:40:34 +0000 |
643 | @@ -36,6 +36,7 @@ |
644 | from testtools import TestCase |
645 | |
646 | from linaro_image_tools import cmd_runner |
647 | +from linaro_image_tools.hwpack.handler import HardwarepackHandler |
648 | from linaro_image_tools.hwpack.packages import PackageMaker |
649 | import linaro_image_tools.media_create |
650 | from linaro_image_tools.media_create import ( |
651 | @@ -61,7 +62,6 @@ |
652 | _get_file_matching, |
653 | _get_mlo_file, |
654 | _run_mkimage, |
655 | - HardwarepackHandler, |
656 | BoardConfig, |
657 | ) |
658 | from linaro_image_tools.media_create.android_boards import ( |
Line
+ RESERVED_BOOTFS, ]
kind of misses the point (I know it was like that originally). The idea of using a trailing comma is to be able to easily reshuffle lines without worrying about broken punctuation.
While at it, please fix it to be
+ RESERVED_BOOTFS,
+ ]
Also, update the copyright to mention 2012 as well.
Otherwise, looks good (I am assuming there are no code changes otherwise).