Patchwork [V2] codemod: register core configitems using a script

login
register
mail settings
Submitter Jun Wu
Date July 14, 2017, 9:23 p.m.
Message ID <4ba8b3e871116249d7a9.1500067399@x1c>
Download mbox | patch
Permalink /patch/22382/
State Accepted
Headers show

Comments

Jun Wu - July 14, 2017, 9:23 p.m.
# HG changeset patch
# User Jun Wu <quark@fb.com>
# Date 1500067360 25200
#      Fri Jul 14 14:22:40 2017 -0700
# Node ID 4ba8b3e871116249d7a99062a08955446e896047
# Parent  80e1331a7fe970f3e56fde9044949d72d3afdf30
# Available At https://bitbucket.org/quark-zju/hg-draft
#              hg pull https://bitbucket.org/quark-zju/hg-draft -r 4ba8b3e87111
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:]))
via Mercurial-devel - July 15, 2017, 12:04 a.m.
On Fri, Jul 14, 2017 at 2:23 PM, Jun Wu <quark@fb.com> wrote:
> # HG changeset patch
> # User Jun Wu <quark@fb.com>
> # Date 1500067360 25200
> #      Fri Jul 14 14:22:40 2017 -0700
> # Node ID 4ba8b3e871116249d7a99062a08955446e896047
> # Parent  80e1331a7fe970f3e56fde9044949d72d3afdf30
> # Available At https://bitbucket.org/quark-zju/hg-draft
> #              hg pull https://bitbucket.org/quark-zju/hg-draft -r 4ba8b3e87111
> codemod: register core configitems using a script

Queued, thanks!

Patch

diff --git a/hgext/journal.py b/hgext/journal.py
--- a/hgext/journal.py
+++ b/hgext/journal.py
@@ -304,5 +304,5 @@  class journalstorage(object):
             l = lock.lock(
                 vfs, 'namejournal.lock',
-                int(self.ui.config("ui", "timeout", "600")), desc=desc)
+                int(self.ui.config("ui", "timeout")), desc=desc)
             self.ui.warn(_("got lock after %s seconds\n") % l.delay)
         self._lockref = weakref.ref(l)
diff --git a/hgext/largefiles/overrides.py b/hgext/largefiles/overrides.py
--- a/hgext/largefiles/overrides.py
+++ b/hgext/largefiles/overrides.py
@@ -974,5 +974,5 @@  def overridearchive(orig, repo, dest, no
     archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
 
-    if repo.ui.configbool("ui", "archivemeta", True):
+    if repo.ui.configbool("ui", "archivemeta"):
         write('.hg_archival.txt', 0o644, False,
               lambda: archival.buildmetadata(ctx))
diff --git a/mercurial/archival.py b/mercurial/archival.py
--- a/mercurial/archival.py
+++ b/mercurial/archival.py
@@ -308,5 +308,5 @@  def archive(repo, dest, node, kind, deco
     archiver = archivers[kind](dest, mtime or ctx.date()[0])
 
-    if repo.ui.configbool("ui", "archivemeta", True):
+    if repo.ui.configbool("ui", "archivemeta"):
         name = '.hg_archival.txt'
         if not matchfn or matchfn(name):
diff --git a/mercurial/bookmarks.py b/mercurial/bookmarks.py
--- a/mercurial/bookmarks.py
+++ b/mercurial/bookmarks.py
@@ -534,5 +534,5 @@  def updatefromremote(ui, repo, remotemar
     status = ui.status
     warn = ui.warn
-    if ui.configbool('ui', 'quietbookmarkmove', False):
+    if ui.configbool('ui', 'quietbookmarkmove'):
         status = warn = ui.debug
 
diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py
--- a/mercurial/bundle2.py
+++ b/mercurial/bundle2.py
@@ -1802,5 +1802,5 @@  def handleobsmarker(op, inpart):
     tr = op.gettransaction()
     markerdata = inpart.read()
-    if op.ui.config('experimental', 'obsmarkers-exchange-debug', False):
+    if op.ui.config('experimental', 'obsmarkers-exchange-debug'):
         op.ui.write(('obsmarker-exchange: %i bytes received\n')
                     % len(markerdata))
diff --git a/mercurial/chgserver.py b/mercurial/chgserver.py
--- a/mercurial/chgserver.py
+++ b/mercurial/chgserver.py
@@ -486,5 +486,5 @@  class chgunixservicehandler(object):
     def __init__(self, ui):
         self.ui = ui
-        self._idletimeout = ui.configint('chgserver', 'idletimeout', 3600)
+        self._idletimeout = ui.configint('chgserver', 'idletimeout')
         self._lastactive = time.time()
 
@@ -498,5 +498,5 @@  class chgunixservicehandler(object):
     def _inithashstate(self, address):
         self._baseaddress = address
-        if self.ui.configbool('chgserver', 'skiphash', False):
+        if self.ui.configbool('chgserver', 'skiphash'):
             self._hashstate = None
             self._realaddress = address
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -209,5 +209,5 @@  def recordfilter(ui, originalhunks, oper
     """
     usecurses = crecordmod.checkcurses(ui)
-    testfile = ui.config('experimental', 'crecordtest', None)
+    testfile = ui.config('experimental', 'crecordtest')
     oldwrite = setupwrapcolorwrite(ui)
     try:
@@ -1688,5 +1688,5 @@  def _lookuplogtemplate(ui, tmpl, style):
             return logtemplatespec(templater.unquotestring(tmpl), None)
         else:
-            style = util.expandpath(ui.config('ui', 'style', ''))
+            style = util.expandpath(ui.config('ui', 'style'))
 
     if not tmpl and style:
@@ -3407,6 +3407,5 @@  def _performrevert(repo, parents, ctx, a
             operation = 'revert'
             reversehunks = repo.ui.configbool('experimental',
-                                              'revertalternateinteractivemode',
-                                              True)
+                'revertalternateinteractivemode')
         if reversehunks:
             diff = patch.diff(repo, ctx.node(), None, m, opts=diffopts)
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1228,7 +1228,7 @@  def bundle(ui, repo, fname, dest=None, *
 
     contentopts = {'cg.version': cgversion}
-    if repo.ui.configbool('experimental', 'evolution.bundle-obsmarker', False):
+    if repo.ui.configbool('experimental', 'evolution.bundle-obsmarker'):
         contentopts['obsolescence'] = True
-    if repo.ui.configbool('experimental', 'bundle-phases', False):
+    if repo.ui.configbool('experimental', 'bundle-phases'):
         contentopts['phases'] = True
     bundle2.writenewbundle(ui, repo, 'bundle', fname, bversion, outgoing,
@@ -4525,5 +4525,5 @@  def rollback(ui, repo, **opts):
     Returns 0 on success, 1 if no rollback data is available.
     """
-    if not ui.configbool('ui', 'rollback', True):
+    if not ui.configbool('ui', 'rollback'):
         raise error.Abort(_('rollback is disabled because it is unsafe'),
                           hint=('see `hg help -v rollback` for information'))
diff --git a/mercurial/commandserver.py b/mercurial/commandserver.py
--- a/mercurial/commandserver.py
+++ b/mercurial/commandserver.py
@@ -157,5 +157,5 @@  class server(object):
 
         # developer config: cmdserver.log
-        logpath = ui.config("cmdserver", "log", None)
+        logpath = ui.config("cmdserver", "log")
         if logpath:
             global logfile
diff --git a/mercurial/configitems.py b/mercurial/configitems.py
--- a/mercurial/configitems.py
+++ b/mercurial/configitems.py
@@ -77,4 +77,16 @@  coreconfigitem('bundle', 'reorder',
     default='auto',
 )
+coreconfigitem('censor', 'policy',
+    default='abort',
+)
+coreconfigitem('chgserver', 'idletimeout',
+    default=3600,
+)
+coreconfigitem('chgserver', 'skiphash',
+    default=False,
+)
+coreconfigitem('cmdserver', 'log',
+    default=None,
+)
 coreconfigitem('color', 'mode',
     default='auto',
@@ -83,4 +95,10 @@  coreconfigitem('color', 'pagermode',
     default=dynamicdefault,
 )
+coreconfigitem('commands', 'status.relative',
+    default=False,
+)
+coreconfigitem('commands', 'update.requiredest',
+    default=False,
+)
 coreconfigitem('devel', 'all-warnings',
     default=False,
@@ -95,4 +113,10 @@  coreconfigitem('devel', 'check-relroot',
     default=False,
 )
+coreconfigitem('devel', 'default-date',
+    default=None,
+)
+coreconfigitem('devel', 'deprec-warn',
+    default=False,
+)
 coreconfigitem('devel', 'disableloaddefaultcerts',
     default=False,
@@ -113,4 +137,97 @@  coreconfigitem('devel', 'strip-obsmarker
     default=True,
 )
+coreconfigitem('email', 'charsets',
+    default=list,
+)
+coreconfigitem('email', 'method',
+    default='smtp',
+)
+coreconfigitem('experimental', 'bundle-phases',
+    default=False,
+)
+coreconfigitem('experimental', 'bundle2-advertise',
+    default=True,
+)
+coreconfigitem('experimental', 'bundle2-output-capture',
+    default=False,
+)
+coreconfigitem('experimental', 'bundle2.pushback',
+    default=False,
+)
+coreconfigitem('experimental', 'bundle2lazylocking',
+    default=False,
+)
+coreconfigitem('experimental', 'bundlecomplevel',
+    default=None,
+)
+coreconfigitem('experimental', 'changegroup3',
+    default=False,
+)
+coreconfigitem('experimental', 'clientcompressionengines',
+    default=list,
+)
+coreconfigitem('experimental', 'crecordtest',
+    default=None,
+)
+coreconfigitem('experimental', 'disablecopytrace',
+    default=False,
+)
+coreconfigitem('experimental', 'editortmpinhg',
+    default=False,
+)
+coreconfigitem('experimental', 'evolution',
+    default=list,
+)
+coreconfigitem('experimental', 'evolution.bundle-obsmarker',
+    default=False,
+)
+coreconfigitem('experimental', 'evolution.track-operation',
+    default=False,
+)
+coreconfigitem('experimental', 'exportableenviron',
+    default=list,
+)
+coreconfigitem('experimental', 'extendedheader.index',
+    default=None,
+)
+coreconfigitem('experimental', 'extendedheader.similarity',
+    default=False,
+)
+coreconfigitem('experimental', 'format.compression',
+    default='zlib',
+)
+coreconfigitem('experimental', 'graphshorten',
+    default=False,
+)
+coreconfigitem('experimental', 'hook-track-tags',
+    default=False,
+)
+coreconfigitem('experimental', 'httppostargs',
+    default=False,
+)
+coreconfigitem('experimental', 'manifestv2',
+    default=False,
+)
+coreconfigitem('experimental', 'mergedriver',
+    default=None,
+)
+coreconfigitem('experimental', 'obsmarkers-exchange-debug',
+    default=False,
+)
+coreconfigitem('experimental', 'revertalternateinteractivemode',
+    default=True,
+)
+coreconfigitem('experimental', 'revlogv2',
+    default=None,
+)
+coreconfigitem('experimental', 'spacemovesdown',
+    default=False,
+)
+coreconfigitem('experimental', 'treemanifest',
+    default=False,
+)
+coreconfigitem('experimental', 'updatecheck',
+    default=None,
+)
 coreconfigitem('format', 'aggressivemergedeltas',
     default=False,
@@ -149,4 +266,25 @@  coreconfigitem('hostsecurity', 'disablet
     default=False,
 )
+coreconfigitem('http_proxy', 'always',
+    default=False,
+)
+coreconfigitem('http_proxy', 'host',
+    default=None,
+)
+coreconfigitem('http_proxy', 'no',
+    default=list,
+)
+coreconfigitem('http_proxy', 'passwd',
+    default=None,
+)
+coreconfigitem('http_proxy', 'user',
+    default=None,
+)
+coreconfigitem('merge', 'followcopies',
+    default=True,
+)
+coreconfigitem('pager', 'ignore',
+    default=list,
+)
 coreconfigitem('patch', 'eol',
     default='strict',
@@ -155,13 +293,61 @@  coreconfigitem('patch', 'fuzz',
     default=2,
 )
+coreconfigitem('paths', 'default',
+    default=None,
+)
+coreconfigitem('paths', 'default-push',
+    default=None,
+)
+coreconfigitem('phases', 'checksubrepos',
+    default='follow',
+)
+coreconfigitem('phases', 'publish',
+    default=True,
+)
+coreconfigitem('profiling', 'enabled',
+    default=False,
+)
+coreconfigitem('profiling', 'format',
+    default='text',
+)
+coreconfigitem('profiling', 'freq',
+    default=1000,
+)
+coreconfigitem('profiling', 'limit',
+    default=30,
+)
+coreconfigitem('profiling', 'nested',
+    default=0,
+)
+coreconfigitem('profiling', 'sort',
+    default='inlinetime',
+)
+coreconfigitem('profiling', 'statformat',
+    default='hotpath',
+)
 coreconfigitem('progress', 'assume-tty',
     default=False,
 )
+coreconfigitem('progress', 'changedelay',
+    default=1,
+)
 coreconfigitem('progress', 'clear-complete',
     default=True,
 )
+coreconfigitem('progress', 'debug',
+    default=False,
+)
+coreconfigitem('progress', 'delay',
+    default=3,
+)
+coreconfigitem('progress', 'disable',
+    default=False,
+)
 coreconfigitem('progress', 'estimate',
     default=2,
 )
+coreconfigitem('progress', 'refresh',
+    default=0.1,
+)
 coreconfigitem('progress', 'width',
     default=dynamicdefault,
@@ -188,4 +374,7 @@  coreconfigitem('server', 'preferuncompre
     default=False,
 )
+coreconfigitem('server', 'uncompressed',
+    default=True,
+)
 coreconfigitem('server', 'uncompressedallowsecret',
     default=False,
@@ -197,16 +386,169 @@  coreconfigitem('server', 'zliblevel',
     default=-1,
 )
+coreconfigitem('smtp', 'host',
+    default=None,
+)
+coreconfigitem('smtp', 'local_hostname',
+    default=None,
+)
+coreconfigitem('smtp', 'password',
+    default=None,
+)
+coreconfigitem('smtp', 'tls',
+    default='none',
+)
+coreconfigitem('smtp', 'username',
+    default=None,
+)
+coreconfigitem('sparse', 'missingwarning',
+    default=True,
+)
+coreconfigitem('trusted', 'groups',
+    default=list,
+)
+coreconfigitem('trusted', 'users',
+    default=list,
+)
+coreconfigitem('ui', '_usedassubrepo',
+    default=False,
+)
+coreconfigitem('ui', 'allowemptycommit',
+    default=False,
+)
+coreconfigitem('ui', 'archivemeta',
+    default=True,
+)
+coreconfigitem('ui', 'askusername',
+    default=False,
+)
+coreconfigitem('ui', 'clonebundlefallback',
+    default=False,
+)
 coreconfigitem('ui', 'clonebundleprefers',
     default=list,
 )
+coreconfigitem('ui', 'clonebundles',
+    default=True,
+)
+coreconfigitem('ui', 'commitsubrepos',
+    default=False,
+)
+coreconfigitem('ui', 'debug',
+    default=False,
+)
+coreconfigitem('ui', 'debugger',
+    default=None,
+)
+coreconfigitem('ui', 'forcemerge',
+    default=None,
+)
+coreconfigitem('ui', 'formatdebug',
+    default=False,
+)
+coreconfigitem('ui', 'formatjson',
+    default=False,
+)
+coreconfigitem('ui', 'formatted',
+    default=None,
+)
+coreconfigitem('ui', 'graphnodetemplate',
+    default=None,
+)
+coreconfigitem('ui', 'http2debuglevel',
+    default=None,
+)
 coreconfigitem('ui', 'interactive',
     default=None,
 )
+coreconfigitem('ui', 'interface',
+    default=None,
+)
+coreconfigitem('ui', 'logblockedtimes',
+    default=False,
+)
+coreconfigitem('ui', 'logtemplate',
+    default=None,
+)
+coreconfigitem('ui', 'merge',
+    default=None,
+)
+coreconfigitem('ui', 'mergemarkers',
+    default='basic',
+)
+coreconfigitem('ui', 'nontty',
+    default=False,
+)
+coreconfigitem('ui', 'origbackuppath',
+    default=None,
+)
+coreconfigitem('ui', 'paginate',
+    default=True,
+)
+coreconfigitem('ui', 'patch',
+    default=None,
+)
+coreconfigitem('ui', 'portablefilenames',
+    default='warn',
+)
+coreconfigitem('ui', 'promptecho',
+    default=False,
+)
 coreconfigitem('ui', 'quiet',
     default=False,
 )
+coreconfigitem('ui', 'quietbookmarkmove',
+    default=False,
+)
+coreconfigitem('ui', 'remotecmd',
+    default='hg',
+)
+coreconfigitem('ui', 'report_untrusted',
+    default=True,
+)
+coreconfigitem('ui', 'rollback',
+    default=True,
+)
+coreconfigitem('ui', 'slash',
+    default=False,
+)
+coreconfigitem('ui', 'ssh',
+    default='ssh',
+)
+coreconfigitem('ui', 'statuscopies',
+    default=False,
+)
+coreconfigitem('ui', 'strict',
+    default=False,
+)
+coreconfigitem('ui', 'style',
+    default='',
+)
+coreconfigitem('ui', 'supportcontact',
+    default=None,
+)
+coreconfigitem('ui', 'textwidth',
+    default=78,
+)
+coreconfigitem('ui', 'timeout',
+    default='600',
+)
+coreconfigitem('ui', 'traceback',
+    default=False,
+)
+coreconfigitem('ui', 'tweakdefaults',
+    default=False,
+)
+coreconfigitem('ui', 'usehttp2',
+    default=False,
+)
 coreconfigitem('ui', 'username',
     alias=[('ui', 'user')]
 )
+coreconfigitem('ui', 'verbose',
+    default=False,
+)
+coreconfigitem('verify', 'skipflags',
+    default=None,
+)
 coreconfigitem('worker', 'backgroundclose',
     default=dynamicdefault,
diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -1232,5 +1232,5 @@  class filectx(basefilectx):
             return self._filelog.read(self._filenode)
         except error.CensoredNodeError:
-            if self._repo.ui.config("censor", "policy", "abort") == "ignore":
+            if self._repo.ui.config("censor", "policy") == "ignore":
                 return ""
             raise error.Abort(_("censored node: %s") % short(self._filenode),
diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py
--- a/mercurial/dispatch.py
+++ b/mercurial/dispatch.py
@@ -917,5 +917,5 @@  def _exceptionwarning(ui):
     ct = util.versiontuple(n=2)
     worst = None, ct, ''
-    if ui.config('ui', 'supportcontact', None) is None:
+    if ui.config('ui', 'supportcontact') is None:
         for name, mod in extensions.extensions():
             testedwith = getattr(mod, 'testedwith', '')
@@ -951,5 +951,5 @@  def _exceptionwarning(ui):
                    % (name, testedwith, name, report))
     else:
-        bugtracker = ui.config('ui', 'supportcontact', None)
+        bugtracker = ui.config('ui', 'supportcontact')
         if bugtracker is None:
             bugtracker = _("https://mercurial-scm.org/wiki/BugTracker")
diff --git a/mercurial/exchange.py b/mercurial/exchange.py
--- a/mercurial/exchange.py
+++ b/mercurial/exchange.py
@@ -548,5 +548,5 @@  def _pushdiscoveryphase(pushop):
     remotephases = pushop.remote.listkeys('phases')
     publishing = remotephases.get('publishing', False)
-    if (pushop.ui.configbool('ui', '_usedassubrepo', False)
+    if (pushop.ui.configbool('ui', '_usedassubrepo')
         and remotephases    # server supports phases
         and not pushop.outgoing.missing # no changesets to be pushed
@@ -994,5 +994,5 @@  def _pushsyncphase(pushop):
     # even when we don't push, exchanging phase data is useful
     remotephases = pushop.remote.listkeys('phases')
-    if (pushop.ui.configbool('ui', '_usedassubrepo', False)
+    if (pushop.ui.configbool('ui', '_usedassubrepo')
         and remotephases    # server supports phases
         and pushop.cgresult is None # nothing was pushed
@@ -1727,6 +1727,5 @@  def unbundle(repo, cg, heads, source, ur
     recordout = None
     # quick fix for output mismatch with bundle2 in 3.4
-    captureoutput = repo.ui.configbool('experimental', 'bundle2-output-capture',
-                                       False)
+    captureoutput = repo.ui.configbool('experimental', 'bundle2-output-capture')
     if url.startswith('remote:http:') or url.startswith('remote:https:'):
         captureoutput = True
@@ -1793,5 +1792,5 @@  def _maybeapplyclonebundle(pullop):
     remote = pullop.remote
 
-    if not repo.ui.configbool('ui', 'clonebundles', True):
+    if not repo.ui.configbool('ui', 'clonebundles'):
         return
 
@@ -1842,5 +1841,5 @@  def _maybeapplyclonebundle(pullop):
     # clients flooding a server that was expecting expensive
     # clone load to be offloaded.
-    elif repo.ui.configbool('ui', 'clonebundlefallback', False):
+    elif repo.ui.configbool('ui', 'clonebundlefallback'):
         repo.ui.warn(_('falling back to normal clone\n'))
     else:
diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py
--- a/mercurial/filemerge.py
+++ b/mercurial/filemerge.py
@@ -686,5 +686,5 @@  def _filemerge(premerge, repo, mynode, o
     r = 1
     try:
-        markerstyle = ui.config('ui', 'mergemarkers', 'basic')
+        markerstyle = ui.config('ui', 'mergemarkers')
         if not labels:
             labels = _defaultconflictlabels
diff --git a/mercurial/help.py b/mercurial/help.py
--- a/mercurial/help.py
+++ b/mercurial/help.py
@@ -648,5 +648,5 @@  def formattedhelp(ui, commands, name, ke
             else:
                 section = remaining
-    textwidth = ui.configint('ui', 'textwidth', 78)
+    textwidth = ui.configint('ui', 'textwidth')
     termwidth = ui.termwidth() - 2
     if textwidth <= 0 or termwidth < textwidth:
diff --git a/mercurial/httpconnection.py b/mercurial/httpconnection.py
--- a/mercurial/httpconnection.py
+++ b/mercurial/httpconnection.py
@@ -142,5 +142,5 @@  class http2handler(urlreq.httphandler, u
         self._connections = {}
         # developer config: ui.http2debuglevel
-        loglevel = ui.config('ui', 'http2debuglevel', default=None)
+        loglevel = ui.config('ui', 'http2debuglevel')
         if loglevel and not _configuredlogging:
             _configuredlogging = True
diff --git a/mercurial/httppeer.py b/mercurial/httppeer.py
--- a/mercurial/httppeer.py
+++ b/mercurial/httppeer.py
@@ -182,5 +182,5 @@  class httppeer(wireproto.wirepeer):
         elif data is not None:
             size = len(data)
-        if size and self.ui.configbool('ui', 'usehttp2', False):
+        if size and self.ui.configbool('ui', 'usehttp2'):
             headers['Expect'] = '100-Continue'
             headers['X-HgHttp2'] = '1'
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -533,5 +533,5 @@  class localrepository(object):
 
     def _restrictcapabilities(self, caps):
-        if self.ui.configbool('experimental', 'bundle2-advertise', True):
+        if self.ui.configbool('experimental', 'bundle2-advertise'):
             caps = set(caps)
             capsblob = bundle2.encodecaps(bundle2.getrepocaps(self))
@@ -952,5 +952,5 @@  class localrepository(object):
         # it's safe (and desirable) to trust the publish flag unconditionally
         # so that we don't finalize changes shared between users via ssh or nfs
-        return self.ui.configbool('phases', 'publish', True, untrusted=True)
+        return self.ui.configbool('phases', 'publish', untrusted=True)
 
     def cancopy(self):
@@ -1150,6 +1150,5 @@  class localrepository(object):
         tracktags = lambda x: None
         # experimental config: experimental.hook-track-tags
-        shouldtracktags = self.ui.configbool('experimental', 'hook-track-tags',
-                                             False)
+        shouldtracktags = self.ui.configbool('experimental', 'hook-track-tags')
         if desc != 'strip' and shouldtracktags:
             oldheads = self.changelog.headrevs()
@@ -1507,5 +1506,5 @@  class localrepository(object):
             # default to 600 seconds timeout
             l = lockmod.lock(vfs, lockname,
-                             int(self.ui.config("ui", "timeout", "600")),
+                             int(self.ui.config("ui", "timeout")),
                              releasefn=releasefn, acquirefn=acquirefn,
                              desc=desc)
@@ -2219,5 +2218,5 @@  def newreporequirements(repo):
                 requirements.add('dotencode')
 
-    compengine = ui.config('experimental', 'format.compression', 'zlib')
+    compengine = ui.config('experimental', 'format.compression')
     if compengine not in util.compengines:
         raise error.Abort(_('compression engine %s defined by '
@@ -2233,7 +2232,7 @@  def newreporequirements(repo):
     if scmutil.gdinitconfig(ui):
         requirements.add('generaldelta')
-    if ui.configbool('experimental', 'treemanifest', False):
+    if ui.configbool('experimental', 'treemanifest'):
         requirements.add('treemanifest')
-    if ui.configbool('experimental', 'manifestv2', False):
+    if ui.configbool('experimental', 'manifestv2'):
         requirements.add('manifestv2')
 
diff --git a/mercurial/mail.py b/mercurial/mail.py
--- a/mercurial/mail.py
+++ b/mercurial/mail.py
@@ -79,5 +79,5 @@  def _smtp(ui):
     '''build an smtp connection and return a function to send mail'''
     local_hostname = ui.config('smtp', 'local_hostname')
-    tls = ui.config('smtp', 'tls', 'none')
+    tls = ui.config('smtp', 'tls')
     # backward compatible: when tls = true, we use starttls.
     starttls = tls == 'starttls' or util.parsebool(tls)
@@ -136,5 +136,5 @@  def _smtp(ui):
 def _sendmail(ui, sender, recipients, msg):
     '''send mail using sendmail.'''
-    program = ui.config('email', 'method', 'smtp')
+    program = ui.config('email', 'method')
     cmdline = '%s -f %s %s' % (program, util.email(sender),
                                ' '.join(map(util.email, recipients)))
@@ -165,5 +165,5 @@  def connect(ui, mbox=None):
         open(mbox, 'wb').close()
         return lambda s, r, m: _mbox(mbox, s, r, m)
-    if ui.config('email', 'method', 'smtp') == 'smtp':
+    if ui.config('email', 'method') == 'smtp':
         return _smtp(ui)
     return lambda s, r, m: _sendmail(ui, s, r, m)
@@ -175,5 +175,5 @@  def sendmail(ui, sender, recipients, msg
 def validateconfig(ui):
     '''determine if we have enough config data to try sending email.'''
-    method = ui.config('email', 'method', 'smtp')
+    method = ui.config('email', 'method')
     if method == 'smtp':
         if not ui.config('smtp', 'host'):
diff --git a/mercurial/merge.py b/mercurial/merge.py
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -1614,5 +1614,5 @@  def update(repo, node, branchmerge, forc
 
         # deprecated config: merge.followcopies
-        followcopies = repo.ui.configbool('merge', 'followcopies', True)
+        followcopies = repo.ui.configbool('merge', 'followcopies')
         if overwrite:
             followcopies = False
diff --git a/mercurial/obsolete.py b/mercurial/obsolete.py
--- a/mercurial/obsolete.py
+++ b/mercurial/obsolete.py
@@ -992,6 +992,5 @@  def createmarkers(repo, relations, flag=
         metadata['user'] = repo.ui.username()
     useoperation = repo.ui.configbool('experimental',
-                                      'evolution.track-operation',
-                                      False)
+        'evolution.track-operation')
     if useoperation and operation:
         metadata['operation'] = operation
diff --git a/mercurial/profiling.py b/mercurial/profiling.py
--- a/mercurial/profiling.py
+++ b/mercurial/profiling.py
@@ -31,8 +31,8 @@  def _loadprofiler(ui, profiler):
 @contextlib.contextmanager
 def lsprofile(ui, fp):
-    format = ui.config('profiling', 'format', default='text')
-    field = ui.config('profiling', 'sort', default='inlinetime')
-    limit = ui.configint('profiling', 'limit', default=30)
-    climit = ui.configint('profiling', 'nested', default=0)
+    format = ui.config('profiling', 'format')
+    field = ui.config('profiling', 'sort')
+    limit = ui.configint('profiling', 'limit')
+    climit = ui.configint('profiling', 'nested')
 
     if format not in ['text', 'kcachegrind']:
@@ -73,5 +73,5 @@  def flameprofile(ui, fp):
             'https://github.com/evanhempel/python-flamegraph'))
     # developer config: profiling.freq
-    freq = ui.configint('profiling', 'freq', default=1000)
+    freq = ui.configint('profiling', 'freq')
     filter_ = None
     collapse_recursion = True
@@ -93,5 +93,5 @@  def statprofile(ui, fp):
     from . import statprof
 
-    freq = ui.configint('profiling', 'freq', default=1000)
+    freq = ui.configint('profiling', 'freq')
     if freq > 0:
         # Cannot reset when profiler is already active. So silently no-op.
@@ -108,5 +108,5 @@  def statprofile(ui, fp):
         data = statprof.stop()
 
-        profformat = ui.config('profiling', 'statformat', 'hotpath')
+        profformat = ui.config('profiling', 'statformat')
 
         formats = {
diff --git a/mercurial/progress.py b/mercurial/progress.py
--- a/mercurial/progress.py
+++ b/mercurial/progress.py
@@ -93,13 +93,13 @@  class progbar(object):
         self.printed = False
         self.lastprint = time.time() + float(self.ui.config(
-            'progress', 'delay', default=3))
+            'progress', 'delay'))
         self.curtopic = None
         self.lasttopic = None
         self.indetcount = 0
         self.refresh = float(self.ui.config(
-            'progress', 'refresh', default=0.1))
+            'progress', 'refresh'))
         self.changedelay = max(3 * self.refresh,
                                float(self.ui.config(
-                                   'progress', 'changedelay', default=1)))
+                                   'progress', 'changedelay')))
         self.order = self.ui.configlist(
             'progress', 'format',
diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -283,5 +283,5 @@  def checkportabilityalert(ui):
     '''check if the user's config requests nothing, a warning, or abort for
     non-portable filenames'''
-    val = ui.config('ui', 'portablefilenames', 'warn')
+    val = ui.config('ui', 'portablefilenames')
     lval = val.lower()
     bval = util.parsebool(val)
@@ -554,5 +554,5 @@  def origpath(ui, repo, filepath):
     Fall back to default (filepath) if not specified
     '''
-    origbackuppath = ui.config('ui', 'origbackuppath', None)
+    origbackuppath = ui.config('ui', 'origbackuppath')
     if origbackuppath is None:
         return filepath + ".orig"
diff --git a/mercurial/sparse.py b/mercurial/sparse.py
--- a/mercurial/sparse.py
+++ b/mercurial/sparse.py
@@ -107,5 +107,5 @@  def patternsforrev(repo, rev):
                 # experimental config: sparse.missingwarning
                 if repo.ui.configbool(
-                        'sparse', 'missingwarning', True):
+                        'sparse', 'missingwarning'):
                     repo.ui.warn(msg)
                 else:
diff --git a/mercurial/sshpeer.py b/mercurial/sshpeer.py
--- a/mercurial/sshpeer.py
+++ b/mercurial/sshpeer.py
@@ -147,6 +147,6 @@  class sshpeer(wireproto.wirepeer):
         self.path = u.path or "."
 
-        sshcmd = self.ui.config("ui", "ssh", "ssh")
-        remotecmd = self.ui.config("ui", "remotecmd", "hg")
+        sshcmd = self.ui.config("ui", "ssh")
+        remotecmd = self.ui.config("ui", "remotecmd")
 
         args = util.sshargs(sshcmd,
diff --git a/mercurial/streamclone.py b/mercurial/streamclone.py
--- a/mercurial/streamclone.py
+++ b/mercurial/streamclone.py
@@ -166,5 +166,5 @@  def maybeperformlegacystreamclone(pullop
 def allowservergeneration(repo):
     """Whether streaming clones are allowed from the server."""
-    if not repo.ui.configbool('server', 'uncompressed', True, untrusted=True):
+    if not repo.ui.configbool('server', 'uncompressed', untrusted=True):
         return False
 
diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py
--- a/mercurial/subrepo.py
+++ b/mercurial/subrepo.py
@@ -402,5 +402,5 @@  def newcommitphase(ui, ctx):
     if not substate:
         return commitphase
-    check = ui.config('phases', 'checksubrepos', 'follow')
+    check = ui.config('phases', 'checksubrepos')
     if check not in ('ignore', 'follow', 'abort'):
         raise error.Abort(_('invalid phases.checksubrepos configuration: %s')
diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -409,6 +409,6 @@  class ui(object):
                 self.quiet = self.verbose = False
             self._reportuntrusted = self.debugflag or self.configbool("ui",
-                "report_untrusted", True)
-            self.tracebackflag = self.configbool('ui', 'traceback', False)
+                "report_untrusted")
+            self.tracebackflag = self.configbool('ui', 'traceback')
             self.logblockedtimes = self.configbool('ui', 'logblockedtimes')
 
@@ -925,5 +925,5 @@  class ui(object):
 
     def _isatty(self, fh):
-        if self.configbool('ui', 'nontty', False):
+        if self.configbool('ui', 'nontty'):
             return False
         return util.isatty(fh)
@@ -948,5 +948,5 @@  class ui(object):
             or self.pageractive
             or command in self.configlist('pager', 'ignore')
-            or not self.configbool('ui', 'paginate', True)
+            or not self.configbool('ui', 'paginate')
             or not self.configbool('pager', 'attend-' + command, True)
             # TODO: if we want to allow HGPLAINEXCEPT=pager,
@@ -1113,5 +1113,5 @@  class ui(object):
         # Default interface for all the features
         defaultinterface = "text"
-        i = self.config("ui", "interface", None)
+        i = self.config("ui", "interface")
         if i in alldefaults:
             defaultinterface = i
@@ -1187,5 +1187,5 @@  class ui(object):
             return False
 
-        i = self.configbool("ui", "formatted", None)
+        i = self.configbool("ui", "formatted")
         if i is None:
             # some environments replace stdout without implementing isatty
@@ -1465,5 +1465,5 @@  class ui(object):
         """setup the progbar singleton to the ui object"""
         if (self.quiet or self.debugflag
-                or self.configbool('progress', 'disable', False)
+                or self.configbool('progress', 'disable')
                 or not progress.shouldprint(self)):
             return None
diff --git a/mercurial/url.py b/mercurial/url.py
--- a/mercurial/url.py
+++ b/mercurial/url.py
@@ -455,5 +455,5 @@  def opener(ui, authinfo=None):
     '''
     # experimental config: ui.usehttp2
-    if ui.configbool('ui', 'usehttp2', False):
+    if ui.configbool('ui', 'usehttp2'):
         handlers = [
             httpconnectionmod.http2handler(
diff --git a/mercurial/verify.py b/mercurial/verify.py
--- a/mercurial/verify.py
+++ b/mercurial/verify.py
@@ -444,5 +444,5 @@  class verifier(object):
                 except error.CensoredNodeError:
                     # experimental config: censor.policy
-                    if ui.config("censor", "policy", "abort") == "abort":
+                    if ui.config("censor", "policy") == "abort":
                         self.err(lr, _("censored file data"), f)
                 except Exception as inst:
diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py
--- a/mercurial/wireproto.py
+++ b/mercurial/wireproto.py
@@ -765,5 +765,5 @@  def _capabilities(repo, proto):
         else:
             caps.append('streamreqs=%s' % ','.join(sorted(requiredformats)))
-    if repo.ui.configbool('experimental', 'bundle2-advertise', True):
+    if repo.ui.configbool('experimental', 'bundle2-advertise'):
         capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo))
         caps.append('bundle2=' + urlreq.quote(capsblob))
@@ -773,5 +773,5 @@  def _capabilities(repo, proto):
         caps.append('httpheader=%d' %
                     repo.ui.configint('server', 'maxhttpheaderlen'))
-        if repo.ui.configbool('experimental', 'httppostargs', False):
+        if repo.ui.configbool('experimental', 'httppostargs'):
             caps.append('httppostargs')