/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: Andrew Bennetts
  • Date: 2008-08-12 14:53:26 UTC
  • mto: This revision was merged to the branch mainline in revision 3624.
  • Revision ID: andrew.bennetts@canonical.com-20080812145326-yx693x2jc4rcovb7
Move the notes on writing tests out of HACKING into a new file, and improve
them.

Many of the testing notes in the HACKING file were in duplicated in two places
in that file!  This change removes that duplication.  It also adds new sections
on “Where should I put a new test?” and “TestCase and its subclasses”, and
others like “Test feature dependencies” have been expanded.  The whole document
has generally been edited to be a bit more coherent. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007, 2009, 2010 Canonical Ltd
 
1
# Copyright (C) 2007 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
"""Container format for Bazaar data.
18
18
 
34
34
 
35
35
def _check_name(name):
36
36
    """Do some basic checking of 'name'.
37
 
 
 
37
    
38
38
    At the moment, this just checks that there are no whitespace characters in a
39
39
    name.
40
40
 
47
47
 
48
48
def _check_name_encoding(name):
49
49
    """Check that 'name' is valid UTF-8.
50
 
 
 
50
    
51
51
    This is separate from _check_name because UTF-8 decoding is relatively
52
52
    expensive, and we usually want to avoid it.
53
53
 
61
61
 
62
62
class ContainerSerialiser(object):
63
63
    """A helper class for serialising containers.
64
 
 
 
64
    
65
65
    It simply returns bytes from method calls to 'begin', 'end' and
66
66
    'bytes_record'.  You may find ContainerWriter to be a more convenient
67
67
    interface.
138
138
 
139
139
    def add_bytes_record(self, bytes, names):
140
140
        """Add a Bytes record with the given names.
141
 
 
 
141
        
142
142
        :param bytes: The bytes to insert.
143
143
        :param names: The names to give the inserted bytes. Each name is
144
144
            a tuple of bytestrings. The bytestrings may not contain
159
159
 
160
160
 
161
161
class ReadVFile(object):
162
 
    """Adapt a readv result iterator to a file like protocol.
163
 
    
164
 
    The readv result must support the iterator protocol returning (offset,
165
 
    data_bytes) pairs.
166
 
    """
167
 
 
168
 
    # XXX: This could be a generic transport class, as other code may want to
169
 
    # gradually consume the readv result.
 
162
    """Adapt a readv result iterator to a file like protocol."""
170
163
 
171
164
    def __init__(self, readv_result):
172
 
        """Construct a new ReadVFile wrapper.
173
 
 
174
 
        :seealso: make_readv_reader
175
 
 
176
 
        :param readv_result: the most recent readv result - list or generator
177
 
        """
178
 
        # readv can return a sequence or an iterator, but we require an
179
 
        # iterator to know how much has been consumed.
180
 
        readv_result = iter(readv_result)
181
165
        self.readv_result = readv_result
 
166
        # the most recent readv result block
182
167
        self._string = None
183
168
 
184
169
    def _next(self):
185
170
        if (self._string is None or
186
171
            self._string.tell() == self._string_length):
187
 
            offset, data = self.readv_result.next()
 
172
            length, data = self.readv_result.next()
188
173
            self._string_length = len(data)
189
174
            self._string = StringIO(data)
190
175
 
192
177
        self._next()
193
178
        result = self._string.read(length)
194
179
        if len(result) < length:
195
 
            raise errors.BzrError('wanted %d bytes but next '
196
 
                'hunk only contains %d: %r...' %
197
 
                (length, len(result), result[:20]))
 
180
            raise errors.BzrError('request for too much data from a readv hunk.')
198
181
        return result
199
182
 
200
183
    def readline(self):
202
185
        self._next()
203
186
        result = self._string.readline()
204
187
        if self._string.tell() == self._string_length and result[-1] != '\n':
205
 
            raise errors.BzrError('short readline in the readvfile hunk: %r'
206
 
                % (result, ))
 
188
            raise errors.BzrError('short readline in the readvfile hunk.')
207
189
        return result
208
190
 
209
191
 
252
234
        is a ``list`` and bytes is a function that takes one argument,
253
235
        ``max_length``.
254
236
 
255
 
        You **must not** call the callable after advancing the iterator to the
 
237
        You **must not** call the callable after advancing the interator to the
256
238
        next record.  That is, this code is invalid::
257
239
 
258
240
            record_iter = container.iter_records()
259
241
            names1, callable1 = record_iter.next()
260
242
            names2, callable2 = record_iter.next()
261
243
            bytes1 = callable1(None)
262
 
 
 
244
        
263
245
        As it will give incorrect results and invalidate the state of the
264
246
        ContainerReader.
265
247
 
266
 
        :raises ContainerError: if any sort of container corruption is
 
248
        :raises ContainerError: if any sort of containter corruption is
267
249
            detected, e.g. UnknownContainerFormatError is the format of the
268
250
            container is unrecognised.
269
251
        :seealso: ContainerReader.read
270
252
        """
271
253
        self._read_format()
272
254
        return self._iter_records()
273
 
 
 
255
    
274
256
    def iter_record_objects(self):
275
257
        """Iterate over the container, yielding each record as it is read.
276
258
 
278
260
        methods.  Like with iter_records, it is not safe to use a record object
279
261
        after advancing the iterator to yield next record.
280
262
 
281
 
        :raises ContainerError: if any sort of container corruption is
 
263
        :raises ContainerError: if any sort of containter corruption is
282
264
            detected, e.g. UnknownContainerFormatError is the format of the
283
265
            container is unrecognised.
284
266
        :seealso: iter_records
285
267
        """
286
268
        self._read_format()
287
269
        return self._iter_record_objects()
288
 
 
 
270
    
289
271
    def _iter_records(self):
290
272
        for record in self._iter_record_objects():
291
273
            yield record.read()
360
342
        except ValueError:
361
343
            raise errors.InvalidRecordError(
362
344
                "%r is not a valid length." % (length_line,))
363
 
 
 
345
        
364
346
        # Read the list of names.
365
347
        names = []
366
348
        while True:
424
406
        # the buffer.
425
407
        last_buffer_length = None
426
408
        cur_buffer_length = len(self._buffer)
427
 
        last_state_handler = None
428
 
        while (cur_buffer_length != last_buffer_length
429
 
               or last_state_handler != self._state_handler):
 
409
        while cur_buffer_length != last_buffer_length:
430
410
            last_buffer_length = cur_buffer_length
431
 
            last_state_handler = self._state_handler
432
411
            self._state_handler()
433
412
            cur_buffer_length = len(self._buffer)
434
413
 
435
 
    def read_pending_records(self, max=None):
436
 
        if max:
437
 
            records = self._parsed_records[:max]
438
 
            del self._parsed_records[:max]
439
 
            return records
440
 
        else:
441
 
            records = self._parsed_records
442
 
            self._parsed_records = []
443
 
            return records
444
 
 
 
414
    def read_pending_records(self):
 
415
        records = self._parsed_records
 
416
        self._parsed_records = []
 
417
        return records
 
418
    
445
419
    def _consume_line(self):
446
420
        """Take a line out of the buffer, and return the line.
447
421
 
494
468
            for name_part in name_parts:
495
469
                _check_name(name_part)
496
470
            self._current_record_names.append(name_parts)
497
 
 
 
471
            
498
472
    def _state_expecting_body(self):
499
473
        if len(self._buffer) >= self._current_record_length:
500
474
            body_bytes = self._buffer[:self._current_record_length]