#!/usr/bin/env python """ Copyright (c) 2018 Wind River Systems, Inc. SPDX-License-Identifier: Apache-2.0 """ import getopt import os import platform import rpm import shutil import subprocess import sys import tempfile import cgcs_patch.patch_functions as pf import cgcs_patch.patch_verify as pv import cgcs_patch.constants as constants import logging logging.getLogger('main_logger') logging.basicConfig(level=logging.INFO) # Override the pv.dev_certificate_marker so we can verify signatures off-box cgcs_patch_bindir = os.path.dirname(os.path.abspath(sys.argv[0])) dev_cert_path = os.path.abspath(os.path.join(cgcs_patch_bindir, '../../enable-dev-patch/enable-dev-patch/dev_certificate_enable.bin')) pv.dev_certificate_marker = dev_cert_path def usage(): print "Usage: %s -o ..." \ % os.path.basename(sys.argv[0]) exit(1) def main(): try: opts, remainder = getopt.getopt(sys.argv[1:], 'o:', ['output=']) except getopt.GetoptError: usage() output = None for opt, arg in opts: if opt == "--output" or opt == '-o': output = arg if output is None: usage() sw_version = os.environ['PLATFORM_RELEASE'] allpatches = pf.PatchData() output = os.path.abspath(output) pkgdir = os.path.join(output, 'Packages') datadir = os.path.join(output, 'metadata') committed_dir = os.path.join(datadir, 'committed') if os.path.exists(output): # Check to see if the expected structure already exists, # maybe we're appending a patch. if not os.path.exists(committed_dir) or not os.path.exists(pkgdir): print "Packages or metadata dir missing from existing %s. Aborting..." % output exit(1) # Load the existing metadata allpatches.load_all_metadata(committed_dir, constants.COMMITTED) else: os.mkdir(output, 0o755) os.mkdir(datadir, 0o755) os.mkdir(committed_dir, 0o755) os.mkdir(pkgdir, 0o755) # Save the current directory, so we can chdir back after orig_wd = os.getcwd() tmpdir = None try: for p in remainder: fpath = os.path.abspath(p) # Create a temporary working directory tmpdir = tempfile.mkdtemp(prefix="patchrepo_") # Change to the tmpdir os.chdir(tmpdir) print "Parsing %s" % fpath pf.PatchFile.read_patch(fpath) thispatch = pf.PatchData() patch_id = thispatch.parse_metadata("metadata.xml", constants.COMMITTED) if patch_id in allpatches.metadata: print "Skipping %s as it's already in the repo" % patch_id # Change back to original working dir os.chdir(orig_wd) shutil.rmtree(tmpdir) tmpdir = None continue patch_sw_version = thispatch.query_line(patch_id, 'sw_version') if patch_sw_version != sw_version: print "%s is for release %s, not %s" % (patch_sw_version, sw_version) # Move the metadata to the "committed" dir, and the rpms to the Packages dir shutil.move('metadata.xml', os.path.join(committed_dir, "%s-metadata.xml" % patch_id)) for f in thispatch.query_line(patch_id, 'contents'): shutil.move(f, pkgdir) allpatches.add_patch(patch_id, thispatch) # Change back to original working dir os.chdir(orig_wd) shutil.rmtree(tmpdir) tmpdir = None except: if tmpdir is not None: # Change back to original working dir os.chdir(orig_wd) shutil.rmtree(tmpdir) tmpdir = None raise allpatches.gen_release_groups_xml(sw_version, output) # Purge unneeded RPMs keep = {} for patch_id in allpatches.metadata.keys(): for rpmname in allpatches.contents[patch_id]: try: pkgname, arch, pkgver = pf.parse_rpm_filename(rpmname) except ValueError as e: raise e if pkgname not in keep: keep[pkgname] = { arch: pkgver } continue elif arch not in keep[pkgname]: keep[pkgname][arch] = pkgver continue # Compare versions keep_pkgver = keep[pkgname][arch] if pkgver > keep_pkgver: # Find the rpmname keep_rpmname = keep_pkgver.generate_rpm_filename(pkgname, arch) filename = os.path.join(pkgdir, keep_rpmname) if os.path.exists(filename): os.remove(filename) # Keep the new pkgver keep[pkgname][arch] = pkgver else: filename = os.path.join(pkgdir, rpmname) if os.path.exists(filename): os.remove(filename) # Create the repo metadata if os.path.exists('/usr/bin/createrepo_c'): createrepo = '/usr/bin/createrepo_c' else: createrepo = 'createrepo' os.chdir(output) subprocess.check_call([createrepo, '-g', 'comps.xml', '.']) if __name__ == "__main__": sys.exit(main())