1018
def get_sha1_for_entry(self, entry, abspath, stat_value=None):
1019
"""Return the sha1 sum for a given file.
1021
:param entry: This is the dirblock entry for the file in question.
1022
:param abspath: The path on disk for this file.
1023
:param stat_value: (optional) if we already have done a stat on the
1025
:return: The sha1 hexdigest of the file (40 bytes)
1027
# This code assumes that the entry passed in is directly held in one of
1028
# the internal _dirblocks. So the dirblock state must have already been
1030
assert self._dirblock_state != DirState.NOT_IN_MEMORY
1031
assert entry[1][0][0] == 'f', \
1032
'can only get sha1 for a file not: %s %s' % (
1033
DirState._minikind_to_kind[entry[1][0][0]], entry[0])
1034
if stat_value is None:
1035
stat_value = os.lstat(abspath)
1036
packed_stat = pack_stat(stat_value)
1037
saved_sha1_digest = entry[1][0][1]
1038
saved_file_size = entry[1][0][2]
1039
saved_packed_stat = entry[1][0][4]
1040
if (packed_stat == saved_packed_stat
1041
and saved_sha1_digest != ''
1042
# size should also be in packed_stat
1043
and saved_file_size == stat_value.st_size):
1044
# The stat hasn't changed since we saved, so we can potentially
1045
# re-use the saved sha hash.
1046
cutoff = self._sha_cutoff_time()
1047
if (stat_value.st_mtime < cutoff
1048
and stat_value.st_ctime < cutoff):
1049
# Return the existing fingerprint
1050
return saved_sha1_digest
1051
# If we have gotten this far, that means that we need to actually
1053
new_sha1_digest = self._sha1_file(abspath)
1054
# TODO: jam 20070301 Is it worth checking to see if the new sha is
1055
# actually different? I'm guessing not, because we wouldn't have
1056
# gotten this far otherwise.
1057
entry[1][0] = ('f', new_sha1_digest, stat_value.st_size,
1058
entry[1][0][3], # Executable?
1061
self._dirblock_state = DirState.IN_MEMORY_MODIFIED
1062
return new_sha1_digest
1064
def _sha_cutoff_time(self):
1065
"""Return cutoff time.
1067
Files modified more recently than this time are at risk of being
1068
undetectably modified and so can't be cached.
1070
return int(time.time()) - 3
1072
def _sha1_file(self, abspath):
1073
"""Calculate the SHA1 of a file by reading the full text"""
1074
f = file(abspath, 'rb', buffering=65000)
1076
return osutils.sha_file(f)
1017
1080
def get_ghosts(self):
1018
1081
"""Return a list of the parent tree revision ids that are ghosts."""
1019
1082
self._read_header_if_needed()
1245
1308
# stock empty dirstate information - a root with ROOT_ID, no children,
1246
1309
# and no parents. Finally it calls save() to ensure that this data will
1248
result = DirState(path)
1249
1312
# root dir and root dir contents with no children.
1250
1313
empty_tree_dirblocks = [('', []), ('', [])]
1251
1314
# a new root directory, with a NULLSTAT.
2051
def pack_stat(st, _encode=base64.encodestring, _pack=struct.pack):
2114
_base64_encoder = codecs.getencoder('base64')
2117
def pack_stat(st, _encode=_base64_encoder, _pack=struct.pack):
2052
2118
"""Convert stat values into a packed representation."""
2053
2119
# jam 20060614 it isn't really worth removing more entries if we
2054
2120
# are going to leave it in packed form.
2059
2125
# base64.encode always adds a final newline, so strip it off
2060
2126
return _encode(_pack('>llllll'
2061
, st.st_size, st.st_mtime, st.st_ctime
2062
, st.st_dev, st.st_ino, st.st_mode))[:-1]
2127
, st.st_size, int(st.st_mtime), int(st.st_ctime)
2128
, st.st_dev, st.st_ino, st.st_mode))[0][:-1]