~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/knit.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-06-05 06:34:59 UTC
  • mfrom: (3468.2.7 234748-integrated)
  • Revision ID: pqm@pqm.ubuntu.com-20080605063459-2lk0v0sayzfqsbqw
(mbp) #234748 fix problems in final newline on Knit add_lines and
        get_lines

Show diffs side-by-side

added added

removed removed

Lines of Context:
60
60
# record content length ?
61
61
                  
62
62
 
63
 
from copy import copy
64
63
from cStringIO import StringIO
65
64
from itertools import izip, chain
66
65
import operator
281
280
 
282
281
 
283
282
class KnitContent(object):
284
 
    """Content of a knit version to which deltas can be applied."""
 
283
    """Content of a knit version to which deltas can be applied.
 
284
    
 
285
    This is always stored in memory as a list of lines with \n at the end,
 
286
    plus a flag saying if the final ending is really there or not, because that 
 
287
    corresponds to the on-disk knit representation.
 
288
    """
285
289
 
286
290
    def __init__(self):
287
291
        self._should_strip_eol = False
290
294
        """Apply delta to this object to become new_version_id."""
291
295
        raise NotImplementedError(self.apply_delta)
292
296
 
293
 
    def cleanup_eol(self, copy_on_mutate=True):
294
 
        if self._should_strip_eol:
295
 
            if copy_on_mutate:
296
 
                self._lines = self._lines[:]
297
 
            self.strip_last_line_newline()
298
 
 
299
297
    def line_delta_iter(self, new_lines):
300
298
        """Generate line-based delta from this content to new_lines."""
301
299
        new_texts = new_lines.text()
346
344
 
347
345
    def annotate(self):
348
346
        """Return a list of (origin, text) for each content line."""
349
 
        return list(self._lines)
 
347
        lines = self._lines[:]
 
348
        if self._should_strip_eol:
 
349
            origin, last_line = lines[-1]
 
350
            lines[-1] = (origin, last_line.rstrip('\n'))
 
351
        return lines
350
352
 
351
353
    def apply_delta(self, delta, new_version_id):
352
354
        """Apply delta to this object to become new_version_id."""
356
358
            lines[offset+start:offset+end] = delta_lines
357
359
            offset = offset + (start - end) + count
358
360
 
359
 
    def strip_last_line_newline(self):
360
 
        line = self._lines[-1][1].rstrip('\n')
361
 
        self._lines[-1] = (self._lines[-1][0], line)
362
 
        self._should_strip_eol = False
363
 
 
364
361
    def text(self):
365
362
        try:
366
363
            lines = [text for origin, text in self._lines]
371
368
            raise KnitCorrupt(self,
372
369
                "line in annotated knit missing annotation information: %s"
373
370
                % (e,))
374
 
 
375
371
        if self._should_strip_eol:
376
372
            lines[-1] = lines[-1].rstrip('\n')
377
373
        return lines
409
405
    def copy(self):
410
406
        return PlainKnitContent(self._lines[:], self._version_id)
411
407
 
412
 
    def strip_last_line_newline(self):
413
 
        self._lines[-1] = self._lines[-1].rstrip('\n')
414
 
        self._should_strip_eol = False
415
 
 
416
408
    def text(self):
417
409
        lines = self._lines
418
410
        if self._should_strip_eol:
1193
1185
                for i, j, n in seq.get_matching_blocks():
1194
1186
                    if n == 0:
1195
1187
                        continue
1196
 
                    # this appears to copy (origin, text) pairs across to the
1197
 
                    # new content for any line that matches the last-checked
 
1188
                    # this copies (origin, text) pairs across to the new
 
1189
                    # content for any line that matches the last-checked
1198
1190
                    # parent.
1199
1191
                    content._lines[j:j+n] = merge_content._lines[i:i+n]
1200
1192
        if delta:
1339
1331
            delta = self._check_should_delta(present_parents)
1340
1332
 
1341
1333
        content = self.factory.make(lines, version_id)
 
1334
        if 'no-eol' in options:
 
1335
            # Hint to the content object that its text() call should strip the
 
1336
            # EOL.
 
1337
            content._should_strip_eol = True
1342
1338
        if delta or (self.factory.annotated and len(present_parents) > 0):
1343
1339
            # Merge annotations from parent texts if needed.
1344
1340
            delta_hunks = self._merge_annotations(content, present_parents,
1473
1469
                    if multiple_versions:
1474
1470
                        content_map[component_id] = content
1475
1471
 
1476
 
            content.cleanup_eol(copy_on_mutate=multiple_versions)
1477
1472
            final_content[version_id] = content
1478
1473
 
1479
1474
            # digest here is the digest from the last applied component.
2278
2273
        self._need_to_create = _need_to_create
2279
2274
        self._create_parent_dir = _create_parent_dir
2280
2275
 
 
2276
    def __repr__(self):
 
2277
        return "%s(%r)" % (self.__class__.__name__,
 
2278
            self._transport.abspath(self._filename))
 
2279
 
2281
2280
    def add_raw_records(self, sizes, raw_data):
2282
2281
        """Add raw knit bytes to a storage area.
2283
2282
 
2697
2696
                                     digest)],
2698
2697
            dense_lines or lines,
2699
2698
            ["end %s\n" % version_id]))
 
2699
        if lines and lines[-1][-1] != '\n':
 
2700
            raise ValueError('corrupt lines value %r' % lines)
2700
2701
        compressed_bytes = bytes_to_gzip(bytes)
2701
2702
        return len(compressed_bytes), compressed_bytes
2702
2703