diff options
author | Milo Casagrande <milo.casagrande@linaro.org> | 2013-12-16 12:33:35 +0100 |
---|---|---|
committer | Milo Casagrande <milo.casagrande@linaro.org> | 2013-12-20 10:23:10 +0100 |
commit | 4d5345db4c9c64d7952b664512542fdf40bd88ee (patch) | |
tree | 1f94afeabd049e109c59661ef33b483033ba73ab /linaro-hwpack-append | |
parent | b59e7a8198c011786d92cfb05e0c971a391db820 (diff) |
Added new linaro-hwpack-append dcommand line program.
* New command line program to add deb packages to an already existent
hardware pack.
Change-Id: I0fe28888a5134de718c09eaa1403b4cdad1f9c96
Diffstat (limited to 'linaro-hwpack-append')
-rwxr-xr-x | linaro-hwpack-append | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/linaro-hwpack-append b/linaro-hwpack-append new file mode 100755 index 0000000..cb586c6 --- /dev/null +++ b/linaro-hwpack-append @@ -0,0 +1,235 @@ +#!/usr/bin/env python +# Copyright (C) 2013 Linaro +# +# Author: Milo Casagrande <milo.casagrande@linaro.org> +# +# This file is part of Linaro Image Tools. It adds the feature +# to append a debian package into the given hwpack. +# We might need to change the manifest and Packages file in the +# future to match the hardware pack v2 changes when available. +# +# Linaro Image Tools 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 3 of the License, or +# (at your option) any later version. +# +# Linaro Image Tools 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 Linaro Image Tools. If not, see <http://www.gnu.org/licenses/>. +# + +import argparse +import atexit +import os +import sys +import tarfile +import tempfile +import shutil +from debian.arfile import ArError + +from linaro_image_tools.hwpack.packages import ( + get_packages_file, + FetchedPackage + ) +from linaro_image_tools.utils import get_logger +from linaro_image_tools.__version__ import __version__ + + +logger = None + + +def setup_args_parser(): + """Setup the argument parsing. + + :return The parsed arguments. + """ + description = "Adds new packages inside a hardware pack." + parser = argparse.ArgumentParser(version=__version__, + description=description) + parser.add_argument("-d", "--debug", action="store_true") + parser.add_argument("-t", "--hwpack", required=True, + help="The hardware pack to modify") + parser.add_argument("-p", "--package", action="append", required=True, + help="The debian package to append. Can be repeated " + "multiple times.") + parser.add_argument("-i", "--inplace", action="store_true", + help="Add the packages in place, without creating a " + "new hardware pack.") + return parser.parse_args() + + +def validate_args(args): + """Verify the arguments passed on the command line. + + :param args: The arguments passed. + """ + hwpack_path = os.path.abspath(args.hwpack) + + if not os.path.isfile(hwpack_path): + logger.error("Error: provided hardware pack file does not exists, or " + "is not a file: {0}.".format(args.hwpack)) + sys.exit(1) + + if not tarfile.is_tarfile(hwpack_path): + logger.error("Error: cannot read hardware pack file. Make sure it " + "is a supported tar archive.") + sys.exit(1) + + for package in args.package: + if not os.path.isfile(os.path.abspath(package)): + logger.error("Error: provided package to add does not exists, or " + "is not a file: {0}.".format(package)) + sys.exit(1) + + +def modify_manifest_file(debpackage_info, hwpack_dir): + """Modify the manifest file to include a new package entry. + + :param debpackage_info: The info to write. + :param hwpack_dir: Where the manifest file is located. + """ + debpack_manifest = os.path.join(hwpack_dir, "manifest") + new_debpack_line = '{0}={1}\n'.format(debpackage_info.name, + debpackage_info.version) + + logger.debug("Manifest line: {0}".format(new_debpack_line)) + + with open(debpack_manifest, "a") as manifest: + manifest.write(new_debpack_line) + + +def modify_packages_file(debpack_info, pkgs_dir): + """Modify the Packages file to include a new package entry. + + :param debpack_info: The info to be written. + :param pkgs_dir: The directory with the Packages file. + """ + debpack_Packages_fname = os.path.join(pkgs_dir, "Packages") + + package_info = get_packages_file([debpack_info]).strip() + + logger.debug("Packages line:\n{0}".format(package_info)) + + with open(debpack_Packages_fname, "a") as packages_file: + packages_file.write("{0}\n\n".format(package_info)) + + +def has_matching_package(pkg_to_search, dir_to_search): + """Search for a matching file name in the provided directory. + + :param pkg_to_search: The package whose name will be matched. + :param dir_to_search: Where to search for a matching name. + """ + logger.debug("Searching matching packages") + + package_found = False + for pkg in os.listdir(dir_to_search): + if os.path.basename(pkg_to_search) == os.path.basename(pkg): + package_found = True + break + return package_found + + +def add_packages_to_hwpack(hwpack, packages_to_add, inplace): + """Add the provided packages to the hardware pack. + + Each package to add will be checked against the already available packages: + if a similar one is found (it just need to have the same name), it will be + skipped. + + :param hwpack: The hardware pack where to add the new files. + :param packagess_to_add: List of package to add. + """ + hwpack = os.path.abspath(hwpack) + tempdir = tempfile.mkdtemp() + pkgs_dir = os.path.join(tempdir, 'pkgs') + + # Cleanup once done. + atexit.register(shutil.rmtree, tempdir) + + # Unfortunately we cannot operate in memory, Python tar library does not + # allow adding files with compressed tarballs. We have to extract it. + logger.info("Opening hardware pack {0}...".format(hwpack)) + logger.debug("Extracting hardware pack in {0}".format(tempdir)) + with tarfile.open(hwpack, "r|gz") as tar_file: + tar_file.extractall(tempdir) + + if not os.path.isdir(pkgs_dir): + logger.error("Error: tar file does not include packages directory.") + sys.exit(1) + + # Flag to check if we really need to save the new hwpack. + save_hwpack = False + + for debpackage in packages_to_add: + debpackage_path = os.path.abspath(debpackage) + + if has_matching_package(debpackage_path, pkgs_dir): + logger.warning("Found similar package in the tar archive: file " + "will not be added.") + continue + + if os.path.isfile(debpackage_path): + logger.info("Adding file {0}...".format(debpackage)) + + try: + debpackage_info = FetchedPackage.from_deb(debpackage_path) + except ArError: + logger.warning("File {0} is invalid, skipping " + "it.".format(debpackage)) + continue + + if debpackage_info: + logger.debug("Package info data:\n{0}".format(debpackage_info)) + modify_manifest_file(debpackage_info, tempdir) + modify_packages_file(debpackage_info, pkgs_dir) + + shutil.copy2(debpackage_path, pkgs_dir) + save_hwpack |= True + else: + logger.warning("Unable to find valid info for package " + "{0}.".format(debpackage)) + else: + logger.warning("File {0} does not exists, skipping " + "it.".format(debpackage)) + + if save_hwpack: + if inplace: + logger.info("Saving hardware pack {0}...".format(hwpack)) + with tarfile.open(hwpack, "w|gz") as tar_file: + tar_file.add(tempdir, arcname="") + else: + save_dir = os.path.dirname(hwpack) + + # Retrieve the file name without the extensions, and create a new + # file name. + root_ext, ext1 = os.path.splitext(os.path.basename(hwpack)) + root, ext2 = os.path.splitext(root_ext) + root += "_new" + new_file_name = root + ext2 + ext1 + save_file = os.path.join(save_dir, new_file_name) + + logger.info("Saving new hardware pack {0}...".format(save_file)) + with tarfile.open(save_file, "w|gz") as tar_file: + tar_file.add(tempdir, arcname="") + logger.info("New packages added successfully.") + else: + logger.info("No packages added. Exiting.") + + +def hwpack_append(): + args = setup_args_parser() + + global logger + logger = get_logger(debug=args.debug) + + validate_args(args) + add_packages_to_hwpack(args.hwpack, args.package, args.inplace) + + +if __name__ == '__main__': + hwpack_append() |