##// END OF EJS Templates
filelog: don't crash on invalid copy metadata (issue5748)...
Gregory Szorc -
r38091:6614cac5 4.6 stable
parent child Browse files
Show More
@@ -1,267 +1,269 b''
1 1 # filelog.py - file history class for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 from . import (
11 11 error,
12 12 repository,
13 13 revlog,
14 14 )
15 15 from .utils import (
16 16 interfaceutil,
17 17 )
18 18
19 19 @interfaceutil.implementer(repository.ifilestorage)
20 20 class filelog(object):
21 21 def __init__(self, opener, path):
22 22 self._revlog = revlog.revlog(opener,
23 23 '/'.join(('data', path + '.i')),
24 24 censorable=True)
25 25 # full name of the user visible file, relative to the repository root
26 26 self.filename = path
27 27 self.index = self._revlog.index
28 28 self.version = self._revlog.version
29 29 self.storedeltachains = self._revlog.storedeltachains
30 30 self._generaldelta = self._revlog._generaldelta
31 31
32 32 def __len__(self):
33 33 return len(self._revlog)
34 34
35 35 def __iter__(self):
36 36 return self._revlog.__iter__()
37 37
38 38 def revs(self, start=0, stop=None):
39 39 return self._revlog.revs(start=start, stop=stop)
40 40
41 41 def parents(self, node):
42 42 return self._revlog.parents(node)
43 43
44 44 def parentrevs(self, rev):
45 45 return self._revlog.parentrevs(rev)
46 46
47 47 def rev(self, node):
48 48 return self._revlog.rev(node)
49 49
50 50 def node(self, rev):
51 51 return self._revlog.node(rev)
52 52
53 53 def lookup(self, node):
54 54 return self._revlog.lookup(node)
55 55
56 56 def linkrev(self, rev):
57 57 return self._revlog.linkrev(rev)
58 58
59 59 def flags(self, rev):
60 60 return self._revlog.flags(rev)
61 61
62 62 def commonancestorsheads(self, node1, node2):
63 63 return self._revlog.commonancestorsheads(node1, node2)
64 64
65 65 def descendants(self, revs):
66 66 return self._revlog.descendants(revs)
67 67
68 68 def headrevs(self):
69 69 return self._revlog.headrevs()
70 70
71 71 def heads(self, start=None, stop=None):
72 72 return self._revlog.heads(start, stop)
73 73
74 74 def children(self, node):
75 75 return self._revlog.children(node)
76 76
77 77 def deltaparent(self, rev):
78 78 return self._revlog.deltaparent(rev)
79 79
80 80 def candelta(self, baserev, rev):
81 81 return self._revlog.candelta(baserev, rev)
82 82
83 83 def iscensored(self, rev):
84 84 return self._revlog.iscensored(rev)
85 85
86 86 def rawsize(self, rev):
87 87 return self._revlog.rawsize(rev)
88 88
89 89 def checkhash(self, text, node, p1=None, p2=None, rev=None):
90 90 return self._revlog.checkhash(text, node, p1=p1, p2=p2, rev=rev)
91 91
92 92 def revision(self, node, _df=None, raw=False):
93 93 return self._revlog.revision(node, _df=_df, raw=raw)
94 94
95 95 def revdiff(self, rev1, rev2):
96 96 return self._revlog.revdiff(rev1, rev2)
97 97
98 98 def addrevision(self, revisiondata, transaction, linkrev, p1, p2,
99 99 node=None, flags=revlog.REVIDX_DEFAULT_FLAGS,
100 100 cachedelta=None):
101 101 return self._revlog.addrevision(revisiondata, transaction, linkrev,
102 102 p1, p2, node=node, flags=flags,
103 103 cachedelta=cachedelta)
104 104
105 105 def addgroup(self, deltas, linkmapper, transaction, addrevisioncb=None):
106 106 return self._revlog.addgroup(deltas, linkmapper, transaction,
107 107 addrevisioncb=addrevisioncb)
108 108
109 109 def getstrippoint(self, minlink):
110 110 return self._revlog.getstrippoint(minlink)
111 111
112 112 def strip(self, minlink, transaction):
113 113 return self._revlog.strip(minlink, transaction)
114 114
115 115 def files(self):
116 116 return self._revlog.files()
117 117
118 118 def checksize(self):
119 119 return self._revlog.checksize()
120 120
121 121 def read(self, node):
122 122 t = self.revision(node)
123 123 if not t.startswith('\1\n'):
124 124 return t
125 125 s = t.index('\1\n', 2)
126 126 return t[s + 2:]
127 127
128 128 def add(self, text, meta, transaction, link, p1=None, p2=None):
129 129 if meta or text.startswith('\1\n'):
130 130 text = revlog.packmeta(meta, text)
131 131 return self.addrevision(text, transaction, link, p1, p2)
132 132
133 133 def renamed(self, node):
134 134 if self.parents(node)[0] != revlog.nullid:
135 135 return False
136 136 t = self.revision(node)
137 137 m = revlog.parsemeta(t)[0]
138 if m and "copy" in m:
138 # copy and copyrev occur in pairs. In rare cases due to bugs,
139 # one can occur without the other.
140 if m and "copy" in m and "copyrev" in m:
139 141 return (m["copy"], revlog.bin(m["copyrev"]))
140 142 return False
141 143
142 144 def size(self, rev):
143 145 """return the size of a given revision"""
144 146
145 147 # for revisions with renames, we have to go the slow way
146 148 node = self.node(rev)
147 149 if self.renamed(node):
148 150 return len(self.read(node))
149 151 if self.iscensored(rev):
150 152 return 0
151 153
152 154 # XXX if self.read(node).startswith("\1\n"), this returns (size+4)
153 155 return self._revlog.size(rev)
154 156
155 157 def cmp(self, node, text):
156 158 """compare text with a given file revision
157 159
158 160 returns True if text is different than what is stored.
159 161 """
160 162
161 163 t = text
162 164 if text.startswith('\1\n'):
163 165 t = '\1\n\1\n' + text
164 166
165 167 samehashes = not self._revlog.cmp(node, t)
166 168 if samehashes:
167 169 return False
168 170
169 171 # censored files compare against the empty file
170 172 if self.iscensored(self.rev(node)):
171 173 return text != ''
172 174
173 175 # renaming a file produces a different hash, even if the data
174 176 # remains unchanged. Check if it's the case (slow):
175 177 if self.renamed(node):
176 178 t2 = self.read(node)
177 179 return t2 != text
178 180
179 181 return True
180 182
181 183 @property
182 184 def filename(self):
183 185 return self._revlog.filename
184 186
185 187 @filename.setter
186 188 def filename(self, value):
187 189 self._revlog.filename = value
188 190
189 191 # TODO these aren't part of the interface and aren't internal methods.
190 192 # Callers should be fixed to not use them.
191 193 @property
192 194 def indexfile(self):
193 195 return self._revlog.indexfile
194 196
195 197 @indexfile.setter
196 198 def indexfile(self, value):
197 199 self._revlog.indexfile = value
198 200
199 201 @property
200 202 def datafile(self):
201 203 return self._revlog.datafile
202 204
203 205 @property
204 206 def opener(self):
205 207 return self._revlog.opener
206 208
207 209 @property
208 210 def _lazydeltabase(self):
209 211 return self._revlog._lazydeltabase
210 212
211 213 @_lazydeltabase.setter
212 214 def _lazydeltabase(self, value):
213 215 self._revlog._lazydeltabase = value
214 216
215 217 @property
216 218 def _aggressivemergedeltas(self):
217 219 return self._revlog._aggressivemergedeltas
218 220
219 221 @_aggressivemergedeltas.setter
220 222 def _aggressivemergedeltas(self, value):
221 223 self._revlog._aggressivemergedeltas = value
222 224
223 225 @property
224 226 def _inline(self):
225 227 return self._revlog._inline
226 228
227 229 @property
228 230 def _withsparseread(self):
229 231 return getattr(self._revlog, '_withsparseread', False)
230 232
231 233 @property
232 234 def _srmingapsize(self):
233 235 return self._revlog._srmingapsize
234 236
235 237 @property
236 238 def _srdensitythreshold(self):
237 239 return self._revlog._srdensitythreshold
238 240
239 241 def _deltachain(self, rev, stoprev=None):
240 242 return self._revlog._deltachain(rev, stoprev)
241 243
242 244 def chainbase(self, rev):
243 245 return self._revlog.chainbase(rev)
244 246
245 247 def chainlen(self, rev):
246 248 return self._revlog.chainlen(rev)
247 249
248 250 def clone(self, tr, destrevlog, **kwargs):
249 251 if not isinstance(destrevlog, filelog):
250 252 raise error.ProgrammingError('expected filelog to clone()')
251 253
252 254 return self._revlog.clone(tr, destrevlog._revlog, **kwargs)
253 255
254 256 def start(self, rev):
255 257 return self._revlog.start(rev)
256 258
257 259 def end(self, rev):
258 260 return self._revlog.end(rev)
259 261
260 262 def length(self, rev):
261 263 return self._revlog.length(rev)
262 264
263 265 def compress(self, data):
264 266 return self._revlog.compress(data)
265 267
266 268 def _addrevision(self, *args, **kwargs):
267 269 return self._revlog._addrevision(*args, **kwargs)
General Comments 0
You need to be logged in to leave comments. Login now