/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/pack.py

  • Committer: Richard Wilbur
  • Date: 2016-02-04 19:07:28 UTC
  • mto: This revision was merged to the branch mainline in revision 6618.
  • Revision ID: richard.wilbur@gmail.com-20160204190728-p0zvfii6zase0fw7
Update COPYING.txt from the original http://www.gnu.org/licenses/gpl-2.0.txt  (Only differences were in whitespace.)  Thanks to Petr Stodulka for pointing out the discrepancy.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
doc/developers/container-format.txt.
21
21
"""
22
22
 
23
 
from io import BytesIO
 
23
from __future__ import absolute_import
 
24
 
 
25
from cStringIO import StringIO
24
26
import re
25
27
 
26
 
from .. import errors
27
 
 
28
 
 
29
 
FORMAT_ONE = b"Bazaar pack format 1 (introduced in 0.18)"
30
 
 
31
 
 
32
 
_whitespace_re = re.compile(b'[\t\n\x0b\x0c\r ]')
 
28
from bzrlib import errors
 
29
 
 
30
 
 
31
FORMAT_ONE = "Bazaar pack format 1 (introduced in 0.18)"
 
32
 
 
33
 
 
34
_whitespace_re = re.compile('[\t\n\x0b\x0c\r ]')
33
35
 
34
36
 
35
37
def _check_name(name):
55
57
    """
56
58
    try:
57
59
        name.decode('utf-8')
58
 
    except UnicodeDecodeError as e:
 
60
    except UnicodeDecodeError, e:
59
61
        raise errors.InvalidRecordError(str(e))
60
62
 
61
63
 
69
71
 
70
72
    def begin(self):
71
73
        """Return the bytes to begin a container."""
72
 
        return FORMAT_ONE + b"\n"
 
74
        return FORMAT_ONE + "\n"
73
75
 
74
76
    def end(self):
75
77
        """Return the bytes to finish a container."""
76
 
        return b"E"
 
78
        return "E"
77
79
 
78
80
    def bytes_header(self, length, names):
79
81
        """Return the header for a Bytes record."""
80
82
        # Kind marker
81
 
        byte_sections = [b"B"]
 
83
        byte_sections = ["B"]
82
84
        # Length
83
 
        byte_sections.append(b"%d\n" % (length,))
 
85
        byte_sections.append(str(length) + "\n")
84
86
        # Names
85
87
        for name_tuple in names:
86
88
            # Make sure we're writing valid names.  Note that we will leave a
87
89
            # half-written record if a name is bad!
88
90
            for name in name_tuple:
89
91
                _check_name(name)
90
 
            byte_sections.append(b'\x00'.join(name_tuple) + b"\n")
 
92
            byte_sections.append('\x00'.join(name_tuple) + "\n")
91
93
        # End of headers
92
 
        byte_sections.append(b"\n")
93
 
        return b''.join(byte_sections)
 
94
        byte_sections.append("\n")
 
95
        return ''.join(byte_sections)
94
96
 
95
97
    def bytes_record(self, bytes, names):
96
98
        """Return the bytes for a Bytes record with the given name and
137
139
        """Finish writing a container."""
138
140
        self.write_func(self._serialiser.end())
139
141
 
140
 
    def add_bytes_record(self, chunks, length, names):
 
142
    def add_bytes_record(self, bytes, names):
141
143
        """Add a Bytes record with the given names.
142
144
 
143
 
        :param bytes: The chunks to insert.
144
 
        :param length: Total length of bytes in chunks
 
145
        :param bytes: The bytes to insert.
145
146
        :param names: The names to give the inserted bytes. Each name is
146
147
            a tuple of bytestrings. The bytestrings may not contain
147
148
            whitespace.
153
154
            and thus are only suitable for use by a ContainerReader.
154
155
        """
155
156
        current_offset = self.current_offset
 
157
        length = len(bytes)
156
158
        if length < self._JOIN_WRITES_THRESHOLD:
157
159
            self.write_func(self._serialiser.bytes_header(length, names)
158
 
                            + b''.join(chunks))
 
160
                + bytes)
159
161
        else:
160
162
            self.write_func(self._serialiser.bytes_header(length, names))
161
 
            for chunk in chunks:
162
 
                self.write_func(chunk)
 
163
            self.write_func(bytes)
163
164
        self.records_written += 1
164
165
        # return a memo of where we wrote data to allow random access.
165
166
        return current_offset, self.current_offset - current_offset
167
168
 
168
169
class ReadVFile(object):
169
170
    """Adapt a readv result iterator to a file like protocol.
170
 
 
 
171
    
171
172
    The readv result must support the iterator protocol returning (offset,
172
173
    data_bytes) pairs.
173
174
    """
190
191
 
191
192
    def _next(self):
192
193
        if (self._string is None or
193
 
                self._string.tell() == self._string_length):
194
 
            offset, data = next(self.readv_result)
 
194
            self._string.tell() == self._string_length):
 
195
            offset, data = self.readv_result.next()
195
196
            self._string_length = len(data)
196
 
            self._string = BytesIO(data)
 
197
            self._string = StringIO(data)
197
198
 
198
199
    def read(self, length):
199
200
        self._next()
200
201
        result = self._string.read(length)
201
202
        if len(result) < length:
202
203
            raise errors.BzrError('wanted %d bytes but next '
203
 
                                  'hunk only contains %d: %r...' %
204
 
                                  (length, len(result), result[:20]))
 
204
                'hunk only contains %d: %r...' %
 
205
                (length, len(result), result[:20]))
205
206
        return result
206
207
 
207
208
    def readline(self):
208
209
        """Note that readline will not cross readv segments."""
209
210
        self._next()
210
211
        result = self._string.readline()
211
 
        if self._string.tell() == self._string_length and result[-1:] != b'\n':
 
212
        if self._string.tell() == self._string_length and result[-1] != '\n':
212
213
            raise errors.BzrError('short readline in the readvfile hunk: %r'
213
 
                                  % (result, ))
 
214
                % (result, ))
214
215
        return result
215
216
 
216
217
 
222
223
    :param requested_records: The record offset, length tuples as returned
223
224
        by add_bytes_record for the desired records.
224
225
    """
225
 
    readv_blocks = [(0, len(FORMAT_ONE) + 1)]
 
226
    readv_blocks = [(0, len(FORMAT_ONE)+1)]
226
227
    readv_blocks.extend(requested_records)
227
228
    result = ContainerReader(ReadVFile(
228
229
        transport.readv(filename, readv_blocks)))
244
245
 
245
246
    def _read_line(self):
246
247
        line = self._source.readline()
247
 
        if not line.endswith(b'\n'):
 
248
        if not line.endswith('\n'):
248
249
            raise errors.UnexpectedEndOfContainerError()
249
 
        return line.rstrip(b'\n')
 
250
        return line.rstrip('\n')
250
251
 
251
252
 
252
253
class ContainerReader(BaseReader):
299
300
 
300
301
    def _iter_record_objects(self):
301
302
        while True:
302
 
            try:
303
 
                record_kind = self.reader_func(1)
304
 
            except StopIteration:
305
 
                return
306
 
            if record_kind == b'B':
 
303
            record_kind = self.reader_func(1)
 
304
            if record_kind == 'B':
307
305
                # Bytes record.
308
306
                reader = BytesRecordReader(self._source)
309
307
                yield reader
310
 
            elif record_kind == b'E':
 
308
            elif record_kind == 'E':
311
309
                # End marker.  There are no more records.
312
310
                return
313
 
            elif record_kind == b'':
 
311
            elif record_kind == '':
314
312
                # End of stream encountered, but no End Marker record seen, so
315
313
                # this container is incomplete.
316
314
                raise errors.UnexpectedEndOfContainerError()
346
344
                    raise errors.DuplicateRecordNameError(name_tuple[0])
347
345
                all_names.add(name_tuple)
348
346
        excess_bytes = self.reader_func(1)
349
 
        if excess_bytes != b'':
 
347
        if excess_bytes != '':
350
348
            raise errors.ContainerHasExcessDataError(excess_bytes)
351
349
 
352
350
 
375
373
        names = []
376
374
        while True:
377
375
            name_line = self._read_line()
378
 
            if name_line == b'':
 
376
            if name_line == '':
379
377
                break
380
 
            name_tuple = tuple(name_line.split(b'\x00'))
 
378
            name_tuple = tuple(name_line.split('\x00'))
381
379
            for name in name_tuple:
382
380
                _check_name(name)
383
381
            names.append(name_tuple)
418
416
    """
419
417
 
420
418
    def __init__(self):
421
 
        self._buffer = b''
 
419
        self._buffer = ''
422
420
        self._state_handler = self._state_expecting_format_line
423
421
        self._parsed_records = []
424
422
        self._reset_current_record()
458
456
        If a newline byte is not found in the buffer, the buffer is
459
457
        unchanged and this returns None instead.
460
458
        """
461
 
        newline_pos = self._buffer.find(b'\n')
 
459
        newline_pos = self._buffer.find('\n')
462
460
        if newline_pos != -1:
463
461
            line = self._buffer[:newline_pos]
464
 
            self._buffer = self._buffer[newline_pos + 1:]
 
462
            self._buffer = self._buffer[newline_pos+1:]
465
463
            return line
466
464
        else:
467
465
            return None
475
473
 
476
474
    def _state_expecting_record_type(self):
477
475
        if len(self._buffer) >= 1:
478
 
            record_type = self._buffer[:1]
 
476
            record_type = self._buffer[0]
479
477
            self._buffer = self._buffer[1:]
480
 
            if record_type == b'B':
 
478
            if record_type == 'B':
481
479
                self._state_handler = self._state_expecting_length
482
 
            elif record_type == b'E':
 
480
            elif record_type == 'E':
483
481
                self.finished = True
484
482
                self._state_handler = self._state_expecting_nothing
485
483
            else:
497
495
 
498
496
    def _state_expecting_name(self):
499
497
        encoded_name_parts = self._consume_line()
500
 
        if encoded_name_parts == b'':
 
498
        if encoded_name_parts == '':
501
499
            self._state_handler = self._state_expecting_body
502
500
        elif encoded_name_parts:
503
 
            name_parts = tuple(encoded_name_parts.split(b'\x00'))
 
501
            name_parts = tuple(encoded_name_parts.split('\x00'))
504
502
            for name_part in name_parts:
505
503
                _check_name(name_part)
506
504
            self._current_record_names.append(name_parts)
536
534
            yield record
537
535
        if parser.finished:
538
536
            break
 
537