##// 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 from mercurial.utils import procutil
14 from mercurial.utils import procutil
15
15
16 from mercurial.revlogutils import (
17 constants as revlog_constants,
18 )
19
16 for fp in (sys.stdin, sys.stdout, sys.stderr):
20 for fp in (sys.stdin, sys.stdout, sys.stderr):
17 procutil.setbinary(fp)
21 procutil.setbinary(fp)
18
22
@@ -32,7 +36,11 b" def printb(data, end=b'\\n'):"
32
36
33
37
34 for f in sys.argv[1:]:
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 print("file:", f)
44 print("file:", f)
37 for i in r:
45 for i in r:
38 n = r.node(i)
46 n = r.node(i)
@@ -66,6 +66,8 b' import sys'
66 import tempfile
66 import tempfile
67 import threading
67 import threading
68 import time
68 import time
69
70 import mercurial.revlog
69 from mercurial import (
71 from mercurial import (
70 changegroup,
72 changegroup,
71 cmdutil,
73 cmdutil,
@@ -76,7 +78,6 b' from mercurial import ('
76 hg,
78 hg,
77 mdiff,
79 mdiff,
78 merge,
80 merge,
79 revlog,
80 util,
81 util,
81 )
82 )
82
83
@@ -119,6 +120,21 b' try:'
119 except ImportError:
120 except ImportError:
120 profiling = None
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 def identity(a):
139 def identity(a):
124 return a
140 return a
@@ -1809,7 +1825,8 b' def perfnodelookup(ui, repo, rev, **opts'
1809
1825
1810 mercurial.revlog._prereadsize = 2 ** 24 # disable lazy parser in old hg
1826 mercurial.revlog._prereadsize = 2 ** 24 # disable lazy parser in old hg
1811 n = scmutil.revsingle(repo, rev).node()
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 def d():
1831 def d():
1815 cl.rev(n)
1832 cl.rev(n)
@@ -2602,9 +2619,9 b' def perfrevlogindex(ui, repo, file_=None'
2602 else:
2619 else:
2603 raise error.Abort(b'unsupported revlog version: %d' % version)
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 if parse_index_v1 is None:
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 rllen = len(rl)
2626 rllen = len(rl)
2610
2627
@@ -2620,7 +2637,7 b' def perfrevlogindex(ui, repo, file_=None'
2620 allnodesrev = list(reversed(allnodes))
2637 allnodesrev = list(reversed(allnodes))
2621
2638
2622 def constructor():
2639 def constructor():
2623 revlog.revlog(opener, indexfile)
2640 revlog(opener, indexfile=indexfile)
2624
2641
2625 def read():
2642 def read():
2626 with opener(indexfile) as fh:
2643 with opener(indexfile) as fh:
@@ -3042,7 +3059,7 b' def _temprevlog(ui, orig, truncaterev):'
3042 vfs = vfsmod.vfs(tmpdir)
3059 vfs = vfsmod.vfs(tmpdir)
3043 vfs.options = getattr(orig.opener, 'options', None)
3060 vfs.options = getattr(orig.opener, 'options', None)
3044
3061
3045 dest = revlog.revlog(
3062 dest = revlog(
3046 vfs, indexfile=indexname, datafile=dataname, **revlogkwargs
3063 vfs, indexfile=indexname, datafile=dataname, **revlogkwargs
3047 )
3064 )
3048 if dest._inline:
3065 if dest._inline:
@@ -15,6 +15,10 b' from mercurial import ('
15 )
15 )
16 from mercurial.utils import procutil
16 from mercurial.utils import procutil
17
17
18 from mercurial.revlogutils import (
19 constants as revlog_constants,
20 )
21
18 for fp in (sys.stdin, sys.stdout, sys.stderr):
22 for fp in (sys.stdin, sys.stdout, sys.stderr):
19 procutil.setbinary(fp)
23 procutil.setbinary(fp)
20
24
@@ -28,7 +32,11 b' while True:'
28 break
32 break
29 if l.startswith("file:"):
33 if l.startswith("file:"):
30 f = encoding.strtolocal(l[6:-1])
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 procutil.stdout.write(b'%s\n' % f)
40 procutil.stdout.write(b'%s\n' % f)
33 elif l.startswith("node:"):
41 elif l.startswith("node:"):
34 n = bin(l[6:-1])
42 n = bin(l[6:-1])
@@ -46,9 +46,13 b' from .utils import ('
46 urlutil,
46 urlutil,
47 )
47 )
48
48
49 from .revlogutils import (
50 constants as revlog_constants,
51 )
52
49
53
50 class bundlerevlog(revlog.revlog):
54 class bundlerevlog(revlog.revlog):
51 def __init__(self, opener, indexfile, cgunpacker, linkmapper):
55 def __init__(self, opener, target, indexfile, cgunpacker, linkmapper):
52 # How it works:
56 # How it works:
53 # To retrieve a revision, we need to know the offset of the revision in
57 # To retrieve a revision, we need to know the offset of the revision in
54 # the bundle (an unbundle object). We store this offset in the index
58 # the bundle (an unbundle object). We store this offset in the index
@@ -57,7 +61,7 b' class bundlerevlog(revlog.revlog):'
57 # To differentiate a rev in the bundle from a rev in the revlog, we
61 # To differentiate a rev in the bundle from a rev in the revlog, we
58 # check revision against repotiprev.
62 # check revision against repotiprev.
59 opener = vfsmod.readonlyvfs(opener)
63 opener = vfsmod.readonlyvfs(opener)
60 revlog.revlog.__init__(self, opener, indexfile)
64 revlog.revlog.__init__(self, opener, target=target, indexfile=indexfile)
61 self.bundle = cgunpacker
65 self.bundle = cgunpacker
62 n = len(self)
66 n = len(self)
63 self.repotiprev = n - 1
67 self.repotiprev = n - 1
@@ -171,7 +175,12 b' class bundlechangelog(bundlerevlog, chan'
171 changelog.changelog.__init__(self, opener)
175 changelog.changelog.__init__(self, opener)
172 linkmapper = lambda x: x
176 linkmapper = lambda x: x
173 bundlerevlog.__init__(
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 manifest.manifestrevlog.__init__(self, nodeconstants, opener, tree=dir)
197 manifest.manifestrevlog.__init__(self, nodeconstants, opener, tree=dir)
189 bundlerevlog.__init__(
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 if dirlogstarts is None:
206 if dirlogstarts is None:
193 dirlogstarts = {}
207 dirlogstarts = {}
@@ -214,7 +228,12 b' class bundlefilelog(filelog.filelog):'
214 def __init__(self, opener, path, cgunpacker, linkmapper):
228 def __init__(self, opener, path, cgunpacker, linkmapper):
215 filelog.filelog.__init__(self, opener, path)
229 filelog.filelog.__init__(self, opener, path)
216 self._revlog = bundlerevlog(
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 dateutil,
25 dateutil,
26 stringutil,
26 stringutil,
27 )
27 )
28 from .revlogutils import flagutil
28 from .revlogutils import (
29 constants as revlog_constants,
30 flagutil,
31 )
29
32
30 _defaultextra = {b'branch': b'default'}
33 _defaultextra = {b'branch': b'default'}
31
34
@@ -401,7 +404,8 b' class changelog(revlog.revlog):'
401 revlog.revlog.__init__(
404 revlog.revlog.__init__(
402 self,
405 self,
403 opener,
406 opener,
404 indexfile,
407 target=(revlog_constants.KIND_CHANGELOG, None),
408 indexfile=indexfile,
405 datafile=datafile,
409 datafile=datafile,
406 checkambig=True,
410 checkambig=True,
407 mmaplargeindex=True,
411 mmaplargeindex=True,
@@ -61,6 +61,10 b' from .utils import ('
61 stringutil,
61 stringutil,
62 )
62 )
63
63
64 from .revlogutils import (
65 constants as revlog_constants,
66 )
67
64 if pycompat.TYPE_CHECKING:
68 if pycompat.TYPE_CHECKING:
65 from typing import (
69 from typing import (
66 Any,
70 Any,
@@ -1428,8 +1432,12 b' def openstorage(repo, cmd, file_, opts, '
1428 raise error.CommandError(cmd, _(b'invalid arguments'))
1432 raise error.CommandError(cmd, _(b'invalid arguments'))
1429 if not os.path.isfile(file_):
1433 if not os.path.isfile(file_):
1430 raise error.InputError(_(b"revlog '%s' not found") % file_)
1434 raise error.InputError(_(b"revlog '%s' not found") % file_)
1435
1436 target = (revlog_constants.KIND_OTHER, b'free-form:%s' % file_)
1431 r = revlog.revlog(
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 return r
1442 return r
1435
1443
@@ -18,13 +18,20 b' from .interfaces import ('
18 util as interfaceutil,
18 util as interfaceutil,
19 )
19 )
20 from .utils import storageutil
20 from .utils import storageutil
21 from .revlogutils import (
22 constants as revlog_constants,
23 )
21
24
22
25
23 @interfaceutil.implementer(repository.ifilestorage)
26 @interfaceutil.implementer(repository.ifilestorage)
24 class filelog(object):
27 class filelog(object):
25 def __init__(self, opener, path):
28 def __init__(self, opener, path):
26 self._revlog = revlog.revlog(
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 # Full name of the user visible file, relative to the repository root.
36 # Full name of the user visible file, relative to the repository root.
30 # Used by LFS.
37 # Used by LFS.
@@ -34,6 +34,9 b' from .interfaces import ('
34 repository,
34 repository,
35 util as interfaceutil,
35 util as interfaceutil,
36 )
36 )
37 from .revlogutils import (
38 constants as revlog_constants,
39 )
37
40
38 parsers = policy.importmod('parsers')
41 parsers = policy.importmod('parsers')
39 propertycache = util.propertycache
42 propertycache = util.propertycache
@@ -1610,7 +1613,8 b' class manifestrevlog(object):'
1610
1613
1611 self._revlog = revlog.revlog(
1614 self._revlog = revlog.revlog(
1612 opener,
1615 opener,
1613 indexfile,
1616 target=(revlog_constants.KIND_MANIFESTLOG, self.tree),
1617 indexfile=indexfile,
1614 # only root indexfile is cached
1618 # only root indexfile is cached
1615 checkambig=not bool(tree),
1619 checkambig=not bool(tree),
1616 mmaplargeindex=True,
1620 mmaplargeindex=True,
@@ -34,6 +34,7 b' from .node import ('
34 from .i18n import _
34 from .i18n import _
35 from .pycompat import getattr
35 from .pycompat import getattr
36 from .revlogutils.constants import (
36 from .revlogutils.constants import (
37 ALL_KINDS,
37 FLAG_GENERALDELTA,
38 FLAG_GENERALDELTA,
38 FLAG_INLINE_DATA,
39 FLAG_INLINE_DATA,
39 INDEX_HEADER,
40 INDEX_HEADER,
@@ -287,7 +288,8 b' class revlog(object):'
287 def __init__(
288 def __init__(
288 self,
289 self,
289 opener,
290 opener,
290 indexfile,
291 target,
292 indexfile=None,
291 datafile=None,
293 datafile=None,
292 checkambig=False,
294 checkambig=False,
293 mmaplargeindex=False,
295 mmaplargeindex=False,
@@ -302,6 +304,12 b' class revlog(object):'
302 opener is a function that abstracts the file opening operation
304 opener is a function that abstracts the file opening operation
303 and can be used to implement COW semantics or the like.
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 self.upperboundcomp = upperboundcomp
314 self.upperboundcomp = upperboundcomp
307 self.indexfile = indexfile
315 self.indexfile = indexfile
@@ -313,6 +321,9 b' class revlog(object):'
313 )
321 )
314
322
315 self.opener = opener
323 self.opener = opener
324 assert target[0] in ALL_KINDS
325 assert len(target) == 2
326 self.target = target
316 # When True, indexfile is opened with checkambig=True at writing, to
327 # When True, indexfile is opened with checkambig=True at writing, to
317 # avoid file stat ambiguity.
328 # avoid file stat ambiguity.
318 self._checkambig = checkambig
329 self._checkambig = checkambig
@@ -2869,7 +2880,13 b' class revlog(object):'
2869 newdatafile = self.datafile + b'.tmpcensored'
2880 newdatafile = self.datafile + b'.tmpcensored'
2870
2881
2871 # This is a bit dangerous. We could easily have a mismatch of state.
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 newrl.version = self.version
2890 newrl.version = self.version
2874 newrl._generaldelta = self._generaldelta
2891 newrl._generaldelta = self._generaldelta
2875 newrl._parse_index = self._parse_index
2892 newrl._parse_index = self._parse_index
@@ -13,6 +13,20 b' import struct'
13
13
14 from ..interfaces import repository
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 ### main revlog header
30 ### main revlog header
17
31
18 INDEX_HEADER = struct.Struct(b">I")
32 INDEX_HEADER = struct.Struct(b">I")
@@ -41,7 +41,11 b' class unionrevlog(revlog.revlog):'
41 # To differentiate a rev in the second revlog from a rev in the revlog,
41 # To differentiate a rev in the second revlog from a rev in the revlog,
42 # we check revision against repotiprev.
42 # we check revision against repotiprev.
43 opener = vfsmod.readonlyvfs(opener)
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 self.revlog2 = revlog2
49 self.revlog2 = revlog2
46
50
47 n = len(self)
51 n = len(self)
@@ -14,6 +14,7 b' from mercurial import ('
14 )
14 )
15
15
16 from mercurial.revlogutils import (
16 from mercurial.revlogutils import (
17 constants,
17 deltas,
18 deltas,
18 flagutil,
19 flagutil,
19 )
20 )
@@ -81,7 +82,9 b' def newtransaction():'
81 def newrevlog(name=b'_testrevlog.i', recreate=False):
82 def newrevlog(name=b'_testrevlog.i', recreate=False):
82 if recreate:
83 if recreate:
83 tvfs.tryunlink(name)
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 return rlog
88 return rlog
86
89
87
90
@@ -45,9 +45,10 b' Test for CVE-2016-3630'
45 0 2 99e0332bd498 000000000000 000000000000
45 0 2 99e0332bd498 000000000000 000000000000
46 1 3 6674f57a23d8 99e0332bd498 000000000000
46 1 3 6674f57a23d8 99e0332bd498 000000000000
47
47
48 >>> from mercurial.revlogutils.constants import KIND_OTHER
48 >>> from mercurial import revlog, vfs
49 >>> from mercurial import revlog, vfs
49 >>> tvfs = vfs.vfs(b'.')
50 >>> tvfs = vfs.vfs(b'.')
50 >>> tvfs.options = {b'revlogv1': True}
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 >>> rl.revision(1)
53 >>> rl.revision(1)
53 mpatchError(*'patch cannot be decoded'*) (glob)
54 mpatchError(*'patch cannot be decoded'*) (glob)
General Comments 0
You need to be logged in to leave comments. Login now