diff options
author | James Tunnicliffe <james.tunnicliffe@linaro.org> | 2012-09-10 10:40:55 +0100 |
---|---|---|
committer | James Tunnicliffe <james.tunnicliffe@linaro.org> | 2012-09-10 10:40:55 +0100 |
commit | fa763179709cfa0be81e611faff895bd0d3835ce (patch) | |
tree | 2a1a29cdfbbf7067e6d4eb0dbf29b0522885d56f /linaro_image_tools/media_create/boards.py | |
parent | 1c495bc7c0a02762aefe9b6357ce9b4488b35079 (diff) |
Refactored copy_files support.
* Don't extract files into hwpack (leave in package)
* Extract files to target path.
TODO:
* Rename file support.
Diffstat (limited to 'linaro_image_tools/media_create/boards.py')
-rw-r--r-- | linaro_image_tools/media_create/boards.py | 138 |
1 files changed, 129 insertions, 9 deletions
diff --git a/linaro_image_tools/media_create/boards.py b/linaro_image_tools/media_create/boards.py index 1809e4a..d54f10e 100644 --- a/linaro_image_tools/media_create/boards.py +++ b/linaro_image_tools/media_create/boards.py @@ -37,6 +37,7 @@ import shutil import string import logging from linaro_image_tools.hwpack.config import Config +from linaro_image_tools.hwpack.builder import PackageUnpacker from parted import Device @@ -128,6 +129,7 @@ class HardwarepackHandler(object): self.hwpack_tarfiles = [] self.bootloader = bootloader self.board = board + self.tempdirs = {} class FakeSecHead(object): """ Add a fake section header to the metadata file. @@ -162,6 +164,11 @@ class HardwarepackHandler(object): if self.tempdir is not None and os.path.exists(self.tempdir): shutil.rmtree(self.tempdir) + for name in self.tempdirs: + tempdir = self.tempdirs[name] + if tempdir is not None and os.path.exists(tempdir): + shutil.rmtree(tempdir) + def get_field(self, field): data = None hwpack_with_data = None @@ -223,6 +230,97 @@ class HardwarepackHandler(object): return out_files[0] return out_files + def list_packages(self): + """Return list of (package names, TarFile object containing them)""" + packages = [] + for tf in self.hwpack_tarfiles: + for name in tf.getnames(): + if name.startswith("pkgs/") and name.endswith(".deb"): + packages.append((tf, name)) + return packages + + def find_package_for(self, name, version=None, revision=None, + architecture=None): + """Find a package that matches the name, version, rev and arch given. + + Packages are named according to the debian specification: + http://www.debian.org/doc/manuals/debian-faq/ch-pkg_basics.en.html + <name>_<Version>-<DebianRevisionNumber>_<DebianArchitecture>.deb + DebianRevisionNumber seems to be optional. + Use this spec to return a package matching the requirements given. + """ + for tar_file, package in self.list_packages(): + file_name = os.path.basename(package) + dpkg_chunks = re.search("^(.+)_(.+)_(.+)\.deb$", + file_name) + assert dpkg_chunks, "Could not split package file name into"\ + "<name>_<Version>_<DebianArchitecture>.deb" + + pkg_name = dpkg_chunks.group(1) + pkg_version = dpkg_chunks.group(2) + pkg_architecture = dpkg_chunks.group(3) + + ver_chunks = re.search("^(.+)-(.+)$", pkg_version) + if ver_chunks: + pkg_version = ver_chunks.group(1) + pkg_revision = ver_chunks.group(2) + else: + pkg_revision = None + + if name != pkg_name: + continue + if version != None and str(version) != pkg_version: + continue + if revision != None and str(revision) != pkg_revision: + continue + if (architecture != None and + str(architecture) != pkg_architecture): + continue + + # Got a matching package - return its path inside the tarball + return tar_file, package + + # Failed to find a matching package - return None + return None + + def get_file_from_package(self, file_path, package_name, + package_version=None, package_revision=None, + package_architecture=None): + """Extract named file from package specified by name, ver, rev, arch. + + File is extracted from the package matching the given specification + to a temporary directory. The absolute path to the extracted file is + returned. + """ + + package_info = self.find_package_for(package_name, + package_version, + package_revision, + package_architecture) + if package_info is None: + return None + tar_file, package = package_info + + # Avoid unpacking hardware pack more than once by assigning each one + # its own tempdir to unpack into. + # TODO: update logic that uses self.tempdir so we can get rid of this + # by sharing nicely. + if not package in self.tempdirs: + self.tempdirs[package] = tempfile.mkdtemp() + tempdir = self.tempdirs[package] + + # We extract everything in the hardware pack so we don't have to worry + # about chasing links (extract a link, find where it points to, extract + # that...). This is slower, but more reliable. + tar_file.extractall(tempdir) + package_path = os.path.join(tempdir, package) + + with PackageUnpacker() as self.package_unpacker: + extracted_file = self.package_unpacker.get_file(package_path, + file_path) + + return extracted_file + class BoardConfig(object): board = None @@ -465,6 +563,9 @@ class BoardConfig(object): cls.SAMSUNG_V310_BL2_START = (cls.SAMSUNG_V310_ENV_START + cls.SAMSUNG_V310_ENV_LEN) + cls.bootloader_copy_files = cls.hardwarepack_handler.get_field( + "bootloader_copy_files") + @classmethod def get_file(cls, file_alias, default=None): # XXX remove the 'default' parameter when V1 support is removed! @@ -793,7 +894,6 @@ class BoardConfig(object): bootloader_parts_dir = os.path.join(chroot_dir, parts_dir) cmd_runner.run(['mkdir', '-p', boot_disk]).wait() with partition_mounted(boot_partition, boot_disk): - boot_files = [] with cls.hardwarepack_handler: if cls.bootloader_file_in_boot_part: # <legacy v1 support> @@ -813,22 +913,42 @@ class BoardConfig(object): assert bootloader_bin is not None, ( "bootloader binary could not be found") - boot_files.append(bootloader_bin) - - copy_files = cls.get_file('boot_copy_files') - if copy_files: - boot_files.extend(copy_files) - - for f in boot_files: proc = cmd_runner.run( - ['cp', '-v', f, boot_disk], as_root=True) + ['cp', '-v', bootloader_bin, boot_disk], as_root=True) proc.wait() + # Handle copy_files field. + cls.copy_files(boot_disk) + cls.make_boot_files( bootloader_parts_dir, is_live, is_lowmem, consoles, chroot_dir, rootfs_id, boot_disk, boot_device_or_file) @classmethod + def copy_files(cls, boot_disk): + """Handle the copy_files metadata field.""" + + # Extract anything specified by copy_files sections + # self.bootloader_copy_files is always of the form: + # {'source_package': + # [ + # {'source_path': 'dest_path'} + # ] + # } + if cls.bootloader_copy_files is None: + return + + for source_package, file_list in cls.bootloader_copy_files.iteritems(): + for file_info in file_list: + for source_path, dest_path in file_info.iteritems(): + source = cls.hardwarepack_handler.get_file_from_package( + source_path, source_package) + proc = cmd_runner.run( + ['cp', '-v', source, + os.path.join(boot_disk, dest_path)], as_root=True) + proc.wait() + + @classmethod def _get_kflavor_files(cls, path): """Search for kernel, initrd and optional dtb in path.""" if cls.kernel_flavors is None: |