#!/usr/bin/python '''A script to buildMoonshot potentially using a schroot for install testing. ''' from contextlib import contextmanager import os, subprocess, exceptions import re import sys import string from optparse import OptionParser from shutil import copy # These variables can be overridden by options. If packages is not # set, then it is read from the rpm_packages file packages = [] # Set of packages to build tar_file = None class CommandError(exceptions.StandardError): pass # Centos 6.5 does not have collections.OrderedDict # This implementation provides the minimal functionality of OrderedDict that we need # It works here, but should not be counted on for anything else. class OrderedDict(dict): def __setitem__(self,k, v): if k not in self: self.keylist.append(k) return super(OrderedDict,self).__setitem__(k,v) def __init__(self, *args, **kwargs): super(OrderedDict,self).__init__(*args, **kwargs) self.keylist = [] def values(self): return map( lambda(elt): self[elt], self.keylist) def iteritems(self): for k in self.keylist: yield (k, self[k]) builder_by_type = { '.tar.gz': lambda(t): run_cmd([ 'rpmbuild', '-ta', t]), '.tar.bz2': lambda(t): run_cmd([ 'rpmbuild', '-ta', t]), '.spec': lambda(s): run_cmd(['rpmbuild', '--define', '_sourcedir '+os.getcwd(), '-ba', s]), } def find_type(name): match = re.match('^.*(\\.tar\\.gz|\\.tar\\.bz2|\\.spec)$', name) if match: return match.group(1) else: return None # The following regexp is not quite right. # One place is the rpm_packages file. # The other is the directory listing. # The rpm_packages file might have entries like shibboleth/xmltooling # Where as the distributions directory might have xmltooling-1.5.tar.gz # Two requirements for correct operation: # trim_target produces unique results for everything in rpm_packages # trim_target correctly trims what's in the packages file to the same # thing it trims the tar file or spec file to. # def trim_target(t): # first lose any suffix (like -1.5.tar.gz) name_parts=t.split('-') if name_parts[-1][0] in string.digits: name_parts=name_parts[:-1] name="-".join(name_parts) # in case it had dash-separated parts name="-".join(name.split("/")) # replace / with - return name @contextmanager def current_directory(dir): "Change the current directory as a context manager; when the context exits, return." cwd = os.getcwd() os.chdir(dir) yield os.chdir(cwd) def run_cmd(args, **kwords): rcode = subprocess.call( args, **kwords) if rcode <> 0: raise CommandError(args) def command_output(args) : p = subprocess.Popen(args, stdout=subprocess.PIPE) output = p.communicate() output = output[0] if p.returncode != 0: raise CommandError(args) return output.strip() def build(package): return builder_by_type[find_type(package)](package) def read_packages(): '''Read in the packages file from rpm_packages ''' try: pf = file("rpm_packages") except IOError: print "Error: rpm_packages file not found" exit(1) def is_comment(line): if re.match("^\\s*#", line): return False if "#" in line: raise ValueError( "Source package line contains a comment but not at beginning") return True return map(lambda(x): x.rstrip(), filter(is_comment, pf.readlines())) # main program opt = OptionParser() opt.usage = "%prog [options] distributions_dir [packages]" opt.add_option('--tar-file', dest='tar_file', help = 'Tar up resulting packages in given tar file', default = None) (options, args) = opt.parse_args() tar_file = options.tar_file if tar_file is not None: tar_file = os.path.join(os.getcwd(), tar_file) if len(args) == 0: print "Distributions directory required" exit(1) dist_dir = args[0] packages = args[1:] if len(packages) == 0: packages = read_packages() package_order = OrderedDict() for t in packages: package_order[trim_target(t)] = None for t in os.listdir(dist_dir): target_type = find_type(t) if target_type is None: continue trimmed = trim_target(t) if target_type == ".spec": package_order[trimmed] = t else: # Replace None but nothing else if not package_order.get(trimmed): package_order[trimmed] = t os.umask(022) try: run_cmd([ 'rm', '-rf', os.path.expanduser("~/rpmbuild")]) run_cmd([ 'rpmdev-setuptree']) for f in os.listdir("rpm-sources"): copy("rpm-sources/" + f, dist_dir) with current_directory(dist_dir): for t in package_order.values(): if t is None: continue build(t) if tar_file is not None: with current_directory(os.path.expanduser("~/rpmbuild")): run_cmd(['tar', '-cf', tar_file, './RPMS', './SRPMS']) except CommandError as c: print "Error:" + str(c.args) exit(1)