Merge lp:~broder/ubuntu-dev-tools/backportpackage into lp:~ubuntu-dev/ubuntu-dev-tools/trunk
- backportpackage
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 830 |
Proposed branch: | lp:~broder/ubuntu-dev-tools/backportpackage |
Merge into: | lp:~ubuntu-dev/ubuntu-dev-tools/trunk |
Diff against target: |
1120 lines (+611/-146) (has conflicts) 8 files modified
backportpackage (+293/-0) debian/changelog (+7/-0) doc/backportpackage.1 (+105/-0) doc/sponsor-patch.1 (+8/-3) setup.py (+1/-0) sponsor-patch (+61/-143) ubuntutools/builder.py (+81/-0) ubuntutools/logger.py (+55/-0) Text conflict in debian/changelog |
To merge this branch: | bzr merge lp:~broder/ubuntu-dev-tools/backportpackage |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Scott Kitterman | interface | Pending | |
Benjamin Drung | Pending | ||
Evan Broder | Pending | ||
Stefano Rivera | Pending | ||
Review via email: mp+43491@code.launchpad.net |
This proposal supersedes a proposal from 2010-12-12.
Commit message
Description of the change
At the Ubuntu Backports BOF at UDS-N (https:/
backportpackage is sort of vaguely analogous to syncpackage for backports. Note that while it should have all of the correct semantics for actually doing a backport to the Ubuntu archive, those should continue to be handled by the Archive Admins. backportpackage is really intended for uploading backports to a PPA.
Benjamin Drung (bdrung) wrote : Posted in a previous version of this proposal | # |
Stefano Rivera (stefanor) wrote : Posted in a previous version of this proposal | # |
Should this be installed by setup.py? (it isn't, yet it appears in the changelog).
Note that on Debian users can't use ppa:X syntax with dput, due to http://
{syncpackage, sponsor-patch} uses the current directory, ack-sync (although it isn't installed) uses /tmp/ack-sync, backportpackage uses a temporary directory. sponsor-patch prints a file:/// URI, others print local paths. I wish there were some consistency.
Evan Broder (broder) wrote : Posted in a previous version of this proposal | # |
Heh. I...guess I sort of expected the script to get magically installed. Clever plan, that one.
In terms of the directory to use, I'm happy to change backportpackage to use the current directory, but I honestly kind of hate it when scripts go and drop stuff all over my cwd. Let me know what your preferences are as package maintainers.
Stefano Rivera (stefanor) wrote : Posted in a previous version of this proposal | # |
I'm with you on the current directory thing. But I'm also hesitant about adding a 3rd behavior.
I guess that as this generates something the user isn't expecting to work with, /tmp is correct. But then I think we should give mkdtemp a 'backportpackage' prefix (so it can be easily tab-completed) and document the fact that it'll build in /tmp in the manpage.
Stefano Rivera (stefanor) wrote : Posted in a previous version of this proposal | # |
LGTM, although still with reservations about defaulting to the -backports pocket (which makes the tool hard to use on Debian, you have to say you are going to upload to Debian, then dput to your ppa in another terminal, while it's asking for confirmation)
Evan Broder (broder) wrote : Posted in a previous version of this proposal | # |
I think you're reading the logic backwards. backportpackage defaults to the release pocket *unless* the upload target is "ubuntu" (i.e. if you were doing a real backport).
Last time I checked, PPAs don't support uploading to anything but the release pocket, so the intent is that if you upload to a PPA, it goes to the release pocket, and if you upload to the archive proper, it goes to the -backports pocket.
Benjamin Drung (bdrung) wrote : Posted in a previous version of this proposal | # |
sponsor-patch prints a file:/// URI to make them click-able in gnome-terminal.
The default workdir of sponsor-patch can be changed to point to temporary directory instead of cwd.
Benjamin Drung (bdrung) wrote : Posted in a previous version of this proposal | # |
Use subprocess.call instead of subprocess.
How do you ensure that the orig source tarball is available in the upload destination?
Evan Broder (broder) wrote : Posted in a previous version of this proposal | # |
Ok, file:/// justification makes sense. I'll updated backportpackage to use that.
I'm also not currently checking to see if the orig tarball is available. Fixing by passing -sa to debuild -S.
Stefano Rivera (stefanor) wrote : Posted in a previous version of this proposal | # |
Sorry yes, I was commenting from memory, always a bad idea. The only check based on "ppa:" is to add ~ppa1. That's fine.
New issue: Your use subprocess.call and check_call. You use it correctly for pull-lp-source.
For dch, you should probably check "== 0", instead of "not" because returncode can be negative if dch was killed.
For debuild, remember that check_call will throw, not return, on error.
Stefano Rivera (stefanor) : Posted in a previous version of this proposal | # |
Evan Broder (broder) wrote : Posted in a previous version of this proposal | # |
Actually, please hold off on merging this for the moment. I'd like to adjust the interface to accept multiple destination releases and do a backport to each one.
Benjamin Drung (bdrung) wrote : Posted in a previous version of this proposal | # |
"Something went wrong updating the package changelog" is not very precise. You could tell that the "dch" command fail and tell the exit code.
- 847. By Evan Broder
-
backportpackage: Unquote URLs we get back from LP
- 848. By Evan Broder
-
backportpackage: Abort if build fails
- 849. By Evan Broder
-
backportpackage: Error if neither -b nor -u is specified
- 850. By Evan Broder
-
backportpackage: --source/
--destination instead of --from/--to - 851. By Evan Broder
-
backportpackage: Eliminate global variables
- 852. By Evan Broder
-
backportpackage: Pass around options instead of options container
- 853. By Evan Broder
-
backportpackage: If no dest release is specified, default to the current release
- 854. By Evan Broder
-
doc/backportpac
kage.1: Add an EXAMPLES section - 855. By Evan Broder
-
backportpackage: Allow specifying a working directory
- 856. By Evan Broder
-
backportpackage: Accept a URL or path to a .dsc file as an alternative to a source package name
Preview Diff
1 | === added file 'backportpackage' |
2 | --- backportpackage 1970-01-01 00:00:00 +0000 |
3 | +++ backportpackage 2010-12-16 09:14:08 +0000 |
4 | @@ -0,0 +1,293 @@ |
5 | +#!/usr/bin/python |
6 | +# -*- coding: utf-8 -*- |
7 | +# ################################################################## |
8 | +# |
9 | +# This program is free software; you can redistribute it and/or |
10 | +# modify it under the terms of the GNU General Public License |
11 | +# as published by the Free Software Foundation; version 2. |
12 | +# |
13 | +# This program is distributed in the hope that it will be useful, |
14 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | +# GNU General Public License for more details. |
17 | +# |
18 | +# See file /usr/share/common-licenses/GPL-2 for more details. |
19 | +# |
20 | +# ################################################################## |
21 | + |
22 | +import optparse |
23 | +import os |
24 | +import shutil |
25 | +import subprocess |
26 | +import sys |
27 | +import tempfile |
28 | +import urllib |
29 | + |
30 | +from debian.deb822 import Dsc |
31 | +import launchpadlib.launchpad |
32 | +import lsb_release |
33 | + |
34 | +from ubuntutools.builder import getBuilder |
35 | +from ubuntutools.logger import Logger |
36 | + |
37 | +def error(msg): |
38 | + Logger.error(msg) |
39 | + sys.exit(1) |
40 | + |
41 | +def check_call(cmd, *args, **kwargs): |
42 | + Logger.command(cmd) |
43 | + ret = subprocess.call(cmd, *args, **kwargs) |
44 | + if ret != 0: |
45 | + error('%s returned %d' % (cmd, ret)) |
46 | + |
47 | +def parse(args): |
48 | + usage = 'Usage: %prog [options] <source package name or .dsc URL/file>' |
49 | + p = optparse.OptionParser(usage) |
50 | + p.add_option('-d', '--destination', |
51 | + dest='dest_releases', |
52 | + default=[], |
53 | + action='append', |
54 | + help='Backport to DEST release (default: current release)', |
55 | + metavar='DEST') |
56 | + p.add_option('-s', '--source', |
57 | + dest='source_release', |
58 | + default=None, |
59 | + help='Backport from SOURCE release (default: devel release)', |
60 | + metavar='SOURCE') |
61 | + p.add_option('-b', '--build', |
62 | + dest='build', |
63 | + default=False, |
64 | + action='store_true', |
65 | + help='Build the package before uploading (default: %default)') |
66 | + p.add_option('-B', '--builder', |
67 | + dest='builder', |
68 | + default=None, |
69 | + help='Specify the package builder (default: pbuilder)', |
70 | + metavar='BUILDER') |
71 | + p.add_option('-u', '--upload', |
72 | + dest='upload', |
73 | + help='Specify an upload destination', |
74 | + metavar='UPLOAD') |
75 | + p.add_option('-v', '--version', |
76 | + dest='version', |
77 | + default=None, |
78 | + help='Package version to backport (or verify)', |
79 | + metavar='VERSION') |
80 | + p.add_option('-w', '--workdir', |
81 | + dest='workdir', |
82 | + default=None, |
83 | + help='Specify a working directory (default: temporary dir)', |
84 | + metavar='WORKDIR') |
85 | + p.add_option('-l', '--launchpad', |
86 | + dest='launchpad', |
87 | + default='production', |
88 | + help='Launchpad instance to connect to (default: %default)', |
89 | + metavar='INSTANCE') |
90 | + |
91 | + opts, args = p.parse_args(args) |
92 | + if len(args) != 1: |
93 | + p.error('You must specify a single source package or a .dsc URL/path') |
94 | + if not opts.upload and not opts.build: |
95 | + p.error('Nothing to do') |
96 | + |
97 | + return opts, args |
98 | + |
99 | +def find_release_package(lp, package, version, source_release): |
100 | + ubuntu = lp.distributions['ubuntu'] |
101 | + archive = ubuntu.main_archive |
102 | + series = ubuntu.getSeries(name_or_version=source_release) |
103 | + status = 'Published' |
104 | + for pocket in ('Updates', 'Security', 'Release'): |
105 | + try: |
106 | + srcpkg = archive.getPublishedSources(source_name=package, |
107 | + distro_series=series, |
108 | + pocket=pocket, |
109 | + status=status, |
110 | + exact_match=True)[0] |
111 | + break |
112 | + except IndexError: |
113 | + continue |
114 | + else: |
115 | + error('Unable to find package %s in release %s' % |
116 | + (package, source_release)) |
117 | + |
118 | + if version and version != srcpkg.source_package_version: |
119 | + error('Requested backport of version %s but %s is at version %s' % |
120 | + (version, package, srcpkg.source_package_version)) |
121 | + |
122 | + return srcpkg |
123 | + |
124 | +def find_version_package(lp, package, version): |
125 | + ubuntu = lp.distributions['ubuntu'] |
126 | + archive = ubuntu.main_archive |
127 | + try: |
128 | + # Might get more than one (i.e. same version in multiple |
129 | + # releases), but they should all be identical |
130 | + return archive.getPublishedSources(source_name=package, |
131 | + version=version)[0] |
132 | + except IndexError: |
133 | + error('Version %s of package %s was never published in Ubuntu' % |
134 | + (version, package)) |
135 | + |
136 | +def dscurl_from_package(lp, workdir, package, version, source_release): |
137 | + if not source_release and not version: |
138 | + source_release = lp.distributions['ubuntu'].current_series.name |
139 | + |
140 | + # If source_release is specified, then version is just for |
141 | + # verification |
142 | + if source_release: |
143 | + srcpkg = find_release_package(lp, package, version, source_release) |
144 | + else: |
145 | + srcpkg = find_version_package(lp, package, version) |
146 | + |
147 | + for f in srcpkg.sourceFileUrls(): |
148 | + if f.endswith('.dsc'): |
149 | + return urllib.unquote(f) |
150 | + else: |
151 | + error('Package %s contains no .dsc file' % package) |
152 | + |
153 | +def dscurl_from_dsc(package): |
154 | + path = os.path.abspath(os.path.expanduser(package)) |
155 | + if os.path.exists(path): |
156 | + return 'file://%s' % path |
157 | + else: |
158 | + # Can't resolve it as a local path? Let's just hope it's good |
159 | + # as-is |
160 | + return package |
161 | + |
162 | +def fetch_package(lp, workdir, package, version, source_release): |
163 | + # Returns the path to the .dsc file that was fetched |
164 | + |
165 | + if package.endswith('.dsc'): |
166 | + dsc = dscurl_from_dsc(package) |
167 | + else: |
168 | + dsc = dscurl_from_package(lp, workdir, package, version, source_release) |
169 | + |
170 | + check_call(['dget', |
171 | + '--download-only', |
172 | + '--allow-unauthenticated', |
173 | + dsc], |
174 | + cwd=workdir) |
175 | + return os.path.join(workdir, os.path.basename(dsc)) |
176 | + |
177 | +def get_backport_version(version, upload, release): |
178 | + v = version + ('~%s1' % release) |
179 | + if upload and upload.startswith('ppa:'): |
180 | + v += '~ppa1' |
181 | + return v |
182 | + |
183 | +def get_backport_dist(upload, release): |
184 | + if not upload or upload == 'ubuntu': |
185 | + return '%s-backports' % release |
186 | + else: |
187 | + return release |
188 | + |
189 | +def do_build(workdir, package, release, bp_version, builder): |
190 | + builder = getBuilder(builder) |
191 | + if not builder: |
192 | + return |
193 | + |
194 | + return builder.build(os.path.join(workdir, |
195 | + '%s_%s.dsc' % (package, bp_version)), |
196 | + release, |
197 | + workdir) |
198 | + |
199 | +def do_upload(workdir, package, bp_version, upload): |
200 | + prompt = 'Do you want to upload this to %s? [Y/n]' % upload |
201 | + while True: |
202 | + answer = raw_input(prompt).strip().lower() |
203 | + if answer in ('', 'y', 'yes'): |
204 | + break |
205 | + elif answer in ('n', 'no'): |
206 | + return |
207 | + |
208 | + check_call(['dput', |
209 | + upload, |
210 | + '%s_%s_source.changes' % |
211 | + (package, bp_version)], |
212 | + cwd=workdir) |
213 | + |
214 | + |
215 | +def do_backport(workdir, package, dscfile, version, release, build, builder, upload): |
216 | + check_call(['dpkg-source', |
217 | + '-x', |
218 | + dscfile, |
219 | + package], |
220 | + cwd=workdir) |
221 | + srcdir = os.path.join(workdir, package) |
222 | + |
223 | + bp_version = get_backport_version(version, upload, release) |
224 | + bp_dist = get_backport_dist(upload, release) |
225 | + |
226 | + check_call(['dch', |
227 | + '--force-bad-version', |
228 | + '--preserve', |
229 | + '--newversion', bp_version, |
230 | + '--distribution', bp_dist, |
231 | + 'No-change backport to %s' % release], |
232 | + cwd=srcdir) |
233 | + check_call(['debuild', '-S', '-sa'], |
234 | + cwd=srcdir) |
235 | + |
236 | + if ':' in bp_version: |
237 | + bp_version = bp_version[bp_version.find(':')+1:] |
238 | + |
239 | + print 'Please check the package in file://%s carefully' % workdir |
240 | + if build: |
241 | + if 0 != do_build(workdir, package, release, bp_version, builder): |
242 | + error('Package failed to build; aborting') |
243 | + if upload: |
244 | + do_upload(workdir, package, bp_version, upload) |
245 | + |
246 | + shutil.rmtree(srcdir) |
247 | + |
248 | +def main(args): |
249 | + os.environ['DEB_VENDOR'] = 'Ubuntu' |
250 | + |
251 | + opts, (package_or_dsc,) = parse(args[1:]) |
252 | + |
253 | + script_name = os.path.basename(sys.argv[0]) |
254 | + lp = launchpadlib.launchpad.Launchpad.login_anonymously(script_name, |
255 | + opts.launchpad) |
256 | + |
257 | + if not opts.dest_releases: |
258 | + try: |
259 | + distinfo = lsb_release.get_distro_information() |
260 | + opts.dest_releases = [distinfo['CODENAME']] |
261 | + except: |
262 | + error('No destination release specified and unable to guess yours') |
263 | + |
264 | + if opts.workdir: |
265 | + workdir = os.path.expanduser(opts.workdir) |
266 | + else: |
267 | + workdir = tempfile.mkdtemp(prefix='backportpackage-') |
268 | + |
269 | + if not os.path.exists(workdir): |
270 | + os.makedirs(workdir) |
271 | + |
272 | + try: |
273 | + dscfile = fetch_package(lp, |
274 | + workdir, |
275 | + package_or_dsc, |
276 | + opts.version, |
277 | + opts.source_release) |
278 | + |
279 | + dsc = Dsc(open(os.path.join(workdir, dscfile))) |
280 | + package = dsc['Source'] |
281 | + version = dsc['Version'] |
282 | + |
283 | + for release in opts.dest_releases: |
284 | + do_backport(workdir, |
285 | + package, |
286 | + dscfile, |
287 | + version, |
288 | + release, |
289 | + opts.build, |
290 | + opts.builder, |
291 | + opts.upload) |
292 | + finally: |
293 | + if not opts.workdir: |
294 | + shutil.rmtree(workdir) |
295 | + |
296 | +if __name__ == '__main__': |
297 | + sys.exit(main(sys.argv)) |
298 | |
299 | === modified file 'debian/changelog' |
300 | --- debian/changelog 2010-12-15 14:50:54 +0000 |
301 | +++ debian/changelog 2010-12-16 09:14:08 +0000 |
302 | @@ -5,6 +5,7 @@ |
303 | Use the 'production' LP instance instead of 'edge' (which is going away). |
304 | * pbuilder-dist: Fix typo in local archive support, introduced in 0.107. |
305 | |
306 | +<<<<<<< TREE |
307 | [ Benjamin Drung ] |
308 | * pull-lp-source: Unquote URI to get "+" instead of "%2B" in the file name |
309 | (LP: #681114). |
310 | @@ -13,6 +14,12 @@ |
311 | * grep-merges: New tool. |
312 | |
313 | -- Benjamin Drung <bdrung@ubuntu.com> Tue, 14 Dec 2010 18:21:37 +0100 |
314 | +======= |
315 | + [ Evan Broder ] |
316 | + * backportpackage: new script for testing backport requests in a PPA. |
317 | + |
318 | + -- Evan Broder <evan@ebroder.net> Sat, 11 Dec 2010 14:11:54 -0800 |
319 | +>>>>>>> MERGE-SOURCE |
320 | |
321 | ubuntu-dev-tools (0.107) experimental; urgency=low |
322 | |
323 | |
324 | === added file 'doc/backportpackage.1' |
325 | --- doc/backportpackage.1 1970-01-01 00:00:00 +0000 |
326 | +++ doc/backportpackage.1 2010-12-16 09:14:08 +0000 |
327 | @@ -0,0 +1,105 @@ |
328 | +.TH BACKPORTPACKAGE "1" "December 2010" "ubuntu-dev-tools" |
329 | +.SH NAME |
330 | +backportpackage \- helper to test package backports |
331 | +.SH SYNOPSIS |
332 | +.TP |
333 | +.B backportpackage \fR[\fIadditional options\fR] |
334 | +\-\-upload <\fIupload target\fR> |
335 | +.br |
336 | +<\fIsource package name or .dsc URL/file\fR> |
337 | +.PP |
338 | +.B backportpackage \-h |
339 | +.SH OPTIONS |
340 | +.TP |
341 | +.B \-d \fIDEST\fR, \-\-destination=\fIDEST\fR |
342 | +\fBRequired\fR. Backport the package to the specified Ubuntu |
343 | +release. If this option is unspecified, then \fBbackportpackage\fR |
344 | +defaults to the release on which it is currently running. |
345 | +.TP |
346 | +.B \-s \fISOURCE\fR, \-\-source=\fISOURCE\fR |
347 | +Backport the package from the specified Ubuntu release. If neither |
348 | +this option nor \fB\-\-version\fR are specified, then |
349 | +\fBbackportpackage\fR defaults to the current Ubuntu development |
350 | +release. |
351 | +.TP |
352 | +.B \-b, \-\-build |
353 | +Build the package with the specified builder before uploading. Note |
354 | +for \fBpbuilder\fR(8) users: This assumes the common configuration, |
355 | +where the \fBDIST\fR environment is read by \fBpbuilderrc\fR(5) to |
356 | +select the correct base image. |
357 | +.TP |
358 | +.B \-B \fIBUILDER\fR, \fB\-\-builder\fR=\fIBUILDER |
359 | +Use the specified builder to build the package. Supported are |
360 | +\fBpbuilder\fR(8) and \fBsbuild\fR(1). This overrides |
361 | +\fBUBUNTUTOOLS_BUILDER\fR. The default is \fBpbuilder\fR(8). |
362 | +.TP |
363 | +.B \-u \fIUPLOAD\fR, \-\-upload=\fIUPLOAD\fR |
364 | +Upload to \fIUPLOAD\fR with \fBdput\fR(1) (after confirmation). |
365 | +.TP |
366 | +.B \-v \fIVERSION\fR, \-\-version=\fIVERSION\fR |
367 | +If the \fB\-\-source\fR option is specified, then |
368 | +\fBbackportpackage\fR verifies that the current version of \fIsource |
369 | +package\fR in \fISOURCE\fR is the same as \fIVERSION\fR. Otherwise, |
370 | +\fBbackportpackage\fR finds version \fIVERSION\fR of \fIsource |
371 | +package\fR, regardless of the release in which it was published (or if |
372 | +that version is still current). This option is ignored if a .dsc URL |
373 | +or path is passed in instead of a source package name. |
374 | +.TP |
375 | +.B \-w \fIWORKDIR\fR, \-\-workdir=\fIWORKDIR\fR |
376 | +If \fIWORKDIR\fR is specified, then all files are downloaded, |
377 | +unpacked, built into, and otherwise manipulated in |
378 | +\fIWORKDIR\fR. Otherwise, a temporary directory is created, which is |
379 | +deleted before \fIbackportpackage\fR exits. |
380 | +.TP |
381 | +.B \-l \fIINSTANCE\fR, \-\-launchpad=\fIINSTANCE\fR |
382 | +Use the specified instance of Launchpad (e.g. "staging"), instead of |
383 | +the default of "production". |
384 | +.SH DESCRIPTION |
385 | +\fBbackportpackage\fR fetches a package from one Ubuntu release or |
386 | +from a specified .dsc path or URL and creates a no-change backport of |
387 | +that package to a previous release, optionally doing a test build of |
388 | +the package and/or uploading the resulting backport for testing. |
389 | +.PP |
390 | +Unless a working directory is specified, the backported package is |
391 | +fetched and built in a temporary directory in \fB/tmp\fR, which is |
392 | +removed once the script finishes running. |
393 | +.PP |
394 | +\fBbackportpackage\fR is only recommended for testing backports in a |
395 | +PPA, not uploading backports to the Ubuntu archive. |
396 | +.SH ENVIRONMENT |
397 | +.TP |
398 | +.B UBUNTUTOOLS_BUILDER |
399 | +The default builder for Ubuntu development tools that support it |
400 | +(including \fBbackportpackage\fR). Supported are \fBpbuilder\fR(8) and |
401 | +\fBsbuild\fR(1). If unset and not provided on the command line, |
402 | +\fBpbuilder\fR(8) is used. |
403 | +.SH EXAMPLES |
404 | +Test-build in your PPA a backport of znc from the current development |
405 | +release to your workstation's release, deleting the build products |
406 | +afterwards: |
407 | +.IP |
408 | +.nf |
409 | +.B backportpackage -u ppa:\fIuser\fR/\fIppa\fB znc |
410 | +.fi |
411 | +.PP |
412 | +Backport squashfs-tools from Maverick to both Karmic and Lucid and |
413 | +test-build both locally, leaving all build products in the current |
414 | +working directory: |
415 | +.IP |
416 | +.nf |
417 | +.B backportpackage -b -s maverick -d karmic -d lucid -w . \\\\ |
418 | +.B " "squashfs-tools |
419 | +.fi |
420 | +.PP |
421 | +Fetch a package from a PPA, backport it to Hardy, then upload it back |
422 | +to the same PPA: |
423 | +.IP |
424 | +.nf |
425 | +.B backportpackage -d hardy -u ppa:\fIuser\fR/\fIppa\fR \\\\ |
426 | +.B " "https://launchpad.net/\fIsome/file.dsc\fR |
427 | +.fi |
428 | +.SH AUTHOR |
429 | +\fBbackportpackage\fR and this manpage were written by Evan Broder |
430 | +<evan@ebroder.net> |
431 | +.PP |
432 | +Both are released under GNU General Public License, version 2. |
433 | |
434 | === modified file 'doc/sponsor-patch.1' |
435 | --- doc/sponsor-patch.1 2010-11-26 18:34:31 +0000 |
436 | +++ doc/sponsor-patch.1 2010-12-16 09:14:08 +0000 |
437 | @@ -61,7 +61,7 @@ |
438 | .B \-B \fIBUILDER\fR, \fB\-\-builder\fR=\fIBUILDER |
439 | Use the specify builder to build the package. |
440 | Supported are \fBpbuilder\fR(8) and \fBsbuild\fR(1). |
441 | -This overrides \fBSPONSOR_PATCH_BUILDER\fR. |
442 | +This overrides \fBUBUNTUTOOLS_BUILDER\fR and \fBSPONSOR_PATCH_BUILDER\fR. |
443 | The default is \fBpbuilder\fR(8). |
444 | .TP |
445 | .BR \-e ", " \-\-edit |
446 | @@ -90,10 +90,15 @@ |
447 | .SH ENVIRONMENT |
448 | |
449 | .TP |
450 | +.B UBUNTUTOOLS_BUILDER |
451 | +The default builder for Ubuntu development tools that support it (including \fBsponsor\-patch\fR. |
452 | +Supported are \fBpbuilder\fR(8) and \fBsbuild\fR(1). |
453 | +If unset and not provided on the command line, \fBpbuilder\fR(8) is used. |
454 | + |
455 | +.TP |
456 | .B SPONSOR_PATCH_BUILDER |
457 | The default builder for \fBsponsor\-patch\fR. |
458 | -Supported are \fBpbuilder\fR(8) and \fBsbuild\fR(1). |
459 | -If unset and not provided on the command line, \fBpbuilder\fR(8) is used. |
460 | +If specified, this overrides \fBUBUNTUTOOLS_BUILDER\fR. |
461 | |
462 | .TP |
463 | .B SPONSOR_PATCH_WORKDIR |
464 | |
465 | === modified file 'setup.py' |
466 | --- setup.py 2010-12-15 20:50:30 +0000 |
467 | +++ setup.py 2010-12-16 09:14:08 +0000 |
468 | @@ -16,6 +16,7 @@ |
469 | setup(name='ubuntu-dev-tools', |
470 | version=version, |
471 | scripts=['404main', |
472 | + 'backportpackage', |
473 | 'check-symbols', |
474 | 'dch-repeat', |
475 | 'dgetlp', |
476 | |
477 | === modified file 'sponsor-patch' |
478 | --- sponsor-patch 2010-11-26 18:34:31 +0000 |
479 | +++ sponsor-patch 2010-12-16 09:14:08 +0000 |
480 | @@ -28,7 +28,9 @@ |
481 | import debian.debian_support |
482 | import launchpadlib.launchpad |
483 | |
484 | +from ubuntutools.builder import getBuilder |
485 | import ubuntutools.update_maintainer |
486 | +from ubuntutools.logger import Logger |
487 | |
488 | USER_ABORT = 2 |
489 | |
490 | @@ -57,7 +59,7 @@ |
491 | dsc_file = None |
492 | for url in source_files: |
493 | filename = urllib.unquote(os.path.basename(url)) |
494 | - Print.info("Downloading %s..." % (filename)) |
495 | + Logger.info("Downloading %s..." % (filename)) |
496 | urllib.urlretrieve(url, filename) |
497 | if url.endswith(".dsc"): |
498 | dsc_file = filename |
499 | @@ -148,50 +150,6 @@ |
500 | return self.project == "ubuntu" |
501 | |
502 | |
503 | -class Builder(object): |
504 | - def __init__(self, name): |
505 | - self.name = name |
506 | - cmd = ["dpkg-architecture", "-qDEB_BUILD_ARCH_CPU"] |
507 | - process = subprocess.Popen(cmd, stdout=subprocess.PIPE) |
508 | - self.architecture = process.communicate()[0].strip() |
509 | - |
510 | - def get_architecture(self): |
511 | - return self.architecture |
512 | - |
513 | - def get_name(self): |
514 | - return self.name |
515 | - |
516 | - |
517 | -class Pbuilder(Builder): |
518 | - def __init__(self): |
519 | - Builder.__init__(self, "pbuilder") |
520 | - |
521 | - def build(self, dsc_file, dist, result_directory): |
522 | - # TODO: Do not rely on a specific pbuilder configuration. |
523 | - cmd = ["sudo", "-E", "DIST=" + dist, "pbuilder", "--build", |
524 | - "--distribution", dist, "--architecture", self.architecture, |
525 | - "--buildresult", result_directory, dsc_file] |
526 | - Print.command(cmd) |
527 | - return subprocess.call(cmd) |
528 | - |
529 | - |
530 | -class Sbuild(Builder): |
531 | - def __init__(self): |
532 | - Builder.__init__(self, "sbuild") |
533 | - |
534 | - def build(self, dsc_file, dist, result_directory): |
535 | - workdir = os.getcwd() |
536 | - Print.command(["cd", result_directory]) |
537 | - os.chdir(result_directory) |
538 | - cmd = ["sbuild", "--arch-all", "--dist=" + dist, |
539 | - "--arch=" + self.architecture, dsc_file] |
540 | - Print.command(cmd) |
541 | - result = subprocess.call(cmd) |
542 | - Print.command(["cd", workdir]) |
543 | - os.chdir(workdir) |
544 | - return result |
545 | - |
546 | - |
547 | class Patch(object): |
548 | def __init__(self, patch_file): |
549 | self.patch_file = patch_file |
550 | @@ -220,41 +178,6 @@ |
551 | self.changed_files)) > 0 |
552 | |
553 | |
554 | -class Print(object): |
555 | - script_name = os.path.basename(sys.argv[0]) |
556 | - verbose = False |
557 | - |
558 | - @classmethod |
559 | - def command(cls, cmd): |
560 | - if cls.verbose: |
561 | - for i in xrange(len(cmd)): |
562 | - if cmd[i].find(" ") >= 0: |
563 | - cmd[i] = '"' + cmd[i] + '"' |
564 | - print "%s: I: %s" % (script_name, " ".join(cmd)) |
565 | - |
566 | - @classmethod |
567 | - def debug(cls, message): |
568 | - if cls.verbose: |
569 | - print "%s: D: %s" % (script_name, message) |
570 | - |
571 | - @classmethod |
572 | - def error(cls, message): |
573 | - print >> sys.stderr, "%s: Error: %s" % (script_name, message) |
574 | - |
575 | - @classmethod |
576 | - def info(cls, message): |
577 | - if cls.verbose: |
578 | - print "%s: I: %s" % (script_name, message) |
579 | - |
580 | - @classmethod |
581 | - def normal(cls, message): |
582 | - print "%s: %s" % (script_name, message) |
583 | - |
584 | - @classmethod |
585 | - def set_verbosity(cls, verbose): |
586 | - cls.verbose = verbose |
587 | - |
588 | - |
589 | def get_source_package_name(bug_task): |
590 | package = None |
591 | if bug_task.bug_target_name != "ubuntu": |
592 | @@ -334,7 +257,7 @@ |
593 | def edit_source(): |
594 | # Spawn shell to allow modifications |
595 | cmd = [get_user_shell()] |
596 | - Print.command(cmd) |
597 | + Logger.command(cmd) |
598 | print """An interactive shell was launched in |
599 | file://%s |
600 | Edit your files. When you are done, exit the shell. If you wish to abort the |
601 | @@ -342,7 +265,7 @@ |
602 | """ % (os.getcwd()), |
603 | returncode = subprocess.call(cmd) |
604 | if returncode != 0: |
605 | - Print.error("Shell exited with exit value %i." % (returncode)) |
606 | + Logger.error("Shell exited with exit value %i." % (returncode)) |
607 | sys.exit(1) |
608 | |
609 | def get_fixed_lauchpad_bugs(changes_file): |
610 | @@ -380,10 +303,10 @@ |
611 | linked_branches = map(lambda b: b.branch, bug.linked_branches) |
612 | if len(attached_patches) == 0 and len(linked_branches) == 0: |
613 | if len(bug.attachments) == 0: |
614 | - Print.error("No attachment and no linked branch found on bug #%i." \ |
615 | + Logger.error("No attachment and no linked branch found on bug #%i." \ |
616 | % (bug.id)) |
617 | else: |
618 | - Print.error(("No attached patch and no linked branch found. Go " \ |
619 | + Logger.error(("No attached patch and no linked branch found. Go " \ |
620 | "to https://launchpad.net/bugs/%i and mark an " \ |
621 | "attachment as patch.") % (bug.id)) |
622 | sys.exit(1) |
623 | @@ -393,13 +316,13 @@ |
624 | branch = linked_branches[0].bzr_identity |
625 | else: |
626 | if len(attached_patches) == 0: |
627 | - Print.normal("https://launchpad.net/bugs/%i has %i branches " \ |
628 | + Logger.normal("https://launchpad.net/bugs/%i has %i branches " \ |
629 | "linked:" % (bug.id, len(linked_branches))) |
630 | elif len(linked_branches) == 0: |
631 | - Print.normal("https://launchpad.net/bugs/%i has %i patches" \ |
632 | + Logger.normal("https://launchpad.net/bugs/%i has %i patches" \ |
633 | " attached:" % (bug.id, len(attached_patches))) |
634 | else: |
635 | - Print.normal("https://launchpad.net/bugs/%i has %i branch(es)" \ |
636 | + Logger.normal("https://launchpad.net/bugs/%i has %i branch(es)" \ |
637 | " linked and %i patch(es) attached:" % \ |
638 | (bug.id, len(linked_branches), len(attached_patches))) |
639 | i = 0 |
640 | @@ -421,11 +344,11 @@ |
641 | patch_filename = re.sub(" ", "_", patch.title) |
642 | if not reduce(lambda r, x: r or patch.title.endswith(x), |
643 | (".debdiff", ".diff", ".patch"), False): |
644 | - Print.info("Patch %s does not have a proper file extension." % \ |
645 | + Logger.info("Patch %s does not have a proper file extension." % \ |
646 | (patch.title)) |
647 | patch_filename += ".patch" |
648 | |
649 | - Print.info("Downloading %s." % (patch_filename)) |
650 | + Logger.info("Downloading %s." % (patch_filename)) |
651 | patch_file = open(patch_filename, "w") |
652 | patch_file.write(patch.data.open().read()) |
653 | patch_file.close() |
654 | @@ -436,18 +359,18 @@ |
655 | if os.path.isdir(dir_name): |
656 | shutil.rmtree(dir_name) |
657 | cmd = ["bzr", "branch", branch] |
658 | - Print.command(cmd) |
659 | + Logger.command(cmd) |
660 | if subprocess.call(cmd) != 0: |
661 | - Print.error("Failed to download branch %s." % (branch)) |
662 | + Logger.error("Failed to download branch %s." % (branch)) |
663 | sys.exit(1) |
664 | return dir_name |
665 | |
666 | def merge_branch(branch): |
667 | edit = False |
668 | cmd = ["bzr", "merge", branch] |
669 | - Print.command(cmd) |
670 | + Logger.command(cmd) |
671 | if subprocess.call(cmd) != 0: |
672 | - Print.error("Failed to merge branch %s." % (branch)) |
673 | + Logger.error("Failed to merge branch %s." % (branch)) |
674 | ask_for_manual_fixing() |
675 | edit = True |
676 | return edit |
677 | @@ -456,9 +379,9 @@ |
678 | cmd = ["dpkg-source", "--no-preparation", "-x", dsc_file] |
679 | if not verbose: |
680 | cmd.insert(1, "-q") |
681 | - Print.command(cmd) |
682 | + Logger.command(cmd) |
683 | if subprocess.call(cmd) != 0: |
684 | - Print.error("Extraction of %s failed." % (os.path.basename(dsc_file))) |
685 | + Logger.error("Extraction of %s failed." % (os.path.basename(dsc_file))) |
686 | sys.exit(1) |
687 | |
688 | def apply_patch(task, patch): |
689 | @@ -466,9 +389,9 @@ |
690 | if patch.is_debdiff(): |
691 | cmd = ["patch", "--merge", "--force", "-p", |
692 | str(patch.get_strip_level()), "-i", patch.full_path] |
693 | - Print.command(cmd) |
694 | + Logger.command(cmd) |
695 | if subprocess.call(cmd) != 0: |
696 | - Print.error("Failed to apply debdiff %s to %s %s." % \ |
697 | + Logger.error("Failed to apply debdiff %s to %s %s." % \ |
698 | (patch.get_name(), task.package, task.get_version())) |
699 | if not edit: |
700 | ask_for_manual_fixing() |
701 | @@ -477,9 +400,9 @@ |
702 | # FIXME: edit-patch needs a non-interactive mode |
703 | # https://launchpad.net/bugs/612566 |
704 | cmd = ["edit-patch", patch.full_path] |
705 | - Print.command(cmd) |
706 | + Logger.command(cmd) |
707 | if subprocess.call(cmd) != 0: |
708 | - Print.error("Failed to apply diff %s to %s %s." % \ |
709 | + Logger.error("Failed to apply diff %s to %s %s." % \ |
710 | (patch.get_name(), task.package, task.get_version())) |
711 | if not edit: |
712 | ask_for_manual_fixing() |
713 | @@ -493,11 +416,11 @@ |
714 | try: |
715 | os.makedirs(workdir) |
716 | except os.error, error: |
717 | - Print.error("Failed to create the working directory %s [Errno " \ |
718 | + Logger.error("Failed to create the working directory %s [Errno " \ |
719 | "%i]: %s." % (workdir, error.errno, error.strerror)) |
720 | sys.exit(1) |
721 | if workdir != os.getcwd(): |
722 | - Print.command(["cd", workdir]) |
723 | + Logger.command(["cd", workdir]) |
724 | os.chdir(workdir) |
725 | |
726 | script_name = os.path.basename(sys.argv[0]) |
727 | @@ -510,13 +433,13 @@ |
728 | bug_tasks = map(lambda x: BugTask(x, launchpad), bug.bug_tasks) |
729 | ubuntu_tasks = filter(lambda x: x.is_ubuntu_task(), bug_tasks) |
730 | if len(ubuntu_tasks) == 0: |
731 | - Print.error("No Ubuntu bug task found on bug #%i." % (bug_number)) |
732 | + Logger.error("No Ubuntu bug task found on bug #%i." % (bug_number)) |
733 | sys.exit(1) |
734 | elif len(ubuntu_tasks) == 1: |
735 | task = ubuntu_tasks[0] |
736 | if len(ubuntu_tasks) > 1: |
737 | if verbose: |
738 | - Print.info("%i Ubuntu tasks exist for bug #%i." % \ |
739 | + Logger.info("%i Ubuntu tasks exist for bug #%i." % \ |
740 | (len(ubuntu_tasks), bug_number)) |
741 | for task in ubuntu_tasks: |
742 | print task.get_short_info() |
743 | @@ -524,7 +447,7 @@ |
744 | if len(open_ubuntu_tasks) == 1: |
745 | task = open_ubuntu_tasks[0] |
746 | else: |
747 | - Print.normal("https://launchpad.net/bugs/%i has %i Ubuntu tasks:" \ |
748 | + Logger.normal("https://launchpad.net/bugs/%i has %i Ubuntu tasks:" \ |
749 | % (bug_number, len(ubuntu_tasks))) |
750 | for i in xrange(len(ubuntu_tasks)): |
751 | print "%i) %s" % (i + 1, |
752 | @@ -532,7 +455,7 @@ |
753 | selected = input_number("To which Ubuntu tasks do the patch belong", |
754 | 1, len(ubuntu_tasks)) |
755 | task = ubuntu_tasks[selected - 1] |
756 | - Print.info("Selected Ubuntu task: %s" % (task.get_short_info())) |
757 | + Logger.info("Selected Ubuntu task: %s" % (task.get_short_info())) |
758 | |
759 | dsc_file = task.download_source() |
760 | assert os.path.isfile(dsc_file), "%s does not exist." % (dsc_file) |
761 | @@ -540,15 +463,15 @@ |
762 | if patch: |
763 | patch = download_patch(patch) |
764 | |
765 | - Print.info("Ubuntu package: %s" % (task.package)) |
766 | + Logger.info("Ubuntu package: %s" % (task.package)) |
767 | if task.is_merge(): |
768 | - Print.info("The task is a merge request.") |
769 | + Logger.info("The task is a merge request.") |
770 | |
771 | extract_source(dsc_file, verbose) |
772 | |
773 | # change directory |
774 | directory = task.package + '-' + task.get_version().upstream_version |
775 | - Print.command(["cd", directory]) |
776 | + Logger.command(["cd", directory]) |
777 | os.chdir(directory) |
778 | |
779 | edit |= apply_patch(task, patch) |
780 | @@ -556,7 +479,7 @@ |
781 | branch_dir = download_branch(task.get_branch_link()) |
782 | |
783 | # change directory |
784 | - Print.command(["cd", branch_dir]) |
785 | + Logger.command(["cd", branch_dir]) |
786 | os.chdir(branch_dir) |
787 | |
788 | edit |= merge_branch(branch) |
789 | @@ -568,9 +491,9 @@ |
790 | edit = True |
791 | |
792 | # update the Maintainer field |
793 | - Print.command(["update-maintainer"]) |
794 | + Logger.command(["update-maintainer"]) |
795 | if ubuntutools.update_maintainer.update_maintainer(verbose) != 0: |
796 | - Print.error("update-maintainer script failed.") |
797 | + Logger.error("update-maintainer script failed.") |
798 | sys.exit(1) |
799 | |
800 | # Get new version of package |
801 | @@ -578,7 +501,7 @@ |
802 | try: |
803 | new_version = changelog.get_version() |
804 | except IndexError: |
805 | - Print.error("Debian package version could not be determined. " \ |
806 | + Logger.error("Debian package version could not be determined. " \ |
807 | "debian/changelog is probably malformed.") |
808 | ask_for_manual_fixing() |
809 | continue |
810 | @@ -586,15 +509,15 @@ |
811 | # Check if version of the new package is greater than the version in |
812 | # the archive. |
813 | if new_version <= task.get_version(): |
814 | - Print.error("The version %s is not greater than the already " \ |
815 | + Logger.error("The version %s is not greater than the already " \ |
816 | "available %s." % (new_version, task.get_version())) |
817 | ask_for_manual_fixing() |
818 | continue |
819 | |
820 | cmd = ["dch", "--maintmaint", "--edit", ""] |
821 | - Print.command(cmd) |
822 | + Logger.command(cmd) |
823 | if subprocess.call(cmd) != 0: |
824 | - Print.info("Failed to update timestamp in debian/changelog.") |
825 | + Logger.info("Failed to update timestamp in debian/changelog.") |
826 | |
827 | # Build source package |
828 | if patch: |
829 | @@ -615,9 +538,9 @@ |
830 | env = os.environ |
831 | if upload == 'ubuntu': |
832 | env['DEB_VENDOR'] = 'Ubuntu' |
833 | - Print.command(cmd) |
834 | + Logger.command(cmd) |
835 | if subprocess.call(cmd, env=env) != 0: |
836 | - Print.error("Failed to build source tarball.") |
837 | + Logger.error("Failed to build source tarball.") |
838 | # TODO: Add a "retry" option |
839 | ask_for_manual_fixing() |
840 | continue |
841 | @@ -634,7 +557,7 @@ |
842 | debdiff_filename = os.path.join(workdir, debdiff_name) |
843 | if not verbose: |
844 | cmd.insert(1, "-q") |
845 | - Print.command(cmd + [">", debdiff_filename]) |
846 | + Logger.command(cmd + [">", debdiff_filename]) |
847 | process = subprocess.Popen(cmd, stdout=subprocess.PIPE) |
848 | debdiff = process.communicate()[0] |
849 | |
850 | @@ -646,7 +569,7 @@ |
851 | # Make sure that the Launchpad bug will be closed |
852 | changes_file = new_dsc_file[:-4] + "_source.changes" |
853 | if bug_number not in get_fixed_lauchpad_bugs(changes_file): |
854 | - Print.error("Launchpad bug #%i is not closed by new version." % \ |
855 | + Logger.error("Launchpad bug #%i is not closed by new version." % \ |
856 | (bug_number)) |
857 | ask_for_manual_fixing() |
858 | continue |
859 | @@ -660,7 +583,7 @@ |
860 | allowed = map(lambda s: s + "-proposed", supported_series) + \ |
861 | [devel_series] |
862 | if changelog.distributions not in allowed: |
863 | - Print.error("%s is not an allowed series. It needs to be one " \ |
864 | + Logger.error("%s is not an allowed series. It needs to be one " \ |
865 | "of %s." % (changelog.distributions, |
866 | ", ".join(allowed))) |
867 | ask_for_manual_fixing() |
868 | @@ -668,7 +591,7 @@ |
869 | elif upload and upload.startwith("ppa/"): |
870 | allowed = supported_series + [devel_series] |
871 | if changelog.distributions not in allowed: |
872 | - Print.error("%s is not an allowed series. It needs to be one " \ |
873 | + Logger.error("%s is not an allowed series. It needs to be one " \ |
874 | "of %s." % (changelog.distributions, |
875 | ", ".join(allowed))) |
876 | ask_for_manual_fixing() |
877 | @@ -683,7 +606,7 @@ |
878 | dist = re.sub("-.*$", "", changelog.distributions) |
879 | result = builder.build(new_dsc_file, dist, buildresult) |
880 | if result != 0: |
881 | - Print.error("Failed to build %s from source with %s." % \ |
882 | + Logger.error("Failed to build %s from source with %s." % \ |
883 | (os.path.basename(new_dsc_file), |
884 | builder.get_name())) |
885 | # TODO: Add "retry" and "update" option |
886 | @@ -699,7 +622,7 @@ |
887 | cmd = ["lintian", "-IE", "--pedantic", "-q", build_changes] |
888 | lintian_filename = os.path.join(workdir, |
889 | task.package + "_" + strip_epoch(new_version) + ".lintian") |
890 | - Print.command(cmd + [">", lintian_filename]) |
891 | + Logger.command(cmd + [">", lintian_filename]) |
892 | process = subprocess.Popen(cmd, stdout=subprocess.PIPE) |
893 | report = process.communicate()[0] |
894 | |
895 | @@ -727,26 +650,26 @@ |
896 | print "Abort." |
897 | sys.exit(USER_ABORT) |
898 | cmd = ["dput", "--force", upload, changes_file] |
899 | - Print.command(cmd) |
900 | + Logger.command(cmd) |
901 | if subprocess.call(cmd) != 0: |
902 | - Print.error("Upload of %s to %s failed." % \ |
903 | + Logger.error("Upload of %s to %s failed." % \ |
904 | (os.path.basename(changes_file), upload)) |
905 | sys.exit(1) |
906 | if branch: |
907 | cmd = ['debcommit'] |
908 | - Print.command(cmd) |
909 | + Logger.command(cmd) |
910 | if subprocess.call(cmd) != 0: |
911 | - Print.error('Bzr commit failed.') |
912 | + Logger.error('Bzr commit failed.') |
913 | sys.exit(1) |
914 | cmd = ['bzr', 'mark-uploaded'] |
915 | - Print.command(cmd) |
916 | + Logger.command(cmd) |
917 | if subprocess.call(cmd) != 0: |
918 | - Print.error('Bzr tagging failed.') |
919 | + Logger.error('Bzr tagging failed.') |
920 | sys.exit(1) |
921 | cmd = ['bzr', 'push', ':parent'] |
922 | - Print.command(cmd) |
923 | + Logger.command(cmd) |
924 | if subprocess.call(cmd) != 0: |
925 | - Print.error('Bzr push failed.') |
926 | + Logger.error('Bzr push failed.') |
927 | sys.exit(1) |
928 | |
929 | # Leave while loop if everything worked |
930 | @@ -766,7 +689,7 @@ |
931 | if "SPONSOR_PATCH_BUILDER" in os.environ: |
932 | default_builder = os.environ["SPONSOR_PATCH_BUILDER"] |
933 | else: |
934 | - default_builder = "pbuilder" |
935 | + default_builder = None |
936 | |
937 | parser.add_option("-b", "--build", dest="build", |
938 | help="Build the package with the specified builder.", |
939 | @@ -790,29 +713,24 @@ |
940 | help="Specify a working directory.") |
941 | |
942 | (options, args) = parser.parse_args() |
943 | - Print.set_verbosity(options.verbose) |
944 | + Logger.set_verbosity(options.verbose) |
945 | |
946 | if len(args) == 0: |
947 | - Print.error("No bug number specified.") |
948 | + Logger.error("No bug number specified.") |
949 | sys.exit(1) |
950 | elif len(args) > 1: |
951 | - Print.error("Multiple bug numbers specified: %s" % (", ".join(args))) |
952 | + Logger.error("Multiple bug numbers specified: %s" % (", ".join(args))) |
953 | sys.exit(1) |
954 | |
955 | bug_number = args[0] |
956 | if bug_number.isdigit(): |
957 | bug_number = int(bug_number) |
958 | else: |
959 | - Print.error("Invalid bug number specified: %s" % (bug_number)) |
960 | + Logger.error("Invalid bug number specified: %s" % (bug_number)) |
961 | sys.exit(1) |
962 | |
963 | - if options.builder == "pbuilder": |
964 | - builder = Pbuilder() |
965 | - elif options.builder == "sbuild": |
966 | - builder = Sbuild() |
967 | - else: |
968 | - Print.error("Unsupported builder specified: %s. Only pbuilder and " |
969 | - "sbuild are supported." % (options.builder)) |
970 | + builder = getBuilder(options.builder) |
971 | + if not builder: |
972 | sys.exit(1) |
973 | |
974 | if options.sponsoring: |
975 | |
976 | === added file 'ubuntutools/builder.py' |
977 | --- ubuntutools/builder.py 1970-01-01 00:00:00 +0000 |
978 | +++ ubuntutools/builder.py 2010-12-16 09:14:08 +0000 |
979 | @@ -0,0 +1,81 @@ |
980 | +# |
981 | +# builder.py - Helper classes for building packages |
982 | +# |
983 | +# Copyright (C) 2010, Benjamin Drung <bdrung@ubuntu.com> |
984 | +# Copyright (C) 2010, Evan Broder <evan@ebroder.net> |
985 | +# |
986 | +# Permission to use, copy, modify, and/or distribute this software |
987 | +# for any purpose with or without fee is hereby granted, provided |
988 | +# that the above copyright notice and this permission notice appear |
989 | +# in all copies. |
990 | +# |
991 | +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
992 | +# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
993 | +# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
994 | +# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR |
995 | +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM |
996 | +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
997 | +# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
998 | +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
999 | +# |
1000 | + |
1001 | +import os |
1002 | +import subprocess |
1003 | + |
1004 | +from ubuntutools.logger import Logger |
1005 | + |
1006 | +class Builder(object): |
1007 | + def __init__(self, name): |
1008 | + self.name = name |
1009 | + cmd = ["dpkg-architecture", "-qDEB_BUILD_ARCH_CPU"] |
1010 | + process = subprocess.Popen(cmd, stdout=subprocess.PIPE) |
1011 | + self.architecture = process.communicate()[0].strip() |
1012 | + |
1013 | + def get_architecture(self): |
1014 | + return self.architecture |
1015 | + |
1016 | + def get_name(self): |
1017 | + return self.name |
1018 | + |
1019 | + |
1020 | +class Pbuilder(Builder): |
1021 | + def __init__(self): |
1022 | + Builder.__init__(self, "pbuilder") |
1023 | + |
1024 | + def build(self, dsc_file, dist, result_directory): |
1025 | + # TODO: Do not rely on a specific pbuilder configuration. |
1026 | + cmd = ["sudo", "-E", "DIST=" + dist, "pbuilder", "--build", |
1027 | + "--distribution", dist, "--architecture", self.architecture, |
1028 | + "--buildresult", result_directory, dsc_file] |
1029 | + Logger.command(cmd) |
1030 | + return subprocess.call(cmd) |
1031 | + |
1032 | + |
1033 | +class Sbuild(Builder): |
1034 | + def __init__(self): |
1035 | + Builder.__init__(self, "sbuild") |
1036 | + |
1037 | + def build(self, dsc_file, dist, result_directory): |
1038 | + workdir = os.getcwd() |
1039 | + Logger.command(["cd", result_directory]) |
1040 | + os.chdir(result_directory) |
1041 | + cmd = ["sbuild", "--arch-all", "--dist=" + dist, |
1042 | + "--arch=" + self.architecture, dsc_file] |
1043 | + Logger.command(cmd) |
1044 | + result = subprocess.call(cmd) |
1045 | + Logger.command(["cd", workdir]) |
1046 | + os.chdir(workdir) |
1047 | + return result |
1048 | + |
1049 | + |
1050 | +def getBuilder(builder=None): |
1051 | + if not builder: |
1052 | + builder = os.environ.get('UBUNTUTOOLS_BUILDER', 'pbuilder') |
1053 | + |
1054 | + if builder == 'pbuilder': |
1055 | + return Pbuilder() |
1056 | + elif builder == 'sbuild': |
1057 | + return Sbuild() |
1058 | + |
1059 | + Logger.error("Unsupported builder specified: %s. Only pbuilder and " |
1060 | + "sbuild are supported." % builder) |
1061 | |
1062 | === added file 'ubuntutools/logger.py' |
1063 | --- ubuntutools/logger.py 1970-01-01 00:00:00 +0000 |
1064 | +++ ubuntutools/logger.py 2010-12-16 09:14:08 +0000 |
1065 | @@ -0,0 +1,55 @@ |
1066 | +# |
1067 | +# logger.py - A simple logging helper class |
1068 | +# |
1069 | +# Copyright (C) 2010, Benjamin Drung <bdrung@ubuntu.com> |
1070 | +# |
1071 | +# Permission to use, copy, modify, and/or distribute this software |
1072 | +# for any purpose with or without fee is hereby granted, provided |
1073 | +# that the above copyright notice and this permission notice appear |
1074 | +# in all copies. |
1075 | +# |
1076 | +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
1077 | +# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
1078 | +# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
1079 | +# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR |
1080 | +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM |
1081 | +# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
1082 | +# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
1083 | +# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
1084 | + |
1085 | +import os |
1086 | +import sys |
1087 | + |
1088 | +class Logger(object): |
1089 | + script_name = os.path.basename(sys.argv[0]) |
1090 | + verbose = False |
1091 | + |
1092 | + @classmethod |
1093 | + def command(cls, cmd): |
1094 | + if cls.verbose: |
1095 | + for i in xrange(len(cmd)): |
1096 | + if cmd[i].find(" ") >= 0: |
1097 | + cmd[i] = '"' + cmd[i] + '"' |
1098 | + print "%s: I: %s" % (cls.script_name, " ".join(cmd)) |
1099 | + |
1100 | + @classmethod |
1101 | + def debug(cls, message): |
1102 | + if cls.verbose: |
1103 | + print "%s: D: %s" % (cls.script_name, message) |
1104 | + |
1105 | + @classmethod |
1106 | + def error(cls, message): |
1107 | + print >> sys.stderr, "%s: Error: %s" % (cls.script_name, message) |
1108 | + |
1109 | + @classmethod |
1110 | + def info(cls, message): |
1111 | + if cls.verbose: |
1112 | + print "%s: I: %s" % (cls.script_name, message) |
1113 | + |
1114 | + @classmethod |
1115 | + def normal(cls, message): |
1116 | + print "%s: %s" % (cls.script_name, message) |
1117 | + |
1118 | + @classmethod |
1119 | + def set_verbosity(cls, verbose): |
1120 | + cls.verbose = verbose |
This script belongs to this package.
You should set DEB_VENDOR=Ubuntu for dpkg-source.