##// END OF EJS Templates
wireproto: allow direct stream processing for unbundle...
Joerg Sonnenberger -
r37432:2d965bfe default
parent child Browse files
Show More
@@ -1,191 +1,192 b''
1 # Copyright 2011 Fog Creek Software
1 # Copyright 2011 Fog Creek Software
2 #
2 #
3 # This software may be used and distributed according to the terms of the
3 # This software may be used and distributed according to the terms of the
4 # GNU General Public License version 2 or any later version.
4 # GNU General Public License version 2 or any later version.
5 from __future__ import absolute_import
5 from __future__ import absolute_import
6
6
7 import os
7 import os
8 import re
8 import re
9
9
10 from mercurial.i18n import _
10 from mercurial.i18n import _
11
11
12 from mercurial import (
12 from mercurial import (
13 error,
13 error,
14 httppeer,
14 httppeer,
15 util,
15 util,
16 wireproto,
16 wireproto,
17 wireprototypes,
17 wireprototypes,
18 )
18 )
19
19
20 from . import (
20 from . import (
21 lfutil,
21 lfutil,
22 )
22 )
23
23
24 urlerr = util.urlerr
24 urlerr = util.urlerr
25 urlreq = util.urlreq
25 urlreq = util.urlreq
26
26
27 LARGEFILES_REQUIRED_MSG = ('\nThis repository uses the largefiles extension.'
27 LARGEFILES_REQUIRED_MSG = ('\nThis repository uses the largefiles extension.'
28 '\n\nPlease enable it in your Mercurial config '
28 '\n\nPlease enable it in your Mercurial config '
29 'file.\n')
29 'file.\n')
30
30
31 # these will all be replaced by largefiles.uisetup
31 # these will all be replaced by largefiles.uisetup
32 ssholdcallstream = None
32 ssholdcallstream = None
33 httpoldcallstream = None
33 httpoldcallstream = None
34
34
35 def putlfile(repo, proto, sha):
35 def putlfile(repo, proto, sha):
36 '''Server command for putting a largefile into a repository's local store
36 '''Server command for putting a largefile into a repository's local store
37 and into the user cache.'''
37 and into the user cache.'''
38 with proto.mayberedirectstdio() as output:
38 with proto.mayberedirectstdio() as output:
39 path = lfutil.storepath(repo, sha)
39 path = lfutil.storepath(repo, sha)
40 util.makedirs(os.path.dirname(path))
40 util.makedirs(os.path.dirname(path))
41 tmpfp = util.atomictempfile(path, createmode=repo.store.createmode)
41 tmpfp = util.atomictempfile(path, createmode=repo.store.createmode)
42
42
43 try:
43 try:
44 proto.forwardpayload(tmpfp)
44 for p in proto.getpayload():
45 tmpfp.write(p)
45 tmpfp._fp.seek(0)
46 tmpfp._fp.seek(0)
46 if sha != lfutil.hexsha1(tmpfp._fp):
47 if sha != lfutil.hexsha1(tmpfp._fp):
47 raise IOError(0, _('largefile contents do not match hash'))
48 raise IOError(0, _('largefile contents do not match hash'))
48 tmpfp.close()
49 tmpfp.close()
49 lfutil.linktousercache(repo, sha)
50 lfutil.linktousercache(repo, sha)
50 except IOError as e:
51 except IOError as e:
51 repo.ui.warn(_('largefiles: failed to put %s into store: %s\n') %
52 repo.ui.warn(_('largefiles: failed to put %s into store: %s\n') %
52 (sha, e.strerror))
53 (sha, e.strerror))
53 return wireprototypes.pushres(
54 return wireprototypes.pushres(
54 1, output.getvalue() if output else '')
55 1, output.getvalue() if output else '')
55 finally:
56 finally:
56 tmpfp.discard()
57 tmpfp.discard()
57
58
58 return wireprototypes.pushres(0, output.getvalue() if output else '')
59 return wireprototypes.pushres(0, output.getvalue() if output else '')
59
60
60 def getlfile(repo, proto, sha):
61 def getlfile(repo, proto, sha):
61 '''Server command for retrieving a largefile from the repository-local
62 '''Server command for retrieving a largefile from the repository-local
62 cache or user cache.'''
63 cache or user cache.'''
63 filename = lfutil.findfile(repo, sha)
64 filename = lfutil.findfile(repo, sha)
64 if not filename:
65 if not filename:
65 raise error.Abort(_('requested largefile %s not present in cache')
66 raise error.Abort(_('requested largefile %s not present in cache')
66 % sha)
67 % sha)
67 f = open(filename, 'rb')
68 f = open(filename, 'rb')
68 length = os.fstat(f.fileno())[6]
69 length = os.fstat(f.fileno())[6]
69
70
70 # Since we can't set an HTTP content-length header here, and
71 # Since we can't set an HTTP content-length header here, and
71 # Mercurial core provides no way to give the length of a streamres
72 # Mercurial core provides no way to give the length of a streamres
72 # (and reading the entire file into RAM would be ill-advised), we
73 # (and reading the entire file into RAM would be ill-advised), we
73 # just send the length on the first line of the response, like the
74 # just send the length on the first line of the response, like the
74 # ssh proto does for string responses.
75 # ssh proto does for string responses.
75 def generator():
76 def generator():
76 yield '%d\n' % length
77 yield '%d\n' % length
77 for chunk in util.filechunkiter(f):
78 for chunk in util.filechunkiter(f):
78 yield chunk
79 yield chunk
79 return wireprototypes.streamreslegacy(gen=generator())
80 return wireprototypes.streamreslegacy(gen=generator())
80
81
81 def statlfile(repo, proto, sha):
82 def statlfile(repo, proto, sha):
82 '''Server command for checking if a largefile is present - returns '2\n' if
83 '''Server command for checking if a largefile is present - returns '2\n' if
83 the largefile is missing, '0\n' if it seems to be in good condition.
84 the largefile is missing, '0\n' if it seems to be in good condition.
84
85
85 The value 1 is reserved for mismatched checksum, but that is too expensive
86 The value 1 is reserved for mismatched checksum, but that is too expensive
86 to be verified on every stat and must be caught be running 'hg verify'
87 to be verified on every stat and must be caught be running 'hg verify'
87 server side.'''
88 server side.'''
88 filename = lfutil.findfile(repo, sha)
89 filename = lfutil.findfile(repo, sha)
89 if not filename:
90 if not filename:
90 return wireprototypes.bytesresponse('2\n')
91 return wireprototypes.bytesresponse('2\n')
91 return wireprototypes.bytesresponse('0\n')
92 return wireprototypes.bytesresponse('0\n')
92
93
93 def wirereposetup(ui, repo):
94 def wirereposetup(ui, repo):
94 class lfileswirerepository(repo.__class__):
95 class lfileswirerepository(repo.__class__):
95 def putlfile(self, sha, fd):
96 def putlfile(self, sha, fd):
96 # unfortunately, httprepository._callpush tries to convert its
97 # unfortunately, httprepository._callpush tries to convert its
97 # input file-like into a bundle before sending it, so we can't use
98 # input file-like into a bundle before sending it, so we can't use
98 # it ...
99 # it ...
99 if issubclass(self.__class__, httppeer.httppeer):
100 if issubclass(self.__class__, httppeer.httppeer):
100 res = self._call('putlfile', data=fd, sha=sha,
101 res = self._call('putlfile', data=fd, sha=sha,
101 headers={r'content-type': r'application/mercurial-0.1'})
102 headers={r'content-type': r'application/mercurial-0.1'})
102 try:
103 try:
103 d, output = res.split('\n', 1)
104 d, output = res.split('\n', 1)
104 for l in output.splitlines(True):
105 for l in output.splitlines(True):
105 self.ui.warn(_('remote: '), l) # assume l ends with \n
106 self.ui.warn(_('remote: '), l) # assume l ends with \n
106 return int(d)
107 return int(d)
107 except ValueError:
108 except ValueError:
108 self.ui.warn(_('unexpected putlfile response: %r\n') % res)
109 self.ui.warn(_('unexpected putlfile response: %r\n') % res)
109 return 1
110 return 1
110 # ... but we can't use sshrepository._call because the data=
111 # ... but we can't use sshrepository._call because the data=
111 # argument won't get sent, and _callpush does exactly what we want
112 # argument won't get sent, and _callpush does exactly what we want
112 # in this case: send the data straight through
113 # in this case: send the data straight through
113 else:
114 else:
114 try:
115 try:
115 ret, output = self._callpush("putlfile", fd, sha=sha)
116 ret, output = self._callpush("putlfile", fd, sha=sha)
116 if ret == "":
117 if ret == "":
117 raise error.ResponseError(_('putlfile failed:'),
118 raise error.ResponseError(_('putlfile failed:'),
118 output)
119 output)
119 return int(ret)
120 return int(ret)
120 except IOError:
121 except IOError:
121 return 1
122 return 1
122 except ValueError:
123 except ValueError:
123 raise error.ResponseError(
124 raise error.ResponseError(
124 _('putlfile failed (unexpected response):'), ret)
125 _('putlfile failed (unexpected response):'), ret)
125
126
126 def getlfile(self, sha):
127 def getlfile(self, sha):
127 """returns an iterable with the chunks of the file with sha sha"""
128 """returns an iterable with the chunks of the file with sha sha"""
128 stream = self._callstream("getlfile", sha=sha)
129 stream = self._callstream("getlfile", sha=sha)
129 length = stream.readline()
130 length = stream.readline()
130 try:
131 try:
131 length = int(length)
132 length = int(length)
132 except ValueError:
133 except ValueError:
133 self._abort(error.ResponseError(_("unexpected response:"),
134 self._abort(error.ResponseError(_("unexpected response:"),
134 length))
135 length))
135
136
136 # SSH streams will block if reading more than length
137 # SSH streams will block if reading more than length
137 for chunk in util.filechunkiter(stream, limit=length):
138 for chunk in util.filechunkiter(stream, limit=length):
138 yield chunk
139 yield chunk
139 # HTTP streams must hit the end to process the last empty
140 # HTTP streams must hit the end to process the last empty
140 # chunk of Chunked-Encoding so the connection can be reused.
141 # chunk of Chunked-Encoding so the connection can be reused.
141 if issubclass(self.__class__, httppeer.httppeer):
142 if issubclass(self.__class__, httppeer.httppeer):
142 chunk = stream.read(1)
143 chunk = stream.read(1)
143 if chunk:
144 if chunk:
144 self._abort(error.ResponseError(_("unexpected response:"),
145 self._abort(error.ResponseError(_("unexpected response:"),
145 chunk))
146 chunk))
146
147
147 @wireproto.batchable
148 @wireproto.batchable
148 def statlfile(self, sha):
149 def statlfile(self, sha):
149 f = wireproto.future()
150 f = wireproto.future()
150 result = {'sha': sha}
151 result = {'sha': sha}
151 yield result, f
152 yield result, f
152 try:
153 try:
153 yield int(f.value)
154 yield int(f.value)
154 except (ValueError, urlerr.httperror):
155 except (ValueError, urlerr.httperror):
155 # If the server returns anything but an integer followed by a
156 # If the server returns anything but an integer followed by a
156 # newline, newline, it's not speaking our language; if we get
157 # newline, newline, it's not speaking our language; if we get
157 # an HTTP error, we can't be sure the largefile is present;
158 # an HTTP error, we can't be sure the largefile is present;
158 # either way, consider it missing.
159 # either way, consider it missing.
159 yield 2
160 yield 2
160
161
161 repo.__class__ = lfileswirerepository
162 repo.__class__ = lfileswirerepository
162
163
163 # advertise the largefiles=serve capability
164 # advertise the largefiles=serve capability
164 def _capabilities(orig, repo, proto):
165 def _capabilities(orig, repo, proto):
165 '''announce largefile server capability'''
166 '''announce largefile server capability'''
166 caps = orig(repo, proto)
167 caps = orig(repo, proto)
167 caps.append('largefiles=serve')
168 caps.append('largefiles=serve')
168 return caps
169 return caps
169
170
170 def heads(repo, proto):
171 def heads(repo, proto):
171 '''Wrap server command - largefile capable clients will know to call
172 '''Wrap server command - largefile capable clients will know to call
172 lheads instead'''
173 lheads instead'''
173 if lfutil.islfilesrepo(repo):
174 if lfutil.islfilesrepo(repo):
174 return wireprototypes.ooberror(LARGEFILES_REQUIRED_MSG)
175 return wireprototypes.ooberror(LARGEFILES_REQUIRED_MSG)
175 return wireproto.heads(repo, proto)
176 return wireproto.heads(repo, proto)
176
177
177 def sshrepocallstream(self, cmd, **args):
178 def sshrepocallstream(self, cmd, **args):
178 if cmd == 'heads' and self.capable('largefiles'):
179 if cmd == 'heads' and self.capable('largefiles'):
179 cmd = 'lheads'
180 cmd = 'lheads'
180 if cmd == 'batch' and self.capable('largefiles'):
181 if cmd == 'batch' and self.capable('largefiles'):
181 args[r'cmds'] = args[r'cmds'].replace('heads ', 'lheads ')
182 args[r'cmds'] = args[r'cmds'].replace('heads ', 'lheads ')
182 return ssholdcallstream(self, cmd, **args)
183 return ssholdcallstream(self, cmd, **args)
183
184
184 headsre = re.compile(br'(^|;)heads\b')
185 headsre = re.compile(br'(^|;)heads\b')
185
186
186 def httprepocallstream(self, cmd, **args):
187 def httprepocallstream(self, cmd, **args):
187 if cmd == 'heads' and self.capable('largefiles'):
188 if cmd == 'heads' and self.capable('largefiles'):
188 cmd = 'lheads'
189 cmd = 'lheads'
189 if cmd == 'batch' and self.capable('largefiles'):
190 if cmd == 'batch' and self.capable('largefiles'):
190 args[r'cmds'] = headsre.sub('lheads', args[r'cmds'])
191 args[r'cmds'] = headsre.sub('lheads', args[r'cmds'])
191 return httpoldcallstream(self, cmd, **args)
192 return httpoldcallstream(self, cmd, **args)
@@ -1,1320 +1,1323 b''
1 # configitems.py - centralized declaration of configuration option
1 # configitems.py - centralized declaration of configuration option
2 #
2 #
3 # Copyright 2017 Pierre-Yves David <pierre-yves.david@octobus.net>
3 # Copyright 2017 Pierre-Yves David <pierre-yves.david@octobus.net>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import functools
10 import functools
11 import re
11 import re
12
12
13 from . import (
13 from . import (
14 encoding,
14 encoding,
15 error,
15 error,
16 )
16 )
17
17
18 def loadconfigtable(ui, extname, configtable):
18 def loadconfigtable(ui, extname, configtable):
19 """update config item known to the ui with the extension ones"""
19 """update config item known to the ui with the extension ones"""
20 for section, items in sorted(configtable.items()):
20 for section, items in sorted(configtable.items()):
21 knownitems = ui._knownconfig.setdefault(section, itemregister())
21 knownitems = ui._knownconfig.setdefault(section, itemregister())
22 knownkeys = set(knownitems)
22 knownkeys = set(knownitems)
23 newkeys = set(items)
23 newkeys = set(items)
24 for key in sorted(knownkeys & newkeys):
24 for key in sorted(knownkeys & newkeys):
25 msg = "extension '%s' overwrite config item '%s.%s'"
25 msg = "extension '%s' overwrite config item '%s.%s'"
26 msg %= (extname, section, key)
26 msg %= (extname, section, key)
27 ui.develwarn(msg, config='warn-config')
27 ui.develwarn(msg, config='warn-config')
28
28
29 knownitems.update(items)
29 knownitems.update(items)
30
30
31 class configitem(object):
31 class configitem(object):
32 """represent a known config item
32 """represent a known config item
33
33
34 :section: the official config section where to find this item,
34 :section: the official config section where to find this item,
35 :name: the official name within the section,
35 :name: the official name within the section,
36 :default: default value for this item,
36 :default: default value for this item,
37 :alias: optional list of tuples as alternatives,
37 :alias: optional list of tuples as alternatives,
38 :generic: this is a generic definition, match name using regular expression.
38 :generic: this is a generic definition, match name using regular expression.
39 """
39 """
40
40
41 def __init__(self, section, name, default=None, alias=(),
41 def __init__(self, section, name, default=None, alias=(),
42 generic=False, priority=0):
42 generic=False, priority=0):
43 self.section = section
43 self.section = section
44 self.name = name
44 self.name = name
45 self.default = default
45 self.default = default
46 self.alias = list(alias)
46 self.alias = list(alias)
47 self.generic = generic
47 self.generic = generic
48 self.priority = priority
48 self.priority = priority
49 self._re = None
49 self._re = None
50 if generic:
50 if generic:
51 self._re = re.compile(self.name)
51 self._re = re.compile(self.name)
52
52
53 class itemregister(dict):
53 class itemregister(dict):
54 """A specialized dictionary that can handle wild-card selection"""
54 """A specialized dictionary that can handle wild-card selection"""
55
55
56 def __init__(self):
56 def __init__(self):
57 super(itemregister, self).__init__()
57 super(itemregister, self).__init__()
58 self._generics = set()
58 self._generics = set()
59
59
60 def update(self, other):
60 def update(self, other):
61 super(itemregister, self).update(other)
61 super(itemregister, self).update(other)
62 self._generics.update(other._generics)
62 self._generics.update(other._generics)
63
63
64 def __setitem__(self, key, item):
64 def __setitem__(self, key, item):
65 super(itemregister, self).__setitem__(key, item)
65 super(itemregister, self).__setitem__(key, item)
66 if item.generic:
66 if item.generic:
67 self._generics.add(item)
67 self._generics.add(item)
68
68
69 def get(self, key):
69 def get(self, key):
70 baseitem = super(itemregister, self).get(key)
70 baseitem = super(itemregister, self).get(key)
71 if baseitem is not None and not baseitem.generic:
71 if baseitem is not None and not baseitem.generic:
72 return baseitem
72 return baseitem
73
73
74 # search for a matching generic item
74 # search for a matching generic item
75 generics = sorted(self._generics, key=(lambda x: (x.priority, x.name)))
75 generics = sorted(self._generics, key=(lambda x: (x.priority, x.name)))
76 for item in generics:
76 for item in generics:
77 # we use 'match' instead of 'search' to make the matching simpler
77 # we use 'match' instead of 'search' to make the matching simpler
78 # for people unfamiliar with regular expression. Having the match
78 # for people unfamiliar with regular expression. Having the match
79 # rooted to the start of the string will produce less surprising
79 # rooted to the start of the string will produce less surprising
80 # result for user writing simple regex for sub-attribute.
80 # result for user writing simple regex for sub-attribute.
81 #
81 #
82 # For example using "color\..*" match produces an unsurprising
82 # For example using "color\..*" match produces an unsurprising
83 # result, while using search could suddenly match apparently
83 # result, while using search could suddenly match apparently
84 # unrelated configuration that happens to contains "color."
84 # unrelated configuration that happens to contains "color."
85 # anywhere. This is a tradeoff where we favor requiring ".*" on
85 # anywhere. This is a tradeoff where we favor requiring ".*" on
86 # some match to avoid the need to prefix most pattern with "^".
86 # some match to avoid the need to prefix most pattern with "^".
87 # The "^" seems more error prone.
87 # The "^" seems more error prone.
88 if item._re.match(key):
88 if item._re.match(key):
89 return item
89 return item
90
90
91 return None
91 return None
92
92
93 coreitems = {}
93 coreitems = {}
94
94
95 def _register(configtable, *args, **kwargs):
95 def _register(configtable, *args, **kwargs):
96 item = configitem(*args, **kwargs)
96 item = configitem(*args, **kwargs)
97 section = configtable.setdefault(item.section, itemregister())
97 section = configtable.setdefault(item.section, itemregister())
98 if item.name in section:
98 if item.name in section:
99 msg = "duplicated config item registration for '%s.%s'"
99 msg = "duplicated config item registration for '%s.%s'"
100 raise error.ProgrammingError(msg % (item.section, item.name))
100 raise error.ProgrammingError(msg % (item.section, item.name))
101 section[item.name] = item
101 section[item.name] = item
102
102
103 # special value for case where the default is derived from other values
103 # special value for case where the default is derived from other values
104 dynamicdefault = object()
104 dynamicdefault = object()
105
105
106 # Registering actual config items
106 # Registering actual config items
107
107
108 def getitemregister(configtable):
108 def getitemregister(configtable):
109 f = functools.partial(_register, configtable)
109 f = functools.partial(_register, configtable)
110 # export pseudo enum as configitem.*
110 # export pseudo enum as configitem.*
111 f.dynamicdefault = dynamicdefault
111 f.dynamicdefault = dynamicdefault
112 return f
112 return f
113
113
114 coreconfigitem = getitemregister(coreitems)
114 coreconfigitem = getitemregister(coreitems)
115
115
116 coreconfigitem('alias', '.*',
116 coreconfigitem('alias', '.*',
117 default=dynamicdefault,
117 default=dynamicdefault,
118 generic=True,
118 generic=True,
119 )
119 )
120 coreconfigitem('annotate', 'nodates',
120 coreconfigitem('annotate', 'nodates',
121 default=False,
121 default=False,
122 )
122 )
123 coreconfigitem('annotate', 'showfunc',
123 coreconfigitem('annotate', 'showfunc',
124 default=False,
124 default=False,
125 )
125 )
126 coreconfigitem('annotate', 'unified',
126 coreconfigitem('annotate', 'unified',
127 default=None,
127 default=None,
128 )
128 )
129 coreconfigitem('annotate', 'git',
129 coreconfigitem('annotate', 'git',
130 default=False,
130 default=False,
131 )
131 )
132 coreconfigitem('annotate', 'ignorews',
132 coreconfigitem('annotate', 'ignorews',
133 default=False,
133 default=False,
134 )
134 )
135 coreconfigitem('annotate', 'ignorewsamount',
135 coreconfigitem('annotate', 'ignorewsamount',
136 default=False,
136 default=False,
137 )
137 )
138 coreconfigitem('annotate', 'ignoreblanklines',
138 coreconfigitem('annotate', 'ignoreblanklines',
139 default=False,
139 default=False,
140 )
140 )
141 coreconfigitem('annotate', 'ignorewseol',
141 coreconfigitem('annotate', 'ignorewseol',
142 default=False,
142 default=False,
143 )
143 )
144 coreconfigitem('annotate', 'nobinary',
144 coreconfigitem('annotate', 'nobinary',
145 default=False,
145 default=False,
146 )
146 )
147 coreconfigitem('annotate', 'noprefix',
147 coreconfigitem('annotate', 'noprefix',
148 default=False,
148 default=False,
149 )
149 )
150 coreconfigitem('auth', 'cookiefile',
150 coreconfigitem('auth', 'cookiefile',
151 default=None,
151 default=None,
152 )
152 )
153 # bookmarks.pushing: internal hack for discovery
153 # bookmarks.pushing: internal hack for discovery
154 coreconfigitem('bookmarks', 'pushing',
154 coreconfigitem('bookmarks', 'pushing',
155 default=list,
155 default=list,
156 )
156 )
157 # bundle.mainreporoot: internal hack for bundlerepo
157 # bundle.mainreporoot: internal hack for bundlerepo
158 coreconfigitem('bundle', 'mainreporoot',
158 coreconfigitem('bundle', 'mainreporoot',
159 default='',
159 default='',
160 )
160 )
161 # bundle.reorder: experimental config
161 # bundle.reorder: experimental config
162 coreconfigitem('bundle', 'reorder',
162 coreconfigitem('bundle', 'reorder',
163 default='auto',
163 default='auto',
164 )
164 )
165 coreconfigitem('censor', 'policy',
165 coreconfigitem('censor', 'policy',
166 default='abort',
166 default='abort',
167 )
167 )
168 coreconfigitem('chgserver', 'idletimeout',
168 coreconfigitem('chgserver', 'idletimeout',
169 default=3600,
169 default=3600,
170 )
170 )
171 coreconfigitem('chgserver', 'skiphash',
171 coreconfigitem('chgserver', 'skiphash',
172 default=False,
172 default=False,
173 )
173 )
174 coreconfigitem('cmdserver', 'log',
174 coreconfigitem('cmdserver', 'log',
175 default=None,
175 default=None,
176 )
176 )
177 coreconfigitem('color', '.*',
177 coreconfigitem('color', '.*',
178 default=None,
178 default=None,
179 generic=True,
179 generic=True,
180 )
180 )
181 coreconfigitem('color', 'mode',
181 coreconfigitem('color', 'mode',
182 default='auto',
182 default='auto',
183 )
183 )
184 coreconfigitem('color', 'pagermode',
184 coreconfigitem('color', 'pagermode',
185 default=dynamicdefault,
185 default=dynamicdefault,
186 )
186 )
187 coreconfigitem('commands', 'show.aliasprefix',
187 coreconfigitem('commands', 'show.aliasprefix',
188 default=list,
188 default=list,
189 )
189 )
190 coreconfigitem('commands', 'status.relative',
190 coreconfigitem('commands', 'status.relative',
191 default=False,
191 default=False,
192 )
192 )
193 coreconfigitem('commands', 'status.skipstates',
193 coreconfigitem('commands', 'status.skipstates',
194 default=[],
194 default=[],
195 )
195 )
196 coreconfigitem('commands', 'status.verbose',
196 coreconfigitem('commands', 'status.verbose',
197 default=False,
197 default=False,
198 )
198 )
199 coreconfigitem('commands', 'update.check',
199 coreconfigitem('commands', 'update.check',
200 default=None,
200 default=None,
201 # Deprecated, remove after 4.4 release
201 # Deprecated, remove after 4.4 release
202 alias=[('experimental', 'updatecheck')]
202 alias=[('experimental', 'updatecheck')]
203 )
203 )
204 coreconfigitem('commands', 'update.requiredest',
204 coreconfigitem('commands', 'update.requiredest',
205 default=False,
205 default=False,
206 )
206 )
207 coreconfigitem('committemplate', '.*',
207 coreconfigitem('committemplate', '.*',
208 default=None,
208 default=None,
209 generic=True,
209 generic=True,
210 )
210 )
211 coreconfigitem('convert', 'cvsps.cache',
211 coreconfigitem('convert', 'cvsps.cache',
212 default=True,
212 default=True,
213 )
213 )
214 coreconfigitem('convert', 'cvsps.fuzz',
214 coreconfigitem('convert', 'cvsps.fuzz',
215 default=60,
215 default=60,
216 )
216 )
217 coreconfigitem('convert', 'cvsps.logencoding',
217 coreconfigitem('convert', 'cvsps.logencoding',
218 default=None,
218 default=None,
219 )
219 )
220 coreconfigitem('convert', 'cvsps.mergefrom',
220 coreconfigitem('convert', 'cvsps.mergefrom',
221 default=None,
221 default=None,
222 )
222 )
223 coreconfigitem('convert', 'cvsps.mergeto',
223 coreconfigitem('convert', 'cvsps.mergeto',
224 default=None,
224 default=None,
225 )
225 )
226 coreconfigitem('convert', 'git.committeractions',
226 coreconfigitem('convert', 'git.committeractions',
227 default=lambda: ['messagedifferent'],
227 default=lambda: ['messagedifferent'],
228 )
228 )
229 coreconfigitem('convert', 'git.extrakeys',
229 coreconfigitem('convert', 'git.extrakeys',
230 default=list,
230 default=list,
231 )
231 )
232 coreconfigitem('convert', 'git.findcopiesharder',
232 coreconfigitem('convert', 'git.findcopiesharder',
233 default=False,
233 default=False,
234 )
234 )
235 coreconfigitem('convert', 'git.remoteprefix',
235 coreconfigitem('convert', 'git.remoteprefix',
236 default='remote',
236 default='remote',
237 )
237 )
238 coreconfigitem('convert', 'git.renamelimit',
238 coreconfigitem('convert', 'git.renamelimit',
239 default=400,
239 default=400,
240 )
240 )
241 coreconfigitem('convert', 'git.saverev',
241 coreconfigitem('convert', 'git.saverev',
242 default=True,
242 default=True,
243 )
243 )
244 coreconfigitem('convert', 'git.similarity',
244 coreconfigitem('convert', 'git.similarity',
245 default=50,
245 default=50,
246 )
246 )
247 coreconfigitem('convert', 'git.skipsubmodules',
247 coreconfigitem('convert', 'git.skipsubmodules',
248 default=False,
248 default=False,
249 )
249 )
250 coreconfigitem('convert', 'hg.clonebranches',
250 coreconfigitem('convert', 'hg.clonebranches',
251 default=False,
251 default=False,
252 )
252 )
253 coreconfigitem('convert', 'hg.ignoreerrors',
253 coreconfigitem('convert', 'hg.ignoreerrors',
254 default=False,
254 default=False,
255 )
255 )
256 coreconfigitem('convert', 'hg.revs',
256 coreconfigitem('convert', 'hg.revs',
257 default=None,
257 default=None,
258 )
258 )
259 coreconfigitem('convert', 'hg.saverev',
259 coreconfigitem('convert', 'hg.saverev',
260 default=False,
260 default=False,
261 )
261 )
262 coreconfigitem('convert', 'hg.sourcename',
262 coreconfigitem('convert', 'hg.sourcename',
263 default=None,
263 default=None,
264 )
264 )
265 coreconfigitem('convert', 'hg.startrev',
265 coreconfigitem('convert', 'hg.startrev',
266 default=None,
266 default=None,
267 )
267 )
268 coreconfigitem('convert', 'hg.tagsbranch',
268 coreconfigitem('convert', 'hg.tagsbranch',
269 default='default',
269 default='default',
270 )
270 )
271 coreconfigitem('convert', 'hg.usebranchnames',
271 coreconfigitem('convert', 'hg.usebranchnames',
272 default=True,
272 default=True,
273 )
273 )
274 coreconfigitem('convert', 'ignoreancestorcheck',
274 coreconfigitem('convert', 'ignoreancestorcheck',
275 default=False,
275 default=False,
276 )
276 )
277 coreconfigitem('convert', 'localtimezone',
277 coreconfigitem('convert', 'localtimezone',
278 default=False,
278 default=False,
279 )
279 )
280 coreconfigitem('convert', 'p4.encoding',
280 coreconfigitem('convert', 'p4.encoding',
281 default=dynamicdefault,
281 default=dynamicdefault,
282 )
282 )
283 coreconfigitem('convert', 'p4.startrev',
283 coreconfigitem('convert', 'p4.startrev',
284 default=0,
284 default=0,
285 )
285 )
286 coreconfigitem('convert', 'skiptags',
286 coreconfigitem('convert', 'skiptags',
287 default=False,
287 default=False,
288 )
288 )
289 coreconfigitem('convert', 'svn.debugsvnlog',
289 coreconfigitem('convert', 'svn.debugsvnlog',
290 default=True,
290 default=True,
291 )
291 )
292 coreconfigitem('convert', 'svn.trunk',
292 coreconfigitem('convert', 'svn.trunk',
293 default=None,
293 default=None,
294 )
294 )
295 coreconfigitem('convert', 'svn.tags',
295 coreconfigitem('convert', 'svn.tags',
296 default=None,
296 default=None,
297 )
297 )
298 coreconfigitem('convert', 'svn.branches',
298 coreconfigitem('convert', 'svn.branches',
299 default=None,
299 default=None,
300 )
300 )
301 coreconfigitem('convert', 'svn.startrev',
301 coreconfigitem('convert', 'svn.startrev',
302 default=0,
302 default=0,
303 )
303 )
304 coreconfigitem('debug', 'dirstate.delaywrite',
304 coreconfigitem('debug', 'dirstate.delaywrite',
305 default=0,
305 default=0,
306 )
306 )
307 coreconfigitem('defaults', '.*',
307 coreconfigitem('defaults', '.*',
308 default=None,
308 default=None,
309 generic=True,
309 generic=True,
310 )
310 )
311 coreconfigitem('devel', 'all-warnings',
311 coreconfigitem('devel', 'all-warnings',
312 default=False,
312 default=False,
313 )
313 )
314 coreconfigitem('devel', 'bundle2.debug',
314 coreconfigitem('devel', 'bundle2.debug',
315 default=False,
315 default=False,
316 )
316 )
317 coreconfigitem('devel', 'cache-vfs',
317 coreconfigitem('devel', 'cache-vfs',
318 default=None,
318 default=None,
319 )
319 )
320 coreconfigitem('devel', 'check-locks',
320 coreconfigitem('devel', 'check-locks',
321 default=False,
321 default=False,
322 )
322 )
323 coreconfigitem('devel', 'check-relroot',
323 coreconfigitem('devel', 'check-relroot',
324 default=False,
324 default=False,
325 )
325 )
326 coreconfigitem('devel', 'default-date',
326 coreconfigitem('devel', 'default-date',
327 default=None,
327 default=None,
328 )
328 )
329 coreconfigitem('devel', 'deprec-warn',
329 coreconfigitem('devel', 'deprec-warn',
330 default=False,
330 default=False,
331 )
331 )
332 coreconfigitem('devel', 'disableloaddefaultcerts',
332 coreconfigitem('devel', 'disableloaddefaultcerts',
333 default=False,
333 default=False,
334 )
334 )
335 coreconfigitem('devel', 'warn-empty-changegroup',
335 coreconfigitem('devel', 'warn-empty-changegroup',
336 default=False,
336 default=False,
337 )
337 )
338 coreconfigitem('devel', 'legacy.exchange',
338 coreconfigitem('devel', 'legacy.exchange',
339 default=list,
339 default=list,
340 )
340 )
341 coreconfigitem('devel', 'servercafile',
341 coreconfigitem('devel', 'servercafile',
342 default='',
342 default='',
343 )
343 )
344 coreconfigitem('devel', 'serverexactprotocol',
344 coreconfigitem('devel', 'serverexactprotocol',
345 default='',
345 default='',
346 )
346 )
347 coreconfigitem('devel', 'serverrequirecert',
347 coreconfigitem('devel', 'serverrequirecert',
348 default=False,
348 default=False,
349 )
349 )
350 coreconfigitem('devel', 'strip-obsmarkers',
350 coreconfigitem('devel', 'strip-obsmarkers',
351 default=True,
351 default=True,
352 )
352 )
353 coreconfigitem('devel', 'warn-config',
353 coreconfigitem('devel', 'warn-config',
354 default=None,
354 default=None,
355 )
355 )
356 coreconfigitem('devel', 'warn-config-default',
356 coreconfigitem('devel', 'warn-config-default',
357 default=None,
357 default=None,
358 )
358 )
359 coreconfigitem('devel', 'user.obsmarker',
359 coreconfigitem('devel', 'user.obsmarker',
360 default=None,
360 default=None,
361 )
361 )
362 coreconfigitem('devel', 'warn-config-unknown',
362 coreconfigitem('devel', 'warn-config-unknown',
363 default=None,
363 default=None,
364 )
364 )
365 coreconfigitem('devel', 'debug.peer-request',
365 coreconfigitem('devel', 'debug.peer-request',
366 default=False,
366 default=False,
367 )
367 )
368 coreconfigitem('diff', 'nodates',
368 coreconfigitem('diff', 'nodates',
369 default=False,
369 default=False,
370 )
370 )
371 coreconfigitem('diff', 'showfunc',
371 coreconfigitem('diff', 'showfunc',
372 default=False,
372 default=False,
373 )
373 )
374 coreconfigitem('diff', 'unified',
374 coreconfigitem('diff', 'unified',
375 default=None,
375 default=None,
376 )
376 )
377 coreconfigitem('diff', 'git',
377 coreconfigitem('diff', 'git',
378 default=False,
378 default=False,
379 )
379 )
380 coreconfigitem('diff', 'ignorews',
380 coreconfigitem('diff', 'ignorews',
381 default=False,
381 default=False,
382 )
382 )
383 coreconfigitem('diff', 'ignorewsamount',
383 coreconfigitem('diff', 'ignorewsamount',
384 default=False,
384 default=False,
385 )
385 )
386 coreconfigitem('diff', 'ignoreblanklines',
386 coreconfigitem('diff', 'ignoreblanklines',
387 default=False,
387 default=False,
388 )
388 )
389 coreconfigitem('diff', 'ignorewseol',
389 coreconfigitem('diff', 'ignorewseol',
390 default=False,
390 default=False,
391 )
391 )
392 coreconfigitem('diff', 'nobinary',
392 coreconfigitem('diff', 'nobinary',
393 default=False,
393 default=False,
394 )
394 )
395 coreconfigitem('diff', 'noprefix',
395 coreconfigitem('diff', 'noprefix',
396 default=False,
396 default=False,
397 )
397 )
398 coreconfigitem('email', 'bcc',
398 coreconfigitem('email', 'bcc',
399 default=None,
399 default=None,
400 )
400 )
401 coreconfigitem('email', 'cc',
401 coreconfigitem('email', 'cc',
402 default=None,
402 default=None,
403 )
403 )
404 coreconfigitem('email', 'charsets',
404 coreconfigitem('email', 'charsets',
405 default=list,
405 default=list,
406 )
406 )
407 coreconfigitem('email', 'from',
407 coreconfigitem('email', 'from',
408 default=None,
408 default=None,
409 )
409 )
410 coreconfigitem('email', 'method',
410 coreconfigitem('email', 'method',
411 default='smtp',
411 default='smtp',
412 )
412 )
413 coreconfigitem('email', 'reply-to',
413 coreconfigitem('email', 'reply-to',
414 default=None,
414 default=None,
415 )
415 )
416 coreconfigitem('email', 'to',
416 coreconfigitem('email', 'to',
417 default=None,
417 default=None,
418 )
418 )
419 coreconfigitem('experimental', 'archivemetatemplate',
419 coreconfigitem('experimental', 'archivemetatemplate',
420 default=dynamicdefault,
420 default=dynamicdefault,
421 )
421 )
422 coreconfigitem('experimental', 'bundle-phases',
422 coreconfigitem('experimental', 'bundle-phases',
423 default=False,
423 default=False,
424 )
424 )
425 coreconfigitem('experimental', 'bundle2-advertise',
425 coreconfigitem('experimental', 'bundle2-advertise',
426 default=True,
426 default=True,
427 )
427 )
428 coreconfigitem('experimental', 'bundle2-output-capture',
428 coreconfigitem('experimental', 'bundle2-output-capture',
429 default=False,
429 default=False,
430 )
430 )
431 coreconfigitem('experimental', 'bundle2.pushback',
431 coreconfigitem('experimental', 'bundle2.pushback',
432 default=False,
432 default=False,
433 )
433 )
434 coreconfigitem('experimental', 'bundle2.stream',
434 coreconfigitem('experimental', 'bundle2.stream',
435 default=False,
435 default=False,
436 )
436 )
437 coreconfigitem('experimental', 'bundle2lazylocking',
437 coreconfigitem('experimental', 'bundle2lazylocking',
438 default=False,
438 default=False,
439 )
439 )
440 coreconfigitem('experimental', 'bundlecomplevel',
440 coreconfigitem('experimental', 'bundlecomplevel',
441 default=None,
441 default=None,
442 )
442 )
443 coreconfigitem('experimental', 'changegroup3',
443 coreconfigitem('experimental', 'changegroup3',
444 default=False,
444 default=False,
445 )
445 )
446 coreconfigitem('experimental', 'clientcompressionengines',
446 coreconfigitem('experimental', 'clientcompressionengines',
447 default=list,
447 default=list,
448 )
448 )
449 coreconfigitem('experimental', 'copytrace',
449 coreconfigitem('experimental', 'copytrace',
450 default='on',
450 default='on',
451 )
451 )
452 coreconfigitem('experimental', 'copytrace.movecandidateslimit',
452 coreconfigitem('experimental', 'copytrace.movecandidateslimit',
453 default=100,
453 default=100,
454 )
454 )
455 coreconfigitem('experimental', 'copytrace.sourcecommitlimit',
455 coreconfigitem('experimental', 'copytrace.sourcecommitlimit',
456 default=100,
456 default=100,
457 )
457 )
458 coreconfigitem('experimental', 'crecordtest',
458 coreconfigitem('experimental', 'crecordtest',
459 default=None,
459 default=None,
460 )
460 )
461 coreconfigitem('experimental', 'directaccess',
461 coreconfigitem('experimental', 'directaccess',
462 default=False,
462 default=False,
463 )
463 )
464 coreconfigitem('experimental', 'directaccess.revnums',
464 coreconfigitem('experimental', 'directaccess.revnums',
465 default=False,
465 default=False,
466 )
466 )
467 coreconfigitem('experimental', 'editortmpinhg',
467 coreconfigitem('experimental', 'editortmpinhg',
468 default=False,
468 default=False,
469 )
469 )
470 coreconfigitem('experimental', 'evolution',
470 coreconfigitem('experimental', 'evolution',
471 default=list,
471 default=list,
472 )
472 )
473 coreconfigitem('experimental', 'evolution.allowdivergence',
473 coreconfigitem('experimental', 'evolution.allowdivergence',
474 default=False,
474 default=False,
475 alias=[('experimental', 'allowdivergence')]
475 alias=[('experimental', 'allowdivergence')]
476 )
476 )
477 coreconfigitem('experimental', 'evolution.allowunstable',
477 coreconfigitem('experimental', 'evolution.allowunstable',
478 default=None,
478 default=None,
479 )
479 )
480 coreconfigitem('experimental', 'evolution.createmarkers',
480 coreconfigitem('experimental', 'evolution.createmarkers',
481 default=None,
481 default=None,
482 )
482 )
483 coreconfigitem('experimental', 'evolution.effect-flags',
483 coreconfigitem('experimental', 'evolution.effect-flags',
484 default=True,
484 default=True,
485 alias=[('experimental', 'effect-flags')]
485 alias=[('experimental', 'effect-flags')]
486 )
486 )
487 coreconfigitem('experimental', 'evolution.exchange',
487 coreconfigitem('experimental', 'evolution.exchange',
488 default=None,
488 default=None,
489 )
489 )
490 coreconfigitem('experimental', 'evolution.bundle-obsmarker',
490 coreconfigitem('experimental', 'evolution.bundle-obsmarker',
491 default=False,
491 default=False,
492 )
492 )
493 coreconfigitem('experimental', 'evolution.report-instabilities',
493 coreconfigitem('experimental', 'evolution.report-instabilities',
494 default=True,
494 default=True,
495 )
495 )
496 coreconfigitem('experimental', 'evolution.track-operation',
496 coreconfigitem('experimental', 'evolution.track-operation',
497 default=True,
497 default=True,
498 )
498 )
499 coreconfigitem('experimental', 'worddiff',
499 coreconfigitem('experimental', 'worddiff',
500 default=False,
500 default=False,
501 )
501 )
502 coreconfigitem('experimental', 'maxdeltachainspan',
502 coreconfigitem('experimental', 'maxdeltachainspan',
503 default=-1,
503 default=-1,
504 )
504 )
505 coreconfigitem('experimental', 'mergetempdirprefix',
505 coreconfigitem('experimental', 'mergetempdirprefix',
506 default=None,
506 default=None,
507 )
507 )
508 coreconfigitem('experimental', 'mmapindexthreshold',
508 coreconfigitem('experimental', 'mmapindexthreshold',
509 default=None,
509 default=None,
510 )
510 )
511 coreconfigitem('experimental', 'nonnormalparanoidcheck',
511 coreconfigitem('experimental', 'nonnormalparanoidcheck',
512 default=False,
512 default=False,
513 )
513 )
514 coreconfigitem('experimental', 'exportableenviron',
514 coreconfigitem('experimental', 'exportableenviron',
515 default=list,
515 default=list,
516 )
516 )
517 coreconfigitem('experimental', 'extendedheader.index',
517 coreconfigitem('experimental', 'extendedheader.index',
518 default=None,
518 default=None,
519 )
519 )
520 coreconfigitem('experimental', 'extendedheader.similarity',
520 coreconfigitem('experimental', 'extendedheader.similarity',
521 default=False,
521 default=False,
522 )
522 )
523 coreconfigitem('experimental', 'format.compression',
523 coreconfigitem('experimental', 'format.compression',
524 default='zlib',
524 default='zlib',
525 )
525 )
526 coreconfigitem('experimental', 'graphshorten',
526 coreconfigitem('experimental', 'graphshorten',
527 default=False,
527 default=False,
528 )
528 )
529 coreconfigitem('experimental', 'graphstyle.parent',
529 coreconfigitem('experimental', 'graphstyle.parent',
530 default=dynamicdefault,
530 default=dynamicdefault,
531 )
531 )
532 coreconfigitem('experimental', 'graphstyle.missing',
532 coreconfigitem('experimental', 'graphstyle.missing',
533 default=dynamicdefault,
533 default=dynamicdefault,
534 )
534 )
535 coreconfigitem('experimental', 'graphstyle.grandparent',
535 coreconfigitem('experimental', 'graphstyle.grandparent',
536 default=dynamicdefault,
536 default=dynamicdefault,
537 )
537 )
538 coreconfigitem('experimental', 'hook-track-tags',
538 coreconfigitem('experimental', 'hook-track-tags',
539 default=False,
539 default=False,
540 )
540 )
541 coreconfigitem('experimental', 'httppostargs',
541 coreconfigitem('experimental', 'httppostargs',
542 default=False,
542 default=False,
543 )
543 )
544 coreconfigitem('experimental', 'mergedriver',
544 coreconfigitem('experimental', 'mergedriver',
545 default=None,
545 default=None,
546 )
546 )
547 coreconfigitem('experimental', 'obsmarkers-exchange-debug',
547 coreconfigitem('experimental', 'obsmarkers-exchange-debug',
548 default=False,
548 default=False,
549 )
549 )
550 coreconfigitem('experimental', 'remotenames',
550 coreconfigitem('experimental', 'remotenames',
551 default=False,
551 default=False,
552 )
552 )
553 coreconfigitem('experimental', 'revlogv2',
553 coreconfigitem('experimental', 'revlogv2',
554 default=None,
554 default=None,
555 )
555 )
556 coreconfigitem('experimental', 'single-head-per-branch',
556 coreconfigitem('experimental', 'single-head-per-branch',
557 default=False,
557 default=False,
558 )
558 )
559 coreconfigitem('experimental', 'sshserver.support-v2',
559 coreconfigitem('experimental', 'sshserver.support-v2',
560 default=False,
560 default=False,
561 )
561 )
562 coreconfigitem('experimental', 'spacemovesdown',
562 coreconfigitem('experimental', 'spacemovesdown',
563 default=False,
563 default=False,
564 )
564 )
565 coreconfigitem('experimental', 'sparse-read',
565 coreconfigitem('experimental', 'sparse-read',
566 default=False,
566 default=False,
567 )
567 )
568 coreconfigitem('experimental', 'sparse-read.density-threshold',
568 coreconfigitem('experimental', 'sparse-read.density-threshold',
569 default=0.25,
569 default=0.25,
570 )
570 )
571 coreconfigitem('experimental', 'sparse-read.min-gap-size',
571 coreconfigitem('experimental', 'sparse-read.min-gap-size',
572 default='256K',
572 default='256K',
573 )
573 )
574 coreconfigitem('experimental', 'treemanifest',
574 coreconfigitem('experimental', 'treemanifest',
575 default=False,
575 default=False,
576 )
576 )
577 coreconfigitem('experimental', 'update.atomic-file',
577 coreconfigitem('experimental', 'update.atomic-file',
578 default=False,
578 default=False,
579 )
579 )
580 coreconfigitem('experimental', 'sshpeer.advertise-v2',
580 coreconfigitem('experimental', 'sshpeer.advertise-v2',
581 default=False,
581 default=False,
582 )
582 )
583 coreconfigitem('experimental', 'web.apiserver',
583 coreconfigitem('experimental', 'web.apiserver',
584 default=False,
584 default=False,
585 )
585 )
586 coreconfigitem('experimental', 'web.api.http-v2',
586 coreconfigitem('experimental', 'web.api.http-v2',
587 default=False,
587 default=False,
588 )
588 )
589 coreconfigitem('experimental', 'web.api.debugreflect',
589 coreconfigitem('experimental', 'web.api.debugreflect',
590 default=False,
590 default=False,
591 )
591 )
592 coreconfigitem('experimental', 'xdiff',
592 coreconfigitem('experimental', 'xdiff',
593 default=False,
593 default=False,
594 )
594 )
595 coreconfigitem('extensions', '.*',
595 coreconfigitem('extensions', '.*',
596 default=None,
596 default=None,
597 generic=True,
597 generic=True,
598 )
598 )
599 coreconfigitem('extdata', '.*',
599 coreconfigitem('extdata', '.*',
600 default=None,
600 default=None,
601 generic=True,
601 generic=True,
602 )
602 )
603 coreconfigitem('format', 'aggressivemergedeltas',
603 coreconfigitem('format', 'aggressivemergedeltas',
604 default=False,
604 default=False,
605 )
605 )
606 coreconfigitem('format', 'chunkcachesize',
606 coreconfigitem('format', 'chunkcachesize',
607 default=None,
607 default=None,
608 )
608 )
609 coreconfigitem('format', 'dotencode',
609 coreconfigitem('format', 'dotencode',
610 default=True,
610 default=True,
611 )
611 )
612 coreconfigitem('format', 'generaldelta',
612 coreconfigitem('format', 'generaldelta',
613 default=False,
613 default=False,
614 )
614 )
615 coreconfigitem('format', 'manifestcachesize',
615 coreconfigitem('format', 'manifestcachesize',
616 default=None,
616 default=None,
617 )
617 )
618 coreconfigitem('format', 'maxchainlen',
618 coreconfigitem('format', 'maxchainlen',
619 default=None,
619 default=None,
620 )
620 )
621 coreconfigitem('format', 'obsstore-version',
621 coreconfigitem('format', 'obsstore-version',
622 default=None,
622 default=None,
623 )
623 )
624 coreconfigitem('format', 'usefncache',
624 coreconfigitem('format', 'usefncache',
625 default=True,
625 default=True,
626 )
626 )
627 coreconfigitem('format', 'usegeneraldelta',
627 coreconfigitem('format', 'usegeneraldelta',
628 default=True,
628 default=True,
629 )
629 )
630 coreconfigitem('format', 'usestore',
630 coreconfigitem('format', 'usestore',
631 default=True,
631 default=True,
632 )
632 )
633 coreconfigitem('fsmonitor', 'warn_when_unused',
633 coreconfigitem('fsmonitor', 'warn_when_unused',
634 default=True,
634 default=True,
635 )
635 )
636 coreconfigitem('fsmonitor', 'warn_update_file_count',
636 coreconfigitem('fsmonitor', 'warn_update_file_count',
637 default=50000,
637 default=50000,
638 )
638 )
639 coreconfigitem('hooks', '.*',
639 coreconfigitem('hooks', '.*',
640 default=dynamicdefault,
640 default=dynamicdefault,
641 generic=True,
641 generic=True,
642 )
642 )
643 coreconfigitem('hgweb-paths', '.*',
643 coreconfigitem('hgweb-paths', '.*',
644 default=list,
644 default=list,
645 generic=True,
645 generic=True,
646 )
646 )
647 coreconfigitem('hostfingerprints', '.*',
647 coreconfigitem('hostfingerprints', '.*',
648 default=list,
648 default=list,
649 generic=True,
649 generic=True,
650 )
650 )
651 coreconfigitem('hostsecurity', 'ciphers',
651 coreconfigitem('hostsecurity', 'ciphers',
652 default=None,
652 default=None,
653 )
653 )
654 coreconfigitem('hostsecurity', 'disabletls10warning',
654 coreconfigitem('hostsecurity', 'disabletls10warning',
655 default=False,
655 default=False,
656 )
656 )
657 coreconfigitem('hostsecurity', 'minimumprotocol',
657 coreconfigitem('hostsecurity', 'minimumprotocol',
658 default=dynamicdefault,
658 default=dynamicdefault,
659 )
659 )
660 coreconfigitem('hostsecurity', '.*:minimumprotocol$',
660 coreconfigitem('hostsecurity', '.*:minimumprotocol$',
661 default=dynamicdefault,
661 default=dynamicdefault,
662 generic=True,
662 generic=True,
663 )
663 )
664 coreconfigitem('hostsecurity', '.*:ciphers$',
664 coreconfigitem('hostsecurity', '.*:ciphers$',
665 default=dynamicdefault,
665 default=dynamicdefault,
666 generic=True,
666 generic=True,
667 )
667 )
668 coreconfigitem('hostsecurity', '.*:fingerprints$',
668 coreconfigitem('hostsecurity', '.*:fingerprints$',
669 default=list,
669 default=list,
670 generic=True,
670 generic=True,
671 )
671 )
672 coreconfigitem('hostsecurity', '.*:verifycertsfile$',
672 coreconfigitem('hostsecurity', '.*:verifycertsfile$',
673 default=None,
673 default=None,
674 generic=True,
674 generic=True,
675 )
675 )
676
676
677 coreconfigitem('http_proxy', 'always',
677 coreconfigitem('http_proxy', 'always',
678 default=False,
678 default=False,
679 )
679 )
680 coreconfigitem('http_proxy', 'host',
680 coreconfigitem('http_proxy', 'host',
681 default=None,
681 default=None,
682 )
682 )
683 coreconfigitem('http_proxy', 'no',
683 coreconfigitem('http_proxy', 'no',
684 default=list,
684 default=list,
685 )
685 )
686 coreconfigitem('http_proxy', 'passwd',
686 coreconfigitem('http_proxy', 'passwd',
687 default=None,
687 default=None,
688 )
688 )
689 coreconfigitem('http_proxy', 'user',
689 coreconfigitem('http_proxy', 'user',
690 default=None,
690 default=None,
691 )
691 )
692 coreconfigitem('logtoprocess', 'commandexception',
692 coreconfigitem('logtoprocess', 'commandexception',
693 default=None,
693 default=None,
694 )
694 )
695 coreconfigitem('logtoprocess', 'commandfinish',
695 coreconfigitem('logtoprocess', 'commandfinish',
696 default=None,
696 default=None,
697 )
697 )
698 coreconfigitem('logtoprocess', 'command',
698 coreconfigitem('logtoprocess', 'command',
699 default=None,
699 default=None,
700 )
700 )
701 coreconfigitem('logtoprocess', 'develwarn',
701 coreconfigitem('logtoprocess', 'develwarn',
702 default=None,
702 default=None,
703 )
703 )
704 coreconfigitem('logtoprocess', 'uiblocked',
704 coreconfigitem('logtoprocess', 'uiblocked',
705 default=None,
705 default=None,
706 )
706 )
707 coreconfigitem('merge', 'checkunknown',
707 coreconfigitem('merge', 'checkunknown',
708 default='abort',
708 default='abort',
709 )
709 )
710 coreconfigitem('merge', 'checkignored',
710 coreconfigitem('merge', 'checkignored',
711 default='abort',
711 default='abort',
712 )
712 )
713 coreconfigitem('experimental', 'merge.checkpathconflicts',
713 coreconfigitem('experimental', 'merge.checkpathconflicts',
714 default=False,
714 default=False,
715 )
715 )
716 coreconfigitem('merge', 'followcopies',
716 coreconfigitem('merge', 'followcopies',
717 default=True,
717 default=True,
718 )
718 )
719 coreconfigitem('merge', 'on-failure',
719 coreconfigitem('merge', 'on-failure',
720 default='continue',
720 default='continue',
721 )
721 )
722 coreconfigitem('merge', 'preferancestor',
722 coreconfigitem('merge', 'preferancestor',
723 default=lambda: ['*'],
723 default=lambda: ['*'],
724 )
724 )
725 coreconfigitem('merge-tools', '.*',
725 coreconfigitem('merge-tools', '.*',
726 default=None,
726 default=None,
727 generic=True,
727 generic=True,
728 )
728 )
729 coreconfigitem('merge-tools', br'.*\.args$',
729 coreconfigitem('merge-tools', br'.*\.args$',
730 default="$local $base $other",
730 default="$local $base $other",
731 generic=True,
731 generic=True,
732 priority=-1,
732 priority=-1,
733 )
733 )
734 coreconfigitem('merge-tools', br'.*\.binary$',
734 coreconfigitem('merge-tools', br'.*\.binary$',
735 default=False,
735 default=False,
736 generic=True,
736 generic=True,
737 priority=-1,
737 priority=-1,
738 )
738 )
739 coreconfigitem('merge-tools', br'.*\.check$',
739 coreconfigitem('merge-tools', br'.*\.check$',
740 default=list,
740 default=list,
741 generic=True,
741 generic=True,
742 priority=-1,
742 priority=-1,
743 )
743 )
744 coreconfigitem('merge-tools', br'.*\.checkchanged$',
744 coreconfigitem('merge-tools', br'.*\.checkchanged$',
745 default=False,
745 default=False,
746 generic=True,
746 generic=True,
747 priority=-1,
747 priority=-1,
748 )
748 )
749 coreconfigitem('merge-tools', br'.*\.executable$',
749 coreconfigitem('merge-tools', br'.*\.executable$',
750 default=dynamicdefault,
750 default=dynamicdefault,
751 generic=True,
751 generic=True,
752 priority=-1,
752 priority=-1,
753 )
753 )
754 coreconfigitem('merge-tools', br'.*\.fixeol$',
754 coreconfigitem('merge-tools', br'.*\.fixeol$',
755 default=False,
755 default=False,
756 generic=True,
756 generic=True,
757 priority=-1,
757 priority=-1,
758 )
758 )
759 coreconfigitem('merge-tools', br'.*\.gui$',
759 coreconfigitem('merge-tools', br'.*\.gui$',
760 default=False,
760 default=False,
761 generic=True,
761 generic=True,
762 priority=-1,
762 priority=-1,
763 )
763 )
764 coreconfigitem('merge-tools', br'.*\.mergemarkers$',
764 coreconfigitem('merge-tools', br'.*\.mergemarkers$',
765 default='basic',
765 default='basic',
766 generic=True,
766 generic=True,
767 priority=-1,
767 priority=-1,
768 )
768 )
769 coreconfigitem('merge-tools', br'.*\.mergemarkertemplate$',
769 coreconfigitem('merge-tools', br'.*\.mergemarkertemplate$',
770 default=dynamicdefault, # take from ui.mergemarkertemplate
770 default=dynamicdefault, # take from ui.mergemarkertemplate
771 generic=True,
771 generic=True,
772 priority=-1,
772 priority=-1,
773 )
773 )
774 coreconfigitem('merge-tools', br'.*\.priority$',
774 coreconfigitem('merge-tools', br'.*\.priority$',
775 default=0,
775 default=0,
776 generic=True,
776 generic=True,
777 priority=-1,
777 priority=-1,
778 )
778 )
779 coreconfigitem('merge-tools', br'.*\.premerge$',
779 coreconfigitem('merge-tools', br'.*\.premerge$',
780 default=dynamicdefault,
780 default=dynamicdefault,
781 generic=True,
781 generic=True,
782 priority=-1,
782 priority=-1,
783 )
783 )
784 coreconfigitem('merge-tools', br'.*\.symlink$',
784 coreconfigitem('merge-tools', br'.*\.symlink$',
785 default=False,
785 default=False,
786 generic=True,
786 generic=True,
787 priority=-1,
787 priority=-1,
788 )
788 )
789 coreconfigitem('pager', 'attend-.*',
789 coreconfigitem('pager', 'attend-.*',
790 default=dynamicdefault,
790 default=dynamicdefault,
791 generic=True,
791 generic=True,
792 )
792 )
793 coreconfigitem('pager', 'ignore',
793 coreconfigitem('pager', 'ignore',
794 default=list,
794 default=list,
795 )
795 )
796 coreconfigitem('pager', 'pager',
796 coreconfigitem('pager', 'pager',
797 default=dynamicdefault,
797 default=dynamicdefault,
798 )
798 )
799 coreconfigitem('patch', 'eol',
799 coreconfigitem('patch', 'eol',
800 default='strict',
800 default='strict',
801 )
801 )
802 coreconfigitem('patch', 'fuzz',
802 coreconfigitem('patch', 'fuzz',
803 default=2,
803 default=2,
804 )
804 )
805 coreconfigitem('paths', 'default',
805 coreconfigitem('paths', 'default',
806 default=None,
806 default=None,
807 )
807 )
808 coreconfigitem('paths', 'default-push',
808 coreconfigitem('paths', 'default-push',
809 default=None,
809 default=None,
810 )
810 )
811 coreconfigitem('paths', '.*',
811 coreconfigitem('paths', '.*',
812 default=None,
812 default=None,
813 generic=True,
813 generic=True,
814 )
814 )
815 coreconfigitem('phases', 'checksubrepos',
815 coreconfigitem('phases', 'checksubrepos',
816 default='follow',
816 default='follow',
817 )
817 )
818 coreconfigitem('phases', 'new-commit',
818 coreconfigitem('phases', 'new-commit',
819 default='draft',
819 default='draft',
820 )
820 )
821 coreconfigitem('phases', 'publish',
821 coreconfigitem('phases', 'publish',
822 default=True,
822 default=True,
823 )
823 )
824 coreconfigitem('profiling', 'enabled',
824 coreconfigitem('profiling', 'enabled',
825 default=False,
825 default=False,
826 )
826 )
827 coreconfigitem('profiling', 'format',
827 coreconfigitem('profiling', 'format',
828 default='text',
828 default='text',
829 )
829 )
830 coreconfigitem('profiling', 'freq',
830 coreconfigitem('profiling', 'freq',
831 default=1000,
831 default=1000,
832 )
832 )
833 coreconfigitem('profiling', 'limit',
833 coreconfigitem('profiling', 'limit',
834 default=30,
834 default=30,
835 )
835 )
836 coreconfigitem('profiling', 'nested',
836 coreconfigitem('profiling', 'nested',
837 default=0,
837 default=0,
838 )
838 )
839 coreconfigitem('profiling', 'output',
839 coreconfigitem('profiling', 'output',
840 default=None,
840 default=None,
841 )
841 )
842 coreconfigitem('profiling', 'showmax',
842 coreconfigitem('profiling', 'showmax',
843 default=0.999,
843 default=0.999,
844 )
844 )
845 coreconfigitem('profiling', 'showmin',
845 coreconfigitem('profiling', 'showmin',
846 default=dynamicdefault,
846 default=dynamicdefault,
847 )
847 )
848 coreconfigitem('profiling', 'sort',
848 coreconfigitem('profiling', 'sort',
849 default='inlinetime',
849 default='inlinetime',
850 )
850 )
851 coreconfigitem('profiling', 'statformat',
851 coreconfigitem('profiling', 'statformat',
852 default='hotpath',
852 default='hotpath',
853 )
853 )
854 coreconfigitem('profiling', 'type',
854 coreconfigitem('profiling', 'type',
855 default='stat',
855 default='stat',
856 )
856 )
857 coreconfigitem('progress', 'assume-tty',
857 coreconfigitem('progress', 'assume-tty',
858 default=False,
858 default=False,
859 )
859 )
860 coreconfigitem('progress', 'changedelay',
860 coreconfigitem('progress', 'changedelay',
861 default=1,
861 default=1,
862 )
862 )
863 coreconfigitem('progress', 'clear-complete',
863 coreconfigitem('progress', 'clear-complete',
864 default=True,
864 default=True,
865 )
865 )
866 coreconfigitem('progress', 'debug',
866 coreconfigitem('progress', 'debug',
867 default=False,
867 default=False,
868 )
868 )
869 coreconfigitem('progress', 'delay',
869 coreconfigitem('progress', 'delay',
870 default=3,
870 default=3,
871 )
871 )
872 coreconfigitem('progress', 'disable',
872 coreconfigitem('progress', 'disable',
873 default=False,
873 default=False,
874 )
874 )
875 coreconfigitem('progress', 'estimateinterval',
875 coreconfigitem('progress', 'estimateinterval',
876 default=60.0,
876 default=60.0,
877 )
877 )
878 coreconfigitem('progress', 'format',
878 coreconfigitem('progress', 'format',
879 default=lambda: ['topic', 'bar', 'number', 'estimate'],
879 default=lambda: ['topic', 'bar', 'number', 'estimate'],
880 )
880 )
881 coreconfigitem('progress', 'refresh',
881 coreconfigitem('progress', 'refresh',
882 default=0.1,
882 default=0.1,
883 )
883 )
884 coreconfigitem('progress', 'width',
884 coreconfigitem('progress', 'width',
885 default=dynamicdefault,
885 default=dynamicdefault,
886 )
886 )
887 coreconfigitem('push', 'pushvars.server',
887 coreconfigitem('push', 'pushvars.server',
888 default=False,
888 default=False,
889 )
889 )
890 coreconfigitem('server', 'bookmarks-pushkey-compat',
890 coreconfigitem('server', 'bookmarks-pushkey-compat',
891 default=True,
891 default=True,
892 )
892 )
893 coreconfigitem('server', 'bundle1',
893 coreconfigitem('server', 'bundle1',
894 default=True,
894 default=True,
895 )
895 )
896 coreconfigitem('server', 'bundle1gd',
896 coreconfigitem('server', 'bundle1gd',
897 default=None,
897 default=None,
898 )
898 )
899 coreconfigitem('server', 'bundle1.pull',
899 coreconfigitem('server', 'bundle1.pull',
900 default=None,
900 default=None,
901 )
901 )
902 coreconfigitem('server', 'bundle1gd.pull',
902 coreconfigitem('server', 'bundle1gd.pull',
903 default=None,
903 default=None,
904 )
904 )
905 coreconfigitem('server', 'bundle1.push',
905 coreconfigitem('server', 'bundle1.push',
906 default=None,
906 default=None,
907 )
907 )
908 coreconfigitem('server', 'bundle1gd.push',
908 coreconfigitem('server', 'bundle1gd.push',
909 default=None,
909 default=None,
910 )
910 )
911 coreconfigitem('server', 'compressionengines',
911 coreconfigitem('server', 'compressionengines',
912 default=list,
912 default=list,
913 )
913 )
914 coreconfigitem('server', 'concurrent-push-mode',
914 coreconfigitem('server', 'concurrent-push-mode',
915 default='strict',
915 default='strict',
916 )
916 )
917 coreconfigitem('server', 'disablefullbundle',
917 coreconfigitem('server', 'disablefullbundle',
918 default=False,
918 default=False,
919 )
919 )
920 coreconfigitem('server', 'streamunbundle',
921 default=False,
922 )
920 coreconfigitem('server', 'maxhttpheaderlen',
923 coreconfigitem('server', 'maxhttpheaderlen',
921 default=1024,
924 default=1024,
922 )
925 )
923 coreconfigitem('server', 'preferuncompressed',
926 coreconfigitem('server', 'preferuncompressed',
924 default=False,
927 default=False,
925 )
928 )
926 coreconfigitem('server', 'uncompressed',
929 coreconfigitem('server', 'uncompressed',
927 default=True,
930 default=True,
928 )
931 )
929 coreconfigitem('server', 'uncompressedallowsecret',
932 coreconfigitem('server', 'uncompressedallowsecret',
930 default=False,
933 default=False,
931 )
934 )
932 coreconfigitem('server', 'validate',
935 coreconfigitem('server', 'validate',
933 default=False,
936 default=False,
934 )
937 )
935 coreconfigitem('server', 'zliblevel',
938 coreconfigitem('server', 'zliblevel',
936 default=-1,
939 default=-1,
937 )
940 )
938 coreconfigitem('share', 'pool',
941 coreconfigitem('share', 'pool',
939 default=None,
942 default=None,
940 )
943 )
941 coreconfigitem('share', 'poolnaming',
944 coreconfigitem('share', 'poolnaming',
942 default='identity',
945 default='identity',
943 )
946 )
944 coreconfigitem('smtp', 'host',
947 coreconfigitem('smtp', 'host',
945 default=None,
948 default=None,
946 )
949 )
947 coreconfigitem('smtp', 'local_hostname',
950 coreconfigitem('smtp', 'local_hostname',
948 default=None,
951 default=None,
949 )
952 )
950 coreconfigitem('smtp', 'password',
953 coreconfigitem('smtp', 'password',
951 default=None,
954 default=None,
952 )
955 )
953 coreconfigitem('smtp', 'port',
956 coreconfigitem('smtp', 'port',
954 default=dynamicdefault,
957 default=dynamicdefault,
955 )
958 )
956 coreconfigitem('smtp', 'tls',
959 coreconfigitem('smtp', 'tls',
957 default='none',
960 default='none',
958 )
961 )
959 coreconfigitem('smtp', 'username',
962 coreconfigitem('smtp', 'username',
960 default=None,
963 default=None,
961 )
964 )
962 coreconfigitem('sparse', 'missingwarning',
965 coreconfigitem('sparse', 'missingwarning',
963 default=True,
966 default=True,
964 )
967 )
965 coreconfigitem('subrepos', 'allowed',
968 coreconfigitem('subrepos', 'allowed',
966 default=dynamicdefault, # to make backporting simpler
969 default=dynamicdefault, # to make backporting simpler
967 )
970 )
968 coreconfigitem('subrepos', 'hg:allowed',
971 coreconfigitem('subrepos', 'hg:allowed',
969 default=dynamicdefault,
972 default=dynamicdefault,
970 )
973 )
971 coreconfigitem('subrepos', 'git:allowed',
974 coreconfigitem('subrepos', 'git:allowed',
972 default=dynamicdefault,
975 default=dynamicdefault,
973 )
976 )
974 coreconfigitem('subrepos', 'svn:allowed',
977 coreconfigitem('subrepos', 'svn:allowed',
975 default=dynamicdefault,
978 default=dynamicdefault,
976 )
979 )
977 coreconfigitem('templates', '.*',
980 coreconfigitem('templates', '.*',
978 default=None,
981 default=None,
979 generic=True,
982 generic=True,
980 )
983 )
981 coreconfigitem('trusted', 'groups',
984 coreconfigitem('trusted', 'groups',
982 default=list,
985 default=list,
983 )
986 )
984 coreconfigitem('trusted', 'users',
987 coreconfigitem('trusted', 'users',
985 default=list,
988 default=list,
986 )
989 )
987 coreconfigitem('ui', '_usedassubrepo',
990 coreconfigitem('ui', '_usedassubrepo',
988 default=False,
991 default=False,
989 )
992 )
990 coreconfigitem('ui', 'allowemptycommit',
993 coreconfigitem('ui', 'allowemptycommit',
991 default=False,
994 default=False,
992 )
995 )
993 coreconfigitem('ui', 'archivemeta',
996 coreconfigitem('ui', 'archivemeta',
994 default=True,
997 default=True,
995 )
998 )
996 coreconfigitem('ui', 'askusername',
999 coreconfigitem('ui', 'askusername',
997 default=False,
1000 default=False,
998 )
1001 )
999 coreconfigitem('ui', 'clonebundlefallback',
1002 coreconfigitem('ui', 'clonebundlefallback',
1000 default=False,
1003 default=False,
1001 )
1004 )
1002 coreconfigitem('ui', 'clonebundleprefers',
1005 coreconfigitem('ui', 'clonebundleprefers',
1003 default=list,
1006 default=list,
1004 )
1007 )
1005 coreconfigitem('ui', 'clonebundles',
1008 coreconfigitem('ui', 'clonebundles',
1006 default=True,
1009 default=True,
1007 )
1010 )
1008 coreconfigitem('ui', 'color',
1011 coreconfigitem('ui', 'color',
1009 default='auto',
1012 default='auto',
1010 )
1013 )
1011 coreconfigitem('ui', 'commitsubrepos',
1014 coreconfigitem('ui', 'commitsubrepos',
1012 default=False,
1015 default=False,
1013 )
1016 )
1014 coreconfigitem('ui', 'debug',
1017 coreconfigitem('ui', 'debug',
1015 default=False,
1018 default=False,
1016 )
1019 )
1017 coreconfigitem('ui', 'debugger',
1020 coreconfigitem('ui', 'debugger',
1018 default=None,
1021 default=None,
1019 )
1022 )
1020 coreconfigitem('ui', 'editor',
1023 coreconfigitem('ui', 'editor',
1021 default=dynamicdefault,
1024 default=dynamicdefault,
1022 )
1025 )
1023 coreconfigitem('ui', 'fallbackencoding',
1026 coreconfigitem('ui', 'fallbackencoding',
1024 default=None,
1027 default=None,
1025 )
1028 )
1026 coreconfigitem('ui', 'forcecwd',
1029 coreconfigitem('ui', 'forcecwd',
1027 default=None,
1030 default=None,
1028 )
1031 )
1029 coreconfigitem('ui', 'forcemerge',
1032 coreconfigitem('ui', 'forcemerge',
1030 default=None,
1033 default=None,
1031 )
1034 )
1032 coreconfigitem('ui', 'formatdebug',
1035 coreconfigitem('ui', 'formatdebug',
1033 default=False,
1036 default=False,
1034 )
1037 )
1035 coreconfigitem('ui', 'formatjson',
1038 coreconfigitem('ui', 'formatjson',
1036 default=False,
1039 default=False,
1037 )
1040 )
1038 coreconfigitem('ui', 'formatted',
1041 coreconfigitem('ui', 'formatted',
1039 default=None,
1042 default=None,
1040 )
1043 )
1041 coreconfigitem('ui', 'graphnodetemplate',
1044 coreconfigitem('ui', 'graphnodetemplate',
1042 default=None,
1045 default=None,
1043 )
1046 )
1044 coreconfigitem('ui', 'interactive',
1047 coreconfigitem('ui', 'interactive',
1045 default=None,
1048 default=None,
1046 )
1049 )
1047 coreconfigitem('ui', 'interface',
1050 coreconfigitem('ui', 'interface',
1048 default=None,
1051 default=None,
1049 )
1052 )
1050 coreconfigitem('ui', 'interface.chunkselector',
1053 coreconfigitem('ui', 'interface.chunkselector',
1051 default=None,
1054 default=None,
1052 )
1055 )
1053 coreconfigitem('ui', 'logblockedtimes',
1056 coreconfigitem('ui', 'logblockedtimes',
1054 default=False,
1057 default=False,
1055 )
1058 )
1056 coreconfigitem('ui', 'logtemplate',
1059 coreconfigitem('ui', 'logtemplate',
1057 default=None,
1060 default=None,
1058 )
1061 )
1059 coreconfigitem('ui', 'merge',
1062 coreconfigitem('ui', 'merge',
1060 default=None,
1063 default=None,
1061 )
1064 )
1062 coreconfigitem('ui', 'mergemarkers',
1065 coreconfigitem('ui', 'mergemarkers',
1063 default='basic',
1066 default='basic',
1064 )
1067 )
1065 coreconfigitem('ui', 'mergemarkertemplate',
1068 coreconfigitem('ui', 'mergemarkertemplate',
1066 default=('{node|short} '
1069 default=('{node|short} '
1067 '{ifeq(tags, "tip", "", '
1070 '{ifeq(tags, "tip", "", '
1068 'ifeq(tags, "", "", "{tags} "))}'
1071 'ifeq(tags, "", "", "{tags} "))}'
1069 '{if(bookmarks, "{bookmarks} ")}'
1072 '{if(bookmarks, "{bookmarks} ")}'
1070 '{ifeq(branch, "default", "", "{branch} ")}'
1073 '{ifeq(branch, "default", "", "{branch} ")}'
1071 '- {author|user}: {desc|firstline}')
1074 '- {author|user}: {desc|firstline}')
1072 )
1075 )
1073 coreconfigitem('ui', 'nontty',
1076 coreconfigitem('ui', 'nontty',
1074 default=False,
1077 default=False,
1075 )
1078 )
1076 coreconfigitem('ui', 'origbackuppath',
1079 coreconfigitem('ui', 'origbackuppath',
1077 default=None,
1080 default=None,
1078 )
1081 )
1079 coreconfigitem('ui', 'paginate',
1082 coreconfigitem('ui', 'paginate',
1080 default=True,
1083 default=True,
1081 )
1084 )
1082 coreconfigitem('ui', 'patch',
1085 coreconfigitem('ui', 'patch',
1083 default=None,
1086 default=None,
1084 )
1087 )
1085 coreconfigitem('ui', 'portablefilenames',
1088 coreconfigitem('ui', 'portablefilenames',
1086 default='warn',
1089 default='warn',
1087 )
1090 )
1088 coreconfigitem('ui', 'promptecho',
1091 coreconfigitem('ui', 'promptecho',
1089 default=False,
1092 default=False,
1090 )
1093 )
1091 coreconfigitem('ui', 'quiet',
1094 coreconfigitem('ui', 'quiet',
1092 default=False,
1095 default=False,
1093 )
1096 )
1094 coreconfigitem('ui', 'quietbookmarkmove',
1097 coreconfigitem('ui', 'quietbookmarkmove',
1095 default=False,
1098 default=False,
1096 )
1099 )
1097 coreconfigitem('ui', 'remotecmd',
1100 coreconfigitem('ui', 'remotecmd',
1098 default='hg',
1101 default='hg',
1099 )
1102 )
1100 coreconfigitem('ui', 'report_untrusted',
1103 coreconfigitem('ui', 'report_untrusted',
1101 default=True,
1104 default=True,
1102 )
1105 )
1103 coreconfigitem('ui', 'rollback',
1106 coreconfigitem('ui', 'rollback',
1104 default=True,
1107 default=True,
1105 )
1108 )
1106 coreconfigitem('ui', 'slash',
1109 coreconfigitem('ui', 'slash',
1107 default=False,
1110 default=False,
1108 )
1111 )
1109 coreconfigitem('ui', 'ssh',
1112 coreconfigitem('ui', 'ssh',
1110 default='ssh',
1113 default='ssh',
1111 )
1114 )
1112 coreconfigitem('ui', 'ssherrorhint',
1115 coreconfigitem('ui', 'ssherrorhint',
1113 default=None,
1116 default=None,
1114 )
1117 )
1115 coreconfigitem('ui', 'statuscopies',
1118 coreconfigitem('ui', 'statuscopies',
1116 default=False,
1119 default=False,
1117 )
1120 )
1118 coreconfigitem('ui', 'strict',
1121 coreconfigitem('ui', 'strict',
1119 default=False,
1122 default=False,
1120 )
1123 )
1121 coreconfigitem('ui', 'style',
1124 coreconfigitem('ui', 'style',
1122 default='',
1125 default='',
1123 )
1126 )
1124 coreconfigitem('ui', 'supportcontact',
1127 coreconfigitem('ui', 'supportcontact',
1125 default=None,
1128 default=None,
1126 )
1129 )
1127 coreconfigitem('ui', 'textwidth',
1130 coreconfigitem('ui', 'textwidth',
1128 default=78,
1131 default=78,
1129 )
1132 )
1130 coreconfigitem('ui', 'timeout',
1133 coreconfigitem('ui', 'timeout',
1131 default='600',
1134 default='600',
1132 )
1135 )
1133 coreconfigitem('ui', 'timeout.warn',
1136 coreconfigitem('ui', 'timeout.warn',
1134 default=0,
1137 default=0,
1135 )
1138 )
1136 coreconfigitem('ui', 'traceback',
1139 coreconfigitem('ui', 'traceback',
1137 default=False,
1140 default=False,
1138 )
1141 )
1139 coreconfigitem('ui', 'tweakdefaults',
1142 coreconfigitem('ui', 'tweakdefaults',
1140 default=False,
1143 default=False,
1141 )
1144 )
1142 coreconfigitem('ui', 'username',
1145 coreconfigitem('ui', 'username',
1143 alias=[('ui', 'user')]
1146 alias=[('ui', 'user')]
1144 )
1147 )
1145 coreconfigitem('ui', 'verbose',
1148 coreconfigitem('ui', 'verbose',
1146 default=False,
1149 default=False,
1147 )
1150 )
1148 coreconfigitem('verify', 'skipflags',
1151 coreconfigitem('verify', 'skipflags',
1149 default=None,
1152 default=None,
1150 )
1153 )
1151 coreconfigitem('web', 'allowbz2',
1154 coreconfigitem('web', 'allowbz2',
1152 default=False,
1155 default=False,
1153 )
1156 )
1154 coreconfigitem('web', 'allowgz',
1157 coreconfigitem('web', 'allowgz',
1155 default=False,
1158 default=False,
1156 )
1159 )
1157 coreconfigitem('web', 'allow-pull',
1160 coreconfigitem('web', 'allow-pull',
1158 alias=[('web', 'allowpull')],
1161 alias=[('web', 'allowpull')],
1159 default=True,
1162 default=True,
1160 )
1163 )
1161 coreconfigitem('web', 'allow-push',
1164 coreconfigitem('web', 'allow-push',
1162 alias=[('web', 'allow_push')],
1165 alias=[('web', 'allow_push')],
1163 default=list,
1166 default=list,
1164 )
1167 )
1165 coreconfigitem('web', 'allowzip',
1168 coreconfigitem('web', 'allowzip',
1166 default=False,
1169 default=False,
1167 )
1170 )
1168 coreconfigitem('web', 'archivesubrepos',
1171 coreconfigitem('web', 'archivesubrepos',
1169 default=False,
1172 default=False,
1170 )
1173 )
1171 coreconfigitem('web', 'cache',
1174 coreconfigitem('web', 'cache',
1172 default=True,
1175 default=True,
1173 )
1176 )
1174 coreconfigitem('web', 'contact',
1177 coreconfigitem('web', 'contact',
1175 default=None,
1178 default=None,
1176 )
1179 )
1177 coreconfigitem('web', 'deny_push',
1180 coreconfigitem('web', 'deny_push',
1178 default=list,
1181 default=list,
1179 )
1182 )
1180 coreconfigitem('web', 'guessmime',
1183 coreconfigitem('web', 'guessmime',
1181 default=False,
1184 default=False,
1182 )
1185 )
1183 coreconfigitem('web', 'hidden',
1186 coreconfigitem('web', 'hidden',
1184 default=False,
1187 default=False,
1185 )
1188 )
1186 coreconfigitem('web', 'labels',
1189 coreconfigitem('web', 'labels',
1187 default=list,
1190 default=list,
1188 )
1191 )
1189 coreconfigitem('web', 'logoimg',
1192 coreconfigitem('web', 'logoimg',
1190 default='hglogo.png',
1193 default='hglogo.png',
1191 )
1194 )
1192 coreconfigitem('web', 'logourl',
1195 coreconfigitem('web', 'logourl',
1193 default='https://mercurial-scm.org/',
1196 default='https://mercurial-scm.org/',
1194 )
1197 )
1195 coreconfigitem('web', 'accesslog',
1198 coreconfigitem('web', 'accesslog',
1196 default='-',
1199 default='-',
1197 )
1200 )
1198 coreconfigitem('web', 'address',
1201 coreconfigitem('web', 'address',
1199 default='',
1202 default='',
1200 )
1203 )
1201 coreconfigitem('web', 'allow_archive',
1204 coreconfigitem('web', 'allow_archive',
1202 default=list,
1205 default=list,
1203 )
1206 )
1204 coreconfigitem('web', 'allow_read',
1207 coreconfigitem('web', 'allow_read',
1205 default=list,
1208 default=list,
1206 )
1209 )
1207 coreconfigitem('web', 'baseurl',
1210 coreconfigitem('web', 'baseurl',
1208 default=None,
1211 default=None,
1209 )
1212 )
1210 coreconfigitem('web', 'cacerts',
1213 coreconfigitem('web', 'cacerts',
1211 default=None,
1214 default=None,
1212 )
1215 )
1213 coreconfigitem('web', 'certificate',
1216 coreconfigitem('web', 'certificate',
1214 default=None,
1217 default=None,
1215 )
1218 )
1216 coreconfigitem('web', 'collapse',
1219 coreconfigitem('web', 'collapse',
1217 default=False,
1220 default=False,
1218 )
1221 )
1219 coreconfigitem('web', 'csp',
1222 coreconfigitem('web', 'csp',
1220 default=None,
1223 default=None,
1221 )
1224 )
1222 coreconfigitem('web', 'deny_read',
1225 coreconfigitem('web', 'deny_read',
1223 default=list,
1226 default=list,
1224 )
1227 )
1225 coreconfigitem('web', 'descend',
1228 coreconfigitem('web', 'descend',
1226 default=True,
1229 default=True,
1227 )
1230 )
1228 coreconfigitem('web', 'description',
1231 coreconfigitem('web', 'description',
1229 default="",
1232 default="",
1230 )
1233 )
1231 coreconfigitem('web', 'encoding',
1234 coreconfigitem('web', 'encoding',
1232 default=lambda: encoding.encoding,
1235 default=lambda: encoding.encoding,
1233 )
1236 )
1234 coreconfigitem('web', 'errorlog',
1237 coreconfigitem('web', 'errorlog',
1235 default='-',
1238 default='-',
1236 )
1239 )
1237 coreconfigitem('web', 'ipv6',
1240 coreconfigitem('web', 'ipv6',
1238 default=False,
1241 default=False,
1239 )
1242 )
1240 coreconfigitem('web', 'maxchanges',
1243 coreconfigitem('web', 'maxchanges',
1241 default=10,
1244 default=10,
1242 )
1245 )
1243 coreconfigitem('web', 'maxfiles',
1246 coreconfigitem('web', 'maxfiles',
1244 default=10,
1247 default=10,
1245 )
1248 )
1246 coreconfigitem('web', 'maxshortchanges',
1249 coreconfigitem('web', 'maxshortchanges',
1247 default=60,
1250 default=60,
1248 )
1251 )
1249 coreconfigitem('web', 'motd',
1252 coreconfigitem('web', 'motd',
1250 default='',
1253 default='',
1251 )
1254 )
1252 coreconfigitem('web', 'name',
1255 coreconfigitem('web', 'name',
1253 default=dynamicdefault,
1256 default=dynamicdefault,
1254 )
1257 )
1255 coreconfigitem('web', 'port',
1258 coreconfigitem('web', 'port',
1256 default=8000,
1259 default=8000,
1257 )
1260 )
1258 coreconfigitem('web', 'prefix',
1261 coreconfigitem('web', 'prefix',
1259 default='',
1262 default='',
1260 )
1263 )
1261 coreconfigitem('web', 'push_ssl',
1264 coreconfigitem('web', 'push_ssl',
1262 default=True,
1265 default=True,
1263 )
1266 )
1264 coreconfigitem('web', 'refreshinterval',
1267 coreconfigitem('web', 'refreshinterval',
1265 default=20,
1268 default=20,
1266 )
1269 )
1267 coreconfigitem('web', 'server-header',
1270 coreconfigitem('web', 'server-header',
1268 default=None,
1271 default=None,
1269 )
1272 )
1270 coreconfigitem('web', 'staticurl',
1273 coreconfigitem('web', 'staticurl',
1271 default=None,
1274 default=None,
1272 )
1275 )
1273 coreconfigitem('web', 'stripes',
1276 coreconfigitem('web', 'stripes',
1274 default=1,
1277 default=1,
1275 )
1278 )
1276 coreconfigitem('web', 'style',
1279 coreconfigitem('web', 'style',
1277 default='paper',
1280 default='paper',
1278 )
1281 )
1279 coreconfigitem('web', 'templates',
1282 coreconfigitem('web', 'templates',
1280 default=None,
1283 default=None,
1281 )
1284 )
1282 coreconfigitem('web', 'view',
1285 coreconfigitem('web', 'view',
1283 default='served',
1286 default='served',
1284 )
1287 )
1285 coreconfigitem('worker', 'backgroundclose',
1288 coreconfigitem('worker', 'backgroundclose',
1286 default=dynamicdefault,
1289 default=dynamicdefault,
1287 )
1290 )
1288 # Windows defaults to a limit of 512 open files. A buffer of 128
1291 # Windows defaults to a limit of 512 open files. A buffer of 128
1289 # should give us enough headway.
1292 # should give us enough headway.
1290 coreconfigitem('worker', 'backgroundclosemaxqueue',
1293 coreconfigitem('worker', 'backgroundclosemaxqueue',
1291 default=384,
1294 default=384,
1292 )
1295 )
1293 coreconfigitem('worker', 'backgroundcloseminfilecount',
1296 coreconfigitem('worker', 'backgroundcloseminfilecount',
1294 default=2048,
1297 default=2048,
1295 )
1298 )
1296 coreconfigitem('worker', 'backgroundclosethreadcount',
1299 coreconfigitem('worker', 'backgroundclosethreadcount',
1297 default=4,
1300 default=4,
1298 )
1301 )
1299 coreconfigitem('worker', 'enabled',
1302 coreconfigitem('worker', 'enabled',
1300 default=True,
1303 default=True,
1301 )
1304 )
1302 coreconfigitem('worker', 'numcpus',
1305 coreconfigitem('worker', 'numcpus',
1303 default=None,
1306 default=None,
1304 )
1307 )
1305
1308
1306 # Rebase related configuration moved to core because other extension are doing
1309 # Rebase related configuration moved to core because other extension are doing
1307 # strange things. For example, shelve import the extensions to reuse some bit
1310 # strange things. For example, shelve import the extensions to reuse some bit
1308 # without formally loading it.
1311 # without formally loading it.
1309 coreconfigitem('commands', 'rebase.requiredest',
1312 coreconfigitem('commands', 'rebase.requiredest',
1310 default=False,
1313 default=False,
1311 )
1314 )
1312 coreconfigitem('experimental', 'rebaseskipobsolete',
1315 coreconfigitem('experimental', 'rebaseskipobsolete',
1313 default=True,
1316 default=True,
1314 )
1317 )
1315 coreconfigitem('rebase', 'singletransaction',
1318 coreconfigitem('rebase', 'singletransaction',
1316 default=False,
1319 default=False,
1317 )
1320 )
1318 coreconfigitem('rebase', 'experimental.inmemory',
1321 coreconfigitem('rebase', 'experimental.inmemory',
1319 default=False,
1322 default=False,
1320 )
1323 )
@@ -1,2623 +1,2628 b''
1 The Mercurial system uses a set of configuration files to control
1 The Mercurial system uses a set of configuration files to control
2 aspects of its behavior.
2 aspects of its behavior.
3
3
4 Troubleshooting
4 Troubleshooting
5 ===============
5 ===============
6
6
7 If you're having problems with your configuration,
7 If you're having problems with your configuration,
8 :hg:`config --debug` can help you understand what is introducing
8 :hg:`config --debug` can help you understand what is introducing
9 a setting into your environment.
9 a setting into your environment.
10
10
11 See :hg:`help config.syntax` and :hg:`help config.files`
11 See :hg:`help config.syntax` and :hg:`help config.files`
12 for information about how and where to override things.
12 for information about how and where to override things.
13
13
14 Structure
14 Structure
15 =========
15 =========
16
16
17 The configuration files use a simple ini-file format. A configuration
17 The configuration files use a simple ini-file format. A configuration
18 file consists of sections, led by a ``[section]`` header and followed
18 file consists of sections, led by a ``[section]`` header and followed
19 by ``name = value`` entries::
19 by ``name = value`` entries::
20
20
21 [ui]
21 [ui]
22 username = Firstname Lastname <firstname.lastname@example.net>
22 username = Firstname Lastname <firstname.lastname@example.net>
23 verbose = True
23 verbose = True
24
24
25 The above entries will be referred to as ``ui.username`` and
25 The above entries will be referred to as ``ui.username`` and
26 ``ui.verbose``, respectively. See :hg:`help config.syntax`.
26 ``ui.verbose``, respectively. See :hg:`help config.syntax`.
27
27
28 Files
28 Files
29 =====
29 =====
30
30
31 Mercurial reads configuration data from several files, if they exist.
31 Mercurial reads configuration data from several files, if they exist.
32 These files do not exist by default and you will have to create the
32 These files do not exist by default and you will have to create the
33 appropriate configuration files yourself:
33 appropriate configuration files yourself:
34
34
35 Local configuration is put into the per-repository ``<repo>/.hg/hgrc`` file.
35 Local configuration is put into the per-repository ``<repo>/.hg/hgrc`` file.
36
36
37 Global configuration like the username setting is typically put into:
37 Global configuration like the username setting is typically put into:
38
38
39 .. container:: windows
39 .. container:: windows
40
40
41 - ``%USERPROFILE%\mercurial.ini`` (on Windows)
41 - ``%USERPROFILE%\mercurial.ini`` (on Windows)
42
42
43 .. container:: unix.plan9
43 .. container:: unix.plan9
44
44
45 - ``$HOME/.hgrc`` (on Unix, Plan9)
45 - ``$HOME/.hgrc`` (on Unix, Plan9)
46
46
47 The names of these files depend on the system on which Mercurial is
47 The names of these files depend on the system on which Mercurial is
48 installed. ``*.rc`` files from a single directory are read in
48 installed. ``*.rc`` files from a single directory are read in
49 alphabetical order, later ones overriding earlier ones. Where multiple
49 alphabetical order, later ones overriding earlier ones. Where multiple
50 paths are given below, settings from earlier paths override later
50 paths are given below, settings from earlier paths override later
51 ones.
51 ones.
52
52
53 .. container:: verbose.unix
53 .. container:: verbose.unix
54
54
55 On Unix, the following files are consulted:
55 On Unix, the following files are consulted:
56
56
57 - ``<repo>/.hg/hgrc`` (per-repository)
57 - ``<repo>/.hg/hgrc`` (per-repository)
58 - ``$HOME/.hgrc`` (per-user)
58 - ``$HOME/.hgrc`` (per-user)
59 - ``${XDG_CONFIG_HOME:-$HOME/.config}/hg/hgrc`` (per-user)
59 - ``${XDG_CONFIG_HOME:-$HOME/.config}/hg/hgrc`` (per-user)
60 - ``<install-root>/etc/mercurial/hgrc`` (per-installation)
60 - ``<install-root>/etc/mercurial/hgrc`` (per-installation)
61 - ``<install-root>/etc/mercurial/hgrc.d/*.rc`` (per-installation)
61 - ``<install-root>/etc/mercurial/hgrc.d/*.rc`` (per-installation)
62 - ``/etc/mercurial/hgrc`` (per-system)
62 - ``/etc/mercurial/hgrc`` (per-system)
63 - ``/etc/mercurial/hgrc.d/*.rc`` (per-system)
63 - ``/etc/mercurial/hgrc.d/*.rc`` (per-system)
64 - ``<internal>/default.d/*.rc`` (defaults)
64 - ``<internal>/default.d/*.rc`` (defaults)
65
65
66 .. container:: verbose.windows
66 .. container:: verbose.windows
67
67
68 On Windows, the following files are consulted:
68 On Windows, the following files are consulted:
69
69
70 - ``<repo>/.hg/hgrc`` (per-repository)
70 - ``<repo>/.hg/hgrc`` (per-repository)
71 - ``%USERPROFILE%\.hgrc`` (per-user)
71 - ``%USERPROFILE%\.hgrc`` (per-user)
72 - ``%USERPROFILE%\Mercurial.ini`` (per-user)
72 - ``%USERPROFILE%\Mercurial.ini`` (per-user)
73 - ``%HOME%\.hgrc`` (per-user)
73 - ``%HOME%\.hgrc`` (per-user)
74 - ``%HOME%\Mercurial.ini`` (per-user)
74 - ``%HOME%\Mercurial.ini`` (per-user)
75 - ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial`` (per-installation)
75 - ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial`` (per-installation)
76 - ``<install-dir>\hgrc.d\*.rc`` (per-installation)
76 - ``<install-dir>\hgrc.d\*.rc`` (per-installation)
77 - ``<install-dir>\Mercurial.ini`` (per-installation)
77 - ``<install-dir>\Mercurial.ini`` (per-installation)
78 - ``<internal>/default.d/*.rc`` (defaults)
78 - ``<internal>/default.d/*.rc`` (defaults)
79
79
80 .. note::
80 .. note::
81
81
82 The registry key ``HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Mercurial``
82 The registry key ``HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Mercurial``
83 is used when running 32-bit Python on 64-bit Windows.
83 is used when running 32-bit Python on 64-bit Windows.
84
84
85 .. container:: windows
85 .. container:: windows
86
86
87 On Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``.
87 On Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``.
88
88
89 .. container:: verbose.plan9
89 .. container:: verbose.plan9
90
90
91 On Plan9, the following files are consulted:
91 On Plan9, the following files are consulted:
92
92
93 - ``<repo>/.hg/hgrc`` (per-repository)
93 - ``<repo>/.hg/hgrc`` (per-repository)
94 - ``$home/lib/hgrc`` (per-user)
94 - ``$home/lib/hgrc`` (per-user)
95 - ``<install-root>/lib/mercurial/hgrc`` (per-installation)
95 - ``<install-root>/lib/mercurial/hgrc`` (per-installation)
96 - ``<install-root>/lib/mercurial/hgrc.d/*.rc`` (per-installation)
96 - ``<install-root>/lib/mercurial/hgrc.d/*.rc`` (per-installation)
97 - ``/lib/mercurial/hgrc`` (per-system)
97 - ``/lib/mercurial/hgrc`` (per-system)
98 - ``/lib/mercurial/hgrc.d/*.rc`` (per-system)
98 - ``/lib/mercurial/hgrc.d/*.rc`` (per-system)
99 - ``<internal>/default.d/*.rc`` (defaults)
99 - ``<internal>/default.d/*.rc`` (defaults)
100
100
101 Per-repository configuration options only apply in a
101 Per-repository configuration options only apply in a
102 particular repository. This file is not version-controlled, and
102 particular repository. This file is not version-controlled, and
103 will not get transferred during a "clone" operation. Options in
103 will not get transferred during a "clone" operation. Options in
104 this file override options in all other configuration files.
104 this file override options in all other configuration files.
105
105
106 .. container:: unix.plan9
106 .. container:: unix.plan9
107
107
108 On Plan 9 and Unix, most of this file will be ignored if it doesn't
108 On Plan 9 and Unix, most of this file will be ignored if it doesn't
109 belong to a trusted user or to a trusted group. See
109 belong to a trusted user or to a trusted group. See
110 :hg:`help config.trusted` for more details.
110 :hg:`help config.trusted` for more details.
111
111
112 Per-user configuration file(s) are for the user running Mercurial. Options
112 Per-user configuration file(s) are for the user running Mercurial. Options
113 in these files apply to all Mercurial commands executed by this user in any
113 in these files apply to all Mercurial commands executed by this user in any
114 directory. Options in these files override per-system and per-installation
114 directory. Options in these files override per-system and per-installation
115 options.
115 options.
116
116
117 Per-installation configuration files are searched for in the
117 Per-installation configuration files are searched for in the
118 directory where Mercurial is installed. ``<install-root>`` is the
118 directory where Mercurial is installed. ``<install-root>`` is the
119 parent directory of the **hg** executable (or symlink) being run.
119 parent directory of the **hg** executable (or symlink) being run.
120
120
121 .. container:: unix.plan9
121 .. container:: unix.plan9
122
122
123 For example, if installed in ``/shared/tools/bin/hg``, Mercurial
123 For example, if installed in ``/shared/tools/bin/hg``, Mercurial
124 will look in ``/shared/tools/etc/mercurial/hgrc``. Options in these
124 will look in ``/shared/tools/etc/mercurial/hgrc``. Options in these
125 files apply to all Mercurial commands executed by any user in any
125 files apply to all Mercurial commands executed by any user in any
126 directory.
126 directory.
127
127
128 Per-installation configuration files are for the system on
128 Per-installation configuration files are for the system on
129 which Mercurial is running. Options in these files apply to all
129 which Mercurial is running. Options in these files apply to all
130 Mercurial commands executed by any user in any directory. Registry
130 Mercurial commands executed by any user in any directory. Registry
131 keys contain PATH-like strings, every part of which must reference
131 keys contain PATH-like strings, every part of which must reference
132 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
132 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
133 be read. Mercurial checks each of these locations in the specified
133 be read. Mercurial checks each of these locations in the specified
134 order until one or more configuration files are detected.
134 order until one or more configuration files are detected.
135
135
136 Per-system configuration files are for the system on which Mercurial
136 Per-system configuration files are for the system on which Mercurial
137 is running. Options in these files apply to all Mercurial commands
137 is running. Options in these files apply to all Mercurial commands
138 executed by any user in any directory. Options in these files
138 executed by any user in any directory. Options in these files
139 override per-installation options.
139 override per-installation options.
140
140
141 Mercurial comes with some default configuration. The default configuration
141 Mercurial comes with some default configuration. The default configuration
142 files are installed with Mercurial and will be overwritten on upgrades. Default
142 files are installed with Mercurial and will be overwritten on upgrades. Default
143 configuration files should never be edited by users or administrators but can
143 configuration files should never be edited by users or administrators but can
144 be overridden in other configuration files. So far the directory only contains
144 be overridden in other configuration files. So far the directory only contains
145 merge tool configuration but packagers can also put other default configuration
145 merge tool configuration but packagers can also put other default configuration
146 there.
146 there.
147
147
148 Syntax
148 Syntax
149 ======
149 ======
150
150
151 A configuration file consists of sections, led by a ``[section]`` header
151 A configuration file consists of sections, led by a ``[section]`` header
152 and followed by ``name = value`` entries (sometimes called
152 and followed by ``name = value`` entries (sometimes called
153 ``configuration keys``)::
153 ``configuration keys``)::
154
154
155 [spam]
155 [spam]
156 eggs=ham
156 eggs=ham
157 green=
157 green=
158 eggs
158 eggs
159
159
160 Each line contains one entry. If the lines that follow are indented,
160 Each line contains one entry. If the lines that follow are indented,
161 they are treated as continuations of that entry. Leading whitespace is
161 they are treated as continuations of that entry. Leading whitespace is
162 removed from values. Empty lines are skipped. Lines beginning with
162 removed from values. Empty lines are skipped. Lines beginning with
163 ``#`` or ``;`` are ignored and may be used to provide comments.
163 ``#`` or ``;`` are ignored and may be used to provide comments.
164
164
165 Configuration keys can be set multiple times, in which case Mercurial
165 Configuration keys can be set multiple times, in which case Mercurial
166 will use the value that was configured last. As an example::
166 will use the value that was configured last. As an example::
167
167
168 [spam]
168 [spam]
169 eggs=large
169 eggs=large
170 ham=serrano
170 ham=serrano
171 eggs=small
171 eggs=small
172
172
173 This would set the configuration key named ``eggs`` to ``small``.
173 This would set the configuration key named ``eggs`` to ``small``.
174
174
175 It is also possible to define a section multiple times. A section can
175 It is also possible to define a section multiple times. A section can
176 be redefined on the same and/or on different configuration files. For
176 be redefined on the same and/or on different configuration files. For
177 example::
177 example::
178
178
179 [foo]
179 [foo]
180 eggs=large
180 eggs=large
181 ham=serrano
181 ham=serrano
182 eggs=small
182 eggs=small
183
183
184 [bar]
184 [bar]
185 eggs=ham
185 eggs=ham
186 green=
186 green=
187 eggs
187 eggs
188
188
189 [foo]
189 [foo]
190 ham=prosciutto
190 ham=prosciutto
191 eggs=medium
191 eggs=medium
192 bread=toasted
192 bread=toasted
193
193
194 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
194 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
195 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
195 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
196 respectively. As you can see there only thing that matters is the last
196 respectively. As you can see there only thing that matters is the last
197 value that was set for each of the configuration keys.
197 value that was set for each of the configuration keys.
198
198
199 If a configuration key is set multiple times in different
199 If a configuration key is set multiple times in different
200 configuration files the final value will depend on the order in which
200 configuration files the final value will depend on the order in which
201 the different configuration files are read, with settings from earlier
201 the different configuration files are read, with settings from earlier
202 paths overriding later ones as described on the ``Files`` section
202 paths overriding later ones as described on the ``Files`` section
203 above.
203 above.
204
204
205 A line of the form ``%include file`` will include ``file`` into the
205 A line of the form ``%include file`` will include ``file`` into the
206 current configuration file. The inclusion is recursive, which means
206 current configuration file. The inclusion is recursive, which means
207 that included files can include other files. Filenames are relative to
207 that included files can include other files. Filenames are relative to
208 the configuration file in which the ``%include`` directive is found.
208 the configuration file in which the ``%include`` directive is found.
209 Environment variables and ``~user`` constructs are expanded in
209 Environment variables and ``~user`` constructs are expanded in
210 ``file``. This lets you do something like::
210 ``file``. This lets you do something like::
211
211
212 %include ~/.hgrc.d/$HOST.rc
212 %include ~/.hgrc.d/$HOST.rc
213
213
214 to include a different configuration file on each computer you use.
214 to include a different configuration file on each computer you use.
215
215
216 A line with ``%unset name`` will remove ``name`` from the current
216 A line with ``%unset name`` will remove ``name`` from the current
217 section, if it has been set previously.
217 section, if it has been set previously.
218
218
219 The values are either free-form text strings, lists of text strings,
219 The values are either free-form text strings, lists of text strings,
220 or Boolean values. Boolean values can be set to true using any of "1",
220 or Boolean values. Boolean values can be set to true using any of "1",
221 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
221 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
222 (all case insensitive).
222 (all case insensitive).
223
223
224 List values are separated by whitespace or comma, except when values are
224 List values are separated by whitespace or comma, except when values are
225 placed in double quotation marks::
225 placed in double quotation marks::
226
226
227 allow_read = "John Doe, PhD", brian, betty
227 allow_read = "John Doe, PhD", brian, betty
228
228
229 Quotation marks can be escaped by prefixing them with a backslash. Only
229 Quotation marks can be escaped by prefixing them with a backslash. Only
230 quotation marks at the beginning of a word is counted as a quotation
230 quotation marks at the beginning of a word is counted as a quotation
231 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
231 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
232
232
233 Sections
233 Sections
234 ========
234 ========
235
235
236 This section describes the different sections that may appear in a
236 This section describes the different sections that may appear in a
237 Mercurial configuration file, the purpose of each section, its possible
237 Mercurial configuration file, the purpose of each section, its possible
238 keys, and their possible values.
238 keys, and their possible values.
239
239
240 ``alias``
240 ``alias``
241 ---------
241 ---------
242
242
243 Defines command aliases.
243 Defines command aliases.
244
244
245 Aliases allow you to define your own commands in terms of other
245 Aliases allow you to define your own commands in terms of other
246 commands (or aliases), optionally including arguments. Positional
246 commands (or aliases), optionally including arguments. Positional
247 arguments in the form of ``$1``, ``$2``, etc. in the alias definition
247 arguments in the form of ``$1``, ``$2``, etc. in the alias definition
248 are expanded by Mercurial before execution. Positional arguments not
248 are expanded by Mercurial before execution. Positional arguments not
249 already used by ``$N`` in the definition are put at the end of the
249 already used by ``$N`` in the definition are put at the end of the
250 command to be executed.
250 command to be executed.
251
251
252 Alias definitions consist of lines of the form::
252 Alias definitions consist of lines of the form::
253
253
254 <alias> = <command> [<argument>]...
254 <alias> = <command> [<argument>]...
255
255
256 For example, this definition::
256 For example, this definition::
257
257
258 latest = log --limit 5
258 latest = log --limit 5
259
259
260 creates a new command ``latest`` that shows only the five most recent
260 creates a new command ``latest`` that shows only the five most recent
261 changesets. You can define subsequent aliases using earlier ones::
261 changesets. You can define subsequent aliases using earlier ones::
262
262
263 stable5 = latest -b stable
263 stable5 = latest -b stable
264
264
265 .. note::
265 .. note::
266
266
267 It is possible to create aliases with the same names as
267 It is possible to create aliases with the same names as
268 existing commands, which will then override the original
268 existing commands, which will then override the original
269 definitions. This is almost always a bad idea!
269 definitions. This is almost always a bad idea!
270
270
271 An alias can start with an exclamation point (``!``) to make it a
271 An alias can start with an exclamation point (``!``) to make it a
272 shell alias. A shell alias is executed with the shell and will let you
272 shell alias. A shell alias is executed with the shell and will let you
273 run arbitrary commands. As an example, ::
273 run arbitrary commands. As an example, ::
274
274
275 echo = !echo $@
275 echo = !echo $@
276
276
277 will let you do ``hg echo foo`` to have ``foo`` printed in your
277 will let you do ``hg echo foo`` to have ``foo`` printed in your
278 terminal. A better example might be::
278 terminal. A better example might be::
279
279
280 purge = !$HG status --no-status --unknown -0 re: | xargs -0 rm -f
280 purge = !$HG status --no-status --unknown -0 re: | xargs -0 rm -f
281
281
282 which will make ``hg purge`` delete all unknown files in the
282 which will make ``hg purge`` delete all unknown files in the
283 repository in the same manner as the purge extension.
283 repository in the same manner as the purge extension.
284
284
285 Positional arguments like ``$1``, ``$2``, etc. in the alias definition
285 Positional arguments like ``$1``, ``$2``, etc. in the alias definition
286 expand to the command arguments. Unmatched arguments are
286 expand to the command arguments. Unmatched arguments are
287 removed. ``$0`` expands to the alias name and ``$@`` expands to all
287 removed. ``$0`` expands to the alias name and ``$@`` expands to all
288 arguments separated by a space. ``"$@"`` (with quotes) expands to all
288 arguments separated by a space. ``"$@"`` (with quotes) expands to all
289 arguments quoted individually and separated by a space. These expansions
289 arguments quoted individually and separated by a space. These expansions
290 happen before the command is passed to the shell.
290 happen before the command is passed to the shell.
291
291
292 Shell aliases are executed in an environment where ``$HG`` expands to
292 Shell aliases are executed in an environment where ``$HG`` expands to
293 the path of the Mercurial that was used to execute the alias. This is
293 the path of the Mercurial that was used to execute the alias. This is
294 useful when you want to call further Mercurial commands in a shell
294 useful when you want to call further Mercurial commands in a shell
295 alias, as was done above for the purge alias. In addition,
295 alias, as was done above for the purge alias. In addition,
296 ``$HG_ARGS`` expands to the arguments given to Mercurial. In the ``hg
296 ``$HG_ARGS`` expands to the arguments given to Mercurial. In the ``hg
297 echo foo`` call above, ``$HG_ARGS`` would expand to ``echo foo``.
297 echo foo`` call above, ``$HG_ARGS`` would expand to ``echo foo``.
298
298
299 .. note::
299 .. note::
300
300
301 Some global configuration options such as ``-R`` are
301 Some global configuration options such as ``-R`` are
302 processed before shell aliases and will thus not be passed to
302 processed before shell aliases and will thus not be passed to
303 aliases.
303 aliases.
304
304
305
305
306 ``annotate``
306 ``annotate``
307 ------------
307 ------------
308
308
309 Settings used when displaying file annotations. All values are
309 Settings used when displaying file annotations. All values are
310 Booleans and default to False. See :hg:`help config.diff` for
310 Booleans and default to False. See :hg:`help config.diff` for
311 related options for the diff command.
311 related options for the diff command.
312
312
313 ``ignorews``
313 ``ignorews``
314 Ignore white space when comparing lines.
314 Ignore white space when comparing lines.
315
315
316 ``ignorewseol``
316 ``ignorewseol``
317 Ignore white space at the end of a line when comparing lines.
317 Ignore white space at the end of a line when comparing lines.
318
318
319 ``ignorewsamount``
319 ``ignorewsamount``
320 Ignore changes in the amount of white space.
320 Ignore changes in the amount of white space.
321
321
322 ``ignoreblanklines``
322 ``ignoreblanklines``
323 Ignore changes whose lines are all blank.
323 Ignore changes whose lines are all blank.
324
324
325
325
326 ``auth``
326 ``auth``
327 --------
327 --------
328
328
329 Authentication credentials and other authentication-like configuration
329 Authentication credentials and other authentication-like configuration
330 for HTTP connections. This section allows you to store usernames and
330 for HTTP connections. This section allows you to store usernames and
331 passwords for use when logging *into* HTTP servers. See
331 passwords for use when logging *into* HTTP servers. See
332 :hg:`help config.web` if you want to configure *who* can login to
332 :hg:`help config.web` if you want to configure *who* can login to
333 your HTTP server.
333 your HTTP server.
334
334
335 The following options apply to all hosts.
335 The following options apply to all hosts.
336
336
337 ``cookiefile``
337 ``cookiefile``
338 Path to a file containing HTTP cookie lines. Cookies matching a
338 Path to a file containing HTTP cookie lines. Cookies matching a
339 host will be sent automatically.
339 host will be sent automatically.
340
340
341 The file format uses the Mozilla cookies.txt format, which defines cookies
341 The file format uses the Mozilla cookies.txt format, which defines cookies
342 on their own lines. Each line contains 7 fields delimited by the tab
342 on their own lines. Each line contains 7 fields delimited by the tab
343 character (domain, is_domain_cookie, path, is_secure, expires, name,
343 character (domain, is_domain_cookie, path, is_secure, expires, name,
344 value). For more info, do an Internet search for "Netscape cookies.txt
344 value). For more info, do an Internet search for "Netscape cookies.txt
345 format."
345 format."
346
346
347 Note: the cookies parser does not handle port numbers on domains. You
347 Note: the cookies parser does not handle port numbers on domains. You
348 will need to remove ports from the domain for the cookie to be recognized.
348 will need to remove ports from the domain for the cookie to be recognized.
349 This could result in a cookie being disclosed to an unwanted server.
349 This could result in a cookie being disclosed to an unwanted server.
350
350
351 The cookies file is read-only.
351 The cookies file is read-only.
352
352
353 Other options in this section are grouped by name and have the following
353 Other options in this section are grouped by name and have the following
354 format::
354 format::
355
355
356 <name>.<argument> = <value>
356 <name>.<argument> = <value>
357
357
358 where ``<name>`` is used to group arguments into authentication
358 where ``<name>`` is used to group arguments into authentication
359 entries. Example::
359 entries. Example::
360
360
361 foo.prefix = hg.intevation.de/mercurial
361 foo.prefix = hg.intevation.de/mercurial
362 foo.username = foo
362 foo.username = foo
363 foo.password = bar
363 foo.password = bar
364 foo.schemes = http https
364 foo.schemes = http https
365
365
366 bar.prefix = secure.example.org
366 bar.prefix = secure.example.org
367 bar.key = path/to/file.key
367 bar.key = path/to/file.key
368 bar.cert = path/to/file.cert
368 bar.cert = path/to/file.cert
369 bar.schemes = https
369 bar.schemes = https
370
370
371 Supported arguments:
371 Supported arguments:
372
372
373 ``prefix``
373 ``prefix``
374 Either ``*`` or a URI prefix with or without the scheme part.
374 Either ``*`` or a URI prefix with or without the scheme part.
375 The authentication entry with the longest matching prefix is used
375 The authentication entry with the longest matching prefix is used
376 (where ``*`` matches everything and counts as a match of length
376 (where ``*`` matches everything and counts as a match of length
377 1). If the prefix doesn't include a scheme, the match is performed
377 1). If the prefix doesn't include a scheme, the match is performed
378 against the URI with its scheme stripped as well, and the schemes
378 against the URI with its scheme stripped as well, and the schemes
379 argument, q.v., is then subsequently consulted.
379 argument, q.v., is then subsequently consulted.
380
380
381 ``username``
381 ``username``
382 Optional. Username to authenticate with. If not given, and the
382 Optional. Username to authenticate with. If not given, and the
383 remote site requires basic or digest authentication, the user will
383 remote site requires basic or digest authentication, the user will
384 be prompted for it. Environment variables are expanded in the
384 be prompted for it. Environment variables are expanded in the
385 username letting you do ``foo.username = $USER``. If the URI
385 username letting you do ``foo.username = $USER``. If the URI
386 includes a username, only ``[auth]`` entries with a matching
386 includes a username, only ``[auth]`` entries with a matching
387 username or without a username will be considered.
387 username or without a username will be considered.
388
388
389 ``password``
389 ``password``
390 Optional. Password to authenticate with. If not given, and the
390 Optional. Password to authenticate with. If not given, and the
391 remote site requires basic or digest authentication, the user
391 remote site requires basic or digest authentication, the user
392 will be prompted for it.
392 will be prompted for it.
393
393
394 ``key``
394 ``key``
395 Optional. PEM encoded client certificate key file. Environment
395 Optional. PEM encoded client certificate key file. Environment
396 variables are expanded in the filename.
396 variables are expanded in the filename.
397
397
398 ``cert``
398 ``cert``
399 Optional. PEM encoded client certificate chain file. Environment
399 Optional. PEM encoded client certificate chain file. Environment
400 variables are expanded in the filename.
400 variables are expanded in the filename.
401
401
402 ``schemes``
402 ``schemes``
403 Optional. Space separated list of URI schemes to use this
403 Optional. Space separated list of URI schemes to use this
404 authentication entry with. Only used if the prefix doesn't include
404 authentication entry with. Only used if the prefix doesn't include
405 a scheme. Supported schemes are http and https. They will match
405 a scheme. Supported schemes are http and https. They will match
406 static-http and static-https respectively, as well.
406 static-http and static-https respectively, as well.
407 (default: https)
407 (default: https)
408
408
409 If no suitable authentication entry is found, the user is prompted
409 If no suitable authentication entry is found, the user is prompted
410 for credentials as usual if required by the remote.
410 for credentials as usual if required by the remote.
411
411
412 ``color``
412 ``color``
413 ---------
413 ---------
414
414
415 Configure the Mercurial color mode. For details about how to define your custom
415 Configure the Mercurial color mode. For details about how to define your custom
416 effect and style see :hg:`help color`.
416 effect and style see :hg:`help color`.
417
417
418 ``mode``
418 ``mode``
419 String: control the method used to output color. One of ``auto``, ``ansi``,
419 String: control the method used to output color. One of ``auto``, ``ansi``,
420 ``win32``, ``terminfo`` or ``debug``. In auto mode, Mercurial will
420 ``win32``, ``terminfo`` or ``debug``. In auto mode, Mercurial will
421 use ANSI mode by default (or win32 mode prior to Windows 10) if it detects a
421 use ANSI mode by default (or win32 mode prior to Windows 10) if it detects a
422 terminal. Any invalid value will disable color.
422 terminal. Any invalid value will disable color.
423
423
424 ``pagermode``
424 ``pagermode``
425 String: optional override of ``color.mode`` used with pager.
425 String: optional override of ``color.mode`` used with pager.
426
426
427 On some systems, terminfo mode may cause problems when using
427 On some systems, terminfo mode may cause problems when using
428 color with ``less -R`` as a pager program. less with the -R option
428 color with ``less -R`` as a pager program. less with the -R option
429 will only display ECMA-48 color codes, and terminfo mode may sometimes
429 will only display ECMA-48 color codes, and terminfo mode may sometimes
430 emit codes that less doesn't understand. You can work around this by
430 emit codes that less doesn't understand. You can work around this by
431 either using ansi mode (or auto mode), or by using less -r (which will
431 either using ansi mode (or auto mode), or by using less -r (which will
432 pass through all terminal control codes, not just color control
432 pass through all terminal control codes, not just color control
433 codes).
433 codes).
434
434
435 On some systems (such as MSYS in Windows), the terminal may support
435 On some systems (such as MSYS in Windows), the terminal may support
436 a different color mode than the pager program.
436 a different color mode than the pager program.
437
437
438 ``commands``
438 ``commands``
439 ------------
439 ------------
440
440
441 ``status.relative``
441 ``status.relative``
442 Make paths in :hg:`status` output relative to the current directory.
442 Make paths in :hg:`status` output relative to the current directory.
443 (default: False)
443 (default: False)
444
444
445 ``update.check``
445 ``update.check``
446 Determines what level of checking :hg:`update` will perform before moving
446 Determines what level of checking :hg:`update` will perform before moving
447 to a destination revision. Valid values are ``abort``, ``none``,
447 to a destination revision. Valid values are ``abort``, ``none``,
448 ``linear``, and ``noconflict``. ``abort`` always fails if the working
448 ``linear``, and ``noconflict``. ``abort`` always fails if the working
449 directory has uncommitted changes. ``none`` performs no checking, and may
449 directory has uncommitted changes. ``none`` performs no checking, and may
450 result in a merge with uncommitted changes. ``linear`` allows any update
450 result in a merge with uncommitted changes. ``linear`` allows any update
451 as long as it follows a straight line in the revision history, and may
451 as long as it follows a straight line in the revision history, and may
452 trigger a merge with uncommitted changes. ``noconflict`` will allow any
452 trigger a merge with uncommitted changes. ``noconflict`` will allow any
453 update which would not trigger a merge with uncommitted changes, if any
453 update which would not trigger a merge with uncommitted changes, if any
454 are present.
454 are present.
455 (default: ``linear``)
455 (default: ``linear``)
456
456
457 ``update.requiredest``
457 ``update.requiredest``
458 Require that the user pass a destination when running :hg:`update`.
458 Require that the user pass a destination when running :hg:`update`.
459 For example, :hg:`update .::` will be allowed, but a plain :hg:`update`
459 For example, :hg:`update .::` will be allowed, but a plain :hg:`update`
460 will be disallowed.
460 will be disallowed.
461 (default: False)
461 (default: False)
462
462
463 ``committemplate``
463 ``committemplate``
464 ------------------
464 ------------------
465
465
466 ``changeset``
466 ``changeset``
467 String: configuration in this section is used as the template to
467 String: configuration in this section is used as the template to
468 customize the text shown in the editor when committing.
468 customize the text shown in the editor when committing.
469
469
470 In addition to pre-defined template keywords, commit log specific one
470 In addition to pre-defined template keywords, commit log specific one
471 below can be used for customization:
471 below can be used for customization:
472
472
473 ``extramsg``
473 ``extramsg``
474 String: Extra message (typically 'Leave message empty to abort
474 String: Extra message (typically 'Leave message empty to abort
475 commit.'). This may be changed by some commands or extensions.
475 commit.'). This may be changed by some commands or extensions.
476
476
477 For example, the template configuration below shows as same text as
477 For example, the template configuration below shows as same text as
478 one shown by default::
478 one shown by default::
479
479
480 [committemplate]
480 [committemplate]
481 changeset = {desc}\n\n
481 changeset = {desc}\n\n
482 HG: Enter commit message. Lines beginning with 'HG:' are removed.
482 HG: Enter commit message. Lines beginning with 'HG:' are removed.
483 HG: {extramsg}
483 HG: {extramsg}
484 HG: --
484 HG: --
485 HG: user: {author}\n{ifeq(p2rev, "-1", "",
485 HG: user: {author}\n{ifeq(p2rev, "-1", "",
486 "HG: branch merge\n")
486 "HG: branch merge\n")
487 }HG: branch '{branch}'\n{if(activebookmark,
487 }HG: branch '{branch}'\n{if(activebookmark,
488 "HG: bookmark '{activebookmark}'\n") }{subrepos %
488 "HG: bookmark '{activebookmark}'\n") }{subrepos %
489 "HG: subrepo {subrepo}\n" }{file_adds %
489 "HG: subrepo {subrepo}\n" }{file_adds %
490 "HG: added {file}\n" }{file_mods %
490 "HG: added {file}\n" }{file_mods %
491 "HG: changed {file}\n" }{file_dels %
491 "HG: changed {file}\n" }{file_dels %
492 "HG: removed {file}\n" }{if(files, "",
492 "HG: removed {file}\n" }{if(files, "",
493 "HG: no files changed\n")}
493 "HG: no files changed\n")}
494
494
495 ``diff()``
495 ``diff()``
496 String: show the diff (see :hg:`help templates` for detail)
496 String: show the diff (see :hg:`help templates` for detail)
497
497
498 Sometimes it is helpful to show the diff of the changeset in the editor without
498 Sometimes it is helpful to show the diff of the changeset in the editor without
499 having to prefix 'HG: ' to each line so that highlighting works correctly. For
499 having to prefix 'HG: ' to each line so that highlighting works correctly. For
500 this, Mercurial provides a special string which will ignore everything below
500 this, Mercurial provides a special string which will ignore everything below
501 it::
501 it::
502
502
503 HG: ------------------------ >8 ------------------------
503 HG: ------------------------ >8 ------------------------
504
504
505 For example, the template configuration below will show the diff below the
505 For example, the template configuration below will show the diff below the
506 extra message::
506 extra message::
507
507
508 [committemplate]
508 [committemplate]
509 changeset = {desc}\n\n
509 changeset = {desc}\n\n
510 HG: Enter commit message. Lines beginning with 'HG:' are removed.
510 HG: Enter commit message. Lines beginning with 'HG:' are removed.
511 HG: {extramsg}
511 HG: {extramsg}
512 HG: ------------------------ >8 ------------------------
512 HG: ------------------------ >8 ------------------------
513 HG: Do not touch the line above.
513 HG: Do not touch the line above.
514 HG: Everything below will be removed.
514 HG: Everything below will be removed.
515 {diff()}
515 {diff()}
516
516
517 .. note::
517 .. note::
518
518
519 For some problematic encodings (see :hg:`help win32mbcs` for
519 For some problematic encodings (see :hg:`help win32mbcs` for
520 detail), this customization should be configured carefully, to
520 detail), this customization should be configured carefully, to
521 avoid showing broken characters.
521 avoid showing broken characters.
522
522
523 For example, if a multibyte character ending with backslash (0x5c) is
523 For example, if a multibyte character ending with backslash (0x5c) is
524 followed by the ASCII character 'n' in the customized template,
524 followed by the ASCII character 'n' in the customized template,
525 the sequence of backslash and 'n' is treated as line-feed unexpectedly
525 the sequence of backslash and 'n' is treated as line-feed unexpectedly
526 (and the multibyte character is broken, too).
526 (and the multibyte character is broken, too).
527
527
528 Customized template is used for commands below (``--edit`` may be
528 Customized template is used for commands below (``--edit`` may be
529 required):
529 required):
530
530
531 - :hg:`backout`
531 - :hg:`backout`
532 - :hg:`commit`
532 - :hg:`commit`
533 - :hg:`fetch` (for merge commit only)
533 - :hg:`fetch` (for merge commit only)
534 - :hg:`graft`
534 - :hg:`graft`
535 - :hg:`histedit`
535 - :hg:`histedit`
536 - :hg:`import`
536 - :hg:`import`
537 - :hg:`qfold`, :hg:`qnew` and :hg:`qrefresh`
537 - :hg:`qfold`, :hg:`qnew` and :hg:`qrefresh`
538 - :hg:`rebase`
538 - :hg:`rebase`
539 - :hg:`shelve`
539 - :hg:`shelve`
540 - :hg:`sign`
540 - :hg:`sign`
541 - :hg:`tag`
541 - :hg:`tag`
542 - :hg:`transplant`
542 - :hg:`transplant`
543
543
544 Configuring items below instead of ``changeset`` allows showing
544 Configuring items below instead of ``changeset`` allows showing
545 customized message only for specific actions, or showing different
545 customized message only for specific actions, or showing different
546 messages for each action.
546 messages for each action.
547
547
548 - ``changeset.backout`` for :hg:`backout`
548 - ``changeset.backout`` for :hg:`backout`
549 - ``changeset.commit.amend.merge`` for :hg:`commit --amend` on merges
549 - ``changeset.commit.amend.merge`` for :hg:`commit --amend` on merges
550 - ``changeset.commit.amend.normal`` for :hg:`commit --amend` on other
550 - ``changeset.commit.amend.normal`` for :hg:`commit --amend` on other
551 - ``changeset.commit.normal.merge`` for :hg:`commit` on merges
551 - ``changeset.commit.normal.merge`` for :hg:`commit` on merges
552 - ``changeset.commit.normal.normal`` for :hg:`commit` on other
552 - ``changeset.commit.normal.normal`` for :hg:`commit` on other
553 - ``changeset.fetch`` for :hg:`fetch` (impling merge commit)
553 - ``changeset.fetch`` for :hg:`fetch` (impling merge commit)
554 - ``changeset.gpg.sign`` for :hg:`sign`
554 - ``changeset.gpg.sign`` for :hg:`sign`
555 - ``changeset.graft`` for :hg:`graft`
555 - ``changeset.graft`` for :hg:`graft`
556 - ``changeset.histedit.edit`` for ``edit`` of :hg:`histedit`
556 - ``changeset.histedit.edit`` for ``edit`` of :hg:`histedit`
557 - ``changeset.histedit.fold`` for ``fold`` of :hg:`histedit`
557 - ``changeset.histedit.fold`` for ``fold`` of :hg:`histedit`
558 - ``changeset.histedit.mess`` for ``mess`` of :hg:`histedit`
558 - ``changeset.histedit.mess`` for ``mess`` of :hg:`histedit`
559 - ``changeset.histedit.pick`` for ``pick`` of :hg:`histedit`
559 - ``changeset.histedit.pick`` for ``pick`` of :hg:`histedit`
560 - ``changeset.import.bypass`` for :hg:`import --bypass`
560 - ``changeset.import.bypass`` for :hg:`import --bypass`
561 - ``changeset.import.normal.merge`` for :hg:`import` on merges
561 - ``changeset.import.normal.merge`` for :hg:`import` on merges
562 - ``changeset.import.normal.normal`` for :hg:`import` on other
562 - ``changeset.import.normal.normal`` for :hg:`import` on other
563 - ``changeset.mq.qnew`` for :hg:`qnew`
563 - ``changeset.mq.qnew`` for :hg:`qnew`
564 - ``changeset.mq.qfold`` for :hg:`qfold`
564 - ``changeset.mq.qfold`` for :hg:`qfold`
565 - ``changeset.mq.qrefresh`` for :hg:`qrefresh`
565 - ``changeset.mq.qrefresh`` for :hg:`qrefresh`
566 - ``changeset.rebase.collapse`` for :hg:`rebase --collapse`
566 - ``changeset.rebase.collapse`` for :hg:`rebase --collapse`
567 - ``changeset.rebase.merge`` for :hg:`rebase` on merges
567 - ``changeset.rebase.merge`` for :hg:`rebase` on merges
568 - ``changeset.rebase.normal`` for :hg:`rebase` on other
568 - ``changeset.rebase.normal`` for :hg:`rebase` on other
569 - ``changeset.shelve.shelve`` for :hg:`shelve`
569 - ``changeset.shelve.shelve`` for :hg:`shelve`
570 - ``changeset.tag.add`` for :hg:`tag` without ``--remove``
570 - ``changeset.tag.add`` for :hg:`tag` without ``--remove``
571 - ``changeset.tag.remove`` for :hg:`tag --remove`
571 - ``changeset.tag.remove`` for :hg:`tag --remove`
572 - ``changeset.transplant.merge`` for :hg:`transplant` on merges
572 - ``changeset.transplant.merge`` for :hg:`transplant` on merges
573 - ``changeset.transplant.normal`` for :hg:`transplant` on other
573 - ``changeset.transplant.normal`` for :hg:`transplant` on other
574
574
575 These dot-separated lists of names are treated as hierarchical ones.
575 These dot-separated lists of names are treated as hierarchical ones.
576 For example, ``changeset.tag.remove`` customizes the commit message
576 For example, ``changeset.tag.remove`` customizes the commit message
577 only for :hg:`tag --remove`, but ``changeset.tag`` customizes the
577 only for :hg:`tag --remove`, but ``changeset.tag`` customizes the
578 commit message for :hg:`tag` regardless of ``--remove`` option.
578 commit message for :hg:`tag` regardless of ``--remove`` option.
579
579
580 When the external editor is invoked for a commit, the corresponding
580 When the external editor is invoked for a commit, the corresponding
581 dot-separated list of names without the ``changeset.`` prefix
581 dot-separated list of names without the ``changeset.`` prefix
582 (e.g. ``commit.normal.normal``) is in the ``HGEDITFORM`` environment
582 (e.g. ``commit.normal.normal``) is in the ``HGEDITFORM`` environment
583 variable.
583 variable.
584
584
585 In this section, items other than ``changeset`` can be referred from
585 In this section, items other than ``changeset`` can be referred from
586 others. For example, the configuration to list committed files up
586 others. For example, the configuration to list committed files up
587 below can be referred as ``{listupfiles}``::
587 below can be referred as ``{listupfiles}``::
588
588
589 [committemplate]
589 [committemplate]
590 listupfiles = {file_adds %
590 listupfiles = {file_adds %
591 "HG: added {file}\n" }{file_mods %
591 "HG: added {file}\n" }{file_mods %
592 "HG: changed {file}\n" }{file_dels %
592 "HG: changed {file}\n" }{file_dels %
593 "HG: removed {file}\n" }{if(files, "",
593 "HG: removed {file}\n" }{if(files, "",
594 "HG: no files changed\n")}
594 "HG: no files changed\n")}
595
595
596 ``decode/encode``
596 ``decode/encode``
597 -----------------
597 -----------------
598
598
599 Filters for transforming files on checkout/checkin. This would
599 Filters for transforming files on checkout/checkin. This would
600 typically be used for newline processing or other
600 typically be used for newline processing or other
601 localization/canonicalization of files.
601 localization/canonicalization of files.
602
602
603 Filters consist of a filter pattern followed by a filter command.
603 Filters consist of a filter pattern followed by a filter command.
604 Filter patterns are globs by default, rooted at the repository root.
604 Filter patterns are globs by default, rooted at the repository root.
605 For example, to match any file ending in ``.txt`` in the root
605 For example, to match any file ending in ``.txt`` in the root
606 directory only, use the pattern ``*.txt``. To match any file ending
606 directory only, use the pattern ``*.txt``. To match any file ending
607 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
607 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
608 For each file only the first matching filter applies.
608 For each file only the first matching filter applies.
609
609
610 The filter command can start with a specifier, either ``pipe:`` or
610 The filter command can start with a specifier, either ``pipe:`` or
611 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
611 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
612
612
613 A ``pipe:`` command must accept data on stdin and return the transformed
613 A ``pipe:`` command must accept data on stdin and return the transformed
614 data on stdout.
614 data on stdout.
615
615
616 Pipe example::
616 Pipe example::
617
617
618 [encode]
618 [encode]
619 # uncompress gzip files on checkin to improve delta compression
619 # uncompress gzip files on checkin to improve delta compression
620 # note: not necessarily a good idea, just an example
620 # note: not necessarily a good idea, just an example
621 *.gz = pipe: gunzip
621 *.gz = pipe: gunzip
622
622
623 [decode]
623 [decode]
624 # recompress gzip files when writing them to the working dir (we
624 # recompress gzip files when writing them to the working dir (we
625 # can safely omit "pipe:", because it's the default)
625 # can safely omit "pipe:", because it's the default)
626 *.gz = gzip
626 *.gz = gzip
627
627
628 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
628 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
629 with the name of a temporary file that contains the data to be
629 with the name of a temporary file that contains the data to be
630 filtered by the command. The string ``OUTFILE`` is replaced with the name
630 filtered by the command. The string ``OUTFILE`` is replaced with the name
631 of an empty temporary file, where the filtered data must be written by
631 of an empty temporary file, where the filtered data must be written by
632 the command.
632 the command.
633
633
634 .. container:: windows
634 .. container:: windows
635
635
636 .. note::
636 .. note::
637
637
638 The tempfile mechanism is recommended for Windows systems,
638 The tempfile mechanism is recommended for Windows systems,
639 where the standard shell I/O redirection operators often have
639 where the standard shell I/O redirection operators often have
640 strange effects and may corrupt the contents of your files.
640 strange effects and may corrupt the contents of your files.
641
641
642 This filter mechanism is used internally by the ``eol`` extension to
642 This filter mechanism is used internally by the ``eol`` extension to
643 translate line ending characters between Windows (CRLF) and Unix (LF)
643 translate line ending characters between Windows (CRLF) and Unix (LF)
644 format. We suggest you use the ``eol`` extension for convenience.
644 format. We suggest you use the ``eol`` extension for convenience.
645
645
646
646
647 ``defaults``
647 ``defaults``
648 ------------
648 ------------
649
649
650 (defaults are deprecated. Don't use them. Use aliases instead.)
650 (defaults are deprecated. Don't use them. Use aliases instead.)
651
651
652 Use the ``[defaults]`` section to define command defaults, i.e. the
652 Use the ``[defaults]`` section to define command defaults, i.e. the
653 default options/arguments to pass to the specified commands.
653 default options/arguments to pass to the specified commands.
654
654
655 The following example makes :hg:`log` run in verbose mode, and
655 The following example makes :hg:`log` run in verbose mode, and
656 :hg:`status` show only the modified files, by default::
656 :hg:`status` show only the modified files, by default::
657
657
658 [defaults]
658 [defaults]
659 log = -v
659 log = -v
660 status = -m
660 status = -m
661
661
662 The actual commands, instead of their aliases, must be used when
662 The actual commands, instead of their aliases, must be used when
663 defining command defaults. The command defaults will also be applied
663 defining command defaults. The command defaults will also be applied
664 to the aliases of the commands defined.
664 to the aliases of the commands defined.
665
665
666
666
667 ``diff``
667 ``diff``
668 --------
668 --------
669
669
670 Settings used when displaying diffs. Everything except for ``unified``
670 Settings used when displaying diffs. Everything except for ``unified``
671 is a Boolean and defaults to False. See :hg:`help config.annotate`
671 is a Boolean and defaults to False. See :hg:`help config.annotate`
672 for related options for the annotate command.
672 for related options for the annotate command.
673
673
674 ``git``
674 ``git``
675 Use git extended diff format.
675 Use git extended diff format.
676
676
677 ``nobinary``
677 ``nobinary``
678 Omit git binary patches.
678 Omit git binary patches.
679
679
680 ``nodates``
680 ``nodates``
681 Don't include dates in diff headers.
681 Don't include dates in diff headers.
682
682
683 ``noprefix``
683 ``noprefix``
684 Omit 'a/' and 'b/' prefixes from filenames. Ignored in plain mode.
684 Omit 'a/' and 'b/' prefixes from filenames. Ignored in plain mode.
685
685
686 ``showfunc``
686 ``showfunc``
687 Show which function each change is in.
687 Show which function each change is in.
688
688
689 ``ignorews``
689 ``ignorews``
690 Ignore white space when comparing lines.
690 Ignore white space when comparing lines.
691
691
692 ``ignorewsamount``
692 ``ignorewsamount``
693 Ignore changes in the amount of white space.
693 Ignore changes in the amount of white space.
694
694
695 ``ignoreblanklines``
695 ``ignoreblanklines``
696 Ignore changes whose lines are all blank.
696 Ignore changes whose lines are all blank.
697
697
698 ``unified``
698 ``unified``
699 Number of lines of context to show.
699 Number of lines of context to show.
700
700
701 ``email``
701 ``email``
702 ---------
702 ---------
703
703
704 Settings for extensions that send email messages.
704 Settings for extensions that send email messages.
705
705
706 ``from``
706 ``from``
707 Optional. Email address to use in "From" header and SMTP envelope
707 Optional. Email address to use in "From" header and SMTP envelope
708 of outgoing messages.
708 of outgoing messages.
709
709
710 ``to``
710 ``to``
711 Optional. Comma-separated list of recipients' email addresses.
711 Optional. Comma-separated list of recipients' email addresses.
712
712
713 ``cc``
713 ``cc``
714 Optional. Comma-separated list of carbon copy recipients'
714 Optional. Comma-separated list of carbon copy recipients'
715 email addresses.
715 email addresses.
716
716
717 ``bcc``
717 ``bcc``
718 Optional. Comma-separated list of blind carbon copy recipients'
718 Optional. Comma-separated list of blind carbon copy recipients'
719 email addresses.
719 email addresses.
720
720
721 ``method``
721 ``method``
722 Optional. Method to use to send email messages. If value is ``smtp``
722 Optional. Method to use to send email messages. If value is ``smtp``
723 (default), use SMTP (see the ``[smtp]`` section for configuration).
723 (default), use SMTP (see the ``[smtp]`` section for configuration).
724 Otherwise, use as name of program to run that acts like sendmail
724 Otherwise, use as name of program to run that acts like sendmail
725 (takes ``-f`` option for sender, list of recipients on command line,
725 (takes ``-f`` option for sender, list of recipients on command line,
726 message on stdin). Normally, setting this to ``sendmail`` or
726 message on stdin). Normally, setting this to ``sendmail`` or
727 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
727 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
728
728
729 ``charsets``
729 ``charsets``
730 Optional. Comma-separated list of character sets considered
730 Optional. Comma-separated list of character sets considered
731 convenient for recipients. Addresses, headers, and parts not
731 convenient for recipients. Addresses, headers, and parts not
732 containing patches of outgoing messages will be encoded in the
732 containing patches of outgoing messages will be encoded in the
733 first character set to which conversion from local encoding
733 first character set to which conversion from local encoding
734 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
734 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
735 conversion fails, the text in question is sent as is.
735 conversion fails, the text in question is sent as is.
736 (default: '')
736 (default: '')
737
737
738 Order of outgoing email character sets:
738 Order of outgoing email character sets:
739
739
740 1. ``us-ascii``: always first, regardless of settings
740 1. ``us-ascii``: always first, regardless of settings
741 2. ``email.charsets``: in order given by user
741 2. ``email.charsets``: in order given by user
742 3. ``ui.fallbackencoding``: if not in email.charsets
742 3. ``ui.fallbackencoding``: if not in email.charsets
743 4. ``$HGENCODING``: if not in email.charsets
743 4. ``$HGENCODING``: if not in email.charsets
744 5. ``utf-8``: always last, regardless of settings
744 5. ``utf-8``: always last, regardless of settings
745
745
746 Email example::
746 Email example::
747
747
748 [email]
748 [email]
749 from = Joseph User <joe.user@example.com>
749 from = Joseph User <joe.user@example.com>
750 method = /usr/sbin/sendmail
750 method = /usr/sbin/sendmail
751 # charsets for western Europeans
751 # charsets for western Europeans
752 # us-ascii, utf-8 omitted, as they are tried first and last
752 # us-ascii, utf-8 omitted, as they are tried first and last
753 charsets = iso-8859-1, iso-8859-15, windows-1252
753 charsets = iso-8859-1, iso-8859-15, windows-1252
754
754
755
755
756 ``extensions``
756 ``extensions``
757 --------------
757 --------------
758
758
759 Mercurial has an extension mechanism for adding new features. To
759 Mercurial has an extension mechanism for adding new features. To
760 enable an extension, create an entry for it in this section.
760 enable an extension, create an entry for it in this section.
761
761
762 If you know that the extension is already in Python's search path,
762 If you know that the extension is already in Python's search path,
763 you can give the name of the module, followed by ``=``, with nothing
763 you can give the name of the module, followed by ``=``, with nothing
764 after the ``=``.
764 after the ``=``.
765
765
766 Otherwise, give a name that you choose, followed by ``=``, followed by
766 Otherwise, give a name that you choose, followed by ``=``, followed by
767 the path to the ``.py`` file (including the file name extension) that
767 the path to the ``.py`` file (including the file name extension) that
768 defines the extension.
768 defines the extension.
769
769
770 To explicitly disable an extension that is enabled in an hgrc of
770 To explicitly disable an extension that is enabled in an hgrc of
771 broader scope, prepend its path with ``!``, as in ``foo = !/ext/path``
771 broader scope, prepend its path with ``!``, as in ``foo = !/ext/path``
772 or ``foo = !`` when path is not supplied.
772 or ``foo = !`` when path is not supplied.
773
773
774 Example for ``~/.hgrc``::
774 Example for ``~/.hgrc``::
775
775
776 [extensions]
776 [extensions]
777 # (the churn extension will get loaded from Mercurial's path)
777 # (the churn extension will get loaded from Mercurial's path)
778 churn =
778 churn =
779 # (this extension will get loaded from the file specified)
779 # (this extension will get loaded from the file specified)
780 myfeature = ~/.hgext/myfeature.py
780 myfeature = ~/.hgext/myfeature.py
781
781
782
782
783 ``format``
783 ``format``
784 ----------
784 ----------
785
785
786 ``usegeneraldelta``
786 ``usegeneraldelta``
787 Enable or disable the "generaldelta" repository format which improves
787 Enable or disable the "generaldelta" repository format which improves
788 repository compression by allowing "revlog" to store delta against arbitrary
788 repository compression by allowing "revlog" to store delta against arbitrary
789 revision instead of the previous stored one. This provides significant
789 revision instead of the previous stored one. This provides significant
790 improvement for repositories with branches.
790 improvement for repositories with branches.
791
791
792 Repositories with this on-disk format require Mercurial version 1.9.
792 Repositories with this on-disk format require Mercurial version 1.9.
793
793
794 Enabled by default.
794 Enabled by default.
795
795
796 ``dotencode``
796 ``dotencode``
797 Enable or disable the "dotencode" repository format which enhances
797 Enable or disable the "dotencode" repository format which enhances
798 the "fncache" repository format (which has to be enabled to use
798 the "fncache" repository format (which has to be enabled to use
799 dotencode) to avoid issues with filenames starting with ._ on
799 dotencode) to avoid issues with filenames starting with ._ on
800 Mac OS X and spaces on Windows.
800 Mac OS X and spaces on Windows.
801
801
802 Repositories with this on-disk format require Mercurial version 1.7.
802 Repositories with this on-disk format require Mercurial version 1.7.
803
803
804 Enabled by default.
804 Enabled by default.
805
805
806 ``usefncache``
806 ``usefncache``
807 Enable or disable the "fncache" repository format which enhances
807 Enable or disable the "fncache" repository format which enhances
808 the "store" repository format (which has to be enabled to use
808 the "store" repository format (which has to be enabled to use
809 fncache) to allow longer filenames and avoids using Windows
809 fncache) to allow longer filenames and avoids using Windows
810 reserved names, e.g. "nul".
810 reserved names, e.g. "nul".
811
811
812 Repositories with this on-disk format require Mercurial version 1.1.
812 Repositories with this on-disk format require Mercurial version 1.1.
813
813
814 Enabled by default.
814 Enabled by default.
815
815
816 ``usestore``
816 ``usestore``
817 Enable or disable the "store" repository format which improves
817 Enable or disable the "store" repository format which improves
818 compatibility with systems that fold case or otherwise mangle
818 compatibility with systems that fold case or otherwise mangle
819 filenames. Disabling this option will allow you to store longer filenames
819 filenames. Disabling this option will allow you to store longer filenames
820 in some situations at the expense of compatibility.
820 in some situations at the expense of compatibility.
821
821
822 Repositories with this on-disk format require Mercurial version 0.9.4.
822 Repositories with this on-disk format require Mercurial version 0.9.4.
823
823
824 Enabled by default.
824 Enabled by default.
825
825
826 ``graph``
826 ``graph``
827 ---------
827 ---------
828
828
829 Web graph view configuration. This section let you change graph
829 Web graph view configuration. This section let you change graph
830 elements display properties by branches, for instance to make the
830 elements display properties by branches, for instance to make the
831 ``default`` branch stand out.
831 ``default`` branch stand out.
832
832
833 Each line has the following format::
833 Each line has the following format::
834
834
835 <branch>.<argument> = <value>
835 <branch>.<argument> = <value>
836
836
837 where ``<branch>`` is the name of the branch being
837 where ``<branch>`` is the name of the branch being
838 customized. Example::
838 customized. Example::
839
839
840 [graph]
840 [graph]
841 # 2px width
841 # 2px width
842 default.width = 2
842 default.width = 2
843 # red color
843 # red color
844 default.color = FF0000
844 default.color = FF0000
845
845
846 Supported arguments:
846 Supported arguments:
847
847
848 ``width``
848 ``width``
849 Set branch edges width in pixels.
849 Set branch edges width in pixels.
850
850
851 ``color``
851 ``color``
852 Set branch edges color in hexadecimal RGB notation.
852 Set branch edges color in hexadecimal RGB notation.
853
853
854 ``hooks``
854 ``hooks``
855 ---------
855 ---------
856
856
857 Commands or Python functions that get automatically executed by
857 Commands or Python functions that get automatically executed by
858 various actions such as starting or finishing a commit. Multiple
858 various actions such as starting or finishing a commit. Multiple
859 hooks can be run for the same action by appending a suffix to the
859 hooks can be run for the same action by appending a suffix to the
860 action. Overriding a site-wide hook can be done by changing its
860 action. Overriding a site-wide hook can be done by changing its
861 value or setting it to an empty string. Hooks can be prioritized
861 value or setting it to an empty string. Hooks can be prioritized
862 by adding a prefix of ``priority.`` to the hook name on a new line
862 by adding a prefix of ``priority.`` to the hook name on a new line
863 and setting the priority. The default priority is 0.
863 and setting the priority. The default priority is 0.
864
864
865 Example ``.hg/hgrc``::
865 Example ``.hg/hgrc``::
866
866
867 [hooks]
867 [hooks]
868 # update working directory after adding changesets
868 # update working directory after adding changesets
869 changegroup.update = hg update
869 changegroup.update = hg update
870 # do not use the site-wide hook
870 # do not use the site-wide hook
871 incoming =
871 incoming =
872 incoming.email = /my/email/hook
872 incoming.email = /my/email/hook
873 incoming.autobuild = /my/build/hook
873 incoming.autobuild = /my/build/hook
874 # force autobuild hook to run before other incoming hooks
874 # force autobuild hook to run before other incoming hooks
875 priority.incoming.autobuild = 1
875 priority.incoming.autobuild = 1
876
876
877 Most hooks are run with environment variables set that give useful
877 Most hooks are run with environment variables set that give useful
878 additional information. For each hook below, the environment variables
878 additional information. For each hook below, the environment variables
879 it is passed are listed with names in the form ``$HG_foo``. The
879 it is passed are listed with names in the form ``$HG_foo``. The
880 ``$HG_HOOKTYPE`` and ``$HG_HOOKNAME`` variables are set for all hooks.
880 ``$HG_HOOKTYPE`` and ``$HG_HOOKNAME`` variables are set for all hooks.
881 They contain the type of hook which triggered the run and the full name
881 They contain the type of hook which triggered the run and the full name
882 of the hook in the config, respectively. In the example above, this will
882 of the hook in the config, respectively. In the example above, this will
883 be ``$HG_HOOKTYPE=incoming`` and ``$HG_HOOKNAME=incoming.email``.
883 be ``$HG_HOOKTYPE=incoming`` and ``$HG_HOOKNAME=incoming.email``.
884
884
885 ``changegroup``
885 ``changegroup``
886 Run after a changegroup has been added via push, pull or unbundle. The ID of
886 Run after a changegroup has been added via push, pull or unbundle. The ID of
887 the first new changeset is in ``$HG_NODE`` and last is in ``$HG_NODE_LAST``.
887 the first new changeset is in ``$HG_NODE`` and last is in ``$HG_NODE_LAST``.
888 The URL from which changes came is in ``$HG_URL``.
888 The URL from which changes came is in ``$HG_URL``.
889
889
890 ``commit``
890 ``commit``
891 Run after a changeset has been created in the local repository. The ID
891 Run after a changeset has been created in the local repository. The ID
892 of the newly created changeset is in ``$HG_NODE``. Parent changeset
892 of the newly created changeset is in ``$HG_NODE``. Parent changeset
893 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
893 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
894
894
895 ``incoming``
895 ``incoming``
896 Run after a changeset has been pulled, pushed, or unbundled into
896 Run after a changeset has been pulled, pushed, or unbundled into
897 the local repository. The ID of the newly arrived changeset is in
897 the local repository. The ID of the newly arrived changeset is in
898 ``$HG_NODE``. The URL that was source of the changes is in ``$HG_URL``.
898 ``$HG_NODE``. The URL that was source of the changes is in ``$HG_URL``.
899
899
900 ``outgoing``
900 ``outgoing``
901 Run after sending changes from the local repository to another. The ID of
901 Run after sending changes from the local repository to another. The ID of
902 first changeset sent is in ``$HG_NODE``. The source of operation is in
902 first changeset sent is in ``$HG_NODE``. The source of operation is in
903 ``$HG_SOURCE``. Also see :hg:`help config.hooks.preoutgoing`.
903 ``$HG_SOURCE``. Also see :hg:`help config.hooks.preoutgoing`.
904
904
905 ``post-<command>``
905 ``post-<command>``
906 Run after successful invocations of the associated command. The
906 Run after successful invocations of the associated command. The
907 contents of the command line are passed as ``$HG_ARGS`` and the result
907 contents of the command line are passed as ``$HG_ARGS`` and the result
908 code in ``$HG_RESULT``. Parsed command line arguments are passed as
908 code in ``$HG_RESULT``. Parsed command line arguments are passed as
909 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
909 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
910 the python data internally passed to <command>. ``$HG_OPTS`` is a
910 the python data internally passed to <command>. ``$HG_OPTS`` is a
911 dictionary of options (with unspecified options set to their defaults).
911 dictionary of options (with unspecified options set to their defaults).
912 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
912 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
913
913
914 ``fail-<command>``
914 ``fail-<command>``
915 Run after a failed invocation of an associated command. The contents
915 Run after a failed invocation of an associated command. The contents
916 of the command line are passed as ``$HG_ARGS``. Parsed command line
916 of the command line are passed as ``$HG_ARGS``. Parsed command line
917 arguments are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain
917 arguments are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain
918 string representations of the python data internally passed to
918 string representations of the python data internally passed to
919 <command>. ``$HG_OPTS`` is a dictionary of options (with unspecified
919 <command>. ``$HG_OPTS`` is a dictionary of options (with unspecified
920 options set to their defaults). ``$HG_PATS`` is a list of arguments.
920 options set to their defaults). ``$HG_PATS`` is a list of arguments.
921 Hook failure is ignored.
921 Hook failure is ignored.
922
922
923 ``pre-<command>``
923 ``pre-<command>``
924 Run before executing the associated command. The contents of the
924 Run before executing the associated command. The contents of the
925 command line are passed as ``$HG_ARGS``. Parsed command line arguments
925 command line are passed as ``$HG_ARGS``. Parsed command line arguments
926 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
926 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
927 representations of the data internally passed to <command>. ``$HG_OPTS``
927 representations of the data internally passed to <command>. ``$HG_OPTS``
928 is a dictionary of options (with unspecified options set to their
928 is a dictionary of options (with unspecified options set to their
929 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
929 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
930 failure, the command doesn't execute and Mercurial returns the failure
930 failure, the command doesn't execute and Mercurial returns the failure
931 code.
931 code.
932
932
933 ``prechangegroup``
933 ``prechangegroup``
934 Run before a changegroup is added via push, pull or unbundle. Exit
934 Run before a changegroup is added via push, pull or unbundle. Exit
935 status 0 allows the changegroup to proceed. A non-zero status will
935 status 0 allows the changegroup to proceed. A non-zero status will
936 cause the push, pull or unbundle to fail. The URL from which changes
936 cause the push, pull or unbundle to fail. The URL from which changes
937 will come is in ``$HG_URL``.
937 will come is in ``$HG_URL``.
938
938
939 ``precommit``
939 ``precommit``
940 Run before starting a local commit. Exit status 0 allows the
940 Run before starting a local commit. Exit status 0 allows the
941 commit to proceed. A non-zero status will cause the commit to fail.
941 commit to proceed. A non-zero status will cause the commit to fail.
942 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
942 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
943
943
944 ``prelistkeys``
944 ``prelistkeys``
945 Run before listing pushkeys (like bookmarks) in the
945 Run before listing pushkeys (like bookmarks) in the
946 repository. A non-zero status will cause failure. The key namespace is
946 repository. A non-zero status will cause failure. The key namespace is
947 in ``$HG_NAMESPACE``.
947 in ``$HG_NAMESPACE``.
948
948
949 ``preoutgoing``
949 ``preoutgoing``
950 Run before collecting changes to send from the local repository to
950 Run before collecting changes to send from the local repository to
951 another. A non-zero status will cause failure. This lets you prevent
951 another. A non-zero status will cause failure. This lets you prevent
952 pull over HTTP or SSH. It can also prevent propagating commits (via
952 pull over HTTP or SSH. It can also prevent propagating commits (via
953 local pull, push (outbound) or bundle commands), but not completely,
953 local pull, push (outbound) or bundle commands), but not completely,
954 since you can just copy files instead. The source of operation is in
954 since you can just copy files instead. The source of operation is in
955 ``$HG_SOURCE``. If "serve", the operation is happening on behalf of a remote
955 ``$HG_SOURCE``. If "serve", the operation is happening on behalf of a remote
956 SSH or HTTP repository. If "push", "pull" or "bundle", the operation
956 SSH or HTTP repository. If "push", "pull" or "bundle", the operation
957 is happening on behalf of a repository on same system.
957 is happening on behalf of a repository on same system.
958
958
959 ``prepushkey``
959 ``prepushkey``
960 Run before a pushkey (like a bookmark) is added to the
960 Run before a pushkey (like a bookmark) is added to the
961 repository. A non-zero status will cause the key to be rejected. The
961 repository. A non-zero status will cause the key to be rejected. The
962 key namespace is in ``$HG_NAMESPACE``, the key is in ``$HG_KEY``,
962 key namespace is in ``$HG_NAMESPACE``, the key is in ``$HG_KEY``,
963 the old value (if any) is in ``$HG_OLD``, and the new value is in
963 the old value (if any) is in ``$HG_OLD``, and the new value is in
964 ``$HG_NEW``.
964 ``$HG_NEW``.
965
965
966 ``pretag``
966 ``pretag``
967 Run before creating a tag. Exit status 0 allows the tag to be
967 Run before creating a tag. Exit status 0 allows the tag to be
968 created. A non-zero status will cause the tag to fail. The ID of the
968 created. A non-zero status will cause the tag to fail. The ID of the
969 changeset to tag is in ``$HG_NODE``. The name of tag is in ``$HG_TAG``. The
969 changeset to tag is in ``$HG_NODE``. The name of tag is in ``$HG_TAG``. The
970 tag is local if ``$HG_LOCAL=1``, or in the repository if ``$HG_LOCAL=0``.
970 tag is local if ``$HG_LOCAL=1``, or in the repository if ``$HG_LOCAL=0``.
971
971
972 ``pretxnopen``
972 ``pretxnopen``
973 Run before any new repository transaction is open. The reason for the
973 Run before any new repository transaction is open. The reason for the
974 transaction will be in ``$HG_TXNNAME``, and a unique identifier for the
974 transaction will be in ``$HG_TXNNAME``, and a unique identifier for the
975 transaction will be in ``HG_TXNID``. A non-zero status will prevent the
975 transaction will be in ``HG_TXNID``. A non-zero status will prevent the
976 transaction from being opened.
976 transaction from being opened.
977
977
978 ``pretxnclose``
978 ``pretxnclose``
979 Run right before the transaction is actually finalized. Any repository change
979 Run right before the transaction is actually finalized. Any repository change
980 will be visible to the hook program. This lets you validate the transaction
980 will be visible to the hook program. This lets you validate the transaction
981 content or change it. Exit status 0 allows the commit to proceed. A non-zero
981 content or change it. Exit status 0 allows the commit to proceed. A non-zero
982 status will cause the transaction to be rolled back. The reason for the
982 status will cause the transaction to be rolled back. The reason for the
983 transaction opening will be in ``$HG_TXNNAME``, and a unique identifier for
983 transaction opening will be in ``$HG_TXNNAME``, and a unique identifier for
984 the transaction will be in ``HG_TXNID``. The rest of the available data will
984 the transaction will be in ``HG_TXNID``. The rest of the available data will
985 vary according the transaction type. New changesets will add ``$HG_NODE``
985 vary according the transaction type. New changesets will add ``$HG_NODE``
986 (the ID of the first added changeset), ``$HG_NODE_LAST`` (the ID of the last
986 (the ID of the first added changeset), ``$HG_NODE_LAST`` (the ID of the last
987 added changeset), ``$HG_URL`` and ``$HG_SOURCE`` variables. Bookmark and
987 added changeset), ``$HG_URL`` and ``$HG_SOURCE`` variables. Bookmark and
988 phase changes will set ``HG_BOOKMARK_MOVED`` and ``HG_PHASES_MOVED`` to ``1``
988 phase changes will set ``HG_BOOKMARK_MOVED`` and ``HG_PHASES_MOVED`` to ``1``
989 respectively, etc.
989 respectively, etc.
990
990
991 ``pretxnclose-bookmark``
991 ``pretxnclose-bookmark``
992 Run right before a bookmark change is actually finalized. Any repository
992 Run right before a bookmark change is actually finalized. Any repository
993 change will be visible to the hook program. This lets you validate the
993 change will be visible to the hook program. This lets you validate the
994 transaction content or change it. Exit status 0 allows the commit to
994 transaction content or change it. Exit status 0 allows the commit to
995 proceed. A non-zero status will cause the transaction to be rolled back.
995 proceed. A non-zero status will cause the transaction to be rolled back.
996 The name of the bookmark will be available in ``$HG_BOOKMARK``, the new
996 The name of the bookmark will be available in ``$HG_BOOKMARK``, the new
997 bookmark location will be available in ``$HG_NODE`` while the previous
997 bookmark location will be available in ``$HG_NODE`` while the previous
998 location will be available in ``$HG_OLDNODE``. In case of a bookmark
998 location will be available in ``$HG_OLDNODE``. In case of a bookmark
999 creation ``$HG_OLDNODE`` will be empty. In case of deletion ``$HG_NODE``
999 creation ``$HG_OLDNODE`` will be empty. In case of deletion ``$HG_NODE``
1000 will be empty.
1000 will be empty.
1001 In addition, the reason for the transaction opening will be in
1001 In addition, the reason for the transaction opening will be in
1002 ``$HG_TXNNAME``, and a unique identifier for the transaction will be in
1002 ``$HG_TXNNAME``, and a unique identifier for the transaction will be in
1003 ``HG_TXNID``.
1003 ``HG_TXNID``.
1004
1004
1005 ``pretxnclose-phase``
1005 ``pretxnclose-phase``
1006 Run right before a phase change is actually finalized. Any repository change
1006 Run right before a phase change is actually finalized. Any repository change
1007 will be visible to the hook program. This lets you validate the transaction
1007 will be visible to the hook program. This lets you validate the transaction
1008 content or change it. Exit status 0 allows the commit to proceed. A non-zero
1008 content or change it. Exit status 0 allows the commit to proceed. A non-zero
1009 status will cause the transaction to be rolled back. The hook is called
1009 status will cause the transaction to be rolled back. The hook is called
1010 multiple times, once for each revision affected by a phase change.
1010 multiple times, once for each revision affected by a phase change.
1011 The affected node is available in ``$HG_NODE``, the phase in ``$HG_PHASE``
1011 The affected node is available in ``$HG_NODE``, the phase in ``$HG_PHASE``
1012 while the previous ``$HG_OLDPHASE``. In case of new node, ``$HG_OLDPHASE``
1012 while the previous ``$HG_OLDPHASE``. In case of new node, ``$HG_OLDPHASE``
1013 will be empty. In addition, the reason for the transaction opening will be in
1013 will be empty. In addition, the reason for the transaction opening will be in
1014 ``$HG_TXNNAME``, and a unique identifier for the transaction will be in
1014 ``$HG_TXNNAME``, and a unique identifier for the transaction will be in
1015 ``HG_TXNID``. The hook is also run for newly added revisions. In this case
1015 ``HG_TXNID``. The hook is also run for newly added revisions. In this case
1016 the ``$HG_OLDPHASE`` entry will be empty.
1016 the ``$HG_OLDPHASE`` entry will be empty.
1017
1017
1018 ``txnclose``
1018 ``txnclose``
1019 Run after any repository transaction has been committed. At this
1019 Run after any repository transaction has been committed. At this
1020 point, the transaction can no longer be rolled back. The hook will run
1020 point, the transaction can no longer be rolled back. The hook will run
1021 after the lock is released. See :hg:`help config.hooks.pretxnclose` for
1021 after the lock is released. See :hg:`help config.hooks.pretxnclose` for
1022 details about available variables.
1022 details about available variables.
1023
1023
1024 ``txnclose-bookmark``
1024 ``txnclose-bookmark``
1025 Run after any bookmark change has been committed. At this point, the
1025 Run after any bookmark change has been committed. At this point, the
1026 transaction can no longer be rolled back. The hook will run after the lock
1026 transaction can no longer be rolled back. The hook will run after the lock
1027 is released. See :hg:`help config.hooks.pretxnclose-bookmark` for details
1027 is released. See :hg:`help config.hooks.pretxnclose-bookmark` for details
1028 about available variables.
1028 about available variables.
1029
1029
1030 ``txnclose-phase``
1030 ``txnclose-phase``
1031 Run after any phase change has been committed. At this point, the
1031 Run after any phase change has been committed. At this point, the
1032 transaction can no longer be rolled back. The hook will run after the lock
1032 transaction can no longer be rolled back. The hook will run after the lock
1033 is released. See :hg:`help config.hooks.pretxnclose-phase` for details about
1033 is released. See :hg:`help config.hooks.pretxnclose-phase` for details about
1034 available variables.
1034 available variables.
1035
1035
1036 ``txnabort``
1036 ``txnabort``
1037 Run when a transaction is aborted. See :hg:`help config.hooks.pretxnclose`
1037 Run when a transaction is aborted. See :hg:`help config.hooks.pretxnclose`
1038 for details about available variables.
1038 for details about available variables.
1039
1039
1040 ``pretxnchangegroup``
1040 ``pretxnchangegroup``
1041 Run after a changegroup has been added via push, pull or unbundle, but before
1041 Run after a changegroup has been added via push, pull or unbundle, but before
1042 the transaction has been committed. The changegroup is visible to the hook
1042 the transaction has been committed. The changegroup is visible to the hook
1043 program. This allows validation of incoming changes before accepting them.
1043 program. This allows validation of incoming changes before accepting them.
1044 The ID of the first new changeset is in ``$HG_NODE`` and last is in
1044 The ID of the first new changeset is in ``$HG_NODE`` and last is in
1045 ``$HG_NODE_LAST``. Exit status 0 allows the transaction to commit. A non-zero
1045 ``$HG_NODE_LAST``. Exit status 0 allows the transaction to commit. A non-zero
1046 status will cause the transaction to be rolled back, and the push, pull or
1046 status will cause the transaction to be rolled back, and the push, pull or
1047 unbundle will fail. The URL that was the source of changes is in ``$HG_URL``.
1047 unbundle will fail. The URL that was the source of changes is in ``$HG_URL``.
1048
1048
1049 ``pretxncommit``
1049 ``pretxncommit``
1050 Run after a changeset has been created, but before the transaction is
1050 Run after a changeset has been created, but before the transaction is
1051 committed. The changeset is visible to the hook program. This allows
1051 committed. The changeset is visible to the hook program. This allows
1052 validation of the commit message and changes. Exit status 0 allows the
1052 validation of the commit message and changes. Exit status 0 allows the
1053 commit to proceed. A non-zero status will cause the transaction to
1053 commit to proceed. A non-zero status will cause the transaction to
1054 be rolled back. The ID of the new changeset is in ``$HG_NODE``. The parent
1054 be rolled back. The ID of the new changeset is in ``$HG_NODE``. The parent
1055 changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
1055 changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
1056
1056
1057 ``preupdate``
1057 ``preupdate``
1058 Run before updating the working directory. Exit status 0 allows
1058 Run before updating the working directory. Exit status 0 allows
1059 the update to proceed. A non-zero status will prevent the update.
1059 the update to proceed. A non-zero status will prevent the update.
1060 The changeset ID of first new parent is in ``$HG_PARENT1``. If updating to a
1060 The changeset ID of first new parent is in ``$HG_PARENT1``. If updating to a
1061 merge, the ID of second new parent is in ``$HG_PARENT2``.
1061 merge, the ID of second new parent is in ``$HG_PARENT2``.
1062
1062
1063 ``listkeys``
1063 ``listkeys``
1064 Run after listing pushkeys (like bookmarks) in the repository. The
1064 Run after listing pushkeys (like bookmarks) in the repository. The
1065 key namespace is in ``$HG_NAMESPACE``. ``$HG_VALUES`` is a
1065 key namespace is in ``$HG_NAMESPACE``. ``$HG_VALUES`` is a
1066 dictionary containing the keys and values.
1066 dictionary containing the keys and values.
1067
1067
1068 ``pushkey``
1068 ``pushkey``
1069 Run after a pushkey (like a bookmark) is added to the
1069 Run after a pushkey (like a bookmark) is added to the
1070 repository. The key namespace is in ``$HG_NAMESPACE``, the key is in
1070 repository. The key namespace is in ``$HG_NAMESPACE``, the key is in
1071 ``$HG_KEY``, the old value (if any) is in ``$HG_OLD``, and the new
1071 ``$HG_KEY``, the old value (if any) is in ``$HG_OLD``, and the new
1072 value is in ``$HG_NEW``.
1072 value is in ``$HG_NEW``.
1073
1073
1074 ``tag``
1074 ``tag``
1075 Run after a tag is created. The ID of the tagged changeset is in ``$HG_NODE``.
1075 Run after a tag is created. The ID of the tagged changeset is in ``$HG_NODE``.
1076 The name of tag is in ``$HG_TAG``. The tag is local if ``$HG_LOCAL=1``, or in
1076 The name of tag is in ``$HG_TAG``. The tag is local if ``$HG_LOCAL=1``, or in
1077 the repository if ``$HG_LOCAL=0``.
1077 the repository if ``$HG_LOCAL=0``.
1078
1078
1079 ``update``
1079 ``update``
1080 Run after updating the working directory. The changeset ID of first
1080 Run after updating the working directory. The changeset ID of first
1081 new parent is in ``$HG_PARENT1``. If updating to a merge, the ID of second new
1081 new parent is in ``$HG_PARENT1``. If updating to a merge, the ID of second new
1082 parent is in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
1082 parent is in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
1083 update failed (e.g. because conflicts were not resolved), ``$HG_ERROR=1``.
1083 update failed (e.g. because conflicts were not resolved), ``$HG_ERROR=1``.
1084
1084
1085 .. note::
1085 .. note::
1086
1086
1087 It is generally better to use standard hooks rather than the
1087 It is generally better to use standard hooks rather than the
1088 generic pre- and post- command hooks, as they are guaranteed to be
1088 generic pre- and post- command hooks, as they are guaranteed to be
1089 called in the appropriate contexts for influencing transactions.
1089 called in the appropriate contexts for influencing transactions.
1090 Also, hooks like "commit" will be called in all contexts that
1090 Also, hooks like "commit" will be called in all contexts that
1091 generate a commit (e.g. tag) and not just the commit command.
1091 generate a commit (e.g. tag) and not just the commit command.
1092
1092
1093 .. note::
1093 .. note::
1094
1094
1095 Environment variables with empty values may not be passed to
1095 Environment variables with empty values may not be passed to
1096 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
1096 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
1097 will have an empty value under Unix-like platforms for non-merge
1097 will have an empty value under Unix-like platforms for non-merge
1098 changesets, while it will not be available at all under Windows.
1098 changesets, while it will not be available at all under Windows.
1099
1099
1100 The syntax for Python hooks is as follows::
1100 The syntax for Python hooks is as follows::
1101
1101
1102 hookname = python:modulename.submodule.callable
1102 hookname = python:modulename.submodule.callable
1103 hookname = python:/path/to/python/module.py:callable
1103 hookname = python:/path/to/python/module.py:callable
1104
1104
1105 Python hooks are run within the Mercurial process. Each hook is
1105 Python hooks are run within the Mercurial process. Each hook is
1106 called with at least three keyword arguments: a ui object (keyword
1106 called with at least three keyword arguments: a ui object (keyword
1107 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
1107 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
1108 keyword that tells what kind of hook is used. Arguments listed as
1108 keyword that tells what kind of hook is used. Arguments listed as
1109 environment variables above are passed as keyword arguments, with no
1109 environment variables above are passed as keyword arguments, with no
1110 ``HG_`` prefix, and names in lower case.
1110 ``HG_`` prefix, and names in lower case.
1111
1111
1112 If a Python hook returns a "true" value or raises an exception, this
1112 If a Python hook returns a "true" value or raises an exception, this
1113 is treated as a failure.
1113 is treated as a failure.
1114
1114
1115
1115
1116 ``hostfingerprints``
1116 ``hostfingerprints``
1117 --------------------
1117 --------------------
1118
1118
1119 (Deprecated. Use ``[hostsecurity]``'s ``fingerprints`` options instead.)
1119 (Deprecated. Use ``[hostsecurity]``'s ``fingerprints`` options instead.)
1120
1120
1121 Fingerprints of the certificates of known HTTPS servers.
1121 Fingerprints of the certificates of known HTTPS servers.
1122
1122
1123 A HTTPS connection to a server with a fingerprint configured here will
1123 A HTTPS connection to a server with a fingerprint configured here will
1124 only succeed if the servers certificate matches the fingerprint.
1124 only succeed if the servers certificate matches the fingerprint.
1125 This is very similar to how ssh known hosts works.
1125 This is very similar to how ssh known hosts works.
1126
1126
1127 The fingerprint is the SHA-1 hash value of the DER encoded certificate.
1127 The fingerprint is the SHA-1 hash value of the DER encoded certificate.
1128 Multiple values can be specified (separated by spaces or commas). This can
1128 Multiple values can be specified (separated by spaces or commas). This can
1129 be used to define both old and new fingerprints while a host transitions
1129 be used to define both old and new fingerprints while a host transitions
1130 to a new certificate.
1130 to a new certificate.
1131
1131
1132 The CA chain and web.cacerts is not used for servers with a fingerprint.
1132 The CA chain and web.cacerts is not used for servers with a fingerprint.
1133
1133
1134 For example::
1134 For example::
1135
1135
1136 [hostfingerprints]
1136 [hostfingerprints]
1137 hg.intevation.de = fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1137 hg.intevation.de = fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1138 hg.intevation.org = fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1138 hg.intevation.org = fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1139
1139
1140 ``hostsecurity``
1140 ``hostsecurity``
1141 ----------------
1141 ----------------
1142
1142
1143 Used to specify global and per-host security settings for connecting to
1143 Used to specify global and per-host security settings for connecting to
1144 other machines.
1144 other machines.
1145
1145
1146 The following options control default behavior for all hosts.
1146 The following options control default behavior for all hosts.
1147
1147
1148 ``ciphers``
1148 ``ciphers``
1149 Defines the cryptographic ciphers to use for connections.
1149 Defines the cryptographic ciphers to use for connections.
1150
1150
1151 Value must be a valid OpenSSL Cipher List Format as documented at
1151 Value must be a valid OpenSSL Cipher List Format as documented at
1152 https://www.openssl.org/docs/manmaster/apps/ciphers.html#CIPHER-LIST-FORMAT.
1152 https://www.openssl.org/docs/manmaster/apps/ciphers.html#CIPHER-LIST-FORMAT.
1153
1153
1154 This setting is for advanced users only. Setting to incorrect values
1154 This setting is for advanced users only. Setting to incorrect values
1155 can significantly lower connection security or decrease performance.
1155 can significantly lower connection security or decrease performance.
1156 You have been warned.
1156 You have been warned.
1157
1157
1158 This option requires Python 2.7.
1158 This option requires Python 2.7.
1159
1159
1160 ``minimumprotocol``
1160 ``minimumprotocol``
1161 Defines the minimum channel encryption protocol to use.
1161 Defines the minimum channel encryption protocol to use.
1162
1162
1163 By default, the highest version of TLS supported by both client and server
1163 By default, the highest version of TLS supported by both client and server
1164 is used.
1164 is used.
1165
1165
1166 Allowed values are: ``tls1.0``, ``tls1.1``, ``tls1.2``.
1166 Allowed values are: ``tls1.0``, ``tls1.1``, ``tls1.2``.
1167
1167
1168 When running on an old Python version, only ``tls1.0`` is allowed since
1168 When running on an old Python version, only ``tls1.0`` is allowed since
1169 old versions of Python only support up to TLS 1.0.
1169 old versions of Python only support up to TLS 1.0.
1170
1170
1171 When running a Python that supports modern TLS versions, the default is
1171 When running a Python that supports modern TLS versions, the default is
1172 ``tls1.1``. ``tls1.0`` can still be used to allow TLS 1.0. However, this
1172 ``tls1.1``. ``tls1.0`` can still be used to allow TLS 1.0. However, this
1173 weakens security and should only be used as a feature of last resort if
1173 weakens security and should only be used as a feature of last resort if
1174 a server does not support TLS 1.1+.
1174 a server does not support TLS 1.1+.
1175
1175
1176 Options in the ``[hostsecurity]`` section can have the form
1176 Options in the ``[hostsecurity]`` section can have the form
1177 ``hostname``:``setting``. This allows multiple settings to be defined on a
1177 ``hostname``:``setting``. This allows multiple settings to be defined on a
1178 per-host basis.
1178 per-host basis.
1179
1179
1180 The following per-host settings can be defined.
1180 The following per-host settings can be defined.
1181
1181
1182 ``ciphers``
1182 ``ciphers``
1183 This behaves like ``ciphers`` as described above except it only applies
1183 This behaves like ``ciphers`` as described above except it only applies
1184 to the host on which it is defined.
1184 to the host on which it is defined.
1185
1185
1186 ``fingerprints``
1186 ``fingerprints``
1187 A list of hashes of the DER encoded peer/remote certificate. Values have
1187 A list of hashes of the DER encoded peer/remote certificate. Values have
1188 the form ``algorithm``:``fingerprint``. e.g.
1188 the form ``algorithm``:``fingerprint``. e.g.
1189 ``sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2``.
1189 ``sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2``.
1190 In addition, colons (``:``) can appear in the fingerprint part.
1190 In addition, colons (``:``) can appear in the fingerprint part.
1191
1191
1192 The following algorithms/prefixes are supported: ``sha1``, ``sha256``,
1192 The following algorithms/prefixes are supported: ``sha1``, ``sha256``,
1193 ``sha512``.
1193 ``sha512``.
1194
1194
1195 Use of ``sha256`` or ``sha512`` is preferred.
1195 Use of ``sha256`` or ``sha512`` is preferred.
1196
1196
1197 If a fingerprint is specified, the CA chain is not validated for this
1197 If a fingerprint is specified, the CA chain is not validated for this
1198 host and Mercurial will require the remote certificate to match one
1198 host and Mercurial will require the remote certificate to match one
1199 of the fingerprints specified. This means if the server updates its
1199 of the fingerprints specified. This means if the server updates its
1200 certificate, Mercurial will abort until a new fingerprint is defined.
1200 certificate, Mercurial will abort until a new fingerprint is defined.
1201 This can provide stronger security than traditional CA-based validation
1201 This can provide stronger security than traditional CA-based validation
1202 at the expense of convenience.
1202 at the expense of convenience.
1203
1203
1204 This option takes precedence over ``verifycertsfile``.
1204 This option takes precedence over ``verifycertsfile``.
1205
1205
1206 ``minimumprotocol``
1206 ``minimumprotocol``
1207 This behaves like ``minimumprotocol`` as described above except it
1207 This behaves like ``minimumprotocol`` as described above except it
1208 only applies to the host on which it is defined.
1208 only applies to the host on which it is defined.
1209
1209
1210 ``verifycertsfile``
1210 ``verifycertsfile``
1211 Path to file a containing a list of PEM encoded certificates used to
1211 Path to file a containing a list of PEM encoded certificates used to
1212 verify the server certificate. Environment variables and ``~user``
1212 verify the server certificate. Environment variables and ``~user``
1213 constructs are expanded in the filename.
1213 constructs are expanded in the filename.
1214
1214
1215 The server certificate or the certificate's certificate authority (CA)
1215 The server certificate or the certificate's certificate authority (CA)
1216 must match a certificate from this file or certificate verification
1216 must match a certificate from this file or certificate verification
1217 will fail and connections to the server will be refused.
1217 will fail and connections to the server will be refused.
1218
1218
1219 If defined, only certificates provided by this file will be used:
1219 If defined, only certificates provided by this file will be used:
1220 ``web.cacerts`` and any system/default certificates will not be
1220 ``web.cacerts`` and any system/default certificates will not be
1221 used.
1221 used.
1222
1222
1223 This option has no effect if the per-host ``fingerprints`` option
1223 This option has no effect if the per-host ``fingerprints`` option
1224 is set.
1224 is set.
1225
1225
1226 The format of the file is as follows::
1226 The format of the file is as follows::
1227
1227
1228 -----BEGIN CERTIFICATE-----
1228 -----BEGIN CERTIFICATE-----
1229 ... (certificate in base64 PEM encoding) ...
1229 ... (certificate in base64 PEM encoding) ...
1230 -----END CERTIFICATE-----
1230 -----END CERTIFICATE-----
1231 -----BEGIN CERTIFICATE-----
1231 -----BEGIN CERTIFICATE-----
1232 ... (certificate in base64 PEM encoding) ...
1232 ... (certificate in base64 PEM encoding) ...
1233 -----END CERTIFICATE-----
1233 -----END CERTIFICATE-----
1234
1234
1235 For example::
1235 For example::
1236
1236
1237 [hostsecurity]
1237 [hostsecurity]
1238 hg.example.com:fingerprints = sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2
1238 hg.example.com:fingerprints = sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2
1239 hg2.example.com:fingerprints = sha1:914f1aff87249c09b6859b88b1906d30756491ca, sha1:fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1239 hg2.example.com:fingerprints = sha1:914f1aff87249c09b6859b88b1906d30756491ca, sha1:fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1240 hg3.example.com:fingerprints = sha256:9a:b0:dc:e2:75:ad:8a:b7:84:58:e5:1f:07:32:f1:87:e6:bd:24:22:af:b7:ce:8e:9c:b4:10:cf:b9:f4:0e:d2
1240 hg3.example.com:fingerprints = sha256:9a:b0:dc:e2:75:ad:8a:b7:84:58:e5:1f:07:32:f1:87:e6:bd:24:22:af:b7:ce:8e:9c:b4:10:cf:b9:f4:0e:d2
1241 foo.example.com:verifycertsfile = /etc/ssl/trusted-ca-certs.pem
1241 foo.example.com:verifycertsfile = /etc/ssl/trusted-ca-certs.pem
1242
1242
1243 To change the default minimum protocol version to TLS 1.2 but to allow TLS 1.1
1243 To change the default minimum protocol version to TLS 1.2 but to allow TLS 1.1
1244 when connecting to ``hg.example.com``::
1244 when connecting to ``hg.example.com``::
1245
1245
1246 [hostsecurity]
1246 [hostsecurity]
1247 minimumprotocol = tls1.2
1247 minimumprotocol = tls1.2
1248 hg.example.com:minimumprotocol = tls1.1
1248 hg.example.com:minimumprotocol = tls1.1
1249
1249
1250 ``http_proxy``
1250 ``http_proxy``
1251 --------------
1251 --------------
1252
1252
1253 Used to access web-based Mercurial repositories through a HTTP
1253 Used to access web-based Mercurial repositories through a HTTP
1254 proxy.
1254 proxy.
1255
1255
1256 ``host``
1256 ``host``
1257 Host name and (optional) port of the proxy server, for example
1257 Host name and (optional) port of the proxy server, for example
1258 "myproxy:8000".
1258 "myproxy:8000".
1259
1259
1260 ``no``
1260 ``no``
1261 Optional. Comma-separated list of host names that should bypass
1261 Optional. Comma-separated list of host names that should bypass
1262 the proxy.
1262 the proxy.
1263
1263
1264 ``passwd``
1264 ``passwd``
1265 Optional. Password to authenticate with at the proxy server.
1265 Optional. Password to authenticate with at the proxy server.
1266
1266
1267 ``user``
1267 ``user``
1268 Optional. User name to authenticate with at the proxy server.
1268 Optional. User name to authenticate with at the proxy server.
1269
1269
1270 ``always``
1270 ``always``
1271 Optional. Always use the proxy, even for localhost and any entries
1271 Optional. Always use the proxy, even for localhost and any entries
1272 in ``http_proxy.no``. (default: False)
1272 in ``http_proxy.no``. (default: False)
1273
1273
1274 ``merge``
1274 ``merge``
1275 ---------
1275 ---------
1276
1276
1277 This section specifies behavior during merges and updates.
1277 This section specifies behavior during merges and updates.
1278
1278
1279 ``checkignored``
1279 ``checkignored``
1280 Controls behavior when an ignored file on disk has the same name as a tracked
1280 Controls behavior when an ignored file on disk has the same name as a tracked
1281 file in the changeset being merged or updated to, and has different
1281 file in the changeset being merged or updated to, and has different
1282 contents. Options are ``abort``, ``warn`` and ``ignore``. With ``abort``,
1282 contents. Options are ``abort``, ``warn`` and ``ignore``. With ``abort``,
1283 abort on such files. With ``warn``, warn on such files and back them up as
1283 abort on such files. With ``warn``, warn on such files and back them up as
1284 ``.orig``. With ``ignore``, don't print a warning and back them up as
1284 ``.orig``. With ``ignore``, don't print a warning and back them up as
1285 ``.orig``. (default: ``abort``)
1285 ``.orig``. (default: ``abort``)
1286
1286
1287 ``checkunknown``
1287 ``checkunknown``
1288 Controls behavior when an unknown file that isn't ignored has the same name
1288 Controls behavior when an unknown file that isn't ignored has the same name
1289 as a tracked file in the changeset being merged or updated to, and has
1289 as a tracked file in the changeset being merged or updated to, and has
1290 different contents. Similar to ``merge.checkignored``, except for files that
1290 different contents. Similar to ``merge.checkignored``, except for files that
1291 are not ignored. (default: ``abort``)
1291 are not ignored. (default: ``abort``)
1292
1292
1293 ``on-failure``
1293 ``on-failure``
1294 When set to ``continue`` (the default), the merge process attempts to
1294 When set to ``continue`` (the default), the merge process attempts to
1295 merge all unresolved files using the merge chosen tool, regardless of
1295 merge all unresolved files using the merge chosen tool, regardless of
1296 whether previous file merge attempts during the process succeeded or not.
1296 whether previous file merge attempts during the process succeeded or not.
1297 Setting this to ``prompt`` will prompt after any merge failure continue
1297 Setting this to ``prompt`` will prompt after any merge failure continue
1298 or halt the merge process. Setting this to ``halt`` will automatically
1298 or halt the merge process. Setting this to ``halt`` will automatically
1299 halt the merge process on any merge tool failure. The merge process
1299 halt the merge process on any merge tool failure. The merge process
1300 can be restarted by using the ``resolve`` command. When a merge is
1300 can be restarted by using the ``resolve`` command. When a merge is
1301 halted, the repository is left in a normal ``unresolved`` merge state.
1301 halted, the repository is left in a normal ``unresolved`` merge state.
1302 (default: ``continue``)
1302 (default: ``continue``)
1303
1303
1304 ``merge-patterns``
1304 ``merge-patterns``
1305 ------------------
1305 ------------------
1306
1306
1307 This section specifies merge tools to associate with particular file
1307 This section specifies merge tools to associate with particular file
1308 patterns. Tools matched here will take precedence over the default
1308 patterns. Tools matched here will take precedence over the default
1309 merge tool. Patterns are globs by default, rooted at the repository
1309 merge tool. Patterns are globs by default, rooted at the repository
1310 root.
1310 root.
1311
1311
1312 Example::
1312 Example::
1313
1313
1314 [merge-patterns]
1314 [merge-patterns]
1315 **.c = kdiff3
1315 **.c = kdiff3
1316 **.jpg = myimgmerge
1316 **.jpg = myimgmerge
1317
1317
1318 ``merge-tools``
1318 ``merge-tools``
1319 ---------------
1319 ---------------
1320
1320
1321 This section configures external merge tools to use for file-level
1321 This section configures external merge tools to use for file-level
1322 merges. This section has likely been preconfigured at install time.
1322 merges. This section has likely been preconfigured at install time.
1323 Use :hg:`config merge-tools` to check the existing configuration.
1323 Use :hg:`config merge-tools` to check the existing configuration.
1324 Also see :hg:`help merge-tools` for more details.
1324 Also see :hg:`help merge-tools` for more details.
1325
1325
1326 Example ``~/.hgrc``::
1326 Example ``~/.hgrc``::
1327
1327
1328 [merge-tools]
1328 [merge-tools]
1329 # Override stock tool location
1329 # Override stock tool location
1330 kdiff3.executable = ~/bin/kdiff3
1330 kdiff3.executable = ~/bin/kdiff3
1331 # Specify command line
1331 # Specify command line
1332 kdiff3.args = $base $local $other -o $output
1332 kdiff3.args = $base $local $other -o $output
1333 # Give higher priority
1333 # Give higher priority
1334 kdiff3.priority = 1
1334 kdiff3.priority = 1
1335
1335
1336 # Changing the priority of preconfigured tool
1336 # Changing the priority of preconfigured tool
1337 meld.priority = 0
1337 meld.priority = 0
1338
1338
1339 # Disable a preconfigured tool
1339 # Disable a preconfigured tool
1340 vimdiff.disabled = yes
1340 vimdiff.disabled = yes
1341
1341
1342 # Define new tool
1342 # Define new tool
1343 myHtmlTool.args = -m $local $other $base $output
1343 myHtmlTool.args = -m $local $other $base $output
1344 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
1344 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
1345 myHtmlTool.priority = 1
1345 myHtmlTool.priority = 1
1346
1346
1347 Supported arguments:
1347 Supported arguments:
1348
1348
1349 ``priority``
1349 ``priority``
1350 The priority in which to evaluate this tool.
1350 The priority in which to evaluate this tool.
1351 (default: 0)
1351 (default: 0)
1352
1352
1353 ``executable``
1353 ``executable``
1354 Either just the name of the executable or its pathname.
1354 Either just the name of the executable or its pathname.
1355
1355
1356 .. container:: windows
1356 .. container:: windows
1357
1357
1358 On Windows, the path can use environment variables with ${ProgramFiles}
1358 On Windows, the path can use environment variables with ${ProgramFiles}
1359 syntax.
1359 syntax.
1360
1360
1361 (default: the tool name)
1361 (default: the tool name)
1362
1362
1363 ``args``
1363 ``args``
1364 The arguments to pass to the tool executable. You can refer to the
1364 The arguments to pass to the tool executable. You can refer to the
1365 files being merged as well as the output file through these
1365 files being merged as well as the output file through these
1366 variables: ``$base``, ``$local``, ``$other``, ``$output``.
1366 variables: ``$base``, ``$local``, ``$other``, ``$output``.
1367
1367
1368 The meaning of ``$local`` and ``$other`` can vary depending on which action is
1368 The meaning of ``$local`` and ``$other`` can vary depending on which action is
1369 being performed. During an update or merge, ``$local`` represents the original
1369 being performed. During an update or merge, ``$local`` represents the original
1370 state of the file, while ``$other`` represents the commit you are updating to or
1370 state of the file, while ``$other`` represents the commit you are updating to or
1371 the commit you are merging with. During a rebase, ``$local`` represents the
1371 the commit you are merging with. During a rebase, ``$local`` represents the
1372 destination of the rebase, and ``$other`` represents the commit being rebased.
1372 destination of the rebase, and ``$other`` represents the commit being rebased.
1373
1373
1374 Some operations define custom labels to assist with identifying the revisions,
1374 Some operations define custom labels to assist with identifying the revisions,
1375 accessible via ``$labellocal``, ``$labelother``, and ``$labelbase``. If custom
1375 accessible via ``$labellocal``, ``$labelother``, and ``$labelbase``. If custom
1376 labels are not available, these will be ``local``, ``other``, and ``base``,
1376 labels are not available, these will be ``local``, ``other``, and ``base``,
1377 respectively.
1377 respectively.
1378 (default: ``$local $base $other``)
1378 (default: ``$local $base $other``)
1379
1379
1380 ``premerge``
1380 ``premerge``
1381 Attempt to run internal non-interactive 3-way merge tool before
1381 Attempt to run internal non-interactive 3-way merge tool before
1382 launching external tool. Options are ``true``, ``false``, ``keep`` or
1382 launching external tool. Options are ``true``, ``false``, ``keep`` or
1383 ``keep-merge3``. The ``keep`` option will leave markers in the file if the
1383 ``keep-merge3``. The ``keep`` option will leave markers in the file if the
1384 premerge fails. The ``keep-merge3`` will do the same but include information
1384 premerge fails. The ``keep-merge3`` will do the same but include information
1385 about the base of the merge in the marker (see internal :merge3 in
1385 about the base of the merge in the marker (see internal :merge3 in
1386 :hg:`help merge-tools`).
1386 :hg:`help merge-tools`).
1387 (default: True)
1387 (default: True)
1388
1388
1389 ``binary``
1389 ``binary``
1390 This tool can merge binary files. (default: False, unless tool
1390 This tool can merge binary files. (default: False, unless tool
1391 was selected by file pattern match)
1391 was selected by file pattern match)
1392
1392
1393 ``symlink``
1393 ``symlink``
1394 This tool can merge symlinks. (default: False)
1394 This tool can merge symlinks. (default: False)
1395
1395
1396 ``check``
1396 ``check``
1397 A list of merge success-checking options:
1397 A list of merge success-checking options:
1398
1398
1399 ``changed``
1399 ``changed``
1400 Ask whether merge was successful when the merged file shows no changes.
1400 Ask whether merge was successful when the merged file shows no changes.
1401 ``conflicts``
1401 ``conflicts``
1402 Check whether there are conflicts even though the tool reported success.
1402 Check whether there are conflicts even though the tool reported success.
1403 ``prompt``
1403 ``prompt``
1404 Always prompt for merge success, regardless of success reported by tool.
1404 Always prompt for merge success, regardless of success reported by tool.
1405
1405
1406 ``fixeol``
1406 ``fixeol``
1407 Attempt to fix up EOL changes caused by the merge tool.
1407 Attempt to fix up EOL changes caused by the merge tool.
1408 (default: False)
1408 (default: False)
1409
1409
1410 ``gui``
1410 ``gui``
1411 This tool requires a graphical interface to run. (default: False)
1411 This tool requires a graphical interface to run. (default: False)
1412
1412
1413 ``mergemarkers``
1413 ``mergemarkers``
1414 Controls whether the labels passed via ``$labellocal``, ``$labelother``, and
1414 Controls whether the labels passed via ``$labellocal``, ``$labelother``, and
1415 ``$labelbase`` are ``detailed`` (respecting ``mergemarkertemplate``) or
1415 ``$labelbase`` are ``detailed`` (respecting ``mergemarkertemplate``) or
1416 ``basic``. If ``premerge`` is ``keep`` or ``keep-merge3``, the conflict
1416 ``basic``. If ``premerge`` is ``keep`` or ``keep-merge3``, the conflict
1417 markers generated during premerge will be ``detailed`` if either this option or
1417 markers generated during premerge will be ``detailed`` if either this option or
1418 the corresponding option in the ``[ui]`` section is ``detailed``.
1418 the corresponding option in the ``[ui]`` section is ``detailed``.
1419 (default: ``basic``)
1419 (default: ``basic``)
1420
1420
1421 ``mergemarkertemplate``
1421 ``mergemarkertemplate``
1422 This setting can be used to override ``mergemarkertemplate`` from the ``[ui]``
1422 This setting can be used to override ``mergemarkertemplate`` from the ``[ui]``
1423 section on a per-tool basis; this applies to the ``$label``-prefixed variables
1423 section on a per-tool basis; this applies to the ``$label``-prefixed variables
1424 and to the conflict markers that are generated if ``premerge`` is ``keep` or
1424 and to the conflict markers that are generated if ``premerge`` is ``keep` or
1425 ``keep-merge3``. See the corresponding variable in ``[ui]`` for more
1425 ``keep-merge3``. See the corresponding variable in ``[ui]`` for more
1426 information.
1426 information.
1427
1427
1428 .. container:: windows
1428 .. container:: windows
1429
1429
1430 ``regkey``
1430 ``regkey``
1431 Windows registry key which describes install location of this
1431 Windows registry key which describes install location of this
1432 tool. Mercurial will search for this key first under
1432 tool. Mercurial will search for this key first under
1433 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
1433 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
1434 (default: None)
1434 (default: None)
1435
1435
1436 ``regkeyalt``
1436 ``regkeyalt``
1437 An alternate Windows registry key to try if the first key is not
1437 An alternate Windows registry key to try if the first key is not
1438 found. The alternate key uses the same ``regname`` and ``regappend``
1438 found. The alternate key uses the same ``regname`` and ``regappend``
1439 semantics of the primary key. The most common use for this key
1439 semantics of the primary key. The most common use for this key
1440 is to search for 32bit applications on 64bit operating systems.
1440 is to search for 32bit applications on 64bit operating systems.
1441 (default: None)
1441 (default: None)
1442
1442
1443 ``regname``
1443 ``regname``
1444 Name of value to read from specified registry key.
1444 Name of value to read from specified registry key.
1445 (default: the unnamed (default) value)
1445 (default: the unnamed (default) value)
1446
1446
1447 ``regappend``
1447 ``regappend``
1448 String to append to the value read from the registry, typically
1448 String to append to the value read from the registry, typically
1449 the executable name of the tool.
1449 the executable name of the tool.
1450 (default: None)
1450 (default: None)
1451
1451
1452 ``pager``
1452 ``pager``
1453 ---------
1453 ---------
1454
1454
1455 Setting used to control when to paginate and with what external tool. See
1455 Setting used to control when to paginate and with what external tool. See
1456 :hg:`help pager` for details.
1456 :hg:`help pager` for details.
1457
1457
1458 ``pager``
1458 ``pager``
1459 Define the external tool used as pager.
1459 Define the external tool used as pager.
1460
1460
1461 If no pager is set, Mercurial uses the environment variable $PAGER.
1461 If no pager is set, Mercurial uses the environment variable $PAGER.
1462 If neither pager.pager, nor $PAGER is set, a default pager will be
1462 If neither pager.pager, nor $PAGER is set, a default pager will be
1463 used, typically `less` on Unix and `more` on Windows. Example::
1463 used, typically `less` on Unix and `more` on Windows. Example::
1464
1464
1465 [pager]
1465 [pager]
1466 pager = less -FRX
1466 pager = less -FRX
1467
1467
1468 ``ignore``
1468 ``ignore``
1469 List of commands to disable the pager for. Example::
1469 List of commands to disable the pager for. Example::
1470
1470
1471 [pager]
1471 [pager]
1472 ignore = version, help, update
1472 ignore = version, help, update
1473
1473
1474 ``patch``
1474 ``patch``
1475 ---------
1475 ---------
1476
1476
1477 Settings used when applying patches, for instance through the 'import'
1477 Settings used when applying patches, for instance through the 'import'
1478 command or with Mercurial Queues extension.
1478 command or with Mercurial Queues extension.
1479
1479
1480 ``eol``
1480 ``eol``
1481 When set to 'strict' patch content and patched files end of lines
1481 When set to 'strict' patch content and patched files end of lines
1482 are preserved. When set to ``lf`` or ``crlf``, both files end of
1482 are preserved. When set to ``lf`` or ``crlf``, both files end of
1483 lines are ignored when patching and the result line endings are
1483 lines are ignored when patching and the result line endings are
1484 normalized to either LF (Unix) or CRLF (Windows). When set to
1484 normalized to either LF (Unix) or CRLF (Windows). When set to
1485 ``auto``, end of lines are again ignored while patching but line
1485 ``auto``, end of lines are again ignored while patching but line
1486 endings in patched files are normalized to their original setting
1486 endings in patched files are normalized to their original setting
1487 on a per-file basis. If target file does not exist or has no end
1487 on a per-file basis. If target file does not exist or has no end
1488 of line, patch line endings are preserved.
1488 of line, patch line endings are preserved.
1489 (default: strict)
1489 (default: strict)
1490
1490
1491 ``fuzz``
1491 ``fuzz``
1492 The number of lines of 'fuzz' to allow when applying patches. This
1492 The number of lines of 'fuzz' to allow when applying patches. This
1493 controls how much context the patcher is allowed to ignore when
1493 controls how much context the patcher is allowed to ignore when
1494 trying to apply a patch.
1494 trying to apply a patch.
1495 (default: 2)
1495 (default: 2)
1496
1496
1497 ``paths``
1497 ``paths``
1498 ---------
1498 ---------
1499
1499
1500 Assigns symbolic names and behavior to repositories.
1500 Assigns symbolic names and behavior to repositories.
1501
1501
1502 Options are symbolic names defining the URL or directory that is the
1502 Options are symbolic names defining the URL or directory that is the
1503 location of the repository. Example::
1503 location of the repository. Example::
1504
1504
1505 [paths]
1505 [paths]
1506 my_server = https://example.com/my_repo
1506 my_server = https://example.com/my_repo
1507 local_path = /home/me/repo
1507 local_path = /home/me/repo
1508
1508
1509 These symbolic names can be used from the command line. To pull
1509 These symbolic names can be used from the command line. To pull
1510 from ``my_server``: :hg:`pull my_server`. To push to ``local_path``:
1510 from ``my_server``: :hg:`pull my_server`. To push to ``local_path``:
1511 :hg:`push local_path`.
1511 :hg:`push local_path`.
1512
1512
1513 Options containing colons (``:``) denote sub-options that can influence
1513 Options containing colons (``:``) denote sub-options that can influence
1514 behavior for that specific path. Example::
1514 behavior for that specific path. Example::
1515
1515
1516 [paths]
1516 [paths]
1517 my_server = https://example.com/my_path
1517 my_server = https://example.com/my_path
1518 my_server:pushurl = ssh://example.com/my_path
1518 my_server:pushurl = ssh://example.com/my_path
1519
1519
1520 The following sub-options can be defined:
1520 The following sub-options can be defined:
1521
1521
1522 ``pushurl``
1522 ``pushurl``
1523 The URL to use for push operations. If not defined, the location
1523 The URL to use for push operations. If not defined, the location
1524 defined by the path's main entry is used.
1524 defined by the path's main entry is used.
1525
1525
1526 ``pushrev``
1526 ``pushrev``
1527 A revset defining which revisions to push by default.
1527 A revset defining which revisions to push by default.
1528
1528
1529 When :hg:`push` is executed without a ``-r`` argument, the revset
1529 When :hg:`push` is executed without a ``-r`` argument, the revset
1530 defined by this sub-option is evaluated to determine what to push.
1530 defined by this sub-option is evaluated to determine what to push.
1531
1531
1532 For example, a value of ``.`` will push the working directory's
1532 For example, a value of ``.`` will push the working directory's
1533 revision by default.
1533 revision by default.
1534
1534
1535 Revsets specifying bookmarks will not result in the bookmark being
1535 Revsets specifying bookmarks will not result in the bookmark being
1536 pushed.
1536 pushed.
1537
1537
1538 The following special named paths exist:
1538 The following special named paths exist:
1539
1539
1540 ``default``
1540 ``default``
1541 The URL or directory to use when no source or remote is specified.
1541 The URL or directory to use when no source or remote is specified.
1542
1542
1543 :hg:`clone` will automatically define this path to the location the
1543 :hg:`clone` will automatically define this path to the location the
1544 repository was cloned from.
1544 repository was cloned from.
1545
1545
1546 ``default-push``
1546 ``default-push``
1547 (deprecated) The URL or directory for the default :hg:`push` location.
1547 (deprecated) The URL or directory for the default :hg:`push` location.
1548 ``default:pushurl`` should be used instead.
1548 ``default:pushurl`` should be used instead.
1549
1549
1550 ``phases``
1550 ``phases``
1551 ----------
1551 ----------
1552
1552
1553 Specifies default handling of phases. See :hg:`help phases` for more
1553 Specifies default handling of phases. See :hg:`help phases` for more
1554 information about working with phases.
1554 information about working with phases.
1555
1555
1556 ``publish``
1556 ``publish``
1557 Controls draft phase behavior when working as a server. When true,
1557 Controls draft phase behavior when working as a server. When true,
1558 pushed changesets are set to public in both client and server and
1558 pushed changesets are set to public in both client and server and
1559 pulled or cloned changesets are set to public in the client.
1559 pulled or cloned changesets are set to public in the client.
1560 (default: True)
1560 (default: True)
1561
1561
1562 ``new-commit``
1562 ``new-commit``
1563 Phase of newly-created commits.
1563 Phase of newly-created commits.
1564 (default: draft)
1564 (default: draft)
1565
1565
1566 ``checksubrepos``
1566 ``checksubrepos``
1567 Check the phase of the current revision of each subrepository. Allowed
1567 Check the phase of the current revision of each subrepository. Allowed
1568 values are "ignore", "follow" and "abort". For settings other than
1568 values are "ignore", "follow" and "abort". For settings other than
1569 "ignore", the phase of the current revision of each subrepository is
1569 "ignore", the phase of the current revision of each subrepository is
1570 checked before committing the parent repository. If any of those phases is
1570 checked before committing the parent repository. If any of those phases is
1571 greater than the phase of the parent repository (e.g. if a subrepo is in a
1571 greater than the phase of the parent repository (e.g. if a subrepo is in a
1572 "secret" phase while the parent repo is in "draft" phase), the commit is
1572 "secret" phase while the parent repo is in "draft" phase), the commit is
1573 either aborted (if checksubrepos is set to "abort") or the higher phase is
1573 either aborted (if checksubrepos is set to "abort") or the higher phase is
1574 used for the parent repository commit (if set to "follow").
1574 used for the parent repository commit (if set to "follow").
1575 (default: follow)
1575 (default: follow)
1576
1576
1577
1577
1578 ``profiling``
1578 ``profiling``
1579 -------------
1579 -------------
1580
1580
1581 Specifies profiling type, format, and file output. Two profilers are
1581 Specifies profiling type, format, and file output. Two profilers are
1582 supported: an instrumenting profiler (named ``ls``), and a sampling
1582 supported: an instrumenting profiler (named ``ls``), and a sampling
1583 profiler (named ``stat``).
1583 profiler (named ``stat``).
1584
1584
1585 In this section description, 'profiling data' stands for the raw data
1585 In this section description, 'profiling data' stands for the raw data
1586 collected during profiling, while 'profiling report' stands for a
1586 collected during profiling, while 'profiling report' stands for a
1587 statistical text report generated from the profiling data.
1587 statistical text report generated from the profiling data.
1588
1588
1589 ``enabled``
1589 ``enabled``
1590 Enable the profiler.
1590 Enable the profiler.
1591 (default: false)
1591 (default: false)
1592
1592
1593 This is equivalent to passing ``--profile`` on the command line.
1593 This is equivalent to passing ``--profile`` on the command line.
1594
1594
1595 ``type``
1595 ``type``
1596 The type of profiler to use.
1596 The type of profiler to use.
1597 (default: stat)
1597 (default: stat)
1598
1598
1599 ``ls``
1599 ``ls``
1600 Use Python's built-in instrumenting profiler. This profiler
1600 Use Python's built-in instrumenting profiler. This profiler
1601 works on all platforms, but each line number it reports is the
1601 works on all platforms, but each line number it reports is the
1602 first line of a function. This restriction makes it difficult to
1602 first line of a function. This restriction makes it difficult to
1603 identify the expensive parts of a non-trivial function.
1603 identify the expensive parts of a non-trivial function.
1604 ``stat``
1604 ``stat``
1605 Use a statistical profiler, statprof. This profiler is most
1605 Use a statistical profiler, statprof. This profiler is most
1606 useful for profiling commands that run for longer than about 0.1
1606 useful for profiling commands that run for longer than about 0.1
1607 seconds.
1607 seconds.
1608
1608
1609 ``format``
1609 ``format``
1610 Profiling format. Specific to the ``ls`` instrumenting profiler.
1610 Profiling format. Specific to the ``ls`` instrumenting profiler.
1611 (default: text)
1611 (default: text)
1612
1612
1613 ``text``
1613 ``text``
1614 Generate a profiling report. When saving to a file, it should be
1614 Generate a profiling report. When saving to a file, it should be
1615 noted that only the report is saved, and the profiling data is
1615 noted that only the report is saved, and the profiling data is
1616 not kept.
1616 not kept.
1617 ``kcachegrind``
1617 ``kcachegrind``
1618 Format profiling data for kcachegrind use: when saving to a
1618 Format profiling data for kcachegrind use: when saving to a
1619 file, the generated file can directly be loaded into
1619 file, the generated file can directly be loaded into
1620 kcachegrind.
1620 kcachegrind.
1621
1621
1622 ``statformat``
1622 ``statformat``
1623 Profiling format for the ``stat`` profiler.
1623 Profiling format for the ``stat`` profiler.
1624 (default: hotpath)
1624 (default: hotpath)
1625
1625
1626 ``hotpath``
1626 ``hotpath``
1627 Show a tree-based display containing the hot path of execution (where
1627 Show a tree-based display containing the hot path of execution (where
1628 most time was spent).
1628 most time was spent).
1629 ``bymethod``
1629 ``bymethod``
1630 Show a table of methods ordered by how frequently they are active.
1630 Show a table of methods ordered by how frequently they are active.
1631 ``byline``
1631 ``byline``
1632 Show a table of lines in files ordered by how frequently they are active.
1632 Show a table of lines in files ordered by how frequently they are active.
1633 ``json``
1633 ``json``
1634 Render profiling data as JSON.
1634 Render profiling data as JSON.
1635
1635
1636 ``frequency``
1636 ``frequency``
1637 Sampling frequency. Specific to the ``stat`` sampling profiler.
1637 Sampling frequency. Specific to the ``stat`` sampling profiler.
1638 (default: 1000)
1638 (default: 1000)
1639
1639
1640 ``output``
1640 ``output``
1641 File path where profiling data or report should be saved. If the
1641 File path where profiling data or report should be saved. If the
1642 file exists, it is replaced. (default: None, data is printed on
1642 file exists, it is replaced. (default: None, data is printed on
1643 stderr)
1643 stderr)
1644
1644
1645 ``sort``
1645 ``sort``
1646 Sort field. Specific to the ``ls`` instrumenting profiler.
1646 Sort field. Specific to the ``ls`` instrumenting profiler.
1647 One of ``callcount``, ``reccallcount``, ``totaltime`` and
1647 One of ``callcount``, ``reccallcount``, ``totaltime`` and
1648 ``inlinetime``.
1648 ``inlinetime``.
1649 (default: inlinetime)
1649 (default: inlinetime)
1650
1650
1651 ``limit``
1651 ``limit``
1652 Number of lines to show. Specific to the ``ls`` instrumenting profiler.
1652 Number of lines to show. Specific to the ``ls`` instrumenting profiler.
1653 (default: 30)
1653 (default: 30)
1654
1654
1655 ``nested``
1655 ``nested``
1656 Show at most this number of lines of drill-down info after each main entry.
1656 Show at most this number of lines of drill-down info after each main entry.
1657 This can help explain the difference between Total and Inline.
1657 This can help explain the difference between Total and Inline.
1658 Specific to the ``ls`` instrumenting profiler.
1658 Specific to the ``ls`` instrumenting profiler.
1659 (default: 0)
1659 (default: 0)
1660
1660
1661 ``showmin``
1661 ``showmin``
1662 Minimum fraction of samples an entry must have for it to be displayed.
1662 Minimum fraction of samples an entry must have for it to be displayed.
1663 Can be specified as a float between ``0.0`` and ``1.0`` or can have a
1663 Can be specified as a float between ``0.0`` and ``1.0`` or can have a
1664 ``%`` afterwards to allow values up to ``100``. e.g. ``5%``.
1664 ``%`` afterwards to allow values up to ``100``. e.g. ``5%``.
1665
1665
1666 Only used by the ``stat`` profiler.
1666 Only used by the ``stat`` profiler.
1667
1667
1668 For the ``hotpath`` format, default is ``0.05``.
1668 For the ``hotpath`` format, default is ``0.05``.
1669 For the ``chrome`` format, default is ``0.005``.
1669 For the ``chrome`` format, default is ``0.005``.
1670
1670
1671 The option is unused on other formats.
1671 The option is unused on other formats.
1672
1672
1673 ``showmax``
1673 ``showmax``
1674 Maximum fraction of samples an entry can have before it is ignored in
1674 Maximum fraction of samples an entry can have before it is ignored in
1675 display. Values format is the same as ``showmin``.
1675 display. Values format is the same as ``showmin``.
1676
1676
1677 Only used by the ``stat`` profiler.
1677 Only used by the ``stat`` profiler.
1678
1678
1679 For the ``chrome`` format, default is ``0.999``.
1679 For the ``chrome`` format, default is ``0.999``.
1680
1680
1681 The option is unused on other formats.
1681 The option is unused on other formats.
1682
1682
1683 ``progress``
1683 ``progress``
1684 ------------
1684 ------------
1685
1685
1686 Mercurial commands can draw progress bars that are as informative as
1686 Mercurial commands can draw progress bars that are as informative as
1687 possible. Some progress bars only offer indeterminate information, while others
1687 possible. Some progress bars only offer indeterminate information, while others
1688 have a definite end point.
1688 have a definite end point.
1689
1689
1690 ``delay``
1690 ``delay``
1691 Number of seconds (float) before showing the progress bar. (default: 3)
1691 Number of seconds (float) before showing the progress bar. (default: 3)
1692
1692
1693 ``changedelay``
1693 ``changedelay``
1694 Minimum delay before showing a new topic. When set to less than 3 * refresh,
1694 Minimum delay before showing a new topic. When set to less than 3 * refresh,
1695 that value will be used instead. (default: 1)
1695 that value will be used instead. (default: 1)
1696
1696
1697 ``estimateinterval``
1697 ``estimateinterval``
1698 Maximum sampling interval in seconds for speed and estimated time
1698 Maximum sampling interval in seconds for speed and estimated time
1699 calculation. (default: 60)
1699 calculation. (default: 60)
1700
1700
1701 ``refresh``
1701 ``refresh``
1702 Time in seconds between refreshes of the progress bar. (default: 0.1)
1702 Time in seconds between refreshes of the progress bar. (default: 0.1)
1703
1703
1704 ``format``
1704 ``format``
1705 Format of the progress bar.
1705 Format of the progress bar.
1706
1706
1707 Valid entries for the format field are ``topic``, ``bar``, ``number``,
1707 Valid entries for the format field are ``topic``, ``bar``, ``number``,
1708 ``unit``, ``estimate``, ``speed``, and ``item``. ``item`` defaults to the
1708 ``unit``, ``estimate``, ``speed``, and ``item``. ``item`` defaults to the
1709 last 20 characters of the item, but this can be changed by adding either
1709 last 20 characters of the item, but this can be changed by adding either
1710 ``-<num>`` which would take the last num characters, or ``+<num>`` for the
1710 ``-<num>`` which would take the last num characters, or ``+<num>`` for the
1711 first num characters.
1711 first num characters.
1712
1712
1713 (default: topic bar number estimate)
1713 (default: topic bar number estimate)
1714
1714
1715 ``width``
1715 ``width``
1716 If set, the maximum width of the progress information (that is, min(width,
1716 If set, the maximum width of the progress information (that is, min(width,
1717 term width) will be used).
1717 term width) will be used).
1718
1718
1719 ``clear-complete``
1719 ``clear-complete``
1720 Clear the progress bar after it's done. (default: True)
1720 Clear the progress bar after it's done. (default: True)
1721
1721
1722 ``disable``
1722 ``disable``
1723 If true, don't show a progress bar.
1723 If true, don't show a progress bar.
1724
1724
1725 ``assume-tty``
1725 ``assume-tty``
1726 If true, ALWAYS show a progress bar, unless disable is given.
1726 If true, ALWAYS show a progress bar, unless disable is given.
1727
1727
1728 ``rebase``
1728 ``rebase``
1729 ----------
1729 ----------
1730
1730
1731 ``evolution.allowdivergence``
1731 ``evolution.allowdivergence``
1732 Default to False, when True allow creating divergence when performing
1732 Default to False, when True allow creating divergence when performing
1733 rebase of obsolete changesets.
1733 rebase of obsolete changesets.
1734
1734
1735 ``revsetalias``
1735 ``revsetalias``
1736 ---------------
1736 ---------------
1737
1737
1738 Alias definitions for revsets. See :hg:`help revsets` for details.
1738 Alias definitions for revsets. See :hg:`help revsets` for details.
1739
1739
1740 ``server``
1740 ``server``
1741 ----------
1741 ----------
1742
1742
1743 Controls generic server settings.
1743 Controls generic server settings.
1744
1744
1745 ``bookmarks-pushkey-compat``
1745 ``bookmarks-pushkey-compat``
1746 Trigger pushkey hook when being pushed bookmark updates. This config exist
1746 Trigger pushkey hook when being pushed bookmark updates. This config exist
1747 for compatibility purpose (default to True)
1747 for compatibility purpose (default to True)
1748
1748
1749 If you use ``pushkey`` and ``pre-pushkey`` hooks to control bookmark
1749 If you use ``pushkey`` and ``pre-pushkey`` hooks to control bookmark
1750 movement we recommend you migrate them to ``txnclose-bookmark`` and
1750 movement we recommend you migrate them to ``txnclose-bookmark`` and
1751 ``pretxnclose-bookmark``.
1751 ``pretxnclose-bookmark``.
1752
1752
1753 ``compressionengines``
1753 ``compressionengines``
1754 List of compression engines and their relative priority to advertise
1754 List of compression engines and their relative priority to advertise
1755 to clients.
1755 to clients.
1756
1756
1757 The order of compression engines determines their priority, the first
1757 The order of compression engines determines their priority, the first
1758 having the highest priority. If a compression engine is not listed
1758 having the highest priority. If a compression engine is not listed
1759 here, it won't be advertised to clients.
1759 here, it won't be advertised to clients.
1760
1760
1761 If not set (the default), built-in defaults are used. Run
1761 If not set (the default), built-in defaults are used. Run
1762 :hg:`debuginstall` to list available compression engines and their
1762 :hg:`debuginstall` to list available compression engines and their
1763 default wire protocol priority.
1763 default wire protocol priority.
1764
1764
1765 Older Mercurial clients only support zlib compression and this setting
1765 Older Mercurial clients only support zlib compression and this setting
1766 has no effect for legacy clients.
1766 has no effect for legacy clients.
1767
1767
1768 ``uncompressed``
1768 ``uncompressed``
1769 Whether to allow clients to clone a repository using the
1769 Whether to allow clients to clone a repository using the
1770 uncompressed streaming protocol. This transfers about 40% more
1770 uncompressed streaming protocol. This transfers about 40% more
1771 data than a regular clone, but uses less memory and CPU on both
1771 data than a regular clone, but uses less memory and CPU on both
1772 server and client. Over a LAN (100 Mbps or better) or a very fast
1772 server and client. Over a LAN (100 Mbps or better) or a very fast
1773 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
1773 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
1774 regular clone. Over most WAN connections (anything slower than
1774 regular clone. Over most WAN connections (anything slower than
1775 about 6 Mbps), uncompressed streaming is slower, because of the
1775 about 6 Mbps), uncompressed streaming is slower, because of the
1776 extra data transfer overhead. This mode will also temporarily hold
1776 extra data transfer overhead. This mode will also temporarily hold
1777 the write lock while determining what data to transfer.
1777 the write lock while determining what data to transfer.
1778 (default: True)
1778 (default: True)
1779
1779
1780 ``uncompressedallowsecret``
1780 ``uncompressedallowsecret``
1781 Whether to allow stream clones when the repository contains secret
1781 Whether to allow stream clones when the repository contains secret
1782 changesets. (default: False)
1782 changesets. (default: False)
1783
1783
1784 ``preferuncompressed``
1784 ``preferuncompressed``
1785 When set, clients will try to use the uncompressed streaming
1785 When set, clients will try to use the uncompressed streaming
1786 protocol. (default: False)
1786 protocol. (default: False)
1787
1787
1788 ``disablefullbundle``
1788 ``disablefullbundle``
1789 When set, servers will refuse attempts to do pull-based clones.
1789 When set, servers will refuse attempts to do pull-based clones.
1790 If this option is set, ``preferuncompressed`` and/or clone bundles
1790 If this option is set, ``preferuncompressed`` and/or clone bundles
1791 are highly recommended. Partial clones will still be allowed.
1791 are highly recommended. Partial clones will still be allowed.
1792 (default: False)
1792 (default: False)
1793
1793
1794 ``streamunbundle``
1795 When set, servers will apply data sent from the client directly,
1796 otherwise it will be written to a temporary file first. This option
1797 effectively prevents concurrent pushes.
1798
1794 ``concurrent-push-mode``
1799 ``concurrent-push-mode``
1795 Level of allowed race condition between two pushing clients.
1800 Level of allowed race condition between two pushing clients.
1796
1801
1797 - 'strict': push is abort if another client touched the repository
1802 - 'strict': push is abort if another client touched the repository
1798 while the push was preparing. (default)
1803 while the push was preparing. (default)
1799 - 'check-related': push is only aborted if it affects head that got also
1804 - 'check-related': push is only aborted if it affects head that got also
1800 affected while the push was preparing.
1805 affected while the push was preparing.
1801
1806
1802 This requires compatible client (version 4.3 and later). Old client will
1807 This requires compatible client (version 4.3 and later). Old client will
1803 use 'strict'.
1808 use 'strict'.
1804
1809
1805 ``validate``
1810 ``validate``
1806 Whether to validate the completeness of pushed changesets by
1811 Whether to validate the completeness of pushed changesets by
1807 checking that all new file revisions specified in manifests are
1812 checking that all new file revisions specified in manifests are
1808 present. (default: False)
1813 present. (default: False)
1809
1814
1810 ``maxhttpheaderlen``
1815 ``maxhttpheaderlen``
1811 Instruct HTTP clients not to send request headers longer than this
1816 Instruct HTTP clients not to send request headers longer than this
1812 many bytes. (default: 1024)
1817 many bytes. (default: 1024)
1813
1818
1814 ``bundle1``
1819 ``bundle1``
1815 Whether to allow clients to push and pull using the legacy bundle1
1820 Whether to allow clients to push and pull using the legacy bundle1
1816 exchange format. (default: True)
1821 exchange format. (default: True)
1817
1822
1818 ``bundle1gd``
1823 ``bundle1gd``
1819 Like ``bundle1`` but only used if the repository is using the
1824 Like ``bundle1`` but only used if the repository is using the
1820 *generaldelta* storage format. (default: True)
1825 *generaldelta* storage format. (default: True)
1821
1826
1822 ``bundle1.push``
1827 ``bundle1.push``
1823 Whether to allow clients to push using the legacy bundle1 exchange
1828 Whether to allow clients to push using the legacy bundle1 exchange
1824 format. (default: True)
1829 format. (default: True)
1825
1830
1826 ``bundle1gd.push``
1831 ``bundle1gd.push``
1827 Like ``bundle1.push`` but only used if the repository is using the
1832 Like ``bundle1.push`` but only used if the repository is using the
1828 *generaldelta* storage format. (default: True)
1833 *generaldelta* storage format. (default: True)
1829
1834
1830 ``bundle1.pull``
1835 ``bundle1.pull``
1831 Whether to allow clients to pull using the legacy bundle1 exchange
1836 Whether to allow clients to pull using the legacy bundle1 exchange
1832 format. (default: True)
1837 format. (default: True)
1833
1838
1834 ``bundle1gd.pull``
1839 ``bundle1gd.pull``
1835 Like ``bundle1.pull`` but only used if the repository is using the
1840 Like ``bundle1.pull`` but only used if the repository is using the
1836 *generaldelta* storage format. (default: True)
1841 *generaldelta* storage format. (default: True)
1837
1842
1838 Large repositories using the *generaldelta* storage format should
1843 Large repositories using the *generaldelta* storage format should
1839 consider setting this option because converting *generaldelta*
1844 consider setting this option because converting *generaldelta*
1840 repositories to the exchange format required by the bundle1 data
1845 repositories to the exchange format required by the bundle1 data
1841 format can consume a lot of CPU.
1846 format can consume a lot of CPU.
1842
1847
1843 ``zliblevel``
1848 ``zliblevel``
1844 Integer between ``-1`` and ``9`` that controls the zlib compression level
1849 Integer between ``-1`` and ``9`` that controls the zlib compression level
1845 for wire protocol commands that send zlib compressed output (notably the
1850 for wire protocol commands that send zlib compressed output (notably the
1846 commands that send repository history data).
1851 commands that send repository history data).
1847
1852
1848 The default (``-1``) uses the default zlib compression level, which is
1853 The default (``-1``) uses the default zlib compression level, which is
1849 likely equivalent to ``6``. ``0`` means no compression. ``9`` means
1854 likely equivalent to ``6``. ``0`` means no compression. ``9`` means
1850 maximum compression.
1855 maximum compression.
1851
1856
1852 Setting this option allows server operators to make trade-offs between
1857 Setting this option allows server operators to make trade-offs between
1853 bandwidth and CPU used. Lowering the compression lowers CPU utilization
1858 bandwidth and CPU used. Lowering the compression lowers CPU utilization
1854 but sends more bytes to clients.
1859 but sends more bytes to clients.
1855
1860
1856 This option only impacts the HTTP server.
1861 This option only impacts the HTTP server.
1857
1862
1858 ``zstdlevel``
1863 ``zstdlevel``
1859 Integer between ``1`` and ``22`` that controls the zstd compression level
1864 Integer between ``1`` and ``22`` that controls the zstd compression level
1860 for wire protocol commands. ``1`` is the minimal amount of compression and
1865 for wire protocol commands. ``1`` is the minimal amount of compression and
1861 ``22`` is the highest amount of compression.
1866 ``22`` is the highest amount of compression.
1862
1867
1863 The default (``3``) should be significantly faster than zlib while likely
1868 The default (``3``) should be significantly faster than zlib while likely
1864 delivering better compression ratios.
1869 delivering better compression ratios.
1865
1870
1866 This option only impacts the HTTP server.
1871 This option only impacts the HTTP server.
1867
1872
1868 See also ``server.zliblevel``.
1873 See also ``server.zliblevel``.
1869
1874
1870 ``smtp``
1875 ``smtp``
1871 --------
1876 --------
1872
1877
1873 Configuration for extensions that need to send email messages.
1878 Configuration for extensions that need to send email messages.
1874
1879
1875 ``host``
1880 ``host``
1876 Host name of mail server, e.g. "mail.example.com".
1881 Host name of mail server, e.g. "mail.example.com".
1877
1882
1878 ``port``
1883 ``port``
1879 Optional. Port to connect to on mail server. (default: 465 if
1884 Optional. Port to connect to on mail server. (default: 465 if
1880 ``tls`` is smtps; 25 otherwise)
1885 ``tls`` is smtps; 25 otherwise)
1881
1886
1882 ``tls``
1887 ``tls``
1883 Optional. Method to enable TLS when connecting to mail server: starttls,
1888 Optional. Method to enable TLS when connecting to mail server: starttls,
1884 smtps or none. (default: none)
1889 smtps or none. (default: none)
1885
1890
1886 ``username``
1891 ``username``
1887 Optional. User name for authenticating with the SMTP server.
1892 Optional. User name for authenticating with the SMTP server.
1888 (default: None)
1893 (default: None)
1889
1894
1890 ``password``
1895 ``password``
1891 Optional. Password for authenticating with the SMTP server. If not
1896 Optional. Password for authenticating with the SMTP server. If not
1892 specified, interactive sessions will prompt the user for a
1897 specified, interactive sessions will prompt the user for a
1893 password; non-interactive sessions will fail. (default: None)
1898 password; non-interactive sessions will fail. (default: None)
1894
1899
1895 ``local_hostname``
1900 ``local_hostname``
1896 Optional. The hostname that the sender can use to identify
1901 Optional. The hostname that the sender can use to identify
1897 itself to the MTA.
1902 itself to the MTA.
1898
1903
1899
1904
1900 ``subpaths``
1905 ``subpaths``
1901 ------------
1906 ------------
1902
1907
1903 Subrepository source URLs can go stale if a remote server changes name
1908 Subrepository source URLs can go stale if a remote server changes name
1904 or becomes temporarily unavailable. This section lets you define
1909 or becomes temporarily unavailable. This section lets you define
1905 rewrite rules of the form::
1910 rewrite rules of the form::
1906
1911
1907 <pattern> = <replacement>
1912 <pattern> = <replacement>
1908
1913
1909 where ``pattern`` is a regular expression matching a subrepository
1914 where ``pattern`` is a regular expression matching a subrepository
1910 source URL and ``replacement`` is the replacement string used to
1915 source URL and ``replacement`` is the replacement string used to
1911 rewrite it. Groups can be matched in ``pattern`` and referenced in
1916 rewrite it. Groups can be matched in ``pattern`` and referenced in
1912 ``replacements``. For instance::
1917 ``replacements``. For instance::
1913
1918
1914 http://server/(.*)-hg/ = http://hg.server/\1/
1919 http://server/(.*)-hg/ = http://hg.server/\1/
1915
1920
1916 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
1921 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
1917
1922
1918 Relative subrepository paths are first made absolute, and the
1923 Relative subrepository paths are first made absolute, and the
1919 rewrite rules are then applied on the full (absolute) path. If ``pattern``
1924 rewrite rules are then applied on the full (absolute) path. If ``pattern``
1920 doesn't match the full path, an attempt is made to apply it on the
1925 doesn't match the full path, an attempt is made to apply it on the
1921 relative path alone. The rules are applied in definition order.
1926 relative path alone. The rules are applied in definition order.
1922
1927
1923 ``subrepos``
1928 ``subrepos``
1924 ------------
1929 ------------
1925
1930
1926 This section contains options that control the behavior of the
1931 This section contains options that control the behavior of the
1927 subrepositories feature. See also :hg:`help subrepos`.
1932 subrepositories feature. See also :hg:`help subrepos`.
1928
1933
1929 Security note: auditing in Mercurial is known to be insufficient to
1934 Security note: auditing in Mercurial is known to be insufficient to
1930 prevent clone-time code execution with carefully constructed Git
1935 prevent clone-time code execution with carefully constructed Git
1931 subrepos. It is unknown if a similar detect is present in Subversion
1936 subrepos. It is unknown if a similar detect is present in Subversion
1932 subrepos. Both Git and Subversion subrepos are disabled by default
1937 subrepos. Both Git and Subversion subrepos are disabled by default
1933 out of security concerns. These subrepo types can be enabled using
1938 out of security concerns. These subrepo types can be enabled using
1934 the respective options below.
1939 the respective options below.
1935
1940
1936 ``allowed``
1941 ``allowed``
1937 Whether subrepositories are allowed in the working directory.
1942 Whether subrepositories are allowed in the working directory.
1938
1943
1939 When false, commands involving subrepositories (like :hg:`update`)
1944 When false, commands involving subrepositories (like :hg:`update`)
1940 will fail for all subrepository types.
1945 will fail for all subrepository types.
1941 (default: true)
1946 (default: true)
1942
1947
1943 ``hg:allowed``
1948 ``hg:allowed``
1944 Whether Mercurial subrepositories are allowed in the working
1949 Whether Mercurial subrepositories are allowed in the working
1945 directory. This option only has an effect if ``subrepos.allowed``
1950 directory. This option only has an effect if ``subrepos.allowed``
1946 is true.
1951 is true.
1947 (default: true)
1952 (default: true)
1948
1953
1949 ``git:allowed``
1954 ``git:allowed``
1950 Whether Git subrepositories are allowed in the working directory.
1955 Whether Git subrepositories are allowed in the working directory.
1951 This option only has an effect if ``subrepos.allowed`` is true.
1956 This option only has an effect if ``subrepos.allowed`` is true.
1952
1957
1953 See the security note above before enabling Git subrepos.
1958 See the security note above before enabling Git subrepos.
1954 (default: false)
1959 (default: false)
1955
1960
1956 ``svn:allowed``
1961 ``svn:allowed``
1957 Whether Subversion subrepositories are allowed in the working
1962 Whether Subversion subrepositories are allowed in the working
1958 directory. This option only has an effect if ``subrepos.allowed``
1963 directory. This option only has an effect if ``subrepos.allowed``
1959 is true.
1964 is true.
1960
1965
1961 See the security note above before enabling Subversion subrepos.
1966 See the security note above before enabling Subversion subrepos.
1962 (default: false)
1967 (default: false)
1963
1968
1964 ``templatealias``
1969 ``templatealias``
1965 -----------------
1970 -----------------
1966
1971
1967 Alias definitions for templates. See :hg:`help templates` for details.
1972 Alias definitions for templates. See :hg:`help templates` for details.
1968
1973
1969 ``templates``
1974 ``templates``
1970 -------------
1975 -------------
1971
1976
1972 Use the ``[templates]`` section to define template strings.
1977 Use the ``[templates]`` section to define template strings.
1973 See :hg:`help templates` for details.
1978 See :hg:`help templates` for details.
1974
1979
1975 ``trusted``
1980 ``trusted``
1976 -----------
1981 -----------
1977
1982
1978 Mercurial will not use the settings in the
1983 Mercurial will not use the settings in the
1979 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
1984 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
1980 user or to a trusted group, as various hgrc features allow arbitrary
1985 user or to a trusted group, as various hgrc features allow arbitrary
1981 commands to be run. This issue is often encountered when configuring
1986 commands to be run. This issue is often encountered when configuring
1982 hooks or extensions for shared repositories or servers. However,
1987 hooks or extensions for shared repositories or servers. However,
1983 the web interface will use some safe settings from the ``[web]``
1988 the web interface will use some safe settings from the ``[web]``
1984 section.
1989 section.
1985
1990
1986 This section specifies what users and groups are trusted. The
1991 This section specifies what users and groups are trusted. The
1987 current user is always trusted. To trust everybody, list a user or a
1992 current user is always trusted. To trust everybody, list a user or a
1988 group with name ``*``. These settings must be placed in an
1993 group with name ``*``. These settings must be placed in an
1989 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
1994 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
1990 user or service running Mercurial.
1995 user or service running Mercurial.
1991
1996
1992 ``users``
1997 ``users``
1993 Comma-separated list of trusted users.
1998 Comma-separated list of trusted users.
1994
1999
1995 ``groups``
2000 ``groups``
1996 Comma-separated list of trusted groups.
2001 Comma-separated list of trusted groups.
1997
2002
1998
2003
1999 ``ui``
2004 ``ui``
2000 ------
2005 ------
2001
2006
2002 User interface controls.
2007 User interface controls.
2003
2008
2004 ``archivemeta``
2009 ``archivemeta``
2005 Whether to include the .hg_archival.txt file containing meta data
2010 Whether to include the .hg_archival.txt file containing meta data
2006 (hashes for the repository base and for tip) in archives created
2011 (hashes for the repository base and for tip) in archives created
2007 by the :hg:`archive` command or downloaded via hgweb.
2012 by the :hg:`archive` command or downloaded via hgweb.
2008 (default: True)
2013 (default: True)
2009
2014
2010 ``askusername``
2015 ``askusername``
2011 Whether to prompt for a username when committing. If True, and
2016 Whether to prompt for a username when committing. If True, and
2012 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
2017 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
2013 be prompted to enter a username. If no username is entered, the
2018 be prompted to enter a username. If no username is entered, the
2014 default ``USER@HOST`` is used instead.
2019 default ``USER@HOST`` is used instead.
2015 (default: False)
2020 (default: False)
2016
2021
2017 ``clonebundles``
2022 ``clonebundles``
2018 Whether the "clone bundles" feature is enabled.
2023 Whether the "clone bundles" feature is enabled.
2019
2024
2020 When enabled, :hg:`clone` may download and apply a server-advertised
2025 When enabled, :hg:`clone` may download and apply a server-advertised
2021 bundle file from a URL instead of using the normal exchange mechanism.
2026 bundle file from a URL instead of using the normal exchange mechanism.
2022
2027
2023 This can likely result in faster and more reliable clones.
2028 This can likely result in faster and more reliable clones.
2024
2029
2025 (default: True)
2030 (default: True)
2026
2031
2027 ``clonebundlefallback``
2032 ``clonebundlefallback``
2028 Whether failure to apply an advertised "clone bundle" from a server
2033 Whether failure to apply an advertised "clone bundle" from a server
2029 should result in fallback to a regular clone.
2034 should result in fallback to a regular clone.
2030
2035
2031 This is disabled by default because servers advertising "clone
2036 This is disabled by default because servers advertising "clone
2032 bundles" often do so to reduce server load. If advertised bundles
2037 bundles" often do so to reduce server load. If advertised bundles
2033 start mass failing and clients automatically fall back to a regular
2038 start mass failing and clients automatically fall back to a regular
2034 clone, this would add significant and unexpected load to the server
2039 clone, this would add significant and unexpected load to the server
2035 since the server is expecting clone operations to be offloaded to
2040 since the server is expecting clone operations to be offloaded to
2036 pre-generated bundles. Failing fast (the default behavior) ensures
2041 pre-generated bundles. Failing fast (the default behavior) ensures
2037 clients don't overwhelm the server when "clone bundle" application
2042 clients don't overwhelm the server when "clone bundle" application
2038 fails.
2043 fails.
2039
2044
2040 (default: False)
2045 (default: False)
2041
2046
2042 ``clonebundleprefers``
2047 ``clonebundleprefers``
2043 Defines preferences for which "clone bundles" to use.
2048 Defines preferences for which "clone bundles" to use.
2044
2049
2045 Servers advertising "clone bundles" may advertise multiple available
2050 Servers advertising "clone bundles" may advertise multiple available
2046 bundles. Each bundle may have different attributes, such as the bundle
2051 bundles. Each bundle may have different attributes, such as the bundle
2047 type and compression format. This option is used to prefer a particular
2052 type and compression format. This option is used to prefer a particular
2048 bundle over another.
2053 bundle over another.
2049
2054
2050 The following keys are defined by Mercurial:
2055 The following keys are defined by Mercurial:
2051
2056
2052 BUNDLESPEC
2057 BUNDLESPEC
2053 A bundle type specifier. These are strings passed to :hg:`bundle -t`.
2058 A bundle type specifier. These are strings passed to :hg:`bundle -t`.
2054 e.g. ``gzip-v2`` or ``bzip2-v1``.
2059 e.g. ``gzip-v2`` or ``bzip2-v1``.
2055
2060
2056 COMPRESSION
2061 COMPRESSION
2057 The compression format of the bundle. e.g. ``gzip`` and ``bzip2``.
2062 The compression format of the bundle. e.g. ``gzip`` and ``bzip2``.
2058
2063
2059 Server operators may define custom keys.
2064 Server operators may define custom keys.
2060
2065
2061 Example values: ``COMPRESSION=bzip2``,
2066 Example values: ``COMPRESSION=bzip2``,
2062 ``BUNDLESPEC=gzip-v2, COMPRESSION=gzip``.
2067 ``BUNDLESPEC=gzip-v2, COMPRESSION=gzip``.
2063
2068
2064 By default, the first bundle advertised by the server is used.
2069 By default, the first bundle advertised by the server is used.
2065
2070
2066 ``color``
2071 ``color``
2067 When to colorize output. Possible value are Boolean ("yes" or "no"), or
2072 When to colorize output. Possible value are Boolean ("yes" or "no"), or
2068 "debug", or "always". (default: "yes"). "yes" will use color whenever it
2073 "debug", or "always". (default: "yes"). "yes" will use color whenever it
2069 seems possible. See :hg:`help color` for details.
2074 seems possible. See :hg:`help color` for details.
2070
2075
2071 ``commitsubrepos``
2076 ``commitsubrepos``
2072 Whether to commit modified subrepositories when committing the
2077 Whether to commit modified subrepositories when committing the
2073 parent repository. If False and one subrepository has uncommitted
2078 parent repository. If False and one subrepository has uncommitted
2074 changes, abort the commit.
2079 changes, abort the commit.
2075 (default: False)
2080 (default: False)
2076
2081
2077 ``debug``
2082 ``debug``
2078 Print debugging information. (default: False)
2083 Print debugging information. (default: False)
2079
2084
2080 ``editor``
2085 ``editor``
2081 The editor to use during a commit. (default: ``$EDITOR`` or ``vi``)
2086 The editor to use during a commit. (default: ``$EDITOR`` or ``vi``)
2082
2087
2083 ``fallbackencoding``
2088 ``fallbackencoding``
2084 Encoding to try if it's not possible to decode the changelog using
2089 Encoding to try if it's not possible to decode the changelog using
2085 UTF-8. (default: ISO-8859-1)
2090 UTF-8. (default: ISO-8859-1)
2086
2091
2087 ``graphnodetemplate``
2092 ``graphnodetemplate``
2088 The template used to print changeset nodes in an ASCII revision graph.
2093 The template used to print changeset nodes in an ASCII revision graph.
2089 (default: ``{graphnode}``)
2094 (default: ``{graphnode}``)
2090
2095
2091 ``ignore``
2096 ``ignore``
2092 A file to read per-user ignore patterns from. This file should be
2097 A file to read per-user ignore patterns from. This file should be
2093 in the same format as a repository-wide .hgignore file. Filenames
2098 in the same format as a repository-wide .hgignore file. Filenames
2094 are relative to the repository root. This option supports hook syntax,
2099 are relative to the repository root. This option supports hook syntax,
2095 so if you want to specify multiple ignore files, you can do so by
2100 so if you want to specify multiple ignore files, you can do so by
2096 setting something like ``ignore.other = ~/.hgignore2``. For details
2101 setting something like ``ignore.other = ~/.hgignore2``. For details
2097 of the ignore file format, see the ``hgignore(5)`` man page.
2102 of the ignore file format, see the ``hgignore(5)`` man page.
2098
2103
2099 ``interactive``
2104 ``interactive``
2100 Allow to prompt the user. (default: True)
2105 Allow to prompt the user. (default: True)
2101
2106
2102 ``interface``
2107 ``interface``
2103 Select the default interface for interactive features (default: text).
2108 Select the default interface for interactive features (default: text).
2104 Possible values are 'text' and 'curses'.
2109 Possible values are 'text' and 'curses'.
2105
2110
2106 ``interface.chunkselector``
2111 ``interface.chunkselector``
2107 Select the interface for change recording (e.g. :hg:`commit -i`).
2112 Select the interface for change recording (e.g. :hg:`commit -i`).
2108 Possible values are 'text' and 'curses'.
2113 Possible values are 'text' and 'curses'.
2109 This config overrides the interface specified by ui.interface.
2114 This config overrides the interface specified by ui.interface.
2110
2115
2111 ``logtemplate``
2116 ``logtemplate``
2112 Template string for commands that print changesets.
2117 Template string for commands that print changesets.
2113
2118
2114 ``merge``
2119 ``merge``
2115 The conflict resolution program to use during a manual merge.
2120 The conflict resolution program to use during a manual merge.
2116 For more information on merge tools see :hg:`help merge-tools`.
2121 For more information on merge tools see :hg:`help merge-tools`.
2117 For configuring merge tools see the ``[merge-tools]`` section.
2122 For configuring merge tools see the ``[merge-tools]`` section.
2118
2123
2119 ``mergemarkers``
2124 ``mergemarkers``
2120 Sets the merge conflict marker label styling. The ``detailed``
2125 Sets the merge conflict marker label styling. The ``detailed``
2121 style uses the ``mergemarkertemplate`` setting to style the labels.
2126 style uses the ``mergemarkertemplate`` setting to style the labels.
2122 The ``basic`` style just uses 'local' and 'other' as the marker label.
2127 The ``basic`` style just uses 'local' and 'other' as the marker label.
2123 One of ``basic`` or ``detailed``.
2128 One of ``basic`` or ``detailed``.
2124 (default: ``basic``)
2129 (default: ``basic``)
2125
2130
2126 ``mergemarkertemplate``
2131 ``mergemarkertemplate``
2127 The template used to print the commit description next to each conflict
2132 The template used to print the commit description next to each conflict
2128 marker during merge conflicts. See :hg:`help templates` for the template
2133 marker during merge conflicts. See :hg:`help templates` for the template
2129 format.
2134 format.
2130
2135
2131 Defaults to showing the hash, tags, branches, bookmarks, author, and
2136 Defaults to showing the hash, tags, branches, bookmarks, author, and
2132 the first line of the commit description.
2137 the first line of the commit description.
2133
2138
2134 If you use non-ASCII characters in names for tags, branches, bookmarks,
2139 If you use non-ASCII characters in names for tags, branches, bookmarks,
2135 authors, and/or commit descriptions, you must pay attention to encodings of
2140 authors, and/or commit descriptions, you must pay attention to encodings of
2136 managed files. At template expansion, non-ASCII characters use the encoding
2141 managed files. At template expansion, non-ASCII characters use the encoding
2137 specified by the ``--encoding`` global option, ``HGENCODING`` or other
2142 specified by the ``--encoding`` global option, ``HGENCODING`` or other
2138 environment variables that govern your locale. If the encoding of the merge
2143 environment variables that govern your locale. If the encoding of the merge
2139 markers is different from the encoding of the merged files,
2144 markers is different from the encoding of the merged files,
2140 serious problems may occur.
2145 serious problems may occur.
2141
2146
2142 Can be overridden per-merge-tool, see the ``[merge-tools]`` section.
2147 Can be overridden per-merge-tool, see the ``[merge-tools]`` section.
2143
2148
2144 ``origbackuppath``
2149 ``origbackuppath``
2145 The path to a directory used to store generated .orig files. If the path is
2150 The path to a directory used to store generated .orig files. If the path is
2146 not a directory, one will be created. If set, files stored in this
2151 not a directory, one will be created. If set, files stored in this
2147 directory have the same name as the original file and do not have a .orig
2152 directory have the same name as the original file and do not have a .orig
2148 suffix.
2153 suffix.
2149
2154
2150 ``paginate``
2155 ``paginate``
2151 Control the pagination of command output (default: True). See :hg:`help pager`
2156 Control the pagination of command output (default: True). See :hg:`help pager`
2152 for details.
2157 for details.
2153
2158
2154 ``patch``
2159 ``patch``
2155 An optional external tool that ``hg import`` and some extensions
2160 An optional external tool that ``hg import`` and some extensions
2156 will use for applying patches. By default Mercurial uses an
2161 will use for applying patches. By default Mercurial uses an
2157 internal patch utility. The external tool must work as the common
2162 internal patch utility. The external tool must work as the common
2158 Unix ``patch`` program. In particular, it must accept a ``-p``
2163 Unix ``patch`` program. In particular, it must accept a ``-p``
2159 argument to strip patch headers, a ``-d`` argument to specify the
2164 argument to strip patch headers, a ``-d`` argument to specify the
2160 current directory, a file name to patch, and a patch file to take
2165 current directory, a file name to patch, and a patch file to take
2161 from stdin.
2166 from stdin.
2162
2167
2163 It is possible to specify a patch tool together with extra
2168 It is possible to specify a patch tool together with extra
2164 arguments. For example, setting this option to ``patch --merge``
2169 arguments. For example, setting this option to ``patch --merge``
2165 will use the ``patch`` program with its 2-way merge option.
2170 will use the ``patch`` program with its 2-way merge option.
2166
2171
2167 ``portablefilenames``
2172 ``portablefilenames``
2168 Check for portable filenames. Can be ``warn``, ``ignore`` or ``abort``.
2173 Check for portable filenames. Can be ``warn``, ``ignore`` or ``abort``.
2169 (default: ``warn``)
2174 (default: ``warn``)
2170
2175
2171 ``warn``
2176 ``warn``
2172 Print a warning message on POSIX platforms, if a file with a non-portable
2177 Print a warning message on POSIX platforms, if a file with a non-portable
2173 filename is added (e.g. a file with a name that can't be created on
2178 filename is added (e.g. a file with a name that can't be created on
2174 Windows because it contains reserved parts like ``AUX``, reserved
2179 Windows because it contains reserved parts like ``AUX``, reserved
2175 characters like ``:``, or would cause a case collision with an existing
2180 characters like ``:``, or would cause a case collision with an existing
2176 file).
2181 file).
2177
2182
2178 ``ignore``
2183 ``ignore``
2179 Don't print a warning.
2184 Don't print a warning.
2180
2185
2181 ``abort``
2186 ``abort``
2182 The command is aborted.
2187 The command is aborted.
2183
2188
2184 ``true``
2189 ``true``
2185 Alias for ``warn``.
2190 Alias for ``warn``.
2186
2191
2187 ``false``
2192 ``false``
2188 Alias for ``ignore``.
2193 Alias for ``ignore``.
2189
2194
2190 .. container:: windows
2195 .. container:: windows
2191
2196
2192 On Windows, this configuration option is ignored and the command aborted.
2197 On Windows, this configuration option is ignored and the command aborted.
2193
2198
2194 ``quiet``
2199 ``quiet``
2195 Reduce the amount of output printed.
2200 Reduce the amount of output printed.
2196 (default: False)
2201 (default: False)
2197
2202
2198 ``remotecmd``
2203 ``remotecmd``
2199 Remote command to use for clone/push/pull operations.
2204 Remote command to use for clone/push/pull operations.
2200 (default: ``hg``)
2205 (default: ``hg``)
2201
2206
2202 ``report_untrusted``
2207 ``report_untrusted``
2203 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
2208 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
2204 trusted user or group.
2209 trusted user or group.
2205 (default: True)
2210 (default: True)
2206
2211
2207 ``slash``
2212 ``slash``
2208 (Deprecated. Use ``slashpath`` template filter instead.)
2213 (Deprecated. Use ``slashpath`` template filter instead.)
2209
2214
2210 Display paths using a slash (``/``) as the path separator. This
2215 Display paths using a slash (``/``) as the path separator. This
2211 only makes a difference on systems where the default path
2216 only makes a difference on systems where the default path
2212 separator is not the slash character (e.g. Windows uses the
2217 separator is not the slash character (e.g. Windows uses the
2213 backslash character (``\``)).
2218 backslash character (``\``)).
2214 (default: False)
2219 (default: False)
2215
2220
2216 ``statuscopies``
2221 ``statuscopies``
2217 Display copies in the status command.
2222 Display copies in the status command.
2218
2223
2219 ``ssh``
2224 ``ssh``
2220 Command to use for SSH connections. (default: ``ssh``)
2225 Command to use for SSH connections. (default: ``ssh``)
2221
2226
2222 ``ssherrorhint``
2227 ``ssherrorhint``
2223 A hint shown to the user in the case of SSH error (e.g.
2228 A hint shown to the user in the case of SSH error (e.g.
2224 ``Please see http://company/internalwiki/ssh.html``)
2229 ``Please see http://company/internalwiki/ssh.html``)
2225
2230
2226 ``strict``
2231 ``strict``
2227 Require exact command names, instead of allowing unambiguous
2232 Require exact command names, instead of allowing unambiguous
2228 abbreviations. (default: False)
2233 abbreviations. (default: False)
2229
2234
2230 ``style``
2235 ``style``
2231 Name of style to use for command output.
2236 Name of style to use for command output.
2232
2237
2233 ``supportcontact``
2238 ``supportcontact``
2234 A URL where users should report a Mercurial traceback. Use this if you are a
2239 A URL where users should report a Mercurial traceback. Use this if you are a
2235 large organisation with its own Mercurial deployment process and crash
2240 large organisation with its own Mercurial deployment process and crash
2236 reports should be addressed to your internal support.
2241 reports should be addressed to your internal support.
2237
2242
2238 ``textwidth``
2243 ``textwidth``
2239 Maximum width of help text. A longer line generated by ``hg help`` or
2244 Maximum width of help text. A longer line generated by ``hg help`` or
2240 ``hg subcommand --help`` will be broken after white space to get this
2245 ``hg subcommand --help`` will be broken after white space to get this
2241 width or the terminal width, whichever comes first.
2246 width or the terminal width, whichever comes first.
2242 A non-positive value will disable this and the terminal width will be
2247 A non-positive value will disable this and the terminal width will be
2243 used. (default: 78)
2248 used. (default: 78)
2244
2249
2245 ``timeout``
2250 ``timeout``
2246 The timeout used when a lock is held (in seconds), a negative value
2251 The timeout used when a lock is held (in seconds), a negative value
2247 means no timeout. (default: 600)
2252 means no timeout. (default: 600)
2248
2253
2249 ``timeout.warn``
2254 ``timeout.warn``
2250 Time (in seconds) before a warning is printed about held lock. A negative
2255 Time (in seconds) before a warning is printed about held lock. A negative
2251 value means no warning. (default: 0)
2256 value means no warning. (default: 0)
2252
2257
2253 ``traceback``
2258 ``traceback``
2254 Mercurial always prints a traceback when an unknown exception
2259 Mercurial always prints a traceback when an unknown exception
2255 occurs. Setting this to True will make Mercurial print a traceback
2260 occurs. Setting this to True will make Mercurial print a traceback
2256 on all exceptions, even those recognized by Mercurial (such as
2261 on all exceptions, even those recognized by Mercurial (such as
2257 IOError or MemoryError). (default: False)
2262 IOError or MemoryError). (default: False)
2258
2263
2259 ``tweakdefaults``
2264 ``tweakdefaults``
2260
2265
2261 By default Mercurial's behavior changes very little from release
2266 By default Mercurial's behavior changes very little from release
2262 to release, but over time the recommended config settings
2267 to release, but over time the recommended config settings
2263 shift. Enable this config to opt in to get automatic tweaks to
2268 shift. Enable this config to opt in to get automatic tweaks to
2264 Mercurial's behavior over time. This config setting will have no
2269 Mercurial's behavior over time. This config setting will have no
2265 effet if ``HGPLAIN` is set or ``HGPLAINEXCEPT`` is set and does
2270 effet if ``HGPLAIN` is set or ``HGPLAINEXCEPT`` is set and does
2266 not include ``tweakdefaults``. (default: False)
2271 not include ``tweakdefaults``. (default: False)
2267
2272
2268 ``username``
2273 ``username``
2269 The committer of a changeset created when running "commit".
2274 The committer of a changeset created when running "commit".
2270 Typically a person's name and email address, e.g. ``Fred Widget
2275 Typically a person's name and email address, e.g. ``Fred Widget
2271 <fred@example.com>``. Environment variables in the
2276 <fred@example.com>``. Environment variables in the
2272 username are expanded.
2277 username are expanded.
2273
2278
2274 (default: ``$EMAIL`` or ``username@hostname``. If the username in
2279 (default: ``$EMAIL`` or ``username@hostname``. If the username in
2275 hgrc is empty, e.g. if the system admin set ``username =`` in the
2280 hgrc is empty, e.g. if the system admin set ``username =`` in the
2276 system hgrc, it has to be specified manually or in a different
2281 system hgrc, it has to be specified manually or in a different
2277 hgrc file)
2282 hgrc file)
2278
2283
2279 ``verbose``
2284 ``verbose``
2280 Increase the amount of output printed. (default: False)
2285 Increase the amount of output printed. (default: False)
2281
2286
2282
2287
2283 ``web``
2288 ``web``
2284 -------
2289 -------
2285
2290
2286 Web interface configuration. The settings in this section apply to
2291 Web interface configuration. The settings in this section apply to
2287 both the builtin webserver (started by :hg:`serve`) and the script you
2292 both the builtin webserver (started by :hg:`serve`) and the script you
2288 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
2293 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
2289 and WSGI).
2294 and WSGI).
2290
2295
2291 The Mercurial webserver does no authentication (it does not prompt for
2296 The Mercurial webserver does no authentication (it does not prompt for
2292 usernames and passwords to validate *who* users are), but it does do
2297 usernames and passwords to validate *who* users are), but it does do
2293 authorization (it grants or denies access for *authenticated users*
2298 authorization (it grants or denies access for *authenticated users*
2294 based on settings in this section). You must either configure your
2299 based on settings in this section). You must either configure your
2295 webserver to do authentication for you, or disable the authorization
2300 webserver to do authentication for you, or disable the authorization
2296 checks.
2301 checks.
2297
2302
2298 For a quick setup in a trusted environment, e.g., a private LAN, where
2303 For a quick setup in a trusted environment, e.g., a private LAN, where
2299 you want it to accept pushes from anybody, you can use the following
2304 you want it to accept pushes from anybody, you can use the following
2300 command line::
2305 command line::
2301
2306
2302 $ hg --config web.allow-push=* --config web.push_ssl=False serve
2307 $ hg --config web.allow-push=* --config web.push_ssl=False serve
2303
2308
2304 Note that this will allow anybody to push anything to the server and
2309 Note that this will allow anybody to push anything to the server and
2305 that this should not be used for public servers.
2310 that this should not be used for public servers.
2306
2311
2307 The full set of options is:
2312 The full set of options is:
2308
2313
2309 ``accesslog``
2314 ``accesslog``
2310 Where to output the access log. (default: stdout)
2315 Where to output the access log. (default: stdout)
2311
2316
2312 ``address``
2317 ``address``
2313 Interface address to bind to. (default: all)
2318 Interface address to bind to. (default: all)
2314
2319
2315 ``allow_archive``
2320 ``allow_archive``
2316 List of archive format (bz2, gz, zip) allowed for downloading.
2321 List of archive format (bz2, gz, zip) allowed for downloading.
2317 (default: empty)
2322 (default: empty)
2318
2323
2319 ``allowbz2``
2324 ``allowbz2``
2320 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
2325 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
2321 revisions.
2326 revisions.
2322 (default: False)
2327 (default: False)
2323
2328
2324 ``allowgz``
2329 ``allowgz``
2325 (DEPRECATED) Whether to allow .tar.gz downloading of repository
2330 (DEPRECATED) Whether to allow .tar.gz downloading of repository
2326 revisions.
2331 revisions.
2327 (default: False)
2332 (default: False)
2328
2333
2329 ``allow-pull``
2334 ``allow-pull``
2330 Whether to allow pulling from the repository. (default: True)
2335 Whether to allow pulling from the repository. (default: True)
2331
2336
2332 ``allow-push``
2337 ``allow-push``
2333 Whether to allow pushing to the repository. If empty or not set,
2338 Whether to allow pushing to the repository. If empty or not set,
2334 pushing is not allowed. If the special value ``*``, any remote
2339 pushing is not allowed. If the special value ``*``, any remote
2335 user can push, including unauthenticated users. Otherwise, the
2340 user can push, including unauthenticated users. Otherwise, the
2336 remote user must have been authenticated, and the authenticated
2341 remote user must have been authenticated, and the authenticated
2337 user name must be present in this list. The contents of the
2342 user name must be present in this list. The contents of the
2338 allow-push list are examined after the deny_push list.
2343 allow-push list are examined after the deny_push list.
2339
2344
2340 ``allow_read``
2345 ``allow_read``
2341 If the user has not already been denied repository access due to
2346 If the user has not already been denied repository access due to
2342 the contents of deny_read, this list determines whether to grant
2347 the contents of deny_read, this list determines whether to grant
2343 repository access to the user. If this list is not empty, and the
2348 repository access to the user. If this list is not empty, and the
2344 user is unauthenticated or not present in the list, then access is
2349 user is unauthenticated or not present in the list, then access is
2345 denied for the user. If the list is empty or not set, then access
2350 denied for the user. If the list is empty or not set, then access
2346 is permitted to all users by default. Setting allow_read to the
2351 is permitted to all users by default. Setting allow_read to the
2347 special value ``*`` is equivalent to it not being set (i.e. access
2352 special value ``*`` is equivalent to it not being set (i.e. access
2348 is permitted to all users). The contents of the allow_read list are
2353 is permitted to all users). The contents of the allow_read list are
2349 examined after the deny_read list.
2354 examined after the deny_read list.
2350
2355
2351 ``allowzip``
2356 ``allowzip``
2352 (DEPRECATED) Whether to allow .zip downloading of repository
2357 (DEPRECATED) Whether to allow .zip downloading of repository
2353 revisions. This feature creates temporary files.
2358 revisions. This feature creates temporary files.
2354 (default: False)
2359 (default: False)
2355
2360
2356 ``archivesubrepos``
2361 ``archivesubrepos``
2357 Whether to recurse into subrepositories when archiving.
2362 Whether to recurse into subrepositories when archiving.
2358 (default: False)
2363 (default: False)
2359
2364
2360 ``baseurl``
2365 ``baseurl``
2361 Base URL to use when publishing URLs in other locations, so
2366 Base URL to use when publishing URLs in other locations, so
2362 third-party tools like email notification hooks can construct
2367 third-party tools like email notification hooks can construct
2363 URLs. Example: ``http://hgserver/repos/``.
2368 URLs. Example: ``http://hgserver/repos/``.
2364
2369
2365 ``cacerts``
2370 ``cacerts``
2366 Path to file containing a list of PEM encoded certificate
2371 Path to file containing a list of PEM encoded certificate
2367 authority certificates. Environment variables and ``~user``
2372 authority certificates. Environment variables and ``~user``
2368 constructs are expanded in the filename. If specified on the
2373 constructs are expanded in the filename. If specified on the
2369 client, then it will verify the identity of remote HTTPS servers
2374 client, then it will verify the identity of remote HTTPS servers
2370 with these certificates.
2375 with these certificates.
2371
2376
2372 To disable SSL verification temporarily, specify ``--insecure`` from
2377 To disable SSL verification temporarily, specify ``--insecure`` from
2373 command line.
2378 command line.
2374
2379
2375 You can use OpenSSL's CA certificate file if your platform has
2380 You can use OpenSSL's CA certificate file if your platform has
2376 one. On most Linux systems this will be
2381 one. On most Linux systems this will be
2377 ``/etc/ssl/certs/ca-certificates.crt``. Otherwise you will have to
2382 ``/etc/ssl/certs/ca-certificates.crt``. Otherwise you will have to
2378 generate this file manually. The form must be as follows::
2383 generate this file manually. The form must be as follows::
2379
2384
2380 -----BEGIN CERTIFICATE-----
2385 -----BEGIN CERTIFICATE-----
2381 ... (certificate in base64 PEM encoding) ...
2386 ... (certificate in base64 PEM encoding) ...
2382 -----END CERTIFICATE-----
2387 -----END CERTIFICATE-----
2383 -----BEGIN CERTIFICATE-----
2388 -----BEGIN CERTIFICATE-----
2384 ... (certificate in base64 PEM encoding) ...
2389 ... (certificate in base64 PEM encoding) ...
2385 -----END CERTIFICATE-----
2390 -----END CERTIFICATE-----
2386
2391
2387 ``cache``
2392 ``cache``
2388 Whether to support caching in hgweb. (default: True)
2393 Whether to support caching in hgweb. (default: True)
2389
2394
2390 ``certificate``
2395 ``certificate``
2391 Certificate to use when running :hg:`serve`.
2396 Certificate to use when running :hg:`serve`.
2392
2397
2393 ``collapse``
2398 ``collapse``
2394 With ``descend`` enabled, repositories in subdirectories are shown at
2399 With ``descend`` enabled, repositories in subdirectories are shown at
2395 a single level alongside repositories in the current path. With
2400 a single level alongside repositories in the current path. With
2396 ``collapse`` also enabled, repositories residing at a deeper level than
2401 ``collapse`` also enabled, repositories residing at a deeper level than
2397 the current path are grouped behind navigable directory entries that
2402 the current path are grouped behind navigable directory entries that
2398 lead to the locations of these repositories. In effect, this setting
2403 lead to the locations of these repositories. In effect, this setting
2399 collapses each collection of repositories found within a subdirectory
2404 collapses each collection of repositories found within a subdirectory
2400 into a single entry for that subdirectory. (default: False)
2405 into a single entry for that subdirectory. (default: False)
2401
2406
2402 ``comparisoncontext``
2407 ``comparisoncontext``
2403 Number of lines of context to show in side-by-side file comparison. If
2408 Number of lines of context to show in side-by-side file comparison. If
2404 negative or the value ``full``, whole files are shown. (default: 5)
2409 negative or the value ``full``, whole files are shown. (default: 5)
2405
2410
2406 This setting can be overridden by a ``context`` request parameter to the
2411 This setting can be overridden by a ``context`` request parameter to the
2407 ``comparison`` command, taking the same values.
2412 ``comparison`` command, taking the same values.
2408
2413
2409 ``contact``
2414 ``contact``
2410 Name or email address of the person in charge of the repository.
2415 Name or email address of the person in charge of the repository.
2411 (default: ui.username or ``$EMAIL`` or "unknown" if unset or empty)
2416 (default: ui.username or ``$EMAIL`` or "unknown" if unset or empty)
2412
2417
2413 ``csp``
2418 ``csp``
2414 Send a ``Content-Security-Policy`` HTTP header with this value.
2419 Send a ``Content-Security-Policy`` HTTP header with this value.
2415
2420
2416 The value may contain a special string ``%nonce%``, which will be replaced
2421 The value may contain a special string ``%nonce%``, which will be replaced
2417 by a randomly-generated one-time use value. If the value contains
2422 by a randomly-generated one-time use value. If the value contains
2418 ``%nonce%``, ``web.cache`` will be disabled, as caching undermines the
2423 ``%nonce%``, ``web.cache`` will be disabled, as caching undermines the
2419 one-time property of the nonce. This nonce will also be inserted into
2424 one-time property of the nonce. This nonce will also be inserted into
2420 ``<script>`` elements containing inline JavaScript.
2425 ``<script>`` elements containing inline JavaScript.
2421
2426
2422 Note: lots of HTML content sent by the server is derived from repository
2427 Note: lots of HTML content sent by the server is derived from repository
2423 data. Please consider the potential for malicious repository data to
2428 data. Please consider the potential for malicious repository data to
2424 "inject" itself into generated HTML content as part of your security
2429 "inject" itself into generated HTML content as part of your security
2425 threat model.
2430 threat model.
2426
2431
2427 ``deny_push``
2432 ``deny_push``
2428 Whether to deny pushing to the repository. If empty or not set,
2433 Whether to deny pushing to the repository. If empty or not set,
2429 push is not denied. If the special value ``*``, all remote users are
2434 push is not denied. If the special value ``*``, all remote users are
2430 denied push. Otherwise, unauthenticated users are all denied, and
2435 denied push. Otherwise, unauthenticated users are all denied, and
2431 any authenticated user name present in this list is also denied. The
2436 any authenticated user name present in this list is also denied. The
2432 contents of the deny_push list are examined before the allow-push list.
2437 contents of the deny_push list are examined before the allow-push list.
2433
2438
2434 ``deny_read``
2439 ``deny_read``
2435 Whether to deny reading/viewing of the repository. If this list is
2440 Whether to deny reading/viewing of the repository. If this list is
2436 not empty, unauthenticated users are all denied, and any
2441 not empty, unauthenticated users are all denied, and any
2437 authenticated user name present in this list is also denied access to
2442 authenticated user name present in this list is also denied access to
2438 the repository. If set to the special value ``*``, all remote users
2443 the repository. If set to the special value ``*``, all remote users
2439 are denied access (rarely needed ;). If deny_read is empty or not set,
2444 are denied access (rarely needed ;). If deny_read is empty or not set,
2440 the determination of repository access depends on the presence and
2445 the determination of repository access depends on the presence and
2441 content of the allow_read list (see description). If both
2446 content of the allow_read list (see description). If both
2442 deny_read and allow_read are empty or not set, then access is
2447 deny_read and allow_read are empty or not set, then access is
2443 permitted to all users by default. If the repository is being
2448 permitted to all users by default. If the repository is being
2444 served via hgwebdir, denied users will not be able to see it in
2449 served via hgwebdir, denied users will not be able to see it in
2445 the list of repositories. The contents of the deny_read list have
2450 the list of repositories. The contents of the deny_read list have
2446 priority over (are examined before) the contents of the allow_read
2451 priority over (are examined before) the contents of the allow_read
2447 list.
2452 list.
2448
2453
2449 ``descend``
2454 ``descend``
2450 hgwebdir indexes will not descend into subdirectories. Only repositories
2455 hgwebdir indexes will not descend into subdirectories. Only repositories
2451 directly in the current path will be shown (other repositories are still
2456 directly in the current path will be shown (other repositories are still
2452 available from the index corresponding to their containing path).
2457 available from the index corresponding to their containing path).
2453
2458
2454 ``description``
2459 ``description``
2455 Textual description of the repository's purpose or contents.
2460 Textual description of the repository's purpose or contents.
2456 (default: "unknown")
2461 (default: "unknown")
2457
2462
2458 ``encoding``
2463 ``encoding``
2459 Character encoding name. (default: the current locale charset)
2464 Character encoding name. (default: the current locale charset)
2460 Example: "UTF-8".
2465 Example: "UTF-8".
2461
2466
2462 ``errorlog``
2467 ``errorlog``
2463 Where to output the error log. (default: stderr)
2468 Where to output the error log. (default: stderr)
2464
2469
2465 ``guessmime``
2470 ``guessmime``
2466 Control MIME types for raw download of file content.
2471 Control MIME types for raw download of file content.
2467 Set to True to let hgweb guess the content type from the file
2472 Set to True to let hgweb guess the content type from the file
2468 extension. This will serve HTML files as ``text/html`` and might
2473 extension. This will serve HTML files as ``text/html`` and might
2469 allow cross-site scripting attacks when serving untrusted
2474 allow cross-site scripting attacks when serving untrusted
2470 repositories. (default: False)
2475 repositories. (default: False)
2471
2476
2472 ``hidden``
2477 ``hidden``
2473 Whether to hide the repository in the hgwebdir index.
2478 Whether to hide the repository in the hgwebdir index.
2474 (default: False)
2479 (default: False)
2475
2480
2476 ``ipv6``
2481 ``ipv6``
2477 Whether to use IPv6. (default: False)
2482 Whether to use IPv6. (default: False)
2478
2483
2479 ``labels``
2484 ``labels``
2480 List of string *labels* associated with the repository.
2485 List of string *labels* associated with the repository.
2481
2486
2482 Labels are exposed as a template keyword and can be used to customize
2487 Labels are exposed as a template keyword and can be used to customize
2483 output. e.g. the ``index`` template can group or filter repositories
2488 output. e.g. the ``index`` template can group or filter repositories
2484 by labels and the ``summary`` template can display additional content
2489 by labels and the ``summary`` template can display additional content
2485 if a specific label is present.
2490 if a specific label is present.
2486
2491
2487 ``logoimg``
2492 ``logoimg``
2488 File name of the logo image that some templates display on each page.
2493 File name of the logo image that some templates display on each page.
2489 The file name is relative to ``staticurl``. That is, the full path to
2494 The file name is relative to ``staticurl``. That is, the full path to
2490 the logo image is "staticurl/logoimg".
2495 the logo image is "staticurl/logoimg".
2491 If unset, ``hglogo.png`` will be used.
2496 If unset, ``hglogo.png`` will be used.
2492
2497
2493 ``logourl``
2498 ``logourl``
2494 Base URL to use for logos. If unset, ``https://mercurial-scm.org/``
2499 Base URL to use for logos. If unset, ``https://mercurial-scm.org/``
2495 will be used.
2500 will be used.
2496
2501
2497 ``maxchanges``
2502 ``maxchanges``
2498 Maximum number of changes to list on the changelog. (default: 10)
2503 Maximum number of changes to list on the changelog. (default: 10)
2499
2504
2500 ``maxfiles``
2505 ``maxfiles``
2501 Maximum number of files to list per changeset. (default: 10)
2506 Maximum number of files to list per changeset. (default: 10)
2502
2507
2503 ``maxshortchanges``
2508 ``maxshortchanges``
2504 Maximum number of changes to list on the shortlog, graph or filelog
2509 Maximum number of changes to list on the shortlog, graph or filelog
2505 pages. (default: 60)
2510 pages. (default: 60)
2506
2511
2507 ``name``
2512 ``name``
2508 Repository name to use in the web interface.
2513 Repository name to use in the web interface.
2509 (default: current working directory)
2514 (default: current working directory)
2510
2515
2511 ``port``
2516 ``port``
2512 Port to listen on. (default: 8000)
2517 Port to listen on. (default: 8000)
2513
2518
2514 ``prefix``
2519 ``prefix``
2515 Prefix path to serve from. (default: '' (server root))
2520 Prefix path to serve from. (default: '' (server root))
2516
2521
2517 ``push_ssl``
2522 ``push_ssl``
2518 Whether to require that inbound pushes be transported over SSL to
2523 Whether to require that inbound pushes be transported over SSL to
2519 prevent password sniffing. (default: True)
2524 prevent password sniffing. (default: True)
2520
2525
2521 ``refreshinterval``
2526 ``refreshinterval``
2522 How frequently directory listings re-scan the filesystem for new
2527 How frequently directory listings re-scan the filesystem for new
2523 repositories, in seconds. This is relevant when wildcards are used
2528 repositories, in seconds. This is relevant when wildcards are used
2524 to define paths. Depending on how much filesystem traversal is
2529 to define paths. Depending on how much filesystem traversal is
2525 required, refreshing may negatively impact performance.
2530 required, refreshing may negatively impact performance.
2526
2531
2527 Values less than or equal to 0 always refresh.
2532 Values less than or equal to 0 always refresh.
2528 (default: 20)
2533 (default: 20)
2529
2534
2530 ``server-header``
2535 ``server-header``
2531 Value for HTTP ``Server`` response header.
2536 Value for HTTP ``Server`` response header.
2532
2537
2533 ``staticurl``
2538 ``staticurl``
2534 Base URL to use for static files. If unset, static files (e.g. the
2539 Base URL to use for static files. If unset, static files (e.g. the
2535 hgicon.png favicon) will be served by the CGI script itself. Use
2540 hgicon.png favicon) will be served by the CGI script itself. Use
2536 this setting to serve them directly with the HTTP server.
2541 this setting to serve them directly with the HTTP server.
2537 Example: ``http://hgserver/static/``.
2542 Example: ``http://hgserver/static/``.
2538
2543
2539 ``stripes``
2544 ``stripes``
2540 How many lines a "zebra stripe" should span in multi-line output.
2545 How many lines a "zebra stripe" should span in multi-line output.
2541 Set to 0 to disable. (default: 1)
2546 Set to 0 to disable. (default: 1)
2542
2547
2543 ``style``
2548 ``style``
2544 Which template map style to use. The available options are the names of
2549 Which template map style to use. The available options are the names of
2545 subdirectories in the HTML templates path. (default: ``paper``)
2550 subdirectories in the HTML templates path. (default: ``paper``)
2546 Example: ``monoblue``.
2551 Example: ``monoblue``.
2547
2552
2548 ``templates``
2553 ``templates``
2549 Where to find the HTML templates. The default path to the HTML templates
2554 Where to find the HTML templates. The default path to the HTML templates
2550 can be obtained from ``hg debuginstall``.
2555 can be obtained from ``hg debuginstall``.
2551
2556
2552 ``websub``
2557 ``websub``
2553 ----------
2558 ----------
2554
2559
2555 Web substitution filter definition. You can use this section to
2560 Web substitution filter definition. You can use this section to
2556 define a set of regular expression substitution patterns which
2561 define a set of regular expression substitution patterns which
2557 let you automatically modify the hgweb server output.
2562 let you automatically modify the hgweb server output.
2558
2563
2559 The default hgweb templates only apply these substitution patterns
2564 The default hgweb templates only apply these substitution patterns
2560 on the revision description fields. You can apply them anywhere
2565 on the revision description fields. You can apply them anywhere
2561 you want when you create your own templates by adding calls to the
2566 you want when you create your own templates by adding calls to the
2562 "websub" filter (usually after calling the "escape" filter).
2567 "websub" filter (usually after calling the "escape" filter).
2563
2568
2564 This can be used, for example, to convert issue references to links
2569 This can be used, for example, to convert issue references to links
2565 to your issue tracker, or to convert "markdown-like" syntax into
2570 to your issue tracker, or to convert "markdown-like" syntax into
2566 HTML (see the examples below).
2571 HTML (see the examples below).
2567
2572
2568 Each entry in this section names a substitution filter.
2573 Each entry in this section names a substitution filter.
2569 The value of each entry defines the substitution expression itself.
2574 The value of each entry defines the substitution expression itself.
2570 The websub expressions follow the old interhg extension syntax,
2575 The websub expressions follow the old interhg extension syntax,
2571 which in turn imitates the Unix sed replacement syntax::
2576 which in turn imitates the Unix sed replacement syntax::
2572
2577
2573 patternname = s/SEARCH_REGEX/REPLACE_EXPRESSION/[i]
2578 patternname = s/SEARCH_REGEX/REPLACE_EXPRESSION/[i]
2574
2579
2575 You can use any separator other than "/". The final "i" is optional
2580 You can use any separator other than "/". The final "i" is optional
2576 and indicates that the search must be case insensitive.
2581 and indicates that the search must be case insensitive.
2577
2582
2578 Examples::
2583 Examples::
2579
2584
2580 [websub]
2585 [websub]
2581 issues = s|issue(\d+)|<a href="http://bts.example.org/issue\1">issue\1</a>|i
2586 issues = s|issue(\d+)|<a href="http://bts.example.org/issue\1">issue\1</a>|i
2582 italic = s/\b_(\S+)_\b/<i>\1<\/i>/
2587 italic = s/\b_(\S+)_\b/<i>\1<\/i>/
2583 bold = s/\*\b(\S+)\b\*/<b>\1<\/b>/
2588 bold = s/\*\b(\S+)\b\*/<b>\1<\/b>/
2584
2589
2585 ``worker``
2590 ``worker``
2586 ----------
2591 ----------
2587
2592
2588 Parallel master/worker configuration. We currently perform working
2593 Parallel master/worker configuration. We currently perform working
2589 directory updates in parallel on Unix-like systems, which greatly
2594 directory updates in parallel on Unix-like systems, which greatly
2590 helps performance.
2595 helps performance.
2591
2596
2592 ``enabled``
2597 ``enabled``
2593 Whether to enable workers code to be used.
2598 Whether to enable workers code to be used.
2594 (default: true)
2599 (default: true)
2595
2600
2596 ``numcpus``
2601 ``numcpus``
2597 Number of CPUs to use for parallel operations. A zero or
2602 Number of CPUs to use for parallel operations. A zero or
2598 negative value is treated as ``use the default``.
2603 negative value is treated as ``use the default``.
2599 (default: 4 or the number of CPUs on the system, whichever is larger)
2604 (default: 4 or the number of CPUs on the system, whichever is larger)
2600
2605
2601 ``backgroundclose``
2606 ``backgroundclose``
2602 Whether to enable closing file handles on background threads during certain
2607 Whether to enable closing file handles on background threads during certain
2603 operations. Some platforms aren't very efficient at closing file
2608 operations. Some platforms aren't very efficient at closing file
2604 handles that have been written or appended to. By performing file closing
2609 handles that have been written or appended to. By performing file closing
2605 on background threads, file write rate can increase substantially.
2610 on background threads, file write rate can increase substantially.
2606 (default: true on Windows, false elsewhere)
2611 (default: true on Windows, false elsewhere)
2607
2612
2608 ``backgroundcloseminfilecount``
2613 ``backgroundcloseminfilecount``
2609 Minimum number of files required to trigger background file closing.
2614 Minimum number of files required to trigger background file closing.
2610 Operations not writing this many files won't start background close
2615 Operations not writing this many files won't start background close
2611 threads.
2616 threads.
2612 (default: 2048)
2617 (default: 2048)
2613
2618
2614 ``backgroundclosemaxqueue``
2619 ``backgroundclosemaxqueue``
2615 The maximum number of opened file handles waiting to be closed in the
2620 The maximum number of opened file handles waiting to be closed in the
2616 background. This option only has an effect if ``backgroundclose`` is
2621 background. This option only has an effect if ``backgroundclose`` is
2617 enabled.
2622 enabled.
2618 (default: 384)
2623 (default: 384)
2619
2624
2620 ``backgroundclosethreadcount``
2625 ``backgroundclosethreadcount``
2621 Number of threads to process background file closes. Only relevant if
2626 Number of threads to process background file closes. Only relevant if
2622 ``backgroundclose`` is enabled.
2627 ``backgroundclose`` is enabled.
2623 (default: 4)
2628 (default: 4)
@@ -1,1181 +1,1199 b''
1 # wireproto.py - generic wire protocol support functions
1 # wireproto.py - generic wire protocol support functions
2 #
2 #
3 # Copyright 2005-2010 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2010 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import hashlib
10 import hashlib
11 import os
11 import os
12 import tempfile
12 import tempfile
13
13
14 from .i18n import _
14 from .i18n import _
15 from .node import (
15 from .node import (
16 bin,
16 bin,
17 hex,
17 hex,
18 nullid,
18 nullid,
19 )
19 )
20
20
21 from . import (
21 from . import (
22 bundle2,
22 bundle2,
23 changegroup as changegroupmod,
23 changegroup as changegroupmod,
24 discovery,
24 discovery,
25 encoding,
25 encoding,
26 error,
26 error,
27 exchange,
27 exchange,
28 peer,
28 peer,
29 pushkey as pushkeymod,
29 pushkey as pushkeymod,
30 pycompat,
30 pycompat,
31 repository,
31 repository,
32 streamclone,
32 streamclone,
33 util,
33 util,
34 wireprototypes,
34 wireprototypes,
35 )
35 )
36
36
37 from .utils import (
37 from .utils import (
38 procutil,
38 procutil,
39 stringutil,
39 stringutil,
40 )
40 )
41
41
42 urlerr = util.urlerr
42 urlerr = util.urlerr
43 urlreq = util.urlreq
43 urlreq = util.urlreq
44
44
45 bundle2requiredmain = _('incompatible Mercurial client; bundle2 required')
45 bundle2requiredmain = _('incompatible Mercurial client; bundle2 required')
46 bundle2requiredhint = _('see https://www.mercurial-scm.org/wiki/'
46 bundle2requiredhint = _('see https://www.mercurial-scm.org/wiki/'
47 'IncompatibleClient')
47 'IncompatibleClient')
48 bundle2required = '%s\n(%s)\n' % (bundle2requiredmain, bundle2requiredhint)
48 bundle2required = '%s\n(%s)\n' % (bundle2requiredmain, bundle2requiredhint)
49
49
50 class remoteiterbatcher(peer.iterbatcher):
50 class remoteiterbatcher(peer.iterbatcher):
51 def __init__(self, remote):
51 def __init__(self, remote):
52 super(remoteiterbatcher, self).__init__()
52 super(remoteiterbatcher, self).__init__()
53 self._remote = remote
53 self._remote = remote
54
54
55 def __getattr__(self, name):
55 def __getattr__(self, name):
56 # Validate this method is batchable, since submit() only supports
56 # Validate this method is batchable, since submit() only supports
57 # batchable methods.
57 # batchable methods.
58 fn = getattr(self._remote, name)
58 fn = getattr(self._remote, name)
59 if not getattr(fn, 'batchable', None):
59 if not getattr(fn, 'batchable', None):
60 raise error.ProgrammingError('Attempted to batch a non-batchable '
60 raise error.ProgrammingError('Attempted to batch a non-batchable '
61 'call to %r' % name)
61 'call to %r' % name)
62
62
63 return super(remoteiterbatcher, self).__getattr__(name)
63 return super(remoteiterbatcher, self).__getattr__(name)
64
64
65 def submit(self):
65 def submit(self):
66 """Break the batch request into many patch calls and pipeline them.
66 """Break the batch request into many patch calls and pipeline them.
67
67
68 This is mostly valuable over http where request sizes can be
68 This is mostly valuable over http where request sizes can be
69 limited, but can be used in other places as well.
69 limited, but can be used in other places as well.
70 """
70 """
71 # 2-tuple of (command, arguments) that represents what will be
71 # 2-tuple of (command, arguments) that represents what will be
72 # sent over the wire.
72 # sent over the wire.
73 requests = []
73 requests = []
74
74
75 # 4-tuple of (command, final future, @batchable generator, remote
75 # 4-tuple of (command, final future, @batchable generator, remote
76 # future).
76 # future).
77 results = []
77 results = []
78
78
79 for command, args, opts, finalfuture in self.calls:
79 for command, args, opts, finalfuture in self.calls:
80 mtd = getattr(self._remote, command)
80 mtd = getattr(self._remote, command)
81 batchable = mtd.batchable(mtd.__self__, *args, **opts)
81 batchable = mtd.batchable(mtd.__self__, *args, **opts)
82
82
83 commandargs, fremote = next(batchable)
83 commandargs, fremote = next(batchable)
84 assert fremote
84 assert fremote
85 requests.append((command, commandargs))
85 requests.append((command, commandargs))
86 results.append((command, finalfuture, batchable, fremote))
86 results.append((command, finalfuture, batchable, fremote))
87
87
88 if requests:
88 if requests:
89 self._resultiter = self._remote._submitbatch(requests)
89 self._resultiter = self._remote._submitbatch(requests)
90
90
91 self._results = results
91 self._results = results
92
92
93 def results(self):
93 def results(self):
94 for command, finalfuture, batchable, remotefuture in self._results:
94 for command, finalfuture, batchable, remotefuture in self._results:
95 # Get the raw result, set it in the remote future, feed it
95 # Get the raw result, set it in the remote future, feed it
96 # back into the @batchable generator so it can be decoded, and
96 # back into the @batchable generator so it can be decoded, and
97 # set the result on the final future to this value.
97 # set the result on the final future to this value.
98 remoteresult = next(self._resultiter)
98 remoteresult = next(self._resultiter)
99 remotefuture.set(remoteresult)
99 remotefuture.set(remoteresult)
100 finalfuture.set(next(batchable))
100 finalfuture.set(next(batchable))
101
101
102 # Verify our @batchable generators only emit 2 values.
102 # Verify our @batchable generators only emit 2 values.
103 try:
103 try:
104 next(batchable)
104 next(batchable)
105 except StopIteration:
105 except StopIteration:
106 pass
106 pass
107 else:
107 else:
108 raise error.ProgrammingError('%s @batchable generator emitted '
108 raise error.ProgrammingError('%s @batchable generator emitted '
109 'unexpected value count' % command)
109 'unexpected value count' % command)
110
110
111 yield finalfuture.value
111 yield finalfuture.value
112
112
113 # Forward a couple of names from peer to make wireproto interactions
113 # Forward a couple of names from peer to make wireproto interactions
114 # slightly more sensible.
114 # slightly more sensible.
115 batchable = peer.batchable
115 batchable = peer.batchable
116 future = peer.future
116 future = peer.future
117
117
118 # list of nodes encoding / decoding
118 # list of nodes encoding / decoding
119
119
120 def decodelist(l, sep=' '):
120 def decodelist(l, sep=' '):
121 if l:
121 if l:
122 return [bin(v) for v in l.split(sep)]
122 return [bin(v) for v in l.split(sep)]
123 return []
123 return []
124
124
125 def encodelist(l, sep=' '):
125 def encodelist(l, sep=' '):
126 try:
126 try:
127 return sep.join(map(hex, l))
127 return sep.join(map(hex, l))
128 except TypeError:
128 except TypeError:
129 raise
129 raise
130
130
131 # batched call argument encoding
131 # batched call argument encoding
132
132
133 def escapearg(plain):
133 def escapearg(plain):
134 return (plain
134 return (plain
135 .replace(':', ':c')
135 .replace(':', ':c')
136 .replace(',', ':o')
136 .replace(',', ':o')
137 .replace(';', ':s')
137 .replace(';', ':s')
138 .replace('=', ':e'))
138 .replace('=', ':e'))
139
139
140 def unescapearg(escaped):
140 def unescapearg(escaped):
141 return (escaped
141 return (escaped
142 .replace(':e', '=')
142 .replace(':e', '=')
143 .replace(':s', ';')
143 .replace(':s', ';')
144 .replace(':o', ',')
144 .replace(':o', ',')
145 .replace(':c', ':'))
145 .replace(':c', ':'))
146
146
147 def encodebatchcmds(req):
147 def encodebatchcmds(req):
148 """Return a ``cmds`` argument value for the ``batch`` command."""
148 """Return a ``cmds`` argument value for the ``batch`` command."""
149 cmds = []
149 cmds = []
150 for op, argsdict in req:
150 for op, argsdict in req:
151 # Old servers didn't properly unescape argument names. So prevent
151 # Old servers didn't properly unescape argument names. So prevent
152 # the sending of argument names that may not be decoded properly by
152 # the sending of argument names that may not be decoded properly by
153 # servers.
153 # servers.
154 assert all(escapearg(k) == k for k in argsdict)
154 assert all(escapearg(k) == k for k in argsdict)
155
155
156 args = ','.join('%s=%s' % (escapearg(k), escapearg(v))
156 args = ','.join('%s=%s' % (escapearg(k), escapearg(v))
157 for k, v in argsdict.iteritems())
157 for k, v in argsdict.iteritems())
158 cmds.append('%s %s' % (op, args))
158 cmds.append('%s %s' % (op, args))
159
159
160 return ';'.join(cmds)
160 return ';'.join(cmds)
161
161
162 def clientcompressionsupport(proto):
162 def clientcompressionsupport(proto):
163 """Returns a list of compression methods supported by the client.
163 """Returns a list of compression methods supported by the client.
164
164
165 Returns a list of the compression methods supported by the client
165 Returns a list of the compression methods supported by the client
166 according to the protocol capabilities. If no such capability has
166 according to the protocol capabilities. If no such capability has
167 been announced, fallback to the default of zlib and uncompressed.
167 been announced, fallback to the default of zlib and uncompressed.
168 """
168 """
169 for cap in proto.getprotocaps():
169 for cap in proto.getprotocaps():
170 if cap.startswith('comp='):
170 if cap.startswith('comp='):
171 return cap[5:].split(',')
171 return cap[5:].split(',')
172 return ['zlib', 'none']
172 return ['zlib', 'none']
173
173
174 # mapping of options accepted by getbundle and their types
174 # mapping of options accepted by getbundle and their types
175 #
175 #
176 # Meant to be extended by extensions. It is extensions responsibility to ensure
176 # Meant to be extended by extensions. It is extensions responsibility to ensure
177 # such options are properly processed in exchange.getbundle.
177 # such options are properly processed in exchange.getbundle.
178 #
178 #
179 # supported types are:
179 # supported types are:
180 #
180 #
181 # :nodes: list of binary nodes
181 # :nodes: list of binary nodes
182 # :csv: list of comma-separated values
182 # :csv: list of comma-separated values
183 # :scsv: list of comma-separated values return as set
183 # :scsv: list of comma-separated values return as set
184 # :plain: string with no transformation needed.
184 # :plain: string with no transformation needed.
185 gboptsmap = {'heads': 'nodes',
185 gboptsmap = {'heads': 'nodes',
186 'bookmarks': 'boolean',
186 'bookmarks': 'boolean',
187 'common': 'nodes',
187 'common': 'nodes',
188 'obsmarkers': 'boolean',
188 'obsmarkers': 'boolean',
189 'phases': 'boolean',
189 'phases': 'boolean',
190 'bundlecaps': 'scsv',
190 'bundlecaps': 'scsv',
191 'listkeys': 'csv',
191 'listkeys': 'csv',
192 'cg': 'boolean',
192 'cg': 'boolean',
193 'cbattempted': 'boolean',
193 'cbattempted': 'boolean',
194 'stream': 'boolean',
194 'stream': 'boolean',
195 }
195 }
196
196
197 # client side
197 # client side
198
198
199 class wirepeer(repository.legacypeer):
199 class wirepeer(repository.legacypeer):
200 """Client-side interface for communicating with a peer repository.
200 """Client-side interface for communicating with a peer repository.
201
201
202 Methods commonly call wire protocol commands of the same name.
202 Methods commonly call wire protocol commands of the same name.
203
203
204 See also httppeer.py and sshpeer.py for protocol-specific
204 See also httppeer.py and sshpeer.py for protocol-specific
205 implementations of this interface.
205 implementations of this interface.
206 """
206 """
207 # Begin of ipeercommands interface.
207 # Begin of ipeercommands interface.
208
208
209 def iterbatch(self):
209 def iterbatch(self):
210 return remoteiterbatcher(self)
210 return remoteiterbatcher(self)
211
211
212 @batchable
212 @batchable
213 def lookup(self, key):
213 def lookup(self, key):
214 self.requirecap('lookup', _('look up remote revision'))
214 self.requirecap('lookup', _('look up remote revision'))
215 f = future()
215 f = future()
216 yield {'key': encoding.fromlocal(key)}, f
216 yield {'key': encoding.fromlocal(key)}, f
217 d = f.value
217 d = f.value
218 success, data = d[:-1].split(" ", 1)
218 success, data = d[:-1].split(" ", 1)
219 if int(success):
219 if int(success):
220 yield bin(data)
220 yield bin(data)
221 else:
221 else:
222 self._abort(error.RepoError(data))
222 self._abort(error.RepoError(data))
223
223
224 @batchable
224 @batchable
225 def heads(self):
225 def heads(self):
226 f = future()
226 f = future()
227 yield {}, f
227 yield {}, f
228 d = f.value
228 d = f.value
229 try:
229 try:
230 yield decodelist(d[:-1])
230 yield decodelist(d[:-1])
231 except ValueError:
231 except ValueError:
232 self._abort(error.ResponseError(_("unexpected response:"), d))
232 self._abort(error.ResponseError(_("unexpected response:"), d))
233
233
234 @batchable
234 @batchable
235 def known(self, nodes):
235 def known(self, nodes):
236 f = future()
236 f = future()
237 yield {'nodes': encodelist(nodes)}, f
237 yield {'nodes': encodelist(nodes)}, f
238 d = f.value
238 d = f.value
239 try:
239 try:
240 yield [bool(int(b)) for b in d]
240 yield [bool(int(b)) for b in d]
241 except ValueError:
241 except ValueError:
242 self._abort(error.ResponseError(_("unexpected response:"), d))
242 self._abort(error.ResponseError(_("unexpected response:"), d))
243
243
244 @batchable
244 @batchable
245 def branchmap(self):
245 def branchmap(self):
246 f = future()
246 f = future()
247 yield {}, f
247 yield {}, f
248 d = f.value
248 d = f.value
249 try:
249 try:
250 branchmap = {}
250 branchmap = {}
251 for branchpart in d.splitlines():
251 for branchpart in d.splitlines():
252 branchname, branchheads = branchpart.split(' ', 1)
252 branchname, branchheads = branchpart.split(' ', 1)
253 branchname = encoding.tolocal(urlreq.unquote(branchname))
253 branchname = encoding.tolocal(urlreq.unquote(branchname))
254 branchheads = decodelist(branchheads)
254 branchheads = decodelist(branchheads)
255 branchmap[branchname] = branchheads
255 branchmap[branchname] = branchheads
256 yield branchmap
256 yield branchmap
257 except TypeError:
257 except TypeError:
258 self._abort(error.ResponseError(_("unexpected response:"), d))
258 self._abort(error.ResponseError(_("unexpected response:"), d))
259
259
260 @batchable
260 @batchable
261 def listkeys(self, namespace):
261 def listkeys(self, namespace):
262 if not self.capable('pushkey'):
262 if not self.capable('pushkey'):
263 yield {}, None
263 yield {}, None
264 f = future()
264 f = future()
265 self.ui.debug('preparing listkeys for "%s"\n' % namespace)
265 self.ui.debug('preparing listkeys for "%s"\n' % namespace)
266 yield {'namespace': encoding.fromlocal(namespace)}, f
266 yield {'namespace': encoding.fromlocal(namespace)}, f
267 d = f.value
267 d = f.value
268 self.ui.debug('received listkey for "%s": %i bytes\n'
268 self.ui.debug('received listkey for "%s": %i bytes\n'
269 % (namespace, len(d)))
269 % (namespace, len(d)))
270 yield pushkeymod.decodekeys(d)
270 yield pushkeymod.decodekeys(d)
271
271
272 @batchable
272 @batchable
273 def pushkey(self, namespace, key, old, new):
273 def pushkey(self, namespace, key, old, new):
274 if not self.capable('pushkey'):
274 if not self.capable('pushkey'):
275 yield False, None
275 yield False, None
276 f = future()
276 f = future()
277 self.ui.debug('preparing pushkey for "%s:%s"\n' % (namespace, key))
277 self.ui.debug('preparing pushkey for "%s:%s"\n' % (namespace, key))
278 yield {'namespace': encoding.fromlocal(namespace),
278 yield {'namespace': encoding.fromlocal(namespace),
279 'key': encoding.fromlocal(key),
279 'key': encoding.fromlocal(key),
280 'old': encoding.fromlocal(old),
280 'old': encoding.fromlocal(old),
281 'new': encoding.fromlocal(new)}, f
281 'new': encoding.fromlocal(new)}, f
282 d = f.value
282 d = f.value
283 d, output = d.split('\n', 1)
283 d, output = d.split('\n', 1)
284 try:
284 try:
285 d = bool(int(d))
285 d = bool(int(d))
286 except ValueError:
286 except ValueError:
287 raise error.ResponseError(
287 raise error.ResponseError(
288 _('push failed (unexpected response):'), d)
288 _('push failed (unexpected response):'), d)
289 for l in output.splitlines(True):
289 for l in output.splitlines(True):
290 self.ui.status(_('remote: '), l)
290 self.ui.status(_('remote: '), l)
291 yield d
291 yield d
292
292
293 def stream_out(self):
293 def stream_out(self):
294 return self._callstream('stream_out')
294 return self._callstream('stream_out')
295
295
296 def getbundle(self, source, **kwargs):
296 def getbundle(self, source, **kwargs):
297 kwargs = pycompat.byteskwargs(kwargs)
297 kwargs = pycompat.byteskwargs(kwargs)
298 self.requirecap('getbundle', _('look up remote changes'))
298 self.requirecap('getbundle', _('look up remote changes'))
299 opts = {}
299 opts = {}
300 bundlecaps = kwargs.get('bundlecaps') or set()
300 bundlecaps = kwargs.get('bundlecaps') or set()
301 for key, value in kwargs.iteritems():
301 for key, value in kwargs.iteritems():
302 if value is None:
302 if value is None:
303 continue
303 continue
304 keytype = gboptsmap.get(key)
304 keytype = gboptsmap.get(key)
305 if keytype is None:
305 if keytype is None:
306 raise error.ProgrammingError(
306 raise error.ProgrammingError(
307 'Unexpectedly None keytype for key %s' % key)
307 'Unexpectedly None keytype for key %s' % key)
308 elif keytype == 'nodes':
308 elif keytype == 'nodes':
309 value = encodelist(value)
309 value = encodelist(value)
310 elif keytype == 'csv':
310 elif keytype == 'csv':
311 value = ','.join(value)
311 value = ','.join(value)
312 elif keytype == 'scsv':
312 elif keytype == 'scsv':
313 value = ','.join(sorted(value))
313 value = ','.join(sorted(value))
314 elif keytype == 'boolean':
314 elif keytype == 'boolean':
315 value = '%i' % bool(value)
315 value = '%i' % bool(value)
316 elif keytype != 'plain':
316 elif keytype != 'plain':
317 raise KeyError('unknown getbundle option type %s'
317 raise KeyError('unknown getbundle option type %s'
318 % keytype)
318 % keytype)
319 opts[key] = value
319 opts[key] = value
320 f = self._callcompressable("getbundle", **pycompat.strkwargs(opts))
320 f = self._callcompressable("getbundle", **pycompat.strkwargs(opts))
321 if any((cap.startswith('HG2') for cap in bundlecaps)):
321 if any((cap.startswith('HG2') for cap in bundlecaps)):
322 return bundle2.getunbundler(self.ui, f)
322 return bundle2.getunbundler(self.ui, f)
323 else:
323 else:
324 return changegroupmod.cg1unpacker(f, 'UN')
324 return changegroupmod.cg1unpacker(f, 'UN')
325
325
326 def unbundle(self, cg, heads, url):
326 def unbundle(self, cg, heads, url):
327 '''Send cg (a readable file-like object representing the
327 '''Send cg (a readable file-like object representing the
328 changegroup to push, typically a chunkbuffer object) to the
328 changegroup to push, typically a chunkbuffer object) to the
329 remote server as a bundle.
329 remote server as a bundle.
330
330
331 When pushing a bundle10 stream, return an integer indicating the
331 When pushing a bundle10 stream, return an integer indicating the
332 result of the push (see changegroup.apply()).
332 result of the push (see changegroup.apply()).
333
333
334 When pushing a bundle20 stream, return a bundle20 stream.
334 When pushing a bundle20 stream, return a bundle20 stream.
335
335
336 `url` is the url the client thinks it's pushing to, which is
336 `url` is the url the client thinks it's pushing to, which is
337 visible to hooks.
337 visible to hooks.
338 '''
338 '''
339
339
340 if heads != ['force'] and self.capable('unbundlehash'):
340 if heads != ['force'] and self.capable('unbundlehash'):
341 heads = encodelist(['hashed',
341 heads = encodelist(['hashed',
342 hashlib.sha1(''.join(sorted(heads))).digest()])
342 hashlib.sha1(''.join(sorted(heads))).digest()])
343 else:
343 else:
344 heads = encodelist(heads)
344 heads = encodelist(heads)
345
345
346 if util.safehasattr(cg, 'deltaheader'):
346 if util.safehasattr(cg, 'deltaheader'):
347 # this a bundle10, do the old style call sequence
347 # this a bundle10, do the old style call sequence
348 ret, output = self._callpush("unbundle", cg, heads=heads)
348 ret, output = self._callpush("unbundle", cg, heads=heads)
349 if ret == "":
349 if ret == "":
350 raise error.ResponseError(
350 raise error.ResponseError(
351 _('push failed:'), output)
351 _('push failed:'), output)
352 try:
352 try:
353 ret = int(ret)
353 ret = int(ret)
354 except ValueError:
354 except ValueError:
355 raise error.ResponseError(
355 raise error.ResponseError(
356 _('push failed (unexpected response):'), ret)
356 _('push failed (unexpected response):'), ret)
357
357
358 for l in output.splitlines(True):
358 for l in output.splitlines(True):
359 self.ui.status(_('remote: '), l)
359 self.ui.status(_('remote: '), l)
360 else:
360 else:
361 # bundle2 push. Send a stream, fetch a stream.
361 # bundle2 push. Send a stream, fetch a stream.
362 stream = self._calltwowaystream('unbundle', cg, heads=heads)
362 stream = self._calltwowaystream('unbundle', cg, heads=heads)
363 ret = bundle2.getunbundler(self.ui, stream)
363 ret = bundle2.getunbundler(self.ui, stream)
364 return ret
364 return ret
365
365
366 # End of ipeercommands interface.
366 # End of ipeercommands interface.
367
367
368 # Begin of ipeerlegacycommands interface.
368 # Begin of ipeerlegacycommands interface.
369
369
370 def branches(self, nodes):
370 def branches(self, nodes):
371 n = encodelist(nodes)
371 n = encodelist(nodes)
372 d = self._call("branches", nodes=n)
372 d = self._call("branches", nodes=n)
373 try:
373 try:
374 br = [tuple(decodelist(b)) for b in d.splitlines()]
374 br = [tuple(decodelist(b)) for b in d.splitlines()]
375 return br
375 return br
376 except ValueError:
376 except ValueError:
377 self._abort(error.ResponseError(_("unexpected response:"), d))
377 self._abort(error.ResponseError(_("unexpected response:"), d))
378
378
379 def between(self, pairs):
379 def between(self, pairs):
380 batch = 8 # avoid giant requests
380 batch = 8 # avoid giant requests
381 r = []
381 r = []
382 for i in xrange(0, len(pairs), batch):
382 for i in xrange(0, len(pairs), batch):
383 n = " ".join([encodelist(p, '-') for p in pairs[i:i + batch]])
383 n = " ".join([encodelist(p, '-') for p in pairs[i:i + batch]])
384 d = self._call("between", pairs=n)
384 d = self._call("between", pairs=n)
385 try:
385 try:
386 r.extend(l and decodelist(l) or [] for l in d.splitlines())
386 r.extend(l and decodelist(l) or [] for l in d.splitlines())
387 except ValueError:
387 except ValueError:
388 self._abort(error.ResponseError(_("unexpected response:"), d))
388 self._abort(error.ResponseError(_("unexpected response:"), d))
389 return r
389 return r
390
390
391 def changegroup(self, nodes, kind):
391 def changegroup(self, nodes, kind):
392 n = encodelist(nodes)
392 n = encodelist(nodes)
393 f = self._callcompressable("changegroup", roots=n)
393 f = self._callcompressable("changegroup", roots=n)
394 return changegroupmod.cg1unpacker(f, 'UN')
394 return changegroupmod.cg1unpacker(f, 'UN')
395
395
396 def changegroupsubset(self, bases, heads, kind):
396 def changegroupsubset(self, bases, heads, kind):
397 self.requirecap('changegroupsubset', _('look up remote changes'))
397 self.requirecap('changegroupsubset', _('look up remote changes'))
398 bases = encodelist(bases)
398 bases = encodelist(bases)
399 heads = encodelist(heads)
399 heads = encodelist(heads)
400 f = self._callcompressable("changegroupsubset",
400 f = self._callcompressable("changegroupsubset",
401 bases=bases, heads=heads)
401 bases=bases, heads=heads)
402 return changegroupmod.cg1unpacker(f, 'UN')
402 return changegroupmod.cg1unpacker(f, 'UN')
403
403
404 # End of ipeerlegacycommands interface.
404 # End of ipeerlegacycommands interface.
405
405
406 def _submitbatch(self, req):
406 def _submitbatch(self, req):
407 """run batch request <req> on the server
407 """run batch request <req> on the server
408
408
409 Returns an iterator of the raw responses from the server.
409 Returns an iterator of the raw responses from the server.
410 """
410 """
411 ui = self.ui
411 ui = self.ui
412 if ui.debugflag and ui.configbool('devel', 'debug.peer-request'):
412 if ui.debugflag and ui.configbool('devel', 'debug.peer-request'):
413 ui.debug('devel-peer-request: batched-content\n')
413 ui.debug('devel-peer-request: batched-content\n')
414 for op, args in req:
414 for op, args in req:
415 msg = 'devel-peer-request: - %s (%d arguments)\n'
415 msg = 'devel-peer-request: - %s (%d arguments)\n'
416 ui.debug(msg % (op, len(args)))
416 ui.debug(msg % (op, len(args)))
417
417
418 rsp = self._callstream("batch", cmds=encodebatchcmds(req))
418 rsp = self._callstream("batch", cmds=encodebatchcmds(req))
419 chunk = rsp.read(1024)
419 chunk = rsp.read(1024)
420 work = [chunk]
420 work = [chunk]
421 while chunk:
421 while chunk:
422 while ';' not in chunk and chunk:
422 while ';' not in chunk and chunk:
423 chunk = rsp.read(1024)
423 chunk = rsp.read(1024)
424 work.append(chunk)
424 work.append(chunk)
425 merged = ''.join(work)
425 merged = ''.join(work)
426 while ';' in merged:
426 while ';' in merged:
427 one, merged = merged.split(';', 1)
427 one, merged = merged.split(';', 1)
428 yield unescapearg(one)
428 yield unescapearg(one)
429 chunk = rsp.read(1024)
429 chunk = rsp.read(1024)
430 work = [merged, chunk]
430 work = [merged, chunk]
431 yield unescapearg(''.join(work))
431 yield unescapearg(''.join(work))
432
432
433 def _submitone(self, op, args):
433 def _submitone(self, op, args):
434 return self._call(op, **pycompat.strkwargs(args))
434 return self._call(op, **pycompat.strkwargs(args))
435
435
436 def debugwireargs(self, one, two, three=None, four=None, five=None):
436 def debugwireargs(self, one, two, three=None, four=None, five=None):
437 # don't pass optional arguments left at their default value
437 # don't pass optional arguments left at their default value
438 opts = {}
438 opts = {}
439 if three is not None:
439 if three is not None:
440 opts[r'three'] = three
440 opts[r'three'] = three
441 if four is not None:
441 if four is not None:
442 opts[r'four'] = four
442 opts[r'four'] = four
443 return self._call('debugwireargs', one=one, two=two, **opts)
443 return self._call('debugwireargs', one=one, two=two, **opts)
444
444
445 def _call(self, cmd, **args):
445 def _call(self, cmd, **args):
446 """execute <cmd> on the server
446 """execute <cmd> on the server
447
447
448 The command is expected to return a simple string.
448 The command is expected to return a simple string.
449
449
450 returns the server reply as a string."""
450 returns the server reply as a string."""
451 raise NotImplementedError()
451 raise NotImplementedError()
452
452
453 def _callstream(self, cmd, **args):
453 def _callstream(self, cmd, **args):
454 """execute <cmd> on the server
454 """execute <cmd> on the server
455
455
456 The command is expected to return a stream. Note that if the
456 The command is expected to return a stream. Note that if the
457 command doesn't return a stream, _callstream behaves
457 command doesn't return a stream, _callstream behaves
458 differently for ssh and http peers.
458 differently for ssh and http peers.
459
459
460 returns the server reply as a file like object.
460 returns the server reply as a file like object.
461 """
461 """
462 raise NotImplementedError()
462 raise NotImplementedError()
463
463
464 def _callcompressable(self, cmd, **args):
464 def _callcompressable(self, cmd, **args):
465 """execute <cmd> on the server
465 """execute <cmd> on the server
466
466
467 The command is expected to return a stream.
467 The command is expected to return a stream.
468
468
469 The stream may have been compressed in some implementations. This
469 The stream may have been compressed in some implementations. This
470 function takes care of the decompression. This is the only difference
470 function takes care of the decompression. This is the only difference
471 with _callstream.
471 with _callstream.
472
472
473 returns the server reply as a file like object.
473 returns the server reply as a file like object.
474 """
474 """
475 raise NotImplementedError()
475 raise NotImplementedError()
476
476
477 def _callpush(self, cmd, fp, **args):
477 def _callpush(self, cmd, fp, **args):
478 """execute a <cmd> on server
478 """execute a <cmd> on server
479
479
480 The command is expected to be related to a push. Push has a special
480 The command is expected to be related to a push. Push has a special
481 return method.
481 return method.
482
482
483 returns the server reply as a (ret, output) tuple. ret is either
483 returns the server reply as a (ret, output) tuple. ret is either
484 empty (error) or a stringified int.
484 empty (error) or a stringified int.
485 """
485 """
486 raise NotImplementedError()
486 raise NotImplementedError()
487
487
488 def _calltwowaystream(self, cmd, fp, **args):
488 def _calltwowaystream(self, cmd, fp, **args):
489 """execute <cmd> on server
489 """execute <cmd> on server
490
490
491 The command will send a stream to the server and get a stream in reply.
491 The command will send a stream to the server and get a stream in reply.
492 """
492 """
493 raise NotImplementedError()
493 raise NotImplementedError()
494
494
495 def _abort(self, exception):
495 def _abort(self, exception):
496 """clearly abort the wire protocol connection and raise the exception
496 """clearly abort the wire protocol connection and raise the exception
497 """
497 """
498 raise NotImplementedError()
498 raise NotImplementedError()
499
499
500 # server side
500 # server side
501
501
502 # wire protocol command can either return a string or one of these classes.
502 # wire protocol command can either return a string or one of these classes.
503
503
504 def getdispatchrepo(repo, proto, command):
504 def getdispatchrepo(repo, proto, command):
505 """Obtain the repo used for processing wire protocol commands.
505 """Obtain the repo used for processing wire protocol commands.
506
506
507 The intent of this function is to serve as a monkeypatch point for
507 The intent of this function is to serve as a monkeypatch point for
508 extensions that need commands to operate on different repo views under
508 extensions that need commands to operate on different repo views under
509 specialized circumstances.
509 specialized circumstances.
510 """
510 """
511 return repo.filtered('served')
511 return repo.filtered('served')
512
512
513 def dispatch(repo, proto, command):
513 def dispatch(repo, proto, command):
514 repo = getdispatchrepo(repo, proto, command)
514 repo = getdispatchrepo(repo, proto, command)
515
515
516 transportversion = wireprototypes.TRANSPORTS[proto.name]['version']
516 transportversion = wireprototypes.TRANSPORTS[proto.name]['version']
517 commandtable = commandsv2 if transportversion == 2 else commands
517 commandtable = commandsv2 if transportversion == 2 else commands
518 func, spec = commandtable[command]
518 func, spec = commandtable[command]
519
519
520 args = proto.getargs(spec)
520 args = proto.getargs(spec)
521 return func(repo, proto, *args)
521 return func(repo, proto, *args)
522
522
523 def options(cmd, keys, others):
523 def options(cmd, keys, others):
524 opts = {}
524 opts = {}
525 for k in keys:
525 for k in keys:
526 if k in others:
526 if k in others:
527 opts[k] = others[k]
527 opts[k] = others[k]
528 del others[k]
528 del others[k]
529 if others:
529 if others:
530 procutil.stderr.write("warning: %s ignored unexpected arguments %s\n"
530 procutil.stderr.write("warning: %s ignored unexpected arguments %s\n"
531 % (cmd, ",".join(others)))
531 % (cmd, ",".join(others)))
532 return opts
532 return opts
533
533
534 def bundle1allowed(repo, action):
534 def bundle1allowed(repo, action):
535 """Whether a bundle1 operation is allowed from the server.
535 """Whether a bundle1 operation is allowed from the server.
536
536
537 Priority is:
537 Priority is:
538
538
539 1. server.bundle1gd.<action> (if generaldelta active)
539 1. server.bundle1gd.<action> (if generaldelta active)
540 2. server.bundle1.<action>
540 2. server.bundle1.<action>
541 3. server.bundle1gd (if generaldelta active)
541 3. server.bundle1gd (if generaldelta active)
542 4. server.bundle1
542 4. server.bundle1
543 """
543 """
544 ui = repo.ui
544 ui = repo.ui
545 gd = 'generaldelta' in repo.requirements
545 gd = 'generaldelta' in repo.requirements
546
546
547 if gd:
547 if gd:
548 v = ui.configbool('server', 'bundle1gd.%s' % action)
548 v = ui.configbool('server', 'bundle1gd.%s' % action)
549 if v is not None:
549 if v is not None:
550 return v
550 return v
551
551
552 v = ui.configbool('server', 'bundle1.%s' % action)
552 v = ui.configbool('server', 'bundle1.%s' % action)
553 if v is not None:
553 if v is not None:
554 return v
554 return v
555
555
556 if gd:
556 if gd:
557 v = ui.configbool('server', 'bundle1gd')
557 v = ui.configbool('server', 'bundle1gd')
558 if v is not None:
558 if v is not None:
559 return v
559 return v
560
560
561 return ui.configbool('server', 'bundle1')
561 return ui.configbool('server', 'bundle1')
562
562
563 def supportedcompengines(ui, role):
563 def supportedcompengines(ui, role):
564 """Obtain the list of supported compression engines for a request."""
564 """Obtain the list of supported compression engines for a request."""
565 assert role in (util.CLIENTROLE, util.SERVERROLE)
565 assert role in (util.CLIENTROLE, util.SERVERROLE)
566
566
567 compengines = util.compengines.supportedwireengines(role)
567 compengines = util.compengines.supportedwireengines(role)
568
568
569 # Allow config to override default list and ordering.
569 # Allow config to override default list and ordering.
570 if role == util.SERVERROLE:
570 if role == util.SERVERROLE:
571 configengines = ui.configlist('server', 'compressionengines')
571 configengines = ui.configlist('server', 'compressionengines')
572 config = 'server.compressionengines'
572 config = 'server.compressionengines'
573 else:
573 else:
574 # This is currently implemented mainly to facilitate testing. In most
574 # This is currently implemented mainly to facilitate testing. In most
575 # cases, the server should be in charge of choosing a compression engine
575 # cases, the server should be in charge of choosing a compression engine
576 # because a server has the most to lose from a sub-optimal choice. (e.g.
576 # because a server has the most to lose from a sub-optimal choice. (e.g.
577 # CPU DoS due to an expensive engine or a network DoS due to poor
577 # CPU DoS due to an expensive engine or a network DoS due to poor
578 # compression ratio).
578 # compression ratio).
579 configengines = ui.configlist('experimental',
579 configengines = ui.configlist('experimental',
580 'clientcompressionengines')
580 'clientcompressionengines')
581 config = 'experimental.clientcompressionengines'
581 config = 'experimental.clientcompressionengines'
582
582
583 # No explicit config. Filter out the ones that aren't supposed to be
583 # No explicit config. Filter out the ones that aren't supposed to be
584 # advertised and return default ordering.
584 # advertised and return default ordering.
585 if not configengines:
585 if not configengines:
586 attr = 'serverpriority' if role == util.SERVERROLE else 'clientpriority'
586 attr = 'serverpriority' if role == util.SERVERROLE else 'clientpriority'
587 return [e for e in compengines
587 return [e for e in compengines
588 if getattr(e.wireprotosupport(), attr) > 0]
588 if getattr(e.wireprotosupport(), attr) > 0]
589
589
590 # If compression engines are listed in the config, assume there is a good
590 # If compression engines are listed in the config, assume there is a good
591 # reason for it (like server operators wanting to achieve specific
591 # reason for it (like server operators wanting to achieve specific
592 # performance characteristics). So fail fast if the config references
592 # performance characteristics). So fail fast if the config references
593 # unusable compression engines.
593 # unusable compression engines.
594 validnames = set(e.name() for e in compengines)
594 validnames = set(e.name() for e in compengines)
595 invalidnames = set(e for e in configengines if e not in validnames)
595 invalidnames = set(e for e in configengines if e not in validnames)
596 if invalidnames:
596 if invalidnames:
597 raise error.Abort(_('invalid compression engine defined in %s: %s') %
597 raise error.Abort(_('invalid compression engine defined in %s: %s') %
598 (config, ', '.join(sorted(invalidnames))))
598 (config, ', '.join(sorted(invalidnames))))
599
599
600 compengines = [e for e in compengines if e.name() in configengines]
600 compengines = [e for e in compengines if e.name() in configengines]
601 compengines = sorted(compengines,
601 compengines = sorted(compengines,
602 key=lambda e: configengines.index(e.name()))
602 key=lambda e: configengines.index(e.name()))
603
603
604 if not compengines:
604 if not compengines:
605 raise error.Abort(_('%s config option does not specify any known '
605 raise error.Abort(_('%s config option does not specify any known '
606 'compression engines') % config,
606 'compression engines') % config,
607 hint=_('usable compression engines: %s') %
607 hint=_('usable compression engines: %s') %
608 ', '.sorted(validnames))
608 ', '.sorted(validnames))
609
609
610 return compengines
610 return compengines
611
611
612 class commandentry(object):
612 class commandentry(object):
613 """Represents a declared wire protocol command."""
613 """Represents a declared wire protocol command."""
614 def __init__(self, func, args='', transports=None,
614 def __init__(self, func, args='', transports=None,
615 permission='push'):
615 permission='push'):
616 self.func = func
616 self.func = func
617 self.args = args
617 self.args = args
618 self.transports = transports or set()
618 self.transports = transports or set()
619 self.permission = permission
619 self.permission = permission
620
620
621 def _merge(self, func, args):
621 def _merge(self, func, args):
622 """Merge this instance with an incoming 2-tuple.
622 """Merge this instance with an incoming 2-tuple.
623
623
624 This is called when a caller using the old 2-tuple API attempts
624 This is called when a caller using the old 2-tuple API attempts
625 to replace an instance. The incoming values are merged with
625 to replace an instance. The incoming values are merged with
626 data not captured by the 2-tuple and a new instance containing
626 data not captured by the 2-tuple and a new instance containing
627 the union of the two objects is returned.
627 the union of the two objects is returned.
628 """
628 """
629 return commandentry(func, args=args, transports=set(self.transports),
629 return commandentry(func, args=args, transports=set(self.transports),
630 permission=self.permission)
630 permission=self.permission)
631
631
632 # Old code treats instances as 2-tuples. So expose that interface.
632 # Old code treats instances as 2-tuples. So expose that interface.
633 def __iter__(self):
633 def __iter__(self):
634 yield self.func
634 yield self.func
635 yield self.args
635 yield self.args
636
636
637 def __getitem__(self, i):
637 def __getitem__(self, i):
638 if i == 0:
638 if i == 0:
639 return self.func
639 return self.func
640 elif i == 1:
640 elif i == 1:
641 return self.args
641 return self.args
642 else:
642 else:
643 raise IndexError('can only access elements 0 and 1')
643 raise IndexError('can only access elements 0 and 1')
644
644
645 class commanddict(dict):
645 class commanddict(dict):
646 """Container for registered wire protocol commands.
646 """Container for registered wire protocol commands.
647
647
648 It behaves like a dict. But __setitem__ is overwritten to allow silent
648 It behaves like a dict. But __setitem__ is overwritten to allow silent
649 coercion of values from 2-tuples for API compatibility.
649 coercion of values from 2-tuples for API compatibility.
650 """
650 """
651 def __setitem__(self, k, v):
651 def __setitem__(self, k, v):
652 if isinstance(v, commandentry):
652 if isinstance(v, commandentry):
653 pass
653 pass
654 # Cast 2-tuples to commandentry instances.
654 # Cast 2-tuples to commandentry instances.
655 elif isinstance(v, tuple):
655 elif isinstance(v, tuple):
656 if len(v) != 2:
656 if len(v) != 2:
657 raise ValueError('command tuples must have exactly 2 elements')
657 raise ValueError('command tuples must have exactly 2 elements')
658
658
659 # It is common for extensions to wrap wire protocol commands via
659 # It is common for extensions to wrap wire protocol commands via
660 # e.g. ``wireproto.commands[x] = (newfn, args)``. Because callers
660 # e.g. ``wireproto.commands[x] = (newfn, args)``. Because callers
661 # doing this aren't aware of the new API that uses objects to store
661 # doing this aren't aware of the new API that uses objects to store
662 # command entries, we automatically merge old state with new.
662 # command entries, we automatically merge old state with new.
663 if k in self:
663 if k in self:
664 v = self[k]._merge(v[0], v[1])
664 v = self[k]._merge(v[0], v[1])
665 else:
665 else:
666 # Use default values from @wireprotocommand.
666 # Use default values from @wireprotocommand.
667 v = commandentry(v[0], args=v[1],
667 v = commandentry(v[0], args=v[1],
668 transports=set(wireprototypes.TRANSPORTS),
668 transports=set(wireprototypes.TRANSPORTS),
669 permission='push')
669 permission='push')
670 else:
670 else:
671 raise ValueError('command entries must be commandentry instances '
671 raise ValueError('command entries must be commandentry instances '
672 'or 2-tuples')
672 'or 2-tuples')
673
673
674 return super(commanddict, self).__setitem__(k, v)
674 return super(commanddict, self).__setitem__(k, v)
675
675
676 def commandavailable(self, command, proto):
676 def commandavailable(self, command, proto):
677 """Determine if a command is available for the requested protocol."""
677 """Determine if a command is available for the requested protocol."""
678 assert proto.name in wireprototypes.TRANSPORTS
678 assert proto.name in wireprototypes.TRANSPORTS
679
679
680 entry = self.get(command)
680 entry = self.get(command)
681
681
682 if not entry:
682 if not entry:
683 return False
683 return False
684
684
685 if proto.name not in entry.transports:
685 if proto.name not in entry.transports:
686 return False
686 return False
687
687
688 return True
688 return True
689
689
690 # Constants specifying which transports a wire protocol command should be
690 # Constants specifying which transports a wire protocol command should be
691 # available on. For use with @wireprotocommand.
691 # available on. For use with @wireprotocommand.
692 POLICY_ALL = 'all'
692 POLICY_ALL = 'all'
693 POLICY_V1_ONLY = 'v1-only'
693 POLICY_V1_ONLY = 'v1-only'
694 POLICY_V2_ONLY = 'v2-only'
694 POLICY_V2_ONLY = 'v2-only'
695
695
696 # For version 1 transports.
696 # For version 1 transports.
697 commands = commanddict()
697 commands = commanddict()
698
698
699 # For version 2 transports.
699 # For version 2 transports.
700 commandsv2 = commanddict()
700 commandsv2 = commanddict()
701
701
702 def wireprotocommand(name, args='', transportpolicy=POLICY_ALL,
702 def wireprotocommand(name, args='', transportpolicy=POLICY_ALL,
703 permission='push'):
703 permission='push'):
704 """Decorator to declare a wire protocol command.
704 """Decorator to declare a wire protocol command.
705
705
706 ``name`` is the name of the wire protocol command being provided.
706 ``name`` is the name of the wire protocol command being provided.
707
707
708 ``args`` is a space-delimited list of named arguments that the command
708 ``args`` is a space-delimited list of named arguments that the command
709 accepts. ``*`` is a special value that says to accept all arguments.
709 accepts. ``*`` is a special value that says to accept all arguments.
710
710
711 ``transportpolicy`` is a POLICY_* constant denoting which transports
711 ``transportpolicy`` is a POLICY_* constant denoting which transports
712 this wire protocol command should be exposed to. By default, commands
712 this wire protocol command should be exposed to. By default, commands
713 are exposed to all wire protocol transports.
713 are exposed to all wire protocol transports.
714
714
715 ``permission`` defines the permission type needed to run this command.
715 ``permission`` defines the permission type needed to run this command.
716 Can be ``push`` or ``pull``. These roughly map to read-write and read-only,
716 Can be ``push`` or ``pull``. These roughly map to read-write and read-only,
717 respectively. Default is to assume command requires ``push`` permissions
717 respectively. Default is to assume command requires ``push`` permissions
718 because otherwise commands not declaring their permissions could modify
718 because otherwise commands not declaring their permissions could modify
719 a repository that is supposed to be read-only.
719 a repository that is supposed to be read-only.
720 """
720 """
721 if transportpolicy == POLICY_ALL:
721 if transportpolicy == POLICY_ALL:
722 transports = set(wireprototypes.TRANSPORTS)
722 transports = set(wireprototypes.TRANSPORTS)
723 transportversions = {1, 2}
723 transportversions = {1, 2}
724 elif transportpolicy == POLICY_V1_ONLY:
724 elif transportpolicy == POLICY_V1_ONLY:
725 transports = {k for k, v in wireprototypes.TRANSPORTS.items()
725 transports = {k for k, v in wireprototypes.TRANSPORTS.items()
726 if v['version'] == 1}
726 if v['version'] == 1}
727 transportversions = {1}
727 transportversions = {1}
728 elif transportpolicy == POLICY_V2_ONLY:
728 elif transportpolicy == POLICY_V2_ONLY:
729 transports = {k for k, v in wireprototypes.TRANSPORTS.items()
729 transports = {k for k, v in wireprototypes.TRANSPORTS.items()
730 if v['version'] == 2}
730 if v['version'] == 2}
731 transportversions = {2}
731 transportversions = {2}
732 else:
732 else:
733 raise error.ProgrammingError('invalid transport policy value: %s' %
733 raise error.ProgrammingError('invalid transport policy value: %s' %
734 transportpolicy)
734 transportpolicy)
735
735
736 # Because SSHv2 is a mirror of SSHv1, we allow "batch" commands through to
736 # Because SSHv2 is a mirror of SSHv1, we allow "batch" commands through to
737 # SSHv2.
737 # SSHv2.
738 # TODO undo this hack when SSH is using the unified frame protocol.
738 # TODO undo this hack when SSH is using the unified frame protocol.
739 if name == b'batch':
739 if name == b'batch':
740 transports.add(wireprototypes.SSHV2)
740 transports.add(wireprototypes.SSHV2)
741
741
742 if permission not in ('push', 'pull'):
742 if permission not in ('push', 'pull'):
743 raise error.ProgrammingError('invalid wire protocol permission; '
743 raise error.ProgrammingError('invalid wire protocol permission; '
744 'got %s; expected "push" or "pull"' %
744 'got %s; expected "push" or "pull"' %
745 permission)
745 permission)
746
746
747 def register(func):
747 def register(func):
748 if 1 in transportversions:
748 if 1 in transportversions:
749 if name in commands:
749 if name in commands:
750 raise error.ProgrammingError('%s command already registered '
750 raise error.ProgrammingError('%s command already registered '
751 'for version 1' % name)
751 'for version 1' % name)
752 commands[name] = commandentry(func, args=args,
752 commands[name] = commandentry(func, args=args,
753 transports=transports,
753 transports=transports,
754 permission=permission)
754 permission=permission)
755 if 2 in transportversions:
755 if 2 in transportversions:
756 if name in commandsv2:
756 if name in commandsv2:
757 raise error.ProgrammingError('%s command already registered '
757 raise error.ProgrammingError('%s command already registered '
758 'for version 2' % name)
758 'for version 2' % name)
759 commandsv2[name] = commandentry(func, args=args,
759 commandsv2[name] = commandentry(func, args=args,
760 transports=transports,
760 transports=transports,
761 permission=permission)
761 permission=permission)
762
762
763 return func
763 return func
764 return register
764 return register
765
765
766 # TODO define a more appropriate permissions type to use for this.
766 # TODO define a more appropriate permissions type to use for this.
767 @wireprotocommand('batch', 'cmds *', permission='pull',
767 @wireprotocommand('batch', 'cmds *', permission='pull',
768 transportpolicy=POLICY_V1_ONLY)
768 transportpolicy=POLICY_V1_ONLY)
769 def batch(repo, proto, cmds, others):
769 def batch(repo, proto, cmds, others):
770 repo = repo.filtered("served")
770 repo = repo.filtered("served")
771 res = []
771 res = []
772 for pair in cmds.split(';'):
772 for pair in cmds.split(';'):
773 op, args = pair.split(' ', 1)
773 op, args = pair.split(' ', 1)
774 vals = {}
774 vals = {}
775 for a in args.split(','):
775 for a in args.split(','):
776 if a:
776 if a:
777 n, v = a.split('=')
777 n, v = a.split('=')
778 vals[unescapearg(n)] = unescapearg(v)
778 vals[unescapearg(n)] = unescapearg(v)
779 func, spec = commands[op]
779 func, spec = commands[op]
780
780
781 # Validate that client has permissions to perform this command.
781 # Validate that client has permissions to perform this command.
782 perm = commands[op].permission
782 perm = commands[op].permission
783 assert perm in ('push', 'pull')
783 assert perm in ('push', 'pull')
784 proto.checkperm(perm)
784 proto.checkperm(perm)
785
785
786 if spec:
786 if spec:
787 keys = spec.split()
787 keys = spec.split()
788 data = {}
788 data = {}
789 for k in keys:
789 for k in keys:
790 if k == '*':
790 if k == '*':
791 star = {}
791 star = {}
792 for key in vals.keys():
792 for key in vals.keys():
793 if key not in keys:
793 if key not in keys:
794 star[key] = vals[key]
794 star[key] = vals[key]
795 data['*'] = star
795 data['*'] = star
796 else:
796 else:
797 data[k] = vals[k]
797 data[k] = vals[k]
798 result = func(repo, proto, *[data[k] for k in keys])
798 result = func(repo, proto, *[data[k] for k in keys])
799 else:
799 else:
800 result = func(repo, proto)
800 result = func(repo, proto)
801 if isinstance(result, wireprototypes.ooberror):
801 if isinstance(result, wireprototypes.ooberror):
802 return result
802 return result
803
803
804 # For now, all batchable commands must return bytesresponse or
804 # For now, all batchable commands must return bytesresponse or
805 # raw bytes (for backwards compatibility).
805 # raw bytes (for backwards compatibility).
806 assert isinstance(result, (wireprototypes.bytesresponse, bytes))
806 assert isinstance(result, (wireprototypes.bytesresponse, bytes))
807 if isinstance(result, wireprototypes.bytesresponse):
807 if isinstance(result, wireprototypes.bytesresponse):
808 result = result.data
808 result = result.data
809 res.append(escapearg(result))
809 res.append(escapearg(result))
810
810
811 return wireprototypes.bytesresponse(';'.join(res))
811 return wireprototypes.bytesresponse(';'.join(res))
812
812
813 @wireprotocommand('between', 'pairs', transportpolicy=POLICY_V1_ONLY,
813 @wireprotocommand('between', 'pairs', transportpolicy=POLICY_V1_ONLY,
814 permission='pull')
814 permission='pull')
815 def between(repo, proto, pairs):
815 def between(repo, proto, pairs):
816 pairs = [decodelist(p, '-') for p in pairs.split(" ")]
816 pairs = [decodelist(p, '-') for p in pairs.split(" ")]
817 r = []
817 r = []
818 for b in repo.between(pairs):
818 for b in repo.between(pairs):
819 r.append(encodelist(b) + "\n")
819 r.append(encodelist(b) + "\n")
820
820
821 return wireprototypes.bytesresponse(''.join(r))
821 return wireprototypes.bytesresponse(''.join(r))
822
822
823 @wireprotocommand('branchmap', permission='pull')
823 @wireprotocommand('branchmap', permission='pull')
824 def branchmap(repo, proto):
824 def branchmap(repo, proto):
825 branchmap = repo.branchmap()
825 branchmap = repo.branchmap()
826 heads = []
826 heads = []
827 for branch, nodes in branchmap.iteritems():
827 for branch, nodes in branchmap.iteritems():
828 branchname = urlreq.quote(encoding.fromlocal(branch))
828 branchname = urlreq.quote(encoding.fromlocal(branch))
829 branchnodes = encodelist(nodes)
829 branchnodes = encodelist(nodes)
830 heads.append('%s %s' % (branchname, branchnodes))
830 heads.append('%s %s' % (branchname, branchnodes))
831
831
832 return wireprototypes.bytesresponse('\n'.join(heads))
832 return wireprototypes.bytesresponse('\n'.join(heads))
833
833
834 @wireprotocommand('branches', 'nodes', transportpolicy=POLICY_V1_ONLY,
834 @wireprotocommand('branches', 'nodes', transportpolicy=POLICY_V1_ONLY,
835 permission='pull')
835 permission='pull')
836 def branches(repo, proto, nodes):
836 def branches(repo, proto, nodes):
837 nodes = decodelist(nodes)
837 nodes = decodelist(nodes)
838 r = []
838 r = []
839 for b in repo.branches(nodes):
839 for b in repo.branches(nodes):
840 r.append(encodelist(b) + "\n")
840 r.append(encodelist(b) + "\n")
841
841
842 return wireprototypes.bytesresponse(''.join(r))
842 return wireprototypes.bytesresponse(''.join(r))
843
843
844 @wireprotocommand('clonebundles', '', permission='pull')
844 @wireprotocommand('clonebundles', '', permission='pull')
845 def clonebundles(repo, proto):
845 def clonebundles(repo, proto):
846 """Server command for returning info for available bundles to seed clones.
846 """Server command for returning info for available bundles to seed clones.
847
847
848 Clients will parse this response and determine what bundle to fetch.
848 Clients will parse this response and determine what bundle to fetch.
849
849
850 Extensions may wrap this command to filter or dynamically emit data
850 Extensions may wrap this command to filter or dynamically emit data
851 depending on the request. e.g. you could advertise URLs for the closest
851 depending on the request. e.g. you could advertise URLs for the closest
852 data center given the client's IP address.
852 data center given the client's IP address.
853 """
853 """
854 return wireprototypes.bytesresponse(
854 return wireprototypes.bytesresponse(
855 repo.vfs.tryread('clonebundles.manifest'))
855 repo.vfs.tryread('clonebundles.manifest'))
856
856
857 wireprotocaps = ['lookup', 'branchmap', 'pushkey',
857 wireprotocaps = ['lookup', 'branchmap', 'pushkey',
858 'known', 'getbundle', 'unbundlehash']
858 'known', 'getbundle', 'unbundlehash']
859
859
860 def _capabilities(repo, proto):
860 def _capabilities(repo, proto):
861 """return a list of capabilities for a repo
861 """return a list of capabilities for a repo
862
862
863 This function exists to allow extensions to easily wrap capabilities
863 This function exists to allow extensions to easily wrap capabilities
864 computation
864 computation
865
865
866 - returns a lists: easy to alter
866 - returns a lists: easy to alter
867 - change done here will be propagated to both `capabilities` and `hello`
867 - change done here will be propagated to both `capabilities` and `hello`
868 command without any other action needed.
868 command without any other action needed.
869 """
869 """
870 # copy to prevent modification of the global list
870 # copy to prevent modification of the global list
871 caps = list(wireprotocaps)
871 caps = list(wireprotocaps)
872
872
873 # Command of same name as capability isn't exposed to version 1 of
873 # Command of same name as capability isn't exposed to version 1 of
874 # transports. So conditionally add it.
874 # transports. So conditionally add it.
875 if commands.commandavailable('changegroupsubset', proto):
875 if commands.commandavailable('changegroupsubset', proto):
876 caps.append('changegroupsubset')
876 caps.append('changegroupsubset')
877
877
878 if streamclone.allowservergeneration(repo):
878 if streamclone.allowservergeneration(repo):
879 if repo.ui.configbool('server', 'preferuncompressed'):
879 if repo.ui.configbool('server', 'preferuncompressed'):
880 caps.append('stream-preferred')
880 caps.append('stream-preferred')
881 requiredformats = repo.requirements & repo.supportedformats
881 requiredformats = repo.requirements & repo.supportedformats
882 # if our local revlogs are just revlogv1, add 'stream' cap
882 # if our local revlogs are just revlogv1, add 'stream' cap
883 if not requiredformats - {'revlogv1'}:
883 if not requiredformats - {'revlogv1'}:
884 caps.append('stream')
884 caps.append('stream')
885 # otherwise, add 'streamreqs' detailing our local revlog format
885 # otherwise, add 'streamreqs' detailing our local revlog format
886 else:
886 else:
887 caps.append('streamreqs=%s' % ','.join(sorted(requiredformats)))
887 caps.append('streamreqs=%s' % ','.join(sorted(requiredformats)))
888 if repo.ui.configbool('experimental', 'bundle2-advertise'):
888 if repo.ui.configbool('experimental', 'bundle2-advertise'):
889 capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo, role='server'))
889 capsblob = bundle2.encodecaps(bundle2.getrepocaps(repo, role='server'))
890 caps.append('bundle2=' + urlreq.quote(capsblob))
890 caps.append('bundle2=' + urlreq.quote(capsblob))
891 caps.append('unbundle=%s' % ','.join(bundle2.bundlepriority))
891 caps.append('unbundle=%s' % ','.join(bundle2.bundlepriority))
892
892
893 return proto.addcapabilities(repo, caps)
893 return proto.addcapabilities(repo, caps)
894
894
895 # If you are writing an extension and consider wrapping this function. Wrap
895 # If you are writing an extension and consider wrapping this function. Wrap
896 # `_capabilities` instead.
896 # `_capabilities` instead.
897 @wireprotocommand('capabilities', permission='pull')
897 @wireprotocommand('capabilities', permission='pull')
898 def capabilities(repo, proto):
898 def capabilities(repo, proto):
899 caps = _capabilities(repo, proto)
899 caps = _capabilities(repo, proto)
900 return wireprototypes.bytesresponse(' '.join(sorted(caps)))
900 return wireprototypes.bytesresponse(' '.join(sorted(caps)))
901
901
902 @wireprotocommand('changegroup', 'roots', transportpolicy=POLICY_V1_ONLY,
902 @wireprotocommand('changegroup', 'roots', transportpolicy=POLICY_V1_ONLY,
903 permission='pull')
903 permission='pull')
904 def changegroup(repo, proto, roots):
904 def changegroup(repo, proto, roots):
905 nodes = decodelist(roots)
905 nodes = decodelist(roots)
906 outgoing = discovery.outgoing(repo, missingroots=nodes,
906 outgoing = discovery.outgoing(repo, missingroots=nodes,
907 missingheads=repo.heads())
907 missingheads=repo.heads())
908 cg = changegroupmod.makechangegroup(repo, outgoing, '01', 'serve')
908 cg = changegroupmod.makechangegroup(repo, outgoing, '01', 'serve')
909 gen = iter(lambda: cg.read(32768), '')
909 gen = iter(lambda: cg.read(32768), '')
910 return wireprototypes.streamres(gen=gen)
910 return wireprototypes.streamres(gen=gen)
911
911
912 @wireprotocommand('changegroupsubset', 'bases heads',
912 @wireprotocommand('changegroupsubset', 'bases heads',
913 transportpolicy=POLICY_V1_ONLY,
913 transportpolicy=POLICY_V1_ONLY,
914 permission='pull')
914 permission='pull')
915 def changegroupsubset(repo, proto, bases, heads):
915 def changegroupsubset(repo, proto, bases, heads):
916 bases = decodelist(bases)
916 bases = decodelist(bases)
917 heads = decodelist(heads)
917 heads = decodelist(heads)
918 outgoing = discovery.outgoing(repo, missingroots=bases,
918 outgoing = discovery.outgoing(repo, missingroots=bases,
919 missingheads=heads)
919 missingheads=heads)
920 cg = changegroupmod.makechangegroup(repo, outgoing, '01', 'serve')
920 cg = changegroupmod.makechangegroup(repo, outgoing, '01', 'serve')
921 gen = iter(lambda: cg.read(32768), '')
921 gen = iter(lambda: cg.read(32768), '')
922 return wireprototypes.streamres(gen=gen)
922 return wireprototypes.streamres(gen=gen)
923
923
924 @wireprotocommand('debugwireargs', 'one two *',
924 @wireprotocommand('debugwireargs', 'one two *',
925 permission='pull')
925 permission='pull')
926 def debugwireargs(repo, proto, one, two, others):
926 def debugwireargs(repo, proto, one, two, others):
927 # only accept optional args from the known set
927 # only accept optional args from the known set
928 opts = options('debugwireargs', ['three', 'four'], others)
928 opts = options('debugwireargs', ['three', 'four'], others)
929 return wireprototypes.bytesresponse(repo.debugwireargs(
929 return wireprototypes.bytesresponse(repo.debugwireargs(
930 one, two, **pycompat.strkwargs(opts)))
930 one, two, **pycompat.strkwargs(opts)))
931
931
932 @wireprotocommand('getbundle', '*', permission='pull')
932 @wireprotocommand('getbundle', '*', permission='pull')
933 def getbundle(repo, proto, others):
933 def getbundle(repo, proto, others):
934 opts = options('getbundle', gboptsmap.keys(), others)
934 opts = options('getbundle', gboptsmap.keys(), others)
935 for k, v in opts.iteritems():
935 for k, v in opts.iteritems():
936 keytype = gboptsmap[k]
936 keytype = gboptsmap[k]
937 if keytype == 'nodes':
937 if keytype == 'nodes':
938 opts[k] = decodelist(v)
938 opts[k] = decodelist(v)
939 elif keytype == 'csv':
939 elif keytype == 'csv':
940 opts[k] = list(v.split(','))
940 opts[k] = list(v.split(','))
941 elif keytype == 'scsv':
941 elif keytype == 'scsv':
942 opts[k] = set(v.split(','))
942 opts[k] = set(v.split(','))
943 elif keytype == 'boolean':
943 elif keytype == 'boolean':
944 # Client should serialize False as '0', which is a non-empty string
944 # Client should serialize False as '0', which is a non-empty string
945 # so it evaluates as a True bool.
945 # so it evaluates as a True bool.
946 if v == '0':
946 if v == '0':
947 opts[k] = False
947 opts[k] = False
948 else:
948 else:
949 opts[k] = bool(v)
949 opts[k] = bool(v)
950 elif keytype != 'plain':
950 elif keytype != 'plain':
951 raise KeyError('unknown getbundle option type %s'
951 raise KeyError('unknown getbundle option type %s'
952 % keytype)
952 % keytype)
953
953
954 if not bundle1allowed(repo, 'pull'):
954 if not bundle1allowed(repo, 'pull'):
955 if not exchange.bundle2requested(opts.get('bundlecaps')):
955 if not exchange.bundle2requested(opts.get('bundlecaps')):
956 if proto.name == 'http-v1':
956 if proto.name == 'http-v1':
957 return wireprototypes.ooberror(bundle2required)
957 return wireprototypes.ooberror(bundle2required)
958 raise error.Abort(bundle2requiredmain,
958 raise error.Abort(bundle2requiredmain,
959 hint=bundle2requiredhint)
959 hint=bundle2requiredhint)
960
960
961 prefercompressed = True
961 prefercompressed = True
962
962
963 try:
963 try:
964 if repo.ui.configbool('server', 'disablefullbundle'):
964 if repo.ui.configbool('server', 'disablefullbundle'):
965 # Check to see if this is a full clone.
965 # Check to see if this is a full clone.
966 clheads = set(repo.changelog.heads())
966 clheads = set(repo.changelog.heads())
967 changegroup = opts.get('cg', True)
967 changegroup = opts.get('cg', True)
968 heads = set(opts.get('heads', set()))
968 heads = set(opts.get('heads', set()))
969 common = set(opts.get('common', set()))
969 common = set(opts.get('common', set()))
970 common.discard(nullid)
970 common.discard(nullid)
971 if changegroup and not common and clheads == heads:
971 if changegroup and not common and clheads == heads:
972 raise error.Abort(
972 raise error.Abort(
973 _('server has pull-based clones disabled'),
973 _('server has pull-based clones disabled'),
974 hint=_('remove --pull if specified or upgrade Mercurial'))
974 hint=_('remove --pull if specified or upgrade Mercurial'))
975
975
976 info, chunks = exchange.getbundlechunks(repo, 'serve',
976 info, chunks = exchange.getbundlechunks(repo, 'serve',
977 **pycompat.strkwargs(opts))
977 **pycompat.strkwargs(opts))
978 prefercompressed = info.get('prefercompressed', True)
978 prefercompressed = info.get('prefercompressed', True)
979 except error.Abort as exc:
979 except error.Abort as exc:
980 # cleanly forward Abort error to the client
980 # cleanly forward Abort error to the client
981 if not exchange.bundle2requested(opts.get('bundlecaps')):
981 if not exchange.bundle2requested(opts.get('bundlecaps')):
982 if proto.name == 'http-v1':
982 if proto.name == 'http-v1':
983 return wireprototypes.ooberror(pycompat.bytestr(exc) + '\n')
983 return wireprototypes.ooberror(pycompat.bytestr(exc) + '\n')
984 raise # cannot do better for bundle1 + ssh
984 raise # cannot do better for bundle1 + ssh
985 # bundle2 request expect a bundle2 reply
985 # bundle2 request expect a bundle2 reply
986 bundler = bundle2.bundle20(repo.ui)
986 bundler = bundle2.bundle20(repo.ui)
987 manargs = [('message', pycompat.bytestr(exc))]
987 manargs = [('message', pycompat.bytestr(exc))]
988 advargs = []
988 advargs = []
989 if exc.hint is not None:
989 if exc.hint is not None:
990 advargs.append(('hint', exc.hint))
990 advargs.append(('hint', exc.hint))
991 bundler.addpart(bundle2.bundlepart('error:abort',
991 bundler.addpart(bundle2.bundlepart('error:abort',
992 manargs, advargs))
992 manargs, advargs))
993 chunks = bundler.getchunks()
993 chunks = bundler.getchunks()
994 prefercompressed = False
994 prefercompressed = False
995
995
996 return wireprototypes.streamres(
996 return wireprototypes.streamres(
997 gen=chunks, prefer_uncompressed=not prefercompressed)
997 gen=chunks, prefer_uncompressed=not prefercompressed)
998
998
999 @wireprotocommand('heads', permission='pull')
999 @wireprotocommand('heads', permission='pull')
1000 def heads(repo, proto):
1000 def heads(repo, proto):
1001 h = repo.heads()
1001 h = repo.heads()
1002 return wireprototypes.bytesresponse(encodelist(h) + '\n')
1002 return wireprototypes.bytesresponse(encodelist(h) + '\n')
1003
1003
1004 @wireprotocommand('hello', permission='pull')
1004 @wireprotocommand('hello', permission='pull')
1005 def hello(repo, proto):
1005 def hello(repo, proto):
1006 """Called as part of SSH handshake to obtain server info.
1006 """Called as part of SSH handshake to obtain server info.
1007
1007
1008 Returns a list of lines describing interesting things about the
1008 Returns a list of lines describing interesting things about the
1009 server, in an RFC822-like format.
1009 server, in an RFC822-like format.
1010
1010
1011 Currently, the only one defined is ``capabilities``, which consists of a
1011 Currently, the only one defined is ``capabilities``, which consists of a
1012 line of space separated tokens describing server abilities:
1012 line of space separated tokens describing server abilities:
1013
1013
1014 capabilities: <token0> <token1> <token2>
1014 capabilities: <token0> <token1> <token2>
1015 """
1015 """
1016 caps = capabilities(repo, proto).data
1016 caps = capabilities(repo, proto).data
1017 return wireprototypes.bytesresponse('capabilities: %s\n' % caps)
1017 return wireprototypes.bytesresponse('capabilities: %s\n' % caps)
1018
1018
1019 @wireprotocommand('listkeys', 'namespace', permission='pull')
1019 @wireprotocommand('listkeys', 'namespace', permission='pull')
1020 def listkeys(repo, proto, namespace):
1020 def listkeys(repo, proto, namespace):
1021 d = sorted(repo.listkeys(encoding.tolocal(namespace)).items())
1021 d = sorted(repo.listkeys(encoding.tolocal(namespace)).items())
1022 return wireprototypes.bytesresponse(pushkeymod.encodekeys(d))
1022 return wireprototypes.bytesresponse(pushkeymod.encodekeys(d))
1023
1023
1024 @wireprotocommand('lookup', 'key', permission='pull')
1024 @wireprotocommand('lookup', 'key', permission='pull')
1025 def lookup(repo, proto, key):
1025 def lookup(repo, proto, key):
1026 try:
1026 try:
1027 k = encoding.tolocal(key)
1027 k = encoding.tolocal(key)
1028 n = repo.lookup(k)
1028 n = repo.lookup(k)
1029 r = hex(n)
1029 r = hex(n)
1030 success = 1
1030 success = 1
1031 except Exception as inst:
1031 except Exception as inst:
1032 r = stringutil.forcebytestr(inst)
1032 r = stringutil.forcebytestr(inst)
1033 success = 0
1033 success = 0
1034 return wireprototypes.bytesresponse('%d %s\n' % (success, r))
1034 return wireprototypes.bytesresponse('%d %s\n' % (success, r))
1035
1035
1036 @wireprotocommand('known', 'nodes *', permission='pull')
1036 @wireprotocommand('known', 'nodes *', permission='pull')
1037 def known(repo, proto, nodes, others):
1037 def known(repo, proto, nodes, others):
1038 v = ''.join(b and '1' or '0' for b in repo.known(decodelist(nodes)))
1038 v = ''.join(b and '1' or '0' for b in repo.known(decodelist(nodes)))
1039 return wireprototypes.bytesresponse(v)
1039 return wireprototypes.bytesresponse(v)
1040
1040
1041 @wireprotocommand('protocaps', 'caps', permission='pull',
1041 @wireprotocommand('protocaps', 'caps', permission='pull',
1042 transportpolicy=POLICY_V1_ONLY)
1042 transportpolicy=POLICY_V1_ONLY)
1043 def protocaps(repo, proto, caps):
1043 def protocaps(repo, proto, caps):
1044 if proto.name == wireprototypes.SSHV1:
1044 if proto.name == wireprototypes.SSHV1:
1045 proto._protocaps = set(caps.split(' '))
1045 proto._protocaps = set(caps.split(' '))
1046 return wireprototypes.bytesresponse('OK')
1046 return wireprototypes.bytesresponse('OK')
1047
1047
1048 @wireprotocommand('pushkey', 'namespace key old new', permission='push')
1048 @wireprotocommand('pushkey', 'namespace key old new', permission='push')
1049 def pushkey(repo, proto, namespace, key, old, new):
1049 def pushkey(repo, proto, namespace, key, old, new):
1050 # compatibility with pre-1.8 clients which were accidentally
1050 # compatibility with pre-1.8 clients which were accidentally
1051 # sending raw binary nodes rather than utf-8-encoded hex
1051 # sending raw binary nodes rather than utf-8-encoded hex
1052 if len(new) == 20 and stringutil.escapestr(new) != new:
1052 if len(new) == 20 and stringutil.escapestr(new) != new:
1053 # looks like it could be a binary node
1053 # looks like it could be a binary node
1054 try:
1054 try:
1055 new.decode('utf-8')
1055 new.decode('utf-8')
1056 new = encoding.tolocal(new) # but cleanly decodes as UTF-8
1056 new = encoding.tolocal(new) # but cleanly decodes as UTF-8
1057 except UnicodeDecodeError:
1057 except UnicodeDecodeError:
1058 pass # binary, leave unmodified
1058 pass # binary, leave unmodified
1059 else:
1059 else:
1060 new = encoding.tolocal(new) # normal path
1060 new = encoding.tolocal(new) # normal path
1061
1061
1062 with proto.mayberedirectstdio() as output:
1062 with proto.mayberedirectstdio() as output:
1063 r = repo.pushkey(encoding.tolocal(namespace), encoding.tolocal(key),
1063 r = repo.pushkey(encoding.tolocal(namespace), encoding.tolocal(key),
1064 encoding.tolocal(old), new) or False
1064 encoding.tolocal(old), new) or False
1065
1065
1066 output = output.getvalue() if output else ''
1066 output = output.getvalue() if output else ''
1067 return wireprototypes.bytesresponse('%d\n%s' % (int(r), output))
1067 return wireprototypes.bytesresponse('%d\n%s' % (int(r), output))
1068
1068
1069 @wireprotocommand('stream_out', permission='pull')
1069 @wireprotocommand('stream_out', permission='pull')
1070 def stream(repo, proto):
1070 def stream(repo, proto):
1071 '''If the server supports streaming clone, it advertises the "stream"
1071 '''If the server supports streaming clone, it advertises the "stream"
1072 capability with a value representing the version and flags of the repo
1072 capability with a value representing the version and flags of the repo
1073 it is serving. Client checks to see if it understands the format.
1073 it is serving. Client checks to see if it understands the format.
1074 '''
1074 '''
1075 return wireprototypes.streamreslegacy(
1075 return wireprototypes.streamreslegacy(
1076 streamclone.generatev1wireproto(repo))
1076 streamclone.generatev1wireproto(repo))
1077
1077
1078 @wireprotocommand('unbundle', 'heads', permission='push')
1078 @wireprotocommand('unbundle', 'heads', permission='push')
1079 def unbundle(repo, proto, heads):
1079 def unbundle(repo, proto, heads):
1080 their_heads = decodelist(heads)
1080 their_heads = decodelist(heads)
1081
1081
1082 with proto.mayberedirectstdio() as output:
1082 with proto.mayberedirectstdio() as output:
1083 try:
1083 try:
1084 exchange.check_heads(repo, their_heads, 'preparing changes')
1084 exchange.check_heads(repo, their_heads, 'preparing changes')
1085 cleanup = lambda: None
1086 try:
1087 payload = proto.getpayload()
1088 if repo.ui.configbool('server', 'streamunbundle'):
1089 def cleanup():
1090 # Ensure that the full payload is consumed, so
1091 # that the connection doesn't contain trailing garbage.
1092 for p in payload:
1093 pass
1094 fp = util.chunkbuffer(payload)
1095 else:
1096 # write bundle data to temporary file as it can be big
1097 fp, tempname = None, None
1098 def cleanup():
1099 if fp:
1100 fp.close()
1101 if tempname:
1102 os.unlink(tempname)
1103 fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-')
1104 repo.ui.debug('redirecting incoming bundle to %s\n' %
1105 tempname)
1106 fp = os.fdopen(fd, pycompat.sysstr('wb+'))
1107 r = 0
1108 for p in payload:
1109 fp.write(p)
1110 fp.seek(0)
1085
1111
1086 # write bundle data to temporary file because it can be big
1087 fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-')
1088 fp = os.fdopen(fd, r'wb+')
1089 r = 0
1090 try:
1091 proto.forwardpayload(fp)
1092 fp.seek(0)
1093 gen = exchange.readbundle(repo.ui, fp, None)
1112 gen = exchange.readbundle(repo.ui, fp, None)
1094 if (isinstance(gen, changegroupmod.cg1unpacker)
1113 if (isinstance(gen, changegroupmod.cg1unpacker)
1095 and not bundle1allowed(repo, 'push')):
1114 and not bundle1allowed(repo, 'push')):
1096 if proto.name == 'http-v1':
1115 if proto.name == 'http-v1':
1097 # need to special case http because stderr do not get to
1116 # need to special case http because stderr do not get to
1098 # the http client on failed push so we need to abuse
1117 # the http client on failed push so we need to abuse
1099 # some other error type to make sure the message get to
1118 # some other error type to make sure the message get to
1100 # the user.
1119 # the user.
1101 return wireprototypes.ooberror(bundle2required)
1120 return wireprototypes.ooberror(bundle2required)
1102 raise error.Abort(bundle2requiredmain,
1121 raise error.Abort(bundle2requiredmain,
1103 hint=bundle2requiredhint)
1122 hint=bundle2requiredhint)
1104
1123
1105 r = exchange.unbundle(repo, gen, their_heads, 'serve',
1124 r = exchange.unbundle(repo, gen, their_heads, 'serve',
1106 proto.client())
1125 proto.client())
1107 if util.safehasattr(r, 'addpart'):
1126 if util.safehasattr(r, 'addpart'):
1108 # The return looks streamable, we are in the bundle2 case
1127 # The return looks streamable, we are in the bundle2 case
1109 # and should return a stream.
1128 # and should return a stream.
1110 return wireprototypes.streamreslegacy(gen=r.getchunks())
1129 return wireprototypes.streamreslegacy(gen=r.getchunks())
1111 return wireprototypes.pushres(
1130 return wireprototypes.pushres(
1112 r, output.getvalue() if output else '')
1131 r, output.getvalue() if output else '')
1113
1132
1114 finally:
1133 finally:
1115 fp.close()
1134 cleanup()
1116 os.unlink(tempname)
1117
1135
1118 except (error.BundleValueError, error.Abort, error.PushRaced) as exc:
1136 except (error.BundleValueError, error.Abort, error.PushRaced) as exc:
1119 # handle non-bundle2 case first
1137 # handle non-bundle2 case first
1120 if not getattr(exc, 'duringunbundle2', False):
1138 if not getattr(exc, 'duringunbundle2', False):
1121 try:
1139 try:
1122 raise
1140 raise
1123 except error.Abort:
1141 except error.Abort:
1124 # The old code we moved used procutil.stderr directly.
1142 # The old code we moved used procutil.stderr directly.
1125 # We did not change it to minimise code change.
1143 # We did not change it to minimise code change.
1126 # This need to be moved to something proper.
1144 # This need to be moved to something proper.
1127 # Feel free to do it.
1145 # Feel free to do it.
1128 procutil.stderr.write("abort: %s\n" % exc)
1146 procutil.stderr.write("abort: %s\n" % exc)
1129 if exc.hint is not None:
1147 if exc.hint is not None:
1130 procutil.stderr.write("(%s)\n" % exc.hint)
1148 procutil.stderr.write("(%s)\n" % exc.hint)
1131 procutil.stderr.flush()
1149 procutil.stderr.flush()
1132 return wireprototypes.pushres(
1150 return wireprototypes.pushres(
1133 0, output.getvalue() if output else '')
1151 0, output.getvalue() if output else '')
1134 except error.PushRaced:
1152 except error.PushRaced:
1135 return wireprototypes.pusherr(
1153 return wireprototypes.pusherr(
1136 pycompat.bytestr(exc),
1154 pycompat.bytestr(exc),
1137 output.getvalue() if output else '')
1155 output.getvalue() if output else '')
1138
1156
1139 bundler = bundle2.bundle20(repo.ui)
1157 bundler = bundle2.bundle20(repo.ui)
1140 for out in getattr(exc, '_bundle2salvagedoutput', ()):
1158 for out in getattr(exc, '_bundle2salvagedoutput', ()):
1141 bundler.addpart(out)
1159 bundler.addpart(out)
1142 try:
1160 try:
1143 try:
1161 try:
1144 raise
1162 raise
1145 except error.PushkeyFailed as exc:
1163 except error.PushkeyFailed as exc:
1146 # check client caps
1164 # check client caps
1147 remotecaps = getattr(exc, '_replycaps', None)
1165 remotecaps = getattr(exc, '_replycaps', None)
1148 if (remotecaps is not None
1166 if (remotecaps is not None
1149 and 'pushkey' not in remotecaps.get('error', ())):
1167 and 'pushkey' not in remotecaps.get('error', ())):
1150 # no support remote side, fallback to Abort handler.
1168 # no support remote side, fallback to Abort handler.
1151 raise
1169 raise
1152 part = bundler.newpart('error:pushkey')
1170 part = bundler.newpart('error:pushkey')
1153 part.addparam('in-reply-to', exc.partid)
1171 part.addparam('in-reply-to', exc.partid)
1154 if exc.namespace is not None:
1172 if exc.namespace is not None:
1155 part.addparam('namespace', exc.namespace,
1173 part.addparam('namespace', exc.namespace,
1156 mandatory=False)
1174 mandatory=False)
1157 if exc.key is not None:
1175 if exc.key is not None:
1158 part.addparam('key', exc.key, mandatory=False)
1176 part.addparam('key', exc.key, mandatory=False)
1159 if exc.new is not None:
1177 if exc.new is not None:
1160 part.addparam('new', exc.new, mandatory=False)
1178 part.addparam('new', exc.new, mandatory=False)
1161 if exc.old is not None:
1179 if exc.old is not None:
1162 part.addparam('old', exc.old, mandatory=False)
1180 part.addparam('old', exc.old, mandatory=False)
1163 if exc.ret is not None:
1181 if exc.ret is not None:
1164 part.addparam('ret', exc.ret, mandatory=False)
1182 part.addparam('ret', exc.ret, mandatory=False)
1165 except error.BundleValueError as exc:
1183 except error.BundleValueError as exc:
1166 errpart = bundler.newpart('error:unsupportedcontent')
1184 errpart = bundler.newpart('error:unsupportedcontent')
1167 if exc.parttype is not None:
1185 if exc.parttype is not None:
1168 errpart.addparam('parttype', exc.parttype)
1186 errpart.addparam('parttype', exc.parttype)
1169 if exc.params:
1187 if exc.params:
1170 errpart.addparam('params', '\0'.join(exc.params))
1188 errpart.addparam('params', '\0'.join(exc.params))
1171 except error.Abort as exc:
1189 except error.Abort as exc:
1172 manargs = [('message', stringutil.forcebytestr(exc))]
1190 manargs = [('message', stringutil.forcebytestr(exc))]
1173 advargs = []
1191 advargs = []
1174 if exc.hint is not None:
1192 if exc.hint is not None:
1175 advargs.append(('hint', exc.hint))
1193 advargs.append(('hint', exc.hint))
1176 bundler.addpart(bundle2.bundlepart('error:abort',
1194 bundler.addpart(bundle2.bundlepart('error:abort',
1177 manargs, advargs))
1195 manargs, advargs))
1178 except error.PushRaced as exc:
1196 except error.PushRaced as exc:
1179 bundler.newpart('error:pushraced',
1197 bundler.newpart('error:pushraced',
1180 [('message', stringutil.forcebytestr(exc))])
1198 [('message', stringutil.forcebytestr(exc))])
1181 return wireprototypes.streamreslegacy(gen=bundler.getchunks())
1199 return wireprototypes.streamreslegacy(gen=bundler.getchunks())
@@ -1,1066 +1,1065 b''
1 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
1 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
2 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
2 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 #
3 #
4 # This software may be used and distributed according to the terms of the
4 # This software may be used and distributed according to the terms of the
5 # GNU General Public License version 2 or any later version.
5 # GNU General Public License version 2 or any later version.
6
6
7 from __future__ import absolute_import
7 from __future__ import absolute_import
8
8
9 import contextlib
9 import contextlib
10 import struct
10 import struct
11 import sys
11 import sys
12 import threading
12 import threading
13
13
14 from .i18n import _
14 from .i18n import _
15 from .thirdparty.zope import (
15 from .thirdparty.zope import (
16 interface as zi,
16 interface as zi,
17 )
17 )
18 from . import (
18 from . import (
19 encoding,
19 encoding,
20 error,
20 error,
21 hook,
21 hook,
22 pycompat,
22 pycompat,
23 util,
23 util,
24 wireproto,
24 wireproto,
25 wireprotoframing,
25 wireprotoframing,
26 wireprototypes,
26 wireprototypes,
27 )
27 )
28 from .utils import (
28 from .utils import (
29 procutil,
29 procutil,
30 )
30 )
31
31
32 stringio = util.stringio
32 stringio = util.stringio
33
33
34 urlerr = util.urlerr
34 urlerr = util.urlerr
35 urlreq = util.urlreq
35 urlreq = util.urlreq
36
36
37 HTTP_OK = 200
37 HTTP_OK = 200
38
38
39 HGTYPE = 'application/mercurial-0.1'
39 HGTYPE = 'application/mercurial-0.1'
40 HGTYPE2 = 'application/mercurial-0.2'
40 HGTYPE2 = 'application/mercurial-0.2'
41 HGERRTYPE = 'application/hg-error'
41 HGERRTYPE = 'application/hg-error'
42 FRAMINGTYPE = b'application/mercurial-exp-framing-0003'
42 FRAMINGTYPE = b'application/mercurial-exp-framing-0003'
43
43
44 HTTPV2 = wireprototypes.HTTPV2
44 HTTPV2 = wireprototypes.HTTPV2
45 SSHV1 = wireprototypes.SSHV1
45 SSHV1 = wireprototypes.SSHV1
46 SSHV2 = wireprototypes.SSHV2
46 SSHV2 = wireprototypes.SSHV2
47
47
48 def decodevaluefromheaders(req, headerprefix):
48 def decodevaluefromheaders(req, headerprefix):
49 """Decode a long value from multiple HTTP request headers.
49 """Decode a long value from multiple HTTP request headers.
50
50
51 Returns the value as a bytes, not a str.
51 Returns the value as a bytes, not a str.
52 """
52 """
53 chunks = []
53 chunks = []
54 i = 1
54 i = 1
55 while True:
55 while True:
56 v = req.headers.get(b'%s-%d' % (headerprefix, i))
56 v = req.headers.get(b'%s-%d' % (headerprefix, i))
57 if v is None:
57 if v is None:
58 break
58 break
59 chunks.append(pycompat.bytesurl(v))
59 chunks.append(pycompat.bytesurl(v))
60 i += 1
60 i += 1
61
61
62 return ''.join(chunks)
62 return ''.join(chunks)
63
63
64 @zi.implementer(wireprototypes.baseprotocolhandler)
64 @zi.implementer(wireprototypes.baseprotocolhandler)
65 class httpv1protocolhandler(object):
65 class httpv1protocolhandler(object):
66 def __init__(self, req, ui, checkperm):
66 def __init__(self, req, ui, checkperm):
67 self._req = req
67 self._req = req
68 self._ui = ui
68 self._ui = ui
69 self._checkperm = checkperm
69 self._checkperm = checkperm
70 self._protocaps = None
70 self._protocaps = None
71
71
72 @property
72 @property
73 def name(self):
73 def name(self):
74 return 'http-v1'
74 return 'http-v1'
75
75
76 def getargs(self, args):
76 def getargs(self, args):
77 knownargs = self._args()
77 knownargs = self._args()
78 data = {}
78 data = {}
79 keys = args.split()
79 keys = args.split()
80 for k in keys:
80 for k in keys:
81 if k == '*':
81 if k == '*':
82 star = {}
82 star = {}
83 for key in knownargs.keys():
83 for key in knownargs.keys():
84 if key != 'cmd' and key not in keys:
84 if key != 'cmd' and key not in keys:
85 star[key] = knownargs[key][0]
85 star[key] = knownargs[key][0]
86 data['*'] = star
86 data['*'] = star
87 else:
87 else:
88 data[k] = knownargs[k][0]
88 data[k] = knownargs[k][0]
89 return [data[k] for k in keys]
89 return [data[k] for k in keys]
90
90
91 def _args(self):
91 def _args(self):
92 args = self._req.qsparams.asdictoflists()
92 args = self._req.qsparams.asdictoflists()
93 postlen = int(self._req.headers.get(b'X-HgArgs-Post', 0))
93 postlen = int(self._req.headers.get(b'X-HgArgs-Post', 0))
94 if postlen:
94 if postlen:
95 args.update(urlreq.parseqs(
95 args.update(urlreq.parseqs(
96 self._req.bodyfh.read(postlen), keep_blank_values=True))
96 self._req.bodyfh.read(postlen), keep_blank_values=True))
97 return args
97 return args
98
98
99 argvalue = decodevaluefromheaders(self._req, b'X-HgArg')
99 argvalue = decodevaluefromheaders(self._req, b'X-HgArg')
100 args.update(urlreq.parseqs(argvalue, keep_blank_values=True))
100 args.update(urlreq.parseqs(argvalue, keep_blank_values=True))
101 return args
101 return args
102
102
103 def getprotocaps(self):
103 def getprotocaps(self):
104 if self._protocaps is None:
104 if self._protocaps is None:
105 value = decodevaluefromheaders(self._req, r'X-HgProto')
105 value = decodevaluefromheaders(self._req, r'X-HgProto')
106 self._protocaps = set(value.split(' '))
106 self._protocaps = set(value.split(' '))
107 return self._protocaps
107 return self._protocaps
108
108
109 def forwardpayload(self, fp):
109 def getpayload(self):
110 # Existing clients *always* send Content-Length.
110 # Existing clients *always* send Content-Length.
111 length = int(self._req.headers[b'Content-Length'])
111 length = int(self._req.headers[b'Content-Length'])
112
112
113 # If httppostargs is used, we need to read Content-Length
113 # If httppostargs is used, we need to read Content-Length
114 # minus the amount that was consumed by args.
114 # minus the amount that was consumed by args.
115 length -= int(self._req.headers.get(b'X-HgArgs-Post', 0))
115 length -= int(self._req.headers.get(b'X-HgArgs-Post', 0))
116 for s in util.filechunkiter(self._req.bodyfh, limit=length):
116 return util.filechunkiter(self._req.bodyfh, limit=length)
117 fp.write(s)
118
117
119 @contextlib.contextmanager
118 @contextlib.contextmanager
120 def mayberedirectstdio(self):
119 def mayberedirectstdio(self):
121 oldout = self._ui.fout
120 oldout = self._ui.fout
122 olderr = self._ui.ferr
121 olderr = self._ui.ferr
123
122
124 out = util.stringio()
123 out = util.stringio()
125
124
126 try:
125 try:
127 self._ui.fout = out
126 self._ui.fout = out
128 self._ui.ferr = out
127 self._ui.ferr = out
129 yield out
128 yield out
130 finally:
129 finally:
131 self._ui.fout = oldout
130 self._ui.fout = oldout
132 self._ui.ferr = olderr
131 self._ui.ferr = olderr
133
132
134 def client(self):
133 def client(self):
135 return 'remote:%s:%s:%s' % (
134 return 'remote:%s:%s:%s' % (
136 self._req.urlscheme,
135 self._req.urlscheme,
137 urlreq.quote(self._req.remotehost or ''),
136 urlreq.quote(self._req.remotehost or ''),
138 urlreq.quote(self._req.remoteuser or ''))
137 urlreq.quote(self._req.remoteuser or ''))
139
138
140 def addcapabilities(self, repo, caps):
139 def addcapabilities(self, repo, caps):
141 caps.append(b'batch')
140 caps.append(b'batch')
142
141
143 caps.append('httpheader=%d' %
142 caps.append('httpheader=%d' %
144 repo.ui.configint('server', 'maxhttpheaderlen'))
143 repo.ui.configint('server', 'maxhttpheaderlen'))
145 if repo.ui.configbool('experimental', 'httppostargs'):
144 if repo.ui.configbool('experimental', 'httppostargs'):
146 caps.append('httppostargs')
145 caps.append('httppostargs')
147
146
148 # FUTURE advertise 0.2rx once support is implemented
147 # FUTURE advertise 0.2rx once support is implemented
149 # FUTURE advertise minrx and mintx after consulting config option
148 # FUTURE advertise minrx and mintx after consulting config option
150 caps.append('httpmediatype=0.1rx,0.1tx,0.2tx')
149 caps.append('httpmediatype=0.1rx,0.1tx,0.2tx')
151
150
152 compengines = wireproto.supportedcompengines(repo.ui, util.SERVERROLE)
151 compengines = wireproto.supportedcompengines(repo.ui, util.SERVERROLE)
153 if compengines:
152 if compengines:
154 comptypes = ','.join(urlreq.quote(e.wireprotosupport().name)
153 comptypes = ','.join(urlreq.quote(e.wireprotosupport().name)
155 for e in compengines)
154 for e in compengines)
156 caps.append('compression=%s' % comptypes)
155 caps.append('compression=%s' % comptypes)
157
156
158 return caps
157 return caps
159
158
160 def checkperm(self, perm):
159 def checkperm(self, perm):
161 return self._checkperm(perm)
160 return self._checkperm(perm)
162
161
163 # This method exists mostly so that extensions like remotefilelog can
162 # This method exists mostly so that extensions like remotefilelog can
164 # disable a kludgey legacy method only over http. As of early 2018,
163 # disable a kludgey legacy method only over http. As of early 2018,
165 # there are no other known users, so with any luck we can discard this
164 # there are no other known users, so with any luck we can discard this
166 # hook if remotefilelog becomes a first-party extension.
165 # hook if remotefilelog becomes a first-party extension.
167 def iscmd(cmd):
166 def iscmd(cmd):
168 return cmd in wireproto.commands
167 return cmd in wireproto.commands
169
168
170 def handlewsgirequest(rctx, req, res, checkperm):
169 def handlewsgirequest(rctx, req, res, checkperm):
171 """Possibly process a wire protocol request.
170 """Possibly process a wire protocol request.
172
171
173 If the current request is a wire protocol request, the request is
172 If the current request is a wire protocol request, the request is
174 processed by this function.
173 processed by this function.
175
174
176 ``req`` is a ``parsedrequest`` instance.
175 ``req`` is a ``parsedrequest`` instance.
177 ``res`` is a ``wsgiresponse`` instance.
176 ``res`` is a ``wsgiresponse`` instance.
178
177
179 Returns a bool indicating if the request was serviced. If set, the caller
178 Returns a bool indicating if the request was serviced. If set, the caller
180 should stop processing the request, as a response has already been issued.
179 should stop processing the request, as a response has already been issued.
181 """
180 """
182 # Avoid cycle involving hg module.
181 # Avoid cycle involving hg module.
183 from .hgweb import common as hgwebcommon
182 from .hgweb import common as hgwebcommon
184
183
185 repo = rctx.repo
184 repo = rctx.repo
186
185
187 # HTTP version 1 wire protocol requests are denoted by a "cmd" query
186 # HTTP version 1 wire protocol requests are denoted by a "cmd" query
188 # string parameter. If it isn't present, this isn't a wire protocol
187 # string parameter. If it isn't present, this isn't a wire protocol
189 # request.
188 # request.
190 if 'cmd' not in req.qsparams:
189 if 'cmd' not in req.qsparams:
191 return False
190 return False
192
191
193 cmd = req.qsparams['cmd']
192 cmd = req.qsparams['cmd']
194
193
195 # The "cmd" request parameter is used by both the wire protocol and hgweb.
194 # The "cmd" request parameter is used by both the wire protocol and hgweb.
196 # While not all wire protocol commands are available for all transports,
195 # While not all wire protocol commands are available for all transports,
197 # if we see a "cmd" value that resembles a known wire protocol command, we
196 # if we see a "cmd" value that resembles a known wire protocol command, we
198 # route it to a protocol handler. This is better than routing possible
197 # route it to a protocol handler. This is better than routing possible
199 # wire protocol requests to hgweb because it prevents hgweb from using
198 # wire protocol requests to hgweb because it prevents hgweb from using
200 # known wire protocol commands and it is less confusing for machine
199 # known wire protocol commands and it is less confusing for machine
201 # clients.
200 # clients.
202 if not iscmd(cmd):
201 if not iscmd(cmd):
203 return False
202 return False
204
203
205 # The "cmd" query string argument is only valid on the root path of the
204 # The "cmd" query string argument is only valid on the root path of the
206 # repo. e.g. ``/?cmd=foo``, ``/repo?cmd=foo``. URL paths within the repo
205 # repo. e.g. ``/?cmd=foo``, ``/repo?cmd=foo``. URL paths within the repo
207 # like ``/blah?cmd=foo`` are not allowed. So don't recognize the request
206 # like ``/blah?cmd=foo`` are not allowed. So don't recognize the request
208 # in this case. We send an HTTP 404 for backwards compatibility reasons.
207 # in this case. We send an HTTP 404 for backwards compatibility reasons.
209 if req.dispatchpath:
208 if req.dispatchpath:
210 res.status = hgwebcommon.statusmessage(404)
209 res.status = hgwebcommon.statusmessage(404)
211 res.headers['Content-Type'] = HGTYPE
210 res.headers['Content-Type'] = HGTYPE
212 # TODO This is not a good response to issue for this request. This
211 # TODO This is not a good response to issue for this request. This
213 # is mostly for BC for now.
212 # is mostly for BC for now.
214 res.setbodybytes('0\n%s\n' % b'Not Found')
213 res.setbodybytes('0\n%s\n' % b'Not Found')
215 return True
214 return True
216
215
217 proto = httpv1protocolhandler(req, repo.ui,
216 proto = httpv1protocolhandler(req, repo.ui,
218 lambda perm: checkperm(rctx, req, perm))
217 lambda perm: checkperm(rctx, req, perm))
219
218
220 # The permissions checker should be the only thing that can raise an
219 # The permissions checker should be the only thing that can raise an
221 # ErrorResponse. It is kind of a layer violation to catch an hgweb
220 # ErrorResponse. It is kind of a layer violation to catch an hgweb
222 # exception here. So consider refactoring into a exception type that
221 # exception here. So consider refactoring into a exception type that
223 # is associated with the wire protocol.
222 # is associated with the wire protocol.
224 try:
223 try:
225 _callhttp(repo, req, res, proto, cmd)
224 _callhttp(repo, req, res, proto, cmd)
226 except hgwebcommon.ErrorResponse as e:
225 except hgwebcommon.ErrorResponse as e:
227 for k, v in e.headers:
226 for k, v in e.headers:
228 res.headers[k] = v
227 res.headers[k] = v
229 res.status = hgwebcommon.statusmessage(e.code, pycompat.bytestr(e))
228 res.status = hgwebcommon.statusmessage(e.code, pycompat.bytestr(e))
230 # TODO This response body assumes the failed command was
229 # TODO This response body assumes the failed command was
231 # "unbundle." That assumption is not always valid.
230 # "unbundle." That assumption is not always valid.
232 res.setbodybytes('0\n%s\n' % pycompat.bytestr(e))
231 res.setbodybytes('0\n%s\n' % pycompat.bytestr(e))
233
232
234 return True
233 return True
235
234
236 def handlewsgiapirequest(rctx, req, res, checkperm):
235 def handlewsgiapirequest(rctx, req, res, checkperm):
237 """Handle requests to /api/*."""
236 """Handle requests to /api/*."""
238 assert req.dispatchparts[0] == b'api'
237 assert req.dispatchparts[0] == b'api'
239
238
240 repo = rctx.repo
239 repo = rctx.repo
241
240
242 # This whole URL space is experimental for now. But we want to
241 # This whole URL space is experimental for now. But we want to
243 # reserve the URL space. So, 404 all URLs if the feature isn't enabled.
242 # reserve the URL space. So, 404 all URLs if the feature isn't enabled.
244 if not repo.ui.configbool('experimental', 'web.apiserver'):
243 if not repo.ui.configbool('experimental', 'web.apiserver'):
245 res.status = b'404 Not Found'
244 res.status = b'404 Not Found'
246 res.headers[b'Content-Type'] = b'text/plain'
245 res.headers[b'Content-Type'] = b'text/plain'
247 res.setbodybytes(_('Experimental API server endpoint not enabled'))
246 res.setbodybytes(_('Experimental API server endpoint not enabled'))
248 return
247 return
249
248
250 # The URL space is /api/<protocol>/*. The structure of URLs under varies
249 # The URL space is /api/<protocol>/*. The structure of URLs under varies
251 # by <protocol>.
250 # by <protocol>.
252
251
253 # Registered APIs are made available via config options of the name of
252 # Registered APIs are made available via config options of the name of
254 # the protocol.
253 # the protocol.
255 availableapis = set()
254 availableapis = set()
256 for k, v in API_HANDLERS.items():
255 for k, v in API_HANDLERS.items():
257 section, option = v['config']
256 section, option = v['config']
258 if repo.ui.configbool(section, option):
257 if repo.ui.configbool(section, option):
259 availableapis.add(k)
258 availableapis.add(k)
260
259
261 # Requests to /api/ list available APIs.
260 # Requests to /api/ list available APIs.
262 if req.dispatchparts == [b'api']:
261 if req.dispatchparts == [b'api']:
263 res.status = b'200 OK'
262 res.status = b'200 OK'
264 res.headers[b'Content-Type'] = b'text/plain'
263 res.headers[b'Content-Type'] = b'text/plain'
265 lines = [_('APIs can be accessed at /api/<name>, where <name> can be '
264 lines = [_('APIs can be accessed at /api/<name>, where <name> can be '
266 'one of the following:\n')]
265 'one of the following:\n')]
267 if availableapis:
266 if availableapis:
268 lines.extend(sorted(availableapis))
267 lines.extend(sorted(availableapis))
269 else:
268 else:
270 lines.append(_('(no available APIs)\n'))
269 lines.append(_('(no available APIs)\n'))
271 res.setbodybytes(b'\n'.join(lines))
270 res.setbodybytes(b'\n'.join(lines))
272 return
271 return
273
272
274 proto = req.dispatchparts[1]
273 proto = req.dispatchparts[1]
275
274
276 if proto not in API_HANDLERS:
275 if proto not in API_HANDLERS:
277 res.status = b'404 Not Found'
276 res.status = b'404 Not Found'
278 res.headers[b'Content-Type'] = b'text/plain'
277 res.headers[b'Content-Type'] = b'text/plain'
279 res.setbodybytes(_('Unknown API: %s\nKnown APIs: %s') % (
278 res.setbodybytes(_('Unknown API: %s\nKnown APIs: %s') % (
280 proto, b', '.join(sorted(availableapis))))
279 proto, b', '.join(sorted(availableapis))))
281 return
280 return
282
281
283 if proto not in availableapis:
282 if proto not in availableapis:
284 res.status = b'404 Not Found'
283 res.status = b'404 Not Found'
285 res.headers[b'Content-Type'] = b'text/plain'
284 res.headers[b'Content-Type'] = b'text/plain'
286 res.setbodybytes(_('API %s not enabled\n') % proto)
285 res.setbodybytes(_('API %s not enabled\n') % proto)
287 return
286 return
288
287
289 API_HANDLERS[proto]['handler'](rctx, req, res, checkperm,
288 API_HANDLERS[proto]['handler'](rctx, req, res, checkperm,
290 req.dispatchparts[2:])
289 req.dispatchparts[2:])
291
290
292 def _handlehttpv2request(rctx, req, res, checkperm, urlparts):
291 def _handlehttpv2request(rctx, req, res, checkperm, urlparts):
293 from .hgweb import common as hgwebcommon
292 from .hgweb import common as hgwebcommon
294
293
295 # URL space looks like: <permissions>/<command>, where <permission> can
294 # URL space looks like: <permissions>/<command>, where <permission> can
296 # be ``ro`` or ``rw`` to signal read-only or read-write, respectively.
295 # be ``ro`` or ``rw`` to signal read-only or read-write, respectively.
297
296
298 # Root URL does nothing meaningful... yet.
297 # Root URL does nothing meaningful... yet.
299 if not urlparts:
298 if not urlparts:
300 res.status = b'200 OK'
299 res.status = b'200 OK'
301 res.headers[b'Content-Type'] = b'text/plain'
300 res.headers[b'Content-Type'] = b'text/plain'
302 res.setbodybytes(_('HTTP version 2 API handler'))
301 res.setbodybytes(_('HTTP version 2 API handler'))
303 return
302 return
304
303
305 if len(urlparts) == 1:
304 if len(urlparts) == 1:
306 res.status = b'404 Not Found'
305 res.status = b'404 Not Found'
307 res.headers[b'Content-Type'] = b'text/plain'
306 res.headers[b'Content-Type'] = b'text/plain'
308 res.setbodybytes(_('do not know how to process %s\n') %
307 res.setbodybytes(_('do not know how to process %s\n') %
309 req.dispatchpath)
308 req.dispatchpath)
310 return
309 return
311
310
312 permission, command = urlparts[0:2]
311 permission, command = urlparts[0:2]
313
312
314 if permission not in (b'ro', b'rw'):
313 if permission not in (b'ro', b'rw'):
315 res.status = b'404 Not Found'
314 res.status = b'404 Not Found'
316 res.headers[b'Content-Type'] = b'text/plain'
315 res.headers[b'Content-Type'] = b'text/plain'
317 res.setbodybytes(_('unknown permission: %s') % permission)
316 res.setbodybytes(_('unknown permission: %s') % permission)
318 return
317 return
319
318
320 if req.method != 'POST':
319 if req.method != 'POST':
321 res.status = b'405 Method Not Allowed'
320 res.status = b'405 Method Not Allowed'
322 res.headers[b'Allow'] = b'POST'
321 res.headers[b'Allow'] = b'POST'
323 res.setbodybytes(_('commands require POST requests'))
322 res.setbodybytes(_('commands require POST requests'))
324 return
323 return
325
324
326 # At some point we'll want to use our own API instead of recycling the
325 # At some point we'll want to use our own API instead of recycling the
327 # behavior of version 1 of the wire protocol...
326 # behavior of version 1 of the wire protocol...
328 # TODO return reasonable responses - not responses that overload the
327 # TODO return reasonable responses - not responses that overload the
329 # HTTP status line message for error reporting.
328 # HTTP status line message for error reporting.
330 try:
329 try:
331 checkperm(rctx, req, 'pull' if permission == b'ro' else 'push')
330 checkperm(rctx, req, 'pull' if permission == b'ro' else 'push')
332 except hgwebcommon.ErrorResponse as e:
331 except hgwebcommon.ErrorResponse as e:
333 res.status = hgwebcommon.statusmessage(e.code, pycompat.bytestr(e))
332 res.status = hgwebcommon.statusmessage(e.code, pycompat.bytestr(e))
334 for k, v in e.headers:
333 for k, v in e.headers:
335 res.headers[k] = v
334 res.headers[k] = v
336 res.setbodybytes('permission denied')
335 res.setbodybytes('permission denied')
337 return
336 return
338
337
339 # We have a special endpoint to reflect the request back at the client.
338 # We have a special endpoint to reflect the request back at the client.
340 if command == b'debugreflect':
339 if command == b'debugreflect':
341 _processhttpv2reflectrequest(rctx.repo.ui, rctx.repo, req, res)
340 _processhttpv2reflectrequest(rctx.repo.ui, rctx.repo, req, res)
342 return
341 return
343
342
344 # Extra commands that we handle that aren't really wire protocol
343 # Extra commands that we handle that aren't really wire protocol
345 # commands. Think extra hard before making this hackery available to
344 # commands. Think extra hard before making this hackery available to
346 # extension.
345 # extension.
347 extracommands = {'multirequest'}
346 extracommands = {'multirequest'}
348
347
349 if command not in wireproto.commandsv2 and command not in extracommands:
348 if command not in wireproto.commandsv2 and command not in extracommands:
350 res.status = b'404 Not Found'
349 res.status = b'404 Not Found'
351 res.headers[b'Content-Type'] = b'text/plain'
350 res.headers[b'Content-Type'] = b'text/plain'
352 res.setbodybytes(_('unknown wire protocol command: %s\n') % command)
351 res.setbodybytes(_('unknown wire protocol command: %s\n') % command)
353 return
352 return
354
353
355 repo = rctx.repo
354 repo = rctx.repo
356 ui = repo.ui
355 ui = repo.ui
357
356
358 proto = httpv2protocolhandler(req, ui)
357 proto = httpv2protocolhandler(req, ui)
359
358
360 if (not wireproto.commandsv2.commandavailable(command, proto)
359 if (not wireproto.commandsv2.commandavailable(command, proto)
361 and command not in extracommands):
360 and command not in extracommands):
362 res.status = b'404 Not Found'
361 res.status = b'404 Not Found'
363 res.headers[b'Content-Type'] = b'text/plain'
362 res.headers[b'Content-Type'] = b'text/plain'
364 res.setbodybytes(_('invalid wire protocol command: %s') % command)
363 res.setbodybytes(_('invalid wire protocol command: %s') % command)
365 return
364 return
366
365
367 # TODO consider cases where proxies may add additional Accept headers.
366 # TODO consider cases where proxies may add additional Accept headers.
368 if req.headers.get(b'Accept') != FRAMINGTYPE:
367 if req.headers.get(b'Accept') != FRAMINGTYPE:
369 res.status = b'406 Not Acceptable'
368 res.status = b'406 Not Acceptable'
370 res.headers[b'Content-Type'] = b'text/plain'
369 res.headers[b'Content-Type'] = b'text/plain'
371 res.setbodybytes(_('client MUST specify Accept header with value: %s\n')
370 res.setbodybytes(_('client MUST specify Accept header with value: %s\n')
372 % FRAMINGTYPE)
371 % FRAMINGTYPE)
373 return
372 return
374
373
375 if req.headers.get(b'Content-Type') != FRAMINGTYPE:
374 if req.headers.get(b'Content-Type') != FRAMINGTYPE:
376 res.status = b'415 Unsupported Media Type'
375 res.status = b'415 Unsupported Media Type'
377 # TODO we should send a response with appropriate media type,
376 # TODO we should send a response with appropriate media type,
378 # since client does Accept it.
377 # since client does Accept it.
379 res.headers[b'Content-Type'] = b'text/plain'
378 res.headers[b'Content-Type'] = b'text/plain'
380 res.setbodybytes(_('client MUST send Content-Type header with '
379 res.setbodybytes(_('client MUST send Content-Type header with '
381 'value: %s\n') % FRAMINGTYPE)
380 'value: %s\n') % FRAMINGTYPE)
382 return
381 return
383
382
384 _processhttpv2request(ui, repo, req, res, permission, command, proto)
383 _processhttpv2request(ui, repo, req, res, permission, command, proto)
385
384
386 def _processhttpv2reflectrequest(ui, repo, req, res):
385 def _processhttpv2reflectrequest(ui, repo, req, res):
387 """Reads unified frame protocol request and dumps out state to client.
386 """Reads unified frame protocol request and dumps out state to client.
388
387
389 This special endpoint can be used to help debug the wire protocol.
388 This special endpoint can be used to help debug the wire protocol.
390
389
391 Instead of routing the request through the normal dispatch mechanism,
390 Instead of routing the request through the normal dispatch mechanism,
392 we instead read all frames, decode them, and feed them into our state
391 we instead read all frames, decode them, and feed them into our state
393 tracker. We then dump the log of all that activity back out to the
392 tracker. We then dump the log of all that activity back out to the
394 client.
393 client.
395 """
394 """
396 import json
395 import json
397
396
398 # Reflection APIs have a history of being abused, accidentally disclosing
397 # Reflection APIs have a history of being abused, accidentally disclosing
399 # sensitive data, etc. So we have a config knob.
398 # sensitive data, etc. So we have a config knob.
400 if not ui.configbool('experimental', 'web.api.debugreflect'):
399 if not ui.configbool('experimental', 'web.api.debugreflect'):
401 res.status = b'404 Not Found'
400 res.status = b'404 Not Found'
402 res.headers[b'Content-Type'] = b'text/plain'
401 res.headers[b'Content-Type'] = b'text/plain'
403 res.setbodybytes(_('debugreflect service not available'))
402 res.setbodybytes(_('debugreflect service not available'))
404 return
403 return
405
404
406 # We assume we have a unified framing protocol request body.
405 # We assume we have a unified framing protocol request body.
407
406
408 reactor = wireprotoframing.serverreactor()
407 reactor = wireprotoframing.serverreactor()
409 states = []
408 states = []
410
409
411 while True:
410 while True:
412 frame = wireprotoframing.readframe(req.bodyfh)
411 frame = wireprotoframing.readframe(req.bodyfh)
413
412
414 if not frame:
413 if not frame:
415 states.append(b'received: <no frame>')
414 states.append(b'received: <no frame>')
416 break
415 break
417
416
418 states.append(b'received: %d %d %d %s' % (frame.typeid, frame.flags,
417 states.append(b'received: %d %d %d %s' % (frame.typeid, frame.flags,
419 frame.requestid,
418 frame.requestid,
420 frame.payload))
419 frame.payload))
421
420
422 action, meta = reactor.onframerecv(frame)
421 action, meta = reactor.onframerecv(frame)
423 states.append(json.dumps((action, meta), sort_keys=True,
422 states.append(json.dumps((action, meta), sort_keys=True,
424 separators=(', ', ': ')))
423 separators=(', ', ': ')))
425
424
426 action, meta = reactor.oninputeof()
425 action, meta = reactor.oninputeof()
427 meta['action'] = action
426 meta['action'] = action
428 states.append(json.dumps(meta, sort_keys=True, separators=(', ',': ')))
427 states.append(json.dumps(meta, sort_keys=True, separators=(', ',': ')))
429
428
430 res.status = b'200 OK'
429 res.status = b'200 OK'
431 res.headers[b'Content-Type'] = b'text/plain'
430 res.headers[b'Content-Type'] = b'text/plain'
432 res.setbodybytes(b'\n'.join(states))
431 res.setbodybytes(b'\n'.join(states))
433
432
434 def _processhttpv2request(ui, repo, req, res, authedperm, reqcommand, proto):
433 def _processhttpv2request(ui, repo, req, res, authedperm, reqcommand, proto):
435 """Post-validation handler for HTTPv2 requests.
434 """Post-validation handler for HTTPv2 requests.
436
435
437 Called when the HTTP request contains unified frame-based protocol
436 Called when the HTTP request contains unified frame-based protocol
438 frames for evaluation.
437 frames for evaluation.
439 """
438 """
440 # TODO Some HTTP clients are full duplex and can receive data before
439 # TODO Some HTTP clients are full duplex and can receive data before
441 # the entire request is transmitted. Figure out a way to indicate support
440 # the entire request is transmitted. Figure out a way to indicate support
442 # for that so we can opt into full duplex mode.
441 # for that so we can opt into full duplex mode.
443 reactor = wireprotoframing.serverreactor(deferoutput=True)
442 reactor = wireprotoframing.serverreactor(deferoutput=True)
444 seencommand = False
443 seencommand = False
445
444
446 outstream = reactor.makeoutputstream()
445 outstream = reactor.makeoutputstream()
447
446
448 while True:
447 while True:
449 frame = wireprotoframing.readframe(req.bodyfh)
448 frame = wireprotoframing.readframe(req.bodyfh)
450 if not frame:
449 if not frame:
451 break
450 break
452
451
453 action, meta = reactor.onframerecv(frame)
452 action, meta = reactor.onframerecv(frame)
454
453
455 if action == 'wantframe':
454 if action == 'wantframe':
456 # Need more data before we can do anything.
455 # Need more data before we can do anything.
457 continue
456 continue
458 elif action == 'runcommand':
457 elif action == 'runcommand':
459 sentoutput = _httpv2runcommand(ui, repo, req, res, authedperm,
458 sentoutput = _httpv2runcommand(ui, repo, req, res, authedperm,
460 reqcommand, reactor, outstream,
459 reqcommand, reactor, outstream,
461 meta, issubsequent=seencommand)
460 meta, issubsequent=seencommand)
462
461
463 if sentoutput:
462 if sentoutput:
464 return
463 return
465
464
466 seencommand = True
465 seencommand = True
467
466
468 elif action == 'error':
467 elif action == 'error':
469 # TODO define proper error mechanism.
468 # TODO define proper error mechanism.
470 res.status = b'200 OK'
469 res.status = b'200 OK'
471 res.headers[b'Content-Type'] = b'text/plain'
470 res.headers[b'Content-Type'] = b'text/plain'
472 res.setbodybytes(meta['message'] + b'\n')
471 res.setbodybytes(meta['message'] + b'\n')
473 return
472 return
474 else:
473 else:
475 raise error.ProgrammingError(
474 raise error.ProgrammingError(
476 'unhandled action from frame processor: %s' % action)
475 'unhandled action from frame processor: %s' % action)
477
476
478 action, meta = reactor.oninputeof()
477 action, meta = reactor.oninputeof()
479 if action == 'sendframes':
478 if action == 'sendframes':
480 # We assume we haven't started sending the response yet. If we're
479 # We assume we haven't started sending the response yet. If we're
481 # wrong, the response type will raise an exception.
480 # wrong, the response type will raise an exception.
482 res.status = b'200 OK'
481 res.status = b'200 OK'
483 res.headers[b'Content-Type'] = FRAMINGTYPE
482 res.headers[b'Content-Type'] = FRAMINGTYPE
484 res.setbodygen(meta['framegen'])
483 res.setbodygen(meta['framegen'])
485 elif action == 'noop':
484 elif action == 'noop':
486 pass
485 pass
487 else:
486 else:
488 raise error.ProgrammingError('unhandled action from frame processor: %s'
487 raise error.ProgrammingError('unhandled action from frame processor: %s'
489 % action)
488 % action)
490
489
491 def _httpv2runcommand(ui, repo, req, res, authedperm, reqcommand, reactor,
490 def _httpv2runcommand(ui, repo, req, res, authedperm, reqcommand, reactor,
492 outstream, command, issubsequent):
491 outstream, command, issubsequent):
493 """Dispatch a wire protocol command made from HTTPv2 requests.
492 """Dispatch a wire protocol command made from HTTPv2 requests.
494
493
495 The authenticated permission (``authedperm``) along with the original
494 The authenticated permission (``authedperm``) along with the original
496 command from the URL (``reqcommand``) are passed in.
495 command from the URL (``reqcommand``) are passed in.
497 """
496 """
498 # We already validated that the session has permissions to perform the
497 # We already validated that the session has permissions to perform the
499 # actions in ``authedperm``. In the unified frame protocol, the canonical
498 # actions in ``authedperm``. In the unified frame protocol, the canonical
500 # command to run is expressed in a frame. However, the URL also requested
499 # command to run is expressed in a frame. However, the URL also requested
501 # to run a specific command. We need to be careful that the command we
500 # to run a specific command. We need to be careful that the command we
502 # run doesn't have permissions requirements greater than what was granted
501 # run doesn't have permissions requirements greater than what was granted
503 # by ``authedperm``.
502 # by ``authedperm``.
504 #
503 #
505 # Our rule for this is we only allow one command per HTTP request and
504 # Our rule for this is we only allow one command per HTTP request and
506 # that command must match the command in the URL. However, we make
505 # that command must match the command in the URL. However, we make
507 # an exception for the ``multirequest`` URL. This URL is allowed to
506 # an exception for the ``multirequest`` URL. This URL is allowed to
508 # execute multiple commands. We double check permissions of each command
507 # execute multiple commands. We double check permissions of each command
509 # as it is invoked to ensure there is no privilege escalation.
508 # as it is invoked to ensure there is no privilege escalation.
510 # TODO consider allowing multiple commands to regular command URLs
509 # TODO consider allowing multiple commands to regular command URLs
511 # iff each command is the same.
510 # iff each command is the same.
512
511
513 proto = httpv2protocolhandler(req, ui, args=command['args'])
512 proto = httpv2protocolhandler(req, ui, args=command['args'])
514
513
515 if reqcommand == b'multirequest':
514 if reqcommand == b'multirequest':
516 if not wireproto.commandsv2.commandavailable(command['command'], proto):
515 if not wireproto.commandsv2.commandavailable(command['command'], proto):
517 # TODO proper error mechanism
516 # TODO proper error mechanism
518 res.status = b'200 OK'
517 res.status = b'200 OK'
519 res.headers[b'Content-Type'] = b'text/plain'
518 res.headers[b'Content-Type'] = b'text/plain'
520 res.setbodybytes(_('wire protocol command not available: %s') %
519 res.setbodybytes(_('wire protocol command not available: %s') %
521 command['command'])
520 command['command'])
522 return True
521 return True
523
522
524 # TODO don't use assert here, since it may be elided by -O.
523 # TODO don't use assert here, since it may be elided by -O.
525 assert authedperm in (b'ro', b'rw')
524 assert authedperm in (b'ro', b'rw')
526 wirecommand = wireproto.commandsv2[command['command']]
525 wirecommand = wireproto.commandsv2[command['command']]
527 assert wirecommand.permission in ('push', 'pull')
526 assert wirecommand.permission in ('push', 'pull')
528
527
529 if authedperm == b'ro' and wirecommand.permission != 'pull':
528 if authedperm == b'ro' and wirecommand.permission != 'pull':
530 # TODO proper error mechanism
529 # TODO proper error mechanism
531 res.status = b'403 Forbidden'
530 res.status = b'403 Forbidden'
532 res.headers[b'Content-Type'] = b'text/plain'
531 res.headers[b'Content-Type'] = b'text/plain'
533 res.setbodybytes(_('insufficient permissions to execute '
532 res.setbodybytes(_('insufficient permissions to execute '
534 'command: %s') % command['command'])
533 'command: %s') % command['command'])
535 return True
534 return True
536
535
537 # TODO should we also call checkperm() here? Maybe not if we're going
536 # TODO should we also call checkperm() here? Maybe not if we're going
538 # to overhaul that API. The granted scope from the URL check should
537 # to overhaul that API. The granted scope from the URL check should
539 # be good enough.
538 # be good enough.
540
539
541 else:
540 else:
542 # Don't allow multiple commands outside of ``multirequest`` URL.
541 # Don't allow multiple commands outside of ``multirequest`` URL.
543 if issubsequent:
542 if issubsequent:
544 # TODO proper error mechanism
543 # TODO proper error mechanism
545 res.status = b'200 OK'
544 res.status = b'200 OK'
546 res.headers[b'Content-Type'] = b'text/plain'
545 res.headers[b'Content-Type'] = b'text/plain'
547 res.setbodybytes(_('multiple commands cannot be issued to this '
546 res.setbodybytes(_('multiple commands cannot be issued to this '
548 'URL'))
547 'URL'))
549 return True
548 return True
550
549
551 if reqcommand != command['command']:
550 if reqcommand != command['command']:
552 # TODO define proper error mechanism
551 # TODO define proper error mechanism
553 res.status = b'200 OK'
552 res.status = b'200 OK'
554 res.headers[b'Content-Type'] = b'text/plain'
553 res.headers[b'Content-Type'] = b'text/plain'
555 res.setbodybytes(_('command in frame must match command in URL'))
554 res.setbodybytes(_('command in frame must match command in URL'))
556 return True
555 return True
557
556
558 rsp = wireproto.dispatch(repo, proto, command['command'])
557 rsp = wireproto.dispatch(repo, proto, command['command'])
559
558
560 res.status = b'200 OK'
559 res.status = b'200 OK'
561 res.headers[b'Content-Type'] = FRAMINGTYPE
560 res.headers[b'Content-Type'] = FRAMINGTYPE
562
561
563 if isinstance(rsp, wireprototypes.bytesresponse):
562 if isinstance(rsp, wireprototypes.bytesresponse):
564 action, meta = reactor.onbytesresponseready(outstream,
563 action, meta = reactor.onbytesresponseready(outstream,
565 command['requestid'],
564 command['requestid'],
566 rsp.data)
565 rsp.data)
567 else:
566 else:
568 action, meta = reactor.onapplicationerror(
567 action, meta = reactor.onapplicationerror(
569 _('unhandled response type from wire proto command'))
568 _('unhandled response type from wire proto command'))
570
569
571 if action == 'sendframes':
570 if action == 'sendframes':
572 res.setbodygen(meta['framegen'])
571 res.setbodygen(meta['framegen'])
573 return True
572 return True
574 elif action == 'noop':
573 elif action == 'noop':
575 return False
574 return False
576 else:
575 else:
577 raise error.ProgrammingError('unhandled event from reactor: %s' %
576 raise error.ProgrammingError('unhandled event from reactor: %s' %
578 action)
577 action)
579
578
580 # Maps API name to metadata so custom API can be registered.
579 # Maps API name to metadata so custom API can be registered.
581 API_HANDLERS = {
580 API_HANDLERS = {
582 HTTPV2: {
581 HTTPV2: {
583 'config': ('experimental', 'web.api.http-v2'),
582 'config': ('experimental', 'web.api.http-v2'),
584 'handler': _handlehttpv2request,
583 'handler': _handlehttpv2request,
585 },
584 },
586 }
585 }
587
586
588 @zi.implementer(wireprototypes.baseprotocolhandler)
587 @zi.implementer(wireprototypes.baseprotocolhandler)
589 class httpv2protocolhandler(object):
588 class httpv2protocolhandler(object):
590 def __init__(self, req, ui, args=None):
589 def __init__(self, req, ui, args=None):
591 self._req = req
590 self._req = req
592 self._ui = ui
591 self._ui = ui
593 self._args = args
592 self._args = args
594
593
595 @property
594 @property
596 def name(self):
595 def name(self):
597 return HTTPV2
596 return HTTPV2
598
597
599 def getargs(self, args):
598 def getargs(self, args):
600 data = {}
599 data = {}
601 for k in args.split():
600 for k in args.split():
602 if k == '*':
601 if k == '*':
603 raise NotImplementedError('do not support * args')
602 raise NotImplementedError('do not support * args')
604 else:
603 else:
605 data[k] = self._args[k]
604 data[k] = self._args[k]
606
605
607 return [data[k] for k in args.split()]
606 return [data[k] for k in args.split()]
608
607
609 def getprotocaps(self):
608 def getprotocaps(self):
610 # Protocol capabilities are currently not implemented for HTTP V2.
609 # Protocol capabilities are currently not implemented for HTTP V2.
611 return set()
610 return set()
612
611
613 def forwardpayload(self, fp):
612 def getpayload(self):
614 raise NotImplementedError
613 raise NotImplementedError
615
614
616 @contextlib.contextmanager
615 @contextlib.contextmanager
617 def mayberedirectstdio(self):
616 def mayberedirectstdio(self):
618 raise NotImplementedError
617 raise NotImplementedError
619
618
620 def client(self):
619 def client(self):
621 raise NotImplementedError
620 raise NotImplementedError
622
621
623 def addcapabilities(self, repo, caps):
622 def addcapabilities(self, repo, caps):
624 return caps
623 return caps
625
624
626 def checkperm(self, perm):
625 def checkperm(self, perm):
627 raise NotImplementedError
626 raise NotImplementedError
628
627
629 def _httpresponsetype(ui, proto, prefer_uncompressed):
628 def _httpresponsetype(ui, proto, prefer_uncompressed):
630 """Determine the appropriate response type and compression settings.
629 """Determine the appropriate response type and compression settings.
631
630
632 Returns a tuple of (mediatype, compengine, engineopts).
631 Returns a tuple of (mediatype, compengine, engineopts).
633 """
632 """
634 # Determine the response media type and compression engine based
633 # Determine the response media type and compression engine based
635 # on the request parameters.
634 # on the request parameters.
636
635
637 if '0.2' in proto.getprotocaps():
636 if '0.2' in proto.getprotocaps():
638 # All clients are expected to support uncompressed data.
637 # All clients are expected to support uncompressed data.
639 if prefer_uncompressed:
638 if prefer_uncompressed:
640 return HGTYPE2, util._noopengine(), {}
639 return HGTYPE2, util._noopengine(), {}
641
640
642 # Now find an agreed upon compression format.
641 # Now find an agreed upon compression format.
643 compformats = wireproto.clientcompressionsupport(proto)
642 compformats = wireproto.clientcompressionsupport(proto)
644 for engine in wireproto.supportedcompengines(ui, util.SERVERROLE):
643 for engine in wireproto.supportedcompengines(ui, util.SERVERROLE):
645 if engine.wireprotosupport().name in compformats:
644 if engine.wireprotosupport().name in compformats:
646 opts = {}
645 opts = {}
647 level = ui.configint('server', '%slevel' % engine.name())
646 level = ui.configint('server', '%slevel' % engine.name())
648 if level is not None:
647 if level is not None:
649 opts['level'] = level
648 opts['level'] = level
650
649
651 return HGTYPE2, engine, opts
650 return HGTYPE2, engine, opts
652
651
653 # No mutually supported compression format. Fall back to the
652 # No mutually supported compression format. Fall back to the
654 # legacy protocol.
653 # legacy protocol.
655
654
656 # Don't allow untrusted settings because disabling compression or
655 # Don't allow untrusted settings because disabling compression or
657 # setting a very high compression level could lead to flooding
656 # setting a very high compression level could lead to flooding
658 # the server's network or CPU.
657 # the server's network or CPU.
659 opts = {'level': ui.configint('server', 'zliblevel')}
658 opts = {'level': ui.configint('server', 'zliblevel')}
660 return HGTYPE, util.compengines['zlib'], opts
659 return HGTYPE, util.compengines['zlib'], opts
661
660
662 def _callhttp(repo, req, res, proto, cmd):
661 def _callhttp(repo, req, res, proto, cmd):
663 # Avoid cycle involving hg module.
662 # Avoid cycle involving hg module.
664 from .hgweb import common as hgwebcommon
663 from .hgweb import common as hgwebcommon
665
664
666 def genversion2(gen, engine, engineopts):
665 def genversion2(gen, engine, engineopts):
667 # application/mercurial-0.2 always sends a payload header
666 # application/mercurial-0.2 always sends a payload header
668 # identifying the compression engine.
667 # identifying the compression engine.
669 name = engine.wireprotosupport().name
668 name = engine.wireprotosupport().name
670 assert 0 < len(name) < 256
669 assert 0 < len(name) < 256
671 yield struct.pack('B', len(name))
670 yield struct.pack('B', len(name))
672 yield name
671 yield name
673
672
674 for chunk in gen:
673 for chunk in gen:
675 yield chunk
674 yield chunk
676
675
677 def setresponse(code, contenttype, bodybytes=None, bodygen=None):
676 def setresponse(code, contenttype, bodybytes=None, bodygen=None):
678 if code == HTTP_OK:
677 if code == HTTP_OK:
679 res.status = '200 Script output follows'
678 res.status = '200 Script output follows'
680 else:
679 else:
681 res.status = hgwebcommon.statusmessage(code)
680 res.status = hgwebcommon.statusmessage(code)
682
681
683 res.headers['Content-Type'] = contenttype
682 res.headers['Content-Type'] = contenttype
684
683
685 if bodybytes is not None:
684 if bodybytes is not None:
686 res.setbodybytes(bodybytes)
685 res.setbodybytes(bodybytes)
687 if bodygen is not None:
686 if bodygen is not None:
688 res.setbodygen(bodygen)
687 res.setbodygen(bodygen)
689
688
690 if not wireproto.commands.commandavailable(cmd, proto):
689 if not wireproto.commands.commandavailable(cmd, proto):
691 setresponse(HTTP_OK, HGERRTYPE,
690 setresponse(HTTP_OK, HGERRTYPE,
692 _('requested wire protocol command is not available over '
691 _('requested wire protocol command is not available over '
693 'HTTP'))
692 'HTTP'))
694 return
693 return
695
694
696 proto.checkperm(wireproto.commands[cmd].permission)
695 proto.checkperm(wireproto.commands[cmd].permission)
697
696
698 rsp = wireproto.dispatch(repo, proto, cmd)
697 rsp = wireproto.dispatch(repo, proto, cmd)
699
698
700 if isinstance(rsp, bytes):
699 if isinstance(rsp, bytes):
701 setresponse(HTTP_OK, HGTYPE, bodybytes=rsp)
700 setresponse(HTTP_OK, HGTYPE, bodybytes=rsp)
702 elif isinstance(rsp, wireprototypes.bytesresponse):
701 elif isinstance(rsp, wireprototypes.bytesresponse):
703 setresponse(HTTP_OK, HGTYPE, bodybytes=rsp.data)
702 setresponse(HTTP_OK, HGTYPE, bodybytes=rsp.data)
704 elif isinstance(rsp, wireprototypes.streamreslegacy):
703 elif isinstance(rsp, wireprototypes.streamreslegacy):
705 setresponse(HTTP_OK, HGTYPE, bodygen=rsp.gen)
704 setresponse(HTTP_OK, HGTYPE, bodygen=rsp.gen)
706 elif isinstance(rsp, wireprototypes.streamres):
705 elif isinstance(rsp, wireprototypes.streamres):
707 gen = rsp.gen
706 gen = rsp.gen
708
707
709 # This code for compression should not be streamres specific. It
708 # This code for compression should not be streamres specific. It
710 # is here because we only compress streamres at the moment.
709 # is here because we only compress streamres at the moment.
711 mediatype, engine, engineopts = _httpresponsetype(
710 mediatype, engine, engineopts = _httpresponsetype(
712 repo.ui, proto, rsp.prefer_uncompressed)
711 repo.ui, proto, rsp.prefer_uncompressed)
713 gen = engine.compressstream(gen, engineopts)
712 gen = engine.compressstream(gen, engineopts)
714
713
715 if mediatype == HGTYPE2:
714 if mediatype == HGTYPE2:
716 gen = genversion2(gen, engine, engineopts)
715 gen = genversion2(gen, engine, engineopts)
717
716
718 setresponse(HTTP_OK, mediatype, bodygen=gen)
717 setresponse(HTTP_OK, mediatype, bodygen=gen)
719 elif isinstance(rsp, wireprototypes.pushres):
718 elif isinstance(rsp, wireprototypes.pushres):
720 rsp = '%d\n%s' % (rsp.res, rsp.output)
719 rsp = '%d\n%s' % (rsp.res, rsp.output)
721 setresponse(HTTP_OK, HGTYPE, bodybytes=rsp)
720 setresponse(HTTP_OK, HGTYPE, bodybytes=rsp)
722 elif isinstance(rsp, wireprototypes.pusherr):
721 elif isinstance(rsp, wireprototypes.pusherr):
723 rsp = '0\n%s\n' % rsp.res
722 rsp = '0\n%s\n' % rsp.res
724 res.drain = True
723 res.drain = True
725 setresponse(HTTP_OK, HGTYPE, bodybytes=rsp)
724 setresponse(HTTP_OK, HGTYPE, bodybytes=rsp)
726 elif isinstance(rsp, wireprototypes.ooberror):
725 elif isinstance(rsp, wireprototypes.ooberror):
727 setresponse(HTTP_OK, HGERRTYPE, bodybytes=rsp.message)
726 setresponse(HTTP_OK, HGERRTYPE, bodybytes=rsp.message)
728 else:
727 else:
729 raise error.ProgrammingError('hgweb.protocol internal failure', rsp)
728 raise error.ProgrammingError('hgweb.protocol internal failure', rsp)
730
729
731 def _sshv1respondbytes(fout, value):
730 def _sshv1respondbytes(fout, value):
732 """Send a bytes response for protocol version 1."""
731 """Send a bytes response for protocol version 1."""
733 fout.write('%d\n' % len(value))
732 fout.write('%d\n' % len(value))
734 fout.write(value)
733 fout.write(value)
735 fout.flush()
734 fout.flush()
736
735
737 def _sshv1respondstream(fout, source):
736 def _sshv1respondstream(fout, source):
738 write = fout.write
737 write = fout.write
739 for chunk in source.gen:
738 for chunk in source.gen:
740 write(chunk)
739 write(chunk)
741 fout.flush()
740 fout.flush()
742
741
743 def _sshv1respondooberror(fout, ferr, rsp):
742 def _sshv1respondooberror(fout, ferr, rsp):
744 ferr.write(b'%s\n-\n' % rsp)
743 ferr.write(b'%s\n-\n' % rsp)
745 ferr.flush()
744 ferr.flush()
746 fout.write(b'\n')
745 fout.write(b'\n')
747 fout.flush()
746 fout.flush()
748
747
749 @zi.implementer(wireprototypes.baseprotocolhandler)
748 @zi.implementer(wireprototypes.baseprotocolhandler)
750 class sshv1protocolhandler(object):
749 class sshv1protocolhandler(object):
751 """Handler for requests services via version 1 of SSH protocol."""
750 """Handler for requests services via version 1 of SSH protocol."""
752 def __init__(self, ui, fin, fout):
751 def __init__(self, ui, fin, fout):
753 self._ui = ui
752 self._ui = ui
754 self._fin = fin
753 self._fin = fin
755 self._fout = fout
754 self._fout = fout
756 self._protocaps = set()
755 self._protocaps = set()
757
756
758 @property
757 @property
759 def name(self):
758 def name(self):
760 return wireprototypes.SSHV1
759 return wireprototypes.SSHV1
761
760
762 def getargs(self, args):
761 def getargs(self, args):
763 data = {}
762 data = {}
764 keys = args.split()
763 keys = args.split()
765 for n in xrange(len(keys)):
764 for n in xrange(len(keys)):
766 argline = self._fin.readline()[:-1]
765 argline = self._fin.readline()[:-1]
767 arg, l = argline.split()
766 arg, l = argline.split()
768 if arg not in keys:
767 if arg not in keys:
769 raise error.Abort(_("unexpected parameter %r") % arg)
768 raise error.Abort(_("unexpected parameter %r") % arg)
770 if arg == '*':
769 if arg == '*':
771 star = {}
770 star = {}
772 for k in xrange(int(l)):
771 for k in xrange(int(l)):
773 argline = self._fin.readline()[:-1]
772 argline = self._fin.readline()[:-1]
774 arg, l = argline.split()
773 arg, l = argline.split()
775 val = self._fin.read(int(l))
774 val = self._fin.read(int(l))
776 star[arg] = val
775 star[arg] = val
777 data['*'] = star
776 data['*'] = star
778 else:
777 else:
779 val = self._fin.read(int(l))
778 val = self._fin.read(int(l))
780 data[arg] = val
779 data[arg] = val
781 return [data[k] for k in keys]
780 return [data[k] for k in keys]
782
781
783 def getprotocaps(self):
782 def getprotocaps(self):
784 return self._protocaps
783 return self._protocaps
785
784
786 def forwardpayload(self, fpout):
785 def getpayload(self):
787 # We initially send an empty response. This tells the client it is
786 # We initially send an empty response. This tells the client it is
788 # OK to start sending data. If a client sees any other response, it
787 # OK to start sending data. If a client sees any other response, it
789 # interprets it as an error.
788 # interprets it as an error.
790 _sshv1respondbytes(self._fout, b'')
789 _sshv1respondbytes(self._fout, b'')
791
790
792 # The file is in the form:
791 # The file is in the form:
793 #
792 #
794 # <chunk size>\n<chunk>
793 # <chunk size>\n<chunk>
795 # ...
794 # ...
796 # 0\n
795 # 0\n
797 count = int(self._fin.readline())
796 count = int(self._fin.readline())
798 while count:
797 while count:
799 fpout.write(self._fin.read(count))
798 yield self._fin.read(count)
800 count = int(self._fin.readline())
799 count = int(self._fin.readline())
801
800
802 @contextlib.contextmanager
801 @contextlib.contextmanager
803 def mayberedirectstdio(self):
802 def mayberedirectstdio(self):
804 yield None
803 yield None
805
804
806 def client(self):
805 def client(self):
807 client = encoding.environ.get('SSH_CLIENT', '').split(' ', 1)[0]
806 client = encoding.environ.get('SSH_CLIENT', '').split(' ', 1)[0]
808 return 'remote:ssh:' + client
807 return 'remote:ssh:' + client
809
808
810 def addcapabilities(self, repo, caps):
809 def addcapabilities(self, repo, caps):
811 if self.name == wireprototypes.SSHV1:
810 if self.name == wireprototypes.SSHV1:
812 caps.append(b'protocaps')
811 caps.append(b'protocaps')
813 caps.append(b'batch')
812 caps.append(b'batch')
814 return caps
813 return caps
815
814
816 def checkperm(self, perm):
815 def checkperm(self, perm):
817 pass
816 pass
818
817
819 class sshv2protocolhandler(sshv1protocolhandler):
818 class sshv2protocolhandler(sshv1protocolhandler):
820 """Protocol handler for version 2 of the SSH protocol."""
819 """Protocol handler for version 2 of the SSH protocol."""
821
820
822 @property
821 @property
823 def name(self):
822 def name(self):
824 return wireprototypes.SSHV2
823 return wireprototypes.SSHV2
825
824
826 def _runsshserver(ui, repo, fin, fout, ev):
825 def _runsshserver(ui, repo, fin, fout, ev):
827 # This function operates like a state machine of sorts. The following
826 # This function operates like a state machine of sorts. The following
828 # states are defined:
827 # states are defined:
829 #
828 #
830 # protov1-serving
829 # protov1-serving
831 # Server is in protocol version 1 serving mode. Commands arrive on
830 # Server is in protocol version 1 serving mode. Commands arrive on
832 # new lines. These commands are processed in this state, one command
831 # new lines. These commands are processed in this state, one command
833 # after the other.
832 # after the other.
834 #
833 #
835 # protov2-serving
834 # protov2-serving
836 # Server is in protocol version 2 serving mode.
835 # Server is in protocol version 2 serving mode.
837 #
836 #
838 # upgrade-initial
837 # upgrade-initial
839 # The server is going to process an upgrade request.
838 # The server is going to process an upgrade request.
840 #
839 #
841 # upgrade-v2-filter-legacy-handshake
840 # upgrade-v2-filter-legacy-handshake
842 # The protocol is being upgraded to version 2. The server is expecting
841 # The protocol is being upgraded to version 2. The server is expecting
843 # the legacy handshake from version 1.
842 # the legacy handshake from version 1.
844 #
843 #
845 # upgrade-v2-finish
844 # upgrade-v2-finish
846 # The upgrade to version 2 of the protocol is imminent.
845 # The upgrade to version 2 of the protocol is imminent.
847 #
846 #
848 # shutdown
847 # shutdown
849 # The server is shutting down, possibly in reaction to a client event.
848 # The server is shutting down, possibly in reaction to a client event.
850 #
849 #
851 # And here are their transitions:
850 # And here are their transitions:
852 #
851 #
853 # protov1-serving -> shutdown
852 # protov1-serving -> shutdown
854 # When server receives an empty request or encounters another
853 # When server receives an empty request or encounters another
855 # error.
854 # error.
856 #
855 #
857 # protov1-serving -> upgrade-initial
856 # protov1-serving -> upgrade-initial
858 # An upgrade request line was seen.
857 # An upgrade request line was seen.
859 #
858 #
860 # upgrade-initial -> upgrade-v2-filter-legacy-handshake
859 # upgrade-initial -> upgrade-v2-filter-legacy-handshake
861 # Upgrade to version 2 in progress. Server is expecting to
860 # Upgrade to version 2 in progress. Server is expecting to
862 # process a legacy handshake.
861 # process a legacy handshake.
863 #
862 #
864 # upgrade-v2-filter-legacy-handshake -> shutdown
863 # upgrade-v2-filter-legacy-handshake -> shutdown
865 # Client did not fulfill upgrade handshake requirements.
864 # Client did not fulfill upgrade handshake requirements.
866 #
865 #
867 # upgrade-v2-filter-legacy-handshake -> upgrade-v2-finish
866 # upgrade-v2-filter-legacy-handshake -> upgrade-v2-finish
868 # Client fulfilled version 2 upgrade requirements. Finishing that
867 # Client fulfilled version 2 upgrade requirements. Finishing that
869 # upgrade.
868 # upgrade.
870 #
869 #
871 # upgrade-v2-finish -> protov2-serving
870 # upgrade-v2-finish -> protov2-serving
872 # Protocol upgrade to version 2 complete. Server can now speak protocol
871 # Protocol upgrade to version 2 complete. Server can now speak protocol
873 # version 2.
872 # version 2.
874 #
873 #
875 # protov2-serving -> protov1-serving
874 # protov2-serving -> protov1-serving
876 # Ths happens by default since protocol version 2 is the same as
875 # Ths happens by default since protocol version 2 is the same as
877 # version 1 except for the handshake.
876 # version 1 except for the handshake.
878
877
879 state = 'protov1-serving'
878 state = 'protov1-serving'
880 proto = sshv1protocolhandler(ui, fin, fout)
879 proto = sshv1protocolhandler(ui, fin, fout)
881 protoswitched = False
880 protoswitched = False
882
881
883 while not ev.is_set():
882 while not ev.is_set():
884 if state == 'protov1-serving':
883 if state == 'protov1-serving':
885 # Commands are issued on new lines.
884 # Commands are issued on new lines.
886 request = fin.readline()[:-1]
885 request = fin.readline()[:-1]
887
886
888 # Empty lines signal to terminate the connection.
887 # Empty lines signal to terminate the connection.
889 if not request:
888 if not request:
890 state = 'shutdown'
889 state = 'shutdown'
891 continue
890 continue
892
891
893 # It looks like a protocol upgrade request. Transition state to
892 # It looks like a protocol upgrade request. Transition state to
894 # handle it.
893 # handle it.
895 if request.startswith(b'upgrade '):
894 if request.startswith(b'upgrade '):
896 if protoswitched:
895 if protoswitched:
897 _sshv1respondooberror(fout, ui.ferr,
896 _sshv1respondooberror(fout, ui.ferr,
898 b'cannot upgrade protocols multiple '
897 b'cannot upgrade protocols multiple '
899 b'times')
898 b'times')
900 state = 'shutdown'
899 state = 'shutdown'
901 continue
900 continue
902
901
903 state = 'upgrade-initial'
902 state = 'upgrade-initial'
904 continue
903 continue
905
904
906 available = wireproto.commands.commandavailable(request, proto)
905 available = wireproto.commands.commandavailable(request, proto)
907
906
908 # This command isn't available. Send an empty response and go
907 # This command isn't available. Send an empty response and go
909 # back to waiting for a new command.
908 # back to waiting for a new command.
910 if not available:
909 if not available:
911 _sshv1respondbytes(fout, b'')
910 _sshv1respondbytes(fout, b'')
912 continue
911 continue
913
912
914 rsp = wireproto.dispatch(repo, proto, request)
913 rsp = wireproto.dispatch(repo, proto, request)
915
914
916 if isinstance(rsp, bytes):
915 if isinstance(rsp, bytes):
917 _sshv1respondbytes(fout, rsp)
916 _sshv1respondbytes(fout, rsp)
918 elif isinstance(rsp, wireprototypes.bytesresponse):
917 elif isinstance(rsp, wireprototypes.bytesresponse):
919 _sshv1respondbytes(fout, rsp.data)
918 _sshv1respondbytes(fout, rsp.data)
920 elif isinstance(rsp, wireprototypes.streamres):
919 elif isinstance(rsp, wireprototypes.streamres):
921 _sshv1respondstream(fout, rsp)
920 _sshv1respondstream(fout, rsp)
922 elif isinstance(rsp, wireprototypes.streamreslegacy):
921 elif isinstance(rsp, wireprototypes.streamreslegacy):
923 _sshv1respondstream(fout, rsp)
922 _sshv1respondstream(fout, rsp)
924 elif isinstance(rsp, wireprototypes.pushres):
923 elif isinstance(rsp, wireprototypes.pushres):
925 _sshv1respondbytes(fout, b'')
924 _sshv1respondbytes(fout, b'')
926 _sshv1respondbytes(fout, b'%d' % rsp.res)
925 _sshv1respondbytes(fout, b'%d' % rsp.res)
927 elif isinstance(rsp, wireprototypes.pusherr):
926 elif isinstance(rsp, wireprototypes.pusherr):
928 _sshv1respondbytes(fout, rsp.res)
927 _sshv1respondbytes(fout, rsp.res)
929 elif isinstance(rsp, wireprototypes.ooberror):
928 elif isinstance(rsp, wireprototypes.ooberror):
930 _sshv1respondooberror(fout, ui.ferr, rsp.message)
929 _sshv1respondooberror(fout, ui.ferr, rsp.message)
931 else:
930 else:
932 raise error.ProgrammingError('unhandled response type from '
931 raise error.ProgrammingError('unhandled response type from '
933 'wire protocol command: %s' % rsp)
932 'wire protocol command: %s' % rsp)
934
933
935 # For now, protocol version 2 serving just goes back to version 1.
934 # For now, protocol version 2 serving just goes back to version 1.
936 elif state == 'protov2-serving':
935 elif state == 'protov2-serving':
937 state = 'protov1-serving'
936 state = 'protov1-serving'
938 continue
937 continue
939
938
940 elif state == 'upgrade-initial':
939 elif state == 'upgrade-initial':
941 # We should never transition into this state if we've switched
940 # We should never transition into this state if we've switched
942 # protocols.
941 # protocols.
943 assert not protoswitched
942 assert not protoswitched
944 assert proto.name == wireprototypes.SSHV1
943 assert proto.name == wireprototypes.SSHV1
945
944
946 # Expected: upgrade <token> <capabilities>
945 # Expected: upgrade <token> <capabilities>
947 # If we get something else, the request is malformed. It could be
946 # If we get something else, the request is malformed. It could be
948 # from a future client that has altered the upgrade line content.
947 # from a future client that has altered the upgrade line content.
949 # We treat this as an unknown command.
948 # We treat this as an unknown command.
950 try:
949 try:
951 token, caps = request.split(b' ')[1:]
950 token, caps = request.split(b' ')[1:]
952 except ValueError:
951 except ValueError:
953 _sshv1respondbytes(fout, b'')
952 _sshv1respondbytes(fout, b'')
954 state = 'protov1-serving'
953 state = 'protov1-serving'
955 continue
954 continue
956
955
957 # Send empty response if we don't support upgrading protocols.
956 # Send empty response if we don't support upgrading protocols.
958 if not ui.configbool('experimental', 'sshserver.support-v2'):
957 if not ui.configbool('experimental', 'sshserver.support-v2'):
959 _sshv1respondbytes(fout, b'')
958 _sshv1respondbytes(fout, b'')
960 state = 'protov1-serving'
959 state = 'protov1-serving'
961 continue
960 continue
962
961
963 try:
962 try:
964 caps = urlreq.parseqs(caps)
963 caps = urlreq.parseqs(caps)
965 except ValueError:
964 except ValueError:
966 _sshv1respondbytes(fout, b'')
965 _sshv1respondbytes(fout, b'')
967 state = 'protov1-serving'
966 state = 'protov1-serving'
968 continue
967 continue
969
968
970 # We don't see an upgrade request to protocol version 2. Ignore
969 # We don't see an upgrade request to protocol version 2. Ignore
971 # the upgrade request.
970 # the upgrade request.
972 wantedprotos = caps.get(b'proto', [b''])[0]
971 wantedprotos = caps.get(b'proto', [b''])[0]
973 if SSHV2 not in wantedprotos:
972 if SSHV2 not in wantedprotos:
974 _sshv1respondbytes(fout, b'')
973 _sshv1respondbytes(fout, b'')
975 state = 'protov1-serving'
974 state = 'protov1-serving'
976 continue
975 continue
977
976
978 # It looks like we can honor this upgrade request to protocol 2.
977 # It looks like we can honor this upgrade request to protocol 2.
979 # Filter the rest of the handshake protocol request lines.
978 # Filter the rest of the handshake protocol request lines.
980 state = 'upgrade-v2-filter-legacy-handshake'
979 state = 'upgrade-v2-filter-legacy-handshake'
981 continue
980 continue
982
981
983 elif state == 'upgrade-v2-filter-legacy-handshake':
982 elif state == 'upgrade-v2-filter-legacy-handshake':
984 # Client should have sent legacy handshake after an ``upgrade``
983 # Client should have sent legacy handshake after an ``upgrade``
985 # request. Expected lines:
984 # request. Expected lines:
986 #
985 #
987 # hello
986 # hello
988 # between
987 # between
989 # pairs 81
988 # pairs 81
990 # 0000...-0000...
989 # 0000...-0000...
991
990
992 ok = True
991 ok = True
993 for line in (b'hello', b'between', b'pairs 81'):
992 for line in (b'hello', b'between', b'pairs 81'):
994 request = fin.readline()[:-1]
993 request = fin.readline()[:-1]
995
994
996 if request != line:
995 if request != line:
997 _sshv1respondooberror(fout, ui.ferr,
996 _sshv1respondooberror(fout, ui.ferr,
998 b'malformed handshake protocol: '
997 b'malformed handshake protocol: '
999 b'missing %s' % line)
998 b'missing %s' % line)
1000 ok = False
999 ok = False
1001 state = 'shutdown'
1000 state = 'shutdown'
1002 break
1001 break
1003
1002
1004 if not ok:
1003 if not ok:
1005 continue
1004 continue
1006
1005
1007 request = fin.read(81)
1006 request = fin.read(81)
1008 if request != b'%s-%s' % (b'0' * 40, b'0' * 40):
1007 if request != b'%s-%s' % (b'0' * 40, b'0' * 40):
1009 _sshv1respondooberror(fout, ui.ferr,
1008 _sshv1respondooberror(fout, ui.ferr,
1010 b'malformed handshake protocol: '
1009 b'malformed handshake protocol: '
1011 b'missing between argument value')
1010 b'missing between argument value')
1012 state = 'shutdown'
1011 state = 'shutdown'
1013 continue
1012 continue
1014
1013
1015 state = 'upgrade-v2-finish'
1014 state = 'upgrade-v2-finish'
1016 continue
1015 continue
1017
1016
1018 elif state == 'upgrade-v2-finish':
1017 elif state == 'upgrade-v2-finish':
1019 # Send the upgrade response.
1018 # Send the upgrade response.
1020 fout.write(b'upgraded %s %s\n' % (token, SSHV2))
1019 fout.write(b'upgraded %s %s\n' % (token, SSHV2))
1021 servercaps = wireproto.capabilities(repo, proto)
1020 servercaps = wireproto.capabilities(repo, proto)
1022 rsp = b'capabilities: %s' % servercaps.data
1021 rsp = b'capabilities: %s' % servercaps.data
1023 fout.write(b'%d\n%s\n' % (len(rsp), rsp))
1022 fout.write(b'%d\n%s\n' % (len(rsp), rsp))
1024 fout.flush()
1023 fout.flush()
1025
1024
1026 proto = sshv2protocolhandler(ui, fin, fout)
1025 proto = sshv2protocolhandler(ui, fin, fout)
1027 protoswitched = True
1026 protoswitched = True
1028
1027
1029 state = 'protov2-serving'
1028 state = 'protov2-serving'
1030 continue
1029 continue
1031
1030
1032 elif state == 'shutdown':
1031 elif state == 'shutdown':
1033 break
1032 break
1034
1033
1035 else:
1034 else:
1036 raise error.ProgrammingError('unhandled ssh server state: %s' %
1035 raise error.ProgrammingError('unhandled ssh server state: %s' %
1037 state)
1036 state)
1038
1037
1039 class sshserver(object):
1038 class sshserver(object):
1040 def __init__(self, ui, repo, logfh=None):
1039 def __init__(self, ui, repo, logfh=None):
1041 self._ui = ui
1040 self._ui = ui
1042 self._repo = repo
1041 self._repo = repo
1043 self._fin = ui.fin
1042 self._fin = ui.fin
1044 self._fout = ui.fout
1043 self._fout = ui.fout
1045
1044
1046 # Log write I/O to stdout and stderr if configured.
1045 # Log write I/O to stdout and stderr if configured.
1047 if logfh:
1046 if logfh:
1048 self._fout = util.makeloggingfileobject(
1047 self._fout = util.makeloggingfileobject(
1049 logfh, self._fout, 'o', logdata=True)
1048 logfh, self._fout, 'o', logdata=True)
1050 ui.ferr = util.makeloggingfileobject(
1049 ui.ferr = util.makeloggingfileobject(
1051 logfh, ui.ferr, 'e', logdata=True)
1050 logfh, ui.ferr, 'e', logdata=True)
1052
1051
1053 hook.redirect(True)
1052 hook.redirect(True)
1054 ui.fout = repo.ui.fout = ui.ferr
1053 ui.fout = repo.ui.fout = ui.ferr
1055
1054
1056 # Prevent insertion/deletion of CRs
1055 # Prevent insertion/deletion of CRs
1057 procutil.setbinary(self._fin)
1056 procutil.setbinary(self._fin)
1058 procutil.setbinary(self._fout)
1057 procutil.setbinary(self._fout)
1059
1058
1060 def serve_forever(self):
1059 def serve_forever(self):
1061 self.serveuntil(threading.Event())
1060 self.serveuntil(threading.Event())
1062 sys.exit(0)
1061 sys.exit(0)
1063
1062
1064 def serveuntil(self, ev):
1063 def serveuntil(self, ev):
1065 """Serve until a threading.Event is set."""
1064 """Serve until a threading.Event is set."""
1066 _runsshserver(self._ui, self._repo, self._fin, self._fout, ev)
1065 _runsshserver(self._ui, self._repo, self._fin, self._fout, ev)
@@ -1,162 +1,163 b''
1 # Copyright 2018 Gregory Szorc <gregory.szorc@gmail.com>
1 # Copyright 2018 Gregory Szorc <gregory.szorc@gmail.com>
2 #
2 #
3 # This software may be used and distributed according to the terms of the
3 # This software may be used and distributed according to the terms of the
4 # GNU General Public License version 2 or any later version.
4 # GNU General Public License version 2 or any later version.
5
5
6 from __future__ import absolute_import
6 from __future__ import absolute_import
7
7
8 from .thirdparty.zope import (
8 from .thirdparty.zope import (
9 interface as zi,
9 interface as zi,
10 )
10 )
11
11
12 # Names of the SSH protocol implementations.
12 # Names of the SSH protocol implementations.
13 SSHV1 = 'ssh-v1'
13 SSHV1 = 'ssh-v1'
14 # These are advertised over the wire. Increment the counters at the end
14 # These are advertised over the wire. Increment the counters at the end
15 # to reflect BC breakages.
15 # to reflect BC breakages.
16 SSHV2 = 'exp-ssh-v2-0001'
16 SSHV2 = 'exp-ssh-v2-0001'
17 HTTPV2 = 'exp-http-v2-0001'
17 HTTPV2 = 'exp-http-v2-0001'
18
18
19 # All available wire protocol transports.
19 # All available wire protocol transports.
20 TRANSPORTS = {
20 TRANSPORTS = {
21 SSHV1: {
21 SSHV1: {
22 'transport': 'ssh',
22 'transport': 'ssh',
23 'version': 1,
23 'version': 1,
24 },
24 },
25 SSHV2: {
25 SSHV2: {
26 'transport': 'ssh',
26 'transport': 'ssh',
27 # TODO mark as version 2 once all commands are implemented.
27 # TODO mark as version 2 once all commands are implemented.
28 'version': 1,
28 'version': 1,
29 },
29 },
30 'http-v1': {
30 'http-v1': {
31 'transport': 'http',
31 'transport': 'http',
32 'version': 1,
32 'version': 1,
33 },
33 },
34 HTTPV2: {
34 HTTPV2: {
35 'transport': 'http',
35 'transport': 'http',
36 'version': 2,
36 'version': 2,
37 }
37 }
38 }
38 }
39
39
40 class bytesresponse(object):
40 class bytesresponse(object):
41 """A wire protocol response consisting of raw bytes."""
41 """A wire protocol response consisting of raw bytes."""
42 def __init__(self, data):
42 def __init__(self, data):
43 self.data = data
43 self.data = data
44
44
45 class ooberror(object):
45 class ooberror(object):
46 """wireproto reply: failure of a batch of operation
46 """wireproto reply: failure of a batch of operation
47
47
48 Something failed during a batch call. The error message is stored in
48 Something failed during a batch call. The error message is stored in
49 `self.message`.
49 `self.message`.
50 """
50 """
51 def __init__(self, message):
51 def __init__(self, message):
52 self.message = message
52 self.message = message
53
53
54 class pushres(object):
54 class pushres(object):
55 """wireproto reply: success with simple integer return
55 """wireproto reply: success with simple integer return
56
56
57 The call was successful and returned an integer contained in `self.res`.
57 The call was successful and returned an integer contained in `self.res`.
58 """
58 """
59 def __init__(self, res, output):
59 def __init__(self, res, output):
60 self.res = res
60 self.res = res
61 self.output = output
61 self.output = output
62
62
63 class pusherr(object):
63 class pusherr(object):
64 """wireproto reply: failure
64 """wireproto reply: failure
65
65
66 The call failed. The `self.res` attribute contains the error message.
66 The call failed. The `self.res` attribute contains the error message.
67 """
67 """
68 def __init__(self, res, output):
68 def __init__(self, res, output):
69 self.res = res
69 self.res = res
70 self.output = output
70 self.output = output
71
71
72 class streamres(object):
72 class streamres(object):
73 """wireproto reply: binary stream
73 """wireproto reply: binary stream
74
74
75 The call was successful and the result is a stream.
75 The call was successful and the result is a stream.
76
76
77 Accepts a generator containing chunks of data to be sent to the client.
77 Accepts a generator containing chunks of data to be sent to the client.
78
78
79 ``prefer_uncompressed`` indicates that the data is expected to be
79 ``prefer_uncompressed`` indicates that the data is expected to be
80 uncompressable and that the stream should therefore use the ``none``
80 uncompressable and that the stream should therefore use the ``none``
81 engine.
81 engine.
82 """
82 """
83 def __init__(self, gen=None, prefer_uncompressed=False):
83 def __init__(self, gen=None, prefer_uncompressed=False):
84 self.gen = gen
84 self.gen = gen
85 self.prefer_uncompressed = prefer_uncompressed
85 self.prefer_uncompressed = prefer_uncompressed
86
86
87 class streamreslegacy(object):
87 class streamreslegacy(object):
88 """wireproto reply: uncompressed binary stream
88 """wireproto reply: uncompressed binary stream
89
89
90 The call was successful and the result is a stream.
90 The call was successful and the result is a stream.
91
91
92 Accepts a generator containing chunks of data to be sent to the client.
92 Accepts a generator containing chunks of data to be sent to the client.
93
93
94 Like ``streamres``, but sends an uncompressed data for "version 1" clients
94 Like ``streamres``, but sends an uncompressed data for "version 1" clients
95 using the application/mercurial-0.1 media type.
95 using the application/mercurial-0.1 media type.
96 """
96 """
97 def __init__(self, gen=None):
97 def __init__(self, gen=None):
98 self.gen = gen
98 self.gen = gen
99
99
100 class baseprotocolhandler(zi.Interface):
100 class baseprotocolhandler(zi.Interface):
101 """Abstract base class for wire protocol handlers.
101 """Abstract base class for wire protocol handlers.
102
102
103 A wire protocol handler serves as an interface between protocol command
103 A wire protocol handler serves as an interface between protocol command
104 handlers and the wire protocol transport layer. Protocol handlers provide
104 handlers and the wire protocol transport layer. Protocol handlers provide
105 methods to read command arguments, redirect stdio for the duration of
105 methods to read command arguments, redirect stdio for the duration of
106 the request, handle response types, etc.
106 the request, handle response types, etc.
107 """
107 """
108
108
109 name = zi.Attribute(
109 name = zi.Attribute(
110 """The name of the protocol implementation.
110 """The name of the protocol implementation.
111
111
112 Used for uniquely identifying the transport type.
112 Used for uniquely identifying the transport type.
113 """)
113 """)
114
114
115 def getargs(args):
115 def getargs(args):
116 """return the value for arguments in <args>
116 """return the value for arguments in <args>
117
117
118 returns a list of values (same order as <args>)"""
118 returns a list of values (same order as <args>)"""
119
119
120 def getprotocaps():
120 def getprotocaps():
121 """Returns the list of protocol-level capabilities of client
121 """Returns the list of protocol-level capabilities of client
122
122
123 Returns a list of capabilities as declared by the client for
123 Returns a list of capabilities as declared by the client for
124 the current request (or connection for stateful protocol handlers)."""
124 the current request (or connection for stateful protocol handlers)."""
125
125
126 def forwardpayload(fp):
126 def getpayload():
127 """Read the raw payload and forward to a file.
127 """Provide a generator for the raw payload.
128
128
129 The payload is read in full before the function returns.
129 The caller is responsible for ensuring that the full payload is
130 processed.
130 """
131 """
131
132
132 def mayberedirectstdio():
133 def mayberedirectstdio():
133 """Context manager to possibly redirect stdio.
134 """Context manager to possibly redirect stdio.
134
135
135 The context manager yields a file-object like object that receives
136 The context manager yields a file-object like object that receives
136 stdout and stderr output when the context manager is active. Or it
137 stdout and stderr output when the context manager is active. Or it
137 yields ``None`` if no I/O redirection occurs.
138 yields ``None`` if no I/O redirection occurs.
138
139
139 The intent of this context manager is to capture stdio output
140 The intent of this context manager is to capture stdio output
140 so it may be sent in the response. Some transports support streaming
141 so it may be sent in the response. Some transports support streaming
141 stdio to the client in real time. For these transports, stdio output
142 stdio to the client in real time. For these transports, stdio output
142 won't be captured.
143 won't be captured.
143 """
144 """
144
145
145 def client():
146 def client():
146 """Returns a string representation of this client (as bytes)."""
147 """Returns a string representation of this client (as bytes)."""
147
148
148 def addcapabilities(repo, caps):
149 def addcapabilities(repo, caps):
149 """Adds advertised capabilities specific to this protocol.
150 """Adds advertised capabilities specific to this protocol.
150
151
151 Receives the list of capabilities collected so far.
152 Receives the list of capabilities collected so far.
152
153
153 Returns a list of capabilities. The passed in argument can be returned.
154 Returns a list of capabilities. The passed in argument can be returned.
154 """
155 """
155
156
156 def checkperm(perm):
157 def checkperm(perm):
157 """Validate that the client has permissions to perform a request.
158 """Validate that the client has permissions to perform a request.
158
159
159 The argument is the permission required to proceed. If the client
160 The argument is the permission required to proceed. If the client
160 doesn't have that permission, the exception should raise or abort
161 doesn't have that permission, the exception should raise or abort
161 in a protocol specific manner.
162 in a protocol specific manner.
162 """
163 """
@@ -1,330 +1,382 b''
1 #require killdaemons
1 #require killdaemons
2
2
3 #testcases bundle1 bundle2
3 #testcases bundle1 bundle2
4
4
5 #if bundle1
5 #if bundle1
6 $ cat << EOF >> $HGRCPATH
6 $ cat << EOF >> $HGRCPATH
7 > [devel]
7 > [devel]
8 > # This test is dedicated to interaction through old bundle
8 > # This test is dedicated to interaction through old bundle
9 > legacy.exchange = bundle1
9 > legacy.exchange = bundle1
10 > EOF
10 > EOF
11 #endif
11 #endif
12
12
13 $ hg init test
13 $ hg init test
14 $ cd test
14 $ cd test
15 $ echo a > a
15 $ echo a > a
16 $ hg ci -Ama
16 $ hg ci -Ama
17 adding a
17 adding a
18 $ cd ..
18 $ cd ..
19 $ hg clone test test2
19 $ hg clone test test2
20 updating to branch default
20 updating to branch default
21 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
21 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
22 $ cd test2
22 $ cd test2
23 $ echo a >> a
23 $ echo a >> a
24 $ hg ci -mb
24 $ hg ci -mb
25 $ req() {
25 $ req() {
26 > hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log
26 > hg $1 serve -p $HGPORT -d --pid-file=hg.pid -E errors.log
27 > cat hg.pid >> $DAEMON_PIDS
27 > cat hg.pid >> $DAEMON_PIDS
28 > hg --cwd ../test2 push http://localhost:$HGPORT/
28 > hg --cwd ../test2 push http://localhost:$HGPORT/
29 > exitstatus=$?
29 > exitstatus=$?
30 > killdaemons.py
30 > killdaemons.py
31 > echo % serve errors
31 > echo % serve errors
32 > cat errors.log
32 > cat errors.log
33 > return $exitstatus
33 > return $exitstatus
34 > }
34 > }
35 $ cd ../test
35 $ cd ../test
36
36
37 expect ssl error
37 expect ssl error
38
38
39 $ req
39 $ req
40 pushing to http://localhost:$HGPORT/
40 pushing to http://localhost:$HGPORT/
41 searching for changes
41 searching for changes
42 abort: HTTP Error 403: ssl required
42 abort: HTTP Error 403: ssl required
43 % serve errors
43 % serve errors
44 [255]
44 [255]
45
45
46 expect authorization error
46 expect authorization error
47
47
48 $ echo '[web]' > .hg/hgrc
48 $ echo '[web]' > .hg/hgrc
49 $ echo 'push_ssl = false' >> .hg/hgrc
49 $ echo 'push_ssl = false' >> .hg/hgrc
50 $ req
50 $ req
51 pushing to http://localhost:$HGPORT/
51 pushing to http://localhost:$HGPORT/
52 searching for changes
52 searching for changes
53 abort: authorization failed
53 abort: authorization failed
54 % serve errors
54 % serve errors
55 [255]
55 [255]
56
56
57 expect authorization error: must have authorized user
57 expect authorization error: must have authorized user
58
58
59 $ echo 'allow_push = unperson' >> .hg/hgrc
59 $ echo 'allow_push = unperson' >> .hg/hgrc
60 $ req
60 $ req
61 pushing to http://localhost:$HGPORT/
61 pushing to http://localhost:$HGPORT/
62 searching for changes
62 searching for changes
63 abort: authorization failed
63 abort: authorization failed
64 % serve errors
64 % serve errors
65 [255]
65 [255]
66
66
67 expect success
67 expect success
68
68
69 $ cat > $TESTTMP/hook.sh <<'EOF'
69 $ cat > $TESTTMP/hook.sh <<'EOF'
70 > echo "phase-move: $HG_NODE: $HG_OLDPHASE -> $HG_PHASE"
70 > echo "phase-move: $HG_NODE: $HG_OLDPHASE -> $HG_PHASE"
71 > EOF
71 > EOF
72
72
73 #if bundle1
74 $ cat >> .hg/hgrc <<EOF
75 > allow_push = *
76 > [hooks]
77 > changegroup = sh -c "printenv.py changegroup 0"
78 > pushkey = sh -c "printenv.py pushkey 0"
79 > txnclose-phase.test = sh $TESTTMP/hook.sh
80 > EOF
81 $ req "--debug --config extensions.blackbox="
82 listening at http://localhost:$HGPORT/ (bound to $LOCALIP:$HGPORT)
83 pushing to http://localhost:$HGPORT/
84 searching for changes
85 remote: redirecting incoming bundle to */hg-unbundle-* (glob)
86 remote: adding changesets
87 remote: add changeset ba677d0156c1
88 remote: adding manifests
89 remote: adding file changes
90 remote: adding a revisions
91 remote: added 1 changesets with 1 changes to 1 files
92 remote: updating the branch cache
93 remote: running hook txnclose-phase.test: sh $TESTTMP/hook.sh
94 remote: phase-move: cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b: draft -> public
95 remote: running hook txnclose-phase.test: sh $TESTTMP/hook.sh
96 remote: phase-move: ba677d0156c1196c1a699fa53f390dcfc3ce3872: -> public
97 remote: running hook changegroup: sh -c "printenv.py changegroup 0"
98 remote: changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: (glob)
99 % serve errors
100 $ hg rollback
101 repository tip rolled back to revision 0 (undo serve)
102 $ req "--debug --config server.streamunbundle=True --config extensions.blackbox="
103 listening at http://localhost:$HGPORT/ (bound to $LOCALIP:$HGPORT)
104 pushing to http://localhost:$HGPORT/
105 searching for changes
106 remote: adding changesets
107 remote: add changeset ba677d0156c1
108 remote: adding manifests
109 remote: adding file changes
110 remote: adding a revisions
111 remote: added 1 changesets with 1 changes to 1 files
112 remote: updating the branch cache
113 remote: running hook txnclose-phase.test: sh $TESTTMP/hook.sh
114 remote: phase-move: cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b: draft -> public
115 remote: running hook txnclose-phase.test: sh $TESTTMP/hook.sh
116 remote: phase-move: ba677d0156c1196c1a699fa53f390dcfc3ce3872: -> public
117 remote: running hook changegroup: sh -c "printenv.py changegroup 0"
118 remote: changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: (glob)
119 % serve errors
120 $ hg rollback
121 repository tip rolled back to revision 0 (undo serve)
122 #endif
123
124 #if bundle2
73 $ cat >> .hg/hgrc <<EOF
125 $ cat >> .hg/hgrc <<EOF
74 > allow_push = *
126 > allow_push = *
75 > [hooks]
127 > [hooks]
76 > changegroup = sh -c "printenv.py changegroup 0"
128 > changegroup = sh -c "printenv.py changegroup 0"
77 > pushkey = sh -c "printenv.py pushkey 0"
129 > pushkey = sh -c "printenv.py pushkey 0"
78 > txnclose-phase.test = sh $TESTTMP/hook.sh
130 > txnclose-phase.test = sh $TESTTMP/hook.sh
79 > EOF
131 > EOF
80 $ req
132 $ req
81 pushing to http://localhost:$HGPORT/
133 pushing to http://localhost:$HGPORT/
82 searching for changes
134 searching for changes
83 remote: adding changesets
135 remote: adding changesets
84 remote: adding manifests
136 remote: adding manifests
85 remote: adding file changes
137 remote: adding file changes
86 remote: added 1 changesets with 1 changes to 1 files
138 remote: added 1 changesets with 1 changes to 1 files
87 remote: phase-move: cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b: draft -> public
139 remote: phase-move: cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b: draft -> public
88 remote: phase-move: ba677d0156c1196c1a699fa53f390dcfc3ce3872: -> public
140 remote: phase-move: ba677d0156c1196c1a699fa53f390dcfc3ce3872: -> public
89 remote: changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: (glob) (bundle1 !)
141 remote: changegroup hook: HG_BUNDLE2=1 HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: (glob)
90 remote: changegroup hook: HG_BUNDLE2=1 HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: (glob) (bundle2 !)
91 % serve errors
142 % serve errors
92 $ hg rollback
143 $ hg rollback
93 repository tip rolled back to revision 0 (undo serve)
144 repository tip rolled back to revision 0 (undo serve)
145 #endif
94
146
95 expect success, server lacks the httpheader capability
147 expect success, server lacks the httpheader capability
96
148
97 $ CAP=httpheader
149 $ CAP=httpheader
98 $ . "$TESTDIR/notcapable"
150 $ . "$TESTDIR/notcapable"
99 $ req
151 $ req
100 pushing to http://localhost:$HGPORT/
152 pushing to http://localhost:$HGPORT/
101 searching for changes
153 searching for changes
102 remote: adding changesets
154 remote: adding changesets
103 remote: adding manifests
155 remote: adding manifests
104 remote: adding file changes
156 remote: adding file changes
105 remote: added 1 changesets with 1 changes to 1 files
157 remote: added 1 changesets with 1 changes to 1 files
106 remote: phase-move: cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b: draft -> public
158 remote: phase-move: cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b: draft -> public
107 remote: phase-move: ba677d0156c1196c1a699fa53f390dcfc3ce3872: -> public
159 remote: phase-move: ba677d0156c1196c1a699fa53f390dcfc3ce3872: -> public
108 remote: changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: (glob) (bundle1 !)
160 remote: changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: (glob) (bundle1 !)
109 remote: changegroup hook: HG_BUNDLE2=1 HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: (glob) (bundle2 !)
161 remote: changegroup hook: HG_BUNDLE2=1 HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: (glob) (bundle2 !)
110 % serve errors
162 % serve errors
111 $ hg rollback
163 $ hg rollback
112 repository tip rolled back to revision 0 (undo serve)
164 repository tip rolled back to revision 0 (undo serve)
113
165
114 expect success, server lacks the unbundlehash capability
166 expect success, server lacks the unbundlehash capability
115
167
116 $ CAP=unbundlehash
168 $ CAP=unbundlehash
117 $ . "$TESTDIR/notcapable"
169 $ . "$TESTDIR/notcapable"
118 $ req
170 $ req
119 pushing to http://localhost:$HGPORT/
171 pushing to http://localhost:$HGPORT/
120 searching for changes
172 searching for changes
121 remote: adding changesets
173 remote: adding changesets
122 remote: adding manifests
174 remote: adding manifests
123 remote: adding file changes
175 remote: adding file changes
124 remote: added 1 changesets with 1 changes to 1 files
176 remote: added 1 changesets with 1 changes to 1 files
125 remote: phase-move: cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b: draft -> public
177 remote: phase-move: cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b: draft -> public
126 remote: phase-move: ba677d0156c1196c1a699fa53f390dcfc3ce3872: -> public
178 remote: phase-move: ba677d0156c1196c1a699fa53f390dcfc3ce3872: -> public
127 remote: changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: (glob) (bundle1 !)
179 remote: changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: (glob) (bundle1 !)
128 remote: changegroup hook: HG_BUNDLE2=1 HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: (glob) (bundle2 !)
180 remote: changegroup hook: HG_BUNDLE2=1 HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: (glob) (bundle2 !)
129 % serve errors
181 % serve errors
130 $ hg rollback
182 $ hg rollback
131 repository tip rolled back to revision 0 (undo serve)
183 repository tip rolled back to revision 0 (undo serve)
132
184
133 expect success, pre-d1b16a746db6 server supports the unbundle capability, but
185 expect success, pre-d1b16a746db6 server supports the unbundle capability, but
134 has no parameter
186 has no parameter
135
187
136 $ cat <<EOF > notcapable-unbundleparam.py
188 $ cat <<EOF > notcapable-unbundleparam.py
137 > from mercurial import extensions, httppeer
189 > from mercurial import extensions, httppeer
138 > def capable(orig, self, name):
190 > def capable(orig, self, name):
139 > if name == 'unbundle':
191 > if name == 'unbundle':
140 > return True
192 > return True
141 > return orig(self, name)
193 > return orig(self, name)
142 > def uisetup(ui):
194 > def uisetup(ui):
143 > extensions.wrapfunction(httppeer.httppeer, 'capable', capable)
195 > extensions.wrapfunction(httppeer.httppeer, 'capable', capable)
144 > EOF
196 > EOF
145 $ cp $HGRCPATH $HGRCPATH.orig
197 $ cp $HGRCPATH $HGRCPATH.orig
146 $ cat <<EOF >> $HGRCPATH
198 $ cat <<EOF >> $HGRCPATH
147 > [extensions]
199 > [extensions]
148 > notcapable-unbundleparam = `pwd`/notcapable-unbundleparam.py
200 > notcapable-unbundleparam = `pwd`/notcapable-unbundleparam.py
149 > EOF
201 > EOF
150 $ req
202 $ req
151 pushing to http://localhost:$HGPORT/
203 pushing to http://localhost:$HGPORT/
152 searching for changes
204 searching for changes
153 remote: adding changesets
205 remote: adding changesets
154 remote: adding manifests
206 remote: adding manifests
155 remote: adding file changes
207 remote: adding file changes
156 remote: added 1 changesets with 1 changes to 1 files
208 remote: added 1 changesets with 1 changes to 1 files
157 remote: phase-move: cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b: draft -> public
209 remote: phase-move: cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b: draft -> public
158 remote: phase-move: ba677d0156c1196c1a699fa53f390dcfc3ce3872: -> public
210 remote: phase-move: ba677d0156c1196c1a699fa53f390dcfc3ce3872: -> public
159 remote: changegroup hook: * (glob)
211 remote: changegroup hook: * (glob)
160 % serve errors
212 % serve errors
161 $ hg rollback
213 $ hg rollback
162 repository tip rolled back to revision 0 (undo serve)
214 repository tip rolled back to revision 0 (undo serve)
163 $ mv $HGRCPATH.orig $HGRCPATH
215 $ mv $HGRCPATH.orig $HGRCPATH
164
216
165 Test pushing to a publishing repository with a failing prepushkey hook
217 Test pushing to a publishing repository with a failing prepushkey hook
166
218
167 $ cat > .hg/hgrc <<EOF
219 $ cat > .hg/hgrc <<EOF
168 > [web]
220 > [web]
169 > push_ssl = false
221 > push_ssl = false
170 > allow_push = *
222 > allow_push = *
171 > [hooks]
223 > [hooks]
172 > prepushkey = sh -c "printenv.py prepushkey 1"
224 > prepushkey = sh -c "printenv.py prepushkey 1"
173 > [devel]
225 > [devel]
174 > legacy.exchange=phases
226 > legacy.exchange=phases
175 > EOF
227 > EOF
176
228
177 #if bundle1
229 #if bundle1
178 Bundle1 works because a) phases are updated as part of changegroup application
230 Bundle1 works because a) phases are updated as part of changegroup application
179 and b) client checks phases after the "unbundle" command. Since it sees no
231 and b) client checks phases after the "unbundle" command. Since it sees no
180 phase changes are necessary, it doesn't send the "pushkey" command and the
232 phase changes are necessary, it doesn't send the "pushkey" command and the
181 prepushkey hook never has to fire.
233 prepushkey hook never has to fire.
182
234
183 $ req
235 $ req
184 pushing to http://localhost:$HGPORT/
236 pushing to http://localhost:$HGPORT/
185 searching for changes
237 searching for changes
186 remote: adding changesets
238 remote: adding changesets
187 remote: adding manifests
239 remote: adding manifests
188 remote: adding file changes
240 remote: adding file changes
189 remote: added 1 changesets with 1 changes to 1 files
241 remote: added 1 changesets with 1 changes to 1 files
190 % serve errors
242 % serve errors
191
243
192 #endif
244 #endif
193
245
194 #if bundle2
246 #if bundle2
195 Bundle2 sends a "pushkey" bundle2 part. This runs as part of the transaction
247 Bundle2 sends a "pushkey" bundle2 part. This runs as part of the transaction
196 and fails the entire push.
248 and fails the entire push.
197 $ req
249 $ req
198 pushing to http://localhost:$HGPORT/
250 pushing to http://localhost:$HGPORT/
199 searching for changes
251 searching for changes
200 remote: adding changesets
252 remote: adding changesets
201 remote: adding manifests
253 remote: adding manifests
202 remote: adding file changes
254 remote: adding file changes
203 remote: added 1 changesets with 1 changes to 1 files
255 remote: added 1 changesets with 1 changes to 1 files
204 remote: prepushkey hook: HG_BUNDLE2=1 HG_HOOKNAME=prepushkey HG_HOOKTYPE=prepushkey HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_OLD=1 HG_PENDING=$TESTTMP/test HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: (glob)
256 remote: prepushkey hook: HG_BUNDLE2=1 HG_HOOKNAME=prepushkey HG_HOOKTYPE=prepushkey HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_OLD=1 HG_PENDING=$TESTTMP/test HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: (glob)
205 remote: pushkey-abort: prepushkey hook exited with status 1
257 remote: pushkey-abort: prepushkey hook exited with status 1
206 remote: transaction abort!
258 remote: transaction abort!
207 remote: rollback completed
259 remote: rollback completed
208 abort: updating ba677d0156c1 to public failed
260 abort: updating ba677d0156c1 to public failed
209 % serve errors
261 % serve errors
210 [255]
262 [255]
211
263
212 #endif
264 #endif
213
265
214 Now remove the failing prepushkey hook.
266 Now remove the failing prepushkey hook.
215
267
216 $ cat >> .hg/hgrc <<EOF
268 $ cat >> .hg/hgrc <<EOF
217 > [hooks]
269 > [hooks]
218 > prepushkey = sh -c "printenv.py prepushkey 0"
270 > prepushkey = sh -c "printenv.py prepushkey 0"
219 > EOF
271 > EOF
220
272
221 We don't need to test bundle1 because it succeeded above.
273 We don't need to test bundle1 because it succeeded above.
222
274
223 #if bundle2
275 #if bundle2
224 $ req
276 $ req
225 pushing to http://localhost:$HGPORT/
277 pushing to http://localhost:$HGPORT/
226 searching for changes
278 searching for changes
227 remote: adding changesets
279 remote: adding changesets
228 remote: adding manifests
280 remote: adding manifests
229 remote: adding file changes
281 remote: adding file changes
230 remote: added 1 changesets with 1 changes to 1 files
282 remote: added 1 changesets with 1 changes to 1 files
231 remote: prepushkey hook: HG_BUNDLE2=1 HG_HOOKNAME=prepushkey HG_HOOKTYPE=prepushkey HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_OLD=1 HG_PENDING=$TESTTMP/test HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: (glob)
283 remote: prepushkey hook: HG_BUNDLE2=1 HG_HOOKNAME=prepushkey HG_HOOKTYPE=prepushkey HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_OLD=1 HG_PENDING=$TESTTMP/test HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: (glob)
232 % serve errors
284 % serve errors
233 #endif
285 #endif
234
286
235 $ hg --config extensions.strip= strip -r 1:
287 $ hg --config extensions.strip= strip -r 1:
236 saved backup bundle to $TESTTMP/test/.hg/strip-backup/ba677d0156c1-eea704d7-backup.hg
288 saved backup bundle to $TESTTMP/test/.hg/strip-backup/ba677d0156c1-eea704d7-backup.hg
237
289
238 Now do a variant of the above, except on a non-publishing repository
290 Now do a variant of the above, except on a non-publishing repository
239
291
240 $ cat >> .hg/hgrc <<EOF
292 $ cat >> .hg/hgrc <<EOF
241 > [phases]
293 > [phases]
242 > publish = false
294 > publish = false
243 > [hooks]
295 > [hooks]
244 > prepushkey = sh -c "printenv.py prepushkey 1"
296 > prepushkey = sh -c "printenv.py prepushkey 1"
245 > EOF
297 > EOF
246
298
247 #if bundle1
299 #if bundle1
248 $ req
300 $ req
249 pushing to http://localhost:$HGPORT/
301 pushing to http://localhost:$HGPORT/
250 searching for changes
302 searching for changes
251 remote: adding changesets
303 remote: adding changesets
252 remote: adding manifests
304 remote: adding manifests
253 remote: adding file changes
305 remote: adding file changes
254 remote: added 1 changesets with 1 changes to 1 files
306 remote: added 1 changesets with 1 changes to 1 files
255 remote: prepushkey hook: HG_HOOKNAME=prepushkey HG_HOOKTYPE=prepushkey HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1
307 remote: prepushkey hook: HG_HOOKNAME=prepushkey HG_HOOKTYPE=prepushkey HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1
256 remote: pushkey-abort: prepushkey hook exited with status 1
308 remote: pushkey-abort: prepushkey hook exited with status 1
257 updating ba677d0156c1 to public failed!
309 updating ba677d0156c1 to public failed!
258 % serve errors
310 % serve errors
259 #endif
311 #endif
260
312
261 #if bundle2
313 #if bundle2
262 $ req
314 $ req
263 pushing to http://localhost:$HGPORT/
315 pushing to http://localhost:$HGPORT/
264 searching for changes
316 searching for changes
265 remote: adding changesets
317 remote: adding changesets
266 remote: adding manifests
318 remote: adding manifests
267 remote: adding file changes
319 remote: adding file changes
268 remote: added 1 changesets with 1 changes to 1 files
320 remote: added 1 changesets with 1 changes to 1 files
269 remote: prepushkey hook: HG_BUNDLE2=1 HG_HOOKNAME=prepushkey HG_HOOKTYPE=prepushkey HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_OLD=1 HG_PENDING=$TESTTMP/test HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: (glob)
321 remote: prepushkey hook: HG_BUNDLE2=1 HG_HOOKNAME=prepushkey HG_HOOKTYPE=prepushkey HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_OLD=1 HG_PENDING=$TESTTMP/test HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: (glob)
270 remote: pushkey-abort: prepushkey hook exited with status 1
322 remote: pushkey-abort: prepushkey hook exited with status 1
271 remote: transaction abort!
323 remote: transaction abort!
272 remote: rollback completed
324 remote: rollback completed
273 abort: updating ba677d0156c1 to public failed
325 abort: updating ba677d0156c1 to public failed
274 % serve errors
326 % serve errors
275 [255]
327 [255]
276 #endif
328 #endif
277
329
278 Make phases updates work
330 Make phases updates work
279
331
280 $ cat >> .hg/hgrc <<EOF
332 $ cat >> .hg/hgrc <<EOF
281 > [hooks]
333 > [hooks]
282 > prepushkey = sh -c "printenv.py prepushkey 0"
334 > prepushkey = sh -c "printenv.py prepushkey 0"
283 > EOF
335 > EOF
284
336
285 #if bundle1
337 #if bundle1
286 $ req
338 $ req
287 pushing to http://localhost:$HGPORT/
339 pushing to http://localhost:$HGPORT/
288 searching for changes
340 searching for changes
289 no changes found
341 no changes found
290 remote: prepushkey hook: HG_HOOKNAME=prepushkey HG_HOOKTYPE=prepushkey HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1
342 remote: prepushkey hook: HG_HOOKNAME=prepushkey HG_HOOKTYPE=prepushkey HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1
291 % serve errors
343 % serve errors
292 [1]
344 [1]
293 #endif
345 #endif
294
346
295 #if bundle2
347 #if bundle2
296 $ req
348 $ req
297 pushing to http://localhost:$HGPORT/
349 pushing to http://localhost:$HGPORT/
298 searching for changes
350 searching for changes
299 remote: adding changesets
351 remote: adding changesets
300 remote: adding manifests
352 remote: adding manifests
301 remote: adding file changes
353 remote: adding file changes
302 remote: added 1 changesets with 1 changes to 1 files
354 remote: added 1 changesets with 1 changes to 1 files
303 remote: prepushkey hook: HG_BUNDLE2=1 HG_HOOKNAME=prepushkey HG_HOOKTYPE=prepushkey HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_OLD=1 HG_PENDING=$TESTTMP/test HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: (glob)
355 remote: prepushkey hook: HG_BUNDLE2=1 HG_HOOKNAME=prepushkey HG_HOOKTYPE=prepushkey HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_OLD=1 HG_PENDING=$TESTTMP/test HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP: (glob)
304 % serve errors
356 % serve errors
305 #endif
357 #endif
306
358
307 $ hg --config extensions.strip= strip -r 1:
359 $ hg --config extensions.strip= strip -r 1:
308 saved backup bundle to $TESTTMP/test/.hg/strip-backup/ba677d0156c1-eea704d7-backup.hg
360 saved backup bundle to $TESTTMP/test/.hg/strip-backup/ba677d0156c1-eea704d7-backup.hg
309
361
310 #if bundle2
362 #if bundle2
311
363
312 $ cat > .hg/hgrc <<EOF
364 $ cat > .hg/hgrc <<EOF
313 > [web]
365 > [web]
314 > push_ssl = false
366 > push_ssl = false
315 > allow_push = *
367 > allow_push = *
316 > [experimental]
368 > [experimental]
317 > httppostargs=true
369 > httppostargs=true
318 > EOF
370 > EOF
319 $ req
371 $ req
320 pushing to http://localhost:$HGPORT/
372 pushing to http://localhost:$HGPORT/
321 searching for changes
373 searching for changes
322 remote: adding changesets
374 remote: adding changesets
323 remote: adding manifests
375 remote: adding manifests
324 remote: adding file changes
376 remote: adding file changes
325 remote: added 1 changesets with 1 changes to 1 files
377 remote: added 1 changesets with 1 changes to 1 files
326 % serve errors
378 % serve errors
327
379
328 #endif
380 #endif
329
381
330 $ cd ..
382 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now