Merge lp:~jelmer/bzr-builder/deb-util into lp:bzr-builder
- deb-util
- Merge into trunk
Proposed by
Jelmer Vernooij
Status: | Merged |
---|---|
Approved by: | James Westby |
Approved revision: | 164 |
Merged at revision: | 163 |
Proposed branch: | lp:~jelmer/bzr-builder/deb-util |
Merge into: | lp:bzr-builder |
Diff against target: |
847 lines (+411/-355) 4 files modified
cmds.py (+39/-353) deb_util.py (+370/-0) tests/__init__.py (+1/-1) tests/test_deb_util.py (+1/-1) |
To merge this branch: | bzr merge lp:~jelmer/bzr-builder/deb-util |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
James Westby | Approve | ||
Review via email: mp+85905@code.launchpad.net |
Commit message
Description of the change
Move debian-related code out of cmds.py into deb_util.py.
This is done in preparation of dropping the hard dependency of bzr-builder on
python-debian, as the "bzr build" command is generic and should not
require anything debian-specific. (bug 824208)
To post a comment you must log in.
Revision history for this message
James Westby (james-w) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'cmds.py' |
2 | --- cmds.py 2011-11-10 17:47:41 +0000 |
3 | +++ cmds.py 2011-12-15 16:22:26 +0000 |
4 | @@ -15,60 +15,31 @@ |
5 | |
6 | """Subcommands provided by bzr-builder.""" |
7 | |
8 | -from base64 import standard_b64decode |
9 | from StringIO import StringIO |
10 | import datetime |
11 | -from email import utils |
12 | -import errno |
13 | import os |
14 | -import signal |
15 | import shutil |
16 | -import subprocess |
17 | import tempfile |
18 | |
19 | -try: |
20 | - from debian import changelog, deb822 |
21 | -except ImportError: |
22 | - # In older versions of python-debian the main package was named |
23 | - # debian_bundle |
24 | - from debian_bundle import changelog, deb822 |
25 | - |
26 | -try: |
27 | - get_maintainer = changelog.get_maintainer |
28 | -except AttributeError: |
29 | - # Implementation of get_maintainer was added after 0.1.18 so import same |
30 | - # function from backports module if python-debian doesn't have it. |
31 | - from bzrlib.plugins.builder.backports import get_maintainer |
32 | - |
33 | from bzrlib import ( |
34 | - errors, |
35 | - export as _mod_export, |
36 | - lazy_regex, |
37 | - osutils, |
38 | - trace, |
39 | - transport as _mod_transport, |
40 | - urlutils, |
41 | - ) |
42 | + errors, |
43 | + lazy_regex, |
44 | + trace, |
45 | + transport as _mod_transport, |
46 | + urlutils, |
47 | + ) |
48 | from bzrlib.branch import Branch |
49 | from bzrlib.commands import Command |
50 | from bzrlib.option import Option |
51 | |
52 | from bzrlib.plugins.builder.recipe import ( |
53 | - BaseRecipeBranch, |
54 | - build_tree, |
55 | - RecipeParser, |
56 | - resolve_revisions, |
57 | - SAFE_INSTRUCTIONS, |
58 | - SubstitutionUnavailable, |
59 | - ) |
60 | - |
61 | - |
62 | -# The default distribution used by add_autobuild_changelog_entry() |
63 | -DEFAULT_UBUNTU_DISTRIBUTION = "lucid" |
64 | - |
65 | - |
66 | -class MissingDependency(errors.BzrError): |
67 | - pass |
68 | + BaseRecipeBranch, |
69 | + build_tree, |
70 | + RecipeParser, |
71 | + resolve_revisions, |
72 | + SAFE_INSTRUCTIONS, |
73 | + ) |
74 | + |
75 | |
76 | |
77 | def write_manifest_to_transport(location, base_branch, |
78 | @@ -135,233 +106,6 @@ |
79 | return old_recipe |
80 | |
81 | |
82 | -def add_autobuild_changelog_entry(base_branch, basedir, package, |
83 | - distribution=None, author_name=None, author_email=None, |
84 | - append_version=None): |
85 | - """Add a new changelog entry for an autobuild. |
86 | - |
87 | - :param base_branch: Recipe base branch |
88 | - :param basedir: Base working directory |
89 | - :param package: package name |
90 | - :param distribution: Optional distribution (defaults to last entry |
91 | - distribution) |
92 | - :param author_name: Name of the build requester |
93 | - :param author_email: Email of the build requester |
94 | - :param append_version: Optional version suffix to add |
95 | - """ |
96 | - debian_dir = os.path.join(basedir, "debian") |
97 | - if not os.path.exists(debian_dir): |
98 | - os.makedirs(debian_dir) |
99 | - cl_path = os.path.join(debian_dir, "changelog") |
100 | - file_found = False |
101 | - if os.path.exists(cl_path): |
102 | - file_found = True |
103 | - cl_f = open(cl_path) |
104 | - try: |
105 | - contents = cl_f.read() |
106 | - finally: |
107 | - cl_f.close() |
108 | - cl = changelog.Changelog(file=contents) |
109 | - else: |
110 | - cl = changelog.Changelog() |
111 | - if len(cl._blocks) > 0: |
112 | - if distribution is None: |
113 | - distribution = cl._blocks[0].distributions.split()[0] |
114 | - else: |
115 | - if file_found: |
116 | - if len(contents.strip()) > 0: |
117 | - reason = ("debian/changelog didn't contain any " |
118 | - "parseable stanzas") |
119 | - else: |
120 | - reason = "debian/changelog was empty" |
121 | - else: |
122 | - reason = "debian/changelog was not present" |
123 | - if distribution is None: |
124 | - distribution = DEFAULT_UBUNTU_DISTRIBUTION |
125 | - if base_branch.format in (0.1, 0.2, 0.3): |
126 | - try: |
127 | - base_branch.substitute_changelog_vars(None, cl) |
128 | - except SubstitutionUnavailable, e: |
129 | - raise errors.BzrCommandError("No previous changelog to " |
130 | - "take the upstream version from as %s was " |
131 | - "used: %s: %s." % (e.name, e.reason, reason)) |
132 | - # Use debian packaging environment variables |
133 | - # or default values if they don't exist |
134 | - if author_name is None or author_email is None: |
135 | - author_name, author_email = get_maintainer() |
136 | - # The python-debian package breaks compatibility at version 0.1.20 by |
137 | - # switching to expecting (but not checking for) unicode rather than |
138 | - # bytestring inputs. Detect this and decode environment if needed. |
139 | - if getattr(changelog.Changelog, "__unicode__", None) is not None: |
140 | - enc = osutils.get_user_encoding() |
141 | - author_name = author_name.decode(enc) |
142 | - author_email = author_email.decode(enc) |
143 | - author = "%s <%s>" % (author_name, author_email) |
144 | - |
145 | - date = utils.formatdate(localtime=True) |
146 | - version = base_branch.deb_version |
147 | - if append_version is not None: |
148 | - version += append_version |
149 | - try: |
150 | - changelog.Version(version) |
151 | - except (changelog.VersionError, ValueError), e: |
152 | - raise errors.BzrCommandError("Invalid deb-version: %s: %s" |
153 | - % (version, e)) |
154 | - cl.new_block(package=package, version=version, |
155 | - distributions=distribution, urgency="low", |
156 | - changes=['', ' * Auto build.', ''], |
157 | - author=author, date=date) |
158 | - cl_f = open(cl_path, 'wb') |
159 | - try: |
160 | - cl.write_to_open_file(cl_f) |
161 | - finally: |
162 | - cl_f.close() |
163 | - |
164 | - |
165 | -def calculate_package_dir(package_name, package_version, working_basedir): |
166 | - """Calculate the directory name that should be used while debuilding. |
167 | - |
168 | - :param base_branch: Recipe base branch |
169 | - :param package_version: Version of the package |
170 | - :param package_name: Package name |
171 | - :param working_basedir: Base directory |
172 | - """ |
173 | - package_basedir = "%s-%s" % (package_name, package_version.upstream_version) |
174 | - package_dir = os.path.join(working_basedir, package_basedir) |
175 | - return package_dir |
176 | - |
177 | - |
178 | -def _run_command(command, basedir, msg, error_msg, |
179 | - not_installed_msg=None, env=None, success_exit_codes=None, indata=None): |
180 | - """ Run a command in a subprocess. |
181 | - |
182 | - :param command: list with command and parameters |
183 | - :param msg: message to display to the user |
184 | - :param error_msg: message to display if something fails. |
185 | - :param not_installed_msg: the message to display if the command |
186 | - isn't available. |
187 | - :param env: Optional environment to use rather than os.environ. |
188 | - :param success_exit_codes: Exit codes to consider succesfull, defaults to [0]. |
189 | - :param indata: Data to write to standard input |
190 | - """ |
191 | - def subprocess_setup(): |
192 | - signal.signal(signal.SIGPIPE, signal.SIG_DFL) |
193 | - trace.note(msg) |
194 | - # Hide output if -q is in use. |
195 | - quiet = trace.is_quiet() |
196 | - if quiet: |
197 | - kwargs = {"stderr": subprocess.STDOUT, "stdout": subprocess.PIPE} |
198 | - else: |
199 | - kwargs = {} |
200 | - if env is not None: |
201 | - kwargs["env"] = env |
202 | - trace.mutter("running: %r", command) |
203 | - try: |
204 | - proc = subprocess.Popen(command, cwd=basedir, |
205 | - stdin=subprocess.PIPE, preexec_fn=subprocess_setup, **kwargs) |
206 | - except OSError, e: |
207 | - if e.errno != errno.ENOENT: |
208 | - raise |
209 | - if not_installed_msg is None: |
210 | - raise |
211 | - raise MissingDependency(msg=not_installed_msg) |
212 | - output = proc.communicate(indata) |
213 | - if success_exit_codes is None: |
214 | - success_exit_codes = [0] |
215 | - if proc.returncode not in success_exit_codes: |
216 | - if quiet: |
217 | - raise errors.BzrCommandError("%s: %s" % (error_msg, output)) |
218 | - else: |
219 | - raise errors.BzrCommandError(error_msg) |
220 | - |
221 | - |
222 | -def build_source_package(basedir, tgz_check=True): |
223 | - command = ["/usr/bin/debuild"] |
224 | - if tgz_check: |
225 | - command.append("--tgz-check") |
226 | - else: |
227 | - command.append("--no-tgz-check") |
228 | - command.extend(["-i", "-I", "-S", "-uc", "-us"]) |
229 | - _run_command(command, basedir, |
230 | - "Building the source package", |
231 | - "Failed to build the source package", |
232 | - not_installed_msg="debuild is not installed, please install " |
233 | - "the devscripts package.") |
234 | - |
235 | - |
236 | -def get_source_format(path): |
237 | - """Retrieve the source format name from a package. |
238 | - |
239 | - :param path: Path to the package |
240 | - :return: String with package format |
241 | - """ |
242 | - source_format_path = os.path.join(path, "debian", "source", "format") |
243 | - if not os.path.exists(source_format_path): |
244 | - return "1.0" |
245 | - f = open(source_format_path, 'r') |
246 | - try: |
247 | - return f.read().strip() |
248 | - finally: |
249 | - f.close() |
250 | - |
251 | - |
252 | -def convert_3_0_quilt_to_native(path): |
253 | - """Convert a package in 3.0 (quilt) format to 3.0 (native). |
254 | - |
255 | - This applies all patches in the package and updates the |
256 | - debian/source/format file. |
257 | - |
258 | - :param path: Path to the package on disk |
259 | - """ |
260 | - path = os.path.abspath(path) |
261 | - patches_dir = os.path.join(path, "debian", "patches") |
262 | - series_file = os.path.join(patches_dir, "series") |
263 | - if os.path.exists(series_file): |
264 | - _run_command(["quilt", "push", "-a", "-v"], path, |
265 | - "Applying quilt patches", |
266 | - "Failed to apply quilt patches", |
267 | - not_installed_msg="quilt is not installed, please install it.", |
268 | - env={"QUILT_SERIES": series_file, "QUILT_PATCHES": patches_dir}, |
269 | - success_exit_codes=(0, 2)) |
270 | - if os.path.exists(patches_dir): |
271 | - shutil.rmtree(patches_dir) |
272 | - f = open(os.path.join(path, "debian", "source", "format"), 'w') |
273 | - try: |
274 | - f.write("3.0 (native)\n") |
275 | - finally: |
276 | - f.close() |
277 | - |
278 | - |
279 | -def force_native_format(working_tree_path, current_format): |
280 | - """Make sure a package is a format that supports native packages. |
281 | - |
282 | - :param working_tree_path: Path to the package |
283 | - """ |
284 | - if current_format == "3.0 (quilt)": |
285 | - convert_3_0_quilt_to_native(working_tree_path) |
286 | - elif current_format not in ("1.0", "3.0 (native)"): |
287 | - raise errors.BzrCommandError("Unknown source format %s" % |
288 | - current_format) |
289 | - |
290 | - |
291 | -def sign_source_package(basedir, key_id): |
292 | - command = ["/usr/bin/debsign", "-S", "-k%s" % key_id] |
293 | - _run_command(command, basedir, |
294 | - "Signing the source package", |
295 | - "Signing the package failed", |
296 | - not_installed_msg="debsign is not installed, please install " |
297 | - "the devscripts package.") |
298 | - |
299 | - |
300 | -def dput_source_package(basedir, target): |
301 | - command = ["/usr/bin/debrelease", "-S", "--dput", target] |
302 | - _run_command(command, basedir, |
303 | - "Uploading the source package", |
304 | - "Uploading the package failed", |
305 | - not_installed_msg="debrelease is not installed, please " |
306 | - "install the devscripts package.") |
307 | - |
308 | - |
309 | launchpad_recipe_re = lazy_regex.lazy_compile( |
310 | r'^https://code.launchpad.net/~(.*)/\+recipe/(.*)$') |
311 | |
312 | @@ -486,72 +230,6 @@ |
313 | possible_transports) |
314 | |
315 | |
316 | -def debian_source_package_name(control_path): |
317 | - """Open a debian control file and extract the package name. |
318 | - |
319 | - """ |
320 | - f = open(control_path, 'r') |
321 | - try: |
322 | - control = deb822.Deb822(f) |
323 | - # Debian policy states package names are [a-z0-9][a-z0-9.+-]+ so ascii |
324 | - return control["Source"].encode("ascii") |
325 | - finally: |
326 | - f.close() |
327 | - |
328 | - |
329 | -def reconstruct_pristine_tar(dest, delta, dest_filename): |
330 | - """Reconstruct a pristine tarball from a directory and a delta. |
331 | - |
332 | - :param dest: Directory to pack |
333 | - :param delta: pristine-tar delta |
334 | - :param dest_filename: Destination filename |
335 | - """ |
336 | - command = ["pristine-tar", "gentar", "-", |
337 | - os.path.abspath(dest_filename)] |
338 | - _run_command(command, dest, |
339 | - "Reconstructing pristine tarball", |
340 | - "Generating tar from delta failed", |
341 | - not_installed_msg="pristine-tar is not installed", |
342 | - indata=delta) |
343 | - |
344 | - |
345 | -def extract_upstream_tarball(branch, package, version, dest_dir): |
346 | - """Extract the upstream tarball from a branch. |
347 | - |
348 | - :param branch: Branch with the upstream pristine tar data |
349 | - :param package: Package name |
350 | - :param version: Package version |
351 | - :param dest_dir: Destination directory |
352 | - """ |
353 | - tag_name = "upstream-%s" % version |
354 | - revid = branch.tags.lookup_tag(tag_name) |
355 | - tree = branch.repository.revision_tree(revid) |
356 | - rev = branch.repository.get_revision(revid) |
357 | - if 'deb-pristine-delta' in rev.properties: |
358 | - uuencoded = rev.properties['deb-pristine-delta'] |
359 | - dest_filename = "%s_%s.orig.tar.gz" % (package, version) |
360 | - elif 'deb-pristine-delta-bz2' in rev.properties: |
361 | - uuencoded = rev.properties['deb-pristine-delta-bz2'] |
362 | - dest_filename = "%s_%s.orig.tar.bz2" % (package, version) |
363 | - else: |
364 | - uuencoded = None |
365 | - if uuencoded is not None: |
366 | - delta = standard_b64decode(uuencoded) |
367 | - dest = os.path.join(dest_dir, "orig") |
368 | - try: |
369 | - _mod_export.export(tree, dest, format='dir') |
370 | - reconstruct_pristine_tar(dest, delta, |
371 | - os.path.join(dest_dir, dest_filename)) |
372 | - finally: |
373 | - if os.path.exists(dest): |
374 | - shutil.rmtree(dest) |
375 | - else: |
376 | - # Default to .tar.gz |
377 | - dest_filename = "%s_%s.orig.tar.gz" % (package, version) |
378 | - _mod_export.export(tree, os.path.join(dest_dir, dest_filename), |
379 | - per_file_timestamps=True) |
380 | - |
381 | - |
382 | class cmd_dailydeb(cmd_build): |
383 | """Build a deb based on a 'recipe' or from a branch. |
384 | |
385 | @@ -600,6 +278,31 @@ |
386 | if_changed_from=None, package=None, distribution=None, |
387 | dput=None, key_id=None, no_build=None, watch_ppa=False, |
388 | append_version=None, safe=False, allow_fallback_to_native=False): |
389 | + try: |
390 | + try: |
391 | + import debian |
392 | + except ImportError: |
393 | + # In older versions of python-debian the main package was named |
394 | + # debian_bundle |
395 | + import debian_bundle |
396 | + except ImportError: |
397 | + raise errors.BzrCommandError("The 'debian' python module " |
398 | + "is required for 'bzr dailydeb'. Install the " |
399 | + "python-debian package.") |
400 | + |
401 | + from bzrlib.plugins.builder.deb_util import ( |
402 | + add_autobuild_changelog_entry, |
403 | + build_source_package, |
404 | + calculate_package_dir, |
405 | + changelog, |
406 | + debian_source_package_name, |
407 | + dput_source_package, |
408 | + extract_upstream_tarball, |
409 | + force_native_format, |
410 | + get_source_format, |
411 | + sign_source_package, |
412 | + target_from_dput, |
413 | + ) |
414 | |
415 | if dput is not None and key_id is None: |
416 | raise errors.BzrCommandError("You must specify --key-id if you " |
417 | @@ -655,7 +358,7 @@ |
418 | if autobuild: |
419 | # Add changelog also substitutes {debupstream}. |
420 | add_autobuild_changelog_entry(base_branch, working_directory, |
421 | - package, distribution=distribution, |
422 | + package, distribution=distribution, |
423 | append_version=append_version) |
424 | else: |
425 | if append_version: |
426 | @@ -718,20 +421,3 @@ |
427 | recipe_name = recipe_name[:-len(".recipe")] |
428 | return package or recipe_name |
429 | |
430 | - |
431 | -def target_from_dput(dput): |
432 | - """Convert a dput specification to a LP API specification. |
433 | - |
434 | - :param dput: A dput command spec like ppa:team-name. |
435 | - :return: A LP API target like team-name/ppa. |
436 | - """ |
437 | - ppa_prefix = 'ppa:' |
438 | - if not dput.startswith(ppa_prefix): |
439 | - raise errors.BzrCommandError('%r does not appear to be a PPA. ' |
440 | - 'A dput target like \'%suser[/name]\' must be used.' |
441 | - % (dput, ppa_prefix)) |
442 | - base, _, suffix = dput[len(ppa_prefix):].partition('/') |
443 | - if not suffix: |
444 | - suffix = 'ppa' |
445 | - return base, suffix |
446 | - |
447 | |
448 | === added file 'deb_util.py' |
449 | --- deb_util.py 1970-01-01 00:00:00 +0000 |
450 | +++ deb_util.py 2011-12-15 16:22:26 +0000 |
451 | @@ -0,0 +1,370 @@ |
452 | +# bzr-builder: a bzr plugin to constuct trees based on recipes |
453 | +# Copyright 2009-2011 Canonical Ltd. |
454 | + |
455 | +# This program is free software: you can redistribute it and/or modify it |
456 | +# under the terms of the GNU General Public License version 3, as published |
457 | +# by the Free Software Foundation. |
458 | + |
459 | +# This program is distributed in the hope that it will be useful, but |
460 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
461 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
462 | +# PURPOSE. See the GNU General Public License for more details. |
463 | + |
464 | +# You should have received a copy of the GNU General Public License along |
465 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
466 | + |
467 | +"""Debian-specific utility functions.""" |
468 | + |
469 | +from base64 import standard_b64decode |
470 | +from email import utils |
471 | +import errno |
472 | +import os |
473 | +import shutil |
474 | +import signal |
475 | +import subprocess |
476 | + |
477 | +from bzrlib import ( |
478 | + errors, |
479 | + export as _mod_export, |
480 | + osutils, |
481 | + trace, |
482 | + ) |
483 | + |
484 | +from bzrlib.plugins.builder.recipe import ( |
485 | + SubstitutionUnavailable, |
486 | + ) |
487 | + |
488 | +try: |
489 | + from debian import changelog, deb822 |
490 | +except ImportError: |
491 | + # In older versions of python-debian the main package was named |
492 | + # debian_bundle |
493 | + from debian_bundle import changelog, deb822 |
494 | + |
495 | + |
496 | +try: |
497 | + get_maintainer = changelog.get_maintainer |
498 | +except AttributeError: |
499 | + # Implementation of get_maintainer was added after 0.1.18 so import same |
500 | + # function from backports module if python-debian doesn't have it. |
501 | + from bzrlib.plugins.builder.backports import get_maintainer |
502 | + |
503 | +# The default distribution used by add_autobuild_changelog_entry() |
504 | +DEFAULT_UBUNTU_DISTRIBUTION = "lucid" |
505 | + |
506 | + |
507 | +class MissingDependency(errors.BzrError): |
508 | + pass |
509 | + |
510 | + |
511 | +def target_from_dput(dput): |
512 | + """Convert a dput specification to a LP API specification. |
513 | + |
514 | + :param dput: A dput command spec like ppa:team-name. |
515 | + :return: A LP API target like team-name/ppa. |
516 | + """ |
517 | + ppa_prefix = 'ppa:' |
518 | + if not dput.startswith(ppa_prefix): |
519 | + raise errors.BzrCommandError('%r does not appear to be a PPA. ' |
520 | + 'A dput target like \'%suser[/name]\' must be used.' |
521 | + % (dput, ppa_prefix)) |
522 | + base, _, suffix = dput[len(ppa_prefix):].partition('/') |
523 | + if not suffix: |
524 | + suffix = 'ppa' |
525 | + return base, suffix |
526 | + |
527 | + |
528 | +def debian_source_package_name(control_path): |
529 | + """Open a debian control file and extract the package name. |
530 | + |
531 | + """ |
532 | + f = open(control_path, 'r') |
533 | + try: |
534 | + control = deb822.Deb822(f) |
535 | + # Debian policy states package names are [a-z0-9][a-z0-9.+-]+ so ascii |
536 | + return control["Source"].encode("ascii") |
537 | + finally: |
538 | + f.close() |
539 | + |
540 | + |
541 | +def reconstruct_pristine_tar(dest, delta, dest_filename): |
542 | + """Reconstruct a pristine tarball from a directory and a delta. |
543 | + |
544 | + :param dest: Directory to pack |
545 | + :param delta: pristine-tar delta |
546 | + :param dest_filename: Destination filename |
547 | + """ |
548 | + command = ["pristine-tar", "gentar", "-", |
549 | + os.path.abspath(dest_filename)] |
550 | + _run_command(command, dest, |
551 | + "Reconstructing pristine tarball", |
552 | + "Generating tar from delta failed", |
553 | + not_installed_msg="pristine-tar is not installed", |
554 | + indata=delta) |
555 | + |
556 | + |
557 | +def extract_upstream_tarball(branch, package, version, dest_dir): |
558 | + """Extract the upstream tarball from a branch. |
559 | + |
560 | + :param branch: Branch with the upstream pristine tar data |
561 | + :param package: Package name |
562 | + :param version: Package version |
563 | + :param dest_dir: Destination directory |
564 | + """ |
565 | + tag_name = "upstream-%s" % version |
566 | + revid = branch.tags.lookup_tag(tag_name) |
567 | + tree = branch.repository.revision_tree(revid) |
568 | + rev = branch.repository.get_revision(revid) |
569 | + if 'deb-pristine-delta' in rev.properties: |
570 | + uuencoded = rev.properties['deb-pristine-delta'] |
571 | + dest_filename = "%s_%s.orig.tar.gz" % (package, version) |
572 | + elif 'deb-pristine-delta-bz2' in rev.properties: |
573 | + uuencoded = rev.properties['deb-pristine-delta-bz2'] |
574 | + dest_filename = "%s_%s.orig.tar.bz2" % (package, version) |
575 | + else: |
576 | + uuencoded = None |
577 | + if uuencoded is not None: |
578 | + delta = standard_b64decode(uuencoded) |
579 | + dest = os.path.join(dest_dir, "orig") |
580 | + try: |
581 | + _mod_export.export(tree, dest, format='dir') |
582 | + reconstruct_pristine_tar(dest, delta, |
583 | + os.path.join(dest_dir, dest_filename)) |
584 | + finally: |
585 | + if os.path.exists(dest): |
586 | + shutil.rmtree(dest) |
587 | + else: |
588 | + # Default to .tar.gz |
589 | + dest_filename = "%s_%s.orig.tar.gz" % (package, version) |
590 | + _mod_export.export(tree, os.path.join(dest_dir, dest_filename), |
591 | + per_file_timestamps=True) |
592 | + |
593 | + |
594 | +def add_autobuild_changelog_entry(base_branch, basedir, package, |
595 | + distribution=None, author_name=None, author_email=None, |
596 | + append_version=None): |
597 | + """Add a new changelog entry for an autobuild. |
598 | + |
599 | + :param base_branch: Recipe base branch |
600 | + :param basedir: Base working directory |
601 | + :param package: package name |
602 | + :param distribution: Optional distribution (defaults to last entry |
603 | + distribution) |
604 | + :param author_name: Name of the build requester |
605 | + :param author_email: Email of the build requester |
606 | + :param append_version: Optional version suffix to add |
607 | + """ |
608 | + debian_dir = os.path.join(basedir, "debian") |
609 | + if not os.path.exists(debian_dir): |
610 | + os.makedirs(debian_dir) |
611 | + cl_path = os.path.join(debian_dir, "changelog") |
612 | + file_found = False |
613 | + if os.path.exists(cl_path): |
614 | + file_found = True |
615 | + cl_f = open(cl_path) |
616 | + try: |
617 | + contents = cl_f.read() |
618 | + finally: |
619 | + cl_f.close() |
620 | + cl = changelog.Changelog(file=contents) |
621 | + else: |
622 | + cl = changelog.Changelog() |
623 | + if len(cl._blocks) > 0: |
624 | + if distribution is None: |
625 | + distribution = cl._blocks[0].distributions.split()[0] |
626 | + else: |
627 | + if file_found: |
628 | + if len(contents.strip()) > 0: |
629 | + reason = ("debian/changelog didn't contain any " |
630 | + "parseable stanzas") |
631 | + else: |
632 | + reason = "debian/changelog was empty" |
633 | + else: |
634 | + reason = "debian/changelog was not present" |
635 | + if distribution is None: |
636 | + distribution = DEFAULT_UBUNTU_DISTRIBUTION |
637 | + if base_branch.format in (0.1, 0.2, 0.3): |
638 | + try: |
639 | + base_branch.substitute_changelog_vars(None, cl) |
640 | + except SubstitutionUnavailable, e: |
641 | + raise errors.BzrCommandError("No previous changelog to " |
642 | + "take the upstream version from as %s was " |
643 | + "used: %s: %s." % (e.name, e.reason, reason)) |
644 | + # Use debian packaging environment variables |
645 | + # or default values if they don't exist |
646 | + if author_name is None or author_email is None: |
647 | + author_name, author_email = get_maintainer() |
648 | + # The python-debian package breaks compatibility at version 0.1.20 by |
649 | + # switching to expecting (but not checking for) unicode rather than |
650 | + # bytestring inputs. Detect this and decode environment if needed. |
651 | + if getattr(changelog.Changelog, "__unicode__", None) is not None: |
652 | + enc = osutils.get_user_encoding() |
653 | + author_name = author_name.decode(enc) |
654 | + author_email = author_email.decode(enc) |
655 | + author = "%s <%s>" % (author_name, author_email) |
656 | + |
657 | + date = utils.formatdate(localtime=True) |
658 | + version = base_branch.deb_version |
659 | + if append_version is not None: |
660 | + version += append_version |
661 | + try: |
662 | + changelog.Version(version) |
663 | + except (changelog.VersionError, ValueError), e: |
664 | + raise errors.BzrCommandError("Invalid deb-version: %s: %s" |
665 | + % (version, e)) |
666 | + cl.new_block(package=package, version=version, |
667 | + distributions=distribution, urgency="low", |
668 | + changes=['', ' * Auto build.', ''], |
669 | + author=author, date=date) |
670 | + cl_f = open(cl_path, 'wb') |
671 | + try: |
672 | + cl.write_to_open_file(cl_f) |
673 | + finally: |
674 | + cl_f.close() |
675 | + |
676 | + |
677 | +def calculate_package_dir(package_name, package_version, working_basedir): |
678 | + """Calculate the directory name that should be used while debuilding. |
679 | + |
680 | + :param base_branch: Recipe base branch |
681 | + :param package_version: Version of the package |
682 | + :param package_name: Package name |
683 | + :param working_basedir: Base directory |
684 | + """ |
685 | + package_basedir = "%s-%s" % (package_name, package_version.upstream_version) |
686 | + package_dir = os.path.join(working_basedir, package_basedir) |
687 | + return package_dir |
688 | + |
689 | + |
690 | +def _run_command(command, basedir, msg, error_msg, |
691 | + not_installed_msg=None, env=None, success_exit_codes=None, indata=None): |
692 | + """ Run a command in a subprocess. |
693 | + |
694 | + :param command: list with command and parameters |
695 | + :param msg: message to display to the user |
696 | + :param error_msg: message to display if something fails. |
697 | + :param not_installed_msg: the message to display if the command |
698 | + isn't available. |
699 | + :param env: Optional environment to use rather than os.environ. |
700 | + :param success_exit_codes: Exit codes to consider succesfull, defaults to [0]. |
701 | + :param indata: Data to write to standard input |
702 | + """ |
703 | + def subprocess_setup(): |
704 | + signal.signal(signal.SIGPIPE, signal.SIG_DFL) |
705 | + trace.note(msg) |
706 | + # Hide output if -q is in use. |
707 | + quiet = trace.is_quiet() |
708 | + if quiet: |
709 | + kwargs = {"stderr": subprocess.STDOUT, "stdout": subprocess.PIPE} |
710 | + else: |
711 | + kwargs = {} |
712 | + if env is not None: |
713 | + kwargs["env"] = env |
714 | + trace.mutter("running: %r", command) |
715 | + try: |
716 | + proc = subprocess.Popen(command, cwd=basedir, |
717 | + stdin=subprocess.PIPE, preexec_fn=subprocess_setup, **kwargs) |
718 | + except OSError, e: |
719 | + if e.errno != errno.ENOENT: |
720 | + raise |
721 | + if not_installed_msg is None: |
722 | + raise |
723 | + raise MissingDependency(msg=not_installed_msg) |
724 | + output = proc.communicate(indata) |
725 | + if success_exit_codes is None: |
726 | + success_exit_codes = [0] |
727 | + if proc.returncode not in success_exit_codes: |
728 | + if quiet: |
729 | + raise errors.BzrCommandError("%s: %s" % (error_msg, output)) |
730 | + else: |
731 | + raise errors.BzrCommandError(error_msg) |
732 | + |
733 | + |
734 | +def build_source_package(basedir, tgz_check=True): |
735 | + command = ["/usr/bin/debuild"] |
736 | + if tgz_check: |
737 | + command.append("--tgz-check") |
738 | + else: |
739 | + command.append("--no-tgz-check") |
740 | + command.extend(["-i", "-I", "-S", "-uc", "-us"]) |
741 | + _run_command(command, basedir, |
742 | + "Building the source package", |
743 | + "Failed to build the source package", |
744 | + not_installed_msg="debuild is not installed, please install " |
745 | + "the devscripts package.") |
746 | + |
747 | + |
748 | +def get_source_format(path): |
749 | + """Retrieve the source format name from a package. |
750 | + |
751 | + :param path: Path to the package |
752 | + :return: String with package format |
753 | + """ |
754 | + source_format_path = os.path.join(path, "debian", "source", "format") |
755 | + if not os.path.exists(source_format_path): |
756 | + return "1.0" |
757 | + f = open(source_format_path, 'r') |
758 | + try: |
759 | + return f.read().strip() |
760 | + finally: |
761 | + f.close() |
762 | + |
763 | + |
764 | +def convert_3_0_quilt_to_native(path): |
765 | + """Convert a package in 3.0 (quilt) format to 3.0 (native). |
766 | + |
767 | + This applies all patches in the package and updates the |
768 | + debian/source/format file. |
769 | + |
770 | + :param path: Path to the package on disk |
771 | + """ |
772 | + path = os.path.abspath(path) |
773 | + patches_dir = os.path.join(path, "debian", "patches") |
774 | + series_file = os.path.join(patches_dir, "series") |
775 | + if os.path.exists(series_file): |
776 | + _run_command(["quilt", "push", "-a", "-v"], path, |
777 | + "Applying quilt patches", |
778 | + "Failed to apply quilt patches", |
779 | + not_installed_msg="quilt is not installed, please install it.", |
780 | + env={"QUILT_SERIES": series_file, "QUILT_PATCHES": patches_dir}, |
781 | + success_exit_codes=(0, 2)) |
782 | + if os.path.exists(patches_dir): |
783 | + shutil.rmtree(patches_dir) |
784 | + f = open(os.path.join(path, "debian", "source", "format"), 'w') |
785 | + try: |
786 | + f.write("3.0 (native)\n") |
787 | + finally: |
788 | + f.close() |
789 | + |
790 | + |
791 | +def force_native_format(working_tree_path, current_format): |
792 | + """Make sure a package is a format that supports native packages. |
793 | + |
794 | + :param working_tree_path: Path to the package |
795 | + """ |
796 | + if current_format == "3.0 (quilt)": |
797 | + convert_3_0_quilt_to_native(working_tree_path) |
798 | + elif current_format not in ("1.0", "3.0 (native)"): |
799 | + raise errors.BzrCommandError("Unknown source format %s" % |
800 | + current_format) |
801 | + |
802 | + |
803 | +def sign_source_package(basedir, key_id): |
804 | + command = ["/usr/bin/debsign", "-S", "-k%s" % key_id] |
805 | + _run_command(command, basedir, |
806 | + "Signing the source package", |
807 | + "Signing the package failed", |
808 | + not_installed_msg="debsign is not installed, please install " |
809 | + "the devscripts package.") |
810 | + |
811 | + |
812 | +def dput_source_package(basedir, target): |
813 | + command = ["/usr/bin/debrelease", "-S", "--dput", target] |
814 | + _run_command(command, basedir, |
815 | + "Uploading the source package", |
816 | + "Uploading the package failed", |
817 | + not_installed_msg="debrelease is not installed, please " |
818 | + "install the devscripts package.") |
819 | + |
820 | + |
821 | + |
822 | |
823 | === modified file 'tests/__init__.py' |
824 | --- tests/__init__.py 2011-08-14 18:08:51 +0000 |
825 | +++ tests/__init__.py 2011-12-15 16:22:26 +0000 |
826 | @@ -45,7 +45,7 @@ |
827 | suite = TestSuite() |
828 | testmod_names = [ |
829 | 'blackbox', |
830 | - 'ppa', |
831 | + 'deb_util', |
832 | 'recipe', |
833 | ] |
834 | suite.addTest(loader.loadTestsFromModuleNames(["%s.test_%s" % (__name__, i) |
835 | |
836 | === renamed file 'tests/test_ppa.py' => 'tests/test_deb_util.py' |
837 | --- tests/test_ppa.py 2011-05-05 12:33:08 +0000 |
838 | +++ tests/test_deb_util.py 2011-12-15 16:22:26 +0000 |
839 | @@ -13,7 +13,7 @@ |
840 | # You should have received a copy of the GNU General Public License along |
841 | # with this program. If not, see <http://www.gnu.org/licenses/>. |
842 | |
843 | -from bzrlib.plugins.builder.cmds import target_from_dput |
844 | +from bzrlib.plugins.builder.deb_util import target_from_dput |
845 | from bzrlib.tests import ( |
846 | TestCase, |
847 | ) |