annotate upmana/mercurial/revlog.py @ 39:ed322725b928 ornery-orc tip

Traipse 'OpenRPG' {110114-00} Traipse is a distribution of OpenRPG that is designed to be easy to setup and go. Traipse also makes it easy for developers to work on code without fear of sacrifice. 'Ornery-Orc' continues the trend of 'Grumpy' and adds fixes to the code. 'Ornery-Orc's main goal is to offer more advanced features and enhance the productivity of the user. Update Summary (Closed) New Features: New to Map, can re-order Grid, Miniatures, and Whiteboard layer draw order New to Server GUI, can now clear log New Earthdawn Dieroller New IronClaw roller, sheet, and image New ShapeShifter PC Sheet Updates: Update to Warhammer PC Sheet. Rollers set as macros. Should work with little maintanence. Update to Browser Server window. Display rooms with ' " & cleaner Update to Server. Handles ' " & cleaner Update to Dieroller. Cleaner, more effecient expression system Update to Hidden Die plugin, allows for non standard dice rolls Update to location.py, allows for more portable references when starting Traipse Update to the Features node Fixes: Fix to InterParse that was causing an Infernal Loop with Namespace Internal Fix to XML data, removed old Minidom and switched to Element Tree Fix to Server that was causing eternal attempt to find a Server ID, in Register Rooms thread Fix to Server, removing wxPython dependencies where not needed Fix to metaservers.xml file not being created Fix to Single and Double quotes in Whiteboard text Fix to Background images not showing when using the Image Server Fix to Duplicate chat names appearing Fix to Server GUI's logging output Fix to FNB.COLORFUL_TABS bug Fix to Gametree for XSLT Sheets Fix to Gametree for locating gametree files Fix to Send to Chat from Gametree Fix to Gametree, renaming and remapping operates correctly Fix to aliaslib, prevents error caused when SafeHTML is sent None
author sirebral
date Fri, 14 Jan 2011 05:24:52 -0600
parents ff154cf3350c
children
rev   line source
28
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1 # revlog.py - storage back-end for mercurial
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
2 #
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
4 #
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
5 # This software may be used and distributed according to the terms of the
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
6 # GNU General Public License version 2, incorporated herein by reference.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
7
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
8 """Storage back-end for Mercurial.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
9
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
10 This provides efficient delta storage with O(1) retrieve and append
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
11 and O(changes) merge between branches.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
12 """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
13
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
14 # import stuff from node for others to import from revlog
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
15 from node import bin, hex, nullid, nullrev, short #@UnusedImport
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
16 from i18n import _
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
17 import changegroup, ancestor, mdiff, parsers, error, util
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
18 import struct, zlib, errno
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
19
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
20 _pack = struct.pack
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
21 _unpack = struct.unpack
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
22 _compress = zlib.compress
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
23 _decompress = zlib.decompress
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
24 _sha = util.sha1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
25
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
26 # revlog flags
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
27 REVLOGV0 = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
28 REVLOGNG = 1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
29 REVLOGNGINLINEDATA = (1 << 16)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
30 REVLOG_DEFAULT_FLAGS = REVLOGNGINLINEDATA
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
31 REVLOG_DEFAULT_FORMAT = REVLOGNG
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
32 REVLOG_DEFAULT_VERSION = REVLOG_DEFAULT_FORMAT | REVLOG_DEFAULT_FLAGS
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
33
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
34 _prereadsize = 1048576
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
35
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
36 RevlogError = error.RevlogError
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
37 LookupError = error.LookupError
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
38
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
39 def getoffset(q):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
40 return int(q >> 16)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
41
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
42 def gettype(q):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
43 return int(q & 0xFFFF)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
44
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
45 def offset_type(offset, type):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
46 return long(long(offset) << 16 | type)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
47
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
48 nullhash = _sha(nullid)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
49
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
50 def hash(text, p1, p2):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
51 """generate a hash from the given text and its parent hashes
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
52
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
53 This hash combines both the current file contents and its history
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
54 in a manner that makes it easy to distinguish nodes with the same
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
55 content in the revision graph.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
56 """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
57 # As of now, if one of the parent node is null, p2 is null
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
58 if p2 == nullid:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
59 # deep copy of a hash is faster than creating one
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
60 s = nullhash.copy()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
61 s.update(p1)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
62 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
63 # none of the parent nodes are nullid
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
64 l = [p1, p2]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
65 l.sort()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
66 s = _sha(l[0])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
67 s.update(l[1])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
68 s.update(text)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
69 return s.digest()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
70
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
71 def compress(text):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
72 """ generate a possibly-compressed representation of text """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
73 if not text:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
74 return ("", text)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
75 l = len(text)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
76 bin = None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
77 if l < 44:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
78 pass
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
79 elif l > 1000000:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
80 # zlib makes an internal copy, thus doubling memory usage for
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
81 # large files, so lets do this in pieces
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
82 z = zlib.compressobj()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
83 p = []
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
84 pos = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
85 while pos < l:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
86 pos2 = pos + 2**20
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
87 p.append(z.compress(text[pos:pos2]))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
88 pos = pos2
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
89 p.append(z.flush())
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
90 if sum(map(len, p)) < l:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
91 bin = "".join(p)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
92 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
93 bin = _compress(text)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
94 if bin is None or len(bin) > l:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
95 if text[0] == '\0':
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
96 return ("", text)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
97 return ('u', text)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
98 return ("", bin)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
99
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
100 def decompress(bin):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
101 """ decompress the given input """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
102 if not bin:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
103 return bin
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
104 t = bin[0]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
105 if t == '\0':
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
106 return bin
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
107 if t == 'x':
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
108 return _decompress(bin)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
109 if t == 'u':
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
110 return bin[1:]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
111 raise RevlogError(_("unknown compression type %r") % t)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
112
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
113 class lazyparser(object):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
114 """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
115 this class avoids the need to parse the entirety of large indices
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
116 """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
117
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
118 # lazyparser is not safe to use on windows if win32 extensions not
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
119 # available. it keeps file handle open, which make it not possible
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
120 # to break hardlinks on local cloned repos.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
121
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
122 def __init__(self, dataf):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
123 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
124 size = util.fstat(dataf).st_size
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
125 except AttributeError:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
126 size = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
127 self.dataf = dataf
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
128 self.s = struct.calcsize(indexformatng)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
129 self.datasize = size
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
130 self.l = size/self.s
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
131 self.index = [None] * self.l
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
132 self.map = {nullid: nullrev}
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
133 self.allmap = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
134 self.all = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
135 self.mapfind_count = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
136
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
137 def loadmap(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
138 """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
139 during a commit, we need to make sure the rev being added is
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
140 not a duplicate. This requires loading the entire index,
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
141 which is fairly slow. loadmap can load up just the node map,
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
142 which takes much less time.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
143 """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
144 if self.allmap:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
145 return
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
146 end = self.datasize
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
147 self.allmap = 1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
148 cur = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
149 count = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
150 blocksize = self.s * 256
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
151 self.dataf.seek(0)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
152 while cur < end:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
153 data = self.dataf.read(blocksize)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
154 off = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
155 for x in xrange(256):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
156 n = data[off + ngshaoffset:off + ngshaoffset + 20]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
157 self.map[n] = count
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
158 count += 1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
159 if count >= self.l:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
160 break
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
161 off += self.s
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
162 cur += blocksize
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
163
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
164 def loadblock(self, blockstart, blocksize, data=None):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
165 if self.all:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
166 return
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
167 if data is None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
168 self.dataf.seek(blockstart)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
169 if blockstart + blocksize > self.datasize:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
170 # the revlog may have grown since we've started running,
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
171 # but we don't have space in self.index for more entries.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
172 # limit blocksize so that we don't get too much data.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
173 blocksize = max(self.datasize - blockstart, 0)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
174 data = self.dataf.read(blocksize)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
175 lend = len(data) / self.s
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
176 i = blockstart / self.s
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
177 off = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
178 # lazyindex supports __delitem__
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
179 if lend > len(self.index) - i:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
180 lend = len(self.index) - i
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
181 for x in xrange(lend):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
182 if self.index[i + x] is None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
183 b = data[off : off + self.s]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
184 self.index[i + x] = b
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
185 n = b[ngshaoffset:ngshaoffset + 20]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
186 self.map[n] = i + x
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
187 off += self.s
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
188
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
189 def findnode(self, node):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
190 """search backwards through the index file for a specific node"""
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
191 if self.allmap:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
192 return None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
193
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
194 # hg log will cause many many searches for the manifest
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
195 # nodes. After we get called a few times, just load the whole
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
196 # thing.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
197 if self.mapfind_count > 8:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
198 self.loadmap()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
199 if node in self.map:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
200 return node
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
201 return None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
202 self.mapfind_count += 1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
203 last = self.l - 1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
204 while self.index[last] != None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
205 if last == 0:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
206 self.all = 1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
207 self.allmap = 1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
208 return None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
209 last -= 1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
210 end = (last + 1) * self.s
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
211 blocksize = self.s * 256
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
212 while end >= 0:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
213 start = max(end - blocksize, 0)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
214 self.dataf.seek(start)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
215 data = self.dataf.read(end - start)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
216 findend = end - start
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
217 while True:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
218 # we're searching backwards, so we have to make sure
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
219 # we don't find a changeset where this node is a parent
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
220 off = data.find(node, 0, findend)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
221 findend = off
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
222 if off >= 0:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
223 i = off / self.s
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
224 off = i * self.s
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
225 n = data[off + ngshaoffset:off + ngshaoffset + 20]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
226 if n == node:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
227 self.map[n] = i + start / self.s
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
228 return node
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
229 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
230 break
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
231 end -= blocksize
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
232 return None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
233
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
234 def loadindex(self, i=None, end=None):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
235 if self.all:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
236 return
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
237 all = False
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
238 if i is None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
239 blockstart = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
240 blocksize = (65536 / self.s) * self.s
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
241 end = self.datasize
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
242 all = True
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
243 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
244 if end:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
245 blockstart = i * self.s
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
246 end = end * self.s
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
247 blocksize = end - blockstart
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
248 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
249 blockstart = (i & ~1023) * self.s
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
250 blocksize = self.s * 1024
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
251 end = blockstart + blocksize
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
252 while blockstart < end:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
253 self.loadblock(blockstart, blocksize)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
254 blockstart += blocksize
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
255 if all:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
256 self.all = True
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
257
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
258 class lazyindex(object):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
259 """a lazy version of the index array"""
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
260 def __init__(self, parser):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
261 self.p = parser
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
262 def __len__(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
263 return len(self.p.index)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
264 def load(self, pos):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
265 if pos < 0:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
266 pos += len(self.p.index)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
267 self.p.loadindex(pos)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
268 return self.p.index[pos]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
269 def __getitem__(self, pos):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
270 return _unpack(indexformatng, self.p.index[pos] or self.load(pos))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
271 def __setitem__(self, pos, item):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
272 self.p.index[pos] = _pack(indexformatng, *item)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
273 def __delitem__(self, pos):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
274 del self.p.index[pos]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
275 def insert(self, pos, e):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
276 self.p.index.insert(pos, _pack(indexformatng, *e))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
277 def append(self, e):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
278 self.p.index.append(_pack(indexformatng, *e))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
279
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
280 class lazymap(object):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
281 """a lazy version of the node map"""
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
282 def __init__(self, parser):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
283 self.p = parser
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
284 def load(self, key):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
285 n = self.p.findnode(key)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
286 if n is None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
287 raise KeyError(key)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
288 def __contains__(self, key):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
289 if key in self.p.map:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
290 return True
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
291 self.p.loadmap()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
292 return key in self.p.map
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
293 def __iter__(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
294 yield nullid
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
295 for i in xrange(self.p.l):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
296 ret = self.p.index[i]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
297 if not ret:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
298 self.p.loadindex(i)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
299 ret = self.p.index[i]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
300 if isinstance(ret, str):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
301 ret = _unpack(indexformatng, ret)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
302 yield ret[7]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
303 def __getitem__(self, key):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
304 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
305 return self.p.map[key]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
306 except KeyError:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
307 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
308 self.load(key)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
309 return self.p.map[key]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
310 except KeyError:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
311 raise KeyError("node " + hex(key))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
312 def __setitem__(self, key, val):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
313 self.p.map[key] = val
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
314 def __delitem__(self, key):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
315 del self.p.map[key]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
316
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
317 indexformatv0 = ">4l20s20s20s"
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
318 v0shaoffset = 56
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
319
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
320 class revlogoldio(object):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
321 def __init__(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
322 self.size = struct.calcsize(indexformatv0)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
323
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
324 def parseindex(self, fp, data, inline):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
325 s = self.size
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
326 index = []
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
327 nodemap = {nullid: nullrev}
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
328 n = off = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
329 if len(data) == _prereadsize:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
330 data += fp.read() # read the rest
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
331 l = len(data)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
332 while off + s <= l:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
333 cur = data[off:off + s]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
334 off += s
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
335 e = _unpack(indexformatv0, cur)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
336 # transform to revlogv1 format
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
337 e2 = (offset_type(e[0], 0), e[1], -1, e[2], e[3],
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
338 nodemap.get(e[4], nullrev), nodemap.get(e[5], nullrev), e[6])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
339 index.append(e2)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
340 nodemap[e[6]] = n
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
341 n += 1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
342
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
343 return index, nodemap, None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
344
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
345 def packentry(self, entry, node, version, rev):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
346 e2 = (getoffset(entry[0]), entry[1], entry[3], entry[4],
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
347 node(entry[5]), node(entry[6]), entry[7])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
348 return _pack(indexformatv0, *e2)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
349
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
350 # index ng:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
351 # 6 bytes offset
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
352 # 2 bytes flags
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
353 # 4 bytes compressed length
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
354 # 4 bytes uncompressed length
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
355 # 4 bytes: base rev
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
356 # 4 bytes link rev
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
357 # 4 bytes parent 1 rev
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
358 # 4 bytes parent 2 rev
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
359 # 32 bytes: nodeid
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
360 indexformatng = ">Qiiiiii20s12x"
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
361 ngshaoffset = 32
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
362 versionformat = ">I"
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
363
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
364 class revlogio(object):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
365 def __init__(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
366 self.size = struct.calcsize(indexformatng)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
367
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
368 def parseindex(self, fp, data, inline):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
369 if len(data) == _prereadsize:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
370 if util.openhardlinks() and not inline:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
371 # big index, let's parse it on demand
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
372 parser = lazyparser(fp)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
373 index = lazyindex(parser)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
374 nodemap = lazymap(parser)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
375 e = list(index[0])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
376 type = gettype(e[0])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
377 e[0] = offset_type(0, type)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
378 index[0] = e
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
379 return index, nodemap, None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
380 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
381 data += fp.read()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
382
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
383 # call the C implementation to parse the index data
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
384 index, nodemap, cache = parsers.parse_index(data, inline)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
385 return index, nodemap, cache
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
386
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
387 def packentry(self, entry, node, version, rev):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
388 p = _pack(indexformatng, *entry)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
389 if rev == 0:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
390 p = _pack(versionformat, version) + p[4:]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
391 return p
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
392
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
393 class revlog(object):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
394 """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
395 the underlying revision storage object
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
396
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
397 A revlog consists of two parts, an index and the revision data.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
398
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
399 The index is a file with a fixed record size containing
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
400 information on each revision, including its nodeid (hash), the
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
401 nodeids of its parents, the position and offset of its data within
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
402 the data file, and the revision it's based on. Finally, each entry
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
403 contains a linkrev entry that can serve as a pointer to external
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
404 data.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
405
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
406 The revision data itself is a linear collection of data chunks.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
407 Each chunk represents a revision and is usually represented as a
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
408 delta against the previous chunk. To bound lookup time, runs of
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
409 deltas are limited to about 2 times the length of the original
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
410 version data. This makes retrieval of a version proportional to
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
411 its size, or O(1) relative to the number of revisions.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
412
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
413 Both pieces of the revlog are written to in an append-only
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
414 fashion, which means we never need to rewrite a file to insert or
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
415 remove data, and can use some simple techniques to avoid the need
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
416 for locking while reading.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
417 """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
418 def __init__(self, opener, indexfile):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
419 """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
420 create a revlog object
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
421
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
422 opener is a function that abstracts the file opening operation
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
423 and can be used to implement COW semantics or the like.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
424 """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
425 self.indexfile = indexfile
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
426 self.datafile = indexfile[:-2] + ".d"
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
427 self.opener = opener
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
428 self._cache = None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
429 self._chunkcache = (0, '')
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
430 self.nodemap = {nullid: nullrev}
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
431 self.index = []
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
432
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
433 v = REVLOG_DEFAULT_VERSION
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
434 if hasattr(opener, "defversion"):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
435 v = opener.defversion
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
436 if v & REVLOGNG:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
437 v |= REVLOGNGINLINEDATA
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
438
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
439 i = ''
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
440 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
441 f = self.opener(self.indexfile)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
442 i = f.read(_prereadsize)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
443 if len(i) > 0:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
444 v = struct.unpack(versionformat, i[:4])[0]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
445 except IOError, inst:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
446 if inst.errno != errno.ENOENT:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
447 raise
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
448
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
449 self.version = v
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
450 self._inline = v & REVLOGNGINLINEDATA
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
451 flags = v & ~0xFFFF
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
452 fmt = v & 0xFFFF
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
453 if fmt == REVLOGV0 and flags:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
454 raise RevlogError(_("index %s unknown flags %#04x for format v0")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
455 % (self.indexfile, flags >> 16))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
456 elif fmt == REVLOGNG and flags & ~REVLOGNGINLINEDATA:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
457 raise RevlogError(_("index %s unknown flags %#04x for revlogng")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
458 % (self.indexfile, flags >> 16))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
459 elif fmt > REVLOGNG:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
460 raise RevlogError(_("index %s unknown format %d")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
461 % (self.indexfile, fmt))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
462
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
463 self._io = revlogio()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
464 if self.version == REVLOGV0:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
465 self._io = revlogoldio()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
466 if i:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
467 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
468 d = self._io.parseindex(f, i, self._inline)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
469 except (ValueError, IndexError), e:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
470 raise RevlogError(_("index %s is corrupted") % (self.indexfile))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
471 self.index, self.nodemap, self._chunkcache = d
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
472 if not self._chunkcache:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
473 self._chunkclear()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
474
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
475 # add the magic null revision at -1 (if it hasn't been done already)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
476 if (self.index == [] or isinstance(self.index, lazyindex) or
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
477 self.index[-1][7] != nullid) :
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
478 self.index.append((0, 0, 0, -1, -1, -1, -1, nullid))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
479
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
480 def _loadindex(self, start, end):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
481 """load a block of indexes all at once from the lazy parser"""
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
482 if isinstance(self.index, lazyindex):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
483 self.index.p.loadindex(start, end)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
484
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
485 def _loadindexmap(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
486 """loads both the map and the index from the lazy parser"""
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
487 if isinstance(self.index, lazyindex):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
488 p = self.index.p
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
489 p.loadindex()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
490 self.nodemap = p.map
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
491
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
492 def _loadmap(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
493 """loads the map from the lazy parser"""
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
494 if isinstance(self.nodemap, lazymap):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
495 self.nodemap.p.loadmap()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
496 self.nodemap = self.nodemap.p.map
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
497
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
498 def tip(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
499 return self.node(len(self.index) - 2)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
500 def __len__(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
501 return len(self.index) - 1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
502 def __iter__(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
503 for i in xrange(len(self)):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
504 yield i
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
505 def rev(self, node):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
506 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
507 return self.nodemap[node]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
508 except KeyError:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
509 raise LookupError(node, self.indexfile, _('no node'))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
510 def node(self, rev):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
511 return self.index[rev][7]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
512 def linkrev(self, rev):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
513 return self.index[rev][4]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
514 def parents(self, node):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
515 i = self.index
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
516 d = i[self.rev(node)]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
517 return i[d[5]][7], i[d[6]][7] # map revisions to nodes inline
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
518 def parentrevs(self, rev):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
519 return self.index[rev][5:7]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
520 def start(self, rev):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
521 return int(self.index[rev][0] >> 16)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
522 def end(self, rev):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
523 return self.start(rev) + self.length(rev)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
524 def length(self, rev):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
525 return self.index[rev][1]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
526 def base(self, rev):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
527 return self.index[rev][3]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
528
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
529 def size(self, rev):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
530 """return the length of the uncompressed text for a given revision"""
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
531 l = self.index[rev][2]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
532 if l >= 0:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
533 return l
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
534
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
535 t = self.revision(self.node(rev))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
536 return len(t)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
537
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
538 # Alternate implementation. The advantage to this code is it
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
539 # will be faster for a single revision. However, the results
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
540 # are not cached, so finding the size of every revision will
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
541 # be slower.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
542 #
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
543 # if self.cache and self.cache[1] == rev:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
544 # return len(self.cache[2])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
545 #
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
546 # base = self.base(rev)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
547 # if self.cache and self.cache[1] >= base and self.cache[1] < rev:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
548 # base = self.cache[1]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
549 # text = self.cache[2]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
550 # else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
551 # text = self.revision(self.node(base))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
552 #
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
553 # l = len(text)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
554 # for x in xrange(base + 1, rev + 1):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
555 # l = mdiff.patchedsize(l, self._chunk(x))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
556 # return l
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
557
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
558 def reachable(self, node, stop=None):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
559 """return the set of all nodes ancestral to a given node, including
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
560 the node itself, stopping when stop is matched"""
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
561 reachable = set((node,))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
562 visit = [node]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
563 if stop:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
564 stopn = self.rev(stop)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
565 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
566 stopn = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
567 while visit:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
568 n = visit.pop(0)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
569 if n == stop:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
570 continue
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
571 if n == nullid:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
572 continue
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
573 for p in self.parents(n):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
574 if self.rev(p) < stopn:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
575 continue
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
576 if p not in reachable:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
577 reachable.add(p)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
578 visit.append(p)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
579 return reachable
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
580
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
581 def ancestors(self, *revs):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
582 'Generate the ancestors of revs using a breadth-first visit'
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
583 visit = list(revs)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
584 seen = set([nullrev])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
585 while visit:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
586 for parent in self.parentrevs(visit.pop(0)):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
587 if parent not in seen:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
588 visit.append(parent)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
589 seen.add(parent)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
590 yield parent
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
591
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
592 def descendants(self, *revs):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
593 'Generate the descendants of revs in topological order'
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
594 seen = set(revs)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
595 for i in xrange(min(revs) + 1, len(self)):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
596 for x in self.parentrevs(i):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
597 if x != nullrev and x in seen:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
598 seen.add(i)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
599 yield i
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
600 break
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
601
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
602 def findmissing(self, common=None, heads=None):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
603 '''
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
604 returns the topologically sorted list of nodes from the set:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
605 missing = (ancestors(heads) \ ancestors(common))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
606
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
607 where ancestors() is the set of ancestors from heads, heads included
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
608
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
609 if heads is None, the heads of the revlog are used
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
610 if common is None, nullid is assumed to be a common node
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
611 '''
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
612 if common is None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
613 common = [nullid]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
614 if heads is None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
615 heads = self.heads()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
616
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
617 common = [self.rev(n) for n in common]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
618 heads = [self.rev(n) for n in heads]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
619
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
620 # we want the ancestors, but inclusive
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
621 has = set(self.ancestors(*common))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
622 has.add(nullrev)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
623 has.update(common)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
624
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
625 # take all ancestors from heads that aren't in has
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
626 missing = set()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
627 visit = [r for r in heads if r not in has]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
628 while visit:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
629 r = visit.pop(0)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
630 if r in missing:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
631 continue
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
632 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
633 missing.add(r)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
634 for p in self.parentrevs(r):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
635 if p not in has:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
636 visit.append(p)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
637 missing = list(missing)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
638 missing.sort()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
639 return [self.node(r) for r in missing]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
640
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
641 def nodesbetween(self, roots=None, heads=None):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
642 """Return a tuple containing three elements. Elements 1 and 2 contain
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
643 a final list bases and heads after all the unreachable ones have been
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
644 pruned. Element 0 contains a topologically sorted list of all
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
645
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
646 nodes that satisfy these constraints:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
647 1. All nodes must be descended from a node in roots (the nodes on
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
648 roots are considered descended from themselves).
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
649 2. All nodes must also be ancestors of a node in heads (the nodes in
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
650 heads are considered to be their own ancestors).
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
651
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
652 If roots is unspecified, nullid is assumed as the only root.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
653 If heads is unspecified, it is taken to be the output of the
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
654 heads method (i.e. a list of all nodes in the repository that
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
655 have no children)."""
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
656 nonodes = ([], [], [])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
657 if roots is not None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
658 roots = list(roots)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
659 if not roots:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
660 return nonodes
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
661 lowestrev = min([self.rev(n) for n in roots])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
662 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
663 roots = [nullid] # Everybody's a descendent of nullid
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
664 lowestrev = nullrev
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
665 if (lowestrev == nullrev) and (heads is None):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
666 # We want _all_ the nodes!
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
667 return ([self.node(r) for r in self], [nullid], list(self.heads()))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
668 if heads is None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
669 # All nodes are ancestors, so the latest ancestor is the last
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
670 # node.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
671 highestrev = len(self) - 1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
672 # Set ancestors to None to signal that every node is an ancestor.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
673 ancestors = None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
674 # Set heads to an empty dictionary for later discovery of heads
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
675 heads = {}
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
676 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
677 heads = list(heads)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
678 if not heads:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
679 return nonodes
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
680 ancestors = set()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
681 # Turn heads into a dictionary so we can remove 'fake' heads.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
682 # Also, later we will be using it to filter out the heads we can't
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
683 # find from roots.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
684 heads = dict.fromkeys(heads, 0)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
685 # Start at the top and keep marking parents until we're done.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
686 nodestotag = set(heads)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
687 # Remember where the top was so we can use it as a limit later.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
688 highestrev = max([self.rev(n) for n in nodestotag])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
689 while nodestotag:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
690 # grab a node to tag
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
691 n = nodestotag.pop()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
692 # Never tag nullid
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
693 if n == nullid:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
694 continue
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
695 # A node's revision number represents its place in a
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
696 # topologically sorted list of nodes.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
697 r = self.rev(n)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
698 if r >= lowestrev:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
699 if n not in ancestors:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
700 # If we are possibly a descendent of one of the roots
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
701 # and we haven't already been marked as an ancestor
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
702 ancestors.add(n) # Mark as ancestor
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
703 # Add non-nullid parents to list of nodes to tag.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
704 nodestotag.update([p for p in self.parents(n) if
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
705 p != nullid])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
706 elif n in heads: # We've seen it before, is it a fake head?
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
707 # So it is, real heads should not be the ancestors of
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
708 # any other heads.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
709 heads.pop(n)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
710 if not ancestors:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
711 return nonodes
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
712 # Now that we have our set of ancestors, we want to remove any
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
713 # roots that are not ancestors.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
714
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
715 # If one of the roots was nullid, everything is included anyway.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
716 if lowestrev > nullrev:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
717 # But, since we weren't, let's recompute the lowest rev to not
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
718 # include roots that aren't ancestors.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
719
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
720 # Filter out roots that aren't ancestors of heads
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
721 roots = [n for n in roots if n in ancestors]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
722 # Recompute the lowest revision
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
723 if roots:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
724 lowestrev = min([self.rev(n) for n in roots])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
725 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
726 # No more roots? Return empty list
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
727 return nonodes
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
728 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
729 # We are descending from nullid, and don't need to care about
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
730 # any other roots.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
731 lowestrev = nullrev
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
732 roots = [nullid]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
733 # Transform our roots list into a set.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
734 descendents = set(roots)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
735 # Also, keep the original roots so we can filter out roots that aren't
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
736 # 'real' roots (i.e. are descended from other roots).
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
737 roots = descendents.copy()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
738 # Our topologically sorted list of output nodes.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
739 orderedout = []
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
740 # Don't start at nullid since we don't want nullid in our output list,
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
741 # and if nullid shows up in descedents, empty parents will look like
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
742 # they're descendents.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
743 for r in xrange(max(lowestrev, 0), highestrev + 1):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
744 n = self.node(r)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
745 isdescendent = False
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
746 if lowestrev == nullrev: # Everybody is a descendent of nullid
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
747 isdescendent = True
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
748 elif n in descendents:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
749 # n is already a descendent
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
750 isdescendent = True
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
751 # This check only needs to be done here because all the roots
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
752 # will start being marked is descendents before the loop.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
753 if n in roots:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
754 # If n was a root, check if it's a 'real' root.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
755 p = tuple(self.parents(n))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
756 # If any of its parents are descendents, it's not a root.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
757 if (p[0] in descendents) or (p[1] in descendents):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
758 roots.remove(n)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
759 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
760 p = tuple(self.parents(n))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
761 # A node is a descendent if either of its parents are
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
762 # descendents. (We seeded the dependents list with the roots
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
763 # up there, remember?)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
764 if (p[0] in descendents) or (p[1] in descendents):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
765 descendents.add(n)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
766 isdescendent = True
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
767 if isdescendent and ((ancestors is None) or (n in ancestors)):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
768 # Only include nodes that are both descendents and ancestors.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
769 orderedout.append(n)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
770 if (ancestors is not None) and (n in heads):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
771 # We're trying to figure out which heads are reachable
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
772 # from roots.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
773 # Mark this head as having been reached
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
774 heads[n] = 1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
775 elif ancestors is None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
776 # Otherwise, we're trying to discover the heads.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
777 # Assume this is a head because if it isn't, the next step
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
778 # will eventually remove it.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
779 heads[n] = 1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
780 # But, obviously its parents aren't.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
781 for p in self.parents(n):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
782 heads.pop(p, None)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
783 heads = [n for n in heads.iterkeys() if heads[n] != 0]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
784 roots = list(roots)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
785 assert orderedout
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
786 assert roots
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
787 assert heads
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
788 return (orderedout, roots, heads)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
789
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
790 def heads(self, start=None, stop=None):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
791 """return the list of all nodes that have no children
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
792
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
793 if start is specified, only heads that are descendants of
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
794 start will be returned
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
795 if stop is specified, it will consider all the revs from stop
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
796 as if they had no children
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
797 """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
798 if start is None and stop is None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
799 count = len(self)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
800 if not count:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
801 return [nullid]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
802 ishead = [1] * (count + 1)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
803 index = self.index
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
804 for r in xrange(count):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
805 e = index[r]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
806 ishead[e[5]] = ishead[e[6]] = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
807 return [self.node(r) for r in xrange(count) if ishead[r]]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
808
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
809 if start is None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
810 start = nullid
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
811 if stop is None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
812 stop = []
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
813 stoprevs = set([self.rev(n) for n in stop])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
814 startrev = self.rev(start)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
815 reachable = set((startrev,))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
816 heads = set((startrev,))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
817
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
818 parentrevs = self.parentrevs
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
819 for r in xrange(startrev + 1, len(self)):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
820 for p in parentrevs(r):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
821 if p in reachable:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
822 if r not in stoprevs:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
823 reachable.add(r)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
824 heads.add(r)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
825 if p in heads and p not in stoprevs:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
826 heads.remove(p)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
827
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
828 return [self.node(r) for r in heads]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
829
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
830 def children(self, node):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
831 """find the children of a given node"""
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
832 c = []
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
833 p = self.rev(node)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
834 for r in range(p + 1, len(self)):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
835 prevs = [pr for pr in self.parentrevs(r) if pr != nullrev]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
836 if prevs:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
837 for pr in prevs:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
838 if pr == p:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
839 c.append(self.node(r))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
840 elif p == nullrev:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
841 c.append(self.node(r))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
842 return c
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
843
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
844 def _match(self, id):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
845 if isinstance(id, (long, int)):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
846 # rev
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
847 return self.node(id)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
848 if len(id) == 20:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
849 # possibly a binary node
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
850 # odds of a binary node being all hex in ASCII are 1 in 10**25
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
851 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
852 node = id
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
853 self.rev(node) # quick search the index
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
854 return node
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
855 except LookupError:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
856 pass # may be partial hex id
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
857 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
858 # str(rev)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
859 rev = int(id)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
860 if str(rev) != id:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
861 raise ValueError
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
862 if rev < 0:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
863 rev = len(self) + rev
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
864 if rev < 0 or rev >= len(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
865 raise ValueError
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
866 return self.node(rev)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
867 except (ValueError, OverflowError):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
868 pass
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
869 if len(id) == 40:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
870 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
871 # a full hex nodeid?
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
872 node = bin(id)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
873 self.rev(node)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
874 return node
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
875 except (TypeError, LookupError):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
876 pass
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
877
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
878 def _partialmatch(self, id):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
879 if len(id) < 40:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
880 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
881 # hex(node)[:...]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
882 l = len(id) / 2 # grab an even number of digits
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
883 bin_id = bin(id[:l*2])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
884 nl = [n for n in self.nodemap if n[:l] == bin_id]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
885 nl = [n for n in nl if hex(n).startswith(id)]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
886 if len(nl) > 0:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
887 if len(nl) == 1:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
888 return nl[0]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
889 raise LookupError(id, self.indexfile,
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
890 _('ambiguous identifier'))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
891 return None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
892 except TypeError:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
893 pass
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
894
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
895 def lookup(self, id):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
896 """locate a node based on:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
897 - revision number or str(revision number)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
898 - nodeid or subset of hex nodeid
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
899 """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
900 n = self._match(id)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
901 if n is not None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
902 return n
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
903 n = self._partialmatch(id)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
904 if n:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
905 return n
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
906
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
907 raise LookupError(id, self.indexfile, _('no match found'))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
908
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
909 def cmp(self, node, text):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
910 """compare text with a given file revision"""
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
911 p1, p2 = self.parents(node)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
912 return hash(text, p1, p2) != node
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
913
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
914 def _addchunk(self, offset, data):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
915 o, d = self._chunkcache
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
916 # try to add to existing cache
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
917 if o + len(d) == offset and len(d) + len(data) < _prereadsize:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
918 self._chunkcache = o, d + data
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
919 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
920 self._chunkcache = offset, data
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
921
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
922 def _loadchunk(self, offset, length):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
923 if self._inline:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
924 df = self.opener(self.indexfile)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
925 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
926 df = self.opener(self.datafile)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
927
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
928 readahead = max(65536, length)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
929 df.seek(offset)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
930 d = df.read(readahead)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
931 self._addchunk(offset, d)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
932 if readahead > length:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
933 return d[:length]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
934 return d
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
935
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
936 def _getchunk(self, offset, length):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
937 o, d = self._chunkcache
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
938 l = len(d)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
939
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
940 # is it in the cache?
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
941 cachestart = offset - o
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
942 cacheend = cachestart + length
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
943 if cachestart >= 0 and cacheend <= l:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
944 if cachestart == 0 and cacheend == l:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
945 return d # avoid a copy
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
946 return d[cachestart:cacheend]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
947
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
948 return self._loadchunk(offset, length)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
949
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
950 def _chunkraw(self, startrev, endrev):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
951 start = self.start(startrev)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
952 length = self.end(endrev) - start
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
953 if self._inline:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
954 start += (startrev + 1) * self._io.size
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
955 return self._getchunk(start, length)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
956
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
957 def _chunk(self, rev):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
958 return decompress(self._chunkraw(rev, rev))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
959
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
960 def _chunkclear(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
961 self._chunkcache = (0, '')
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
962
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
963 def revdiff(self, rev1, rev2):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
964 """return or calculate a delta between two revisions"""
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
965 if rev1 + 1 == rev2 and self.base(rev1) == self.base(rev2):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
966 return self._chunk(rev2)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
967
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
968 return mdiff.textdiff(self.revision(self.node(rev1)),
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
969 self.revision(self.node(rev2)))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
970
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
971 def revision(self, node):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
972 """return an uncompressed revision of a given node"""
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
973 if node == nullid:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
974 return ""
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
975 if self._cache and self._cache[0] == node:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
976 return str(self._cache[2])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
977
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
978 # look up what we need to read
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
979 text = None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
980 rev = self.rev(node)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
981 base = self.base(rev)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
982
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
983 # check rev flags
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
984 if self.index[rev][0] & 0xFFFF:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
985 raise RevlogError(_('incompatible revision flag %x') %
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
986 (self.index[rev][0] & 0xFFFF))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
987
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
988 # do we have useful data cached?
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
989 if self._cache and self._cache[1] >= base and self._cache[1] < rev:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
990 base = self._cache[1]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
991 text = str(self._cache[2])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
992
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
993 self._loadindex(base, rev + 1)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
994 self._chunkraw(base, rev)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
995 if text is None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
996 text = self._chunk(base)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
997
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
998 bins = [self._chunk(r) for r in xrange(base + 1, rev + 1)]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
999 text = mdiff.patches(text, bins)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1000 p1, p2 = self.parents(node)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1001 if node != hash(text, p1, p2):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1002 raise RevlogError(_("integrity check failed on %s:%d")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1003 % (self.indexfile, rev))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1004
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1005 self._cache = (node, rev, text)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1006 return text
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1007
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1008 def checkinlinesize(self, tr, fp=None):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1009 if not self._inline or (self.start(-2) + self.length(-2)) < 131072:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1010 return
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1011
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1012 trinfo = tr.find(self.indexfile)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1013 if trinfo is None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1014 raise RevlogError(_("%s not found in the transaction")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1015 % self.indexfile)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1016
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1017 trindex = trinfo[2]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1018 dataoff = self.start(trindex)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1019
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1020 tr.add(self.datafile, dataoff)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1021
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1022 if fp:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1023 fp.flush()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1024 fp.close()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1025
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1026 df = self.opener(self.datafile, 'w')
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1027 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1028 for r in self:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1029 df.write(self._chunkraw(r, r))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1030 finally:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1031 df.close()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1032
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1033 fp = self.opener(self.indexfile, 'w', atomictemp=True)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1034 self.version &= ~(REVLOGNGINLINEDATA)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1035 self._inline = False
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1036 for i in self:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1037 e = self._io.packentry(self.index[i], self.node, self.version, i)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1038 fp.write(e)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1039
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1040 # if we don't call rename, the temp file will never replace the
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1041 # real index
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1042 fp.rename()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1043
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1044 tr.replace(self.indexfile, trindex * self._io.size)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1045 self._chunkclear()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1046
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1047 def addrevision(self, text, transaction, link, p1, p2, d=None):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1048 """add a revision to the log
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1049
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1050 text - the revision data to add
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1051 transaction - the transaction object used for rollback
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1052 link - the linkrev data to add
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1053 p1, p2 - the parent nodeids of the revision
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1054 d - an optional precomputed delta
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1055 """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1056 dfh = None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1057 if not self._inline:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1058 dfh = self.opener(self.datafile, "a")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1059 ifh = self.opener(self.indexfile, "a+")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1060 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1061 return self._addrevision(text, transaction, link, p1, p2, d, ifh, dfh)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1062 finally:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1063 if dfh:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1064 dfh.close()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1065 ifh.close()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1066
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1067 def _addrevision(self, text, transaction, link, p1, p2, d, ifh, dfh):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1068 node = hash(text, p1, p2)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1069 if node in self.nodemap:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1070 return node
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1071
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1072 curr = len(self)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1073 prev = curr - 1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1074 base = self.base(prev)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1075 offset = self.end(prev)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1076
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1077 if curr:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1078 if not d:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1079 ptext = self.revision(self.node(prev))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1080 d = mdiff.textdiff(ptext, text)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1081 data = compress(d)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1082 l = len(data[1]) + len(data[0])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1083 dist = l + offset - self.start(base)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1084
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1085 # full versions are inserted when the needed deltas
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1086 # become comparable to the uncompressed text
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1087 if not curr or dist > len(text) * 2:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1088 data = compress(text)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1089 l = len(data[1]) + len(data[0])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1090 base = curr
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1091
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1092 e = (offset_type(offset, 0), l, len(text),
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1093 base, link, self.rev(p1), self.rev(p2), node)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1094 self.index.insert(-1, e)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1095 self.nodemap[node] = curr
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1096
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1097 entry = self._io.packentry(e, self.node, self.version, curr)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1098 if not self._inline:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1099 transaction.add(self.datafile, offset)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1100 transaction.add(self.indexfile, curr * len(entry))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1101 if data[0]:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1102 dfh.write(data[0])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1103 dfh.write(data[1])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1104 dfh.flush()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1105 ifh.write(entry)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1106 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1107 offset += curr * self._io.size
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1108 transaction.add(self.indexfile, offset, curr)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1109 ifh.write(entry)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1110 ifh.write(data[0])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1111 ifh.write(data[1])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1112 self.checkinlinesize(transaction, ifh)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1113
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1114 self._cache = (node, curr, text)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1115 return node
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1116
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1117 def ancestor(self, a, b):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1118 """calculate the least common ancestor of nodes a and b"""
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1119
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1120 def parents(rev):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1121 return [p for p in self.parentrevs(rev) if p != nullrev]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1122
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1123 c = ancestor.ancestor(self.rev(a), self.rev(b), parents)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1124 if c is None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1125 return nullid
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1126
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1127 return self.node(c)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1128
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1129 def group(self, nodelist, lookup, infocollect=None):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1130 """calculate a delta group
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1131
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1132 Given a list of changeset revs, return a set of deltas and
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1133 metadata corresponding to nodes. the first delta is
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1134 parent(nodes[0]) -> nodes[0] the receiver is guaranteed to
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1135 have this parent as it has all history before these
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1136 changesets. parent is parent[0]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1137 """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1138
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1139 revs = [self.rev(n) for n in nodelist]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1140
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1141 # if we don't have any revisions touched by these changesets, bail
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1142 if not revs:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1143 yield changegroup.closechunk()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1144 return
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1145
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1146 # add the parent of the first rev
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1147 p = self.parentrevs(revs[0])[0]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1148 revs.insert(0, p)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1149
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1150 # build deltas
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1151 for d in xrange(len(revs) - 1):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1152 a, b = revs[d], revs[d + 1]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1153 nb = self.node(b)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1154
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1155 if infocollect is not None:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1156 infocollect(nb)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1157
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1158 p = self.parents(nb)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1159 meta = nb + p[0] + p[1] + lookup(nb)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1160 if a == -1:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1161 d = self.revision(nb)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1162 meta += mdiff.trivialdiffheader(len(d))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1163 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1164 d = self.revdiff(a, b)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1165 yield changegroup.chunkheader(len(meta) + len(d))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1166 yield meta
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1167 if len(d) > 2**20:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1168 pos = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1169 while pos < len(d):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1170 pos2 = pos + 2 ** 18
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1171 yield d[pos:pos2]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1172 pos = pos2
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1173 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1174 yield d
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1175
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1176 yield changegroup.closechunk()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1177
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1178 def addgroup(self, revs, linkmapper, transaction):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1179 """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1180 add a delta group
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1181
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1182 given a set of deltas, add them to the revision log. the
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1183 first delta is against its parent, which should be in our
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1184 log, the rest are against the previous delta.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1185 """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1186
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1187 #track the base of the current delta log
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1188 r = len(self)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1189 t = r - 1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1190 node = None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1191
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1192 base = prev = nullrev
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1193 start = end = textlen = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1194 if r:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1195 end = self.end(t)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1196
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1197 ifh = self.opener(self.indexfile, "a+")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1198 isize = r * self._io.size
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1199 if self._inline:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1200 transaction.add(self.indexfile, end + isize, r)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1201 dfh = None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1202 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1203 transaction.add(self.indexfile, isize, r)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1204 transaction.add(self.datafile, end)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1205 dfh = self.opener(self.datafile, "a")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1206
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1207 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1208 # loop through our set of deltas
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1209 chain = None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1210 for chunk in revs:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1211 node, p1, p2, cs = struct.unpack("20s20s20s20s", chunk[:80])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1212 link = linkmapper(cs)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1213 if node in self.nodemap:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1214 # this can happen if two branches make the same change
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1215 chain = node
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1216 continue
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1217 delta = buffer(chunk, 80)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1218 del chunk
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1219
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1220 for p in (p1, p2):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1221 if not p in self.nodemap:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1222 raise LookupError(p, self.indexfile, _('unknown parent'))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1223
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1224 if not chain:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1225 # retrieve the parent revision of the delta chain
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1226 chain = p1
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1227 if not chain in self.nodemap:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1228 raise LookupError(chain, self.indexfile, _('unknown base'))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1229
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1230 # full versions are inserted when the needed deltas become
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1231 # comparable to the uncompressed text or when the previous
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1232 # version is not the one we have a delta against. We use
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1233 # the size of the previous full rev as a proxy for the
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1234 # current size.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1235
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1236 if chain == prev:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1237 cdelta = compress(delta)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1238 cdeltalen = len(cdelta[0]) + len(cdelta[1])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1239 textlen = mdiff.patchedsize(textlen, delta)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1240
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1241 if chain != prev or (end - start + cdeltalen) > textlen * 2:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1242 # flush our writes here so we can read it in revision
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1243 if dfh:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1244 dfh.flush()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1245 ifh.flush()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1246 text = self.revision(chain)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1247 if len(text) == 0:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1248 # skip over trivial delta header
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1249 text = buffer(delta, 12)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1250 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1251 text = mdiff.patches(text, [delta])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1252 del delta
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1253 chk = self._addrevision(text, transaction, link, p1, p2, None,
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1254 ifh, dfh)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1255 if not dfh and not self._inline:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1256 # addrevision switched from inline to conventional
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1257 # reopen the index
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1258 dfh = self.opener(self.datafile, "a")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1259 ifh = self.opener(self.indexfile, "a")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1260 if chk != node:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1261 raise RevlogError(_("consistency error adding group"))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1262 textlen = len(text)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1263 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1264 e = (offset_type(end, 0), cdeltalen, textlen, base,
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1265 link, self.rev(p1), self.rev(p2), node)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1266 self.index.insert(-1, e)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1267 self.nodemap[node] = r
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1268 entry = self._io.packentry(e, self.node, self.version, r)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1269 if self._inline:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1270 ifh.write(entry)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1271 ifh.write(cdelta[0])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1272 ifh.write(cdelta[1])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1273 self.checkinlinesize(transaction, ifh)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1274 if not self._inline:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1275 dfh = self.opener(self.datafile, "a")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1276 ifh = self.opener(self.indexfile, "a")
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1277 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1278 dfh.write(cdelta[0])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1279 dfh.write(cdelta[1])
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1280 ifh.write(entry)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1281
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1282 t, r, chain, prev = r, r + 1, node, node
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1283 base = self.base(t)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1284 start = self.start(base)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1285 end = self.end(t)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1286 finally:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1287 if dfh:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1288 dfh.close()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1289 ifh.close()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1290
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1291 return node
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1292
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1293 def strip(self, minlink, transaction):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1294 """truncate the revlog on the first revision with a linkrev >= minlink
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1295
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1296 This function is called when we're stripping revision minlink and
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1297 its descendants from the repository.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1298
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1299 We have to remove all revisions with linkrev >= minlink, because
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1300 the equivalent changelog revisions will be renumbered after the
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1301 strip.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1302
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1303 So we truncate the revlog on the first of these revisions, and
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1304 trust that the caller has saved the revisions that shouldn't be
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1305 removed and that it'll readd them after this truncation.
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1306 """
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1307 if len(self) == 0:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1308 return
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1309
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1310 if isinstance(self.index, lazyindex):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1311 self._loadindexmap()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1312
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1313 for rev in self:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1314 if self.index[rev][4] >= minlink:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1315 break
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1316 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1317 return
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1318
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1319 # first truncate the files on disk
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1320 end = self.start(rev)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1321 if not self._inline:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1322 transaction.add(self.datafile, end)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1323 end = rev * self._io.size
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1324 else:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1325 end += rev * self._io.size
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1326
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1327 transaction.add(self.indexfile, end)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1328
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1329 # then reset internal state in memory to forget those revisions
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1330 self._cache = None
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1331 self._chunkclear()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1332 for x in xrange(rev, len(self)):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1333 del self.nodemap[self.node(x)]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1334
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1335 del self.index[rev:-1]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1336
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1337 def checksize(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1338 expected = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1339 if len(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1340 expected = max(0, self.end(len(self) - 1))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1341
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1342 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1343 f = self.opener(self.datafile)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1344 f.seek(0, 2)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1345 actual = f.tell()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1346 dd = actual - expected
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1347 except IOError, inst:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1348 if inst.errno != errno.ENOENT:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1349 raise
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1350 dd = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1351
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1352 try:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1353 f = self.opener(self.indexfile)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1354 f.seek(0, 2)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1355 actual = f.tell()
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1356 s = self._io.size
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1357 i = max(0, actual / s)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1358 di = actual - (i * s)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1359 if self._inline:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1360 databytes = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1361 for r in self:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1362 databytes += max(0, self.length(r))
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1363 dd = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1364 di = actual - len(self) * s - databytes
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1365 except IOError, inst:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1366 if inst.errno != errno.ENOENT:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1367 raise
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1368 di = 0
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1369
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1370 return (dd, di)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1371
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1372 def files(self):
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1373 res = [ self.indexfile ]
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1374 if not self._inline:
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1375 res.append(self.datafile)
ff154cf3350c Traipse 'OpenRPG' {100203-00}
sirebral
parents:
diff changeset
1376 return res