From patchwork Tue Jul 19 01:27:23 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Westby X-Patchwork-Id: 2749 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 14F0923F44 for ; Tue, 19 Jul 2011 01:27:27 +0000 (UTC) Received: from mail-qy0-f180.google.com (mail-qy0-f180.google.com [209.85.216.180]) by fiordland.canonical.com (Postfix) with ESMTP id B1607A180DA for ; Tue, 19 Jul 2011 01:27:26 +0000 (UTC) Received: by qyk30 with SMTP id 30so2638177qyk.11 for ; Mon, 18 Jul 2011 18:27:26 -0700 (PDT) Received: by 10.229.217.3 with SMTP id hk3mr6099178qcb.38.1311038846066; Mon, 18 Jul 2011 18:27:26 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.229.217.78 with SMTP id hl14cs72802qcb; Mon, 18 Jul 2011 18:27:25 -0700 (PDT) Received: by 10.227.201.144 with SMTP id fa16mr1878343wbb.71.1311038844730; Mon, 18 Jul 2011 18:27:24 -0700 (PDT) Received: from adelie.canonical.com (adelie.canonical.com [91.189.90.139]) by mx.google.com with ESMTP id p6si8849094wbh.74.2011.07.18.18.27.24; Mon, 18 Jul 2011 18:27:24 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.139 as permitted sender) client-ip=91.189.90.139; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.139 as permitted sender) smtp.mail=bounces@canonical.com Received: from loganberry.canonical.com ([91.189.90.37]) by adelie.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1Qiz5n-0004sF-Oi for ; Tue, 19 Jul 2011 01:27:23 +0000 Received: from loganberry.canonical.com (localhost [127.0.0.1]) by loganberry.canonical.com (Postfix) with ESMTP id B74FB2E899C for ; Tue, 19 Jul 2011 01:27:23 +0000 (UTC) MIME-Version: 1.0 X-Launchpad-Project: linaro-image-tools X-Launchpad-Branch: ~linaro-image-tools/linaro-image-tools/trunk X-Launchpad-Message-Rationale: Subscriber X-Launchpad-Branch-Revision-Number: 379 X-Launchpad-Notification-Type: branch-revision To: Linaro Patch Tracker From: noreply@launchpad.net Subject: [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> Date: Tue, 19 Jul 2011 01:27:23 -0000 Reply-To: noreply@launchpad.net Sender: bounces@canonical.com Errors-To: bounces@canonical.com Precedence: bulk X-Generated-By: Launchpad (canonical.com); Revision="13405"; Instance="initZopeless config overlay" X-Launchpad-Hash: 1ca06d40dee2706ce26778dfe98d06f395045188 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 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 === 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 +# +# 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 . +# + +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())