##// END OF EJS Templates
filelog: stop proxying start(), end(), and length() (API)...
Gregory Szorc -
r39815:42aa61fc default
parent child Browse files
Show More
@@ -1,281 +1,272 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._generaldelta = self._revlog._generaldelta
29 self._generaldelta = self._revlog._generaldelta
30
30
31 def __len__(self):
31 def __len__(self):
32 return len(self._revlog)
32 return len(self._revlog)
33
33
34 def __iter__(self):
34 def __iter__(self):
35 return self._revlog.__iter__()
35 return self._revlog.__iter__()
36
36
37 def revs(self, start=0, stop=None):
37 def revs(self, start=0, stop=None):
38 return self._revlog.revs(start=start, stop=stop)
38 return self._revlog.revs(start=start, stop=stop)
39
39
40 def parents(self, node):
40 def parents(self, node):
41 return self._revlog.parents(node)
41 return self._revlog.parents(node)
42
42
43 def parentrevs(self, rev):
43 def parentrevs(self, rev):
44 return self._revlog.parentrevs(rev)
44 return self._revlog.parentrevs(rev)
45
45
46 def rev(self, node):
46 def rev(self, node):
47 return self._revlog.rev(node)
47 return self._revlog.rev(node)
48
48
49 def node(self, rev):
49 def node(self, rev):
50 return self._revlog.node(rev)
50 return self._revlog.node(rev)
51
51
52 def lookup(self, node):
52 def lookup(self, node):
53 return self._revlog.lookup(node)
53 return self._revlog.lookup(node)
54
54
55 def linkrev(self, rev):
55 def linkrev(self, rev):
56 return self._revlog.linkrev(rev)
56 return self._revlog.linkrev(rev)
57
57
58 def flags(self, rev):
58 def flags(self, rev):
59 return self._revlog.flags(rev)
59 return self._revlog.flags(rev)
60
60
61 def commonancestorsheads(self, node1, node2):
61 def commonancestorsheads(self, node1, node2):
62 return self._revlog.commonancestorsheads(node1, node2)
62 return self._revlog.commonancestorsheads(node1, node2)
63
63
64 def descendants(self, revs):
64 def descendants(self, revs):
65 return self._revlog.descendants(revs)
65 return self._revlog.descendants(revs)
66
66
67 def headrevs(self):
67 def headrevs(self):
68 return self._revlog.headrevs()
68 return self._revlog.headrevs()
69
69
70 def heads(self, start=None, stop=None):
70 def heads(self, start=None, stop=None):
71 return self._revlog.heads(start, stop)
71 return self._revlog.heads(start, stop)
72
72
73 def children(self, node):
73 def children(self, node):
74 return self._revlog.children(node)
74 return self._revlog.children(node)
75
75
76 def deltaparent(self, rev):
76 def deltaparent(self, rev):
77 return self._revlog.deltaparent(rev)
77 return self._revlog.deltaparent(rev)
78
78
79 def iscensored(self, rev):
79 def iscensored(self, rev):
80 return self._revlog.iscensored(rev)
80 return self._revlog.iscensored(rev)
81
81
82 def rawsize(self, rev):
82 def rawsize(self, rev):
83 return self._revlog.rawsize(rev)
83 return self._revlog.rawsize(rev)
84
84
85 def checkhash(self, text, node, p1=None, p2=None, rev=None):
85 def checkhash(self, text, node, p1=None, p2=None, rev=None):
86 return self._revlog.checkhash(text, node, p1=p1, p2=p2, rev=rev)
86 return self._revlog.checkhash(text, node, p1=p1, p2=p2, rev=rev)
87
87
88 def revision(self, node, _df=None, raw=False):
88 def revision(self, node, _df=None, raw=False):
89 return self._revlog.revision(node, _df=_df, raw=raw)
89 return self._revlog.revision(node, _df=_df, raw=raw)
90
90
91 def revdiff(self, rev1, rev2):
91 def revdiff(self, rev1, rev2):
92 return self._revlog.revdiff(rev1, rev2)
92 return self._revlog.revdiff(rev1, rev2)
93
93
94 def emitrevisiondeltas(self, requests):
94 def emitrevisiondeltas(self, requests):
95 return self._revlog.emitrevisiondeltas(requests)
95 return self._revlog.emitrevisiondeltas(requests)
96
96
97 def addrevision(self, revisiondata, transaction, linkrev, p1, p2,
97 def addrevision(self, revisiondata, transaction, linkrev, p1, p2,
98 node=None, flags=revlog.REVIDX_DEFAULT_FLAGS,
98 node=None, flags=revlog.REVIDX_DEFAULT_FLAGS,
99 cachedelta=None):
99 cachedelta=None):
100 return self._revlog.addrevision(revisiondata, transaction, linkrev,
100 return self._revlog.addrevision(revisiondata, transaction, linkrev,
101 p1, p2, node=node, flags=flags,
101 p1, p2, node=node, flags=flags,
102 cachedelta=cachedelta)
102 cachedelta=cachedelta)
103
103
104 def addgroup(self, deltas, linkmapper, transaction, addrevisioncb=None):
104 def addgroup(self, deltas, linkmapper, transaction, addrevisioncb=None):
105 return self._revlog.addgroup(deltas, linkmapper, transaction,
105 return self._revlog.addgroup(deltas, linkmapper, transaction,
106 addrevisioncb=addrevisioncb)
106 addrevisioncb=addrevisioncb)
107
107
108 def getstrippoint(self, minlink):
108 def getstrippoint(self, minlink):
109 return self._revlog.getstrippoint(minlink)
109 return self._revlog.getstrippoint(minlink)
110
110
111 def strip(self, minlink, transaction):
111 def strip(self, minlink, transaction):
112 return self._revlog.strip(minlink, transaction)
112 return self._revlog.strip(minlink, transaction)
113
113
114 def censorrevision(self, tr, node, tombstone=b''):
114 def censorrevision(self, tr, node, tombstone=b''):
115 return self._revlog.censorrevision(node, tombstone=tombstone)
115 return self._revlog.censorrevision(node, tombstone=tombstone)
116
116
117 def files(self):
117 def files(self):
118 return self._revlog.files()
118 return self._revlog.files()
119
119
120 def checksize(self):
120 def checksize(self):
121 return self._revlog.checksize()
121 return self._revlog.checksize()
122
122
123 def read(self, node):
123 def read(self, node):
124 t = self.revision(node)
124 t = self.revision(node)
125 if not t.startswith('\1\n'):
125 if not t.startswith('\1\n'):
126 return t
126 return t
127 s = t.index('\1\n', 2)
127 s = t.index('\1\n', 2)
128 return t[s + 2:]
128 return t[s + 2:]
129
129
130 def add(self, text, meta, transaction, link, p1=None, p2=None):
130 def add(self, text, meta, transaction, link, p1=None, p2=None):
131 if meta or text.startswith('\1\n'):
131 if meta or text.startswith('\1\n'):
132 text = revlog.packmeta(meta, text)
132 text = revlog.packmeta(meta, text)
133 return self.addrevision(text, transaction, link, p1, p2)
133 return self.addrevision(text, transaction, link, p1, p2)
134
134
135 def renamed(self, node):
135 def renamed(self, node):
136 if self.parents(node)[0] != revlog.nullid:
136 if self.parents(node)[0] != revlog.nullid:
137 return False
137 return False
138 t = self.revision(node)
138 t = self.revision(node)
139 m = revlog.parsemeta(t)[0]
139 m = revlog.parsemeta(t)[0]
140 # copy and copyrev occur in pairs. In rare cases due to bugs,
140 # copy and copyrev occur in pairs. In rare cases due to bugs,
141 # one can occur without the other.
141 # one can occur without the other.
142 if m and "copy" in m and "copyrev" in m:
142 if m and "copy" in m and "copyrev" in m:
143 return (m["copy"], revlog.bin(m["copyrev"]))
143 return (m["copy"], revlog.bin(m["copyrev"]))
144 return False
144 return False
145
145
146 def size(self, rev):
146 def size(self, rev):
147 """return the size of a given revision"""
147 """return the size of a given revision"""
148
148
149 # for revisions with renames, we have to go the slow way
149 # for revisions with renames, we have to go the slow way
150 node = self.node(rev)
150 node = self.node(rev)
151 if self.renamed(node):
151 if self.renamed(node):
152 return len(self.read(node))
152 return len(self.read(node))
153 if self.iscensored(rev):
153 if self.iscensored(rev):
154 return 0
154 return 0
155
155
156 # XXX if self.read(node).startswith("\1\n"), this returns (size+4)
156 # XXX if self.read(node).startswith("\1\n"), this returns (size+4)
157 return self._revlog.size(rev)
157 return self._revlog.size(rev)
158
158
159 def cmp(self, node, text):
159 def cmp(self, node, text):
160 """compare text with a given file revision
160 """compare text with a given file revision
161
161
162 returns True if text is different than what is stored.
162 returns True if text is different than what is stored.
163 """
163 """
164
164
165 t = text
165 t = text
166 if text.startswith('\1\n'):
166 if text.startswith('\1\n'):
167 t = '\1\n\1\n' + text
167 t = '\1\n\1\n' + text
168
168
169 samehashes = not self._revlog.cmp(node, t)
169 samehashes = not self._revlog.cmp(node, t)
170 if samehashes:
170 if samehashes:
171 return False
171 return False
172
172
173 # censored files compare against the empty file
173 # censored files compare against the empty file
174 if self.iscensored(self.rev(node)):
174 if self.iscensored(self.rev(node)):
175 return text != ''
175 return text != ''
176
176
177 # renaming a file produces a different hash, even if the data
177 # renaming a file produces a different hash, even if the data
178 # remains unchanged. Check if it's the case (slow):
178 # remains unchanged. Check if it's the case (slow):
179 if self.renamed(node):
179 if self.renamed(node):
180 t2 = self.read(node)
180 t2 = self.read(node)
181 return t2 != text
181 return t2 != text
182
182
183 return True
183 return True
184
184
185 @property
185 @property
186 def filename(self):
186 def filename(self):
187 return self._revlog.filename
187 return self._revlog.filename
188
188
189 @filename.setter
189 @filename.setter
190 def filename(self, value):
190 def filename(self, value):
191 self._revlog.filename = value
191 self._revlog.filename = value
192
192
193 # TODO these aren't part of the interface and aren't internal methods.
193 # TODO these aren't part of the interface and aren't internal methods.
194 # Callers should be fixed to not use them.
194 # Callers should be fixed to not use them.
195 @property
195 @property
196 def indexfile(self):
196 def indexfile(self):
197 return self._revlog.indexfile
197 return self._revlog.indexfile
198
198
199 @indexfile.setter
199 @indexfile.setter
200 def indexfile(self, value):
200 def indexfile(self, value):
201 self._revlog.indexfile = value
201 self._revlog.indexfile = value
202
202
203 @property
203 @property
204 def datafile(self):
204 def datafile(self):
205 return self._revlog.datafile
205 return self._revlog.datafile
206
206
207 @property
207 @property
208 def opener(self):
208 def opener(self):
209 return self._revlog.opener
209 return self._revlog.opener
210
210
211 def clone(self, tr, destrevlog, **kwargs):
211 def clone(self, tr, destrevlog, **kwargs):
212 if not isinstance(destrevlog, filelog):
212 if not isinstance(destrevlog, filelog):
213 raise error.ProgrammingError('expected filelog to clone()')
213 raise error.ProgrammingError('expected filelog to clone()')
214
214
215 return self._revlog.clone(tr, destrevlog._revlog, **kwargs)
215 return self._revlog.clone(tr, destrevlog._revlog, **kwargs)
216
216
217 def start(self, rev):
218 return self._revlog.start(rev)
219
220 def end(self, rev):
221 return self._revlog.end(rev)
222
223 def length(self, rev):
224 return self._revlog.length(rev)
225
226 def compress(self, data):
217 def compress(self, data):
227 return self._revlog.compress(data)
218 return self._revlog.compress(data)
228
219
229 def _addrevision(self, *args, **kwargs):
220 def _addrevision(self, *args, **kwargs):
230 return self._revlog._addrevision(*args, **kwargs)
221 return self._revlog._addrevision(*args, **kwargs)
231
222
232 class narrowfilelog(filelog):
223 class narrowfilelog(filelog):
233 """Filelog variation to be used with narrow stores."""
224 """Filelog variation to be used with narrow stores."""
234
225
235 def __init__(self, opener, path, narrowmatch):
226 def __init__(self, opener, path, narrowmatch):
236 super(narrowfilelog, self).__init__(opener, path)
227 super(narrowfilelog, self).__init__(opener, path)
237 self._narrowmatch = narrowmatch
228 self._narrowmatch = narrowmatch
238
229
239 def renamed(self, node):
230 def renamed(self, node):
240 res = super(narrowfilelog, self).renamed(node)
231 res = super(narrowfilelog, self).renamed(node)
241
232
242 # Renames that come from outside the narrowspec are problematic
233 # Renames that come from outside the narrowspec are problematic
243 # because we may lack the base text for the rename. This can result
234 # because we may lack the base text for the rename. This can result
244 # in code attempting to walk the ancestry or compute a diff
235 # in code attempting to walk the ancestry or compute a diff
245 # encountering a missing revision. We address this by silently
236 # encountering a missing revision. We address this by silently
246 # removing rename metadata if the source file is outside the
237 # removing rename metadata if the source file is outside the
247 # narrow spec.
238 # narrow spec.
248 #
239 #
249 # A better solution would be to see if the base revision is available,
240 # A better solution would be to see if the base revision is available,
250 # rather than assuming it isn't.
241 # rather than assuming it isn't.
251 #
242 #
252 # An even better solution would be to teach all consumers of rename
243 # An even better solution would be to teach all consumers of rename
253 # metadata that the base revision may not be available.
244 # metadata that the base revision may not be available.
254 #
245 #
255 # TODO consider better ways of doing this.
246 # TODO consider better ways of doing this.
256 if res and not self._narrowmatch(res[0]):
247 if res and not self._narrowmatch(res[0]):
257 return None
248 return None
258
249
259 return res
250 return res
260
251
261 def size(self, rev):
252 def size(self, rev):
262 # Because we have a custom renamed() that may lie, we need to call
253 # Because we have a custom renamed() that may lie, we need to call
263 # the base renamed() to report accurate results.
254 # the base renamed() to report accurate results.
264 node = self.node(rev)
255 node = self.node(rev)
265 if super(narrowfilelog, self).renamed(node):
256 if super(narrowfilelog, self).renamed(node):
266 return len(self.read(node))
257 return len(self.read(node))
267 else:
258 else:
268 return super(narrowfilelog, self).size(rev)
259 return super(narrowfilelog, self).size(rev)
269
260
270 def cmp(self, node, text):
261 def cmp(self, node, text):
271 different = super(narrowfilelog, self).cmp(node, text)
262 different = super(narrowfilelog, self).cmp(node, text)
272
263
273 # Because renamed() may lie, we may get false positives for
264 # Because renamed() may lie, we may get false positives for
274 # different content. Check for this by comparing against the original
265 # different content. Check for this by comparing against the original
275 # renamed() implementation.
266 # renamed() implementation.
276 if different:
267 if different:
277 if super(narrowfilelog, self).renamed(node):
268 if super(narrowfilelog, self).renamed(node):
278 t2 = self.read(node)
269 t2 = self.read(node)
279 return t2 != text
270 return t2 != text
280
271
281 return different
272 return different
General Comments 0
You need to be logged in to leave comments. Login now