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