135
106
return old_recipe
138
def add_autobuild_changelog_entry(base_branch, basedir, package,
139
distribution=None, author_name=None, author_email=None,
140
append_version=None):
141
"""Add a new changelog entry for an autobuild.
143
:param base_branch: Recipe base branch
144
:param basedir: Base working directory
145
:param package: package name
146
:param distribution: Optional distribution (defaults to last entry
148
:param author_name: Name of the build requester
149
:param author_email: Email of the build requester
150
:param append_version: Optional version suffix to add
152
debian_dir = os.path.join(basedir, "debian")
153
if not os.path.exists(debian_dir):
154
os.makedirs(debian_dir)
155
cl_path = os.path.join(debian_dir, "changelog")
157
if os.path.exists(cl_path):
161
contents = cl_f.read()
164
cl = changelog.Changelog(file=contents)
166
cl = changelog.Changelog()
167
if len(cl._blocks) > 0:
168
if distribution is None:
169
distribution = cl._blocks[0].distributions.split()[0]
172
if len(contents.strip()) > 0:
173
reason = ("debian/changelog didn't contain any "
176
reason = "debian/changelog was empty"
178
reason = "debian/changelog was not present"
179
if distribution is None:
180
distribution = DEFAULT_UBUNTU_DISTRIBUTION
181
if base_branch.format in (0.1, 0.2, 0.3):
183
base_branch.substitute_changelog_vars(None, cl)
184
except SubstitutionUnavailable, e:
185
raise errors.BzrCommandError("No previous changelog to "
186
"take the upstream version from as %s was "
187
"used: %s: %s." % (e.name, e.reason, reason))
188
# Use debian packaging environment variables
189
# or default values if they don't exist
190
if author_name is None or author_email is None:
191
author_name, author_email = get_maintainer()
192
# The python-debian package breaks compatibility at version 0.1.20 by
193
# switching to expecting (but not checking for) unicode rather than
194
# bytestring inputs. Detect this and decode environment if needed.
195
if getattr(changelog.Changelog, "__unicode__", None) is not None:
196
enc = osutils.get_user_encoding()
197
author_name = author_name.decode(enc)
198
author_email = author_email.decode(enc)
199
author = "%s <%s>" % (author_name, author_email)
201
date = utils.formatdate(localtime=True)
202
version = base_branch.deb_version
203
if append_version is not None:
204
version += append_version
206
changelog.Version(version)
207
except (changelog.VersionError, ValueError), e:
208
raise errors.BzrCommandError("Invalid deb-version: %s: %s"
210
cl.new_block(package=package, version=version,
211
distributions=distribution, urgency="low",
212
changes=['', ' * Auto build.', ''],
213
author=author, date=date)
214
cl_f = open(cl_path, 'wb')
216
cl.write_to_open_file(cl_f)
221
def calculate_package_dir(package_name, package_version, working_basedir):
222
"""Calculate the directory name that should be used while debuilding.
224
:param base_branch: Recipe base branch
225
:param package_version: Version of the package
226
:param package_name: Package name
227
:param working_basedir: Base directory
229
package_basedir = "%s-%s" % (package_name, package_version.upstream_version)
230
package_dir = os.path.join(working_basedir, package_basedir)
234
def _run_command(command, basedir, msg, error_msg,
235
not_installed_msg=None, env=None, success_exit_codes=None, indata=None):
236
""" Run a command in a subprocess.
238
:param command: list with command and parameters
239
:param msg: message to display to the user
240
:param error_msg: message to display if something fails.
241
:param not_installed_msg: the message to display if the command
243
:param env: Optional environment to use rather than os.environ.
244
:param success_exit_codes: Exit codes to consider succesfull, defaults to [0].
245
:param indata: Data to write to standard input
247
def subprocess_setup():
248
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
250
# Hide output if -q is in use.
251
quiet = trace.is_quiet()
253
kwargs = {"stderr": subprocess.STDOUT, "stdout": subprocess.PIPE}
258
trace.mutter("running: %r", command)
260
proc = subprocess.Popen(command, cwd=basedir,
261
stdin=subprocess.PIPE, preexec_fn=subprocess_setup, **kwargs)
263
if e.errno != errno.ENOENT:
265
if not_installed_msg is None:
267
raise MissingDependency(msg=not_installed_msg)
268
output = proc.communicate(indata)
269
if success_exit_codes is None:
270
success_exit_codes = [0]
271
if proc.returncode not in success_exit_codes:
273
raise errors.BzrCommandError("%s: %s" % (error_msg, output))
275
raise errors.BzrCommandError(error_msg)
278
def build_source_package(basedir, tgz_check=True):
279
command = ["/usr/bin/debuild"]
281
command.append("--tgz-check")
283
command.append("--no-tgz-check")
284
command.extend(["-i", "-I", "-S", "-uc", "-us"])
285
_run_command(command, basedir,
286
"Building the source package",
287
"Failed to build the source package",
288
not_installed_msg="debuild is not installed, please install "
289
"the devscripts package.")
292
def get_source_format(path):
293
"""Retrieve the source format name from a package.
295
:param path: Path to the package
296
:return: String with package format
298
source_format_path = os.path.join(path, "debian", "source", "format")
299
if not os.path.exists(source_format_path):
301
f = open(source_format_path, 'r')
303
return f.read().strip()
308
def convert_3_0_quilt_to_native(path):
309
"""Convert a package in 3.0 (quilt) format to 3.0 (native).
311
This applies all patches in the package and updates the
312
debian/source/format file.
314
:param path: Path to the package on disk
316
path = os.path.abspath(path)
317
patches_dir = os.path.join(path, "debian", "patches")
318
series_file = os.path.join(patches_dir, "series")
319
if os.path.exists(series_file):
320
_run_command(["quilt", "push", "-a", "-v"], path,
321
"Applying quilt patches",
322
"Failed to apply quilt patches",
323
not_installed_msg="quilt is not installed, please install it.",
324
env={"QUILT_SERIES": series_file, "QUILT_PATCHES": patches_dir},
325
success_exit_codes=(0, 2))
326
if os.path.exists(patches_dir):
327
shutil.rmtree(patches_dir)
328
f = open(os.path.join(path, "debian", "source", "format"), 'w')
330
f.write("3.0 (native)\n")
335
def force_native_format(working_tree_path, current_format):
336
"""Make sure a package is a format that supports native packages.
338
:param working_tree_path: Path to the package
340
if current_format == "3.0 (quilt)":
341
convert_3_0_quilt_to_native(working_tree_path)
342
elif current_format not in ("1.0", "3.0 (native)"):
343
raise errors.BzrCommandError("Unknown source format %s" %
347
def sign_source_package(basedir, key_id):
348
command = ["/usr/bin/debsign", "-S", "-k%s" % key_id]
349
_run_command(command, basedir,
350
"Signing the source package",
351
"Signing the package failed",
352
not_installed_msg="debsign is not installed, please install "
353
"the devscripts package.")
356
def dput_source_package(basedir, target):
357
command = ["/usr/bin/debrelease", "-S", "--dput", target]
358
_run_command(command, basedir,
359
"Uploading the source package",
360
"Uploading the package failed",
361
not_installed_msg="debrelease is not installed, please "
362
"install the devscripts package.")
365
109
launchpad_recipe_re = lazy_regex.lazy_compile(
366
110
r'^https://code.launchpad.net/~(.*)/\+recipe/(.*)$')
430
def _get_prepared_branch_from_location(self, location,
431
if_changed_from=None, safe=False, possible_transports=None,
433
"""Common code to prepare a branch and do substitutions.
435
:param location: a path to a recipe file or branch to work from.
436
:param if_changed_from: an optional location of a manifest to
437
compare the recipe against.
438
:param safe: if True, reject recipes that would cause arbitrary code
440
:return: A tuple with (retcode, base_branch). If retcode is None
441
then the command execution should continue.
444
base_branch = get_branch_from_recipe_location(location, safe=safe,
445
possible_transports=possible_transports)
446
except (_mod_transport.LateReadError, errors.ReadError):
447
# Presume unable to read means location is a directory rather than a file
448
base_branch = get_branch_from_branch_location(location,
449
possible_transports=possible_transports)
451
if revspec is not None:
452
raise errors.BzrCommandError("--revision only supported when "
453
"building from branch")
454
time = datetime.datetime.utcnow()
455
base_branch.substitute_time(time)
457
if if_changed_from is not None:
458
old_recipe = get_old_recipe(if_changed_from, possible_transports)
459
# Save the unsubstituted version for dailydeb.
460
self._template_version = base_branch.deb_version
461
changed = resolve_revisions(base_branch, if_changed_from=old_recipe)
463
trace.note("Unchanged")
464
return 0, base_branch
465
return None, base_branch
467
201
def run(self, location, working_directory, manifest=None,
468
202
if_changed_from=None, revision=None):
469
203
if revision is not None and len(revision) > 0:
486
225
possible_transports)
489
def debian_source_package_name(control_path):
490
"""Open a debian control file and extract the package name.
493
f = open(control_path, 'r')
495
control = deb822.Deb822(f)
496
# Debian policy states package names are [a-z0-9][a-z0-9.+-]+ so ascii
497
return control["Source"].encode("ascii")
502
def reconstruct_pristine_tar(dest, delta, dest_filename):
503
"""Reconstruct a pristine tarball from a directory and a delta.
505
:param dest: Directory to pack
506
:param delta: pristine-tar delta
507
:param dest_filename: Destination filename
509
command = ["pristine-tar", "gentar", "-",
510
os.path.abspath(dest_filename)]
511
_run_command(command, dest,
512
"Reconstructing pristine tarball",
513
"Generating tar from delta failed",
514
not_installed_msg="pristine-tar is not installed",
518
def extract_upstream_tarball(branch, package, version, dest_dir):
519
"""Extract the upstream tarball from a branch.
521
:param branch: Branch with the upstream pristine tar data
522
:param package: Package name
523
:param version: Package version
524
:param dest_dir: Destination directory
526
tag_name = "upstream-%s" % version
527
revid = branch.tags.lookup_tag(tag_name)
528
tree = branch.repository.revision_tree(revid)
529
rev = branch.repository.get_revision(revid)
530
if 'deb-pristine-delta' in rev.properties:
531
uuencoded = rev.properties['deb-pristine-delta']
532
dest_filename = "%s_%s.orig.tar.gz" % (package, version)
533
elif 'deb-pristine-delta-bz2' in rev.properties:
534
uuencoded = rev.properties['deb-pristine-delta-bz2']
535
dest_filename = "%s_%s.orig.tar.bz2" % (package, version)
538
if uuencoded is not None:
539
delta = standard_b64decode(uuencoded)
540
dest = os.path.join(dest_dir, "orig")
542
_mod_export.export(tree, dest, format='dir')
543
reconstruct_pristine_tar(dest, delta,
544
os.path.join(dest_dir, dest_filename))
546
if os.path.exists(dest):
550
dest_filename = "%s_%s.orig.tar.gz" % (package, version)
551
_mod_export.export(tree, os.path.join(dest_dir, dest_filename),
552
per_file_timestamps=True)
555
class cmd_dailydeb(cmd_build):
228
class cmd_dailydeb(Command):
556
229
"""Build a deb based on a 'recipe' or from a branch.
558
231
See "bzr help builder" for more information on what a recipe is.
672
389
# working_directory -> package_dir: after this debian stuff works.
673
390
os.rename(working_directory, package_dir)
675
if manifest is not None:
676
write_manifest_to_transport(manifest, base_branch,
679
current_format = get_source_format(package_dir)
680
if (package_version.debian_version is not None or
681
current_format == "3.0 (quilt)"):
684
extract_upstream_tarball(base_branch.branch, package_name,
685
package_version.upstream_version, working_basedir)
686
except errors.NoSuchTag, e:
687
if not allow_fallback_to_native:
688
raise errors.BzrCommandError(
689
"Unable to find the upstream source. Import it "
690
"as tag %s or build with "
691
"--allow-fallback-to-native." % e.tag_name)
693
force_native_format(package_dir, current_format)
695
build_source_package(package_dir,
696
tgz_check=not allow_fallback_to_native)
697
if key_id is not None:
698
sign_source_package(package_dir, key_id)
700
dput_source_package(package_dir, dput)
392
current_format = get_source_format(package_dir)
393
if (package_version.debian_version is not None or
394
current_format == "3.0 (quilt)"):
397
extract_upstream_tarball(base_branch.branch, package_name,
398
package_version.upstream_version, working_basedir)
399
except errors.NoSuchTag, e:
400
if not allow_fallback_to_native:
401
raise errors.BzrCommandError(
402
"Unable to find the upstream source. Import it "
403
"as tag %s or build with "
404
"--allow-fallback-to-native." % e.tag_name)
406
force_native_format(package_dir, current_format)
408
build_source_package(package_dir,
409
tgz_check=not allow_fallback_to_native)
410
if key_id is not None:
411
sign_source_package(package_dir, key_id)
413
dput_source_package(package_dir, dput)
702
415
# package_dir -> working_directory
703
416
# FIXME: may fail in error unwind, masking the original exception.