251
249
ERROR_DIRECTORY = 267
254
if not getattr(struct, '_compile', None):
255
# Cannot pre-compile the dirstate pack_stat
256
def pack_stat(st, _encode=binascii.b2a_base64, _pack=struct.pack):
257
"""Convert stat values into a packed representation."""
258
return _encode(_pack('>LLLLLL', st.st_size & 0xFFFFFFFF,
259
int(st.st_mtime) & 0xFFFFFFFF, int(st.st_ctime) & 0xFFFFFFFF,
260
st.st_dev & 0xFFFFFFFF, st.st_ino & 0xFFFFFFFF,
263
# compile the struct compiler we need, so as to only do it once
264
from _struct import Struct
265
_compiled_pack = Struct('>LLLLLL').pack
266
def pack_stat(st, _encode=binascii.b2a_base64, _pack=_compiled_pack):
267
"""Convert stat values into a packed representation."""
268
# jam 20060614 it isn't really worth removing more entries if we
269
# are going to leave it in packed form.
270
# With only st_mtime and st_mode filesize is 5.5M and read time is 275ms
271
# With all entries, filesize is 5.9M and read time is maybe 280ms
272
# well within the noise margin
274
# base64 encoding always adds a final newline, so strip it off
275
# The current version
276
return _encode(_pack(st.st_size, int(st.st_mtime), int(st.st_ctime),
277
st.st_dev, st.st_ino & 0xFFFFFFFF, st.st_mode))[:-1]
278
# This is 0.060s / 1.520s faster by not encoding as much information
279
# return _encode(_pack('>LL', int(st.st_mtime), st.st_mode))[:-1]
280
# This is not strictly faster than _encode(_pack())[:-1]
281
# return '%X.%X.%X.%X.%X.%X' % (
282
# st.st_size, int(st.st_mtime), int(st.st_ctime),
283
# st.st_dev, st.st_ino, st.st_mode)
284
# Similar to the _encode(_pack('>LL'))
285
# return '%X.%X' % (int(st.st_mtime), st.st_mode)
288
def _unpack_stat(packed_stat):
289
"""Turn a packed_stat back into the stat fields.
291
This is meant as a debugging tool, should not be used in real code.
293
(st_size, st_mtime, st_ctime, st_dev, st_ino,
294
st_mode) = struct.unpack('>LLLLLL', binascii.a2b_base64(packed_stat))
295
return dict(st_size=st_size, st_mtime=st_mtime, st_ctime=st_ctime,
296
st_dev=st_dev, st_ino=st_ino, st_mode=st_mode)
299
252
class SHA1Provider(object):
300
253
"""An interface for getting sha1s of a file."""
1897
1850
file_id, "This parent is not a directory.")
1899
1852
def _observed_sha1(self, entry, sha1, stat_value,
1900
_stat_to_minikind=_stat_to_minikind, _pack_stat=pack_stat):
1853
_stat_to_minikind=_stat_to_minikind):
1901
1854
"""Note the sha1 of a file.
1903
1856
:param entry: The entry the sha1 is for.
1909
1862
except KeyError:
1910
1863
# Unhandled kind
1912
packed_stat = _pack_stat(stat_value)
1913
1865
if minikind == 'f':
1914
1866
if self._cutoff_time is None:
1915
1867
self._sha_cutoff_time()
1916
1868
if (stat_value.st_mtime < self._cutoff_time
1917
1869
and stat_value.st_ctime < self._cutoff_time):
1918
1870
entry[1][0] = ('f', sha1, stat_value.st_size, entry[1][0][3],
1871
pack_stat(stat_value))
1920
1872
self._mark_modified([entry])
1922
1874
def _sha_cutoff_time(self):
2475
2427
raise errors.BzrError('missing num_entries line')
2476
2428
self._num_entries = int(num_entries_line[len('num_entries: '):-1])
2478
def sha1_from_stat(self, path, stat_result, _pack_stat=pack_stat):
2430
def sha1_from_stat(self, path, stat_result):
2479
2431
"""Find a sha1 given a stat lookup."""
2480
return self._get_packed_stat_index().get(_pack_stat(stat_result), None)
2432
return self._get_packed_stat_index().get(pack_stat(stat_result), None)
2482
2434
def _get_packed_stat_index(self):
2483
2435
"""Get a packed_stat index of self._dirblocks."""