25
25
# We cannot import the dirstate module, because it loads this module
26
26
# All we really need is the IN_MEMORY_MODIFIED constant
27
from .dirstate import DirState, DirstateCorrupt
28
from ..sixish import (
27
from bzrlib import errors
28
from bzrlib.dirstate import DirState
33
31
def pack_stat(st, _b64=binascii.b2a_base64, _pack=struct.Struct('>6L').pack):
156
154
cur_split = cache[cur]
158
cur_split = cur.split(b'/')
156
cur_split = cur.split('/')
159
157
cache[cur] = cur_split
160
158
if cur_split < dirname_split: lo = mid + 1
165
def lt_by_dirs(path1, path2):
163
def cmp_by_dirs(path1, path2):
166
164
"""Compare two paths directory by directory.
168
166
This is equivalent to doing::
170
operator.lt(path1.split('/'), path2.split('/'))
168
cmp(path1.split('/'), path2.split('/'))
172
170
The idea is that you should compare path components separately. This
173
differs from plain ``path1 < path2`` for paths like ``'a-b'`` and ``a/b``.
174
"a-b" comes after "a" but would come before "a/b" lexically.
171
differs from plain ``cmp(path1, path2)`` for paths like ``'a-b'`` and
172
``a/b``. "a-b" comes after "a" but would come before "a/b" lexically.
176
174
:param path1: first path
177
175
:param path2: second path
178
:return: True if path1 comes first, otherwise False
176
:return: negative number if ``path1`` comes first,
177
0 if paths are equal,
178
and positive number if ``path2`` sorts first
180
if not isinstance(path1, bytes):
180
if not isinstance(path1, str):
181
181
raise TypeError("'path1' must be a plain string, not %s: %r"
182
182
% (type(path1), path1))
183
if not isinstance(path2, bytes):
183
if not isinstance(path2, str):
184
184
raise TypeError("'path2' must be a plain string, not %s: %r"
185
185
% (type(path2), path2))
186
return path1.split(b'/') < path2.split(b'/')
189
def _lt_path_by_dirblock(path1, path2):
186
return cmp(path1.split('/'), path2.split('/'))
189
def _cmp_path_by_dirblock(path1, path2):
190
190
"""Compare two paths based on what directory they are in.
192
192
This generates a sort order, such that all children of a directory are
196
196
:param path1: first path
197
197
:param path2: the second path
198
:return: True if path1 comes first, otherwise False
198
:return: negative number if ``path1`` comes first,
200
and a positive number if ``path2`` sorts first
200
if not isinstance(path1, bytes):
202
if not isinstance(path1, str):
201
203
raise TypeError("'path1' must be a plain string, not %s: %r"
202
204
% (type(path1), path1))
203
if not isinstance(path2, bytes):
205
if not isinstance(path2, str):
204
206
raise TypeError("'path2' must be a plain string, not %s: %r"
205
207
% (type(path2), path2))
206
208
dirname1, basename1 = os.path.split(path1)
207
key1 = (dirname1.split(b'/'), basename1)
209
key1 = (dirname1.split('/'), basename1)
208
210
dirname2, basename2 = os.path.split(path2)
209
key2 = (dirname2.split(b'/'), basename2)
211
key2 = (dirname2.split('/'), basename2)
212
return cmp(key1, key2)
213
215
def _read_dirblocks(state):
224
226
text = state._state_file.read()
225
227
# TODO: check the crc checksums. crc_measured = zlib.crc32(text)
227
fields = text.split(b'\0')
229
fields = text.split('\0')
228
230
# Remove the last blank entry
229
231
trailing = fields.pop()
231
raise DirstateCorrupt(state,
233
raise errors.DirstateCorrupt(state,
232
234
'trailing garbage: %r' % (trailing,))
233
235
# consider turning fields into a tuple.
247
249
field_count = len(fields)
248
250
# this checks our adjustment, and also catches file too short.
249
251
if field_count - cur != expected_field_count:
250
raise DirstateCorrupt(state,
252
raise errors.DirstateCorrupt(state,
251
253
'field count incorrect %s != %s, entry_size=%s, '\
252
254
'num_entries=%s fields=%r' % (
253
255
field_count - cur, expected_field_count, entry_size,
260
262
# them. Grab an straight iterator over the fields. (We use an
261
263
# iterator because we don't want to do a lot of additions, nor
262
264
# do we want to do a lot of slicing)
264
# Get a local reference to the compatible next method
265
next = getattr(_iter, '__next__', None)
265
next = iter(fields).next
268
266
# Move the iterator to the current position
267
for x in xrange(cur):
271
269
# The two blocks here are deliberate: the root block and the
272
270
# contents-of-root block.
291
289
next(), # minikind
292
290
next(), # fingerprint
293
291
_int(next()), # size
294
next() == b'y', # executable
292
next() == 'y', # executable
295
293
next(), # packed_stat or revision_id
298
296
next(), # minikind
299
297
next(), # fingerprint
300
298
_int(next()), # size
301
next() == b'y', # executable
299
next() == 'y', # executable
302
300
next(), # packed_stat or revision_id
312
310
fields_to_entry = state._get_fields_to_entry()
313
311
entries = [fields_to_entry(fields[pos:pos+entry_size])
314
for pos in range(cur, field_count, entry_size)]
312
for pos in xrange(cur, field_count, entry_size)]
315
313
state._entries_to_current_state(entries)
316
314
# To convert from format 2 => format 3
317
315
# state._dirblocks = sorted(state._dirblocks,