Include freeradius in build
[moonshot.git] / rpm-builder
1 #!/usr/bin/python
2
3 '''A script to buildMoonshot  potentially using a schroot for install testing.
4 '''
5
6 from contextlib import contextmanager
7 import os, subprocess, exceptions
8 import re
9 import sys
10 from optparse import OptionParser
11 from shutil import copy
12
13
14
15 # These variables can be overridden by options. If packages is not
16 # set, then it is read from the rpm_packages file
17 packages = []  # Set of packages to build
18 tar_file = None
19
20 class CommandError(exceptions.StandardError):
21     pass
22
23 # Centos 6.5 does not have collections.OrderedDict
24 # This implementation provides the minimal functionality of OrderedDict that we need
25 # It works here, but should not be counted on for anything else.
26 class OrderedDict(dict):
27
28     def __setitem__(self,k, v):
29         if k not in self:
30             self.keylist.append(k)
31         return             super(OrderedDict,self).__setitem__(k,v)
32
33     def __init__(self, *args, **kwargs):
34         super(OrderedDict,self).__init__(*args, **kwargs)
35         self.keylist = []
36
37     def values(self):
38         return map( lambda(elt): self[elt], self.keylist)
39
40 builder_by_type = {
41     '.tar.gz': lambda(t): run_cmd([ 'rpmbuild', '-ta', t]),
42     '.spec':
43     lambda(s): run_cmd(['rpmbuild', '--define', '_sourcedir '+os.getcwd(),
44                         '-ba', s]),
45     }
46
47
48 def find_type(name):
49     match = re.match('^.*(\\.tar\\.gz|\\.spec)$', name)
50     if match:
51         return match.group(1)
52     else: return None
53         
54
55 # The following regexp is not quite right.
56 # One place is the rpm_packages file.
57 # The other is the directory listing.
58 # The rpm_packages file might have entries like shibboleth/xmltooling
59 # Where as the distributions directory might have xmltooling-1.5.tar.gz
60 # Two requirements for correct operation:
61 # trim_target produces unique results for everything in rpm_packages
62 # trim_target correctly trims what's in the packages file to the same
63 # thing it trims the tar file or spec file to.
64 #
65 def trim_target(t):
66     match = re.match('([^/-]*/)?([^-/]+)', t)
67     return match.group(2)
68
69     
70 @contextmanager
71 def current_directory(dir):
72     "Change the current directory as a context manager; when the context exits, return."
73     cwd = os.getcwd()
74     os.chdir(dir)
75     yield
76     os.chdir(cwd)
77
78
79 def run_cmd(args, **kwords):
80     rcode =  subprocess.call( args, **kwords)
81     if rcode <> 0:
82         raise CommandError(args)
83
84 def command_output(args) :
85     p = subprocess.Popen(args, stdout=subprocess.PIPE)
86     output = p.communicate()
87     output = output[0]
88     if p.returncode != 0:
89         raise CommandError(args)
90     return output.strip()
91
92 def build(package):
93     return builder_by_type[find_type(package)](package)
94
95
96
97 def read_packages():
98     '''Read in the packages file from rpm_packages
99     '''
100     try: pf = file("rpm_packages")
101     except IOError:
102         print "Error: rpm_packages file not found"
103         exit(1)
104     def is_comment(line):
105         if re.match("^\\s*#", line): return False
106         if "#" in line: raise ValueError(
107             "Source package line contains a comment but not at beginning")
108         return True
109     return map(lambda(x): x.rstrip(),
110         filter(is_comment, pf.readlines()))
111
112
113 # main program
114 opt = OptionParser()
115 opt.usage = "%prog [options] distributions_dir [packages]"
116 opt.add_option('--tar-file',
117                dest='tar_file',
118                help = 'Tar up resulting packages in given tar file',
119                default = None)
120 (options, args) = opt.parse_args()
121 tar_file = options.tar_file
122 if tar_file is not None:
123     tar_file = os.path.join(os.getcwd(), tar_file)
124 if len(args) == 0:
125     print "Distributions directory required"
126     exit(1)
127 dist_dir = args[0]
128 packages = args[1:]
129 if len(packages) == 0: packages = read_packages()
130 package_order = OrderedDict()
131 for t in packages:
132     package_order[trim_target(t)] = None
133
134 for t in os.listdir(dist_dir):
135     target_type = find_type(t)
136     if target_type is None: continue
137     trimmed = trim_target(t)
138     if target_type == ".spec":
139         package_order[trimmed] = t
140     else:
141         if trimmed not in package_order: package_order[trimmed] = t
142
143     
144
145 os.umask(022)
146
147 try:
148     run_cmd([ 'rm', '-rf',
149               os.path.expanduser("~/rpmbuild")])
150     run_cmd([ 'rpmdev-setuptree'])
151     for f in os.listdir("rpm-sources"):
152         copy("rpm-sources/" + f, dist_dir)
153
154     with current_directory(dist_dir):
155         for t in package_order.values():
156             if t is None: continue
157             build(t)
158     if tar_file is not None:
159         with current_directory(os.path.expanduser("~/rpmbuild")):
160             run_cmd(['tar', '-cf', tar_file,
161                      './RPMS', './SRPMS'])
162
163 except CommandError as c:
164     print "Error:" + str(c.args)
165     exit(1)
166
167
168     
169