##// END OF EJS Templates
flagprocessors: return flagdata in the main processing function...
marmoute -
r43254:66dc5a52 default
parent child Browse files
Show More
@@ -1,200 +1,200 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
90 _flagserrorclass = error.RevlogError
91
91
92 def _processflags(self, text, flags, operation, raw=False):
92 def _processflags(self, text, flags, operation, raw=False):
93 """deprecated entry point to access flag processors"""
93 """deprecated entry point to access flag processors"""
94 msg = ('_processflag(...) use the specialized variant')
94 msg = ('_processflag(...) use the specialized variant')
95 util.nouideprecwarn(msg, '5.2', stacklevel=2)
95 util.nouideprecwarn(msg, '5.2', stacklevel=2)
96 if raw:
96 if raw:
97 return text, self._processflagsraw(text, flags)
97 return text, self._processflagsraw(text, flags)
98 elif operation == 'read':
98 elif operation == 'read':
99 return self._processflagsread(text, flags)
99 return self._processflagsread(text, flags)
100 else: # write operation
100 else: # write operation
101 return self._processflagswrite(text, flags)
101 return self._processflagswrite(text, flags)
102
102
103 def _processflagsread(self, text, flags):
103 def _processflagsread(self, text, flags):
104 """Inspect revision data flags and applies read transformations defined
104 """Inspect revision data flags and applies read transformations defined
105 by registered flag processors.
105 by registered flag processors.
106
106
107 ``text`` - the revision data to process
107 ``text`` - the revision data to process
108 ``flags`` - the revision flags
108 ``flags`` - the revision flags
109 ``raw`` - an optional argument describing if the raw transform should be
109 ``raw`` - an optional argument describing if the raw transform should be
110 applied.
110 applied.
111
111
112 This method processes the flags in the order (or reverse order if
112 This method processes the flags in the order (or reverse order if
113 ``operation`` is 'write') defined by REVIDX_FLAGS_ORDER, applying the
113 ``operation`` is 'write') defined by REVIDX_FLAGS_ORDER, applying the
114 flag processors registered for present flags. The order of flags defined
114 flag processors registered for present flags. The order of flags defined
115 in REVIDX_FLAGS_ORDER needs to be stable to allow non-commutativity.
115 in REVIDX_FLAGS_ORDER needs to be stable to allow non-commutativity.
116
116
117 Returns a 2-tuple of ``(text, validatehash)`` where ``text`` is the
117 Returns a 2-tuple of ``(text, validatehash)`` where ``text`` is the
118 processed text and ``validatehash`` is a bool indicating whether the
118 processed text and ``validatehash`` is a bool indicating whether the
119 returned text should be checked for hash integrity.
119 returned text should be checked for hash integrity.
120 """
120 """
121 text, vhash = self._processflagsfunc(text, flags, 'read')
121 return self._processflagsfunc(text, flags, 'read')
122 return text, vhash, {}
123
122
124 def _processflagswrite(self, text, flags):
123 def _processflagswrite(self, text, flags):
125 """Inspect revision data flags and applies write transformations defined
124 """Inspect revision data flags and applies write transformations defined
126 by registered flag processors.
125 by registered flag processors.
127
126
128 ``text`` - the revision data to process
127 ``text`` - the revision data to process
129 ``flags`` - the revision flags
128 ``flags`` - the revision flags
130
129
131 This method processes the flags in the order (or reverse order if
130 This method processes the flags in the order (or reverse order if
132 ``operation`` is 'write') defined by REVIDX_FLAGS_ORDER, applying the
131 ``operation`` is 'write') defined by REVIDX_FLAGS_ORDER, applying the
133 flag processors registered for present flags. The order of flags defined
132 flag processors registered for present flags. The order of flags defined
134 in REVIDX_FLAGS_ORDER needs to be stable to allow non-commutativity.
133 in REVIDX_FLAGS_ORDER needs to be stable to allow non-commutativity.
135
134
136 Returns a 2-tuple of ``(text, validatehash)`` where ``text`` is the
135 Returns a 2-tuple of ``(text, validatehash)`` where ``text`` is the
137 processed text and ``validatehash`` is a bool indicating whether the
136 processed text and ``validatehash`` is a bool indicating whether the
138 returned text should be checked for hash integrity.
137 returned text should be checked for hash integrity.
139 """
138 """
140 return self._processflagsfunc(text, flags, 'write')
139 return self._processflagsfunc(text, flags, 'write')[:2]
141
140
142 def _processflagsraw(self, text, flags):
141 def _processflagsraw(self, text, flags):
143 """Inspect revision data flags to check is the content hash should be
142 """Inspect revision data flags to check is the content hash should be
144 validated.
143 validated.
145
144
146 ``text`` - the revision data to process
145 ``text`` - the revision data to process
147 ``flags`` - the revision flags
146 ``flags`` - the revision flags
148
147
149 This method processes the flags in the order (or reverse order if
148 This method processes the flags in the order (or reverse order if
150 ``operation`` is 'write') defined by REVIDX_FLAGS_ORDER, applying the
149 ``operation`` is 'write') defined by REVIDX_FLAGS_ORDER, applying the
151 flag processors registered for present flags. The order of flags defined
150 flag processors registered for present flags. The order of flags defined
152 in REVIDX_FLAGS_ORDER needs to be stable to allow non-commutativity.
151 in REVIDX_FLAGS_ORDER needs to be stable to allow non-commutativity.
153
152
154 Returns a 2-tuple of ``(text, validatehash)`` where ``text`` is the
153 Returns a 2-tuple of ``(text, validatehash)`` where ``text`` is the
155 processed text and ``validatehash`` is a bool indicating whether the
154 processed text and ``validatehash`` is a bool indicating whether the
156 returned text should be checked for hash integrity.
155 returned text should be checked for hash integrity.
157 """
156 """
158 return self._processflagsfunc(text, flags, 'raw')[1]
157 return self._processflagsfunc(text, flags, 'raw')[1]
159
158
160 def _processflagsfunc(self, text, flags, operation):
159 def _processflagsfunc(self, text, flags, operation):
161 # fast path: no flag processors will run
160 # fast path: no flag processors will run
162 if flags == 0:
161 if flags == 0:
163 return text, True
162 return text, True, {}
164 if operation not in ('read', 'write', 'raw'):
163 if operation not in ('read', 'write', 'raw'):
165 raise error.ProgrammingError(_("invalid '%s' operation") %
164 raise error.ProgrammingError(_("invalid '%s' operation") %
166 operation)
165 operation)
167 # Check all flags are known.
166 # Check all flags are known.
168 if flags & ~REVIDX_KNOWN_FLAGS:
167 if flags & ~REVIDX_KNOWN_FLAGS:
169 raise self._flagserrorclass(_("incompatible revision flag '%#x'") %
168 raise self._flagserrorclass(_("incompatible revision flag '%#x'") %
170 (flags & ~REVIDX_KNOWN_FLAGS))
169 (flags & ~REVIDX_KNOWN_FLAGS))
171 validatehash = True
170 validatehash = True
172 # Depending on the operation (read or write), the order might be
171 # Depending on the operation (read or write), the order might be
173 # reversed due to non-commutative transforms.
172 # reversed due to non-commutative transforms.
174 orderedflags = REVIDX_FLAGS_ORDER
173 orderedflags = REVIDX_FLAGS_ORDER
175 if operation == 'write':
174 if operation == 'write':
176 orderedflags = reversed(orderedflags)
175 orderedflags = reversed(orderedflags)
177
176
177 outsidedata = {}
178 for flag in orderedflags:
178 for flag in orderedflags:
179 # If a flagprocessor has been registered for a known flag, apply the
179 # If a flagprocessor has been registered for a known flag, apply the
180 # related operation transform and update result tuple.
180 # related operation transform and update result tuple.
181 if flag & flags:
181 if flag & flags:
182 vhash = True
182 vhash = True
183
183
184 if flag not in self._flagprocessors:
184 if flag not in self._flagprocessors:
185 message = _("missing processor for flag '%#x'") % (flag)
185 message = _("missing processor for flag '%#x'") % (flag)
186 raise self._flagserrorclass(message)
186 raise self._flagserrorclass(message)
187
187
188 processor = self._flagprocessors[flag]
188 processor = self._flagprocessors[flag]
189 if processor is not None:
189 if processor is not None:
190 readtransform, writetransform, rawtransform = processor
190 readtransform, writetransform, rawtransform = processor
191
191
192 if operation == 'raw':
192 if operation == 'raw':
193 vhash = rawtransform(self, text)
193 vhash = rawtransform(self, text)
194 elif operation == 'read':
194 elif operation == 'read':
195 text, vhash = readtransform(self, text)
195 text, vhash = readtransform(self, text)
196 else: # write operation
196 else: # write operation
197 text, vhash = writetransform(self, text)
197 text, vhash = writetransform(self, text)
198 validatehash = validatehash and vhash
198 validatehash = validatehash and vhash
199
199
200 return text, validatehash
200 return text, validatehash, outsidedata
General Comments 0
You need to be logged in to leave comments. Login now