~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

(spiv) Fetch tagged revisions (not just tags) during branch,
 merge and pull. (Andrew Bennetts)

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
        controldir,
29
29
        debug,
30
30
        errors,
 
31
        fetch,
 
32
        graph as _mod_graph,
31
33
        lockdir,
32
34
        lockable_files,
33
35
        remote,
660
662
        raise errors.UnsupportedOperation(self.get_reference_info, self)
661
663
 
662
664
    @needs_write_lock
663
 
    def fetch(self, from_branch, last_revision=None, pb=None):
 
665
    def fetch(self, from_branch, last_revision=None, pb=None, fetch_spec=None):
664
666
        """Copy revisions from from_branch into this branch.
665
667
 
666
668
        :param from_branch: Where to copy from.
667
669
        :param last_revision: What revision to stop at (None for at the end
668
670
                              of the branch.
669
671
        :param pb: An optional progress bar to use.
 
672
        :param fetch_spec: If specified, a SearchResult or
 
673
            PendingAncestryResult that describes which revisions to copy.  This
 
674
            allows copying multiple heads at once.  Mutually exclusive with
 
675
            last_revision.
670
676
        :return: None
671
677
        """
 
678
        if fetch_spec is not None and last_revision is not None:
 
679
            raise AssertionError(
 
680
                "fetch_spec and last_revision are mutually exclusive.")
672
681
        if self.base == from_branch.base:
673
682
            return (0, [])
674
683
        if pb is not None:
677
686
                % "pb parameter to fetch()")
678
687
        from_branch.lock_read()
679
688
        try:
680
 
            if last_revision is None:
 
689
            if last_revision is None and fetch_spec is None:
681
690
                last_revision = from_branch.last_revision()
682
691
                last_revision = _mod_revision.ensure_null(last_revision)
683
692
            return self.repository.fetch(from_branch.repository,
684
693
                                         revision_id=last_revision,
685
 
                                         pb=pb)
 
694
                                         pb=pb, fetch_spec=fetch_spec)
686
695
        finally:
687
696
            from_branch.unlock()
688
697
 
1020
1029
        return other_history[self_len:stop_revision]
1021
1030
 
1022
1031
    def update_revisions(self, other, stop_revision=None, overwrite=False,
1023
 
                         graph=None):
 
1032
                         graph=None, fetch_tags=True):
1024
1033
        """Pull in new perfect-fit revisions.
1025
1034
 
1026
1035
        :param other: Another Branch to pull from
1029
1038
            to see if it is a proper descendant.
1030
1039
        :param graph: A Graph object that can be used to query history
1031
1040
            information. This can be None.
 
1041
        :param fetch_tags: Flag that specifies if tags from other should be
 
1042
            fetched too.
1032
1043
        :return: None
1033
1044
        """
1034
1045
        return InterBranch.get(other, self).update_revisions(stop_revision,
1035
 
            overwrite, graph)
 
1046
            overwrite, graph, fetch_tags=fetch_tags)
1036
1047
 
 
1048
    @deprecated_method(deprecated_in((2, 4, 0)))
1037
1049
    def import_last_revision_info(self, source_repo, revno, revid):
1038
1050
        """Set the last revision info, importing from another repo if necessary.
1039
1051
 
1040
 
        This is used by the bound branch code to upload a revision to
1041
 
        the master branch first before updating the tip of the local branch.
1042
 
 
1043
1052
        :param source_repo: Source repository to optionally fetch from
1044
1053
        :param revno: Revision number of the new tip
1045
1054
        :param revid: Revision id of the new tip
1048
1057
            self.repository.fetch(source_repo, revision_id=revid)
1049
1058
        self.set_last_revision_info(revno, revid)
1050
1059
 
 
1060
    def import_last_revision_info_and_tags(self, source, revno, revid):
 
1061
        """Set the last revision info, importing from another repo if necessary.
 
1062
 
 
1063
        This is used by the bound branch code to upload a revision to
 
1064
        the master branch first before updating the tip of the local branch.
 
1065
        Revisions referenced by source's tags are also transferred.
 
1066
 
 
1067
        :param source: Source branch to optionally fetch from
 
1068
        :param revno: Revision number of the new tip
 
1069
        :param revid: Revision id of the new tip
 
1070
        """
 
1071
        if not self.repository.has_same_location(source.repository):
 
1072
            try:
 
1073
                tags_to_fetch = set(source.tags.get_reverse_tag_dict())
 
1074
            except errors.TagsNotSupported:
 
1075
                tags_to_fetch = set()
 
1076
            fetch_spec = _mod_graph.NotInOtherForRevs(self.repository,
 
1077
                source.repository, [revid],
 
1078
                if_present_ids=tags_to_fetch).execute()
 
1079
            self.repository.fetch(source.repository, fetch_spec=fetch_spec)
 
1080
        self.set_last_revision_info(revno, revid)
 
1081
 
1051
1082
    def revision_id_to_revno(self, revision_id):
1052
1083
        """Given a revision id, return its revno"""
1053
1084
        if _mod_revision.is_null(revision_id):
3353
3384
 
3354
3385
    @needs_write_lock
3355
3386
    def update_revisions(self, stop_revision=None, overwrite=False,
3356
 
                         graph=None):
 
3387
                         graph=None, fetch_tags=True):
3357
3388
        """Pull in new perfect-fit revisions.
3358
3389
 
3359
3390
        :param stop_revision: Updated until the given revision
3361
3392
            to see if it is a proper descendant.
3362
3393
        :param graph: A Graph object that can be used to query history
3363
3394
            information. This can be None.
 
3395
        :param fetch_tags: Flag that specifies if tags from source should be
 
3396
            fetched too.
3364
3397
        :return: None
3365
3398
        """
3366
3399
        raise NotImplementedError(self.update_revisions)
3424
3457
 
3425
3458
    @needs_write_lock
3426
3459
    def update_revisions(self, stop_revision=None, overwrite=False,
3427
 
        graph=None):
 
3460
        graph=None, fetch_tags=True):
3428
3461
        """See InterBranch.update_revisions()."""
3429
3462
        other_revno, other_last_revision = self.source.last_revision_info()
3430
3463
        stop_revno = None # unknown
3442
3475
        # case of having something to pull, and so that the check for
3443
3476
        # already merged can operate on the just fetched graph, which will
3444
3477
        # be cached in memory.
3445
 
        self.target.fetch(self.source, stop_revision)
 
3478
        if fetch_tags:
 
3479
            fetch_spec_factory = fetch.FetchSpecFactory()
 
3480
            fetch_spec_factory.source_branch = self.source
 
3481
            fetch_spec_factory.source_branch_stop_revision_id = stop_revision
 
3482
            fetch_spec_factory.source_repo = self.source.repository
 
3483
            fetch_spec_factory.target_repo = self.target.repository
 
3484
            fetch_spec_factory.target_repo_kind = fetch.TargetRepoKinds.PREEXISTING
 
3485
            fetch_spec = fetch_spec_factory.make_fetch_spec()
 
3486
        else:
 
3487
            fetch_spec = _mod_graph.NotInOtherForRevs(self.target.repository,
 
3488
                self.source.repository, revision_ids=[stop_revision]).execute()
 
3489
        self.target.fetch(self.source, fetch_spec=fetch_spec)
3446
3490
        # Check to see if one is an ancestor of the other
3447
3491
        if not overwrite:
3448
3492
            if graph is None: