##// END OF EJS Templates
typing: make the filelog class known to pytype...
Matt Harbison -
r52715:e78b75f3 default
parent child Browse files
Show More
@@ -1,312 +1,319
1 # filelog.py - file history class for mercurial
1 # filelog.py - file history class for mercurial
2 #
2 #
3 # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
3 # Copyright 2005-2007 Olivia Mackall <olivia@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
8
9 import typing
10
9 from .i18n import _
11 from .i18n import _
10 from .node import nullrev
12 from .node import nullrev
11 from . import (
13 from . import (
12 error,
14 error,
13 revlog,
15 revlog,
14 )
16 )
15 from .interfaces import (
17 from .interfaces import (
16 repository,
18 repository,
17 util as interfaceutil,
19 util as interfaceutil,
18 )
20 )
19 from .utils import storageutil
21 from .utils import storageutil
20 from .revlogutils import (
22 from .revlogutils import (
21 constants as revlog_constants,
23 constants as revlog_constants,
22 rewrite,
24 rewrite,
23 )
25 )
24
26
25
27
26 @interfaceutil.implementer(repository.ifilestorage)
28 class FileLog:
27 class filelog:
28 def __init__(self, opener, path, try_split=False):
29 def __init__(self, opener, path, try_split=False):
29 self._revlog = revlog.revlog(
30 self._revlog = revlog.revlog(
30 opener,
31 opener,
31 # XXX should use the unencoded path
32 # XXX should use the unencoded path
32 target=(revlog_constants.KIND_FILELOG, path),
33 target=(revlog_constants.KIND_FILELOG, path),
33 radix=b'/'.join((b'data', path)),
34 radix=b'/'.join((b'data', path)),
34 censorable=True,
35 censorable=True,
35 canonical_parent_order=False, # see comment in revlog.py
36 canonical_parent_order=False, # see comment in revlog.py
36 try_split=try_split,
37 try_split=try_split,
37 )
38 )
38 # Full name of the user visible file, relative to the repository root.
39 # Full name of the user visible file, relative to the repository root.
39 # Used by LFS.
40 # Used by LFS.
40 self._revlog.filename = path
41 self._revlog.filename = path
41 self.nullid = self._revlog.nullid
42 self.nullid = self._revlog.nullid
42 opts = opener.options
43 opts = opener.options
43 self._fix_issue6528 = opts.get(b'issue6528.fix-incoming', True)
44 self._fix_issue6528 = opts.get(b'issue6528.fix-incoming', True)
44
45
45 def get_revlog(self):
46 def get_revlog(self):
46 """return an actual revlog instance if any
47 """return an actual revlog instance if any
47
48
48 This exist because a lot of code leverage the fact the underlying
49 This exist because a lot of code leverage the fact the underlying
49 storage is a revlog for optimization, so giving simple way to access
50 storage is a revlog for optimization, so giving simple way to access
50 the revlog instance helps such code.
51 the revlog instance helps such code.
51 """
52 """
52 return self._revlog
53 return self._revlog
53
54
54 def __len__(self):
55 def __len__(self):
55 return len(self._revlog)
56 return len(self._revlog)
56
57
57 def __iter__(self):
58 def __iter__(self):
58 return self._revlog.__iter__()
59 return self._revlog.__iter__()
59
60
60 def hasnode(self, node):
61 def hasnode(self, node):
61 if node in (self.nullid, nullrev):
62 if node in (self.nullid, nullrev):
62 return False
63 return False
63
64
64 try:
65 try:
65 self._revlog.rev(node)
66 self._revlog.rev(node)
66 return True
67 return True
67 except (TypeError, ValueError, IndexError, error.LookupError):
68 except (TypeError, ValueError, IndexError, error.LookupError):
68 return False
69 return False
69
70
70 def revs(self, start=0, stop=None):
71 def revs(self, start=0, stop=None):
71 return self._revlog.revs(start=start, stop=stop)
72 return self._revlog.revs(start=start, stop=stop)
72
73
73 def parents(self, node):
74 def parents(self, node):
74 return self._revlog.parents(node)
75 return self._revlog.parents(node)
75
76
76 def parentrevs(self, rev):
77 def parentrevs(self, rev):
77 return self._revlog.parentrevs(rev)
78 return self._revlog.parentrevs(rev)
78
79
79 def rev(self, node):
80 def rev(self, node):
80 return self._revlog.rev(node)
81 return self._revlog.rev(node)
81
82
82 def node(self, rev):
83 def node(self, rev):
83 return self._revlog.node(rev)
84 return self._revlog.node(rev)
84
85
85 def lookup(self, node):
86 def lookup(self, node):
86 return storageutil.fileidlookup(
87 return storageutil.fileidlookup(
87 self._revlog, node, self._revlog.display_id
88 self._revlog, node, self._revlog.display_id
88 )
89 )
89
90
90 def linkrev(self, rev):
91 def linkrev(self, rev):
91 return self._revlog.linkrev(rev)
92 return self._revlog.linkrev(rev)
92
93
93 def commonancestorsheads(self, node1, node2):
94 def commonancestorsheads(self, node1, node2):
94 return self._revlog.commonancestorsheads(node1, node2)
95 return self._revlog.commonancestorsheads(node1, node2)
95
96
96 # Used by dagop.blockdescendants().
97 # Used by dagop.blockdescendants().
97 def descendants(self, revs):
98 def descendants(self, revs):
98 return self._revlog.descendants(revs)
99 return self._revlog.descendants(revs)
99
100
100 def heads(self, start=None, stop=None):
101 def heads(self, start=None, stop=None):
101 return self._revlog.heads(start, stop)
102 return self._revlog.heads(start, stop)
102
103
103 # Used by hgweb, children extension.
104 # Used by hgweb, children extension.
104 def children(self, node):
105 def children(self, node):
105 return self._revlog.children(node)
106 return self._revlog.children(node)
106
107
107 def iscensored(self, rev):
108 def iscensored(self, rev):
108 return self._revlog.iscensored(rev)
109 return self._revlog.iscensored(rev)
109
110
110 def revision(self, node):
111 def revision(self, node):
111 return self._revlog.revision(node)
112 return self._revlog.revision(node)
112
113
113 def rawdata(self, node):
114 def rawdata(self, node):
114 return self._revlog.rawdata(node)
115 return self._revlog.rawdata(node)
115
116
116 def emitrevisions(
117 def emitrevisions(
117 self,
118 self,
118 nodes,
119 nodes,
119 nodesorder=None,
120 nodesorder=None,
120 revisiondata=False,
121 revisiondata=False,
121 assumehaveparentrevisions=False,
122 assumehaveparentrevisions=False,
122 deltamode=repository.CG_DELTAMODE_STD,
123 deltamode=repository.CG_DELTAMODE_STD,
123 sidedata_helpers=None,
124 sidedata_helpers=None,
124 debug_info=None,
125 debug_info=None,
125 ):
126 ):
126 return self._revlog.emitrevisions(
127 return self._revlog.emitrevisions(
127 nodes,
128 nodes,
128 nodesorder=nodesorder,
129 nodesorder=nodesorder,
129 revisiondata=revisiondata,
130 revisiondata=revisiondata,
130 assumehaveparentrevisions=assumehaveparentrevisions,
131 assumehaveparentrevisions=assumehaveparentrevisions,
131 deltamode=deltamode,
132 deltamode=deltamode,
132 sidedata_helpers=sidedata_helpers,
133 sidedata_helpers=sidedata_helpers,
133 debug_info=debug_info,
134 debug_info=debug_info,
134 )
135 )
135
136
136 def addrevision(
137 def addrevision(
137 self,
138 self,
138 revisiondata,
139 revisiondata,
139 transaction,
140 transaction,
140 linkrev,
141 linkrev,
141 p1,
142 p1,
142 p2,
143 p2,
143 node=None,
144 node=None,
144 flags=revlog.REVIDX_DEFAULT_FLAGS,
145 flags=revlog.REVIDX_DEFAULT_FLAGS,
145 cachedelta=None,
146 cachedelta=None,
146 ):
147 ):
147 return self._revlog.addrevision(
148 return self._revlog.addrevision(
148 revisiondata,
149 revisiondata,
149 transaction,
150 transaction,
150 linkrev,
151 linkrev,
151 p1,
152 p1,
152 p2,
153 p2,
153 node=node,
154 node=node,
154 flags=flags,
155 flags=flags,
155 cachedelta=cachedelta,
156 cachedelta=cachedelta,
156 )
157 )
157
158
158 def addgroup(
159 def addgroup(
159 self,
160 self,
160 deltas,
161 deltas,
161 linkmapper,
162 linkmapper,
162 transaction,
163 transaction,
163 addrevisioncb=None,
164 addrevisioncb=None,
164 duplicaterevisioncb=None,
165 duplicaterevisioncb=None,
165 maybemissingparents=False,
166 maybemissingparents=False,
166 debug_info=None,
167 debug_info=None,
167 delta_base_reuse_policy=None,
168 delta_base_reuse_policy=None,
168 ):
169 ):
169 if maybemissingparents:
170 if maybemissingparents:
170 raise error.Abort(
171 raise error.Abort(
171 _(
172 _(
172 b'revlog storage does not support missing '
173 b'revlog storage does not support missing '
173 b'parents write mode'
174 b'parents write mode'
174 )
175 )
175 )
176 )
176
177
177 with self._revlog._writing(transaction):
178 with self._revlog._writing(transaction):
178 if self._fix_issue6528:
179 if self._fix_issue6528:
179 deltas = rewrite.filter_delta_issue6528(self._revlog, deltas)
180 deltas = rewrite.filter_delta_issue6528(self._revlog, deltas)
180
181
181 return self._revlog.addgroup(
182 return self._revlog.addgroup(
182 deltas,
183 deltas,
183 linkmapper,
184 linkmapper,
184 transaction,
185 transaction,
185 addrevisioncb=addrevisioncb,
186 addrevisioncb=addrevisioncb,
186 duplicaterevisioncb=duplicaterevisioncb,
187 duplicaterevisioncb=duplicaterevisioncb,
187 debug_info=debug_info,
188 debug_info=debug_info,
188 delta_base_reuse_policy=delta_base_reuse_policy,
189 delta_base_reuse_policy=delta_base_reuse_policy,
189 )
190 )
190
191
191 def getstrippoint(self, minlink):
192 def getstrippoint(self, minlink):
192 return self._revlog.getstrippoint(minlink)
193 return self._revlog.getstrippoint(minlink)
193
194
194 def strip(self, minlink, transaction):
195 def strip(self, minlink, transaction):
195 return self._revlog.strip(minlink, transaction)
196 return self._revlog.strip(minlink, transaction)
196
197
197 def censorrevision(self, tr, node, tombstone=b''):
198 def censorrevision(self, tr, node, tombstone=b''):
198 return self._revlog.censorrevision(tr, node, tombstone=tombstone)
199 return self._revlog.censorrevision(tr, node, tombstone=tombstone)
199
200
200 def files(self):
201 def files(self):
201 return self._revlog.files()
202 return self._revlog.files()
202
203
203 def read(self, node):
204 def read(self, node):
204 return storageutil.filtermetadata(self.revision(node))
205 return storageutil.filtermetadata(self.revision(node))
205
206
206 def add(self, text, meta, transaction, link, p1=None, p2=None):
207 def add(self, text, meta, transaction, link, p1=None, p2=None):
207 if meta or text.startswith(b'\1\n'):
208 if meta or text.startswith(b'\1\n'):
208 text = storageutil.packmeta(meta, text)
209 text = storageutil.packmeta(meta, text)
209 rev = self.addrevision(text, transaction, link, p1, p2)
210 rev = self.addrevision(text, transaction, link, p1, p2)
210 return self.node(rev)
211 return self.node(rev)
211
212
212 def renamed(self, node):
213 def renamed(self, node):
213 return storageutil.filerevisioncopied(self, node)
214 return storageutil.filerevisioncopied(self, node)
214
215
215 def size(self, rev):
216 def size(self, rev):
216 """return the size of a given revision"""
217 """return the size of a given revision"""
217
218
218 # for revisions with renames, we have to go the slow way
219 # for revisions with renames, we have to go the slow way
219 node = self.node(rev)
220 node = self.node(rev)
220 if self.iscensored(rev):
221 if self.iscensored(rev):
221 return 0
222 return 0
222 if self.renamed(node):
223 if self.renamed(node):
223 return len(self.read(node))
224 return len(self.read(node))
224
225
225 # XXX if self.read(node).startswith("\1\n"), this returns (size+4)
226 # XXX if self.read(node).startswith("\1\n"), this returns (size+4)
226 # XXX See also basefilectx.cmp.
227 # XXX See also basefilectx.cmp.
227 return self._revlog.size(rev)
228 return self._revlog.size(rev)
228
229
229 def cmp(self, node, text):
230 def cmp(self, node, text):
230 """compare text with a given file revision
231 """compare text with a given file revision
231
232
232 returns True if text is different than what is stored.
233 returns True if text is different than what is stored.
233 """
234 """
234 return not storageutil.filedataequivalent(self, node, text)
235 return not storageutil.filedataequivalent(self, node, text)
235
236
236 def verifyintegrity(self, state):
237 def verifyintegrity(self, state):
237 return self._revlog.verifyintegrity(state)
238 return self._revlog.verifyintegrity(state)
238
239
239 def storageinfo(
240 def storageinfo(
240 self,
241 self,
241 exclusivefiles=False,
242 exclusivefiles=False,
242 sharedfiles=False,
243 sharedfiles=False,
243 revisionscount=False,
244 revisionscount=False,
244 trackedsize=False,
245 trackedsize=False,
245 storedsize=False,
246 storedsize=False,
246 ):
247 ):
247 return self._revlog.storageinfo(
248 return self._revlog.storageinfo(
248 exclusivefiles=exclusivefiles,
249 exclusivefiles=exclusivefiles,
249 sharedfiles=sharedfiles,
250 sharedfiles=sharedfiles,
250 revisionscount=revisionscount,
251 revisionscount=revisionscount,
251 trackedsize=trackedsize,
252 trackedsize=trackedsize,
252 storedsize=storedsize,
253 storedsize=storedsize,
253 )
254 )
254
255
255 # Used by repo upgrade.
256 # Used by repo upgrade.
256 def clone(self, tr, destrevlog, **kwargs):
257 def clone(self, tr, destrevlog, **kwargs):
257 if not isinstance(destrevlog, filelog):
258 if not isinstance(destrevlog, filelog):
258 msg = b'expected filelog to clone(), not %r'
259 msg = b'expected filelog to clone(), not %r'
259 msg %= destrevlog
260 msg %= destrevlog
260 raise error.ProgrammingError(msg)
261 raise error.ProgrammingError(msg)
261
262
262 return self._revlog.clone(tr, destrevlog._revlog, **kwargs)
263 return self._revlog.clone(tr, destrevlog._revlog, **kwargs)
263
264
264
265
266 filelog = interfaceutil.implementer(repository.ifilestorage)(FileLog)
267
268 if typing.TYPE_CHECKING:
269 filelog = FileLog
270
271
265 class narrowfilelog(filelog):
272 class narrowfilelog(filelog):
266 """Filelog variation to be used with narrow stores."""
273 """Filelog variation to be used with narrow stores."""
267
274
268 def __init__(self, opener, path, narrowmatch, try_split=False):
275 def __init__(self, opener, path, narrowmatch, try_split=False):
269 super(narrowfilelog, self).__init__(opener, path, try_split=try_split)
276 super(narrowfilelog, self).__init__(opener, path, try_split=try_split)
270 self._narrowmatch = narrowmatch
277 self._narrowmatch = narrowmatch
271
278
272 def renamed(self, node):
279 def renamed(self, node):
273 res = super(narrowfilelog, self).renamed(node)
280 res = super(narrowfilelog, self).renamed(node)
274
281
275 # Renames that come from outside the narrowspec are problematic
282 # Renames that come from outside the narrowspec are problematic
276 # because we may lack the base text for the rename. This can result
283 # because we may lack the base text for the rename. This can result
277 # in code attempting to walk the ancestry or compute a diff
284 # in code attempting to walk the ancestry or compute a diff
278 # encountering a missing revision. We address this by silently
285 # encountering a missing revision. We address this by silently
279 # removing rename metadata if the source file is outside the
286 # removing rename metadata if the source file is outside the
280 # narrow spec.
287 # narrow spec.
281 #
288 #
282 # A better solution would be to see if the base revision is available,
289 # A better solution would be to see if the base revision is available,
283 # rather than assuming it isn't.
290 # rather than assuming it isn't.
284 #
291 #
285 # An even better solution would be to teach all consumers of rename
292 # An even better solution would be to teach all consumers of rename
286 # metadata that the base revision may not be available.
293 # metadata that the base revision may not be available.
287 #
294 #
288 # TODO consider better ways of doing this.
295 # TODO consider better ways of doing this.
289 if res and not self._narrowmatch(res[0]):
296 if res and not self._narrowmatch(res[0]):
290 return None
297 return None
291
298
292 return res
299 return res
293
300
294 def size(self, rev):
301 def size(self, rev):
295 # Because we have a custom renamed() that may lie, we need to call
302 # Because we have a custom renamed() that may lie, we need to call
296 # the base renamed() to report accurate results.
303 # the base renamed() to report accurate results.
297 node = self.node(rev)
304 node = self.node(rev)
298 if super(narrowfilelog, self).renamed(node):
305 if super(narrowfilelog, self).renamed(node):
299 return len(self.read(node))
306 return len(self.read(node))
300 else:
307 else:
301 return super(narrowfilelog, self).size(rev)
308 return super(narrowfilelog, self).size(rev)
302
309
303 def cmp(self, node, text):
310 def cmp(self, node, text):
304 # We don't call `super` because narrow parents can be buggy in case of a
311 # We don't call `super` because narrow parents can be buggy in case of a
305 # ambiguous dirstate. Always take the slow path until there is a better
312 # ambiguous dirstate. Always take the slow path until there is a better
306 # fix, see issue6150.
313 # fix, see issue6150.
307
314
308 # Censored files compare against the empty file.
315 # Censored files compare against the empty file.
309 if self.iscensored(self.rev(node)):
316 if self.iscensored(self.rev(node)):
310 return text != b''
317 return text != b''
311
318
312 return self.read(node) != text
319 return self.read(node) != text
General Comments 0
You need to be logged in to leave comments. Login now