aboutsummaryrefslogtreecommitdiff
path: root/linaro-hwpack-append
diff options
context:
space:
mode:
authorMilo Casagrande <milo.casagrande@linaro.org>2013-12-16 12:33:35 +0100
committerMilo Casagrande <milo.casagrande@linaro.org>2013-12-20 10:23:10 +0100
commit4d5345db4c9c64d7952b664512542fdf40bd88ee (patch)
tree1f94afeabd049e109c59661ef33b483033ba73ab /linaro-hwpack-append
parentb59e7a8198c011786d92cfb05e0c971a391db820 (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-xlinaro-hwpack-append235
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()