~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

  • Committer: Parth Malwankar
  • Date: 2010-05-05 14:11:13 UTC
  • mfrom: (5211 +trunk)
  • mto: This revision was merged to the branch mainline in revision 5213.
  • Revision ID: parth.malwankar@gmail.com-20100505141113-c21oicoxzb3u6if6
merged in changes from trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
63
63
BZR_BRANCH_FORMAT_6 = "Bazaar Branch Format 6 (bzr 0.15)\n"
64
64
 
65
65
 
66
 
# TODO: Maybe include checks for common corruption of newlines, etc?
67
 
 
68
 
# TODO: Some operations like log might retrieve the same revisions
69
 
# repeatedly to calculate deltas.  We could perhaps have a weakref
70
 
# cache in memory to make this faster.  In general anything can be
71
 
# cached in memory between lock and unlock operations. .. nb thats
72
 
# what the transaction identity map provides
73
 
 
74
 
 
75
 
######################################################################
76
 
# branch objects
77
 
 
78
 
class Branch(object):
 
66
class Branch(bzrdir.ControlComponent):
79
67
    """Branch holding a history of revisions.
80
68
 
81
 
    base
82
 
        Base directory/url of the branch.
 
69
    :ivar base:
 
70
        Base directory/url of the branch; using control_url and
 
71
        control_transport is more standardized.
83
72
 
84
73
    hooks: An instance of BranchHooks.
85
74
    """
87
76
    # - RBC 20060112
88
77
    base = None
89
78
 
 
79
    @property
 
80
    def control_transport(self):
 
81
        return self._transport
 
82
 
 
83
    @property
 
84
    def user_transport(self):
 
85
        return self.bzrdir.user_transport
 
86
 
90
87
    def __init__(self, *ignored, **ignored_too):
91
88
        self.tags = self._format.make_tags(self)
92
89
        self._revision_history_cache = None
107
104
        """Activate the branch/repository from url as a fallback repository."""
108
105
        repo = self._get_fallback_repository(url)
109
106
        if repo.has_same_location(self.repository):
110
 
            raise errors.UnstackableLocationError(self.base, url)
 
107
            raise errors.UnstackableLocationError(self.user_url, url)
111
108
        self.repository.add_fallback_repository(repo)
112
109
 
113
110
    def break_lock(self):
420
417
            * 'include' - the stop revision is the last item in the result
421
418
            * 'with-merges' - include the stop revision and all of its
422
419
              merged revisions in the result
 
420
            * 'with-merges-without-common-ancestry' - filter out revisions 
 
421
              that are in both ancestries
423
422
        :param direction: either 'reverse' or 'forward':
424
423
            * reverse means return the start_revision_id first, i.e.
425
424
              start at the most recent revision and go backwards in history
456
455
            stop_revision_id, stop_rule)
457
456
        # Make sure we don't return revisions that are not part of the
458
457
        # start_revision_id ancestry.
459
 
        filtered = self._filter_non_ancestors(filtered)
 
458
        filtered = self._filter_start_non_ancestors(filtered)
460
459
        if direction == 'reverse':
461
460
            return filtered
462
461
        if direction == 'forward':
499
498
                       node.end_of_merge)
500
499
                if rev_id == stop_revision_id:
501
500
                    return
 
501
        elif stop_rule == 'with-merges-without-common-ancestry':
 
502
            # We want to exclude all revisions that are already part of the
 
503
            # stop_revision_id ancestry.
 
504
            graph = self.repository.get_graph()
 
505
            ancestors = graph.find_unique_ancestors(start_revision_id,
 
506
                                                    [stop_revision_id])
 
507
            for node in rev_iter:
 
508
                rev_id = node.key[-1]
 
509
                if rev_id not in ancestors:
 
510
                    continue
 
511
                yield (rev_id, node.merge_depth, node.revno,
 
512
                       node.end_of_merge)
502
513
        elif stop_rule == 'with-merges':
503
514
            stop_rev = self.repository.get_revision(stop_revision_id)
504
515
            if stop_rev.parent_ids:
527
538
        else:
528
539
            raise ValueError('invalid stop_rule %r' % stop_rule)
529
540
 
530
 
    def _filter_non_ancestors(self, rev_iter):
 
541
    def _filter_start_non_ancestors(self, rev_iter):
531
542
        # If we started from a dotted revno, we want to consider it as a tip
532
543
        # and don't want to yield revisions that are not part of its
533
544
        # ancestry. Given the order guaranteed by the merge sort, we will see
594
605
        :param other: The branch to bind to
595
606
        :type other: Branch
596
607
        """
597
 
        raise errors.UpgradeRequired(self.base)
 
608
        raise errors.UpgradeRequired(self.user_url)
598
609
 
599
610
    def set_append_revisions_only(self, enabled):
600
611
        if not self._format.supports_set_append_revisions_only():
601
 
            raise errors.UpgradeRequired(self.base)
 
612
            raise errors.UpgradeRequired(self.user_url)
602
613
        if enabled:
603
614
            value = 'True'
604
615
        else:
652
663
    def get_old_bound_location(self):
653
664
        """Return the URL of the branch we used to be bound to
654
665
        """
655
 
        raise errors.UpgradeRequired(self.base)
 
666
        raise errors.UpgradeRequired(self.user_url)
656
667
 
657
668
    def get_commit_builder(self, parents, config=None, timestamp=None,
658
669
                           timezone=None, committer=None, revprops=None,
736
747
            stacking.
737
748
        """
738
749
        if not self._format.supports_stacking():
739
 
            raise errors.UnstackableBranchFormat(self._format, self.base)
 
750
            raise errors.UnstackableBranchFormat(self._format, self.user_url)
740
751
        # XXX: Changing from one fallback repository to another does not check
741
752
        # that all the data you need is present in the new fallback.
742
753
        # Possibly it should.
893
904
 
894
905
    def unbind(self):
895
906
        """Older format branches cannot bind or unbind."""
896
 
        raise errors.UpgradeRequired(self.base)
 
907
        raise errors.UpgradeRequired(self.user_url)
897
908
 
898
909
    def last_revision(self):
899
910
        """Return last revision id, or NULL_REVISION."""
1059
1070
        try:
1060
1071
            return urlutils.join(self.base[:-1], parent)
1061
1072
        except errors.InvalidURLJoin, e:
1062
 
            raise errors.InaccessibleParent(parent, self.base)
 
1073
            raise errors.InaccessibleParent(parent, self.user_url)
1063
1074
 
1064
1075
    def _get_parent_location(self):
1065
1076
        raise NotImplementedError(self._get_parent_location)
1564
1575
            elsewhere)
1565
1576
        :return: a branch in this format
1566
1577
        """
1567
 
        mutter('creating branch %r in %s', self, a_bzrdir.transport.base)
 
1578
        mutter('creating branch %r in %s', self, a_bzrdir.user_url)
1568
1579
        branch_transport = a_bzrdir.get_branch_transport(self, name=name)
1569
1580
        lock_map = {
1570
1581
            'metadir': ('lock', lockdir.LockDir),
1957
1968
            if format.__class__ != self.__class__:
1958
1969
                raise AssertionError("wrong format %r found for %r" %
1959
1970
                    (format, self))
 
1971
        transport = a_bzrdir.get_branch_transport(None, name=name)
1960
1972
        try:
1961
 
            transport = a_bzrdir.get_branch_transport(None, name=name)
1962
1973
            control_files = lockable_files.LockableFiles(transport, 'lock',
1963
1974
                                                         lockdir.LockDir)
1964
1975
            return self._branch_class()(_format=self,
2162
2173
            # this format does not implement branch itself, thus the implicit
2163
2174
            # creation contract must see it as uninitializable
2164
2175
            raise errors.UninitializableFormat(self)
2165
 
        mutter('creating branch reference in %s', a_bzrdir.transport.base)
 
2176
        mutter('creating branch reference in %s', a_bzrdir.user_url)
2166
2177
        branch_transport = a_bzrdir.get_branch_transport(self, name=name)
2167
2178
        branch_transport.put_bytes('location',
2168
 
            target_branch.bzrdir.root_transport.base)
 
2179
            target_branch.bzrdir.user_url)
2169
2180
        branch_transport.put_bytes('format', self.get_format_string())
2170
2181
        branch = self.open(
2171
2182
            a_bzrdir, name, _found=True,
2293
2304
 
2294
2305
    def __str__(self):
2295
2306
        if self.name is None:
2296
 
            return '%s(%r)' % (self.__class__.__name__, self.base)
 
2307
            return '%s(%s)' % (self.__class__.__name__, self.user_url)
2297
2308
        else:
2298
 
            return '%s(%r,%r)' % (self.__class__.__name__, self.base, self.name)
 
2309
            return '%s(%s,%s)' % (self.__class__.__name__, self.user_url,
 
2310
                self.name)
2299
2311
 
2300
2312
    __repr__ = __str__
2301
2313
 
2516
2528
        return result
2517
2529
 
2518
2530
    def get_stacked_on_url(self):
2519
 
        raise errors.UnstackableBranchFormat(self._format, self.base)
 
2531
        raise errors.UnstackableBranchFormat(self._format, self.user_url)
2520
2532
 
2521
2533
    def set_push_location(self, location):
2522
2534
        """See Branch.set_push_location."""
2712
2724
        if _mod_revision.is_null(last_revision):
2713
2725
            return
2714
2726
        if last_revision not in self._lefthand_history(revision_id):
2715
 
            raise errors.AppendRevisionsOnlyViolation(self.base)
 
2727
            raise errors.AppendRevisionsOnlyViolation(self.user_url)
2716
2728
 
2717
2729
    def _gen_revision_history(self):
2718
2730
        """Generate the revision history from last revision
2818
2830
        if branch_location is None:
2819
2831
            return Branch.reference_parent(self, file_id, path,
2820
2832
                                           possible_transports)
2821
 
        branch_location = urlutils.join(self.base, branch_location)
 
2833
        branch_location = urlutils.join(self.user_url, branch_location)
2822
2834
        return Branch.open(branch_location,
2823
2835
                           possible_transports=possible_transports)
2824
2836
 
2939
2951
    """
2940
2952
 
2941
2953
    def get_stacked_on_url(self):
2942
 
        raise errors.UnstackableBranchFormat(self._format, self.base)
 
2954
        raise errors.UnstackableBranchFormat(self._format, self.user_url)
2943
2955
 
2944
2956
 
2945
2957
######################################################################
3032
3044
        :param verbose: Requests more detailed display of what was checked,
3033
3045
            if any.
3034
3046
        """
3035
 
        note('checked branch %s format %s', self.branch.base,
 
3047
        note('checked branch %s format %s', self.branch.user_url,
3036
3048
            self.branch._format)
3037
3049
        for error in self.errors:
3038
3050
            note('found error:%s', error)
3367
3379
        if local and not bound_location:
3368
3380
            raise errors.LocalRequiresBoundBranch()
3369
3381
        master_branch = None
3370
 
        if not local and bound_location and self.source.base != bound_location:
 
3382
        if not local and bound_location and self.source.user_url != bound_location:
3371
3383
            # not pulling from master, so we need to update master.
3372
3384
            master_branch = self.target.get_master_branch(possible_transports)
3373
3385
            master_branch.lock_write()