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