204
216
def get_file(self, file_alias):
205
file_name, hwpack_tarfile = self.get_field(file_alias)
206
if file_name is not None:
207
hwpack_tarfile.extract(file_name, self.tempdir)
208
file_name = os.path.join(self.tempdir, file_name)
217
"""Get file(s) from a hwpack.
218
:param file_alias: Property name (not field name) which contains
220
:return: path to a file or list of paths to files
222
file_names, hwpack_tarfile, keys = self.get_field(file_alias,
227
if not isinstance(file_names, list):
229
file_names = [file_names]
232
# Depending on if board and/or bootloader were used to look up the
233
# file we are getting, we need to prepend those names to the path
234
# to get the correct extracted file from the hardware pack.
235
config_names = [("board", "boards"), ("bootloader", "bootloaders")]
238
# If keys is non-empty, we have a V3 config option that was
239
# modified by the bootloader and/or boot option...
240
for name, key in config_names:
241
if self.get_field(name):
242
value = self.get_field(name)[0]
244
base_path = os.path.join(base_path, value)
248
# Check that the base path is needed. If the file doesn't exist,
249
# try without it (this provides fallback to V2 style directory
250
# layouts with a V3 config).
251
path_inc_board_and_bootloader = os.path.join(base_path, f)
252
if path_inc_board_and_bootloader in hwpack_tarfile.getnames():
253
f = path_inc_board_and_bootloader
254
hwpack_tarfile.extract(f, self.tempdir)
255
f = os.path.join(self.tempdir, f)
261
def list_packages(self):
262
"""Return list of (package names, TarFile object containing them)"""
264
for tf in self.hwpack_tarfiles:
265
for name in tf.getnames():
266
if name.startswith("pkgs/") and name.endswith(".deb"):
267
packages.append((tf, name))
270
def find_package_for(self, name, version=None, revision=None,
272
"""Find a package that matches the name, version, rev and arch given.
274
Packages are named according to the debian specification:
275
http://www.debian.org/doc/manuals/debian-faq/ch-pkg_basics.en.html
276
<name>_<Version>-<DebianRevisionNumber>_<DebianArchitecture>.deb
277
DebianRevisionNumber seems to be optional.
278
Use this spec to return a package matching the requirements given.
280
for tar_file, package in self.list_packages():
281
file_name = os.path.basename(package)
282
dpkg_chunks = re.search("^(.+)_(.+)_(.+)\.deb$",
284
assert dpkg_chunks, "Could not split package file name into"\
285
"<name>_<Version>_<DebianArchitecture>.deb"
287
pkg_name = dpkg_chunks.group(1)
288
pkg_version = dpkg_chunks.group(2)
289
pkg_architecture = dpkg_chunks.group(3)
291
ver_chunks = re.search("^(.+)-(.+)$", pkg_version)
293
pkg_version = ver_chunks.group(1)
294
pkg_revision = ver_chunks.group(2)
300
if version != None and str(version) != pkg_version:
302
if revision != None and str(revision) != pkg_revision:
304
if (architecture != None and
305
str(architecture) != pkg_architecture):
308
# Got a matching package - return its path inside the tarball
309
return tar_file, package
311
# Failed to find a matching package - return None
314
def get_file_from_package(self, file_path, package_name,
315
package_version=None, package_revision=None,
316
package_architecture=None):
317
"""Extract named file from package specified by name, ver, rev, arch.
319
File is extracted from the package matching the given specification
320
to a temporary directory. The absolute path to the extracted file is
324
package_info = self.find_package_for(package_name,
327
package_architecture)
328
if package_info is None:
330
tar_file, package = package_info
332
# Avoid unpacking hardware pack more than once by assigning each one
333
# its own tempdir to unpack into.
334
# TODO: update logic that uses self.tempdir so we can get rid of this
336
if not package in self.tempdirs:
337
self.tempdirs[package] = tempfile.mkdtemp()
338
tempdir = self.tempdirs[package]
340
# We extract everything in the hardware pack so we don't have to worry
341
# about chasing links (extract a link, find where it points to, extract
342
# that...). This is slower, but more reliable.
343
tar_file.extractall(tempdir)
344
package_path = os.path.join(tempdir, package)
346
with PackageUnpacker() as self.package_unpacker:
347
extracted_file = self.package_unpacker.get_file(package_path,
349
after_tmp = re.sub(self.package_unpacker.tempdir, "",
350
extracted_file).lstrip("/\\")
351
extract_dir = os.path.join(tempdir, "extracted",
352
os.path.dirname(after_tmp))
353
os.makedirs(extract_dir)
354
shutil.move(extracted_file, extract_dir)
355
extracted_file = os.path.join(extract_dir,
356
os.path.basename(extracted_file))
357
return extracted_file
212
360
class BoardConfig(object):
801
956
['cp', '-v', bootloader_bin, boot_disk], as_root=True)
959
# Handle copy_files field.
960
cls.copy_files(boot_disk)
804
962
cls.make_boot_files(
805
963
bootloader_parts_dir, is_live, is_lowmem, consoles, chroot_dir,
806
964
rootfs_id, boot_disk, boot_device_or_file)
967
def copy_files(cls, boot_disk):
968
"""Handle the copy_files metadata field."""
970
# Extract anything specified by copy_files sections
971
# self.bootloader_copy_files is always of the form:
974
# {'source_path': 'dest_path'}
977
if cls.bootloader_copy_files is None:
980
for source_package, file_list in cls.bootloader_copy_files.iteritems():
981
for file_info in file_list:
982
for source_path, dest_path in file_info.iteritems():
983
source = cls.hardwarepack_handler.get_file_from_package(
984
source_path, source_package)
985
dest_path = dest_path.lstrip("/\\")
986
dirname = os.path.dirname(dest_path)
987
dirname = os.path.join(boot_disk, dirname)
988
if not os.path.exists(dirname):
989
cmd_runner.run(["mkdir", "-p", dirname],
991
proc = cmd_runner.run(
993
os.path.join(boot_disk, dest_path)], as_root=True)
809
997
def _get_kflavor_files(cls, path):
810
998
"""Search for kernel, initrd and optional dtb in path."""
811
999
if cls.kernel_flavors is None: