/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/_dirstate_helpers_py.py

  • Committer: Martin
  • Date: 2017-06-11 01:12:29 UTC
  • mto: This revision was merged to the branch mainline in revision 6685.
  • Revision ID: gzlist@googlemail.com-20170611011229-somdjbalby8m7vlw
Make _chunks_to_lines pass for Python 3

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
"""Python implementations of Dirstate Helper functions."""
18
18
 
 
19
from __future__ import absolute_import
 
20
 
 
21
import binascii
19
22
import os
 
23
import struct
20
24
 
21
25
# We cannot import the dirstate module, because it loads this module
22
26
# All we really need is the IN_MEMORY_MODIFIED constant
23
 
from bzrlib import errors
24
 
from bzrlib.dirstate import DirState
 
27
from breezy import errors
 
28
from .dirstate import DirState
 
29
from .sixish import (
 
30
    range,
 
31
    )
 
32
 
 
33
 
 
34
def pack_stat(st, _b64=binascii.b2a_base64, _pack=struct.Struct('>6L').pack):
 
35
    """Convert stat values into a packed representation
 
36
 
 
37
    Not all of the fields from the stat included are strictly needed, and by
 
38
    just encoding the mtime and mode a slight speed increase could be gained.
 
39
    However, using the pyrex version instead is a bigger win.
 
40
    """
 
41
    # base64 encoding always adds a final newline, so strip it off
 
42
    return _b64(_pack(st.st_size & 0xFFFFFFFF, int(st.st_mtime) & 0xFFFFFFFF,
 
43
        int(st.st_ctime) & 0xFFFFFFFF, st.st_dev & 0xFFFFFFFF,
 
44
        st.st_ino & 0xFFFFFFFF, st.st_mode))[:-1]
 
45
 
 
46
 
 
47
def _unpack_stat(packed_stat):
 
48
    """Turn a packed_stat back into the stat fields.
 
49
 
 
50
    This is meant as a debugging tool, should not be used in real code.
 
51
    """
 
52
    (st_size, st_mtime, st_ctime, st_dev, st_ino,
 
53
     st_mode) = struct.unpack('>6L', binascii.a2b_base64(packed_stat))
 
54
    return dict(st_size=st_size, st_mtime=st_mtime, st_ctime=st_ctime,
 
55
                st_dev=st_dev, st_ino=st_ino, st_mode=st_mode)
25
56
 
26
57
 
27
58
def _bisect_path_left(paths, path):
63
94
        mid = (lo + hi) // 2
64
95
        # Grab the dirname for the current dirblock
65
96
        cur = paths[mid]
66
 
        if _cmp_path_by_dirblock(cur, path) < 0:
 
97
        if _lt_path_by_dirblock(cur, path):
67
98
            lo = mid + 1
68
99
        else:
69
100
            hi = mid
94
125
        mid = (lo+hi)//2
95
126
        # Grab the dirname for the current dirblock
96
127
        cur = paths[mid]
97
 
        if _cmp_path_by_dirblock(path, cur) < 0:
 
128
        if _lt_path_by_dirblock(path, cur):
98
129
            hi = mid
99
130
        else:
100
131
            lo = mid + 1
116
147
    try:
117
148
        dirname_split = cache[dirname]
118
149
    except KeyError:
119
 
        dirname_split = dirname.split('/')
 
150
        dirname_split = dirname.split(b'/')
120
151
        cache[dirname] = dirname_split
121
152
    while lo < hi:
122
153
        mid = (lo + hi) // 2
125
156
        try:
126
157
            cur_split = cache[cur]
127
158
        except KeyError:
128
 
            cur_split = cur.split('/')
 
159
            cur_split = cur.split(b'/')
129
160
            cache[cur] = cur_split
130
161
        if cur_split < dirname_split: lo = mid + 1
131
162
        else: hi = mid
132
163
    return lo
133
164
 
134
165
 
135
 
def cmp_by_dirs(path1, path2):
 
166
def lt_by_dirs(path1, path2):
136
167
    """Compare two paths directory by directory.
137
168
 
138
169
    This is equivalent to doing::
139
170
 
140
 
       cmp(path1.split('/'), path2.split('/'))
 
171
       operator.lt(path1.split('/'), path2.split('/'))
141
172
 
142
173
    The idea is that you should compare path components separately. This
143
 
    differs from plain ``cmp(path1, path2)`` for paths like ``'a-b'`` and
144
 
    ``a/b``. "a-b" comes after "a" but would come before "a/b" lexically.
 
174
    differs from plain ``path1 < path2`` for paths like ``'a-b'`` and ``a/b``.
 
175
    "a-b" comes after "a" but would come before "a/b" lexically.
145
176
 
146
177
    :param path1: first path
147
178
    :param path2: second path
148
 
    :return: negative number if ``path1`` comes first,
149
 
        0 if paths are equal,
150
 
        and positive number if ``path2`` sorts first
 
179
    :return: True if path1 comes first, otherwise False
151
180
    """
152
 
    if not isinstance(path1, str):
 
181
    if not isinstance(path1, bytes):
153
182
        raise TypeError("'path1' must be a plain string, not %s: %r"
154
183
                        % (type(path1), path1))
155
 
    if not isinstance(path2, str):
 
184
    if not isinstance(path2, bytes):
156
185
        raise TypeError("'path2' must be a plain string, not %s: %r"
157
186
                        % (type(path2), path2))
158
 
    return cmp(path1.split('/'), path2.split('/'))
159
 
 
160
 
 
161
 
def _cmp_path_by_dirblock(path1, path2):
 
187
    return path1.split('/') < path2.split('/')
 
188
 
 
189
 
 
190
def _lt_path_by_dirblock(path1, path2):
162
191
    """Compare two paths based on what directory they are in.
163
192
 
164
193
    This generates a sort order, such that all children of a directory are
167
196
 
168
197
    :param path1: first path
169
198
    :param path2: the second path
170
 
    :return: negative number if ``path1`` comes first,
171
 
        0 if paths are equal
172
 
        and a positive number if ``path2`` sorts first
 
199
    :return: True if path1 comes first, otherwise False
173
200
    """
174
 
    if not isinstance(path1, str):
 
201
    if not isinstance(path1, bytes):
175
202
        raise TypeError("'path1' must be a plain string, not %s: %r"
176
203
                        % (type(path1), path1))
177
 
    if not isinstance(path2, str):
 
204
    if not isinstance(path2, bytes):
178
205
        raise TypeError("'path2' must be a plain string, not %s: %r"
179
206
                        % (type(path2), path2))
180
207
    dirname1, basename1 = os.path.split(path1)
181
 
    key1 = (dirname1.split('/'), basename1)
 
208
    key1 = (dirname1.split(b'/'), basename1)
182
209
    dirname2, basename2 = os.path.split(path2)
183
210
    key2 = (dirname2.split('/'), basename2)
184
 
    return cmp(key1, key2)
 
211
    return key1 < key2
185
212
 
186
213
 
187
214
def _read_dirblocks(state):
198
225
    text = state._state_file.read()
199
226
    # TODO: check the crc checksums. crc_measured = zlib.crc32(text)
200
227
 
201
 
    fields = text.split('\0')
 
228
    fields = text.split(b'\0')
202
229
    # Remove the last blank entry
203
230
    trailing = fields.pop()
204
 
    if trailing != '':
 
231
    if trailing != b'':
205
232
        raise errors.DirstateCorrupt(state,
206
233
            'trailing garbage: %r' % (trailing,))
207
234
    # consider turning fields into a tuple.
234
261
        # them. Grab an straight iterator over the fields. (We use an
235
262
        # iterator because we don't want to do a lot of additions, nor
236
263
        # do we want to do a lot of slicing)
237
 
        next = iter(fields).next
 
264
        _iter = iter(fields)
 
265
        # Get a local reference to the compatible next method
 
266
        next = getattr(_iter, '__next__', None)
 
267
        if next is None:
 
268
            next = _iter.next
238
269
        # Move the iterator to the current position
239
 
        for x in xrange(cur):
 
270
        for x in range(cur):
240
271
            next()
241
272
        # The two blocks here are deliberate: the root block and the
242
273
        # contents-of-root block.
244
275
        current_block = state._dirblocks[0][1]
245
276
        current_dirname = ''
246
277
        append_entry = current_block.append
247
 
        for count in xrange(state._num_entries):
 
278
        for count in range(state._num_entries):
248
279
            dirname = next()
249
280
            name = next()
250
281
            file_id = next()
261
292
                         next(),                # minikind
262
293
                         next(),                # fingerprint
263
294
                         _int(next()),          # size
264
 
                         next() == 'y',         # executable
 
295
                         next() == b'y',        # executable
265
296
                         next(),                # packed_stat or revision_id
266
297
                     ),
267
298
                     ( # Parent 1
268
299
                         next(),                # minikind
269
300
                         next(),                # fingerprint
270
301
                         _int(next()),          # size
271
 
                         next() == 'y',         # executable
 
302
                         next() == b'y',        # executable
272
303
                         next(),                # packed_stat or revision_id
273
304
                     ),
274
305
                     ])
281
312
    else:
282
313
        fields_to_entry = state._get_fields_to_entry()
283
314
        entries = [fields_to_entry(fields[pos:pos+entry_size])
284
 
                   for pos in xrange(cur, field_count, entry_size)]
 
315
                   for pos in range(cur, field_count, entry_size)]
285
316
        state._entries_to_current_state(entries)
286
317
    # To convert from format 2  => format 3
287
318
    # state._dirblocks = sorted(state._dirblocks,