Show More
@@ -258,93 +258,3 b' class config(object):' | |||
|
258 | 258 | self.parse( |
|
259 | 259 | path, fp.read(), sections=sections, remap=remap, include=include |
|
260 | 260 | ) |
|
261 | ||
|
262 | ||
|
263 | def parselist(value): | |
|
264 | """parse a configuration value as a list of comma/space separated strings | |
|
265 | ||
|
266 | >>> parselist(b'this,is "a small" ,test') | |
|
267 | ['this', 'is', 'a small', 'test'] | |
|
268 | """ | |
|
269 | ||
|
270 | def _parse_plain(parts, s, offset): | |
|
271 | whitespace = False | |
|
272 | while offset < len(s) and ( | |
|
273 | s[offset : offset + 1].isspace() or s[offset : offset + 1] == b',' | |
|
274 | ): | |
|
275 | whitespace = True | |
|
276 | offset += 1 | |
|
277 | if offset >= len(s): | |
|
278 | return None, parts, offset | |
|
279 | if whitespace: | |
|
280 | parts.append(b'') | |
|
281 | if s[offset : offset + 1] == b'"' and not parts[-1]: | |
|
282 | return _parse_quote, parts, offset + 1 | |
|
283 | elif s[offset : offset + 1] == b'"' and parts[-1][-1:] == b'\\': | |
|
284 | parts[-1] = parts[-1][:-1] + s[offset : offset + 1] | |
|
285 | return _parse_plain, parts, offset + 1 | |
|
286 | parts[-1] += s[offset : offset + 1] | |
|
287 | return _parse_plain, parts, offset + 1 | |
|
288 | ||
|
289 | def _parse_quote(parts, s, offset): | |
|
290 | if offset < len(s) and s[offset : offset + 1] == b'"': # "" | |
|
291 | parts.append(b'') | |
|
292 | offset += 1 | |
|
293 | while offset < len(s) and ( | |
|
294 | s[offset : offset + 1].isspace() | |
|
295 | or s[offset : offset + 1] == b',' | |
|
296 | ): | |
|
297 | offset += 1 | |
|
298 | return _parse_plain, parts, offset | |
|
299 | ||
|
300 | while offset < len(s) and s[offset : offset + 1] != b'"': | |
|
301 | if ( | |
|
302 | s[offset : offset + 1] == b'\\' | |
|
303 | and offset + 1 < len(s) | |
|
304 | and s[offset + 1 : offset + 2] == b'"' | |
|
305 | ): | |
|
306 | offset += 1 | |
|
307 | parts[-1] += b'"' | |
|
308 | else: | |
|
309 | parts[-1] += s[offset : offset + 1] | |
|
310 | offset += 1 | |
|
311 | ||
|
312 | if offset >= len(s): | |
|
313 | real_parts = _configlist(parts[-1]) | |
|
314 | if not real_parts: | |
|
315 | parts[-1] = b'"' | |
|
316 | else: | |
|
317 | real_parts[0] = b'"' + real_parts[0] | |
|
318 | parts = parts[:-1] | |
|
319 | parts.extend(real_parts) | |
|
320 | return None, parts, offset | |
|
321 | ||
|
322 | offset += 1 | |
|
323 | while offset < len(s) and s[offset : offset + 1] in [b' ', b',']: | |
|
324 | offset += 1 | |
|
325 | ||
|
326 | if offset < len(s): | |
|
327 | if offset + 1 == len(s) and s[offset : offset + 1] == b'"': | |
|
328 | parts[-1] += b'"' | |
|
329 | offset += 1 | |
|
330 | else: | |
|
331 | parts.append(b'') | |
|
332 | else: | |
|
333 | return None, parts, offset | |
|
334 | ||
|
335 | return _parse_plain, parts, offset | |
|
336 | ||
|
337 | def _configlist(s): | |
|
338 | s = s.rstrip(b' ,') | |
|
339 | if not s: | |
|
340 | return [] | |
|
341 | parser, parts, offset = _parse_plain, [b''], 0 | |
|
342 | while parser: | |
|
343 | parser, parts, offset = parser(parts, s, offset) | |
|
344 | return parts | |
|
345 | ||
|
346 | if value is not None and isinstance(value, bytes): | |
|
347 | result = _configlist(value.lstrip(b' ,\n')) | |
|
348 | else: | |
|
349 | result = value | |
|
350 | return result or [] |
@@ -887,10 +887,10 b' class ui(object):' | |||
|
887 | 887 | """ |
|
888 | 888 | # default is not always a list |
|
889 | 889 | v = self.configwith( |
|
890 |
|
|
|
890 | stringutil.parselist, section, name, default, b'list', untrusted | |
|
891 | 891 | ) |
|
892 | 892 | if isinstance(v, bytes): |
|
893 |
return |
|
|
893 | return stringutil.parselist(v) | |
|
894 | 894 | elif v is None: |
|
895 | 895 | return [] |
|
896 | 896 | return v |
@@ -868,6 +868,96 b' def parsebool(s):' | |||
|
868 | 868 | return _booleans.get(s.lower(), None) |
|
869 | 869 | |
|
870 | 870 | |
|
871 | def parselist(value): | |
|
872 | """parse a configuration value as a list of comma/space separated strings | |
|
873 | ||
|
874 | >>> parselist(b'this,is "a small" ,test') | |
|
875 | ['this', 'is', 'a small', 'test'] | |
|
876 | """ | |
|
877 | ||
|
878 | def _parse_plain(parts, s, offset): | |
|
879 | whitespace = False | |
|
880 | while offset < len(s) and ( | |
|
881 | s[offset : offset + 1].isspace() or s[offset : offset + 1] == b',' | |
|
882 | ): | |
|
883 | whitespace = True | |
|
884 | offset += 1 | |
|
885 | if offset >= len(s): | |
|
886 | return None, parts, offset | |
|
887 | if whitespace: | |
|
888 | parts.append(b'') | |
|
889 | if s[offset : offset + 1] == b'"' and not parts[-1]: | |
|
890 | return _parse_quote, parts, offset + 1 | |
|
891 | elif s[offset : offset + 1] == b'"' and parts[-1][-1:] == b'\\': | |
|
892 | parts[-1] = parts[-1][:-1] + s[offset : offset + 1] | |
|
893 | return _parse_plain, parts, offset + 1 | |
|
894 | parts[-1] += s[offset : offset + 1] | |
|
895 | return _parse_plain, parts, offset + 1 | |
|
896 | ||
|
897 | def _parse_quote(parts, s, offset): | |
|
898 | if offset < len(s) and s[offset : offset + 1] == b'"': # "" | |
|
899 | parts.append(b'') | |
|
900 | offset += 1 | |
|
901 | while offset < len(s) and ( | |
|
902 | s[offset : offset + 1].isspace() | |
|
903 | or s[offset : offset + 1] == b',' | |
|
904 | ): | |
|
905 | offset += 1 | |
|
906 | return _parse_plain, parts, offset | |
|
907 | ||
|
908 | while offset < len(s) and s[offset : offset + 1] != b'"': | |
|
909 | if ( | |
|
910 | s[offset : offset + 1] == b'\\' | |
|
911 | and offset + 1 < len(s) | |
|
912 | and s[offset + 1 : offset + 2] == b'"' | |
|
913 | ): | |
|
914 | offset += 1 | |
|
915 | parts[-1] += b'"' | |
|
916 | else: | |
|
917 | parts[-1] += s[offset : offset + 1] | |
|
918 | offset += 1 | |
|
919 | ||
|
920 | if offset >= len(s): | |
|
921 | real_parts = _configlist(parts[-1]) | |
|
922 | if not real_parts: | |
|
923 | parts[-1] = b'"' | |
|
924 | else: | |
|
925 | real_parts[0] = b'"' + real_parts[0] | |
|
926 | parts = parts[:-1] | |
|
927 | parts.extend(real_parts) | |
|
928 | return None, parts, offset | |
|
929 | ||
|
930 | offset += 1 | |
|
931 | while offset < len(s) and s[offset : offset + 1] in [b' ', b',']: | |
|
932 | offset += 1 | |
|
933 | ||
|
934 | if offset < len(s): | |
|
935 | if offset + 1 == len(s) and s[offset : offset + 1] == b'"': | |
|
936 | parts[-1] += b'"' | |
|
937 | offset += 1 | |
|
938 | else: | |
|
939 | parts.append(b'') | |
|
940 | else: | |
|
941 | return None, parts, offset | |
|
942 | ||
|
943 | return _parse_plain, parts, offset | |
|
944 | ||
|
945 | def _configlist(s): | |
|
946 | s = s.rstrip(b' ,') | |
|
947 | if not s: | |
|
948 | return [] | |
|
949 | parser, parts, offset = _parse_plain, [b''], 0 | |
|
950 | while parser: | |
|
951 | parser, parts, offset = parser(parts, s, offset) | |
|
952 | return parts | |
|
953 | ||
|
954 | if value is not None and isinstance(value, bytes): | |
|
955 | result = _configlist(value.lstrip(b' ,\n')) | |
|
956 | else: | |
|
957 | result = value | |
|
958 | return result or [] | |
|
959 | ||
|
960 | ||
|
871 | 961 | def evalpythonliteral(s): |
|
872 | 962 | """Evaluate a string containing a Python literal expression""" |
|
873 | 963 | # We could backport our tokenizer hack to rewrite '' to u'' if we want |
@@ -361,10 +361,11 b' impl Config {' | |||
|
361 | 361 | /// |
|
362 | 362 | /// This is appropriate for new configuration keys. The value syntax is |
|
363 | 363 | /// **not** the same as most existing list-valued config, which has Python |
|
364 |
/// parsing implemented in `parselist()` in |
|
|
365 | /// Faithfully porting that parsing algorithm to Rust (including behavior | |
|
366 | /// that are arguably bugs) turned out to be non-trivial and hasn’t been | |
|
367 | /// completed as of this writing. | |
|
364 | /// parsing implemented in `parselist()` in | |
|
365 | /// `mercurial/utils/stringutil.py`. Faithfully porting that parsing | |
|
366 | /// algorithm to Rust (including behavior that are arguably bugs) | |
|
367 | /// turned out to be non-trivial and hasn’t been completed as of this | |
|
368 | /// writing. | |
|
368 | 369 | /// |
|
369 | 370 | /// Instead, the "simple" syntax is: split on comma, then trim leading and |
|
370 | 371 | /// trailing whitespace of each component. Quotes or backslashes are not |
@@ -131,7 +131,6 b' expected_mods_tested = set(' | |||
|
131 | 131 | ('mercurial.changelog', '{}'), |
|
132 | 132 | ('mercurial.cmdutil', '{}'), |
|
133 | 133 | ('mercurial.color', '{}'), |
|
134 | ('mercurial.config', '{}'), | |
|
135 | 134 | ('mercurial.dagparser', "{'optionflags': 4}"), |
|
136 | 135 | ('mercurial.encoding', '{}'), |
|
137 | 136 | ('mercurial.fancyopts', '{}'), |
General Comments 0
You need to be logged in to leave comments.
Login now