1 |
#!/usr/bin/env python |
2 |
# dtar - Tool to produce .deb package from source tarball |
3 |
# Copyright (C) 2008 John Pye <john@curioussymbols.com> |
4 |
# |
5 |
# This program is free software; you can redistribute it and/or modify |
6 |
# it under the terms of the GNU General Public License as published by |
7 |
# the Free Software Foundation; either version 2, or (at your option) |
8 |
# any later version. |
9 |
# |
10 |
# This program is distributed in the hope that it will be useful, |
11 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 |
# GNU General Public License for more details. |
14 |
# |
15 |
# You should have received a copy of the GNU General Public License |
16 |
# along with this program; if not, write to the Free Software |
17 |
# Foundation, Inc., 59 Temple Place - Suite 330, |
18 |
# Boston, MA 02111-1307, USA. |
19 |
|
20 |
import sys, re, tarfile, os.path, subprocess |
21 |
import apt |
22 |
from debian_bundle import deb822, changelog |
23 |
|
24 |
# the tarball is the argument to this script |
25 |
f = sys.argv[1] |
26 |
|
27 |
# get the first filename in the tarball |
28 |
t = tarfile.open(f) |
29 |
M = t.getmembers() |
30 |
print M[0].name |
31 |
|
32 |
# split the top-level directory name from that path |
33 |
|
34 |
h,path = os.path.split(M[0].name) |
35 |
if not h: |
36 |
raise RuntimeError("Tarball appears not contain a top-level directory") |
37 |
|
38 |
while h: |
39 |
head = h |
40 |
h,path = os.path.split(path) |
41 |
|
42 |
print "Head directory = ",head |
43 |
|
44 |
r = re.compile(r"^%s/debian/(.*)$" % re.escape(head)) |
45 |
|
46 |
# search for 'debian/changelog' inside the tarfile |
47 |
|
48 |
debfiles = {} |
49 |
for m in M: |
50 |
if r.match(m.name): |
51 |
h,p = os.path.split(m.name) |
52 |
debfiles[p] = m |
53 |
|
54 |
|
55 |
fc = t.extractfile(debfiles['control']) |
56 |
|
57 |
# display mandatory fields from 'debian/control' |
58 |
|
59 |
controlmandatory = ['Source','Maintainer'] |
60 |
|
61 |
control = deb822.Deb822(fc.read()) |
62 |
for _c in controlmandatory: |
63 |
print "%s: %s" % (_c, control[_c]) |
64 |
|
65 |
# check that debian/changelog is current |
66 |
|
67 |
fchange = t.extractfile(debfiles['changelog']) |
68 |
|
69 |
changes = changelog.Changelog(file=fchange.read()) |
70 |
|
71 |
debianname = "%s-%s" % (control['Source'],changes.upstream_version) |
72 |
|
73 |
if debianname != head: |
74 |
raise RuntimeError("Debian files not up to date: debian/changelog refers to version '%s' but tarball head directory is '%s'" |
75 |
% (debianname,head)); |
76 |
|
77 |
# check for build-time dependencies |
78 |
|
79 |
dependencies = ['build-essential'] |
80 |
|
81 |
if 'Build-Depends' in control: |
82 |
#print "Build-Depends:",control['Build-Depends'] |
83 |
c = apt.Cache() |
84 |
dependencies += control['Build-Depends'].split(', ') |
85 |
|
86 |
print "Checking build dependencies..." |
87 |
depsmissing = [] |
88 |
for d in dependencies: |
89 |
p = c[d] |
90 |
if not p.isInstalled: |
91 |
depsmissing.append(d) |
92 |
|
93 |
if depsmissing: |
94 |
raise RuntimeError("Unable to proceed. Missing buildtime dependencies: %s" % (depsmissing)) |
95 |
|
96 |
# original tarball (recompressing to .gz if required) |
97 |
|
98 |
if f[-3:] == ".gz": |
99 |
print "Original tarball is in gzip format" |
100 |
elif f[-4:] == ".bz2": |
101 |
print "Original tarball is in bzip2 format" |
102 |
else: |
103 |
raise RuntimeError("Unrecognized tarball compression style") |
104 |
|
105 |
# extract tarball to tmp dir |
106 |
|
107 |
maindir = "/tmp/dtar-%s" % os.getpid() |
108 |
|
109 |
print "Extracting tarball to '%s'..." % maindir |
110 |
|
111 |
if os.path.exists(maindir): |
112 |
raise RuntimeError("Temp path '%s' already exists!"%maindir) |
113 |
|
114 |
os.mkdir(maindir) |
115 |
|
116 |
try: |
117 |
os.chdir(maindir) |
118 |
t.extractall() |
119 |
assert(os.path.exists(head)) |
120 |
print "Files extracted to '%s'" % os.getcwd() |
121 |
|
122 |
# build the source package |
123 |
print "Building source package..." |
124 |
res = subprocess.call(["dpkg-source","-b",head,f],executable="/usr/bin/dpkg-source") |
125 |
|
126 |
if res: |
127 |
raise RuntimeError("dpkg-source returned error code %d",res) |
128 |
|
129 |
# build the binary package |
130 |
print "Building binary package..." |
131 |
os.chdir(head) |
132 |
res = subprocess.call(["dpkg-buildpackage","-b","-rfakeroot"]) |
133 |
|
134 |
except Exception, e: |
135 |
print "ERROR: %s", str(e) |
136 |
|
137 |
#clean up files |
138 |
|
139 |
print "EXITING now" |
140 |
sys.exit(1) |
141 |
|
142 |
print "Cleaning up files..." |
143 |
assert maindir[:10]=="/tmp/dtar-" |
144 |
for _root,_dirs,_files in os.walk(maindir,topdown=False): |
145 |
for _f in _files: |
146 |
os.remove(os.path.join(_root,_f)) |
147 |
for _d in _dirs: |
148 |
os.rmdir(os.path.join(_root,_d)) |
149 |
print "All done, exiting" |
150 |
|
151 |
os.rmdir(maindir) |