/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

  • Committer: Jelmer Vernooij
  • Date: 2010-04-29 08:59:13 UTC
  • mfrom: (5193 +trunk)
  • mto: This revision was merged to the branch mainline in revision 5218.
  • Revision ID: jelmer@samba.org-20100429085913-7208x0s3of34kehh
merge bzr.dev.

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)
1547
1558
        """Return the short format description for this format."""
1548
1559
        raise NotImplementedError(self.get_format_description)
1549
1560
 
 
1561
    def _run_post_branch_init_hooks(self, a_bzrdir, name, branch):
 
1562
        hooks = Branch.hooks['post_branch_init']
 
1563
        if not hooks:
 
1564
            return
 
1565
        params = BranchInitHookParams(self, a_bzrdir, name, branch)
 
1566
        for hook in hooks:
 
1567
            hook(params)
 
1568
 
1550
1569
    def _initialize_helper(self, a_bzrdir, utf8_files, name=None,
1551
1570
                           lock_type='metadir', set_format=True):
1552
1571
        """Initialize a branch in a bzrdir, with specified files
1560
1579
            elsewhere)
1561
1580
        :return: a branch in this format
1562
1581
        """
1563
 
        mutter('creating branch %r in %s', self, a_bzrdir.transport.base)
 
1582
        mutter('creating branch %r in %s', self, a_bzrdir.user_url)
1564
1583
        branch_transport = a_bzrdir.get_branch_transport(self, name=name)
1565
1584
        lock_map = {
1566
1585
            'metadir': ('lock', lockdir.LockDir),
1588
1607
        finally:
1589
1608
            if lock_taken:
1590
1609
                control_files.unlock()
1591
 
        return self.open(a_bzrdir, name, _found=True)
 
1610
        branch = self.open(a_bzrdir, name, _found=True)
 
1611
        self._run_post_branch_init_hooks(a_bzrdir, name, branch)
 
1612
        return branch
1592
1613
 
1593
1614
    def initialize(self, a_bzrdir, name=None):
1594
1615
        """Create a branch of this format in a_bzrdir.
1754
1775
            "should return a tag name or None if no tag name could be "
1755
1776
            "determined. The first non-None tag name returned will be used.",
1756
1777
            (2, 2), None))
 
1778
        self.create_hook(HookPoint('post_branch_init',
 
1779
            "Called after new branch initialization completes. "
 
1780
            "post_branch_init is called with a "
 
1781
            "bzrlib.branch.BranchInitHookParams. "
 
1782
            "Note that init, branch and checkout (both heavyweight and "
 
1783
            "lightweight) will all trigger this hook.", (2, 2), None))
 
1784
        self.create_hook(HookPoint('post_switch',
 
1785
            "Called after a checkout switches branch. "
 
1786
            "post_switch is called with a "
 
1787
            "bzrlib.branch.SwitchHookParams.", (2, 2), None))
1757
1788
 
1758
1789
 
1759
1790
 
1799
1830
            self.old_revno, self.old_revid, self.new_revno, self.new_revid)
1800
1831
 
1801
1832
 
 
1833
class BranchInitHookParams(object):
 
1834
    """Object holding parameters passed to *_branch_init hooks.
 
1835
 
 
1836
    There are 4 fields that hooks may wish to access:
 
1837
 
 
1838
    :ivar format: the branch format
 
1839
    :ivar bzrdir: the BzrDir where the branch will be/has been initialized
 
1840
    :ivar name: name of colocated branch, if any (or None)
 
1841
    :ivar branch: the branch created
 
1842
 
 
1843
    Note that for lightweight checkouts, the bzrdir and format fields refer to
 
1844
    the checkout, hence they are different from the corresponding fields in
 
1845
    branch, which refer to the original branch.
 
1846
    """
 
1847
 
 
1848
    def __init__(self, format, a_bzrdir, name, branch):
 
1849
        """Create a group of BranchInitHook parameters.
 
1850
 
 
1851
        :param format: the branch format
 
1852
        :param a_bzrdir: the BzrDir where the branch will be/has been
 
1853
            initialized
 
1854
        :param name: name of colocated branch, if any (or None)
 
1855
        :param branch: the branch created
 
1856
 
 
1857
        Note that for lightweight checkouts, the bzrdir and format fields refer
 
1858
        to the checkout, hence they are different from the corresponding fields
 
1859
        in branch, which refer to the original branch.
 
1860
        """
 
1861
        self.format = format
 
1862
        self.bzrdir = a_bzrdir
 
1863
        self.name = name
 
1864
        self.branch = branch
 
1865
 
 
1866
    def __eq__(self, other):
 
1867
        return self.__dict__ == other.__dict__
 
1868
 
 
1869
    def __repr__(self):
 
1870
        if self.branch:
 
1871
            return "<%s of %s>" % (self.__class__.__name__, self.branch)
 
1872
        else:
 
1873
            return "<%s of format:%s bzrdir:%s>" % (
 
1874
                self.__class__.__name__, self.branch,
 
1875
                self.format, self.bzrdir)
 
1876
 
 
1877
 
 
1878
class SwitchHookParams(object):
 
1879
    """Object holding parameters passed to *_switch hooks.
 
1880
 
 
1881
    There are 4 fields that hooks may wish to access:
 
1882
 
 
1883
    :ivar control_dir: BzrDir of the checkout to change
 
1884
    :ivar to_branch: branch that the checkout is to reference
 
1885
    :ivar force: skip the check for local commits in a heavy checkout
 
1886
    :ivar revision_id: revision ID to switch to (or None)
 
1887
    """
 
1888
 
 
1889
    def __init__(self, control_dir, to_branch, force, revision_id):
 
1890
        """Create a group of SwitchHook parameters.
 
1891
 
 
1892
        :param control_dir: BzrDir of the checkout to change
 
1893
        :param to_branch: branch that the checkout is to reference
 
1894
        :param force: skip the check for local commits in a heavy checkout
 
1895
        :param revision_id: revision ID to switch to (or None)
 
1896
        """
 
1897
        self.control_dir = control_dir
 
1898
        self.to_branch = to_branch
 
1899
        self.force = force
 
1900
        self.revision_id = revision_id
 
1901
 
 
1902
    def __eq__(self, other):
 
1903
        return self.__dict__ == other.__dict__
 
1904
 
 
1905
    def __repr__(self):
 
1906
        return "<%s for %s to (%s, %s)>" % (self.__class__.__name__,
 
1907
            self.control_dir, self.to_branch,
 
1908
            self.revision_id)
 
1909
 
 
1910
 
1802
1911
class BzrBranchFormat4(BranchFormat):
1803
1912
    """Bzr branch format 4.
1804
1913
 
1863
1972
            if format.__class__ != self.__class__:
1864
1973
                raise AssertionError("wrong format %r found for %r" %
1865
1974
                    (format, self))
 
1975
        transport = a_bzrdir.get_branch_transport(None, name=name)
1866
1976
        try:
1867
 
            transport = a_bzrdir.get_branch_transport(None, name=name)
1868
1977
            control_files = lockable_files.LockableFiles(transport, 'lock',
1869
1978
                                                         lockdir.LockDir)
1870
1979
            return self._branch_class()(_format=self,
2068
2177
            # this format does not implement branch itself, thus the implicit
2069
2178
            # creation contract must see it as uninitializable
2070
2179
            raise errors.UninitializableFormat(self)
2071
 
        mutter('creating branch reference in %s', a_bzrdir.transport.base)
 
2180
        mutter('creating branch reference in %s', a_bzrdir.user_url)
2072
2181
        branch_transport = a_bzrdir.get_branch_transport(self, name=name)
2073
2182
        branch_transport.put_bytes('location',
2074
 
            target_branch.bzrdir.root_transport.base)
 
2183
            target_branch.bzrdir.user_url)
2075
2184
        branch_transport.put_bytes('format', self.get_format_string())
2076
 
        return self.open(
 
2185
        branch = self.open(
2077
2186
            a_bzrdir, name, _found=True,
2078
2187
            possible_transports=[target_branch.bzrdir.root_transport])
 
2188
        self._run_post_branch_init_hooks(a_bzrdir, name, branch)
 
2189
        return branch
2079
2190
 
2080
2191
    def __init__(self):
2081
2192
        super(BranchReferenceFormat, self).__init__()
2197
2308
 
2198
2309
    def __str__(self):
2199
2310
        if self.name is None:
2200
 
            return '%s(%r)' % (self.__class__.__name__, self.base)
 
2311
            return '%s(%s)' % (self.__class__.__name__, self.user_url)
2201
2312
        else:
2202
 
            return '%s(%r,%r)' % (self.__class__.__name__, self.base, self.name)
 
2313
            return '%s(%s,%s)' % (self.__class__.__name__, self.user_url,
 
2314
                self.name)
2203
2315
 
2204
2316
    __repr__ = __str__
2205
2317
 
2420
2532
        return result
2421
2533
 
2422
2534
    def get_stacked_on_url(self):
2423
 
        raise errors.UnstackableBranchFormat(self._format, self.base)
 
2535
        raise errors.UnstackableBranchFormat(self._format, self.user_url)
2424
2536
 
2425
2537
    def set_push_location(self, location):
2426
2538
        """See Branch.set_push_location."""
2616
2728
        if _mod_revision.is_null(last_revision):
2617
2729
            return
2618
2730
        if last_revision not in self._lefthand_history(revision_id):
2619
 
            raise errors.AppendRevisionsOnlyViolation(self.base)
 
2731
            raise errors.AppendRevisionsOnlyViolation(self.user_url)
2620
2732
 
2621
2733
    def _gen_revision_history(self):
2622
2734
        """Generate the revision history from last revision
2722
2834
        if branch_location is None:
2723
2835
            return Branch.reference_parent(self, file_id, path,
2724
2836
                                           possible_transports)
2725
 
        branch_location = urlutils.join(self.base, branch_location)
 
2837
        branch_location = urlutils.join(self.user_url, branch_location)
2726
2838
        return Branch.open(branch_location,
2727
2839
                           possible_transports=possible_transports)
2728
2840
 
2774
2886
        return stacked_url
2775
2887
 
2776
2888
    def _get_append_revisions_only(self):
2777
 
        value = self.get_config().get_user_option('append_revisions_only')
2778
 
        return value == 'True'
 
2889
        return self.get_config(
 
2890
            ).get_user_option_as_bool('append_revisions_only')
2779
2891
 
2780
2892
    @needs_write_lock
2781
2893
    def generate_revision_history(self, revision_id, last_rev=None,
2843
2955
    """
2844
2956
 
2845
2957
    def get_stacked_on_url(self):
2846
 
        raise errors.UnstackableBranchFormat(self._format, self.base)
 
2958
        raise errors.UnstackableBranchFormat(self._format, self.user_url)
2847
2959
 
2848
2960
 
2849
2961
######################################################################
2936
3048
        :param verbose: Requests more detailed display of what was checked,
2937
3049
            if any.
2938
3050
        """
2939
 
        note('checked branch %s format %s', self.branch.base,
 
3051
        note('checked branch %s format %s', self.branch.user_url,
2940
3052
            self.branch._format)
2941
3053
        for error in self.errors:
2942
3054
            note('found error:%s', error)
3271
3383
        if local and not bound_location:
3272
3384
            raise errors.LocalRequiresBoundBranch()
3273
3385
        master_branch = None
3274
 
        if not local and bound_location and self.source.base != bound_location:
 
3386
        if not local and bound_location and self.source.user_url != bound_location:
3275
3387
            # not pulling from master, so we need to update master.
3276
3388
            master_branch = self.target.get_master_branch(possible_transports)
3277
3389
            master_branch.lock_write()