Show More
@@ -1,151 +1,153 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 | _flagserrorclass = error.RevlogError | |
|
91 | ||
|
90 | 92 | def _processflags(self, text, flags, operation, raw=False): |
|
91 | 93 | """Inspect revision data flags and applies transforms defined by |
|
92 | 94 | registered flag processors. |
|
93 | 95 | |
|
94 | 96 | ``text`` - the revision data to process |
|
95 | 97 | ``flags`` - the revision flags |
|
96 | 98 | ``operation`` - the operation being performed (read or write) |
|
97 | 99 | ``raw`` - an optional argument describing if the raw transform should be |
|
98 | 100 | applied. |
|
99 | 101 | |
|
100 | 102 | This method processes the flags in the order (or reverse order if |
|
101 | 103 | ``operation`` is 'write') defined by REVIDX_FLAGS_ORDER, applying the |
|
102 | 104 | flag processors registered for present flags. The order of flags defined |
|
103 | 105 | in REVIDX_FLAGS_ORDER needs to be stable to allow non-commutativity. |
|
104 | 106 | |
|
105 | 107 | Returns a 2-tuple of ``(text, validatehash)`` where ``text`` is the |
|
106 | 108 | processed text and ``validatehash`` is a bool indicating whether the |
|
107 | 109 | returned text should be checked for hash integrity. |
|
108 | 110 | |
|
109 | 111 | Note: If the ``raw`` argument is set, it has precedence over the |
|
110 | 112 | operation and will only update the value of ``validatehash``. |
|
111 | 113 | """ |
|
112 | 114 | # fast path: no flag processors will run |
|
113 | 115 | if flags == 0: |
|
114 | 116 | return text, True |
|
115 | 117 | if not operation in ('read', 'write'): |
|
116 | 118 | raise error.ProgrammingError(_("invalid '%s' operation") % |
|
117 | 119 | operation) |
|
118 | 120 | # Check all flags are known. |
|
119 | 121 | if flags & ~REVIDX_KNOWN_FLAGS: |
|
120 |
raise |
|
|
121 | (flags & ~REVIDX_KNOWN_FLAGS)) | |
|
122 | raise self._flagserrorclass(_("incompatible revision flag '%#x'") % | |
|
123 | (flags & ~REVIDX_KNOWN_FLAGS)) | |
|
122 | 124 | validatehash = True |
|
123 | 125 | # Depending on the operation (read or write), the order might be |
|
124 | 126 | # reversed due to non-commutative transforms. |
|
125 | 127 | orderedflags = REVIDX_FLAGS_ORDER |
|
126 | 128 | if operation == 'write': |
|
127 | 129 | orderedflags = reversed(orderedflags) |
|
128 | 130 | |
|
129 | 131 | for flag in orderedflags: |
|
130 | 132 | # If a flagprocessor has been registered for a known flag, apply the |
|
131 | 133 | # related operation transform and update result tuple. |
|
132 | 134 | if flag & flags: |
|
133 | 135 | vhash = True |
|
134 | 136 | |
|
135 | 137 | if flag not in self._flagprocessors: |
|
136 | 138 | message = _("missing processor for flag '%#x'") % (flag) |
|
137 |
raise |
|
|
139 | raise self._flagserrorclass(message) | |
|
138 | 140 | |
|
139 | 141 | processor = self._flagprocessors[flag] |
|
140 | 142 | if processor is not None: |
|
141 | 143 | readtransform, writetransform, rawtransform = processor |
|
142 | 144 | |
|
143 | 145 | if raw: |
|
144 | 146 | vhash = rawtransform(self, text) |
|
145 | 147 | elif operation == 'read': |
|
146 | 148 | text, vhash = readtransform(self, text) |
|
147 | 149 | else: # write operation |
|
148 | 150 | text, vhash = writetransform(self, text) |
|
149 | 151 | validatehash = validatehash and vhash |
|
150 | 152 | |
|
151 | 153 | return text, validatehash |
General Comments 0
You need to be logged in to leave comments.
Login now