##// END OF EJS Templates
revlog: introduce an explicit tracking of what the revlog is about...
marmoute -
r47838:4c041c71 default
parent child Browse files
Show More
@@ -13,6 +13,10 b' from mercurial import ('
13 13 )
14 14 from mercurial.utils import procutil
15 15
16 from mercurial.revlogutils import (
17 constants as revlog_constants,
18 )
19
16 20 for fp in (sys.stdin, sys.stdout, sys.stderr):
17 21 procutil.setbinary(fp)
18 22
@@ -32,7 +36,11 b" def printb(data, end=b'\\n'):"
32 36
33 37
34 38 for f in sys.argv[1:]:
35 r = revlog.revlog(binopen, encoding.strtolocal(f))
39 r = revlog.revlog(
40 binopen,
41 target=(revlog_constants.KIND_OTHER, b'dump-revlog'),
42 indexfile=encoding.strtolocal(f),
43 )
36 44 print("file:", f)
37 45 for i in r:
38 46 n = r.node(i)
@@ -66,6 +66,8 b' import sys'
66 66 import tempfile
67 67 import threading
68 68 import time
69
70 import mercurial.revlog
69 71 from mercurial import (
70 72 changegroup,
71 73 cmdutil,
@@ -76,7 +78,6 b' from mercurial import ('
76 78 hg,
77 79 mdiff,
78 80 merge,
79 revlog,
80 81 util,
81 82 )
82 83
@@ -119,6 +120,21 b' try:'
119 120 except ImportError:
120 121 profiling = None
121 122
123 try:
124 from mercurial.revlogutils import constants as revlog_constants
125
126 perf_rl_kind = (revlog_constants.KIND_OTHER, b'created-by-perf')
127
128 def revlog(opener, *args, **kwargs):
129 return mercurial.revlog.revlog(opener, perf_rl_kind, *args, **kwargs)
130
131
132 except (ImportError, AttributeError):
133 perf_rl_kind = None
134
135 def revlog(opener, *args, **kwargs):
136 return mercurial.revlog.revlog(opener, *args, **kwargs)
137
122 138
123 139 def identity(a):
124 140 return a
@@ -1809,7 +1825,8 b' def perfnodelookup(ui, repo, rev, **opts'
1809 1825
1810 1826 mercurial.revlog._prereadsize = 2 ** 24 # disable lazy parser in old hg
1811 1827 n = scmutil.revsingle(repo, rev).node()
1812 cl = mercurial.revlog.revlog(getsvfs(repo), b"00changelog.i")
1828
1829 cl = revlog(getsvfs(repo), indexfile=b"00changelog.i")
1813 1830
1814 1831 def d():
1815 1832 cl.rev(n)
@@ -2602,9 +2619,9 b' def perfrevlogindex(ui, repo, file_=None'
2602 2619 else:
2603 2620 raise error.Abort(b'unsupported revlog version: %d' % version)
2604 2621
2605 parse_index_v1 = getattr(revlog, 'parse_index_v1', None)
2622 parse_index_v1 = getattr(mercurial.revlog, 'parse_index_v1', None)
2606 2623 if parse_index_v1 is None:
2607 parse_index_v1 = revlog.revlogio().parseindex
2624 parse_index_v1 = mercurial.revlog.revlogio().parseindex
2608 2625
2609 2626 rllen = len(rl)
2610 2627
@@ -2620,7 +2637,7 b' def perfrevlogindex(ui, repo, file_=None'
2620 2637 allnodesrev = list(reversed(allnodes))
2621 2638
2622 2639 def constructor():
2623 revlog.revlog(opener, indexfile)
2640 revlog(opener, indexfile=indexfile)
2624 2641
2625 2642 def read():
2626 2643 with opener(indexfile) as fh:
@@ -3042,7 +3059,7 b' def _temprevlog(ui, orig, truncaterev):'
3042 3059 vfs = vfsmod.vfs(tmpdir)
3043 3060 vfs.options = getattr(orig.opener, 'options', None)
3044 3061
3045 dest = revlog.revlog(
3062 dest = revlog(
3046 3063 vfs, indexfile=indexname, datafile=dataname, **revlogkwargs
3047 3064 )
3048 3065 if dest._inline:
@@ -15,6 +15,10 b' from mercurial import ('
15 15 )
16 16 from mercurial.utils import procutil
17 17
18 from mercurial.revlogutils import (
19 constants as revlog_constants,
20 )
21
18 22 for fp in (sys.stdin, sys.stdout, sys.stderr):
19 23 procutil.setbinary(fp)
20 24
@@ -28,7 +32,11 b' while True:'
28 32 break
29 33 if l.startswith("file:"):
30 34 f = encoding.strtolocal(l[6:-1])
31 r = revlog.revlog(opener, f)
35 r = revlog.revlog(
36 opener,
37 target=(revlog_constants.KIND_OTHER, b'undump-revlog'),
38 indexfile=f,
39 )
32 40 procutil.stdout.write(b'%s\n' % f)
33 41 elif l.startswith("node:"):
34 42 n = bin(l[6:-1])
@@ -46,9 +46,13 b' from .utils import ('
46 46 urlutil,
47 47 )
48 48
49 from .revlogutils import (
50 constants as revlog_constants,
51 )
52
49 53
50 54 class bundlerevlog(revlog.revlog):
51 def __init__(self, opener, indexfile, cgunpacker, linkmapper):
55 def __init__(self, opener, target, indexfile, cgunpacker, linkmapper):
52 56 # How it works:
53 57 # To retrieve a revision, we need to know the offset of the revision in
54 58 # the bundle (an unbundle object). We store this offset in the index
@@ -57,7 +61,7 b' class bundlerevlog(revlog.revlog):'
57 61 # To differentiate a rev in the bundle from a rev in the revlog, we
58 62 # check revision against repotiprev.
59 63 opener = vfsmod.readonlyvfs(opener)
60 revlog.revlog.__init__(self, opener, indexfile)
64 revlog.revlog.__init__(self, opener, target=target, indexfile=indexfile)
61 65 self.bundle = cgunpacker
62 66 n = len(self)
63 67 self.repotiprev = n - 1
@@ -171,7 +175,12 b' class bundlechangelog(bundlerevlog, chan'
171 175 changelog.changelog.__init__(self, opener)
172 176 linkmapper = lambda x: x
173 177 bundlerevlog.__init__(
174 self, opener, self.indexfile, cgunpacker, linkmapper
178 self,
179 opener,
180 (revlog_constants.KIND_CHANGELOG, None),
181 self.indexfile,
182 cgunpacker,
183 linkmapper,
175 184 )
176 185
177 186
@@ -187,7 +196,12 b' class bundlemanifest(bundlerevlog, manif'
187 196 ):
188 197 manifest.manifestrevlog.__init__(self, nodeconstants, opener, tree=dir)
189 198 bundlerevlog.__init__(
190 self, opener, self.indexfile, cgunpacker, linkmapper
199 self,
200 opener,
201 (revlog_constants.KIND_MANIFESTLOG, dir),
202 self.indexfile,
203 cgunpacker,
204 linkmapper,
191 205 )
192 206 if dirlogstarts is None:
193 207 dirlogstarts = {}
@@ -214,7 +228,12 b' class bundlefilelog(filelog.filelog):'
214 228 def __init__(self, opener, path, cgunpacker, linkmapper):
215 229 filelog.filelog.__init__(self, opener, path)
216 230 self._revlog = bundlerevlog(
217 opener, self.indexfile, cgunpacker, linkmapper
231 opener,
232 # XXX should use the unencoded path
233 target=(revlog_constants.KIND_FILELOG, path),
234 indexfile=self.indexfile,
235 cgunpacker=cgunpacker,
236 linkmapper=linkmapper,
218 237 )
219 238
220 239
@@ -25,7 +25,10 b' from .utils import ('
25 25 dateutil,
26 26 stringutil,
27 27 )
28 from .revlogutils import flagutil
28 from .revlogutils import (
29 constants as revlog_constants,
30 flagutil,
31 )
29 32
30 33 _defaultextra = {b'branch': b'default'}
31 34
@@ -401,7 +404,8 b' class changelog(revlog.revlog):'
401 404 revlog.revlog.__init__(
402 405 self,
403 406 opener,
404 indexfile,
407 target=(revlog_constants.KIND_CHANGELOG, None),
408 indexfile=indexfile,
405 409 datafile=datafile,
406 410 checkambig=True,
407 411 mmaplargeindex=True,
@@ -61,6 +61,10 b' from .utils import ('
61 61 stringutil,
62 62 )
63 63
64 from .revlogutils import (
65 constants as revlog_constants,
66 )
67
64 68 if pycompat.TYPE_CHECKING:
65 69 from typing import (
66 70 Any,
@@ -1428,8 +1432,12 b' def openstorage(repo, cmd, file_, opts, '
1428 1432 raise error.CommandError(cmd, _(b'invalid arguments'))
1429 1433 if not os.path.isfile(file_):
1430 1434 raise error.InputError(_(b"revlog '%s' not found") % file_)
1435
1436 target = (revlog_constants.KIND_OTHER, b'free-form:%s' % file_)
1431 1437 r = revlog.revlog(
1432 vfsmod.vfs(encoding.getcwd(), audit=False), file_[:-2] + b".i"
1438 vfsmod.vfs(encoding.getcwd(), audit=False),
1439 target=target,
1440 indexfile=file_[:-2] + b".i",
1433 1441 )
1434 1442 return r
1435 1443
@@ -18,13 +18,20 b' from .interfaces import ('
18 18 util as interfaceutil,
19 19 )
20 20 from .utils import storageutil
21 from .revlogutils import (
22 constants as revlog_constants,
23 )
21 24
22 25
23 26 @interfaceutil.implementer(repository.ifilestorage)
24 27 class filelog(object):
25 28 def __init__(self, opener, path):
26 29 self._revlog = revlog.revlog(
27 opener, b'/'.join((b'data', path + b'.i')), censorable=True
30 opener,
31 # XXX should use the unencoded path
32 target=(revlog_constants.KIND_FILELOG, path),
33 indexfile=b'/'.join((b'data', path + b'.i')),
34 censorable=True,
28 35 )
29 36 # Full name of the user visible file, relative to the repository root.
30 37 # Used by LFS.
@@ -34,6 +34,9 b' from .interfaces import ('
34 34 repository,
35 35 util as interfaceutil,
36 36 )
37 from .revlogutils import (
38 constants as revlog_constants,
39 )
37 40
38 41 parsers = policy.importmod('parsers')
39 42 propertycache = util.propertycache
@@ -1610,7 +1613,8 b' class manifestrevlog(object):'
1610 1613
1611 1614 self._revlog = revlog.revlog(
1612 1615 opener,
1613 indexfile,
1616 target=(revlog_constants.KIND_MANIFESTLOG, self.tree),
1617 indexfile=indexfile,
1614 1618 # only root indexfile is cached
1615 1619 checkambig=not bool(tree),
1616 1620 mmaplargeindex=True,
@@ -34,6 +34,7 b' from .node import ('
34 34 from .i18n import _
35 35 from .pycompat import getattr
36 36 from .revlogutils.constants import (
37 ALL_KINDS,
37 38 FLAG_GENERALDELTA,
38 39 FLAG_INLINE_DATA,
39 40 INDEX_HEADER,
@@ -287,7 +288,8 b' class revlog(object):'
287 288 def __init__(
288 289 self,
289 290 opener,
290 indexfile,
291 target,
292 indexfile=None,
291 293 datafile=None,
292 294 checkambig=False,
293 295 mmaplargeindex=False,
@@ -302,6 +304,12 b' class revlog(object):'
302 304 opener is a function that abstracts the file opening operation
303 305 and can be used to implement COW semantics or the like.
304 306
307 `target`: a (KIND, ID) tuple that identify the content stored in
308 this revlog. It help the rest of the code to understand what the revlog
309 is about without having to resort to heuristic and index filename
310 analysis. Note: that this must be reliably be set by normal code, but
311 that test, debug, or performance measurement code might not set this to
312 accurate value.
305 313 """
306 314 self.upperboundcomp = upperboundcomp
307 315 self.indexfile = indexfile
@@ -313,6 +321,9 b' class revlog(object):'
313 321 )
314 322
315 323 self.opener = opener
324 assert target[0] in ALL_KINDS
325 assert len(target) == 2
326 self.target = target
316 327 # When True, indexfile is opened with checkambig=True at writing, to
317 328 # avoid file stat ambiguity.
318 329 self._checkambig = checkambig
@@ -2869,7 +2880,13 b' class revlog(object):'
2869 2880 newdatafile = self.datafile + b'.tmpcensored'
2870 2881
2871 2882 # This is a bit dangerous. We could easily have a mismatch of state.
2872 newrl = revlog(self.opener, newindexfile, newdatafile, censorable=True)
2883 newrl = revlog(
2884 self.opener,
2885 target=self.target,
2886 indexfile=newindexfile,
2887 datafile=newdatafile,
2888 censorable=True,
2889 )
2873 2890 newrl.version = self.version
2874 2891 newrl._generaldelta = self._generaldelta
2875 2892 newrl._parse_index = self._parse_index
@@ -13,6 +13,20 b' import struct'
13 13
14 14 from ..interfaces import repository
15 15
16 ### Internal utily constants
17
18 KIND_CHANGELOG = 1001 # over 256 to not be comparable with a bytes
19 KIND_MANIFESTLOG = 1002
20 KIND_FILELOG = 1003
21 KIND_OTHER = 1004
22
23 ALL_KINDS = {
24 KIND_CHANGELOG,
25 KIND_MANIFESTLOG,
26 KIND_FILELOG,
27 KIND_OTHER,
28 }
29
16 30 ### main revlog header
17 31
18 32 INDEX_HEADER = struct.Struct(b">I")
@@ -41,7 +41,11 b' class unionrevlog(revlog.revlog):'
41 41 # To differentiate a rev in the second revlog from a rev in the revlog,
42 42 # we check revision against repotiprev.
43 43 opener = vfsmod.readonlyvfs(opener)
44 revlog.revlog.__init__(self, opener, indexfile)
44 target = getattr(revlog2, 'target', None)
45 if target is None:
46 # a revlog wrapper, eg: the manifestlog that is not an actual revlog
47 target = revlog2._revlog.target
48 revlog.revlog.__init__(self, opener, target=target, indexfile=indexfile)
45 49 self.revlog2 = revlog2
46 50
47 51 n = len(self)
@@ -14,6 +14,7 b' from mercurial import ('
14 14 )
15 15
16 16 from mercurial.revlogutils import (
17 constants,
17 18 deltas,
18 19 flagutil,
19 20 )
@@ -81,7 +82,9 b' def newtransaction():'
81 82 def newrevlog(name=b'_testrevlog.i', recreate=False):
82 83 if recreate:
83 84 tvfs.tryunlink(name)
84 rlog = revlog.revlog(tvfs, name)
85 rlog = revlog.revlog(
86 tvfs, target=(constants.KIND_OTHER, b'test'), indexfile=name
87 )
85 88 return rlog
86 89
87 90
@@ -45,9 +45,10 b' Test for CVE-2016-3630'
45 45 0 2 99e0332bd498 000000000000 000000000000
46 46 1 3 6674f57a23d8 99e0332bd498 000000000000
47 47
48 >>> from mercurial.revlogutils.constants import KIND_OTHER
48 49 >>> from mercurial import revlog, vfs
49 50 >>> tvfs = vfs.vfs(b'.')
50 51 >>> tvfs.options = {b'revlogv1': True}
51 >>> rl = revlog.revlog(tvfs, b'a.i')
52 >>> rl = revlog.revlog(tvfs, target=(KIND_OTHER, b'test'), indexfile=b'a.i')
52 53 >>> rl.revision(1)
53 54 mpatchError(*'patch cannot be decoded'*) (glob)
General Comments 0
You need to be logged in to leave comments. Login now