comparison mercurial/configitems.py @ 33499:0407a51b9d8c

codemod: register core configitems using a script This is done by a script [2] using RedBaron [1], a tool designed for doing code refactoring. All "default" values are decided by the script and are strongly consistent with the existing code. There are 2 changes done manually to fix tests: [warn] mercurial/exchange.py: experimental.bundle2-output-capture: default needs manual removal [warn] mercurial/localrepo.py: experimental.hook-track-tags: default needs manual removal Since RedBaron is not confident about how to indent things [2]. [1]: https://github.com/PyCQA/redbaron [2]: https://github.com/PyCQA/redbaron/issues/100 [3]: #!/usr/bin/env python # codemod_configitems.py - codemod tool to fill configitems # # Copyright 2017 Facebook, Inc. # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. from __future__ import absolute_import, print_function import os import sys import redbaron def readpath(path): with open(path) as f: return f.read() def writepath(path, content): with open(path, 'w') as f: f.write(content) _configmethods = {'config', 'configbool', 'configint', 'configbytes', 'configlist', 'configdate'} def extractstring(rnode): """get the string from a RedBaron string or call_argument node""" while rnode.type != 'string': rnode = rnode.value return rnode.value[1:-1] # unquote, "'str'" -> "str" def uiconfigitems(red): """match *.ui.config* pattern, yield (node, method, args, section, name)""" for node in red.find_all('atomtrailers'): entry = None try: obj = node[-3].value method = node[-2].value args = node[-1] section = args[0].value name = args[1].value if (obj in ('ui', 'self') and method in _configmethods and section.type == 'string' and name.type == 'string'): entry = (node, method, args, extractstring(section), extractstring(name)) except Exception: pass else: if entry: yield entry def coreconfigitems(red): """match coreconfigitem(...) pattern, yield (node, args, section, name)""" for node in red.find_all('atomtrailers'): entry = None try: args = node[1] section = args[0].value name = args[1].value if (node[0].value == 'coreconfigitem' and section.type == 'string' and name.type == 'string'): entry = (node, args, extractstring(section), extractstring(name)) except Exception: pass else: if entry: yield entry def registercoreconfig(cfgred, section, name, defaultrepr): """insert coreconfigitem to cfgred AST section and name are plain string, defaultrepr is a string """ # find a place to insert the "coreconfigitem" item entries = list(coreconfigitems(cfgred)) for node, args, nodesection, nodename in reversed(entries): if (nodesection, nodename) < (section, name): # insert after this entry node.insert_after( 'coreconfigitem(%r, %r,\n' ' default=%s,\n' ')' % (section, name, defaultrepr)) return def main(argv): if not argv: print('Usage: codemod_configitems.py FILES\n' 'For example, FILES could be "{hgext,mercurial}/*/**.py"') dirname = os.path.dirname reporoot = dirname(dirname(dirname(os.path.abspath(__file__)))) # register configitems to this destination cfgpath = os.path.join(reporoot, 'mercurial', 'configitems.py') cfgred = redbaron.RedBaron(readpath(cfgpath)) # state about what to do registered = set((s, n) for n, a, s, n in coreconfigitems(cfgred)) toregister = {} # {(section, name): defaultrepr} coreconfigs = set() # {(section, name)}, whether it's used in core # first loop: scan all files before taking any action for i, path in enumerate(argv): print('(%d/%d) scanning %s' % (i + 1, len(argv), path)) iscore = ('mercurial' in path) and ('hgext' not in path) red = redbaron.RedBaron(readpath(path)) # find all repo.ui.config* and ui.config* calls, and collect their # section, name and default value information. for node, method, args, section, name in uiconfigitems(red): if section == 'web': # [web] section has some weirdness, ignore them for now continue defaultrepr = None key = (section, name) if len(args) == 2: if key in registered: continue if method == 'configlist': defaultrepr = 'list' elif method == 'configbool': defaultrepr = 'False' else: defaultrepr = 'None' elif len(args) >= 3 and (args[2].target is None or args[2].target.value == 'default'): # try to understand the "default" value dnode = args[2].value if dnode.type == 'name': if dnode.value in {'None', 'True', 'False'}: defaultrepr = dnode.value elif dnode.type == 'string': defaultrepr = repr(dnode.value[1:-1]) elif dnode.type in ('int', 'float'): defaultrepr = dnode.value # inconsistent default if key in toregister and toregister[key] != defaultrepr: defaultrepr = None # interesting to rewrite if key not in registered: if defaultrepr is None: print('[note] %s: %s.%s: unsupported default' % (path, section, name)) registered.add(key) # skip checking it again else: toregister[key] = defaultrepr if iscore: coreconfigs.add(key) # second loop: rewrite files given "toregister" result for path in argv: # reconstruct redbaron - trade CPU for memory red = redbaron.RedBaron(readpath(path)) changed = False for node, method, args, section, name in uiconfigitems(red): key = (section, name) defaultrepr = toregister.get(key) if defaultrepr is None or key not in coreconfigs: continue if len(args) >= 3 and (args[2].target is None or args[2].target.value == 'default'): try: del args[2] changed = True except Exception: # redbaron fails to do the rewrite due to indentation # see https://github.com/PyCQA/redbaron/issues/100 print('[warn] %s: %s.%s: default needs manual removal' % (path, section, name)) if key not in registered: print('registering %s.%s' % (section, name)) registercoreconfig(cfgred, section, name, defaultrepr) registered.add(key) if changed: print('updating %s' % path) writepath(path, red.dumps()) if toregister: print('updating configitems.py') writepath(cfgpath, cfgred.dumps()) if __name__ == "__main__": sys.exit(main(sys.argv[1:]))
author Jun Wu <quark@fb.com>
date Fri, 14 Jul 2017 14:22:40 -0700
parents c514b4fb5e27
children 3b7e36f7e632
comparison
equal deleted inserted replaced
33498:b7a75b9a3386 33499:0407a51b9d8c
74 ) 74 )
75 # bundle.reorder: experimental config 75 # bundle.reorder: experimental config
76 coreconfigitem('bundle', 'reorder', 76 coreconfigitem('bundle', 'reorder',
77 default='auto', 77 default='auto',
78 ) 78 )
79 coreconfigitem('censor', 'policy',
80 default='abort',
81 )
82 coreconfigitem('chgserver', 'idletimeout',
83 default=3600,
84 )
85 coreconfigitem('chgserver', 'skiphash',
86 default=False,
87 )
88 coreconfigitem('cmdserver', 'log',
89 default=None,
90 )
79 coreconfigitem('color', 'mode', 91 coreconfigitem('color', 'mode',
80 default='auto', 92 default='auto',
81 ) 93 )
82 coreconfigitem('color', 'pagermode', 94 coreconfigitem('color', 'pagermode',
83 default=dynamicdefault, 95 default=dynamicdefault,
84 ) 96 )
97 coreconfigitem('commands', 'status.relative',
98 default=False,
99 )
100 coreconfigitem('commands', 'update.requiredest',
101 default=False,
102 )
85 coreconfigitem('devel', 'all-warnings', 103 coreconfigitem('devel', 'all-warnings',
86 default=False, 104 default=False,
87 ) 105 )
88 coreconfigitem('devel', 'bundle2.debug', 106 coreconfigitem('devel', 'bundle2.debug',
89 default=False, 107 default=False,
90 ) 108 )
91 coreconfigitem('devel', 'check-locks', 109 coreconfigitem('devel', 'check-locks',
92 default=False, 110 default=False,
93 ) 111 )
94 coreconfigitem('devel', 'check-relroot', 112 coreconfigitem('devel', 'check-relroot',
113 default=False,
114 )
115 coreconfigitem('devel', 'default-date',
116 default=None,
117 )
118 coreconfigitem('devel', 'deprec-warn',
95 default=False, 119 default=False,
96 ) 120 )
97 coreconfigitem('devel', 'disableloaddefaultcerts', 121 coreconfigitem('devel', 'disableloaddefaultcerts',
98 default=False, 122 default=False,
99 ) 123 )
110 default=False, 134 default=False,
111 ) 135 )
112 coreconfigitem('devel', 'strip-obsmarkers', 136 coreconfigitem('devel', 'strip-obsmarkers',
113 default=True, 137 default=True,
114 ) 138 )
139 coreconfigitem('email', 'charsets',
140 default=list,
141 )
142 coreconfigitem('email', 'method',
143 default='smtp',
144 )
145 coreconfigitem('experimental', 'bundle-phases',
146 default=False,
147 )
148 coreconfigitem('experimental', 'bundle2-advertise',
149 default=True,
150 )
151 coreconfigitem('experimental', 'bundle2-output-capture',
152 default=False,
153 )
154 coreconfigitem('experimental', 'bundle2.pushback',
155 default=False,
156 )
157 coreconfigitem('experimental', 'bundle2lazylocking',
158 default=False,
159 )
160 coreconfigitem('experimental', 'bundlecomplevel',
161 default=None,
162 )
163 coreconfigitem('experimental', 'changegroup3',
164 default=False,
165 )
166 coreconfigitem('experimental', 'clientcompressionengines',
167 default=list,
168 )
169 coreconfigitem('experimental', 'crecordtest',
170 default=None,
171 )
172 coreconfigitem('experimental', 'disablecopytrace',
173 default=False,
174 )
175 coreconfigitem('experimental', 'editortmpinhg',
176 default=False,
177 )
178 coreconfigitem('experimental', 'evolution',
179 default=list,
180 )
181 coreconfigitem('experimental', 'evolution.bundle-obsmarker',
182 default=False,
183 )
184 coreconfigitem('experimental', 'evolution.track-operation',
185 default=False,
186 )
187 coreconfigitem('experimental', 'exportableenviron',
188 default=list,
189 )
190 coreconfigitem('experimental', 'extendedheader.index',
191 default=None,
192 )
193 coreconfigitem('experimental', 'extendedheader.similarity',
194 default=False,
195 )
196 coreconfigitem('experimental', 'format.compression',
197 default='zlib',
198 )
199 coreconfigitem('experimental', 'graphshorten',
200 default=False,
201 )
202 coreconfigitem('experimental', 'hook-track-tags',
203 default=False,
204 )
205 coreconfigitem('experimental', 'httppostargs',
206 default=False,
207 )
208 coreconfigitem('experimental', 'manifestv2',
209 default=False,
210 )
211 coreconfigitem('experimental', 'mergedriver',
212 default=None,
213 )
214 coreconfigitem('experimental', 'obsmarkers-exchange-debug',
215 default=False,
216 )
217 coreconfigitem('experimental', 'revertalternateinteractivemode',
218 default=True,
219 )
220 coreconfigitem('experimental', 'revlogv2',
221 default=None,
222 )
223 coreconfigitem('experimental', 'spacemovesdown',
224 default=False,
225 )
226 coreconfigitem('experimental', 'treemanifest',
227 default=False,
228 )
229 coreconfigitem('experimental', 'updatecheck',
230 default=None,
231 )
115 coreconfigitem('format', 'aggressivemergedeltas', 232 coreconfigitem('format', 'aggressivemergedeltas',
116 default=False, 233 default=False,
117 ) 234 )
118 coreconfigitem('format', 'chunkcachesize', 235 coreconfigitem('format', 'chunkcachesize',
119 default=None, 236 default=None,
145 coreconfigitem('hostsecurity', 'ciphers', 262 coreconfigitem('hostsecurity', 'ciphers',
146 default=None, 263 default=None,
147 ) 264 )
148 coreconfigitem('hostsecurity', 'disabletls10warning', 265 coreconfigitem('hostsecurity', 'disabletls10warning',
149 default=False, 266 default=False,
267 )
268 coreconfigitem('http_proxy', 'always',
269 default=False,
270 )
271 coreconfigitem('http_proxy', 'host',
272 default=None,
273 )
274 coreconfigitem('http_proxy', 'no',
275 default=list,
276 )
277 coreconfigitem('http_proxy', 'passwd',
278 default=None,
279 )
280 coreconfigitem('http_proxy', 'user',
281 default=None,
282 )
283 coreconfigitem('merge', 'followcopies',
284 default=True,
285 )
286 coreconfigitem('pager', 'ignore',
287 default=list,
150 ) 288 )
151 coreconfigitem('patch', 'eol', 289 coreconfigitem('patch', 'eol',
152 default='strict', 290 default='strict',
153 ) 291 )
154 coreconfigitem('patch', 'fuzz', 292 coreconfigitem('patch', 'fuzz',
155 default=2, 293 default=2,
156 ) 294 )
295 coreconfigitem('paths', 'default',
296 default=None,
297 )
298 coreconfigitem('paths', 'default-push',
299 default=None,
300 )
301 coreconfigitem('phases', 'checksubrepos',
302 default='follow',
303 )
304 coreconfigitem('phases', 'publish',
305 default=True,
306 )
307 coreconfigitem('profiling', 'enabled',
308 default=False,
309 )
310 coreconfigitem('profiling', 'format',
311 default='text',
312 )
313 coreconfigitem('profiling', 'freq',
314 default=1000,
315 )
316 coreconfigitem('profiling', 'limit',
317 default=30,
318 )
319 coreconfigitem('profiling', 'nested',
320 default=0,
321 )
322 coreconfigitem('profiling', 'sort',
323 default='inlinetime',
324 )
325 coreconfigitem('profiling', 'statformat',
326 default='hotpath',
327 )
157 coreconfigitem('progress', 'assume-tty', 328 coreconfigitem('progress', 'assume-tty',
158 default=False, 329 default=False,
159 ) 330 )
331 coreconfigitem('progress', 'changedelay',
332 default=1,
333 )
160 coreconfigitem('progress', 'clear-complete', 334 coreconfigitem('progress', 'clear-complete',
161 default=True, 335 default=True,
336 )
337 coreconfigitem('progress', 'debug',
338 default=False,
339 )
340 coreconfigitem('progress', 'delay',
341 default=3,
342 )
343 coreconfigitem('progress', 'disable',
344 default=False,
162 ) 345 )
163 coreconfigitem('progress', 'estimate', 346 coreconfigitem('progress', 'estimate',
164 default=2, 347 default=2,
165 ) 348 )
349 coreconfigitem('progress', 'refresh',
350 default=0.1,
351 )
166 coreconfigitem('progress', 'width', 352 coreconfigitem('progress', 'width',
167 default=dynamicdefault, 353 default=dynamicdefault,
168 ) 354 )
169 coreconfigitem('server', 'bundle1', 355 coreconfigitem('server', 'bundle1',
170 default=True, 356 default=True,
185 default=1024, 371 default=1024,
186 ) 372 )
187 coreconfigitem('server', 'preferuncompressed', 373 coreconfigitem('server', 'preferuncompressed',
188 default=False, 374 default=False,
189 ) 375 )
376 coreconfigitem('server', 'uncompressed',
377 default=True,
378 )
190 coreconfigitem('server', 'uncompressedallowsecret', 379 coreconfigitem('server', 'uncompressedallowsecret',
191 default=False, 380 default=False,
192 ) 381 )
193 coreconfigitem('server', 'validate', 382 coreconfigitem('server', 'validate',
194 default=False, 383 default=False,
195 ) 384 )
196 coreconfigitem('server', 'zliblevel', 385 coreconfigitem('server', 'zliblevel',
197 default=-1, 386 default=-1,
198 ) 387 )
388 coreconfigitem('smtp', 'host',
389 default=None,
390 )
391 coreconfigitem('smtp', 'local_hostname',
392 default=None,
393 )
394 coreconfigitem('smtp', 'password',
395 default=None,
396 )
397 coreconfigitem('smtp', 'tls',
398 default='none',
399 )
400 coreconfigitem('smtp', 'username',
401 default=None,
402 )
403 coreconfigitem('sparse', 'missingwarning',
404 default=True,
405 )
406 coreconfigitem('trusted', 'groups',
407 default=list,
408 )
409 coreconfigitem('trusted', 'users',
410 default=list,
411 )
412 coreconfigitem('ui', '_usedassubrepo',
413 default=False,
414 )
415 coreconfigitem('ui', 'allowemptycommit',
416 default=False,
417 )
418 coreconfigitem('ui', 'archivemeta',
419 default=True,
420 )
421 coreconfigitem('ui', 'askusername',
422 default=False,
423 )
424 coreconfigitem('ui', 'clonebundlefallback',
425 default=False,
426 )
199 coreconfigitem('ui', 'clonebundleprefers', 427 coreconfigitem('ui', 'clonebundleprefers',
200 default=list, 428 default=list,
201 ) 429 )
430 coreconfigitem('ui', 'clonebundles',
431 default=True,
432 )
433 coreconfigitem('ui', 'commitsubrepos',
434 default=False,
435 )
436 coreconfigitem('ui', 'debug',
437 default=False,
438 )
439 coreconfigitem('ui', 'debugger',
440 default=None,
441 )
442 coreconfigitem('ui', 'forcemerge',
443 default=None,
444 )
445 coreconfigitem('ui', 'formatdebug',
446 default=False,
447 )
448 coreconfigitem('ui', 'formatjson',
449 default=False,
450 )
451 coreconfigitem('ui', 'formatted',
452 default=None,
453 )
454 coreconfigitem('ui', 'graphnodetemplate',
455 default=None,
456 )
457 coreconfigitem('ui', 'http2debuglevel',
458 default=None,
459 )
202 coreconfigitem('ui', 'interactive', 460 coreconfigitem('ui', 'interactive',
203 default=None, 461 default=None,
204 ) 462 )
463 coreconfigitem('ui', 'interface',
464 default=None,
465 )
466 coreconfigitem('ui', 'logblockedtimes',
467 default=False,
468 )
469 coreconfigitem('ui', 'logtemplate',
470 default=None,
471 )
472 coreconfigitem('ui', 'merge',
473 default=None,
474 )
475 coreconfigitem('ui', 'mergemarkers',
476 default='basic',
477 )
478 coreconfigitem('ui', 'nontty',
479 default=False,
480 )
481 coreconfigitem('ui', 'origbackuppath',
482 default=None,
483 )
484 coreconfigitem('ui', 'paginate',
485 default=True,
486 )
487 coreconfigitem('ui', 'patch',
488 default=None,
489 )
490 coreconfigitem('ui', 'portablefilenames',
491 default='warn',
492 )
493 coreconfigitem('ui', 'promptecho',
494 default=False,
495 )
205 coreconfigitem('ui', 'quiet', 496 coreconfigitem('ui', 'quiet',
497 default=False,
498 )
499 coreconfigitem('ui', 'quietbookmarkmove',
500 default=False,
501 )
502 coreconfigitem('ui', 'remotecmd',
503 default='hg',
504 )
505 coreconfigitem('ui', 'report_untrusted',
506 default=True,
507 )
508 coreconfigitem('ui', 'rollback',
509 default=True,
510 )
511 coreconfigitem('ui', 'slash',
512 default=False,
513 )
514 coreconfigitem('ui', 'ssh',
515 default='ssh',
516 )
517 coreconfigitem('ui', 'statuscopies',
518 default=False,
519 )
520 coreconfigitem('ui', 'strict',
521 default=False,
522 )
523 coreconfigitem('ui', 'style',
524 default='',
525 )
526 coreconfigitem('ui', 'supportcontact',
527 default=None,
528 )
529 coreconfigitem('ui', 'textwidth',
530 default=78,
531 )
532 coreconfigitem('ui', 'timeout',
533 default='600',
534 )
535 coreconfigitem('ui', 'traceback',
536 default=False,
537 )
538 coreconfigitem('ui', 'tweakdefaults',
539 default=False,
540 )
541 coreconfigitem('ui', 'usehttp2',
206 default=False, 542 default=False,
207 ) 543 )
208 coreconfigitem('ui', 'username', 544 coreconfigitem('ui', 'username',
209 alias=[('ui', 'user')] 545 alias=[('ui', 'user')]
546 )
547 coreconfigitem('ui', 'verbose',
548 default=False,
549 )
550 coreconfigitem('verify', 'skipflags',
551 default=None,
210 ) 552 )
211 coreconfigitem('worker', 'backgroundclose', 553 coreconfigitem('worker', 'backgroundclose',
212 default=dynamicdefault, 554 default=dynamicdefault,
213 ) 555 )
214 # Windows defaults to a limit of 512 open files. A buffer of 128 556 # Windows defaults to a limit of 512 open files. A buffer of 128