##// END OF EJS Templates
flagutil: make the error class used by the mixin configurable...
marmoute -
r43142:7907008a default
parent child Browse files
Show More
@@ -1,151 +1,153 b''
1 # flagutils.py - code to deal with revlog flags and their processors
1 # flagutils.py - code to deal with revlog flags and their processors
2 #
2 #
3 # Copyright 2016 Remi Chaintron <remi@fb.com>
3 # Copyright 2016 Remi Chaintron <remi@fb.com>
4 # Copyright 2016-2019 Pierre-Yves David <pierre-yves.david@ens-lyon.org>
4 # Copyright 2016-2019 Pierre-Yves David <pierre-yves.david@ens-lyon.org>
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 from __future__ import absolute_import
9 from __future__ import absolute_import
10
10
11 from ..i18n import _
11 from ..i18n import _
12
12
13 from .constants import (
13 from .constants import (
14 REVIDX_DEFAULT_FLAGS,
14 REVIDX_DEFAULT_FLAGS,
15 REVIDX_ELLIPSIS,
15 REVIDX_ELLIPSIS,
16 REVIDX_EXTSTORED,
16 REVIDX_EXTSTORED,
17 REVIDX_FLAGS_ORDER,
17 REVIDX_FLAGS_ORDER,
18 REVIDX_ISCENSORED,
18 REVIDX_ISCENSORED,
19 REVIDX_RAWTEXT_CHANGING_FLAGS,
19 REVIDX_RAWTEXT_CHANGING_FLAGS,
20 )
20 )
21
21
22 from .. import (
22 from .. import (
23 error,
23 error,
24 util
24 util
25 )
25 )
26
26
27 # blanked usage of all the name to prevent pyflakes constraints
27 # blanked usage of all the name to prevent pyflakes constraints
28 # We need these name available in the module for extensions.
28 # We need these name available in the module for extensions.
29 REVIDX_ISCENSORED
29 REVIDX_ISCENSORED
30 REVIDX_ELLIPSIS
30 REVIDX_ELLIPSIS
31 REVIDX_EXTSTORED
31 REVIDX_EXTSTORED
32 REVIDX_DEFAULT_FLAGS
32 REVIDX_DEFAULT_FLAGS
33 REVIDX_FLAGS_ORDER
33 REVIDX_FLAGS_ORDER
34 REVIDX_RAWTEXT_CHANGING_FLAGS
34 REVIDX_RAWTEXT_CHANGING_FLAGS
35
35
36 REVIDX_KNOWN_FLAGS = util.bitsfrom(REVIDX_FLAGS_ORDER)
36 REVIDX_KNOWN_FLAGS = util.bitsfrom(REVIDX_FLAGS_ORDER)
37
37
38 # Store flag processors (cf. 'addflagprocessor()' to register)
38 # Store flag processors (cf. 'addflagprocessor()' to register)
39 flagprocessors = {
39 flagprocessors = {
40 REVIDX_ISCENSORED: None,
40 REVIDX_ISCENSORED: None,
41 }
41 }
42
42
43 def addflagprocessor(flag, processor):
43 def addflagprocessor(flag, processor):
44 """Register a flag processor on a revision data flag.
44 """Register a flag processor on a revision data flag.
45
45
46 Invariant:
46 Invariant:
47 - Flags need to be defined in REVIDX_KNOWN_FLAGS and REVIDX_FLAGS_ORDER,
47 - Flags need to be defined in REVIDX_KNOWN_FLAGS and REVIDX_FLAGS_ORDER,
48 and REVIDX_RAWTEXT_CHANGING_FLAGS if they can alter rawtext.
48 and REVIDX_RAWTEXT_CHANGING_FLAGS if they can alter rawtext.
49 - Only one flag processor can be registered on a specific flag.
49 - Only one flag processor can be registered on a specific flag.
50 - flagprocessors must be 3-tuples of functions (read, write, raw) with the
50 - flagprocessors must be 3-tuples of functions (read, write, raw) with the
51 following signatures:
51 following signatures:
52 - (read) f(self, rawtext) -> text, bool
52 - (read) f(self, rawtext) -> text, bool
53 - (write) f(self, text) -> rawtext, bool
53 - (write) f(self, text) -> rawtext, bool
54 - (raw) f(self, rawtext) -> bool
54 - (raw) f(self, rawtext) -> bool
55 "text" is presented to the user. "rawtext" is stored in revlog data, not
55 "text" is presented to the user. "rawtext" is stored in revlog data, not
56 directly visible to the user.
56 directly visible to the user.
57 The boolean returned by these transforms is used to determine whether
57 The boolean returned by these transforms is used to determine whether
58 the returned text can be used for hash integrity checking. For example,
58 the returned text can be used for hash integrity checking. For example,
59 if "write" returns False, then "text" is used to generate hash. If
59 if "write" returns False, then "text" is used to generate hash. If
60 "write" returns True, that basically means "rawtext" returned by "write"
60 "write" returns True, that basically means "rawtext" returned by "write"
61 should be used to generate hash. Usually, "write" and "read" return
61 should be used to generate hash. Usually, "write" and "read" return
62 different booleans. And "raw" returns a same boolean as "write".
62 different booleans. And "raw" returns a same boolean as "write".
63
63
64 Note: The 'raw' transform is used for changegroup generation and in some
64 Note: The 'raw' transform is used for changegroup generation and in some
65 debug commands. In this case the transform only indicates whether the
65 debug commands. In this case the transform only indicates whether the
66 contents can be used for hash integrity checks.
66 contents can be used for hash integrity checks.
67 """
67 """
68 insertflagprocessor(flag, processor, flagprocessors)
68 insertflagprocessor(flag, processor, flagprocessors)
69
69
70 def insertflagprocessor(flag, processor, flagprocessors):
70 def insertflagprocessor(flag, processor, flagprocessors):
71 if not flag & REVIDX_KNOWN_FLAGS:
71 if not flag & REVIDX_KNOWN_FLAGS:
72 msg = _("cannot register processor on unknown flag '%#x'.") % (flag)
72 msg = _("cannot register processor on unknown flag '%#x'.") % (flag)
73 raise error.ProgrammingError(msg)
73 raise error.ProgrammingError(msg)
74 if flag not in REVIDX_FLAGS_ORDER:
74 if flag not in REVIDX_FLAGS_ORDER:
75 msg = _("flag '%#x' undefined in REVIDX_FLAGS_ORDER.") % (flag)
75 msg = _("flag '%#x' undefined in REVIDX_FLAGS_ORDER.") % (flag)
76 raise error.ProgrammingError(msg)
76 raise error.ProgrammingError(msg)
77 if flag in flagprocessors:
77 if flag in flagprocessors:
78 msg = _("cannot register multiple processors on flag '%#x'.") % (flag)
78 msg = _("cannot register multiple processors on flag '%#x'.") % (flag)
79 raise error.Abort(msg)
79 raise error.Abort(msg)
80 flagprocessors[flag] = processor
80 flagprocessors[flag] = processor
81
81
82 class flagprocessorsmixin(object):
82 class flagprocessorsmixin(object):
83 """basic mixin to support revlog flag processing
83 """basic mixin to support revlog flag processing
84
84
85 Make sure the `_flagprocessors` attribute is set at ``__init__`` time.
85 Make sure the `_flagprocessors` attribute is set at ``__init__`` time.
86
86
87 See the documentation of the ``_processflags`` method for details.
87 See the documentation of the ``_processflags`` method for details.
88 """
88 """
89
89
90 _flagserrorclass = error.RevlogError
91
90 def _processflags(self, text, flags, operation, raw=False):
92 def _processflags(self, text, flags, operation, raw=False):
91 """Inspect revision data flags and applies transforms defined by
93 """Inspect revision data flags and applies transforms defined by
92 registered flag processors.
94 registered flag processors.
93
95
94 ``text`` - the revision data to process
96 ``text`` - the revision data to process
95 ``flags`` - the revision flags
97 ``flags`` - the revision flags
96 ``operation`` - the operation being performed (read or write)
98 ``operation`` - the operation being performed (read or write)
97 ``raw`` - an optional argument describing if the raw transform should be
99 ``raw`` - an optional argument describing if the raw transform should be
98 applied.
100 applied.
99
101
100 This method processes the flags in the order (or reverse order if
102 This method processes the flags in the order (or reverse order if
101 ``operation`` is 'write') defined by REVIDX_FLAGS_ORDER, applying the
103 ``operation`` is 'write') defined by REVIDX_FLAGS_ORDER, applying the
102 flag processors registered for present flags. The order of flags defined
104 flag processors registered for present flags. The order of flags defined
103 in REVIDX_FLAGS_ORDER needs to be stable to allow non-commutativity.
105 in REVIDX_FLAGS_ORDER needs to be stable to allow non-commutativity.
104
106
105 Returns a 2-tuple of ``(text, validatehash)`` where ``text`` is the
107 Returns a 2-tuple of ``(text, validatehash)`` where ``text`` is the
106 processed text and ``validatehash`` is a bool indicating whether the
108 processed text and ``validatehash`` is a bool indicating whether the
107 returned text should be checked for hash integrity.
109 returned text should be checked for hash integrity.
108
110
109 Note: If the ``raw`` argument is set, it has precedence over the
111 Note: If the ``raw`` argument is set, it has precedence over the
110 operation and will only update the value of ``validatehash``.
112 operation and will only update the value of ``validatehash``.
111 """
113 """
112 # fast path: no flag processors will run
114 # fast path: no flag processors will run
113 if flags == 0:
115 if flags == 0:
114 return text, True
116 return text, True
115 if not operation in ('read', 'write'):
117 if not operation in ('read', 'write'):
116 raise error.ProgrammingError(_("invalid '%s' operation") %
118 raise error.ProgrammingError(_("invalid '%s' operation") %
117 operation)
119 operation)
118 # Check all flags are known.
120 # Check all flags are known.
119 if flags & ~REVIDX_KNOWN_FLAGS:
121 if flags & ~REVIDX_KNOWN_FLAGS:
120 raise error.RevlogError(_("incompatible revision flag '%#x'") %
122 raise self._flagserrorclass(_("incompatible revision flag '%#x'") %
121 (flags & ~REVIDX_KNOWN_FLAGS))
123 (flags & ~REVIDX_KNOWN_FLAGS))
122 validatehash = True
124 validatehash = True
123 # Depending on the operation (read or write), the order might be
125 # Depending on the operation (read or write), the order might be
124 # reversed due to non-commutative transforms.
126 # reversed due to non-commutative transforms.
125 orderedflags = REVIDX_FLAGS_ORDER
127 orderedflags = REVIDX_FLAGS_ORDER
126 if operation == 'write':
128 if operation == 'write':
127 orderedflags = reversed(orderedflags)
129 orderedflags = reversed(orderedflags)
128
130
129 for flag in orderedflags:
131 for flag in orderedflags:
130 # If a flagprocessor has been registered for a known flag, apply the
132 # If a flagprocessor has been registered for a known flag, apply the
131 # related operation transform and update result tuple.
133 # related operation transform and update result tuple.
132 if flag & flags:
134 if flag & flags:
133 vhash = True
135 vhash = True
134
136
135 if flag not in self._flagprocessors:
137 if flag not in self._flagprocessors:
136 message = _("missing processor for flag '%#x'") % (flag)
138 message = _("missing processor for flag '%#x'") % (flag)
137 raise error.RevlogError(message)
139 raise self._flagserrorclass(message)
138
140
139 processor = self._flagprocessors[flag]
141 processor = self._flagprocessors[flag]
140 if processor is not None:
142 if processor is not None:
141 readtransform, writetransform, rawtransform = processor
143 readtransform, writetransform, rawtransform = processor
142
144
143 if raw:
145 if raw:
144 vhash = rawtransform(self, text)
146 vhash = rawtransform(self, text)
145 elif operation == 'read':
147 elif operation == 'read':
146 text, vhash = readtransform(self, text)
148 text, vhash = readtransform(self, text)
147 else: # write operation
149 else: # write operation
148 text, vhash = writetransform(self, text)
150 text, vhash = writetransform(self, text)
149 validatehash = validatehash and vhash
151 validatehash = validatehash and vhash
150
152
151 return text, validatehash
153 return text, validatehash
General Comments 0
You need to be logged in to leave comments. Login now