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