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