~ubuntu-branches/ubuntu/quantal/bzr-builder/quantal

« back to all changes in this revision

Viewing changes to cmds.py

  • Committer: Package Import Robot
  • Author(s): Logan Rosen
  • Date: 2012-06-10 02:45:03 UTC
  • mfrom: (1.1.6) (12.1.2 precise)
  • Revision ID: package-import@ubuntu.com-20120610024503-4syoetggxq6qr1lp
Tags: 0.7.3-0ubuntu1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
"""Subcommands provided by bzr-builder."""
17
17
 
18
 
from base64 import standard_b64decode
19
18
from StringIO import StringIO
20
19
import datetime
21
 
from email import utils
22
 
import errno
23
20
import os
24
 
import signal
25
21
import shutil
26
 
import subprocess
27
22
import tempfile
28
23
 
29
 
try:
30
 
    from debian import changelog, deb822
31
 
except ImportError:
32
 
    # In older versions of python-debian the main package was named 
33
 
    # debian_bundle
34
 
    from debian_bundle import changelog, deb822
35
 
 
36
 
try:
37
 
    get_maintainer = changelog.get_maintainer
38
 
except AttributeError:
39
 
    # Implementation of get_maintainer was added after 0.1.18 so import same
40
 
    # function from backports module if python-debian doesn't have it.
41
 
    from bzrlib.plugins.builder.backports import get_maintainer
42
 
 
43
24
from bzrlib import (
44
 
        errors,
45
 
        export as _mod_export,
46
 
        lazy_regex,
47
 
        osutils,
48
 
        trace,
49
 
        transport as _mod_transport,
50
 
        urlutils,
51
 
        )
 
25
    errors,
 
26
    lazy_regex,
 
27
    trace,
 
28
    transport as _mod_transport,
 
29
    urlutils,
 
30
    )
52
31
from bzrlib.branch import Branch
53
32
from bzrlib.commands import Command
54
33
from bzrlib.option import Option
55
34
 
56
35
from bzrlib.plugins.builder.recipe import (
57
 
        BaseRecipeBranch,
58
 
        build_tree,
59
 
        RecipeParser,
60
 
        resolve_revisions,
61
 
        SAFE_INSTRUCTIONS,
62
 
        SubstitutionUnavailable,
63
 
        )
64
 
 
65
 
 
66
 
# The default distribution used by add_autobuild_changelog_entry()
67
 
DEFAULT_UBUNTU_DISTRIBUTION = "lucid"
68
 
 
69
 
 
70
 
class MissingDependency(errors.BzrError):
71
 
    pass
 
36
    BaseRecipeBranch,
 
37
    build_tree,
 
38
    RecipeParser,
 
39
    resolve_revisions,
 
40
    SAFE_INSTRUCTIONS,
 
41
    )
 
42
 
72
43
 
73
44
 
74
45
def write_manifest_to_transport(location, base_branch,
135
106
    return old_recipe
136
107
 
137
108
 
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.
142
 
 
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
147
 
        distribution)
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
151
 
    """
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")
156
 
    file_found = False
157
 
    if os.path.exists(cl_path):
158
 
        file_found = True
159
 
        cl_f = open(cl_path)
160
 
        try:
161
 
            contents = cl_f.read()
162
 
        finally:
163
 
            cl_f.close()
164
 
        cl = changelog.Changelog(file=contents)
165
 
    else:
166
 
        cl = changelog.Changelog()
167
 
    if len(cl._blocks) > 0:
168
 
        if distribution is None:
169
 
            distribution = cl._blocks[0].distributions.split()[0]
170
 
    else:
171
 
        if file_found:
172
 
            if len(contents.strip()) > 0:
173
 
                reason = ("debian/changelog didn't contain any "
174
 
                         "parseable stanzas")
175
 
            else:
176
 
                reason = "debian/changelog was empty"
177
 
        else:
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):
182
 
        try:
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)
200
 
 
201
 
    date = utils.formatdate(localtime=True)
202
 
    version = base_branch.deb_version
203
 
    if append_version is not None:
204
 
        version += append_version
205
 
    try:
206
 
        changelog.Version(version)
207
 
    except (changelog.VersionError, ValueError), e:
208
 
        raise errors.BzrCommandError("Invalid deb-version: %s: %s"
209
 
                % (version, e))
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')
215
 
    try:
216
 
        cl.write_to_open_file(cl_f)
217
 
    finally:
218
 
        cl_f.close()
219
 
 
220
 
 
221
 
def calculate_package_dir(package_name, package_version, working_basedir):
222
 
    """Calculate the directory name that should be used while debuilding.
223
 
 
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
228
 
    """
229
 
    package_basedir = "%s-%s" % (package_name, package_version.upstream_version)
230
 
    package_dir = os.path.join(working_basedir, package_basedir)
231
 
    return package_dir
232
 
 
233
 
 
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.
237
 
 
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
242
 
        isn't available.
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
246
 
    """
247
 
    def subprocess_setup():
248
 
        signal.signal(signal.SIGPIPE, signal.SIG_DFL)
249
 
    trace.note(msg)
250
 
    # Hide output if -q is in use.
251
 
    quiet = trace.is_quiet()
252
 
    if quiet:
253
 
        kwargs = {"stderr": subprocess.STDOUT, "stdout": subprocess.PIPE}
254
 
    else:
255
 
        kwargs = {}
256
 
    if env is not None:
257
 
        kwargs["env"] = env
258
 
    trace.mutter("running: %r", command)
259
 
    try:
260
 
        proc = subprocess.Popen(command, cwd=basedir,
261
 
                stdin=subprocess.PIPE, preexec_fn=subprocess_setup, **kwargs)
262
 
    except OSError, e:
263
 
        if e.errno != errno.ENOENT:
264
 
            raise
265
 
        if not_installed_msg is None:
266
 
            raise
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:
272
 
        if quiet:
273
 
            raise errors.BzrCommandError("%s: %s" % (error_msg, output))
274
 
        else:
275
 
            raise errors.BzrCommandError(error_msg)
276
 
 
277
 
 
278
 
def build_source_package(basedir, tgz_check=True):
279
 
    command = ["/usr/bin/debuild"]
280
 
    if tgz_check:
281
 
        command.append("--tgz-check")
282
 
    else:
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.")
290
 
 
291
 
 
292
 
def get_source_format(path):
293
 
    """Retrieve the source format name from a package.
294
 
 
295
 
    :param path: Path to the package
296
 
    :return: String with package format
297
 
    """
298
 
    source_format_path = os.path.join(path, "debian", "source", "format")
299
 
    if not os.path.exists(source_format_path):
300
 
        return "1.0"
301
 
    f = open(source_format_path, 'r')
302
 
    try:
303
 
        return f.read().strip()
304
 
    finally:
305
 
        f.close()
306
 
 
307
 
 
308
 
def convert_3_0_quilt_to_native(path):
309
 
    """Convert a package in 3.0 (quilt) format to 3.0 (native).
310
 
 
311
 
    This applies all patches in the package and updates the 
312
 
    debian/source/format file.
313
 
 
314
 
    :param path: Path to the package on disk
315
 
    """
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')
329
 
    try:
330
 
        f.write("3.0 (native)\n")
331
 
    finally:
332
 
        f.close()
333
 
 
334
 
 
335
 
def force_native_format(working_tree_path, current_format):
336
 
    """Make sure a package is a format that supports native packages.
337
 
 
338
 
    :param working_tree_path: Path to the package
339
 
    """
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" %
344
 
                                     current_format)
345
 
 
346
 
 
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.")
354
 
 
355
 
 
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.")
363
 
 
364
 
 
365
109
launchpad_recipe_re = lazy_regex.lazy_compile(
366
110
    r'^https://code.launchpad.net/~(.*)/\+recipe/(.*)$')
367
111
 
409
153
    return basename, recipe_transport.get(basename)
410
154
 
411
155
 
 
156
def get_prepared_branch_from_location(location,
 
157
        safe=False, possible_transports=None,
 
158
        revspec=None):
 
159
    """Common code to prepare a branch and do substitutions.
 
160
 
 
161
    :param location: a path to a recipe file or branch to work from.
 
162
    :param if_changed_from: an optional location of a manifest to
 
163
        compare the recipe against.
 
164
    :param safe: if True, reject recipes that would cause arbitrary code
 
165
        execution.
 
166
    :return: A tuple with (retcode, base_branch). If retcode is None
 
167
        then the command execution should continue.
 
168
    """
 
169
    try:
 
170
        base_branch = get_branch_from_recipe_location(location, safe=safe,
 
171
            possible_transports=possible_transports)
 
172
    except (_mod_transport.LateReadError, errors.ReadError):
 
173
        # Presume unable to read means location is a directory rather than a file
 
174
        base_branch = get_branch_from_branch_location(location,
 
175
            possible_transports=possible_transports)
 
176
    else:
 
177
        if revspec is not None:
 
178
            raise errors.BzrCommandError("--revision only supported when "
 
179
                "building from branch")
 
180
    return base_branch
 
181
 
 
182
 
412
183
class cmd_build(Command):
413
184
    """Build a tree based on a branch or a recipe.
414
185
 
427
198
            'revision',
428
199
                    ]
429
200
 
430
 
    def _get_prepared_branch_from_location(self, location,
431
 
            if_changed_from=None, safe=False, possible_transports=None,
432
 
            revspec=None):
433
 
        """Common code to prepare a branch and do substitutions.
434
 
 
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
439
 
            execution.
440
 
        :return: A tuple with (retcode, base_branch). If retcode is None
441
 
            then the command execution should continue.
442
 
        """
443
 
        try:
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)
450
 
        else:
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)
456
 
        old_recipe = None
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)
462
 
        if not changed:
463
 
            trace.note("Unchanged")
464
 
            return 0, base_branch
465
 
        return None, base_branch
466
 
 
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:
474
208
        else:
475
209
            revspec = None
476
210
        possible_transports = []
477
 
        result, base_branch = self._get_prepared_branch_from_location(location,
478
 
            if_changed_from=if_changed_from,
 
211
        base_branch = get_prepared_branch_from_location(location,
479
212
            possible_transports=possible_transports, revspec=revspec)
480
 
        if result is not None:
481
 
            return result
 
213
        if if_changed_from is not None:
 
214
            old_recipe = get_old_recipe(if_changed_from, possible_transports)
 
215
        else:
 
216
            old_recipe = None
 
217
        changed = resolve_revisions(base_branch, if_changed_from=old_recipe)
 
218
        if not changed:
 
219
            trace.note("Unchanged")
 
220
            return 0
482
221
        manifest_path = manifest or os.path.join(working_directory,
483
222
                        "bzr-builder.manifest")
484
223
        build_tree(base_branch, working_directory)
486
225
            possible_transports)
487
226
 
488
227
 
489
 
def debian_source_package_name(control_path):
490
 
    """Open a debian control file and extract the package name.
491
 
 
492
 
    """
493
 
    f = open(control_path, 'r')
494
 
    try:
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")
498
 
    finally:
499
 
        f.close()
500
 
 
501
 
 
502
 
def reconstruct_pristine_tar(dest, delta, dest_filename):
503
 
    """Reconstruct a pristine tarball from a directory and a delta.
504
 
 
505
 
    :param dest: Directory to pack
506
 
    :param delta: pristine-tar delta
507
 
    :param dest_filename: Destination filename
508
 
    """
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",
515
 
        indata=delta)
516
 
 
517
 
 
518
 
def extract_upstream_tarball(branch, package, version, dest_dir):
519
 
    """Extract the upstream tarball from a branch.
520
 
 
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
525
 
    """
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)
536
 
    else:
537
 
        uuencoded = None
538
 
    if uuencoded is not None:
539
 
        delta = standard_b64decode(uuencoded)
540
 
        dest = os.path.join(dest_dir, "orig")
541
 
        try:
542
 
            _mod_export.export(tree, dest, format='dir')
543
 
            reconstruct_pristine_tar(dest, delta,
544
 
                os.path.join(dest_dir, dest_filename))
545
 
        finally:
546
 
            if os.path.exists(dest):
547
 
                shutil.rmtree(dest)
548
 
    else:
549
 
        # Default to .tar.gz
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)
553
 
 
554
 
 
555
 
class cmd_dailydeb(cmd_build):
 
228
class cmd_dailydeb(Command):
556
229
    """Build a deb based on a 'recipe' or from a branch.
557
230
 
558
231
    See "bzr help builder" for more information on what a recipe is.
600
273
            if_changed_from=None, package=None, distribution=None,
601
274
            dput=None, key_id=None, no_build=None, watch_ppa=False,
602
275
            append_version=None, safe=False, allow_fallback_to_native=False):
 
276
        try:
 
277
            try:
 
278
                import debian
 
279
            except ImportError:
 
280
                # In older versions of python-debian the main package was named 
 
281
                # debian_bundle
 
282
                import debian_bundle
 
283
        except ImportError:
 
284
            raise errors.BzrCommandError("The 'debian' python module "
 
285
                "is required for 'bzr dailydeb'. Install the "
 
286
                "python-debian package.")
 
287
 
 
288
        from bzrlib.plugins.builder.deb_util import (
 
289
            add_autobuild_changelog_entry,
 
290
            build_source_package,
 
291
            calculate_package_dir,
 
292
            changelog,
 
293
            debian_source_package_name,
 
294
            dput_source_package,
 
295
            extract_upstream_tarball,
 
296
            force_native_format,
 
297
            get_source_format,
 
298
            sign_source_package,
 
299
            target_from_dput,
 
300
            )
 
301
        from bzrlib.plugins.builder.deb_version import (
 
302
            check_expanded_deb_version,
 
303
            substitute_branch_vars,
 
304
            substitute_time,
 
305
            )
603
306
 
604
307
        if dput is not None and key_id is None:
605
308
            raise errors.BzrCommandError("You must specify --key-id if you "
613
316
                target_from_dput(dput)
614
317
 
615
318
        possible_transports = []
616
 
        result, base_branch = self._get_prepared_branch_from_location(location,
617
 
            if_changed_from=if_changed_from, safe=safe,
 
319
        base_branch = get_prepared_branch_from_location(location, safe=safe,
618
320
            possible_transports=possible_transports)
619
 
        if result is not None:
620
 
            return result
 
321
        # Save the unsubstituted version
 
322
        template_version = base_branch.deb_version
 
323
        if if_changed_from is not None:
 
324
            old_recipe = get_old_recipe(if_changed_from, possible_transports)
 
325
        else:
 
326
            old_recipe = None
 
327
        if base_branch.deb_version is not None:
 
328
            time = datetime.datetime.utcnow()
 
329
            substitute_time(base_branch, time)
 
330
            changed = resolve_revisions(base_branch, if_changed_from=old_recipe,
 
331
                substitute_branch_vars=substitute_branch_vars)
 
332
            check_expanded_deb_version(base_branch)
 
333
        else:
 
334
            changed = resolve_revisions(base_branch, if_changed_from=old_recipe)
 
335
        if not changed:
 
336
            trace.note("Unchanged")
 
337
            return 0
621
338
        if working_basedir is None:
622
339
            temp_dir = tempfile.mkdtemp(prefix="bzr-builder-")
623
340
            working_basedir = temp_dir
626
343
            if not os.path.exists(working_basedir):
627
344
                os.makedirs(working_basedir)
628
345
        package_name = self._calculate_package_name(location, package)
629
 
        if self._template_version is None:
 
346
        if template_version is None:
630
347
            working_directory = os.path.join(working_basedir,
631
348
                "%s-direct" % (package_name,))
632
349
        else:
633
350
            working_directory = os.path.join(working_basedir,
634
 
                "%s-%s" % (package_name, self._template_version))
 
351
                "%s-%s" % (package_name, template_version))
635
352
        try:
636
353
            # we want to use a consistent package_dir always to support
637
354
            # updates in place, but debuild etc want PACKAGE-UPSTREAMVERSION
655
372
            if autobuild:
656
373
                # Add changelog also substitutes {debupstream}.
657
374
                add_autobuild_changelog_entry(base_branch, working_directory,
658
 
                    package, distribution=distribution, 
 
375
                    package, distribution=distribution,
659
376
                    append_version=append_version)
660
377
            else:
661
378
                if append_version:
671
388
                working_basedir)
672
389
            # working_directory -> package_dir: after this debian stuff works.
673
390
            os.rename(working_directory, package_dir)
674
 
            if no_build:
675
 
                if manifest is not None:
676
 
                    write_manifest_to_transport(manifest, base_branch,
677
 
                        possible_transports)
678
 
                return 0
679
 
            current_format = get_source_format(package_dir)
680
 
            if (package_version.debian_version is not None or
681
 
                current_format == "3.0 (quilt)"):
682
 
                # Non-native package
683
 
                try:
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)
692
 
                    else:
693
 
                        force_native_format(package_dir, current_format)
694
391
            try:
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)
699
 
                if dput is not None:
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)"):
 
395
                    # Non-native package
 
396
                    try:
 
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)
 
405
                        else:
 
406
                            force_native_format(package_dir, current_format)
 
407
                if not no_build:
 
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)
 
412
                    if dput is not None:
 
413
                        dput_source_package(package_dir, dput)
701
414
            finally:
702
415
                # package_dir -> working_directory
703
416
                # FIXME: may fail in error unwind, masking the original exception.
722
435
            recipe_name = recipe_name[:-len(".recipe")]
723
436
        return package or recipe_name
724
437
 
725
 
 
726
 
def target_from_dput(dput):
727
 
    """Convert a dput specification to a LP API specification.
728
 
 
729
 
    :param dput: A dput command spec like ppa:team-name.
730
 
    :return: A LP API target like team-name/ppa.
731
 
    """
732
 
    ppa_prefix = 'ppa:'
733
 
    if not dput.startswith(ppa_prefix):
734
 
        raise errors.BzrCommandError('%r does not appear to be a PPA. '
735
 
            'A dput target like \'%suser[/name]\' must be used.'
736
 
            % (dput, ppa_prefix))
737
 
    base, _, suffix = dput[len(ppa_prefix):].partition('/')
738
 
    if not suffix:
739
 
        suffix = 'ppa'
740
 
    return base, suffix
741