~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/knit.py

Merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
89
89
     sha_strings
90
90
from bzrlib.symbol_versioning import DEPRECATED_PARAMETER, deprecated_passed
91
91
from bzrlib.tsort import topo_sort
 
92
import bzrlib.ui
92
93
import bzrlib.weave
93
94
from bzrlib.versionedfile import VersionedFile, InterVersionedFile
94
95
 
118
119
 
119
120
    def annotate_iter(self):
120
121
        """Yield tuples of (origin, text) for each content line."""
121
 
        for origin, text in self._lines:
122
 
            yield origin, text
 
122
        return iter(self._lines)
123
123
 
124
124
    def annotate(self):
125
125
        """Return a list of (origin, text) tuples."""
127
127
 
128
128
    def line_delta_iter(self, new_lines):
129
129
        """Generate line-based delta from this content to new_lines."""
130
 
        new_texts = [text for origin, text in new_lines._lines]
131
 
        old_texts = [text for origin, text in self._lines]
 
130
        new_texts = new_lines.text()
 
131
        old_texts = self.text()
132
132
        s = KnitSequenceMatcher(None, old_texts, new_texts)
133
 
        for op in s.get_opcodes():
134
 
            if op[0] == 'equal':
 
133
        for tag, i1, i2, j1, j2 in s.get_opcodes():
 
134
            if tag == 'equal':
135
135
                continue
136
 
            #     ofrom   oto   length        data
137
 
            yield (op[1], op[2], op[4]-op[3], new_lines._lines[op[3]:op[4]])
 
136
            # ofrom, oto, length, data
 
137
            yield i1, i2, j2 - j1, new_lines._lines[j1:j2]
138
138
 
139
139
    def line_delta(self, new_lines):
140
140
        return list(self.line_delta_iter(new_lines))
308
308
        self.writable = (access_mode == 'w')
309
309
        self.delta = delta
310
310
 
 
311
        self._max_delta_chain = 200
 
312
 
311
313
        self._index = _KnitIndex(transport, relpath + INDEX_SUFFIX,
312
314
            access_mode, create=create, file_mode=file_mode,
313
315
            create_parent_dir=create_parent_dir, delay_create=delay_create,
321
323
        return '%s(%s)' % (self.__class__.__name__, 
322
324
                           self.transport.abspath(self.filename))
323
325
    
 
326
    def _check_should_delta(self, first_parents):
 
327
        """Iterate back through the parent listing, looking for a fulltext.
 
328
 
 
329
        This is used when we want to decide whether to add a delta or a new
 
330
        fulltext. It searches for _max_delta_chain parents. When it finds a
 
331
        fulltext parent, it sees if the total size of the deltas leading up to
 
332
        it is large enough to indicate that we want a new full text anyway.
 
333
 
 
334
        Return True if we should create a new delta, False if we should use a
 
335
        full text.
 
336
        """
 
337
        delta_size = 0
 
338
        fulltext_size = None
 
339
        delta_parents = first_parents
 
340
        for count in xrange(self._max_delta_chain):
 
341
            parent = delta_parents[0]
 
342
            method = self._index.get_method(parent)
 
343
            pos, size = self._index.get_position(parent)
 
344
            if method == 'fulltext':
 
345
                fulltext_size = size
 
346
                break
 
347
            delta_size += size
 
348
            delta_parents = self._index.get_parents(parent)
 
349
        else:
 
350
            # We couldn't find a fulltext, so we must create a new one
 
351
            return False
 
352
 
 
353
        return fulltext_size > delta_size
 
354
 
324
355
    def _add_delta(self, version_id, parents, delta_parent, sha1, noeol, delta):
325
356
        """See VersionedFile._add_delta()."""
326
357
        self._check_add(version_id, []) # should we check the lines ?
358
389
            # To speed the extract of texts the delta chain is limited
359
390
            # to a fixed number of deltas.  This should minimize both
360
391
            # I/O and the time spend applying deltas.
361
 
            count = 0
362
 
            delta_parents = [delta_parent]
363
 
            while count < 25:
364
 
                parent = delta_parents[0]
365
 
                method = self._index.get_method(parent)
366
 
                if method == 'fulltext':
367
 
                    break
368
 
                delta_parents = self._index.get_parents(parent)
369
 
                count = count + 1
370
 
            if method == 'line-delta':
371
 
                # did not find a fulltext in the delta limit.
372
 
                # just do a normal insertion.
 
392
            # The window was changed to a maximum of 200 deltas, but also added
 
393
            # was a check that the total compressed size of the deltas is
 
394
            # smaller than the compressed size of the fulltext.
 
395
            if not self._check_should_delta([delta_parent]):
 
396
                # We don't want a delta here, just do a normal insertion.
373
397
                return super(KnitVersionedFile, self)._add_delta(version_id,
374
398
                                                                 parents,
375
399
                                                                 delta_parent,
669
693
            # To speed the extract of texts the delta chain is limited
670
694
            # to a fixed number of deltas.  This should minimize both
671
695
            # I/O and the time spend applying deltas.
672
 
            count = 0
673
 
            delta_parents = present_parents
674
 
            while count < 25:
675
 
                parent = delta_parents[0]
676
 
                method = self._index.get_method(parent)
677
 
                if method == 'fulltext':
678
 
                    break
679
 
                delta_parents = self._index.get_parents(parent)
680
 
                count = count + 1
681
 
            if method == 'line-delta':
682
 
                delta = False
 
696
            delta = self._check_should_delta(present_parents)
683
697
 
684
698
        lines = self.factory.make(lines, version_id)
685
699
        if delta or (self.factory.annotated and len(present_parents) > 0):
826
840
                data_pos, length = self._index.get_position(version_id)
827
841
                version_id_records.append((version_id, data_pos, length))
828
842
 
829
 
        count = 0
830
843
        total = len(version_id_records)
831
 
        pb.update('Walking content.', count, total)
832
 
        for version_id, data, sha_value in \
833
 
            self._data.read_records_iter(version_id_records):
834
 
            pb.update('Walking content.', count, total)
 
844
        for version_idx, (version_id, data, sha_value) in \
 
845
            enumerate(self._data.read_records_iter(version_id_records)):
 
846
            pb.update('Walking content.', version_idx, total)
835
847
            method = self._index.get_method(version_id)
836
848
            version_idx = self._index.lookup(version_id)
837
849
            assert method in ('fulltext', 'line-delta')
844
856
                for start, end, count, lines in delta:
845
857
                    for origin, line in lines:
846
858
                        yield line
847
 
            count +=1
848
859
        pb.update('Walking content.', total, total)
849
860
        
850
861
    def num_versions(self):