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

Contents of /trunk/tools/dtar/dtar

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1820 - (show annotations) (download)
Sat Aug 16 13:58:43 2008 UTC (15 years, 8 months ago) by jpye
File size: 8363 byte(s)
Fixed dtar to support separate debian.tar.gz file.
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']
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 p = c[d]
182 if not p.isInstalled:
183 depsmissing.append(d)
184
185 if depsmissing:
186 raise RuntimeError("Unable to proceed. Missing buildtime dependencies: %s" % (depsmissing))
187
188 # extract tarball to tmp dir
189
190 maindir = "/tmp/dtar-%s" % os.getpid()
191
192 if os.path.exists(maindir):
193 raise RuntimeError("Temp path '%s' already exists!"%maindir)
194
195 os.mkdir(maindir)
196
197 try:
198 # extract source code tarball
199
200 print "Extracting tarball to '%s'..." % maindir
201 os.chdir(maindir)
202 t.extractall()
203 assert(os.path.exists(head))
204 print "Files extracted to '%s'" % os.getcwd()
205
206 # extract meta-file tarball if provided
207
208 if tmeta:
209 print "Extracting meta tarball to '%s'..." % maindir
210 os.chdir(os.path.join(maindir,debianname))
211 tmeta.extractall()
212 os.chdir(maindir)
213
214 assert(os.path.exists(os.path.join(head,"debian/control")))
215
216 # copy original tarball (recompressing to .gz if required?)
217
218 ext = ""
219 origname = "%s_%s.orig.tar.gz" % (control['Source'],changes.upstream_version)
220 t1 = t
221 if f[-7:] == ".tar.gz":
222 ext = ".tar.bz"
223 print "Original tarball is in gzip format"
224 shutil.copyfile(ffull, origname)
225 elif f[-8:] == ".tar.bz2":
226 ext = ".tar.bz2"
227 print "Original tarball is in bzip2 format"
228 temptar = "%s_%s.orig.tar" % (control['Source'],changes.upstream_version)
229 tempbz2 = "%s.bz2"%temptar
230 print "Copying '%s.bz2'" % temptar
231 print "ffull = ",ffull
232 shutil.copyfile(ffull,tempbz2)
233 assert(os.path.exists(tempbz2))
234 print "Unbzipping '%s'..." % tempbz2
235 subprocess.call(["bzip2","-d",tempbz2],executable="/bin/bzip2")
236 assert(os.path.exists(temptar))
237 print "Gzipping '%s'..." % temptar
238 subprocess.call(["gzip",temptar],executable="/bin/gzip")
239 print "Checking final path..."
240 assert(os.path.exists(origname))
241 else:
242 raise RuntimeError("Unrecognized tarball compression style")
243
244 # build the source package
245 #print "Building source package..."
246 #res = subprocess.call(["dpkg-source","-b",head,ffull],executable="/usr/bin/dpkg-source")
247
248 #if res:
249 # raise RuntimeError("dpkg-source returned error code %d" % res)
250
251 # build the binary package
252 os.chdir(head)
253 if buildsource:
254 print "Building source package..."
255 res = subprocess.call(["debuild","-rfakeroot","-S","-sa"])
256 else:
257 print "Building binary package..."
258 res = subprocess.call(["dpkg-buildpackage","-rfakeroot","-sa"])
259
260 if res:
261 raise RuntimeError("dpkg-buildpackage returned error code %s" % res)
262
263 except Exception, e:
264 print "ERROR: %s"% str(e)
265
266 print "Found files:"
267 os.chdir(maindir)
268 resultfiles = glob.glob("*.dsc") + glob.glob("*.deb") + glob.glob("*.gz") + glob.glob("*.changes")
269 print resultfiles
270
271 # move found files to current directory
272 failedtomovefiles = []
273 for _f in resultfiles:
274 _p2 = os.path.join(startingcwd,_f)
275
276 if not overwrite and os.path.exists(_p2):
277 failedtomovefiles.append(_f)
278 os.rename(_f, _p2)
279
280 if failedtomovefiles:
281 raise RuntimeError("Failed to move the following files (check --nooverwrite): %s",failedtomovefiles)
282
283 #clean up files
284
285 print "Cleaning up files from '%s'..." % maindir
286 assert maindir[:10]=="/tmp/dtar-"
287 for _root,_dirs,_files in os.walk(maindir,topdown=False):
288 for _f in _files:
289 os.remove(os.path.join(_root,_f))
290 for _d in _dirs:
291 os.rmdir(os.path.join(_root,_d))
292 print "All done, exiting"
293
294 os.rmdir(maindir)

Properties

Name Value
svn:executable *

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