Actually make install as root
[moonshot.git] / 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 source_packages file
17 packages = []  # Set of packages to build
18 prefix = "/usr/local/moonshot"
19 root_command = "fakeroot"
20
21 class CommandError(exceptions.StandardError):
22     pass
23
24 class Schroot(object):
25     '''Represents a schroot used for building moonshot.'''
26
27     def __init__(self, name):
28         '''Initialize a new schroot option from the named
29         schroot. Unless the named schroot starts with session:, then a
30         new session schroot is created.'''
31         if not name.startswith('session:'):
32             self.name = command_output(('schroot', '-b',
33                                         '-c', name))
34             self.end_session = True
35         else:
36             self.name = name
37             self.end_session = False
38
39     def __del__(self):
40         if self.end_session:
41             try:
42                 run_cmd(('schroot', '-e', '-c', self.name))
43             except CommandError: pass
44
45 @contextmanager
46 def current_directory(dir):
47     "Change the current directory as a context manager; when the context exits, return."
48     cwd = os.getcwd()
49     os.chdir(dir)
50     yield
51     os.chdir(cwd)
52
53
54 def run_cmd(args, **kwords):
55     rcode =  subprocess.call( args, **kwords)
56     if rcode <> 0:
57         raise CommandError(args)
58
59 def command_output(args) :
60     p = subprocess.Popen(args, stdout=subprocess.PIPE)
61     output = p.communicate()
62     output = output[0]
63     if p.returncode != 0:
64         raise CommandError(args)
65     return output.strip()
66
67 def build(package):
68     with current_directory(package):
69         run_cmd(('autoreconf', '-i', '-f'))
70         configure_command = ' '.join(['./configure'] + configure_opts)
71         print configure_command
72         sys.stdout.flush()
73         run_cmd(configure_command, shell=True)
74         run_cmd('make')
75
76 def make_install(package):
77     with current_directory(package):
78         install_command = root_command + " make install"
79         print install_command
80         sys.stdout.flush()
81         run_cmd(install_command, shell=True)
82         
83
84
85 def read_packages():
86     '''Read in the packages file from source_packages
87     '''
88     try: pf = file("source_packages")
89     except IOError:
90         print "Error: source_packages file not found"
91         exit(1)
92     def is_comment(line):
93         if re.match("^\\s*#", line): return False
94         if "#" in line: raise ValueError(
95             "Source package line contains a comment but not at beginning")
96         return True
97     return map(lambda(x): x.rstrip(),
98         filter(is_comment, pf.readlines()))
99
100
101 # main program
102 opt = OptionParser()
103 opt.add_option('--prefix',
104                dest="prefix", default=prefix,
105                help="Set the prefix under which packages are built and"
106                + "installed")
107 opt.add_option('-c', '--configure-opt', dest="configure_opts",
108                action="append",
109                help="Specify an option to pass to configure")
110 opt.add_option('-r', '--root-cmd', dest="root_command",
111                default=root_command,
112                help="Specify command to gain root for make install")
113 opt.add_option('-s', '--schroot',
114                dest="schroot",
115                help="Specify name of schroot to use for build;"
116                "implicitly sets root_command")
117 opt.usage = "%prog [options] [packages]"
118 (options, packages) = opt.parse_args()
119 prefix = options.prefix
120 root_command = options.root_command
121 configure_opts = ['--prefix', prefix,
122                   "LDFLAGS='-Wl,-L"+prefix+"/lib"
123                   + " -Wl,-R"+prefix+"/lib'",
124                   'CPPFLAGS="-I '+prefix+'/include"']
125 if options.configure_opts is not None: 
126     configure_opts.extend(options.configure_opts)
127
128 our_schroot = None
129 if options.schroot is not None:
130     our_schroot = Schroot(options.schroot)
131     root_command = "schroot -u root -r -c " + our_schroot.name
132
133 all_packages = read_packages()
134 if len(packages) == 0: packages = all_packages
135
136
137 try:
138     for p in all_packages:
139         if p in packages: build(p)
140         make_install(p)
141 except CommandError as c:
142     print "Error:" + str(c.args)
143     our_schroot = None
144     exit(1)
145 finally: del our_schroot
146
147     
148