~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

Merge from bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
        errors,
26
26
        lockdir,
27
27
        lockable_files,
 
28
        repository,
28
29
        revision as _mod_revision,
29
30
        transport,
30
31
        tsort,
192
193
        :return: A dictionary mapping revision_id => dotted revno.
193
194
        """
194
195
        last_revision = self.last_revision()
195
 
        revision_graph = self.repository.get_revision_graph(last_revision)
 
196
        revision_graph = repository._old_get_graph(self.repository,
 
197
            last_revision)
196
198
        merge_sorted_revisions = tsort.merge_sort(
197
199
            revision_graph,
198
200
            last_revision,
1023
1025
        # local is the local branch or None, master is the target branch,
1024
1026
        # and an empty branch recieves new_revno of 0, new_revid of None.
1025
1027
        self['post_uncommit'] = []
 
1028
        # Introduced in 1.4
 
1029
        # Invoked after the tip of a branch changes.
 
1030
        # the api signature is
 
1031
        # (params) where params is a ChangeBranchTipParams with the members
 
1032
        # (branch, old_revno, new_revno, old_revid, new_revid)
 
1033
        self['post_change_branch_tip'] = []
1026
1034
 
1027
1035
 
1028
1036
# install the default hooks into the Branch class.
1029
1037
Branch.hooks = BranchHooks()
1030
1038
 
1031
1039
 
 
1040
class ChangeBranchTipParams(object):
 
1041
    """Object holding parameters passed to *_change_branch_tip hooks.
 
1042
 
 
1043
    There are 5 fields that hooks may wish to access:
 
1044
 
 
1045
    :ivar branch: the branch being changed
 
1046
    :ivar old_revno: revision number before the change
 
1047
    :ivar new_revno: revision number after the change
 
1048
    :ivar old_revid: revision id before the change
 
1049
    :ivar new_revid: revision id after the change
 
1050
 
 
1051
    The revid fields are strings. The revno fields are integers.
 
1052
    """
 
1053
 
 
1054
    def __init__(self, branch, old_revno, new_revno, old_revid, new_revid):
 
1055
        """Create a group of ChangeBranchTip parameters.
 
1056
 
 
1057
        :param branch: The branch being changed.
 
1058
        :param old_revno: Revision number before the change.
 
1059
        :param new_revno: Revision number after the change.
 
1060
        :param old_revid: Tip revision id before the change.
 
1061
        :param new_revid: Tip revision id after the change.
 
1062
        """
 
1063
        self.branch = branch
 
1064
        self.old_revno = old_revno
 
1065
        self.new_revno = new_revno
 
1066
        self.old_revid = old_revid
 
1067
        self.new_revid = new_revid
 
1068
 
 
1069
 
1032
1070
class BzrBranchFormat4(BranchFormat):
1033
1071
    """Bzr branch format 4.
1034
1072
 
1375
1413
        """See Branch.set_revision_history."""
1376
1414
        if 'evil' in debug.debug_flags:
1377
1415
            mutter_callsite(3, "set_revision_history scales with history.")
1378
 
        self._clear_cached_state()
1379
1416
        self._write_revision_history(rev_history)
 
1417
        self._clear_cached_state()
1380
1418
        self._cache_revision_history(rev_history)
1381
1419
        for hook in Branch.hooks['set_rh']:
1382
1420
            hook(self, rev_history)
1383
1421
 
 
1422
    def _run_post_change_branch_tip_hooks(self, old_revno, old_revid):
 
1423
        """Run the post_change_branch_tip hooks."""
 
1424
        hooks = Branch.hooks['post_change_branch_tip']
 
1425
        if not hooks:
 
1426
            return
 
1427
        new_revno, new_revid = self.last_revision_info()
 
1428
        params = ChangeBranchTipParams(
 
1429
            self, old_revno, new_revno, old_revid, new_revid)
 
1430
        for hook in hooks:
 
1431
            hook(params)
 
1432
 
1384
1433
    @needs_write_lock
1385
1434
    def set_last_revision_info(self, revno, revision_id):
1386
1435
        """Set the last revision of this branch.
1394
1443
        be permitted.
1395
1444
        """
1396
1445
        revision_id = _mod_revision.ensure_null(revision_id)
 
1446
        old_revno, old_revid = self.last_revision_info()
1397
1447
        history = self._lefthand_history(revision_id)
1398
1448
        assert len(history) == revno, '%d != %d' % (len(history), revno)
1399
1449
        self.set_revision_history(history)
 
1450
        self._run_post_change_branch_tip_hooks(old_revno, old_revid)
1400
1451
 
1401
1452
    def _gen_revision_history(self):
1402
1453
        history = self.control_files.get('revision-history').read().split('\n')
1809
1860
 
1810
1861
class BzrBranch6(BzrBranch5):
1811
1862
 
 
1863
    def __init__(self, *args, **kwargs):
 
1864
        super(BzrBranch6, self).__init__(*args, **kwargs)
 
1865
        self._last_revision_info_cache = None
 
1866
        self._partial_revision_history_cache = []
 
1867
 
 
1868
    def _clear_cached_state(self):
 
1869
        super(BzrBranch6, self)._clear_cached_state()
 
1870
        self._last_revision_info_cache = None
 
1871
        self._partial_revision_history_cache = []
 
1872
 
1812
1873
    @needs_read_lock
1813
1874
    def last_revision_info(self):
 
1875
        """Return information about the last revision.
 
1876
 
 
1877
        :return: A tuple (revno, revision_id).
 
1878
        """
 
1879
        if self._last_revision_info_cache is None:
 
1880
            self._last_revision_info_cache = self._last_revision_info()
 
1881
        return self._last_revision_info_cache
 
1882
 
 
1883
    def _last_revision_info(self):
1814
1884
        revision_string = self.control_files.get('last-revision').read()
1815
1885
        revno, revision_id = revision_string.rstrip('\n').split(' ', 1)
1816
1886
        revision_id = cache_utf8.get_cached_utf8(revision_id)
1833
1903
    @needs_write_lock
1834
1904
    def set_last_revision_info(self, revno, revision_id):
1835
1905
        revision_id = _mod_revision.ensure_null(revision_id)
 
1906
        old_revno, old_revid = self.last_revision_info()
1836
1907
        if self._get_append_revisions_only():
1837
1908
            self._check_history_violation(revision_id)
1838
1909
        self._write_last_revision_info(revno, revision_id)
1839
1910
        self._clear_cached_state()
 
1911
        self._last_revision_info_cache = revno, revision_id
 
1912
        self._run_post_change_branch_tip_hooks(old_revno, old_revid)
1840
1913
 
1841
1914
    def _check_history_violation(self, revision_id):
1842
1915
        last_revision = _mod_revision.ensure_null(self.last_revision())
1848
1921
    def _gen_revision_history(self):
1849
1922
        """Generate the revision history from last revision
1850
1923
        """
1851
 
        history = list(self.repository.iter_reverse_revision_history(
1852
 
            self.last_revision()))
1853
 
        history.reverse()
1854
 
        return history
 
1924
        self._extend_partial_history()
 
1925
        return list(reversed(self._partial_revision_history_cache))
 
1926
 
 
1927
    def _extend_partial_history(self, stop_index=None, stop_revision=None):
 
1928
        """Extend the partial history to include a given index
 
1929
 
 
1930
        If a stop_index is supplied, stop when that index has been reached.
 
1931
        If a stop_revision is supplied, stop when that revision is
 
1932
        encountered.  Otherwise, stop when the beginning of history is
 
1933
        reached.
 
1934
 
 
1935
        :param stop_index: The index which should be present.  When it is
 
1936
            present, history extension will stop.
 
1937
        :param revision_id: The revision id which should be present.  When
 
1938
            it is encountered, history extension will stop.
 
1939
        """
 
1940
        repo = self.repository
 
1941
        if len(self._partial_revision_history_cache) == 0:
 
1942
            iterator = repo.iter_reverse_revision_history(self.last_revision())
 
1943
        else:
 
1944
            start_revision = self._partial_revision_history_cache[-1]
 
1945
            iterator = repo.iter_reverse_revision_history(start_revision)
 
1946
            #skip the last revision in the list
 
1947
            next_revision = iterator.next()
 
1948
            assert next_revision == start_revision
 
1949
        for revision_id in iterator:
 
1950
            self._partial_revision_history_cache.append(revision_id)
 
1951
            if (stop_index is not None and
 
1952
                len(self._partial_revision_history_cache) > stop_index):
 
1953
                break
 
1954
            if revision_id == stop_revision:
 
1955
                break
1855
1956
 
1856
1957
    def _write_revision_history(self, history):
1857
1958
        """Factored out of set_revision_history.
1969
2070
        revno = len(history)
1970
2071
        self.set_last_revision_info(revno, revision_id)
1971
2072
 
 
2073
    @needs_read_lock
 
2074
    def get_rev_id(self, revno, history=None):
 
2075
        """Find the revision id of the specified revno."""
 
2076
        if revno == 0:
 
2077
            return _mod_revision.NULL_REVISION
 
2078
 
 
2079
        last_revno, last_revision_id = self.last_revision_info()
 
2080
        if revno <= 0 or revno > last_revno:
 
2081
            raise errors.NoSuchRevision(self, revno)
 
2082
 
 
2083
        if history is not None:
 
2084
            assert len(history) == last_revno, 'revno/history mismatch'
 
2085
            return history[revno - 1]
 
2086
 
 
2087
        index = last_revno - revno
 
2088
        if len(self._partial_revision_history_cache) <= index:
 
2089
            self._extend_partial_history(stop_index=index)
 
2090
        if len(self._partial_revision_history_cache) > index:
 
2091
            return self._partial_revision_history_cache[index]
 
2092
        else:
 
2093
            raise errors.NoSuchRevision(self, revno)
 
2094
 
 
2095
    @needs_read_lock
 
2096
    def revision_id_to_revno(self, revision_id):
 
2097
        """Given a revision id, return its revno"""
 
2098
        if _mod_revision.is_null(revision_id):
 
2099
            return 0
 
2100
        try:
 
2101
            index = self._partial_revision_history_cache.index(revision_id)
 
2102
        except ValueError:
 
2103
            self._extend_partial_history(stop_revision=revision_id)
 
2104
            index = len(self._partial_revision_history_cache) - 1
 
2105
            if self._partial_revision_history_cache[index] != revision_id:
 
2106
                raise errors.NoSuchRevision(self, revision_id)
 
2107
        return self.revno() - index
 
2108
 
1972
2109
 
1973
2110
######################################################################
1974
2111
# results of operations
2063
2200
        new_branch = format.open(branch.bzrdir, _found=True)
2064
2201
 
2065
2202
        # Copy source data into target
2066
 
        new_branch.set_last_revision_info(*branch.last_revision_info())
 
2203
        new_branch._write_last_revision_info(*branch.last_revision_info())
2067
2204
        new_branch.set_parent(branch.get_parent())
2068
2205
        new_branch.set_bound_location(branch.get_bound_location())
2069
2206
        new_branch.set_push_location(branch.get_push_location())