Mercurial > public > mercurial-scm > hg
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 |