contrib/check-config.py
author Gregory Szorc <gregory.szorc@gmail.com>
Sat, 27 Feb 2016 18:22:49 -0800
branchstable
changeset 28289 d493d64757eb
parent 27313 9d155accd8f1
child 27992 8f244b75cc5e
permissions -rwxr-xr-x
hg: obtain lock when creating share from pooled repo (issue5104) There are race conditions between clients performing a shared clone to pooled storage: 1) Clients race to create the new shared repo in the pool directory 2) 1 client is seeding the repo in the pool directory and another goes to share it before it is fully cloned We prevent these race conditions by obtaining a lock in the pool directory that is derived from the name of the repo we will be accessing. To test this, a simple generic "lockdelay" extension has been added. The extension inserts an optional, configurable delay before or after lock acquisition. In the test, we delay 2 seconds after lock acquisition in the first process and 1 second before lock acquisition in the 2nd process. This means the first process has 1s to obtain the lock. There is a race condition here. If we encounter it in the wild, we could change the dummy extension to wait on the lock file to appear instead of relying on timing. But that's more complicated. Let's see what happens first.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     1
#!/usr/bin/env python
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     2
#
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     3
# check-config - a config flag documentation checker for Mercurial
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     4
#
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     5
# Copyright 2015 Matt Mackall <mpm@selenic.com>
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     6
#
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     7
# This software may be used and distributed according to the terms of the
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     8
# GNU General Public License version 2 or any later version.
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     9
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    10
import re
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    11
import sys
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    12
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    13
foundopts = {}
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    14
documented = {}
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    15
27313
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
    16
configre = (r"""ui\.config(|int|bool|list)\(['"](\S+)['"],\s*"""
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
    17
            r"""['"](\S+)['"](,\s+(?:default=)?(\S+?))?\)""")
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
    18
configpartialre = (r"""ui\.config""")
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    19
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    20
def main(args):
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    21
    for f in args:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    22
        sect = ''
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    23
        prevname = ''
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    24
        confsect = ''
27313
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
    25
        carryover = ''
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    26
        for l in open(f):
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    27
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    28
            # check topic-like bits
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    29
            m = re.match('\s*``(\S+)``', l)
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    30
            if m:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    31
                prevname = m.group(1)
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    32
            if re.match('^\s*-+$', l):
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    33
                sect = prevname
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    34
                prevname = ''
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    35
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    36
            if sect and prevname:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    37
                name = sect + '.' + prevname
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    38
                documented[name] = 1
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    39
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    40
            # check docstring bits
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    41
            m = re.match(r'^\s+\[(\S+)\]', l)
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    42
            if m:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    43
                confsect = m.group(1)
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    44
                continue
27311
24a1c24fad6e check-config: allow numbers in configs
timeless <timeless@mozdev.org>
parents: 27310
diff changeset
    45
            m = re.match(r'^\s+(?:#\s*)?(\S+) = ', l)
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    46
            if m:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    47
                name = confsect + '.' + m.group(1)
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    48
                documented[name] = 1
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    49
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    50
            # like the bugzilla extension
27311
24a1c24fad6e check-config: allow numbers in configs
timeless <timeless@mozdev.org>
parents: 27310
diff changeset
    51
            m = re.match(r'^\s*(\S+\.\S+)$', l)
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    52
            if m:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    53
                documented[m.group(1)] = 1
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    54
27310
9c98fe1416c2 check-config: recognize convert style documentation
timeless <timeless@mozdev.org>
parents: 25849
diff changeset
    55
            # like convert
9c98fe1416c2 check-config: recognize convert style documentation
timeless <timeless@mozdev.org>
parents: 25849
diff changeset
    56
            m = re.match(r'^\s*:(\S+\.\S+):\s+', l)
9c98fe1416c2 check-config: recognize convert style documentation
timeless <timeless@mozdev.org>
parents: 25849
diff changeset
    57
            if m:
9c98fe1416c2 check-config: recognize convert style documentation
timeless <timeless@mozdev.org>
parents: 25849
diff changeset
    58
                documented[m.group(1)] = 1
9c98fe1416c2 check-config: recognize convert style documentation
timeless <timeless@mozdev.org>
parents: 25849
diff changeset
    59
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    60
            # quoted in help or docstrings
27311
24a1c24fad6e check-config: allow numbers in configs
timeless <timeless@mozdev.org>
parents: 27310
diff changeset
    61
            m = re.match(r'.*?``(\S+\.\S+)``', l)
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    62
            if m:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    63
                documented[m.group(1)] = 1
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    64
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    65
            # look for ignore markers
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    66
            m = re.search(r'# (?:internal|experimental|deprecated|developer)'
27312
f925d492113a check-config: escape period in regexp for inline comments
timeless <timeless@mozdev.org>
parents: 27311
diff changeset
    67
                          ' config: (\S+\.\S+)$', l)
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    68
            if m:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    69
                documented[m.group(1)] = 1
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    70
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    71
            # look for code-like bits
27313
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
    72
            line = carryover + l
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
    73
            m = re.search(configre, line, re.MULTILINE)
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    74
            if m:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    75
                ctype = m.group(1)
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    76
                if not ctype:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    77
                    ctype = 'str'
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    78
                name = m.group(2) + "." + m.group(3)
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    79
                default = m.group(5)
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    80
                if default in (None, 'False', 'None', '0', '[]', '""', "''"):
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    81
                    default = ''
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    82
                if re.match('[a-z.]+$', default):
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    83
                    default = '<variable>'
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    84
                if name in foundopts and (ctype, default) != foundopts[name]:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    85
                    print l
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    86
                    print "conflict on %s: %r != %r" % (name, (ctype, default),
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    87
                                                        foundopts[name])
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    88
                foundopts[name] = (ctype, default)
27313
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
    89
                carryover = ''
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
    90
            else:
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
    91
                m = re.search(configpartialre, line)
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
    92
                if m:
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
    93
                    carryover = line
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
    94
                else:
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
    95
                    carryover = ''
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    96
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    97
    for name in sorted(foundopts):
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    98
        if name not in documented:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    99
            if not (name.startswith("devel.") or
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   100
                    name.startswith("experimental.") or
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   101
                    name.startswith("debug.")):
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   102
                ctype, default = foundopts[name]
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   103
                if default:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   104
                    default = ' [%s]' % default
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   105
                print "undocumented: %s (%s)%s" % (name, ctype, default)
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   106
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   107
if __name__ == "__main__":
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   108
    sys.exit(main(sys.argv[1:]))