diff mbox

[Branch,~linaro-image-tools/linaro-image-tools/trunk] Rev 379: Add linaro-hwpack-replace to replace a .deb in a hwpack with another.

Message ID 20110719012723.29402.77054.launchpad@loganberry.canonical.com
State Accepted
Headers show

Commit Message

James Westby July 19, 2011, 1:27 a.m. UTC
Merge authors:
  Deepti B. Kalakeri (deeptik)
Related merge proposals:
  https://code.launchpad.net/~deeptik/linaro-image-tools/linaro-inject-debian-inhwpack/+merge/67667
  proposed by: Deepti B. Kalakeri (deeptik)
  review: Approve - James Westby (james-w)
------------------------------------------------------------
revno: 379 [merge]
committer: James Westby <james.westby@linaro.org>
branch nick: trunk
timestamp: Mon 2011-07-18 21:25:57 -0400
message:
  Add linaro-hwpack-replace to replace a .deb in a hwpack with another.
added:
  linaro-hwpack-replace


--
lp:linaro-image-tools
https://code.launchpad.net/~linaro-image-tools/linaro-image-tools/trunk

You are subscribed to branch lp:linaro-image-tools.
To unsubscribe from this branch go to https://code.launchpad.net/~linaro-image-tools/linaro-image-tools/trunk/+edit-subscription
diff mbox

Patch

=== added file 'linaro-hwpack-replace'
--- linaro-hwpack-replace	1970-01-01 00:00:00 +0000
+++ linaro-hwpack-replace	2011-07-19 01:25:57 +0000
@@ -0,0 +1,219 @@ 
+#!/usr/bin/env python
+# Copyright (C) 2010, 2011 Linaro
+#
+# Author: Deepti B. Kalakeri <deepti.kalakeri@linaro.org>
+#
+# This file is part of Linaro Image Tools. It adds the feature
+# to include/replace a debian package into the given hwpack
+#
+# 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 os
+import sys
+import shutil
+import logging
+import tarfile
+import tempfile
+import argparse
+import datetime
+import fileinput
+from debian.deb822 import Packages
+from linaro_image_tools.hwpack.packages import get_packages_file
+from linaro_image_tools.hwpack.packages import FetchedPackage
+
+
+parser = argparse.ArgumentParser()
+parser.add_argument("-t", "--hwpack_name", dest="hwpack_name",
+                    help="Specific hwpack_name to use (default: None)")
+parser.add_argument("-p", "--deb_pack", dest="deb_pack",
+                    help="Specific debian package to replace (default: None).")
+parser.add_argument("-d", "--debug-output", action="store_true", dest="debug",
+                    help="Verbose messages are displayed when specified")
+
+logger = logging.getLogger("linaro-hwpack-replace")
+
+
+class DummyStanza(object):
+
+    def __init__(self, info):
+        self.info = info
+
+    def dump(self, fd):
+        fd.write(get_packages_file([self.info]))
+
+
+def set_logging_param(args):
+    ch = logging.StreamHandler()
+    ch.setLevel(logging.INFO)
+    formatter = logging.Formatter("%(message)s")
+    ch.setFormatter(formatter)
+    logger.setLevel(logging.INFO)
+    logger.addHandler(ch)
+    if args.debug:
+        ch.setLevel(logging.DEBUG)
+        formatter = logging.Formatter(
+            "%(asctime)s - %(name)s - %(levelname)s - %(message)s")
+        ch.setFormatter(formatter)
+        logger.setLevel(logging.DEBUG)
+
+
+def get_hwpack_name(old_hwpack):
+    timestamp = [datetime.datetime.now().strftime("%Y%m%d-%H%S")]
+    hwpack_name_parts = (old_hwpack.split('_', 3))
+    return('_'.join(hwpack_name_parts[:2] + timestamp + hwpack_name_parts[3:]))
+
+
+def verify_existing_debians(debpack_dirname, new_debpack_info):
+    """
+       Find if the debian file with the same name exists,
+       if it exists then remove it and replace with the new deb file
+       If similar debian file exists then remove it
+    """
+
+    old_debpack_info = None
+    deb_file_to_remove = None
+
+    try:
+        for deb_filename in os.listdir(debpack_dirname):
+            root, ext = os.path.splitext(deb_filename)
+            root = root + '_'
+            if root.startswith("%s_" %new_debpack_info.name) and ext == '.deb':
+                deb_file_to_remove =  os.path.join(debpack_dirname, deb_filename)
+                old_debpack_info = FetchedPackage.from_deb(deb_file_to_remove)
+                os.remove(deb_file_to_remove)
+    except Exception, details:
+        logger.error("Error Details: %s", details)
+
+    return old_debpack_info
+
+
+def modify_manifest_info(tempdir, new_debpack_info, deb_pack_found):
+    """ Modify the manifest file to include the new debian information """
+
+    debpack_manifest_fname = os.path.join(tempdir, "manifest")
+    new_debpack_line = '%s=%s\n' % (new_debpack_info.name, new_debpack_info.version)
+
+    for line in fileinput.FileInput(debpack_manifest_fname, inplace=1):
+        if '=' in line:
+            package_name, version = line.split('=')
+            old_debpack = '%s=%s' % (package_name, version)
+        else:
+            package_name = line.rstrip("\n")
+            old_debpack = '%s' % package_name
+
+        if new_debpack_info.name == package_name:
+            deb_pack_found = 1
+            line = new_debpack_line
+        sys.stdout.write(line)
+
+    if deb_pack_found == 0:
+        logger.debug("Adding the new debian package info to manifest")
+        fout = open(debpack_manifest_fname, "a")
+        fout.write(new_debpack_line)
+        fout.close()
+    else:
+        logger.debug("Replaced the old debian package information "\
+                    "with the new information")
+
+
+def modify_Packages_info(debpack_dirname, new_debpack_info):
+    """ Modify the Packages file to include the new debian information """
+
+    debpack_Packages_fname = os.path.join(debpack_dirname, "Packages")
+    f = open(debpack_Packages_fname, "r+")
+    try:
+        output = []
+        for stanza in Packages.iter_paragraphs(f):
+            if stanza["Package"] == new_debpack_info.name:
+                output.append(DummyStanza(new_debpack_info))
+            else:
+                output.append(stanza)
+        f.seek(0,0)
+
+        for stanza in output:
+            stanza.dump(f)
+            f.write("\n")
+    finally:
+        f.close()
+
+
+def main():
+    # Validate that all the required information is passed on the command line
+    args = parser.parse_args()
+    if args.hwpack_name == None or args.deb_pack == None:
+        parser.print_help()
+        parser.error("You must specify both hwpack name "\
+                     "and the debian package information\n")
+        return 1
+
+    set_logging_param(args)
+
+    deb_pack_found = 0
+    old_debpack_info = None
+    old_hwpack = args.hwpack_name
+    new_deb_file_to_copy = args.deb_pack
+    status = 0
+
+    try:
+        # Get the new hardware pack name
+        hwpack_name = get_hwpack_name(old_hwpack)
+        if hwpack_name == None:
+            logger.error("Did not get a valid hwpack name, exiting")
+            return status
+
+        # untar the hardware pack and extract all the files in it
+        tar = tarfile.open(old_hwpack, "r:gz")
+        tempdir = tempfile.mkdtemp()
+        tar.extractall(tempdir)
+
+        # Search if a similar package with the same name exists, if yes then
+        # replace it. IF the old and new debian have the same name then we
+        # are still replacing the old one with the new one.
+        debpack_dirname = os.path.join(tempdir, 'pkgs/')
+        if not os.path.exists(debpack_dirname):
+            logger.error("Failed to extract the hwpack: %s ", old_hwpack)
+            return status
+
+        new_debpack_info = FetchedPackage.from_deb(new_deb_file_to_copy)
+
+        old_debpack_info = verify_existing_debians(debpack_dirname, new_debpack_info)
+
+        # Copy the new debian file to the pkgs dir,
+        shutil.copy2(new_deb_file_to_copy, debpack_dirname)
+
+        modify_manifest_info(tempdir, new_debpack_info, deb_pack_found)
+
+        modify_Packages_info(debpack_dirname, new_debpack_info)
+
+        #tar the hardware pack with the new debian file included in it
+        tar = tarfile.open( hwpack_name , "w:gz")
+        os.chdir(tempdir)
+        tar.add('.', recursive=True)
+        tar.close()
+    except Exception, details:
+        logger.error("Error Details: %s", details)
+        status = 1
+
+    if status == 0:
+        logger.info("The debian package '%s' has been been included in '%s'",
+                     new_deb_file_to_copy, hwpack_name)
+    else:
+        logger.error("Injecting the debian package '%s' failed", new_deb_file_to_copy)
+
+    return status
+
+
+if __name__ == '__main__':
+    sys.exit(main())