Mercurial > public > mercurial-scm > hg
comparison mercurial/revlog.py @ 9420:d0db168136dc
manifest/revlog: do not let the revlog cache mutable objects
If a buffer of an mutable object is passed to revlog.addrevision(), the revlog
will happily store it in its cache. Later when the revlog reuses the cached
entry, if the manifest modified the object in-between, all kind of bugs
appears.
We fix it by:
- passing immutable objects to addrevision() if they are already available
- only storing the text in the cache if it's of str type
Then we can remove the conversion of the cache entry to str() during
retrieval. That was probably just there hiding the bug for the common cases
but not really fixing it.
author | Benoit Boissinot <benoit.boissinot@ens-lyon.org> |
---|---|
date | Fri, 04 Sep 2009 10:47:55 +0200 |
parents | 0001e49f1c11 |
children | 1c4e4004f3a6 |
comparison
equal
deleted
inserted
replaced
9419:3516a4e877c1 | 9420:d0db168136dc |
---|---|
971 def revision(self, node): | 971 def revision(self, node): |
972 """return an uncompressed revision of a given node""" | 972 """return an uncompressed revision of a given node""" |
973 if node == nullid: | 973 if node == nullid: |
974 return "" | 974 return "" |
975 if self._cache and self._cache[0] == node: | 975 if self._cache and self._cache[0] == node: |
976 return str(self._cache[2]) | 976 return self._cache[2] |
977 | 977 |
978 # look up what we need to read | 978 # look up what we need to read |
979 text = None | 979 text = None |
980 rev = self.rev(node) | 980 rev = self.rev(node) |
981 base = self.base(rev) | 981 base = self.base(rev) |
986 (self.index[rev][0] & 0xFFFF)) | 986 (self.index[rev][0] & 0xFFFF)) |
987 | 987 |
988 # do we have useful data cached? | 988 # do we have useful data cached? |
989 if self._cache and self._cache[1] >= base and self._cache[1] < rev: | 989 if self._cache and self._cache[1] >= base and self._cache[1] < rev: |
990 base = self._cache[1] | 990 base = self._cache[1] |
991 text = str(self._cache[2]) | 991 text = self._cache[2] |
992 | 992 |
993 self._loadindex(base, rev + 1) | 993 self._loadindex(base, rev + 1) |
994 self._chunkraw(base, rev) | 994 self._chunkraw(base, rev) |
995 if text is None: | 995 if text is None: |
996 text = self._chunk(base) | 996 text = self._chunk(base) |
1109 ifh.write(entry) | 1109 ifh.write(entry) |
1110 ifh.write(data[0]) | 1110 ifh.write(data[0]) |
1111 ifh.write(data[1]) | 1111 ifh.write(data[1]) |
1112 self.checkinlinesize(transaction, ifh) | 1112 self.checkinlinesize(transaction, ifh) |
1113 | 1113 |
1114 self._cache = (node, curr, text) | 1114 if type(text) == str: # only accept immutable objects |
1115 self._cache = (node, curr, text) | |
1115 return node | 1116 return node |
1116 | 1117 |
1117 def ancestor(self, a, b): | 1118 def ancestor(self, a, b): |
1118 """calculate the least common ancestor of nodes a and b""" | 1119 """calculate the least common ancestor of nodes a and b""" |
1119 | 1120 |