Create build directory
[moonshot.git] / debian-builder
1 #!/usr/bin/python
2
3 from contextlib import contextmanager
4 import os, subprocess, exceptions
5 import debian.changelog, debian.deb822
6 from shutil import copy
7
8
9
10 packages = [
11     'shibboleth/xmltooling',
12     "shibboleth/opensaml2"]
13 distribution = "sid"
14 build_place = os.path.join(os.getcwd(), 'debian_build')
15
16 class CommandError(exceptions.StandardError):
17     pass
18
19 @contextmanager
20 def current_directory(dir):
21     "Change the current directory as a context manager; when the context exits, return."
22     cwd = os.getcwd()
23     os.chdir(dir)
24     yield
25     os.chdir(cwd)
26
27 def run_cmd(args, **kwords):
28     rcode =  subprocess.call( args, **kwords)
29     if rcode <> 0:
30         raise CommandError(args)
31
32 def command_output(args) :
33     p = subprocess.Popen(args, stdout=subprocess.PIPE)
34     output = p.communicate()
35     output = output[0]
36     if p.returncode != 0:
37         raise CommandError(args)
38     return output
39
40 def dsc_files(dsc) :
41     '''Describe all the files included in dsc, wich is a string name
42     of a dsc package. dsc itself is included'''
43     package = debian.deb822.Dsc(file(dsc))
44     internal_files = map( lambda(x): x['name'], package['Files'])
45     internal_files.append(dsc)
46     return internal_files
47
48 def build(package):
49     with current_directory(package):
50         cl = debian.changelog.Changelog(file('debian/changelog'))
51         package_name = cl.package
52         package_version = str(cl.version)
53         orig_tgz = package_name+'_'+ cl.upstream_version + ".orig.tar.gz"
54         dsc_name = package_name+"_"+package_version + ".dsc"
55         source_format = command_output(('dpkg-source', '--print-format', '.'))
56         if "native" not in source_format:
57             run_cmd( ('pristine-tar', 'checkout', '../'+orig_tgz))
58     package_path = os.path.split(package)
59     with current_directory(os.path.join ('.', *package_path[0:len(package_path)-1])) :
60         package_path = package_path[len(package_path)-1]
61         try:
62             run_cmd(("dpkg-source", '-b', '-i', package_path))
63             for f in dsc_files(dsc_name):
64                 copy(f, build_place)
65         finally:
66             for f in dsc_files(dsc_name):
67                 try: os.unlink(f)
68                 except OSError: pass
69     with current_directory(build_place):
70         run_cmd(('sbuild', '-d', distribution, '--setup-hook',
71     build_place + '/add_source',
72                  dsc_name))
73
74 def gen_package_files() :
75     '''Generate package files in build_place and a script
76     build_place/add_source that can be used as a sbuild setup hook to
77     include the package files. Unfortunately, apt doesn't have a
78     mechanism for asserting that a package file is trusted when it is
79     local. We could generate a unique gpg key, generate signed
80     releases files and trust that key. It's easier to simply touch the
81     release.gpg in apt's lists directory, which turns out to do what
82     we need.'''
83     # Rather than substuting the release file directly, we create gpg
84     # release files for any  local package list. That's easier than
85     # encoding apt's ideas about what characters to escape.
86     script = '''#!/bin/sh
87     set -e
88     echo deb file:{build_place} ./ >>/etc/apt/sources.list
89     apt-get update
90     touch $(ls /var/lib/apt/lists/_*Packages \
91         |sed -e s:Packages\$:Release.gpg:)
92     '''.format (
93         build_place = build_place
94         )
95     f = file(build_place + "/add_source", "w")
96     f.write(script)
97     f.close()
98     with current_directory(build_place):
99         run_cmd(('chmod', 'a+x', 'add_source'))
100         run_cmd( 'dpkg-scanpackages . >Packages',
101                  shell = True)
102         
103 try:
104     os.makedirs(build_place)
105 except OSError: pass
106
107 try:
108     for p in packages:
109         gen_package_files()
110         build(p)
111 except CommandError as c:
112     print "Error:" + str(c.args)
113     exit(1)
114
115