Merge lp:~jelmer/bzr-builder/deb-util into lp:bzr-builder

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
Reviewer Review Type Date Requested Status
James Westby Approve
Review via email: mp+85905@code.launchpad.net

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 )

Subscribers

People subscribed via source and target branches