42
43
self._annotations_cache = {}
43
44
self._heads_provider = None
46
def _update_needed_children(self, key, parent_keys):
47
for parent_key in parent_keys:
48
if parent_key in self._num_needed_children:
49
self._num_needed_children[parent_key] += 1
51
self._num_needed_children[parent_key] = 1
45
53
def _get_needed_keys(self, key):
46
graph = _mod_graph.Graph(self._vf)
54
"""Determine the texts we need to get from the backing vf.
56
:return: (vf_keys_needed, ann_keys_needed)
57
vf_keys_needed These are keys that we need to get from the vf
58
ann_keys_needed Texts which we have in self._text_cache but we
59
don't have annotations for. We need to yield these
60
in the proper order so that we can get proper
63
parent_map = self._parent_map
48
64
# We need 1 extra copy of the node we will be looking at when we are
50
66
self._num_needed_children[key] = 1
51
for key, parent_keys in graph.iter_ancestry([key]):
52
if parent_keys is None:
54
parent_map[key] = parent_keys
55
for parent_key in parent_keys:
56
if parent_key in self._num_needed_children:
57
self._num_needed_children[parent_key] += 1
67
vf_keys_needed = set()
68
ann_keys_needed = set()
69
needed_keys = set([key])
73
for key in needed_keys:
74
if key in self._parent_map:
75
# We don't need to lookup this key in the vf
76
if key not in self._text_cache:
77
# Extract this text from the vf
78
vf_keys_needed.add(key)
79
elif key not in self._annotations_cache:
80
# We do need to annotate
81
ann_keys_needed.add(key)
82
next_parent_map[key] = self._parent_map[key]
59
self._num_needed_children[parent_key] = 1
60
self._parent_map.update(parent_map)
61
# _heads_provider does some graph caching, so it is only valid while
62
# self._parent_map hasn't changed
63
self._heads_provider = None
64
keys = parent_map.keys()
84
parent_lookup.append(key)
85
vf_keys_needed.add(key)
87
next_parent_map.update(self._vf.get_parent_map(parent_lookup))
88
for key, parent_keys in next_parent_map.iteritems():
89
self._update_needed_children(key, parent_keys)
90
needed_keys.update([key for key in parent_keys
91
if key not in parent_map])
92
parent_map.update(next_parent_map)
93
# _heads_provider does some graph caching, so it is only valid while
94
# self._parent_map hasn't changed
95
self._heads_provider = None
96
# self._parent_map.update(parent_map)
97
return vf_keys_needed, ann_keys_needed
67
99
def _get_needed_texts(self, key, pb=None):
68
100
"""Get the texts we need to properly annotate key.
73
105
matcher object we are using. Currently it is always 'lines' but
74
106
future improvements may change this to a simple text string.
76
keys = self._get_needed_keys(key)
108
keys, ann_keys = self._get_needed_keys(key)
77
109
if pb is not None:
78
110
pb.update('getting stream', 0, len(keys))
79
111
stream = self._vf.get_record_stream(keys, 'topological', True)
80
112
for idx, record in enumerate(stream):
81
113
if pb is not None:
82
114
pb.update('extracting', 0, len(keys))
115
if record.storage_kind == 'absent':
116
raise errors.RevisionNotPresent(record.key, self._vf)
83
117
this_key = record.key
84
118
lines = osutils.chunks_to_lines(record.get_bytes_as('chunked'))
85
119
num_lines = len(lines)
86
120
self._text_cache[this_key] = lines
87
121
yield this_key, lines, num_lines
123
lines = self._text_cache[key]
124
num_lines = len(lines)
125
yield key, lines, num_lines
89
127
def _get_parent_annotations_and_matches(self, key, text, parent_key):
90
128
"""Get the list of annotations for the parent, and the matching lines.
186
224
this_annotation, parent)
187
225
self._record_annotation(key, parent_keys, annotations)
227
def add_special_text(self, key, parent_keys, text):
228
"""Add a specific text to the graph."""
229
self._special_keys.add(key)
230
self._parent_map[key] = parent_keys
231
self._text_cache[key] = osutils.split_lines(text)
232
self._heads_provider = None
189
234
def annotate(self, key):
190
235
"""Return annotated fulltext for the given key."""
191
236
pb = ui.ui_factory.nested_progress_bar()