2
# Copyright (C) 2008, 2009 Canonical Ltd.
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
"""Cache the whole history data needed by loggerhead about a branch."""
23
from bzrlib.revision import is_null, NULL_REVISION
24
from bzrlib.tsort import merge_sort
26
from loggerhead.util import StaticTuple
29
def _strip_NULL_ghosts(revision_graph):
31
Copied over from bzrlib meant as a temporary workaround for
34
# Filter ghosts, and null:
35
if NULL_REVISION in revision_graph:
36
del revision_graph[NULL_REVISION]
37
as_st = StaticTuple.from_sequence
38
for key, parents in revision_graph.iteritems():
39
revision_graph[key] = as_st([
40
parent for parent in parents if parent in revision_graph])
44
def compute_whole_history_data(branch):
45
"""Compute _rev_info and _rev_indices for a branch.
47
See History.__doc__ for what these data structures mean.
51
last_revid = branch.last_revision()
53
log = logging.getLogger('loggerhead.%s' %
54
(branch.get_config().get_nickname(),))
56
graph = branch.repository.get_graph()
57
# Note: iter_ancestry returns StaticTuples in 2.1.0, but I don't know if
58
# it's only on CHK repos, and we have to be compatible with older bzrlibs
60
as_st = StaticTuple.from_sequence
61
parent_map = dict((key, as_st(value).intern()) for key, value in
62
graph.iter_ancestry([last_revid]) if value is not None)
64
_revision_graph = _strip_NULL_ghosts(parent_map)
69
if is_null(last_revid):
72
_merge_sort = merge_sort(
73
_revision_graph, last_revid, generate_revno=True)
75
for info in _merge_sort:
76
seq, revid, merge_depth, revno, end_of_merge = info
77
revno_str = '.'.join([str(n) for n in revno])
78
parents = _revision_graph[revid]
79
_rev_indices[revid] = len(_rev_info)
80
# TODO: Do something about interning the outer tuple. The problem is,
81
# it may/will be modified by the loop below, so it's a waste to intern
82
# it before that happens.
83
# TODO: I'm 99% sure "parents" is the same StaticTuple that was
84
# interned above, but I'd like to verify it.
85
_rev_info.append(StaticTuple(
87
seq, revid, merge_depth, revno_str, end_of_merge).intern(),
88
StaticTuple(), parents.intern()))
90
for revid in _revision_graph.iterkeys():
91
revid_index = _rev_indices[revid]
92
if _rev_info[revid_index][0][2] == 0:
94
for parent in _revision_graph[revid]:
95
# TODO: Rebuilding 'c' is a bit ugly.
96
parent_index = _rev_indices[parent]
97
c = _rev_info[parent_index]
99
_rev_info[parent_index] = StaticTuple(
100
# TODO: Interning c[1] and StaticTuple(revid) is not ideal,
101
# since the loop might modify them again, but hopefully
102
# it's a net benefit.
103
c[0], (c[1] + StaticTuple(revid).intern()).intern(), c[2])
105
log.info('built revision graph cache: %r secs' % (time.time() - z,))
107
return (_rev_info, _rev_indices)