/[ascend]/trunk/tools/dtar/dtar
ViewVC logotype

Contents of /trunk/tools/dtar/dtar

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2003 - (show annotations) (download)
Fri Mar 13 05:30:00 2009 UTC (11 years, 6 months ago) by jpye
File size: 8381 byte(s)
Update to current freesteam.
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, shutil, getopt, glob
21 import apt
22 from debian_bundle import deb822, changelog
23
24 def usage():
25 print """%s: create debian package directly from source code tarball
26 %s [-s] originaltarball.tar.* [debian.tar.bz2|debian.tar.gz]
27
28 originaltarball.tar.*
29 The tarball containing the source code for the package
30 or packages you are going to create
31 debian.tar.*
32 OPTIONAL tarball containing the debian files
33 for your package. Only use this file if you have excluded
34 the debian/* files from your original source code tarball.
35 It is probably best to use a separate debian* tarball
36 for these files if you are likely to run into build
37 problems, eg when uploading packages to a build farm such
38 as Ubuntu PPA or openSUSE Build Service.
39
40 -s
41 --source Create source package only, no binary
42
43 -h
44 -help Print this message.
45
46 -o
47 --overwrite
48 Copy files into current directory *with overwrite* at the
49 end of the build.
50 """
51
52 opts,args = getopt.getopt(sys.argv[1:],"nhs",["help","source","nooverwrite"])
53
54 # do we just want a source package?
55 buildsource = False
56 overwrite = True
57
58
59 for _o,_a in opts:
60 if _o in ['-h','--help']:
61 usage()
62 sys.exit()
63 elif _o in ['-s','--source']:
64 buildsource = True
65 elif _o in ['-n','--nooverwrite']:
66 overwrite = False
67 else:
68 assert False,"unhandled option"
69
70 if len(args)<1 or len(args)>2:
71 raise RuntimeError("One or two tarballs must be supplied to dtar! (see dtar --help)")
72
73 # the tarball is the argument to this script
74
75 startingcwd = os.getcwd()
76
77 f = args[0]
78
79 fmeta = None
80 if len(args)==2:
81 # debian.tar.* meta-file tarball, optional
82 fmeta = args[1]
83 fmetafull = os.path.abspath(fmeta)
84
85 if not os.path.exists(fmeta):
86 raise RuntimeError("Debian metadata tarball '%s' was not found" % fmeta)
87
88 ffull = os.path.abspath(f)
89
90 # get the first filename in the tarball
91 t = tarfile.open(ffull)
92 M = t.getmembers()
93 print M[0].name
94
95 # split the top-level directory name from that path
96
97 h,path = os.path.split(M[0].name)
98 if not h:
99 raise RuntimeError("Tarball appears not contain a top-level directory")
100
101 while h:
102 head = h
103 h,path = os.path.split(path)
104
105 print "Head directory = ",head
106
107 r = re.compile(r"^%s/debian/([^/]*)$" % re.escape(head))
108 r2 = re.compile(r"^debian/([^/]*)$")
109
110 debfiles = {}
111 # this is a dictionary of sequences, first element 'm' or 's' depending
112 # on whether the debian file comes from the 'meta' tarball (if given), or the
113 # source tarball.
114
115 # search for debian/* files inside the original tarball
116
117 for m in M:
118 if r.match(m.name):
119 h,p = os.path.split(m.name)
120 debfiles[p] = [t,m]
121
122 # search for debian/* files inside the meta tarball
123 tmeta = None
124 if fmeta:
125 tmeta = tarfile.open(fmetafull)
126 Mmeta = tmeta.getmembers()
127 for m in Mmeta:
128 print "meta file contains '%s'" % m.name
129 if r2.match(m.name):
130 h,p = os.path.split(m.name)
131 debfiles[p] = [tmeta,m]
132
133 def getdebfile(name):
134 _t,_f = debfiles[name]
135 return _t.extractfile(_f)
136
137 mandatorydebfiles = ['control','changelog','rules']
138
139 missingdebfiles = []
140 for _f in mandatorydebfiles:
141 if _f not in debfiles:
142 missingdebfiles.append(_f)
143 if missingdebfiles:
144 s = "Tarball(s) missing required debian/* files: %s" %missingdebfiles
145 raise RuntimeError(s)
146
147 fc = getdebfile('control')
148
149 # display mandatory fields from 'debian/control'
150
151 controlmandatory = ['Source','Maintainer']
152
153 control = deb822.Deb822(fc.read())
154 for _c in controlmandatory:
155 print "%s: %s" % (_c, control[_c])
156
157 # check that debian/changelog is current
158
159 fchange = getdebfile('changelog')
160
161 changes = changelog.Changelog(file=fchange.read())
162
163 debianname = "%s-%s" % (control['Source'],changes.upstream_version)
164
165 if debianname != head:
166 raise RuntimeError("Debian files not up to date: debian/changelog refers to version '%s' but tarball head directory is '%s'"
167 % (debianname,head));
168
169 # check for build-time dependencies
170
171 dependencies = ['build-essential','fakeroot']
172
173 if 'Build-Depends' in control:
174 #print "Build-Depends:",control['Build-Depends']
175 c = apt.Cache()
176 dependencies += control['Build-Depends'].split(', ')
177
178 print "Checking build dependencies..."
179 depsmissing = []
180 for d in dependencies:
181 if d not in c or not c[d].isInstalled:
182 depsmissing.append(d)
183
184 if depsmissing:
185 raise RuntimeError("Unable to proceed. Missing buildtime dependencies: %s" % (depsmissing))
186
187 # extract tarball to tmp dir
188
189 maindir = "/tmp/dtar-%s" % os.getpid()
190
191 if os.path.exists(maindir):
192 raise RuntimeError("Temp path '%s' already exists!"%maindir)
193
194 os.mkdir(maindir)
195
196 try:
197 # extract source code tarball
198
199 print "Extracting tarball to '%s'..." % maindir
200 os.chdir(maindir)
201 t.extractall()
202 assert(os.path.exists(head))
203 print "Files extracted to '%s'" % os.getcwd()
204
205 # extract meta-file tarball if provided
206
207 if tmeta:
208 print "Extracting meta tarball to '%s'..." % maindir
209 os.chdir(os.path.join(maindir,debianname))
210 tmeta.extractall()
211 os.chdir(maindir)
212
213 assert(os.path.exists(os.path.join(head,"debian/control")))
214
215 # copy original tarball (recompressing to .gz if required?)
216
217 ext = ""
218 origname = "%s_%s.orig.tar.gz" % (control['Source'],changes.upstream_version)
219 t1 = t
220 if f[-7:] == ".tar.gz":
221 ext = ".tar.bz"
222 print "Original tarball is in gzip format"
223 shutil.copyfile(ffull, origname)
224 elif f[-8:] == ".tar.bz2":
225 ext = ".tar.bz2"
226 print "Original tarball is in bzip2 format"
227 temptar = "%s_%s.orig.tar" % (control['Source'],changes.upstream_version)
228 tempbz2 = "%s.bz2"%temptar
229 print "Copying '%s.bz2'" % temptar
230 print "ffull = ",ffull
231 shutil.copyfile(ffull,tempbz2)
232 assert(os.path.exists(tempbz2))
233 print "Unbzipping '%s'..." % tempbz2
234 subprocess.call(["bzip2","-d",tempbz2],executable="/bin/bzip2")
235 assert(os.path.exists(temptar))
236 print "Gzipping '%s'..." % temptar
237 subprocess.call(["gzip",temptar],executable="/bin/gzip")
238 print "Checking final path..."
239 assert(os.path.exists(origname))
240 else:
241 raise RuntimeError("Unrecognized tarball compression style")
242
243 # build the source package
244 #print "Building source package..."
245 #res = subprocess.call(["dpkg-source","-b",head,ffull],executable="/usr/bin/dpkg-source")
246
247 #if res:
248 # raise RuntimeError("dpkg-source returned error code %d" % res)
249
250 # build the binary package
251 os.chdir(head)
252 if buildsource:
253 print "Building source package..."
254 res = subprocess.call(["debuild","-rfakeroot","-S","-sa"])
255 else:
256 print "Building binary package..."
257 res = subprocess.call(["dpkg-buildpackage","-rfakeroot","-sa"])
258
259 if res:
260 raise RuntimeError("dpkg-buildpackage returned error code %s" % res)
261
262 except Exception, e:
263 print "ERROR: %s"% str(e)
264
265 print "Found files:"
266 os.chdir(maindir)
267 resultfiles = glob.glob("*.dsc") + glob.glob("*.deb") + glob.glob("*.gz") + glob.glob("*.changes")
268 print resultfiles
269
270 # move found files to current directory
271 failedtomovefiles = []
272 for _f in resultfiles:
273 _p2 = os.path.join(startingcwd,_f)
274
275 if not overwrite and os.path.exists(_p2):
276 failedtomovefiles.append(_f)
277 os.rename(_f, _p2)
278
279 if failedtomovefiles:
280 raise RuntimeError("Failed to move the following files (check --nooverwrite): %s",failedtomovefiles)
281
282 #clean up files
283
284 print "Cleaning up files from '%s'..." % maindir
285 assert maindir[:10]=="/tmp/dtar-"
286 for _root,_dirs,_files in os.walk(maindir,topdown=False):
287 for _f in _files:
288 os.remove(os.path.join(_root,_f))
289 for _d in _dirs:
290 os.rmdir(os.path.join(_root,_d))
291 print "All done, exiting"
292
293 os.rmdir(maindir)

Properties

Name Value
svn:executable *

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22