~ubuntu-branches/debian/sid/bzr-builddeb/sid

« back to all changes in this revision

Viewing changes to import_dsc.py

  • Committer: Bazaar Package Importer
  • Author(s): Jelmer Vernooij, Jelmer Vernooij, Jonathan Riddell, Scott Kitterman
  • Date: 2011-07-15 12:15:22 UTC
  • Revision ID: james.westby@ubuntu.com-20110715121522-avtc0uc3uuzcg7zn
Tags: 2.7.5
[ Jelmer Vernooij ]
* New 'bzr dep3-patch' subcommand that can generate DEP-3 compliant
  patches. LP: #460576

[ Jonathan Riddell ]
* Use new set_commit_message() hook in bzr to set the commit
  message from debian/changelog and set fixed bugs in tags. LP: #707274

[ Jelmer Vernooij ]
* Add dependency on devscripts >= 2.10.59, required now that 'dch --
  package' is used. LP: #783122
* Fix support for native packages with dashes in their version in
  sources.list. LP: #796853
* Fix deprecation warnings for TestCase.failUnlessExists and
  TestCase.failIfExists in bzr 2.4.

[ Scott Kitterman ]
* Delete debian/bzr-builddeb.dirs so the long obsolete and empty
  /usr/lib/python2.4/site-packages/bzrlib/plugins/bzr-builddeb/ is no
  longer created. Closes: #631564

[ Jelmer Vernooij ]
* Add support for xz and lzma tarballs. LP: #553668
* When importing upstream component tarballs, don't repack bz2/lzma
  tarballs to gz if the package is in v3 source format. LP: #810531

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
26
26
#
27
27
 
28
 
from base64 import (
29
 
    standard_b64encode,
30
 
    )
31
28
 
32
29
import os
33
 
import re
34
30
import shutil
35
31
import stat
36
32
import subprocess
40
36
    from debian import deb822
41
37
    from debian.changelog import Version, Changelog, VersionError
42
38
except ImportError:
43
 
  # Prior to 0.1.15 the debian module was called debian_bundle
 
39
    # Prior to 0.1.15 the debian module was called debian_bundle
44
40
    from debian_bundle import deb822
45
41
    from debian_bundle.changelog import Version, Changelog, VersionError
46
42
 
53
49
        AlreadyBranchError,
54
50
        BzrCommandError,
55
51
        NotBranchError,
56
 
        NoSuchRevision,
57
52
        NoWorkingTree,
58
53
        UnrelatedBranches,
59
54
        )
65
60
 
66
61
from bzrlib.plugins.builddeb.bzrtools_import import import_dir
67
62
from bzrlib.plugins.builddeb.errors import (
68
 
    TarFailed,
 
63
    PackageVersionNotPresent,
69
64
    UpstreamAlreadyImported,
70
65
    UpstreamBranchAlreadyMerged,
71
66
    )
72
67
from bzrlib.plugins.builddeb.util import (
 
68
    FORMAT_1_0,
73
69
    FORMAT_3_0_QUILT,
74
70
    FORMAT_3_0_NATIVE,
75
 
    export,
 
71
    component_from_orig_tarball,
 
72
    extract_orig_tarballs,
76
73
    get_commit_info_from_changelog,
77
 
    make_pristine_tar_delta,
78
74
    md5sum_filename,
79
75
    open_file_via_transport,
80
76
    open_transport,
81
77
    safe_decode,
82
78
    subprocess_setup,
83
79
    )
84
 
from bzrlib.plugins.builddeb.upstream import (
 
80
from bzrlib.plugins.builddeb.upstream.pristinetar import (
85
81
    PristineTarSource,
86
82
    )
87
 
from bzrlib.plugins.builddeb.upstream.branch import (
88
 
    UpstreamBranchSource,
89
 
    )
90
83
 
91
84
 
92
85
class DscCache(object):
93
86
 
94
 
  def __init__(self, transport=None):
95
 
    self.cache = {}
96
 
    self.transport_cache = {}
97
 
    self.transport = transport
98
 
 
99
 
  def get_dsc(self, name):
100
 
 
101
 
    if name in self.cache:
102
 
      dsc1 = self.cache[name]
103
 
    else:
104
 
      # Obtain the dsc file, following any redirects as needed.
105
 
      filename, transport = open_transport(name)
106
 
      f1 = open_file_via_transport(filename, transport)
107
 
      try:
108
 
        dsc1 = deb822.Dsc(f1)
109
 
      finally:
110
 
        f1.close()
111
 
      self.cache[name] = dsc1
112
 
      self.transport_cache[name] = transport
113
 
 
114
 
    return dsc1
115
 
 
116
 
  def get_transport(self, name):
117
 
    return self.transport_cache[name]
 
87
    def __init__(self, transport=None):
 
88
        self.cache = {}
 
89
        self.transport_cache = {}
 
90
        self.transport = transport
 
91
 
 
92
    def get_dsc(self, name):
 
93
 
 
94
        if name in self.cache:
 
95
            dsc1 = self.cache[name]
 
96
        else:
 
97
            # Obtain the dsc file, following any redirects as needed.
 
98
            filename, transport = open_transport(name)
 
99
            f1 = open_file_via_transport(filename, transport)
 
100
            try:
 
101
                dsc1 = deb822.Dsc(f1)
 
102
            finally:
 
103
                f1.close()
 
104
            self.cache[name] = dsc1
 
105
            self.transport_cache[name] = transport
 
106
 
 
107
        return dsc1
 
108
 
 
109
    def get_transport(self, name):
 
110
        return self.transport_cache[name]
118
111
 
119
112
class DscComp(object):
120
113
 
121
 
  def __init__(self, cache):
122
 
    self.cache = cache
 
114
    def __init__(self, cache):
 
115
        self.cache = cache
123
116
 
124
 
  def cmp(self, dscname1, dscname2):
125
 
    dsc1 = self.cache.get_dsc(dscname1)
126
 
    dsc2 = self.cache.get_dsc(dscname2)
127
 
    v1 = Version(dsc1['Version'])
128
 
    v2 = Version(dsc2['Version'])
129
 
    if v1 == v2:
130
 
      return 0
131
 
    if v1 > v2:
132
 
      return 1
133
 
    return -1
 
117
    def cmp(self, dscname1, dscname2):
 
118
        dsc1 = self.cache.get_dsc(dscname1)
 
119
        dsc2 = self.cache.get_dsc(dscname2)
 
120
        v1 = Version(dsc1['Version'])
 
121
        v2 = Version(dsc2['Version'])
 
122
        if v1 == v2:
 
123
            return 0
 
124
        if v1 > v2:
 
125
            return 1
 
126
        return -1
134
127
 
135
128
 
136
129
 
212
205
    have a total ordering with respect to these relationships.
213
206
    """
214
207
 
215
 
    def __init__(self, branch, upstream_branch, tree=None,
216
 
            upstream_tree=None):
 
208
    def __init__(self, branch, pristine_upstream_branch, tree=None,
 
209
            pristine_upstream_tree=None):
217
210
        """Create a distribution branch.
218
211
 
219
212
        You can only import packages on to the DistributionBranch
220
 
        if both tree and upstream_tree are provided.
 
213
        if both tree and pristine_upstream_tree are provided.
221
214
 
222
215
        :param branch: the Branch for the packaging part.
223
 
        :param upstream_branch: the Branch for the upstream part, if any.
 
216
        :param upstream_pristine_branch: the Branch for the pristine tar part, if any.
224
217
        :param tree: an optional tree for the branch.
225
 
        :param upstream_tree: an optional upstream_tree for the
 
218
        :param pristine_upstream_tree: an optional tree for the
226
219
            upstream_branch.
227
220
        """
228
221
        self.branch = branch
229
222
        self.tree = tree
230
 
        self.pristine_tar_source = PristineTarSource(branch=branch, tree=tree)
231
 
        self.upstream_branch = upstream_branch
232
 
        self.upstream_tree = upstream_tree
233
 
        if upstream_branch is not None:
234
 
            self.upstream_source = UpstreamBranchSource(self.upstream_branch)
 
223
        self.pristine_upstream_branch = pristine_upstream_branch
 
224
        self.pristine_upstream_tree = pristine_upstream_tree
 
225
        if pristine_upstream_branch is not None:
 
226
            self.pristine_upstream_source = PristineTarSource(
 
227
                branch=pristine_upstream_branch, tree=pristine_upstream_tree)
235
228
        else:
236
 
            self.upstream_source = None
 
229
            self.pristine_upstream_source = None
237
230
        self.get_lesser_branches = None
238
231
        self.get_greater_branches = None
239
232
 
284
277
        return str(version)
285
278
 
286
279
    def _has_version(self, branch, tag_name, md5=None):
287
 
        if branch.tags.has_tag(tag_name):
288
 
            revid = branch.tags.lookup_tag(tag_name)
289
 
            branch.lock_read()
290
 
            try:
291
 
                graph = branch.repository.get_graph()
292
 
                if not graph.is_ancestor(revid, branch.last_revision()):
293
 
                    return False
294
 
            finally:
295
 
                branch.unlock()
296
 
            if md5 is None:
297
 
                return True
298
 
            rev = branch.repository.get_revision(revid)
299
 
            try:
300
 
                return rev.properties['deb-md5'] == md5
301
 
            except KeyError:
302
 
                warning("tag %s present in branch, but there is no "
303
 
                    "associated 'deb-md5' property" % tag_name)
304
 
                pass
305
 
        return False
 
280
        if not branch.tags.has_tag(tag_name):
 
281
            return False
 
282
        revid = branch.tags.lookup_tag(tag_name)
 
283
        branch.lock_read()
 
284
        try:
 
285
            graph = branch.repository.get_graph()
 
286
            if not graph.is_ancestor(revid, branch.last_revision()):
 
287
                return False
 
288
        finally:
 
289
            branch.unlock()
 
290
        if md5 is None:
 
291
            return True
 
292
        rev = branch.repository.get_revision(revid)
 
293
        try:
 
294
            return rev.properties['deb-md5'] == md5
 
295
        except KeyError:
 
296
            warning("tag %s present in branch, but there is no "
 
297
                "associated 'deb-md5' property" % tag_name)
 
298
            return False
306
299
 
307
300
    def has_version(self, version, md5=None):
308
301
        """Whether this branch contains the package version specified.
329
322
            return True
330
323
        return False
331
324
 
332
 
    def has_upstream_version(self, version, md5=None):
333
 
        """Whether this branch contains the upstream version specified.
334
 
 
335
 
        The version must be judged present by having the appropriate tag
336
 
        in the upstream branch. If the md5 argument is not None then the
337
 
        string passed must the the md5sum that is associated with the
338
 
        revision pointed to by the tag.
339
 
 
340
 
        :param version: a upstream version number to look for in the upstream 
341
 
            branch.
342
 
        :param md5: a string with the md5sum that if not None must be
343
 
            associated with the revision.
344
 
        :return: True if the upstream branch contains the specified upstream
345
 
            version of the package. False otherwise.
346
 
        """
347
 
        for tag_name in self.pristine_tar_source.possible_tag_names(version):
348
 
            if self._has_version(self.upstream_branch, tag_name, md5=md5):
349
 
                return True
350
 
        return False
351
 
 
352
325
    def contained_versions(self, versions):
353
326
        """Splits a list of versions depending on presence in the branch.
354
327
 
436
409
            return self.branch.tags.lookup_tag(ubuntu_tag_name)
437
410
        return self.branch.tags.lookup_tag(tag_name)
438
411
 
439
 
    def revid_of_upstream_version(self, version):
440
 
        """Returns the revision id corresponding to the upstream version.
441
 
 
442
 
        :param version: the Version object to extract the upstream version
443
 
            from to retreive the revid of. The upstream version must be
444
 
            present in the upstream branch.
445
 
        :return: the revision id corresponding to the upstream portion
446
 
            of the version
447
 
        """
448
 
        for tag_name in self.pristine_tar_source.possible_tag_names(version):
449
 
            if self._has_version(self.upstream_branch, tag_name):
450
 
                return self.upstream_branch.tags.lookup_tag(tag_name)
451
 
        tag_name = self.pristine_tar_source.tag_name(version)
452
 
        return self.upstream_branch.tags.lookup_tag(tag_name)
453
 
 
454
412
    def tag_version(self, version, revid=None):
455
413
        """Tags the branch's last revision with the given version.
456
414
 
478
436
        :param version: the upstream part of the version number to derive the 
479
437
            tag name from.
480
438
        :param revid: the revid to associate the tag with, or None for the
481
 
            tip of self.upstream_branch.
 
439
            tip of self.pristine_upstream_branch.
482
440
        :return The tag name, revid of the added tag.
483
441
        """
484
442
        assert isinstance(version, str)
485
 
        tag_name = self.pristine_tar_source.tag_name(version)
 
443
        tag_name = self.pristine_upstream_source.tag_name(version)
486
444
        if revid is None:
487
 
            revid = self.upstream_branch.last_revision()
488
 
        self.upstream_branch.tags.set_tag(tag_name, revid)
489
 
        try:
490
 
            self.branch.repository.fetch(self.upstream_branch.repository,
491
 
                revision_id=revid)
492
 
        except NoSuchRevision:
493
 
            # See bug lp:574223
494
 
            pass
 
445
            revid = self.pristine_upstream_branch.last_revision()
 
446
        self.pristine_upstream_source.tag_version(version, revid)
 
447
        self.branch.fetch(self.pristine_upstream_branch)
495
448
        self.branch.tags.set_tag(tag_name, revid)
496
449
        return tag_name, revid
497
450
 
541
494
        except KeyError:
542
495
            return False
543
496
 
 
497
    def can_pull_from_branch(self, branch, version, md5):
 
498
        if not branch.has_version(version, md5=md5):
 
499
            return False
 
500
 
 
501
        # Check that they haven't diverged
 
502
        branch.branch.lock_read()
 
503
        try:
 
504
            graph = branch.branch.repository.get_graph(
 
505
                    self.branch.repository)
 
506
            return graph.is_ancestor(self.branch.last_revision(),
 
507
                    branch.revid_of_version(version))
 
508
        finally:
 
509
            branch.branch.unlock()
 
510
 
 
511
 
544
512
    def branch_to_pull_version_from(self, version, md5):
545
513
        """Checks whether this upload is a pull from a lesser branch.
546
514
 
566
534
        self.branch.lock_read()
567
535
        try:
568
536
            for branch in reversed(self.get_lesser_branches()):
569
 
                if branch.has_version(version, md5=md5):
570
 
                    # Check that they haven't diverged
571
 
                    branch.branch.lock_read()
572
 
                    try:
573
 
                        graph = branch.branch.repository.get_graph(
574
 
                                self.branch.repository)
575
 
                        other_revid = branch.revid_of_version(version)
576
 
                        if len(graph.heads([other_revid,
577
 
                                    self.branch.last_revision()])) == 1:
578
 
                            return branch
579
 
                    finally:
580
 
                        branch.branch.unlock()
 
537
                if self.can_pull_from_branch(branch, version, md5):
 
538
                    return branch
581
539
            for branch in self.get_greater_branches():
582
 
                if branch.has_version(version, md5=md5):
583
 
                    # Check that they haven't diverged
584
 
                    branch.branch.lock_read()
585
 
                    try:
586
 
                        graph = branch.branch.repository.get_graph(
587
 
                                self.branch.repository)
588
 
                        other_revid = branch.revid_of_version(version)
589
 
                        if len(graph.heads([other_revid,
590
 
                                    self.branch.last_revision()])) == 1:
591
 
                            return branch
592
 
                    finally:
593
 
                        branch.branch.unlock()
 
540
                if self.can_pull_from_branch(branch, version, md5):
 
541
                    return branch
594
542
            return None
595
543
        finally:
596
544
            self.branch.unlock()
597
545
 
598
 
    def branch_to_pull_upstream_from(self, version, md5):
 
546
    def can_pull_upstream_from_branch(self, branch, package, version,
 
547
            upstream_tarballs=None):
 
548
        """Check if a version can be pulled from another branch into this one.
 
549
 
 
550
        :param branch: Branch with upstream version
 
551
        :param package: Package name
 
552
        :param version: Package version
 
553
        :param upstream_tarballs: Required upstream tarballs (optional)
 
554
        """
 
555
        if not branch.pristine_upstream_source.has_version(package, version,
 
556
                tarballs=upstream_tarballs):
 
557
            return False
 
558
 
 
559
        up_branch = self.pristine_upstream_branch
 
560
        up_branch.lock_read()
 
561
        try:
 
562
            # Check that they haven't diverged
 
563
            other_up_branch = branch.pristine_upstream_branch
 
564
            other_up_branch.lock_read()
 
565
            try:
 
566
                graph = other_up_branch.repository.get_graph(
 
567
                        up_branch.repository)
 
568
                return graph.is_ancestor(up_branch.last_revision(),
 
569
                        branch.pristine_upstream_source.version_as_revision(package, version))
 
570
            finally:
 
571
                other_up_branch.unlock()
 
572
        finally:
 
573
            up_branch.unlock()
 
574
 
 
575
    def branch_to_pull_upstream_from(self, package, version, upstream_tarballs):
599
576
        """Checks whether this upstream is a pull from a lesser branch.
600
577
 
601
578
        Looks in all the other upstream branches for the given
608
585
 
609
586
        :param version: the upstream version to use when searching in the 
610
587
            lesser branches.
611
 
        :param md5: a String containing the md5 associateed with the
612
 
            upstream version.
613
588
        :return: a DistributionBranch object to pull the upstream from
614
589
            if that is what should be done, otherwise None.
615
590
        """
616
591
        assert isinstance(version, str)
617
 
        assert md5 is not None, \
618
 
            ("It's not a good idea to use branch_to_pull_upstream_from with "
619
 
             "md5 == None, as you may pull the wrong revision.")
620
 
        up_branch = self.upstream_branch
621
 
        up_branch.lock_read()
622
 
        try:
623
 
            for branch in reversed(self.get_lesser_branches()):
624
 
                if branch.has_upstream_version(version, md5=md5):
625
 
                    # Check for divergenge.
626
 
                    other_up_branch = branch.upstream_branch
627
 
                    other_up_branch.lock_read()
628
 
                    try:
629
 
                        graph = other_up_branch.repository.get_graph(
630
 
                                up_branch.repository)
631
 
                        other_revid = branch.revid_of_upstream_version(
632
 
                                version)
633
 
                        if len(graph.heads([other_revid,
634
 
                                    up_branch.last_revision()])) == 1:
635
 
                            return branch
636
 
                    finally:
637
 
                        other_up_branch.unlock()
638
 
            for branch in self.get_greater_branches():
639
 
                if branch.has_upstream_version(version, md5=md5):
640
 
                    # Check for divergenge.
641
 
                    other_up_branch = branch.upstream_branch
642
 
                    other_up_branch.lock_read()
643
 
                    try:
644
 
                        graph = other_up_branch.repository.get_graph(
645
 
                                up_branch.repository)
646
 
                        other_revid = branch.revid_of_upstream_version(
647
 
                                version)
648
 
                        if len(graph.heads([other_revid,
649
 
                                    up_branch.last_revision()])) == 1:
650
 
                            return branch
651
 
                    finally:
652
 
                        other_up_branch.unlock()
653
 
            return None
654
 
        finally:
655
 
            up_branch.unlock()
 
592
        for branch in reversed(self.get_lesser_branches()):
 
593
            if self.can_pull_upstream_from_branch(branch, package, version,
 
594
                    upstream_tarballs):
 
595
                return branch
 
596
        for branch in self.get_greater_branches():
 
597
            if self.can_pull_upstream_from_branch(branch, package, version,
 
598
                    upstream_tarballs):
 
599
                return branch
 
600
        return None
656
601
 
657
602
    def get_parents(self, versions):
658
603
        """Return the list of parents for a specific version.
719
664
                        last_revision=revid)
720
665
        return parents
721
666
 
722
 
    def pull_upstream_from_branch(self, pull_branch, version):
 
667
    def pull_upstream_from_branch(self, pull_branch, package, version):
723
668
        """Pulls an upstream version from a branch.
724
669
 
725
670
        Given a DistributionBranch and a version number this method
735
680
        :param version: the upstream version string
736
681
        """
737
682
        assert isinstance(version, str)
738
 
        pull_revision = pull_branch.revid_of_upstream_version(version)
 
683
        pull_revision = pull_branch.pristine_upstream_source.version_as_revision(package, version)
739
684
        mutter("Pulling upstream part of %s from revision %s" % \
740
685
                (version, pull_revision))
741
 
        up_pull_branch = pull_branch.upstream_branch
742
 
        assert self.upstream_tree is not None, \
 
686
        assert self.pristine_upstream_tree is not None, \
743
687
            "Can't pull upstream with no tree"
744
 
        self.upstream_tree.pull(up_pull_branch,
 
688
        self.pristine_upstream_tree.pull(pull_branch.pristine_upstream_branch,
745
689
                stop_revision=pull_revision)
746
 
        self.tag_upstream_version(version, revid=pull_revision)
747
 
        self.branch.fetch(self.upstream_branch, last_revision=pull_revision)
748
 
        self.upstream_branch.tags.merge_to(self.branch.tags)
 
690
        self.pristine_upstream_source.tag_version(version, pull_revision)
 
691
        self.branch.fetch(self.pristine_upstream_branch, last_revision=pull_revision)
 
692
        self.pristine_upstream_branch.tags.merge_to(self.branch.tags)
749
693
 
750
 
    def pull_version_from_branch(self, pull_branch, version, native=False):
 
694
    def pull_version_from_branch(self, pull_branch, package, version, native=False):
751
695
        """Pull a version from a particular branch.
752
696
 
753
697
        Given a DistributionBranch and a version number this method
774
718
        assert self.tree is not None, "Can't pull branch with no tree"
775
719
        self.tree.pull(pull_branch.branch, stop_revision=pull_revision)
776
720
        self.tag_version(version, revid=pull_revision)
777
 
        if not native and not self.has_upstream_version(version.upstream_version):
778
 
            if pull_branch.has_upstream_version(version.upstream_version):
 
721
        if not native and not self.pristine_upstream_source.has_version(package, version.upstream_version):
 
722
            if pull_branch.pristine_upstream_source.has_version(package, version.upstream_version):
779
723
                self.pull_upstream_from_branch(pull_branch, 
780
 
                    version.upstream_version)
 
724
                    package, version.upstream_version)
781
725
            else:
782
726
                assert False, ("Can't find the needed upstream part "
783
727
                        "for version %s" % version)
784
 
        if (native and self.upstream_branch.last_revision() == NULL_REVISION
785
 
            and pull_branch.upstream_branch.last_revision() != NULL_REVISION):
 
728
        if (native and self.pristine_upstream_branch.last_revision() == NULL_REVISION
 
729
            and pull_branch.pristine_upstream_branch.last_revision() != NULL_REVISION):
786
730
            # in case the package wasn't native before then we pull
787
731
            # the upstream. These checks may be a bit restrictive.
788
 
            self.upstream_tree.pull(pull_branch.upstream_branch)
789
 
            pull_branch.upstream_branch.tags.merge_to(self.upstream_branch.tags)
 
732
            self.pristine_upstream_tree.pull(pull_branch.pristine_upstream_branch)
 
733
            pull_branch.pristine_upstream_branch.tags.merge_to(self.pristine_upstream_branch.tags)
790
734
        elif native:
791
735
            mutter("Not checking for upstream as it is a native package")
792
736
        else:
793
737
            mutter("Not importing the upstream part as it is already "
794
738
                    "present in the upstream branch")
795
739
 
796
 
    def get_parents_with_upstream(self, version, versions,
797
 
            force_upstream_parent=False):
 
740
    def get_parents_with_upstream(self, package, version, versions,
 
741
            tarballs, force_upstream_parent=False):
798
742
        """Get the list of parents including any upstream parents.
799
743
 
800
744
        Further to get_parents this method includes any upstream parents
806
750
        If force_upstream_parent is True then the upstream parent will
807
751
        be included, even if another parent is already using that
808
752
        upstream. This is for use in cases where the .orig.tar.gz
809
 
        is different in two ditributions.
 
753
        is different in two distributions.
810
754
 
811
755
        :param version: the Version that we are currently importing.
812
756
        :param versions: the list of Versions that are ancestors of
830
774
                    break
831
775
        real_parents = [p[2] for p in parents]
832
776
        if need_upstream_parent:
833
 
            parent_revid = self.revid_of_upstream_version(version.upstream_version)
 
777
            parent_revid = self.pristine_upstream_source.version_as_revision(package,
 
778
                version.upstream_version, tarballs)
834
779
            if len(parents) > 0:
835
780
                real_parents.insert(1, parent_revid)
836
781
            else:
843
788
        # Make sure we see any revisions added by the upstream branch
844
789
        # since self.tree was locked.
845
790
        self.branch.repository.refresh_data()
846
 
        self.branch.fetch(self.upstream_branch, last_revision=revid)
847
 
        self.upstream_branch.tags.merge_to(self.branch.tags)
 
791
        self.branch.fetch(self.pristine_upstream_branch, last_revision=revid)
 
792
        self.pristine_upstream_branch.tags.merge_to(self.branch.tags)
848
793
 
849
 
    def import_upstream(self, upstream_part, version, md5, upstream_parents,
850
 
            upstream_tarball=None, upstream_branch=None,
 
794
    def import_upstream(self, upstream_part, package, version, upstream_parents,
 
795
            upstream_tarballs, upstream_branch=None,
851
796
            upstream_revision=None, timestamp=None, author=None,
852
797
            file_ids_from=None):
853
798
        """Import an upstream part on to the upstream branch.
858
803
        :param upstream_part: the path of a directory containing the
859
804
            unpacked upstream part of the source package.
860
805
        :param version: upstream version that is being imported
861
 
        :param md5: the md5 of the upstream part.
862
806
        :param upstream_parents: the parents to give the upstream revision
863
807
        :param timestamp: a tuple of (timestamp, timezone) to use for
864
808
            the commit, or None to use the current time.
865
 
        :return: (tag_name, revision_id) of the imported tarball.
 
809
        :return: list with (component, tag, revid) tuples
866
810
        """
867
811
        # Should we just dump the upstream part on whatever is currently
868
812
        # there, or try and pull all of the other upstream versions
872
816
        assert isinstance(version, str)
873
817
        mutter("Importing upstream version %s from %s with parents %s" \
874
818
                % (version, upstream_part, str(upstream_parents)))
875
 
        assert self.upstream_tree is not None, \
 
819
        assert self.pristine_upstream_tree is not None, \
876
820
            "Can't import upstream with no tree"
877
 
        if len(upstream_parents) > 0:
878
 
            parent_revid = upstream_parents[0]
879
 
        else:
880
 
            parent_revid = NULL_REVISION
881
 
        self.upstream_tree.pull(self.upstream_tree.branch, overwrite=True,
882
 
                stop_revision=parent_revid)
883
821
        other_branches = self.get_other_branches()
884
 
        def get_last_revision_tree(br):
885
 
            return br.repository.revision_tree(br.last_revision())
886
 
        upstream_trees = [get_last_revision_tree(o.upstream_branch)
887
 
            for o in other_branches]
888
 
        target_tree = None
889
 
        if upstream_branch is not None:
890
 
            if upstream_revision is None:
891
 
                upstream_revision = upstream_branch.last_revision()
892
 
            self.upstream_branch.fetch(upstream_branch,
893
 
                    last_revision=upstream_revision)
894
 
            upstream_branch.tags.merge_to(self.upstream_branch.tags)
895
 
            upstream_parents.append(upstream_revision)
896
 
            target_tree = self.upstream_branch.repository.revision_tree(
897
 
                        upstream_revision)
898
 
        if file_ids_from is not None:
899
 
            upstream_trees = file_ids_from + upstream_trees
900
 
        if self.tree:
901
 
            self_tree = self.tree
902
 
            self_tree.lock_write() # might also be upstream tree for dh_make
903
 
        else:
904
 
            self_tree = self.get_branch_tip_revtree()
905
 
            self_tree.lock_read()
906
 
        try:
907
 
            import_dir(self.upstream_tree, upstream_part,
908
 
                    file_ids_from=[self_tree] + upstream_trees,
909
 
                    target_tree=target_tree)
910
 
        finally:
911
 
            self_tree.unlock()
912
 
        self.upstream_tree.set_parent_ids(upstream_parents)
913
 
        revprops = {"deb-md5": md5}
914
 
        if upstream_tarball is not None:
915
 
            delta = self.make_pristine_tar_delta(
916
 
                self.upstream_tree, upstream_tarball)
917
 
            uuencoded = standard_b64encode(delta)
918
 
            if upstream_tarball.endswith(".tar.bz2"):
919
 
                revprops["deb-pristine-delta-bz2"] = uuencoded
920
 
            else:
921
 
                revprops["deb-pristine-delta"] = uuencoded
922
 
        if author is not None:
923
 
            revprops['authors'] = author
924
 
        timezone=None
925
 
        if timestamp is not None:
926
 
            timezone = timestamp[1]
927
 
            timestamp = timestamp[0]
928
 
        revid = self.upstream_tree.commit("Import upstream version %s" \
929
 
                % (version,),
930
 
                revprops=revprops, timestamp=timestamp, timezone=timezone)
931
 
        tag_name, _ = self.tag_upstream_version(version, revid=revid)
932
 
        return tag_name, revid
 
822
        ret = []
 
823
        for (tarball, component, md5) in upstream_tarballs:
 
824
            upstream_trees = [o.pristine_upstream_branch.basis_tree()
 
825
                for o in other_branches]
 
826
            target_tree = None
 
827
            if upstream_branch is not None:
 
828
                if upstream_revision is None:
 
829
                    upstream_revision = upstream_branch.last_revision()
 
830
                self.pristine_upstream_branch.fetch(upstream_branch,
 
831
                        last_revision=upstream_revision)
 
832
                upstream_branch.tags.merge_to(self.pristine_upstream_branch.tags)
 
833
                upstream_parents.append(upstream_revision)
 
834
                target_tree = self.pristine_upstream_branch.repository.revision_tree(
 
835
                            upstream_revision)
 
836
            if file_ids_from is not None:
 
837
                upstream_trees = file_ids_from + upstream_trees
 
838
            if self.tree:
 
839
                self_tree = self.tree
 
840
                self_tree.lock_write() # might also be upstream tree for dh_make
 
841
            else:
 
842
                self_tree = self.branch.basis_tree()
 
843
                self_tree.lock_read()
 
844
            if len(upstream_parents) > 0:
 
845
                parent_revid = upstream_parents[0]
 
846
            else:
 
847
                parent_revid = NULL_REVISION
 
848
            self.pristine_upstream_tree.pull(self.pristine_upstream_tree.branch,
 
849
                overwrite=True, stop_revision=parent_revid)
 
850
            if component is None:
 
851
                path = upstream_part
 
852
            else:
 
853
                path = os.path.join(upstream_part, component)
 
854
            try:
 
855
                import_dir(self.pristine_upstream_tree, path,
 
856
                        file_ids_from=[self_tree] + upstream_trees,
 
857
                        target_tree=target_tree)
 
858
            finally:
 
859
                self_tree.unlock()
 
860
            (tag, revid) = self.pristine_upstream_source.import_component_tarball(
 
861
                package, version, self.pristine_upstream_tree, upstream_parents, component,
 
862
                md5, tarball, author=author, timestamp=timestamp)
 
863
            ret.append((component, tag, revid))
 
864
            self.branch.fetch(self.pristine_upstream_branch)
 
865
            self.branch.tags.set_tag(tag, revid)
 
866
        return ret
933
867
 
934
 
    def import_upstream_tarball(self, tarball_filename, version, parents,
935
 
        md5sum=None, upstream_branch=None, upstream_revision=None):
 
868
    def import_upstream_tarballs(self, tarballs, package, version, parents,
 
869
        upstream_branch=None, upstream_revision=None):
936
870
        """Import an upstream part to the upstream branch.
937
871
 
938
 
        :param tarball_filename: The tarball to import.
 
872
        :param tarballs: List of tarballs / components to extract
939
873
        :param version: The upstream version to import.
940
874
        :param parents: The tarball-branch parents to use for the import.
941
875
            If an upstream branch is supplied, its automatically added to
944
878
            tarball.
945
879
        :param upstream_revision: Upstream revision id
946
880
        :param md5sum: hex digest of the md5sum of the tarball, if known.
947
 
        :return: (tag_name, revision_id) of the imported tarball.
 
881
        :return: list with (component, tag, revid) tuples
948
882
        """
949
 
        if not md5sum:
950
 
            md5sum = md5sum_filename(tarball_filename)
951
 
        tarball_dir = self._extract_tarball_to_tempdir(tarball_filename)
 
883
        tarball_dir = self._extract_tarballs_to_tempdir(tarballs)
952
884
        try:
953
 
            return self.import_upstream(tarball_dir, version, md5sum, parents,
954
 
                upstream_tarball=tarball_filename,
 
885
            return self.import_upstream(tarball_dir, package, version, parents,
 
886
                tarballs,
955
887
                upstream_branch=upstream_branch,
956
888
                upstream_revision=upstream_revision)
957
889
        finally:
958
890
            shutil.rmtree(tarball_dir)
959
891
 
960
 
    def get_branch_tip_revtree(self):
961
 
        return self.branch.repository.revision_tree(
962
 
                self.branch.last_revision())
963
 
 
964
892
    def _mark_native_config(self, native):
965
 
        poss_native_tree = self.get_branch_tip_revtree()
 
893
        poss_native_tree = self.branch.basis_tree()
966
894
        current_native = self._is_tree_native(poss_native_tree)
967
895
        current_config = self._default_config_for_tree(poss_native_tree)
968
 
        dirname = os.path.join(self.tree.basedir,
969
 
                '.bzr-builddeb')
 
896
        dirname = os.path.join(self.tree.basedir, '.bzr-builddeb')
970
897
        if current_config is not None:
971
898
            # Add that back to the current tree
972
899
            if not os.path.exists(dirname):
1043
970
                   "as the single parent")
1044
971
            parents = [self.branch.last_revision()]
1045
972
        other_branches = self.get_other_branches()
1046
 
        def get_last_revision_tree(br):
1047
 
            return br.repository.revision_tree(br.last_revision())
1048
 
        debian_trees = [get_last_revision_tree(o.branch)
1049
 
            for o in other_branches]
 
973
        debian_trees = [o.branch.basis_tree() for o in other_branches]
1050
974
        parent_trees = []
1051
975
        if file_ids_from is not None:
1052
976
            parent_trees = file_ids_from[:]
1075
999
        if message is None:
1076
1000
            message = 'Import packaging changes for version %s' % \
1077
1001
                        (str(version),)
1078
 
        revprops={"deb-md5":md5}
 
1002
        revprops={"deb-md5": md5}
1079
1003
        if native:
1080
1004
            revprops['deb-native'] = "True"
1081
1005
        if authors:
1093
1017
                timezone=timezone)
1094
1018
        self.tag_version(version, revid=revid)
1095
1019
 
1096
 
    def upstream_parents(self, versions, version):
 
1020
    def upstream_parents(self, package, versions, version):
1097
1021
        """Get the parents for importing a new upstream.
1098
1022
 
1099
1023
        The upstream parents will be the last upstream version,
1103
1027
            importing the specified upstream version.
1104
1028
        """
1105
1029
        parents = []
1106
 
        first_parent = self.upstream_branch.last_revision()
 
1030
        first_parent = self.pristine_upstream_branch.last_revision()
1107
1031
        if first_parent != NULL_REVISION:
1108
1032
            parents = [first_parent]
1109
1033
        last_contained_version = self.last_contained_version(versions)
1112
1036
            # upstream as a non-native version (i.e. it wasn't a mistaken
1113
1037
            # native -2 version), then we want to add an extra parent.
1114
1038
            if (self.is_version_native(last_contained_version)
1115
 
                and not self.has_upstream_version(last_contained_version.upstream_version)):
 
1039
                and not self.pristine_upstream_source.has_version(package,
 
1040
                    last_contained_version.upstream_version)):
1116
1041
                revid = self.revid_of_version(last_contained_version)
1117
1042
                parents.append(revid)
1118
 
                self.upstream_branch.fetch(self.branch,
 
1043
                self.pristine_upstream_branch.fetch(self.branch,
1119
1044
                        last_revision=revid)
1120
1045
        pull_parents = self.get_parents(versions)
1121
1046
        if ((first_parent == NULL_REVISION and len(pull_parents) > 0)
1127
1052
                pull_branch = pull_parents[1][0]
1128
1053
                pull_version = pull_parents[1][1]
1129
1054
            if not pull_branch.is_version_native(pull_version):
1130
 
                    pull_revid = \
1131
 
                        pull_branch.revid_of_upstream_version(pull_version.upstream_version)
1132
 
                    mutter("Initialising upstream from %s, version %s" \
1133
 
                        % (str(pull_branch), str(pull_version)))
1134
 
                    parents.append(pull_revid)
1135
 
                    self.upstream_branch.fetch(
1136
 
                            pull_branch.upstream_branch,
1137
 
                            last_revision=pull_revid)
1138
 
                    pull_branch.upstream_branch.tags.merge_to(
1139
 
                            self.upstream_branch.tags)
 
1055
                pull_revid = pull_branch.pristine_upstream_source.version_as_revision(
 
1056
                    package, pull_version.upstream_version)
 
1057
                mutter("Initialising upstream from %s, version %s",
 
1058
                    str(pull_branch), str(pull_version))
 
1059
                parents.append(pull_revid)
 
1060
                self.pristine_upstream_branch.fetch(
 
1061
                        pull_branch.pristine_upstream_branch,
 
1062
                        last_revision=pull_revid)
 
1063
                pull_branch.pristine_upstream_branch.tags.merge_to(
 
1064
                        self.pristine_upstream_branch.tags)
1140
1065
        return parents
1141
1066
 
1142
1067
    def get_changelog_from_source(self, dir):
1145
1070
        cl.parse_changelog(open(cl_filename).read(), strict=False)
1146
1071
        return cl
1147
1072
 
1148
 
    def _do_import_package(self, version, versions, debian_part, md5,
1149
 
            upstream_part, upstream_md5, upstream_tarball=None,
1150
 
            timestamp=None, author=None, file_ids_from=None,
1151
 
            pull_debian=True):
 
1073
    def _import_normal_package(self, package, version, versions, debian_part, md5,
 
1074
            upstream_part, upstream_tarballs, timestamp=None, author=None,
 
1075
            file_ids_from=None, pull_debian=True):
 
1076
        """Import a source package.
 
1077
 
 
1078
        :param package: Package name
 
1079
        :param version: Full Debian version
 
1080
        :param versions: Safe versions from changelog
 
1081
        :param debian_part: Path to extracted directory with Debian changes
 
1082
        :param unextracted_debian_md5: MD5 sum of unextracted Debian diff/tarball
 
1083
        :param upstream_part: Extracted upstream directory
 
1084
        :param upstream_tarballs: List of tuples with (upstream tarfile, md5sum)
 
1085
        :param timestamp: Version timestamp according to changelog
 
1086
        :param author: Author according to changelog
 
1087
        :param file_ids_from: Sequence of trees to take file ids from
 
1088
        :param pull_debian: Whether to pull from the Debian branch
 
1089
        """
1152
1090
        pull_branch = None
1153
1091
        if pull_debian:
1154
1092
            pull_branch = self.branch_to_pull_version_from(version, md5)
1155
1093
        if pull_branch is not None:
1156
 
            if (self.branch_to_pull_upstream_from(version.upstream_version,
1157
 
                        upstream_md5)
 
1094
            if (self.branch_to_pull_upstream_from(package,
 
1095
                    version.upstream_version, upstream_tarballs)
1158
1096
                    is None):
1159
1097
                pull_branch = None
1160
1098
        if pull_branch is not None:
1161
 
            self.pull_version_from_branch(pull_branch, version)
 
1099
            self.pull_version_from_branch(pull_branch, package, version)
1162
1100
        else:
1163
1101
            # We need to import at least the diff, possibly upstream.
1164
1102
            # Work out if we need the upstream part first.
1165
1103
            imported_upstream = False
1166
 
            if not self.has_upstream_version(version.upstream_version):
 
1104
            if not self.pristine_upstream_source.has_version(package,
 
1105
                    version.upstream_version):
1167
1106
                up_pull_branch = \
1168
 
                    self.branch_to_pull_upstream_from(version.upstream_version,
1169
 
                            upstream_md5)
 
1107
                    self.branch_to_pull_upstream_from(package, version.upstream_version,
 
1108
                            upstream_tarballs)
1170
1109
                if up_pull_branch is not None:
1171
1110
                    self.pull_upstream_from_branch(up_pull_branch,
1172
 
                            version.upstream_version)
 
1111
                            package, version.upstream_version)
1173
1112
                else:
1174
1113
                    imported_upstream = True
1175
1114
                    # Check whether we should pull first if this initialises
1176
1115
                    # from another branch:
1177
 
                    upstream_parents = self.upstream_parents(versions,
 
1116
                    upstream_parents = self.upstream_parents(package, versions,
1178
1117
                            version.upstream_version)
1179
 
                    _, new_revid = self.import_upstream(upstream_part,
1180
 
                            version.upstream_version,
1181
 
                            upstream_md5, upstream_parents,
1182
 
                            upstream_tarball=upstream_tarball,
 
1118
                    for (component, tag, revid) in self.import_upstream(upstream_part,
 
1119
                            package, version.upstream_version,
 
1120
                            upstream_parents,
 
1121
                            upstream_tarballs=upstream_tarballs,
1183
1122
                            timestamp=timestamp, author=author,
1184
 
                            file_ids_from=file_ids_from)
1185
 
                    self._fetch_upstream_to_branch(new_revid)
 
1123
                            file_ids_from=file_ids_from):
 
1124
                        self._fetch_upstream_to_branch(revid)
1186
1125
            else:
1187
1126
                mutter("We already have the needed upstream part")
1188
 
            parents = self.get_parents_with_upstream(version, versions,
1189
 
                    force_upstream_parent=imported_upstream)
 
1127
            parents = self.get_parents_with_upstream(package, version, versions,
 
1128
                    upstream_tarballs, force_upstream_parent=imported_upstream)
1190
1129
            # Now we have the list of parents we need to import the .diff.gz
1191
1130
            self.import_debian(debian_part, version, parents, md5,
1192
1131
                    timestamp=timestamp, file_ids_from=file_ids_from)
1208
1147
                branch.branch.tags.merge_to(self.branch.tags)
1209
1148
                self.branch.fetch(branch.branch,
1210
1149
                        last_revision=revid)
1211
 
                if self.upstream_branch.last_revision() == NULL_REVISION:
1212
 
                    self.upstream_tree.pull(branch.upstream_branch)
1213
 
                    branch.upstream_branch.tags.merge_to(self.upstream_branch.tags)
 
1150
                if self.pristine_upstream_branch.last_revision() == NULL_REVISION:
 
1151
                    self.pristine_upstream_tree.pull(branch.pristine_upstream_branch)
 
1152
                    branch.pristine_upstream_branch.tags.merge_to(self.pristine_upstream_branch.tags)
1214
1153
        for branch in self.get_greater_branches():
1215
1154
            merged, missing_versions = \
1216
1155
                branch.contained_versions(missing_versions)
1221
1160
                branch.branch.tags.merge_to(self.branch.tags)
1222
1161
                self.branch.fetch(branch.branch,
1223
1162
                        last_revision=revid)
1224
 
                if self.upstream_branch.last_revision() == NULL_REVISION:
1225
 
                    self.upstream_tree.pull(branch.upstream_branch)
1226
 
                    branch.upstream_branch.tags.merge_to(self.upstream_branch.tags)
 
1163
                if self.pristine_upstream_branch.last_revision() == NULL_REVISION:
 
1164
                    self.pristine_upstream_tree.pull(branch.pristine_upstream_branch)
 
1165
                    branch.pristine_upstream_branch.tags.merge_to(self.pristine_upstream_branch.tags)
1227
1166
        if (self.branch.last_revision() != NULL_REVISION
1228
1167
                and not self.branch.last_revision() in parents):
1229
1168
            parents.insert(0, self.branch.last_revision())
1230
1169
        return parents
1231
1170
 
1232
 
    def _import_native_package(self, version, versions, debian_part, md5,
 
1171
    def _import_native_package(self, package, version, versions, debian_part, md5,
1233
1172
            timestamp=None, file_ids_from=None, pull_debian=True):
1234
1173
        pull_branch = None
1235
1174
        if pull_debian:
1236
1175
            pull_branch = self.branch_to_pull_version_from(version, md5)
1237
1176
        if pull_branch is not None:
1238
 
            self.pull_version_from_branch(pull_branch, version, native=True)
 
1177
            self.pull_version_from_branch(pull_branch, package, version, native=True)
1239
1178
        else:
1240
1179
            parents = self.get_native_parents(version, versions)
1241
1180
            self.import_debian(debian_part, version, parents, md5,
1263
1202
        base_path = osutils.dirname(dsc_filename)
1264
1203
        dsc = deb822.Dsc(open(dsc_filename).read())
1265
1204
        version = Version(dsc['Version'])
1266
 
        format = dsc.get('Format', '1.0').strip()
 
1205
        format = dsc.get('Format', FORMAT_1_0).strip()
1267
1206
        extractor_cls = SOURCE_EXTRACTORS.get(format)
1268
1207
        if extractor_cls is None:
1269
1208
            raise AssertionError("Don't know how to import source format %s yet"
1287
1226
            #TODO: check that the versions list is correctly ordered,
1288
1227
            # as some methods assume that, and it's not clear what
1289
1228
            # should happen if it isn't.
 
1229
 
1290
1230
            if extractor.extracted_upstream is not None:
1291
 
                self._do_import_package(version, versions,
 
1231
                self._import_normal_package(dsc['Source'], version, versions,
1292
1232
                        extractor.extracted_debianised,
1293
1233
                        extractor.unextracted_debian_md5,
1294
1234
                        extractor.extracted_upstream,
1295
 
                        extractor.unextracted_upstream_md5,
1296
 
                        upstream_tarball=extractor.unextracted_upstream,
 
1235
                        extractor.upstream_tarballs,
1297
1236
                        timestamp=timestamp, author=author,
1298
1237
                        file_ids_from=file_ids_from,
1299
1238
                        pull_debian=pull_debian)
1300
1239
            else:
1301
 
                self._import_native_package(version, versions,
 
1240
                self._import_native_package(dsc['Source'], version, versions,
1302
1241
                        extractor.extracted_debianised,
1303
1242
                        extractor.unextracted_debian_md5,
1304
1243
                        timestamp=timestamp, file_ids_from=file_ids_from,
1313
1252
        # TODO: remove the _extract_upstream_tree alias below.
1314
1253
        to_location = os.path.join(basedir, "upstream")
1315
1254
        # Use upstream_branch if it has been set, otherwise self.branch.
1316
 
        source_branch = self.upstream_branch or self.branch
 
1255
        source_branch = self.pristine_upstream_branch or self.branch
1317
1256
        dir_to = source_branch.bzrdir.sprout(to_location,
1318
1257
                revision_id=upstream_tip,
1319
1258
                accelerator_tree=self.tree)
1320
1259
        try:
1321
 
            self.upstream_tree = dir_to.open_workingtree()
 
1260
            self.pristine_upstream_tree = dir_to.open_workingtree()
1322
1261
        except NoWorkingTree:
1323
1262
            # Handle shared treeless repo's.
1324
 
            self.upstream_tree = dir_to.create_workingtree()
1325
 
        self.upstream_branch = self.upstream_tree.branch
 
1263
            self.pristine_upstream_tree = dir_to.create_workingtree()
 
1264
        self.pristine_upstream_branch = self.pristine_upstream_tree.branch
1326
1265
 
1327
1266
    _extract_upstream_tree = extract_upstream_tree
1328
1267
 
1346
1285
            else:
1347
1286
                branch = existing_bzrdir.create_branch()
1348
1287
                existing_bzrdir.create_workingtree()
1349
 
        self.upstream_branch = branch
1350
 
        self.upstream_tree = branch.bzrdir.open_workingtree()
 
1288
        self.pristine_upstream_branch = branch
 
1289
        self.pristine_upstream_tree = branch.bzrdir.open_workingtree()
1351
1290
        if self.tree:
1352
1291
            root_id = self.tree.path2id('')
1353
1292
        else:
1354
 
            tip = self.get_branch_tip_revtree()
 
1293
            tip = self.branch.basis_tree()
1355
1294
            tip.lock_read()
1356
1295
            try:
1357
1296
                root_id = tip.path2id('')
1358
1297
            finally:
1359
1298
                tip.unlock()
1360
1299
        if root_id:
1361
 
            self.upstream_tree.set_root_id(root_id)
 
1300
            self.pristine_upstream_tree.set_root_id(root_id)
1362
1301
 
1363
 
    def _extract_tarball_to_tempdir(self, tarball_filename):
 
1302
    def _extract_tarballs_to_tempdir(self, tarballs):
1364
1303
        tempdir = tempfile.mkdtemp()
1365
 
        if tarball_filename.endswith(".tar.bz2"):
1366
 
            tar_args = 'xjf'
1367
 
        else:
1368
 
            tar_args = 'xzf'
1369
1304
        try:
1370
 
            proc = subprocess.Popen(["tar", tar_args, tarball_filename, "-C",
1371
 
                    tempdir, "--strip-components", "1"],
1372
 
                    preexec_fn=subprocess_setup)
1373
 
            proc.communicate()
1374
 
            if proc.returncode != 0:
1375
 
                raise TarFailed("extract", tarball_filename)
 
1305
            extract_orig_tarballs(
 
1306
                [(fn, component) for (fn, component, md5) in tarballs],
 
1307
                tempdir, strip_components=1)
1376
1308
            return tempdir
1377
1309
        except:
1378
1310
            shutil.rmtree(tempdir)
1379
1311
            raise
1380
1312
 
1381
 
    def _export_previous_upstream_tree(self, package, previous_version, tempdir, upstream_branch=None):
 
1313
    def _export_previous_upstream_tree(self, package, previous_version, tempdir):
1382
1314
        assert isinstance(previous_version, str), \
1383
1315
            "Should pass upstream version as str, not Version."
1384
 
        if self.pristine_tar_source.has_version(package, previous_version):
1385
 
            upstream_tip = self.pristine_tar_source.version_as_revision(
 
1316
        try:
 
1317
            upstream_tip = self.pristine_upstream_source.version_as_revision(
1386
1318
                    package, previous_version)
1387
 
            self.extract_upstream_tree(upstream_tip, tempdir)
1388
 
        elif self.upstream_source is not None:
1389
 
            upstream_tip = self.upstream_source.version_as_revision(package, previous_version)
1390
 
            self.extract_upstream_tree(upstream_tip, tempdir)
1391
 
        else:
 
1319
        except PackageVersionNotPresent:
1392
1320
            raise BzrCommandError("Unable to find the tag for the "
1393
1321
                    "previous upstream version, %s, in the branch: "
1394
1322
                    "%s" % (
1395
1323
                previous_version,
1396
 
                self.pristine_tar_source.tag_name(previous_version)))
 
1324
                self.pristine_upstream_source.tag_name(previous_version)))
 
1325
        self.extract_upstream_tree(upstream_tip, tempdir)
1397
1326
 
1398
 
    def merge_upstream(self, tarball_filename, package, version, previous_version,
 
1327
    def merge_upstream(self, tarball_filenames, package, version, previous_version,
1399
1328
            upstream_branch=None, upstream_revision=None, merge_type=None,
1400
1329
            force=False):
1401
 
        assert self.upstream_branch is None, \
1402
 
                "Should use self.upstream_branch if set"
1403
1330
        assert isinstance(version, str), \
1404
1331
            "Should pass version as str not %s" % str(type(version))
1405
1332
        assert isinstance(previous_version, str) or previous_version is None, \
1408
1335
        tempdir = tempfile.mkdtemp(dir=os.path.join(self.tree.basedir, '..'))
1409
1336
        try:
1410
1337
            if previous_version is not None:
1411
 
                self._export_previous_upstream_tree(package, previous_version, tempdir,
1412
 
                    upstream_branch)
 
1338
                self._export_previous_upstream_tree(package, previous_version, tempdir)
1413
1339
            else:
1414
1340
                self._create_empty_upstream_tree(tempdir)
1415
 
            if self.pristine_tar_source.has_version(package, version):
 
1341
            if self.pristine_upstream_source.has_version(package, version):
1416
1342
                raise UpstreamAlreadyImported(version)
1417
1343
            if upstream_branch is not None:
1418
1344
                upstream_branch.lock_read()
1425
1351
                    if not force and graph.is_ancestor(upstream_revision,
1426
1352
                            self.branch.last_revision()):
1427
1353
                        raise UpstreamBranchAlreadyMerged
1428
 
                tarball_filename = os.path.abspath(tarball_filename)
1429
 
                md5sum = md5sum_filename(tarball_filename)
1430
 
                tarball_dir = self._extract_tarball_to_tempdir(tarball_filename)
 
1354
                upstream_tarballs = [
 
1355
                    (os.path.abspath(fn), component, md5sum_filename(fn)) for
 
1356
                    (fn, component) in
 
1357
                    tarball_filenames]
 
1358
                tarball_dir = self._extract_tarballs_to_tempdir(upstream_tarballs)
1431
1359
                try:
1432
1360
                    # FIXME: should use upstream_parents()?
1433
1361
                    parents = []
1434
 
                    if self.upstream_branch.last_revision() != NULL_REVISION:
1435
 
                        parents = [self.upstream_branch.last_revision()]
1436
 
                    _, new_revid = self.import_upstream(tarball_dir,
1437
 
                            version,
1438
 
                            md5sum, parents, upstream_tarball=tarball_filename,
 
1362
                    if self.pristine_upstream_branch.last_revision() != NULL_REVISION:
 
1363
                        parents = [self.pristine_upstream_branch.last_revision()]
 
1364
                    for (component, tag, revid) in self.import_upstream(tarball_dir,
 
1365
                            package, version, parents, upstream_tarballs=upstream_tarballs,
1439
1366
                            upstream_branch=upstream_branch,
1440
 
                            upstream_revision=upstream_revision)
1441
 
                    self._fetch_upstream_to_branch(new_revid)
 
1367
                            upstream_revision=upstream_revision):
 
1368
                        self._fetch_upstream_to_branch(revid)
1442
1369
                finally:
1443
1370
                    shutil.rmtree(tarball_dir)
1444
1371
                if self.branch.last_revision() != NULL_REVISION:
1445
1372
                    try:
1446
1373
                        conflicts = self.tree.merge_from_branch(
1447
 
                                self.upstream_branch, merge_type=merge_type)
 
1374
                                self.pristine_upstream_branch, merge_type=merge_type)
1448
1375
                    except UnrelatedBranches:
1449
1376
                        # Bug lp:515367 where the first upstream tarball is
1450
1377
                        # missing a proper history link and a criss-cross merge
1455
1382
                        else:
1456
1383
                            from_revision = parents[0]
1457
1384
                        conflicts = self.tree.merge_from_branch(
1458
 
                                self.upstream_branch, merge_type=merge_type,
 
1385
                                self.pristine_upstream_branch, merge_type=merge_type,
1459
1386
                                from_revision=from_revision)
1460
1387
                else:
1461
1388
                    # Pull so that merge-upstream allows you to start a branch
1462
1389
                    # from upstream tarball.
1463
1390
                    conflicts = 0
1464
 
                    self.tree.pull(self.upstream_branch)
1465
 
                self.upstream_branch.tags.merge_to(self.branch.tags)
 
1391
                    self.tree.pull(self.pristine_upstream_branch)
 
1392
                self.pristine_upstream_branch.tags.merge_to(self.branch.tags)
1466
1393
                return conflicts
1467
1394
            finally:
1468
1395
                if upstream_branch is not None:
1470
1397
        finally:
1471
1398
            shutil.rmtree(tempdir)
1472
1399
 
1473
 
    def make_pristine_tar_delta(self, tree, tarball_path):
1474
 
        tmpdir = tempfile.mkdtemp(prefix="builddeb-pristine-")
1475
 
        try:
1476
 
            dest = os.path.join(tmpdir, "orig")
1477
 
            tree.lock_read()
1478
 
            try:
1479
 
                for (dp, ie) in tree.inventory.iter_entries():
1480
 
                    ie._read_tree_state(dp, tree)
1481
 
                export(tree, dest, format='dir')
1482
 
            finally:
1483
 
                tree.unlock()
1484
 
            return make_pristine_tar_delta(dest, tarball_path)
1485
 
        finally:
1486
 
            shutil.rmtree(tmpdir)
1487
 
 
1488
1400
 
1489
1401
class SourceExtractor(object):
1490
1402
    """A class to extract a source package to its constituent parts"""
1494
1406
        self.dsc = dsc
1495
1407
        self.extracted_upstream = None
1496
1408
        self.extracted_debianised = None
1497
 
        self.unextracted_upstream = None
1498
1409
        self.unextracted_debian_md5 = None
1499
 
        self.unextracted_upstream_md5 = None
 
1410
        self.upstream_tarballs = []
 
1411
        self.tempdir = None
 
1412
 
 
1413
    def extract(self):
 
1414
        """Extract the package to a new temporary directory."""
 
1415
        raise NotImplementedError(self.extract)
 
1416
 
 
1417
    def cleanup(self):
 
1418
        """Cleanup any extracted files."""
 
1419
        if self.tempdir is not None and os.path.isdir(self.tempdir):
 
1420
            shutil.rmtree(self.tempdir)
 
1421
 
 
1422
 
 
1423
class OneZeroSourceExtractor(SourceExtractor):
 
1424
    """Source extract for the "1.0" source format."""
1500
1425
 
1501
1426
    def extract(self):
1502
1427
        """Extract the package to a new temporary directory."""
1523
1448
                    self.unextracted_debian_md5 = part['md5sum']
1524
1449
            else:
1525
1450
                if part['name'].endswith(".orig.tar.gz"):
1526
 
                    assert self.unextracted_upstream is None, "Two .orig.tar.gz?"
1527
 
                    self.unextracted_upstream = os.path.abspath(
 
1451
                    self.upstream_tarballs.append((os.path.abspath(
1528
1452
                            os.path.join(osutils.dirname(self.dsc_path),
1529
 
                                part['name']))
1530
 
                    self.unextracted_upstream_md5 = part['md5sum']
 
1453
                                part['name'])),
 
1454
                            component_from_orig_tarball(part['name'], name, str(version.upstream_version)),
 
1455
                            part['md5sum']))
1531
1456
                elif part['name'].endswith(".diff.gz"):
1532
1457
                    self.unextracted_debian_md5 = part['md5sum']
1533
1458
 
1534
 
    def cleanup(self):
1535
 
        if os.path.exists(self.tempdir):
1536
 
            shutil.rmtree(self.tempdir)
1537
 
 
1538
1459
 
1539
1460
class ThreeDotZeroNativeSourceExtractor(SourceExtractor):
 
1461
    """Source extractor for the "3.0 (native)" source format."""
1540
1462
 
1541
1463
    def extract(self):
1542
1464
        self.tempdir = tempfile.mkdtemp()
1554
1476
        self.extracted_upstream = None
1555
1477
        for part in self.dsc['files']:
1556
1478
            if (part['name'].endswith(".tar.gz")
1557
 
                    or part['name'].endswith(".tar.bz2")):
 
1479
                    or part['name'].endswith(".tar.bz2")
 
1480
                    or part['name'].endswith(".tar.lzma")):
1558
1481
                self.unextracted_debian_md5 = part['md5sum']
1559
1482
 
1560
1483
 
1561
1484
class ThreeDotZeroQuiltSourceExtractor(SourceExtractor):
 
1485
    """Source extractor for the "3.0 (quilt)" source format."""
1562
1486
 
1563
1487
    def extract(self):
1564
1488
        self.tempdir = tempfile.mkdtemp()
1588
1512
        subprocess.call(["find", self.extracted_debianised, "-perm",
1589
1513
                "0000", "-exec", "chmod", "644", "{}", ";"])
1590
1514
        for part in self.dsc['files']:
1591
 
            if (re.search("\.orig-[^.]+\.tar\.(gz|bz2|lzma)$", part['name'])):
1592
 
                raise AssertionError("Can't import packages with multiple "
1593
 
                    "upstream tarballs yet")
1594
 
            if (part['name'].endswith(".orig.tar.gz")
1595
 
                    or part['name'].endswith(".orig.tar.bz2")):
1596
 
                assert self.unextracted_upstream is None, "Two .orig.tar.(gz|bz2)?"
1597
 
                self.unextracted_upstream = os.path.abspath(
 
1515
            if part['name'].startswith("%s_%s.orig" % (name, str(version.upstream_version))):
 
1516
                self.upstream_tarballs.append((os.path.abspath(
1598
1517
                        os.path.join(osutils.dirname(self.dsc_path),
1599
 
                            part['name']))
1600
 
                self.unextracted_upstream_md5 = part['md5sum']
 
1518
                            part['name'])), part['md5sum']))
1601
1519
            elif (part['name'].endswith(".debian.tar.gz")
1602
 
                    or part['name'].endswith(".debian.tar.bz2")):
 
1520
                    or part['name'].endswith(".debian.tar.bz2")
 
1521
                    or part['name'].endswith(".debian.tar.lzma")):
1603
1522
                self.unextracted_debian_md5 = part['md5sum']
1604
 
        assert self.unextracted_upstream is not None, \
1605
 
            "Can't handle non gz|bz2 tarballs yet"
 
1523
        assert self.upstream_tarballs is not None, \
 
1524
            "Can't handle non gz|bz2|lzma tarballs yet"
1606
1525
        assert self.unextracted_debian_md5 is not None, \
1607
 
            "Can't handle non gz|bz2 tarballs yet"
 
1526
            "Can't handle non gz|bz2|lzma tarballs yet"
1608
1527
 
1609
1528
 
1610
1529
SOURCE_EXTRACTORS = {}
1611
 
SOURCE_EXTRACTORS["1.0"] = SourceExtractor
 
1530
SOURCE_EXTRACTORS[FORMAT_1_0] = OneZeroSourceExtractor
1612
1531
SOURCE_EXTRACTORS[FORMAT_3_0_NATIVE] = ThreeDotZeroNativeSourceExtractor
1613
1532
SOURCE_EXTRACTORS[FORMAT_3_0_QUILT] = ThreeDotZeroQuiltSourceExtractor