##// END OF EJS Templates
push: add a way to allow concurrent pushes on unrelated heads...
push: add a way to allow concurrent pushes on unrelated heads Client has a mechanism for the server to check that nothing changed server side since the client prepared a push. That check is wide and any head changed on the server will lead to an aborted push. We introduce a way for the client to send a less strict checking. That logic will check that no heads impacted by the push have been affected. If other unrelated heads (including named branches heads) have been affected, the push will proceed. This is very helpful for repositories with high developers traffic on different heads, a common setup. That behavior is currently controlled by an experimental option. The config should live in the "server" section but bike-shedding of the name will happen in the next changesets. Servers advertise this capability through a new bundle2 capability 'checkeads', using the value 'related'. The 'test-push-race.t' is updated to check that new capabilities on the documented cases.

File last commit:

r28352:a92ee4d8 default
r32709:16ada4cb default
Show More
check-config.py
112 lines | 3.6 KiB | text/x-python | PythonLexer
Matt Mackall
check-config: add config option checker...
r25790 #!/usr/bin/env python
#
# check-config - a config flag documentation checker for Mercurial
#
# Copyright 2015 Matt Mackall <mpm@selenic.com>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
Pulkit Goyal
check-config: use absolute_import and print_function
r28352 from __future__ import absolute_import, print_function
Matt Mackall
check-config: add config option checker...
r25790 import re
import sys
foundopts = {}
documented = {}
timeless
check-config: handle multiline config
r27313 configre = (r"""ui\.config(|int|bool|list)\(['"](\S+)['"],\s*"""
r"""['"](\S+)['"](,\s+(?:default=)?(\S+?))?\)""")
configpartialre = (r"""ui\.config""")
Matt Mackall
check-config: add config option checker...
r25790
def main(args):
for f in args:
sect = ''
prevname = ''
confsect = ''
timeless
check-config: handle multiline config
r27313 carryover = ''
Matt Mackall
check-config: add config option checker...
r25790 for l in open(f):
# check topic-like bits
m = re.match('\s*``(\S+)``', l)
if m:
prevname = m.group(1)
if re.match('^\s*-+$', l):
sect = prevname
prevname = ''
if sect and prevname:
name = sect + '.' + prevname
documented[name] = 1
# check docstring bits
m = re.match(r'^\s+\[(\S+)\]', l)
if m:
confsect = m.group(1)
continue
timeless
check-config: allow numbers in configs...
r27311 m = re.match(r'^\s+(?:#\s*)?(\S+) = ', l)
Matt Mackall
check-config: add config option checker...
r25790 if m:
name = confsect + '.' + m.group(1)
documented[name] = 1
# like the bugzilla extension
timeless
check-config: allow numbers in configs...
r27311 m = re.match(r'^\s*(\S+\.\S+)$', l)
Matt Mackall
check-config: add config option checker...
r25790 if m:
documented[m.group(1)] = 1
timeless
check-config: recognize convert style documentation
r27310 # like convert
m = re.match(r'^\s*:(\S+\.\S+):\s+', l)
if m:
documented[m.group(1)] = 1
Matt Mackall
check-config: add config option checker...
r25790 # quoted in help or docstrings
timeless
check-config: allow numbers in configs...
r27311 m = re.match(r'.*?``(\S+\.\S+)``', l)
Matt Mackall
check-config: add config option checker...
r25790 if m:
documented[m.group(1)] = 1
# look for ignore markers
m = re.search(r'# (?:internal|experimental|deprecated|developer)'
timeless
check-config: escape period in regexp for inline comments
r27312 ' config: (\S+\.\S+)$', l)
Matt Mackall
check-config: add config option checker...
r25790 if m:
documented[m.group(1)] = 1
# look for code-like bits
timeless
check-config: handle multiline config
r27313 line = carryover + l
m = re.search(configre, line, re.MULTILINE)
Matt Mackall
check-config: add config option checker...
r25790 if m:
ctype = m.group(1)
if not ctype:
ctype = 'str'
name = m.group(2) + "." + m.group(3)
default = m.group(5)
if default in (None, 'False', 'None', '0', '[]', '""', "''"):
default = ''
if re.match('[a-z.]+$', default):
default = '<variable>'
if name in foundopts and (ctype, default) != foundopts[name]:
Pulkit Goyal
check-config: use absolute_import and print_function
r28352 print(l)
print("conflict on %s: %r != %r" % (name, (ctype, default),
foundopts[name]))
Matt Mackall
check-config: add config option checker...
r25790 foundopts[name] = (ctype, default)
timeless
check-config: handle multiline config
r27313 carryover = ''
else:
m = re.search(configpartialre, line)
if m:
carryover = line
else:
carryover = ''
Matt Mackall
check-config: add config option checker...
r25790
for name in sorted(foundopts):
if name not in documented:
if not (name.startswith("devel.") or
name.startswith("experimental.") or
name.startswith("debug.")):
ctype, default = foundopts[name]
if default:
default = ' [%s]' % default
Pulkit Goyal
check-config: use absolute_import and print_function
r28352 print("undocumented: %s (%s)%s" % (name, ctype, default))
Matt Mackall
check-config: add config option checker...
r25790
if __name__ == "__main__":
FUJIWARA Katsunori
tests: execute check-config.py without xargs...
r27992 if len(sys.argv) > 1:
sys.exit(main(sys.argv[1:]))
else:
sys.exit(main([l.rstrip() for l in sys.stdin]))