/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 breezy/pack.py

  • Committer: Jelmer Vernooij
  • Author(s): Richard Wilbur
  • Date: 2017-05-30 23:37:11 UTC
  • mto: This revision was merged to the branch mainline in revision 6645.
  • Revision ID: jelmer@jelmer.uk-20170530233711-r0m0qp8hpkqzpopw
Fix order in which files are processed.

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 cStringIO import StringIO
 
23
from __future__ import absolute_import
 
24
 
24
25
import re
25
26
 
26
 
from bzrlib import errors
 
27
from . import errors
 
28
from .sixish import (
 
29
    BytesIO,
 
30
    )
27
31
 
28
32
 
29
33
FORMAT_ONE = "Bazaar pack format 1 (introduced in 0.18)"
55
59
    """
56
60
    try:
57
61
        name.decode('utf-8')
58
 
    except UnicodeDecodeError, e:
 
62
    except UnicodeDecodeError as e:
59
63
        raise errors.InvalidRecordError(str(e))
60
64
 
61
65
 
75
79
        """Return the bytes to finish a container."""
76
80
        return "E"
77
81
 
78
 
    def bytes_record(self, bytes, names):
79
 
        """Return the bytes for a Bytes record with the given name and
80
 
        contents.
81
 
        """
 
82
    def bytes_header(self, length, names):
 
83
        """Return the header for a Bytes record."""
82
84
        # Kind marker
83
85
        byte_sections = ["B"]
84
86
        # Length
85
 
        byte_sections.append(str(len(bytes)) + "\n")
 
87
        byte_sections.append(str(length) + "\n")
86
88
        # Names
87
89
        for name_tuple in names:
88
90
            # Make sure we're writing valid names.  Note that we will leave a
92
94
            byte_sections.append('\x00'.join(name_tuple) + "\n")
93
95
        # End of headers
94
96
        byte_sections.append("\n")
95
 
        # Finally, the contents.
96
 
        byte_sections.append(bytes)
97
 
        # XXX: This causes a memory copy of bytes in size, but is usually
98
 
        # faster than two write calls (12 vs 13 seconds to output a gig of
99
 
        # 1k records.) - results may differ on significantly larger records
100
 
        # like .iso's but as they should be rare in any case and thus not
101
 
        # likely to be the common case. The biggest issue is causing extreme
102
 
        # memory pressure in that case. One possibly improvement here is to
103
 
        # check the size of the content before deciding to join here vs call
104
 
        # write twice.
105
97
        return ''.join(byte_sections)
106
98
 
 
99
    def bytes_record(self, bytes, names):
 
100
        """Return the bytes for a Bytes record with the given name and
 
101
        contents.
 
102
 
 
103
        If the content may be large, construct the header separately and then
 
104
        stream out the contents.
 
105
        """
 
106
        return self.bytes_header(len(bytes), names) + bytes
 
107
 
107
108
 
108
109
class ContainerWriter(object):
109
110
    """A class for writing containers to a file.
113
114
        introduced by the begin() and end() methods.
114
115
    """
115
116
 
 
117
    # Join up headers with the body if writing fewer than this many bytes:
 
118
    # trades off memory usage and copying to do less IO ops.
 
119
    _JOIN_WRITES_THRESHOLD = 100000
 
120
 
116
121
    def __init__(self, write_func):
117
122
        """Constructor.
118
123
 
151
156
            and thus are only suitable for use by a ContainerReader.
152
157
        """
153
158
        current_offset = self.current_offset
154
 
        serialised_record = self._serialiser.bytes_record(bytes, names)
155
 
        self.write_func(serialised_record)
 
159
        length = len(bytes)
 
160
        if length < self._JOIN_WRITES_THRESHOLD:
 
161
            self.write_func(self._serialiser.bytes_header(length, names)
 
162
                + bytes)
 
163
        else:
 
164
            self.write_func(self._serialiser.bytes_header(length, names))
 
165
            self.write_func(bytes)
156
166
        self.records_written += 1
157
167
        # return a memo of where we wrote data to allow random access.
158
168
        return current_offset, self.current_offset - current_offset
184
194
    def _next(self):
185
195
        if (self._string is None or
186
196
            self._string.tell() == self._string_length):
187
 
            offset, data = self.readv_result.next()
 
197
            offset, data = next(self.readv_result)
188
198
            self._string_length = len(data)
189
 
            self._string = StringIO(data)
 
199
            self._string = BytesIO(data)
190
200
 
191
201
    def read(self, length):
192
202
        self._next()
333
343
                # risk that the same unicode string has been encoded two
334
344
                # different ways.
335
345
                if name_tuple in all_names:
336
 
                    raise errors.DuplicateRecordNameError(name_tuple)
 
346
                    raise errors.DuplicateRecordNameError(name_tuple[0])
337
347
                all_names.add(name_tuple)
338
348
        excess_bytes = self.reader_func(1)
339
349
        if excess_bytes != '':