##// END OF EJS Templates
filelog: stop proxying datafile (API)...
Gregory Szorc -
r39818:03bedf1d default
parent child Browse files
Show More
@@ -1,266 +1,262 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):
205 return self._revlog.datafile
206
207 @property
208 def opener(self):
204 def opener(self):
209 return self._revlog.opener
205 return self._revlog.opener
210
206
211 def clone(self, tr, destrevlog, **kwargs):
207 def clone(self, tr, destrevlog, **kwargs):
212 if not isinstance(destrevlog, filelog):
208 if not isinstance(destrevlog, filelog):
213 raise error.ProgrammingError('expected filelog to clone()')
209 raise error.ProgrammingError('expected filelog to clone()')
214
210
215 return self._revlog.clone(tr, destrevlog._revlog, **kwargs)
211 return self._revlog.clone(tr, destrevlog._revlog, **kwargs)
216
212
217 class narrowfilelog(filelog):
213 class narrowfilelog(filelog):
218 """Filelog variation to be used with narrow stores."""
214 """Filelog variation to be used with narrow stores."""
219
215
220 def __init__(self, opener, path, narrowmatch):
216 def __init__(self, opener, path, narrowmatch):
221 super(narrowfilelog, self).__init__(opener, path)
217 super(narrowfilelog, self).__init__(opener, path)
222 self._narrowmatch = narrowmatch
218 self._narrowmatch = narrowmatch
223
219
224 def renamed(self, node):
220 def renamed(self, node):
225 res = super(narrowfilelog, self).renamed(node)
221 res = super(narrowfilelog, self).renamed(node)
226
222
227 # Renames that come from outside the narrowspec are problematic
223 # Renames that come from outside the narrowspec are problematic
228 # because we may lack the base text for the rename. This can result
224 # because we may lack the base text for the rename. This can result
229 # in code attempting to walk the ancestry or compute a diff
225 # in code attempting to walk the ancestry or compute a diff
230 # encountering a missing revision. We address this by silently
226 # encountering a missing revision. We address this by silently
231 # removing rename metadata if the source file is outside the
227 # removing rename metadata if the source file is outside the
232 # narrow spec.
228 # narrow spec.
233 #
229 #
234 # A better solution would be to see if the base revision is available,
230 # A better solution would be to see if the base revision is available,
235 # rather than assuming it isn't.
231 # rather than assuming it isn't.
236 #
232 #
237 # An even better solution would be to teach all consumers of rename
233 # An even better solution would be to teach all consumers of rename
238 # metadata that the base revision may not be available.
234 # metadata that the base revision may not be available.
239 #
235 #
240 # TODO consider better ways of doing this.
236 # TODO consider better ways of doing this.
241 if res and not self._narrowmatch(res[0]):
237 if res and not self._narrowmatch(res[0]):
242 return None
238 return None
243
239
244 return res
240 return res
245
241
246 def size(self, rev):
242 def size(self, rev):
247 # Because we have a custom renamed() that may lie, we need to call
243 # Because we have a custom renamed() that may lie, we need to call
248 # the base renamed() to report accurate results.
244 # the base renamed() to report accurate results.
249 node = self.node(rev)
245 node = self.node(rev)
250 if super(narrowfilelog, self).renamed(node):
246 if super(narrowfilelog, self).renamed(node):
251 return len(self.read(node))
247 return len(self.read(node))
252 else:
248 else:
253 return super(narrowfilelog, self).size(rev)
249 return super(narrowfilelog, self).size(rev)
254
250
255 def cmp(self, node, text):
251 def cmp(self, node, text):
256 different = super(narrowfilelog, self).cmp(node, text)
252 different = super(narrowfilelog, self).cmp(node, text)
257
253
258 # Because renamed() may lie, we may get false positives for
254 # Because renamed() may lie, we may get false positives for
259 # different content. Check for this by comparing against the original
255 # different content. Check for this by comparing against the original
260 # renamed() implementation.
256 # renamed() implementation.
261 if different:
257 if different:
262 if super(narrowfilelog, self).renamed(node):
258 if super(narrowfilelog, self).renamed(node):
263 t2 = self.read(node)
259 t2 = self.read(node)
264 return t2 != text
260 return t2 != text
265
261
266 return different
262 return different
General Comments 0
You need to be logged in to leave comments. Login now