~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/_annotator_pyx.pyx

  • Committer: John Arbash Meinel
  • Date: 2009-07-08 15:41:18 UTC
  • mto: This revision was merged to the branch mainline in revision 4522.
  • Revision ID: john@arbash-meinel.com-20090708154118-q0k3jyyhhnmoezr7
Move the core loops into module-level helpers.

Not sure if it really matters, but it does make it a bit simpler, and it
means the code matches _update_from_first_parent.

Show diffs side-by-side

added added

removed removed

Lines of Context:
56
56
 
57
57
 
58
58
from bzrlib import _annotator_py
59
 
from bzrlib import errors, graph as _mod_graph, osutils, patiencediff, ui
60
59
 
61
60
 
62
61
cdef int _check_annotations_are_lists(annotations,
155
154
    return new_ann
156
155
 
157
156
 
158
 
cdef _apply_parent_annotations(annotations, parent_annotations,
159
 
                               matching_blocks):
 
157
cdef int _apply_parent_annotations(annotations, parent_annotations,
 
158
                                   matching_blocks) except -1:
160
159
    """Apply the annotations from parent_annotations into annotations.
161
160
 
162
161
    matching_blocks defines the ranges that match.
181
180
            Py_INCREF_ptr(par_temp[idx])
182
181
            Py_DECREF_ptr(ann_temp[idx])
183
182
            ann_temp[idx] = par_temp[idx]
 
183
    return 0
 
184
 
 
185
 
 
186
cdef int _merge_annotations(this_annotation, annotations, parent_annotations,
 
187
                            matching_blocks, ann_cache) except -1:
 
188
    cdef Py_ssize_t parent_idx, ann_idx, lines_idx, match_len, idx
 
189
    cdef Py_ssize_t pos
 
190
    cdef PyObject *ann_temp, *par_temp
 
191
 
 
192
    _check_annotations_are_lists(annotations, parent_annotations)
 
193
    last_ann = None
 
194
    last_parent = None
 
195
    last_res = None
 
196
    for parent_idx, lines_idx, match_len in matching_blocks:
 
197
        _check_match_ranges(parent_annotations, annotations,
 
198
                            parent_idx, lines_idx, match_len)
 
199
        # For lines which match this parent, we will now resolve whether
 
200
        # this parent wins over the current annotation
 
201
        for idx from 0 <= idx < match_len:
 
202
            ann_idx = lines_idx + idx
 
203
            ann_temp = PyList_GET_ITEM(annotations, ann_idx)
 
204
            par_temp = PyList_GET_ITEM(parent_annotations, parent_idx + idx)
 
205
            if (ann_temp == par_temp):
 
206
                # This is parent, do nothing
 
207
                # Pointer comparison is fine here. Value comparison would
 
208
                # be ok, but it will be handled in the final if clause by
 
209
                # merging the two tuples into the same tuple
 
210
                # Avoiding the Py_INCREF and function call to
 
211
                # PyObject_RichCompareBool using pointer comparison drops
 
212
                # timing from 215ms => 125ms
 
213
                continue
 
214
            par_ann = <object>par_temp
 
215
            ann = <object>ann_temp
 
216
            if (ann is this_annotation):
 
217
                # Originally claimed 'this', but it was really in this
 
218
                # parent
 
219
                Py_INCREF(par_ann)
 
220
                PyList_SetItem(annotations, ann_idx, par_ann)
 
221
                continue
 
222
            # Resolve the fact that both sides have a different value for
 
223
            # last modified
 
224
            if (ann is last_ann and par_ann is last_parent):
 
225
                Py_INCREF(last_res)
 
226
                PyList_SetItem(annotations, ann_idx, last_res)
 
227
            else:
 
228
                new_ann = _combine_annotations(ann, par_ann, ann_cache)
 
229
                Py_INCREF(new_ann)
 
230
                PyList_SetItem(annotations, ann_idx, new_ann)
 
231
                last_ann = ann
 
232
                last_parent = par_ann
 
233
                last_res = new_ann
184
234
 
185
235
 
186
236
class Annotator(_annotator_py.Annotator):
188
238
 
189
239
    def _update_from_first_parent(self, key, annotations, lines, parent_key):
190
240
        """Reannotate this text relative to its first parent."""
191
 
        parent_annotations, matching_blocks = self._get_parent_annotations_and_matches(
192
 
            key, lines, parent_key)
 
241
        (parent_annotations,
 
242
         matching_blocks) = self._get_parent_annotations_and_matches(
 
243
                                key, lines, parent_key)
193
244
 
194
245
        _apply_parent_annotations(annotations, parent_annotations,
195
246
                                  matching_blocks)
197
248
    def _update_from_other_parents(self, key, annotations, lines,
198
249
                                   this_annotation, parent_key):
199
250
        """Reannotate this text relative to a second (or more) parent."""
200
 
        cdef Py_ssize_t parent_idx, ann_idx, lines_idx, match_len, idx
201
 
        cdef Py_ssize_t pos
202
 
        cdef PyObject *ann_temp, *par_temp
203
 
        parent_annotations, matching_blocks = self._get_parent_annotations_and_matches(
204
 
            key, lines, parent_key)
205
 
        _check_annotations_are_lists(annotations, parent_annotations)
206
 
        last_ann = None
207
 
        last_parent = None
208
 
        last_res = None
209
 
        cache = self._ann_tuple_cache
210
 
        for parent_idx, lines_idx, match_len in matching_blocks:
211
 
            _check_match_ranges(parent_annotations, annotations,
212
 
                                parent_idx, lines_idx, match_len)
213
 
            # For lines which match this parent, we will now resolve whether
214
 
            # this parent wins over the current annotation
215
 
            for idx from 0 <= idx < match_len:
216
 
                ann_idx = lines_idx + idx
217
 
                ann_temp = PyList_GET_ITEM(annotations, ann_idx)
218
 
                par_temp = PyList_GET_ITEM(parent_annotations, parent_idx + idx)
219
 
                if (ann_temp == par_temp):
220
 
                    # This is parent, do nothing
221
 
                    # Pointer comparison is fine here. Value comparison would
222
 
                    # be ok, but it will be handled in the final if clause by
223
 
                    # merging the two tuples into the same tuple
224
 
                    # Avoiding the Py_INCREF by using pointer comparison drops
225
 
                    # timing from 215ms => 125ms
226
 
                    continue
227
 
                par_ann = <object>par_temp
228
 
                ann = <object>ann_temp
229
 
                if (ann is this_annotation):
230
 
                    # Originally claimed 'this', but it was really in this
231
 
                    # parent
232
 
                    Py_INCREF(par_ann)
233
 
                    PyList_SetItem(annotations, ann_idx, par_ann)
234
 
                    continue
235
 
                # Resolve the fact that both sides have a different value for
236
 
                # last modified
237
 
                if (ann is last_ann and par_ann is last_parent):
238
 
                    Py_INCREF(last_res)
239
 
                    PyList_SetItem(annotations, ann_idx, last_res)
240
 
                else:
241
 
                    new_ann = _combine_annotations(ann, par_ann, cache)
242
 
                    Py_INCREF(new_ann)
243
 
                    PyList_SetItem(annotations, ann_idx, new_ann)
244
 
                    last_ann = ann
245
 
                    last_parent = par_ann
246
 
                    last_res = new_ann
 
251
        (parent_annotations,
 
252
         matching_blocks) = self._get_parent_annotations_and_matches(
 
253
                                key, lines, parent_key)
 
254
        _merge_annotations(this_annotation, annotations, parent_annotations,
 
255
                           matching_blocks, self._ann_tuple_cache)
247
256
 
248
257
    def annotate_flat(self, key):
249
258
        """Determine the single-best-revision to source for each line.