# Koji callback for extracting Maven artifacts (.pom and .jar files) # from an rpm and making them available via the Koji-managed Maven repo. # Copyright (c) 2010-2014 Red Hat, Inc. # # Authors: # Mike Bonnet import fnmatch import os import subprocess import koji from koji.context import context from koji.plugin import callback from koji.util import joinpath, rmtree CONFIG_FILE = '/etc/koji-hub/plugins/rpm2maven.conf' config = None @callback('postImport') def maven_import(cbtype, *args, **kws): global config if not context.opts.get('EnableMaven', False): return if kws.get('type') != 'rpm': return buildinfo = kws['build'] rpminfo = kws['rpm'] filepath = kws['filepath'] if not config: config = koji.read_config_files([(CONFIG_FILE, True)]) name_patterns = config.get('patterns', 'rpm_names').split() for pattern in name_patterns: if fnmatch.fnmatch(rpminfo['name'], pattern): break else: return tmpdir = joinpath(koji.pathinfo.work(), 'rpm2maven', koji.buildLabel(buildinfo)) try: if os.path.exists(tmpdir): rmtree(tmpdir) koji.ensuredir(tmpdir) expand_rpm(filepath, tmpdir) scan_and_import(buildinfo, rpminfo, tmpdir) finally: if os.path.exists(tmpdir): rmtree(tmpdir) def expand_rpm(filepath, tmpdir): devnull = open('/dev/null', 'r+') rpm2cpio = subprocess.Popen(['/usr/bin/rpm2cpio', filepath], stdout=subprocess.PIPE, stdin=devnull, stderr=devnull, close_fds=True) cpio = subprocess.Popen(['/bin/cpio', '-id'], stdin=rpm2cpio.stdout, cwd=tmpdir, stdout=devnull, stderr=devnull, close_fds=True) if rpm2cpio.wait() != 0 or cpio.wait() != 0: raise koji.CallbackError('error extracting files from %s, ' 'rpm2cpio returned %s, cpio returned %s' % (filepath, rpm2cpio.wait(), cpio.wait())) devnull.close() def scan_and_import(buildinfo, rpminfo, tmpdir): global config path_patterns = config.get('patterns', 'artifact_paths').split() maven_archives = [] for dirpath, dirnames, filenames in os.walk(tmpdir): relpath = dirpath[len(tmpdir):] for pattern in path_patterns: if fnmatch.fnmatch(relpath, pattern): break else: continue poms = [f for f in filenames if f.endswith('.pom')] if len(poms) != 1: continue pom_info = koji.parse_pom(joinpath(dirpath, poms[0])) maven_info = koji.pom_to_maven_info(pom_info) maven_archives.append({'maven_info': maven_info, 'files': [joinpath(dirpath, f) for f in filenames]}) if not maven_archives: return # We don't know which pom is the top-level pom, so we don't know what Maven # metadata to associate with the build. So we make something up. maven_build = {'group_id': buildinfo['name'], 'artifact_id': rpminfo['name'], 'version': '%(version)s-%(release)s' % buildinfo} context.handlers.call('host.createMavenBuild', buildinfo, maven_build) for entry in maven_archives: maven_info = entry['maven_info'] for filepath in entry['files']: if not context.handlers.call('getArchiveType', filename=filepath): # unsupported archive type, skip it continue context.handlers.call('host.importArchive', filepath, buildinfo, 'maven', maven_info)