comparison mercurial/revlog.py @ 6750:fb42030d79d6

add __len__ and __iter__ methods to repo and revlog
author Matt Mackall <mpm@selenic.com>
date Thu, 26 Jun 2008 14:35:50 -0500
parents bacfee67c1a9
children c7cc40fd74f6
comparison
equal deleted inserted replaced
6749:51b0e799352f 6750:fb42030d79d6
513 self.nodemap.p.loadmap() 513 self.nodemap.p.loadmap()
514 self.nodemap = self.nodemap.p.map 514 self.nodemap = self.nodemap.p.map
515 515
516 def tip(self): 516 def tip(self):
517 return self.node(len(self.index) - 2) 517 return self.node(len(self.index) - 2)
518 def count(self): 518 def __len__(self):
519 return len(self.index) - 1 519 return len(self.index) - 1
520 520 def __iter__(self):
521 for i in xrange(len(self)):
522 yield i
521 def rev(self, node): 523 def rev(self, node):
522 try: 524 try:
523 return self.nodemap[node] 525 return self.nodemap[node]
524 except KeyError: 526 except KeyError:
525 raise LookupError(node, self.indexfile, _('no node')) 527 raise LookupError(node, self.indexfile, _('no node'))
618 else: 620 else:
619 roots = [nullid] # Everybody's a descendent of nullid 621 roots = [nullid] # Everybody's a descendent of nullid
620 lowestrev = nullrev 622 lowestrev = nullrev
621 if (lowestrev == nullrev) and (heads is None): 623 if (lowestrev == nullrev) and (heads is None):
622 # We want _all_ the nodes! 624 # We want _all_ the nodes!
623 return ([self.node(r) for r in xrange(0, self.count())], 625 return ([self.node(r) for r in self], [nullid], list(self.heads()))
624 [nullid], list(self.heads()))
625 if heads is None: 626 if heads is None:
626 # All nodes are ancestors, so the latest ancestor is the last 627 # All nodes are ancestors, so the latest ancestor is the last
627 # node. 628 # node.
628 highestrev = self.count() - 1 629 highestrev = len(self) - 1
629 # Set ancestors to None to signal that every node is an ancestor. 630 # Set ancestors to None to signal that every node is an ancestor.
630 ancestors = None 631 ancestors = None
631 # Set heads to an empty dictionary for later discovery of heads 632 # Set heads to an empty dictionary for later discovery of heads
632 heads = {} 633 heads = {}
633 else: 634 else:
752 start will be returned 753 start will be returned
753 if stop is specified, it will consider all the revs from stop 754 if stop is specified, it will consider all the revs from stop
754 as if they had no children 755 as if they had no children
755 """ 756 """
756 if start is None and stop is None: 757 if start is None and stop is None:
757 count = self.count() 758 count = len(self)
758 if not count: 759 if not count:
759 return [nullid] 760 return [nullid]
760 ishead = [1] * (count + 1) 761 ishead = [1] * (count + 1)
761 index = self.index 762 index = self.index
762 for r in xrange(count): 763 for r in self:
763 e = index[r] 764 e = index[r]
764 ishead[e[5]] = ishead[e[6]] = 0 765 ishead[e[5]] = ishead[e[6]] = 0
765 return [self.node(r) for r in xrange(count) if ishead[r]] 766 return [self.node(r) for r in self if ishead[r]]
766 767
767 if start is None: 768 if start is None:
768 start = nullid 769 start = nullid
769 if stop is None: 770 if stop is None:
770 stop = [] 771 stop = []
772 startrev = self.rev(start) 773 startrev = self.rev(start)
773 reachable = {startrev: 1} 774 reachable = {startrev: 1}
774 heads = {startrev: 1} 775 heads = {startrev: 1}
775 776
776 parentrevs = self.parentrevs 777 parentrevs = self.parentrevs
777 for r in xrange(startrev + 1, self.count()): 778 for r in xrange(startrev + 1, len(self)):
778 for p in parentrevs(r): 779 for p in parentrevs(r):
779 if p in reachable: 780 if p in reachable:
780 if r not in stoprevs: 781 if r not in stoprevs:
781 reachable[r] = 1 782 reachable[r] = 1
782 heads[r] = 1 783 heads[r] = 1
787 788
788 def children(self, node): 789 def children(self, node):
789 """find the children of a given node""" 790 """find the children of a given node"""
790 c = [] 791 c = []
791 p = self.rev(node) 792 p = self.rev(node)
792 for r in range(p + 1, self.count()): 793 for r in range(p + 1, len(self)):
793 prevs = [pr for pr in self.parentrevs(r) if pr != nullrev] 794 prevs = [pr for pr in self.parentrevs(r) if pr != nullrev]
794 if prevs: 795 if prevs:
795 for pr in prevs: 796 for pr in prevs:
796 if pr == p: 797 if pr == p:
797 c.append(self.node(r)) 798 c.append(self.node(r))
816 # str(rev) 817 # str(rev)
817 rev = int(id) 818 rev = int(id)
818 if str(rev) != id: 819 if str(rev) != id:
819 raise ValueError 820 raise ValueError
820 if rev < 0: 821 if rev < 0:
821 rev = self.count() + rev 822 rev = len(self) + rev
822 if rev < 0 or rev >= self.count(): 823 if rev < 0 or rev >= len(self):
823 raise ValueError 824 raise ValueError
824 return self.node(rev) 825 return self.node(rev)
825 except (ValueError, OverflowError): 826 except (ValueError, OverflowError):
826 pass 827 pass
827 if len(id) == 40: 828 if len(id) == 40:
980 981
981 tr.add(self.datafile, dataoff) 982 tr.add(self.datafile, dataoff)
982 df = self.opener(self.datafile, 'w') 983 df = self.opener(self.datafile, 'w')
983 try: 984 try:
984 calc = self._io.size 985 calc = self._io.size
985 for r in xrange(self.count()): 986 for r in self:
986 start = self.start(r) + (r + 1) * calc 987 start = self.start(r) + (r + 1) * calc
987 length = self.length(r) 988 length = self.length(r)
988 fp.seek(start) 989 fp.seek(start)
989 d = fp.read(length) 990 d = fp.read(length)
990 df.write(d) 991 df.write(d)
993 994
994 fp.close() 995 fp.close()
995 fp = self.opener(self.indexfile, 'w', atomictemp=True) 996 fp = self.opener(self.indexfile, 'w', atomictemp=True)
996 self.version &= ~(REVLOGNGINLINEDATA) 997 self.version &= ~(REVLOGNGINLINEDATA)
997 self._inline = False 998 self._inline = False
998 for i in xrange(self.count()): 999 for i in self:
999 e = self._io.packentry(self.index[i], self.node, self.version, i) 1000 e = self._io.packentry(self.index[i], self.node, self.version, i)
1000 fp.write(e) 1001 fp.write(e)
1001 1002
1002 # if we don't call rename, the temp file will never replace the 1003 # if we don't call rename, the temp file will never replace the
1003 # real index 1004 # real index
1029 def _addrevision(self, text, transaction, link, p1, p2, d, ifh, dfh): 1030 def _addrevision(self, text, transaction, link, p1, p2, d, ifh, dfh):
1030 node = hash(text, p1, p2) 1031 node = hash(text, p1, p2)
1031 if node in self.nodemap: 1032 if node in self.nodemap:
1032 return node 1033 return node
1033 1034
1034 curr = self.count() 1035 curr = len(self)
1035 prev = curr - 1 1036 prev = curr - 1
1036 base = self.base(prev) 1037 base = self.base(prev)
1037 offset = self.end(prev) 1038 offset = self.end(prev)
1038 1039
1039 if curr: 1040 if curr:
1144 first delta is against its parent, which should be in our 1145 first delta is against its parent, which should be in our
1145 log, the rest are against the previous delta. 1146 log, the rest are against the previous delta.
1146 """ 1147 """
1147 1148
1148 #track the base of the current delta log 1149 #track the base of the current delta log
1149 r = self.count() 1150 r = len(self)
1150 t = r - 1 1151 t = r - 1
1151 node = None 1152 node = None
1152 1153
1153 base = prev = nullrev 1154 base = prev = nullrev
1154 start = end = textlen = 0 1155 start = end = textlen = 0
1263 1264
1264 So we truncate the revlog on the first of these revisions, and 1265 So we truncate the revlog on the first of these revisions, and
1265 trust that the caller has saved the revisions that shouldn't be 1266 trust that the caller has saved the revisions that shouldn't be
1266 removed and that it'll readd them after this truncation. 1267 removed and that it'll readd them after this truncation.
1267 """ 1268 """
1268 if self.count() == 0: 1269 if len(self) == 0:
1269 return 1270 return
1270 1271
1271 if isinstance(self.index, lazyindex): 1272 if isinstance(self.index, lazyindex):
1272 self._loadindexmap() 1273 self._loadindexmap()
1273 1274
1274 for rev in xrange(0, self.count()): 1275 for rev in self:
1275 if self.index[rev][4] >= minlink: 1276 if self.index[rev][4] >= minlink:
1276 break 1277 break
1277 else: 1278 else:
1278 return 1279 return
1279 1280
1290 indexf.truncate(end) 1291 indexf.truncate(end)
1291 1292
1292 # then reset internal state in memory to forget those revisions 1293 # then reset internal state in memory to forget those revisions
1293 self._cache = None 1294 self._cache = None
1294 self._chunkcache = None 1295 self._chunkcache = None
1295 for x in xrange(rev, self.count()): 1296 for x in xrange(rev, len(self)):
1296 del self.nodemap[self.node(x)] 1297 del self.nodemap[self.node(x)]
1297 1298
1298 del self.index[rev:-1] 1299 del self.index[rev:-1]
1299 1300
1300 def checksize(self): 1301 def checksize(self):
1301 expected = 0 1302 expected = 0
1302 if self.count(): 1303 if len(self):
1303 expected = max(0, self.end(self.count() - 1)) 1304 expected = max(0, self.end(len(self) - 1))
1304 1305
1305 try: 1306 try:
1306 f = self.opener(self.datafile) 1307 f = self.opener(self.datafile)
1307 f.seek(0, 2) 1308 f.seek(0, 2)
1308 actual = f.tell() 1309 actual = f.tell()
1319 s = self._io.size 1320 s = self._io.size
1320 i = max(0, actual / s) 1321 i = max(0, actual / s)
1321 di = actual - (i * s) 1322 di = actual - (i * s)
1322 if self._inline: 1323 if self._inline:
1323 databytes = 0 1324 databytes = 0
1324 for r in xrange(self.count()): 1325 for r in self:
1325 databytes += max(0, self.length(r)) 1326 databytes += max(0, self.length(r))
1326 dd = 0 1327 dd = 0
1327 di = actual - self.count() * s - databytes 1328 di = actual - len(self) * s - databytes
1328 except IOError, inst: 1329 except IOError, inst:
1329 if inst.errno != errno.ENOENT: 1330 if inst.errno != errno.ENOENT:
1330 raise 1331 raise
1331 di = 0 1332 di = 0
1332 1333