comparison mercurial/revlog.py @ 4980:fc44c8df9d99

revlog: some codingstyle cleanups
author Matt Mackall <mpm@selenic.com>
date Mon, 23 Jul 2007 20:44:08 -0500
parents 06abdaf78788
children e7131935fbb3
comparison
equal deleted inserted replaced
4979:06abdaf78788 4980:fc44c8df9d99
40 s.update(text) 40 s.update(text)
41 return s.digest() 41 return s.digest()
42 42
43 def compress(text): 43 def compress(text):
44 """ generate a possibly-compressed representation of text """ 44 """ generate a possibly-compressed representation of text """
45 if not text: return ("", text) 45 if not text:
46 return ("", text)
46 if len(text) < 44: 47 if len(text) < 44:
47 if text[0] == '\0': return ("", text) 48 if text[0] == '\0':
49 return ("", text)
48 return ('u', text) 50 return ('u', text)
49 bin = zlib.compress(text) 51 bin = zlib.compress(text)
50 if len(bin) > len(text): 52 if len(bin) > len(text):
51 if text[0] == '\0': return ("", text) 53 if text[0] == '\0':
54 return ("", text)
52 return ('u', text) 55 return ('u', text)
53 return ("", bin) 56 return ("", bin)
54 57
55 def decompress(bin): 58 def decompress(bin):
56 """ decompress the given input """ 59 """ decompress the given input """
57 if not bin: return bin 60 if not bin:
61 return bin
58 t = bin[0] 62 t = bin[0]
59 if t == '\0': return bin 63 if t == '\0':
60 if t == 'x': return zlib.decompress(bin) 64 return bin
61 if t == 'u': return bin[1:] 65 if t == 'x':
66 return zlib.decompress(bin)
67 if t == 'u':
68 return bin[1:]
62 raise RevlogError(_("unknown compression type %r") % t) 69 raise RevlogError(_("unknown compression type %r") % t)
63 70
64 indexformatv0 = ">4l20s20s20s" 71 indexformatv0 = ">4l20s20s20s"
65 v0shaoffset = 56 72 v0shaoffset = 56
66 # index ng: 73 # index ng:
104 during a commit, we need to make sure the rev being added is 111 during a commit, we need to make sure the rev being added is
105 not a duplicate. This requires loading the entire index, 112 not a duplicate. This requires loading the entire index,
106 which is fairly slow. loadmap can load up just the node map, 113 which is fairly slow. loadmap can load up just the node map,
107 which takes much less time. 114 which takes much less time.
108 """ 115 """
109 if self.allmap: return 116 if self.allmap:
117 return
110 end = self.datasize 118 end = self.datasize
111 self.allmap = 1 119 self.allmap = 1
112 cur = 0 120 cur = 0
113 count = 0 121 count = 0
114 blocksize = self.s * 256 122 blocksize = self.s * 256
124 break 132 break
125 off += self.s 133 off += self.s
126 cur += blocksize 134 cur += blocksize
127 135
128 def loadblock(self, blockstart, blocksize, data=None): 136 def loadblock(self, blockstart, blocksize, data=None):
129 if self.all: return 137 if self.all:
138 return
130 if data is None: 139 if data is None:
131 self.dataf.seek(blockstart) 140 self.dataf.seek(blockstart)
132 if blockstart + blocksize > self.datasize: 141 if blockstart + blocksize > self.datasize:
133 # the revlog may have grown since we've started running, 142 # the revlog may have grown since we've started running,
134 # but we don't have space in self.index for more entries. 143 # but we don't have space in self.index for more entries.
149 self.map[n] = i + x 158 self.map[n] = i + x
150 off += self.s 159 off += self.s
151 160
152 def findnode(self, node): 161 def findnode(self, node):
153 """search backwards through the index file for a specific node""" 162 """search backwards through the index file for a specific node"""
154 if self.allmap: return None 163 if self.allmap:
164 return None
155 165
156 # hg log will cause many many searches for the manifest 166 # hg log will cause many many searches for the manifest
157 # nodes. After we get called a few times, just load the whole 167 # nodes. After we get called a few times, just load the whole
158 # thing. 168 # thing.
159 if self.mapfind_count > 8: 169 if self.mapfind_count > 8:
192 break 202 break
193 end -= blocksize 203 end -= blocksize
194 return None 204 return None
195 205
196 def loadindex(self, i=None, end=None): 206 def loadindex(self, i=None, end=None):
197 if self.all: return 207 if self.all:
208 return
198 all = False 209 all = False
199 if i == None: 210 if i == None:
200 blockstart = 0 211 blockstart = 0
201 blocksize = (512 / self.s) * self.s 212 blocksize = (512 / self.s) * self.s
202 end = self.datasize 213 end = self.datasize
211 blocksize = self.s * 64 222 blocksize = self.s * 64
212 end = blockstart + blocksize 223 end = blockstart + blocksize
213 while blockstart < end: 224 while blockstart < end:
214 self.loadblock(blockstart, blocksize) 225 self.loadblock(blockstart, blocksize)
215 blockstart += blocksize 226 blockstart += blocksize
216 if all: self.all = True 227 if all:
228 self.all = True
217 229
218 class lazyindex(object): 230 class lazyindex(object):
219 """a lazy version of the index array""" 231 """a lazy version of the index array"""
220 def __init__(self, parser): 232 def __init__(self, parser):
221 self.p = parser 233 self.p = parser
275 def __setitem__(self, key, val): 287 def __setitem__(self, key, val):
276 self.p.map[key] = val 288 self.p.map[key] = val
277 def __delitem__(self, key): 289 def __delitem__(self, key):
278 del self.p.map[key] 290 del self.p.map[key]
279 291
280 class RevlogError(Exception): pass 292 class RevlogError(Exception):
281 class LookupError(RevlogError): pass 293 pass
294 class LookupError(RevlogError):
295 pass
282 296
283 def getoffset(q): 297 def getoffset(q):
284 if q & 0xFFFF: 298 if q & 0xFFFF:
285 raise RevlogError(_('incompatible revision flag %x') % q) 299 raise RevlogError(_('incompatible revision flag %x') % q)
286 return int(q >> 16) 300 return int(q >> 16)
472 """loads the map from the lazy parser""" 486 """loads the map from the lazy parser"""
473 if isinstance(self.nodemap, lazymap): 487 if isinstance(self.nodemap, lazymap):
474 self.nodemap.p.loadmap() 488 self.nodemap.p.loadmap()
475 self.nodemap = self.nodemap.p.map 489 self.nodemap = self.nodemap.p.map
476 490
477 def _inline(self): return self.version & REVLOGNGINLINEDATA 491 def _inline(self):
478 492 return self.version & REVLOGNGINLINEDATA
479 def tip(self): return self.node(len(self.index) - 2) 493 def tip(self):
480 def count(self): return len(self.index) - 1 494 return self.node(len(self.index) - 2)
481 def node(self, rev): 495 def count(self):
482 return self.index[rev][7] 496 return len(self.index) - 1
497
483 def rev(self, node): 498 def rev(self, node):
484 try: 499 try:
485 return self.nodemap[node] 500 return self.nodemap[node]
486 except KeyError: 501 except KeyError:
487 raise LookupError(_('%s: no node %s') % (self.indexfile, hex(node))) 502 raise LookupError(_('%s: no node %s') % (self.indexfile, hex(node)))
503 def node(self, rev):
504 return self.index[rev][7]
488 def linkrev(self, node): 505 def linkrev(self, node):
489 return self.index[self.rev(node)][4] 506 return self.index[self.rev(node)][4]
490 def parents(self, node): 507 def parents(self, node):
491 d = self.index[self.rev(node)][5:7] 508 d = self.index[self.rev(node)][5:7]
492 return (self.node(d[0]), self.node(d[1])) 509 return (self.node(d[0]), self.node(d[1]))
493 def parentrevs(self, rev): 510 def parentrevs(self, rev):
494 return self.index[rev][5:7] 511 return self.index[rev][5:7]
495 def start(self, rev): 512 def start(self, rev):
496 return getoffset(self.index[rev][0]) 513 return getoffset(self.index[rev][0])
497 def end(self, rev): return self.start(rev) + self.length(rev) 514 def end(self, rev):
515 return self.start(rev) + self.length(rev)
516 def length(self, rev):
517 return self.index[rev][1]
518 def base(self, rev):
519 return self.index[rev][3]
498 520
499 def size(self, rev): 521 def size(self, rev):
500 """return the length of the uncompressed text for a given revision""" 522 """return the length of the uncompressed text for a given revision"""
501 l = self.index[rev][2] 523 l = self.index[rev][2]
502 if l >= 0: 524 if l >= 0:
522 l = len(text) 544 l = len(text)
523 for x in xrange(base + 1, rev + 1): 545 for x in xrange(base + 1, rev + 1):
524 l = mdiff.patchedsize(l, self.chunk(x)) 546 l = mdiff.patchedsize(l, self.chunk(x))
525 return l 547 return l
526 """ 548 """
527
528 def length(self, rev):
529 return self.index[rev][1]
530 def base(self, rev):
531 return self.index[rev][3]
532 549
533 def reachable(self, node, stop=None): 550 def reachable(self, node, stop=None):
534 """return a hash of all nodes ancestral to a given node, including 551 """return a hash of all nodes ancestral to a given node, including
535 the node itself, stopping when stop is matched""" 552 the node itself, stopping when stop is matched"""
536 reachable = {} 553 reachable = {}
762 except LookupError: 779 except LookupError:
763 pass # may be partial hex id 780 pass # may be partial hex id
764 try: 781 try:
765 # str(rev) 782 # str(rev)
766 rev = int(id) 783 rev = int(id)
767 if str(rev) != id: raise ValueError 784 if str(rev) != id:
768 if rev < 0: rev = self.count() + rev 785 raise ValueError
769 if rev < 0 or rev >= self.count(): raise ValueError 786 if rev < 0:
787 rev = self.count() + rev
788 if rev < 0 or rev >= self.count():
789 raise ValueError
770 return self.node(rev) 790 return self.node(rev)
771 except (ValueError, OverflowError): 791 except (ValueError, OverflowError):
772 pass 792 pass
773 if len(id) == 40: 793 if len(id) == 40:
774 try: 794 try:
798 def lookup(self, id): 818 def lookup(self, id):
799 """locate a node based on: 819 """locate a node based on:
800 - revision number or str(revision number) 820 - revision number or str(revision number)
801 - nodeid or subset of hex nodeid 821 - nodeid or subset of hex nodeid
802 """ 822 """
803
804 n = self._match(id) 823 n = self._match(id)
805 if n is not None: 824 if n is not None:
806 return n 825 return n
807 n = self._partialmatch(id) 826 n = self._partialmatch(id)
808 if n: 827 if n:
849 offset = start - cache_start 868 offset = start - cache_start
850 else: 869 else:
851 loadcache(df) 870 loadcache(df)
852 offset = 0 871 offset = 0
853 872
854 #def checkchunk():
855 # df = self.opener(self.datafile)
856 # df.seek(start)
857 # return df.read(length)
858 #assert s == checkchunk()
859 return decompress(self._io.chunkcache[1][offset:offset + length]) 873 return decompress(self._io.chunkcache[1][offset:offset + length])
860 874
861 def delta(self, node): 875 def delta(self, node):
862 """return or calculate a delta between a node and its predecessor""" 876 """return or calculate a delta between a node and its predecessor"""
863 r = self.rev(node) 877 r = self.rev(node)
873 return self.diff(self.revision(self.node(rev1)), 887 return self.diff(self.revision(self.node(rev1)),
874 self.revision(self.node(rev2))) 888 self.revision(self.node(rev2)))
875 889
876 def revision(self, node): 890 def revision(self, node):
877 """return an uncompressed revision of a given""" 891 """return an uncompressed revision of a given"""
878 if node == nullid: return "" 892 if node == nullid:
879 if self.cache and self.cache[0] == node: return self.cache[2] 893 return ""
894 if self.cache and self.cache[0] == node:
895 return self.cache[2]
880 896
881 # look up what we need to read 897 # look up what we need to read
882 text = None 898 text = None
883 rev = self.rev(node) 899 rev = self.rev(node)
884 base = self.base(rev) 900 base = self.base(rev)
976 dfh = None 992 dfh = None
977 ifh = self.opener(self.indexfile, "a+") 993 ifh = self.opener(self.indexfile, "a+")
978 return self._addrevision(text, transaction, link, p1, p2, d, ifh, dfh) 994 return self._addrevision(text, transaction, link, p1, p2, d, ifh, dfh)
979 995
980 def _addrevision(self, text, transaction, link, p1, p2, d, ifh, dfh): 996 def _addrevision(self, text, transaction, link, p1, p2, d, ifh, dfh):
981 if text is None: text = "" 997 if text is None:
982 if p1 is None: p1 = self.tip() 998 text = ""
983 if p2 is None: p2 = nullid 999 if p1 is None:
1000 p1 = self.tip()
1001 if p2 is None:
1002 p2 = nullid
984 1003
985 node = hash(text, p1, p2) 1004 node = hash(text, p1, p2)
986 1005
987 if node in self.nodemap: 1006 if node in self.nodemap:
988 return node 1007 return node