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 |
|
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 |
|
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