##// END OF EJS Templates
bundle2: graduate bundle2.stream option from experimental to server section...
av6 -
r39757:1b588035 default
parent child Browse files
Show More
@@ -1,2268 +1,2268 b''
1 # bundle2.py - generic container format to transmit arbitrary data.
1 # bundle2.py - generic container format to transmit arbitrary data.
2 #
2 #
3 # Copyright 2013 Facebook, Inc.
3 # Copyright 2013 Facebook, Inc.
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 """Handling of the new bundle2 format
7 """Handling of the new bundle2 format
8
8
9 The goal of bundle2 is to act as an atomically packet to transmit a set of
9 The goal of bundle2 is to act as an atomically packet to transmit a set of
10 payloads in an application agnostic way. It consist in a sequence of "parts"
10 payloads in an application agnostic way. It consist in a sequence of "parts"
11 that will be handed to and processed by the application layer.
11 that will be handed to and processed by the application layer.
12
12
13
13
14 General format architecture
14 General format architecture
15 ===========================
15 ===========================
16
16
17 The format is architectured as follow
17 The format is architectured as follow
18
18
19 - magic string
19 - magic string
20 - stream level parameters
20 - stream level parameters
21 - payload parts (any number)
21 - payload parts (any number)
22 - end of stream marker.
22 - end of stream marker.
23
23
24 the Binary format
24 the Binary format
25 ============================
25 ============================
26
26
27 All numbers are unsigned and big-endian.
27 All numbers are unsigned and big-endian.
28
28
29 stream level parameters
29 stream level parameters
30 ------------------------
30 ------------------------
31
31
32 Binary format is as follow
32 Binary format is as follow
33
33
34 :params size: int32
34 :params size: int32
35
35
36 The total number of Bytes used by the parameters
36 The total number of Bytes used by the parameters
37
37
38 :params value: arbitrary number of Bytes
38 :params value: arbitrary number of Bytes
39
39
40 A blob of `params size` containing the serialized version of all stream level
40 A blob of `params size` containing the serialized version of all stream level
41 parameters.
41 parameters.
42
42
43 The blob contains a space separated list of parameters. Parameters with value
43 The blob contains a space separated list of parameters. Parameters with value
44 are stored in the form `<name>=<value>`. Both name and value are urlquoted.
44 are stored in the form `<name>=<value>`. Both name and value are urlquoted.
45
45
46 Empty name are obviously forbidden.
46 Empty name are obviously forbidden.
47
47
48 Name MUST start with a letter. If this first letter is lower case, the
48 Name MUST start with a letter. If this first letter is lower case, the
49 parameter is advisory and can be safely ignored. However when the first
49 parameter is advisory and can be safely ignored. However when the first
50 letter is capital, the parameter is mandatory and the bundling process MUST
50 letter is capital, the parameter is mandatory and the bundling process MUST
51 stop if he is not able to proceed it.
51 stop if he is not able to proceed it.
52
52
53 Stream parameters use a simple textual format for two main reasons:
53 Stream parameters use a simple textual format for two main reasons:
54
54
55 - Stream level parameters should remain simple and we want to discourage any
55 - Stream level parameters should remain simple and we want to discourage any
56 crazy usage.
56 crazy usage.
57 - Textual data allow easy human inspection of a bundle2 header in case of
57 - Textual data allow easy human inspection of a bundle2 header in case of
58 troubles.
58 troubles.
59
59
60 Any Applicative level options MUST go into a bundle2 part instead.
60 Any Applicative level options MUST go into a bundle2 part instead.
61
61
62 Payload part
62 Payload part
63 ------------------------
63 ------------------------
64
64
65 Binary format is as follow
65 Binary format is as follow
66
66
67 :header size: int32
67 :header size: int32
68
68
69 The total number of Bytes used by the part header. When the header is empty
69 The total number of Bytes used by the part header. When the header is empty
70 (size = 0) this is interpreted as the end of stream marker.
70 (size = 0) this is interpreted as the end of stream marker.
71
71
72 :header:
72 :header:
73
73
74 The header defines how to interpret the part. It contains two piece of
74 The header defines how to interpret the part. It contains two piece of
75 data: the part type, and the part parameters.
75 data: the part type, and the part parameters.
76
76
77 The part type is used to route an application level handler, that can
77 The part type is used to route an application level handler, that can
78 interpret payload.
78 interpret payload.
79
79
80 Part parameters are passed to the application level handler. They are
80 Part parameters are passed to the application level handler. They are
81 meant to convey information that will help the application level object to
81 meant to convey information that will help the application level object to
82 interpret the part payload.
82 interpret the part payload.
83
83
84 The binary format of the header is has follow
84 The binary format of the header is has follow
85
85
86 :typesize: (one byte)
86 :typesize: (one byte)
87
87
88 :parttype: alphanumerical part name (restricted to [a-zA-Z0-9_:-]*)
88 :parttype: alphanumerical part name (restricted to [a-zA-Z0-9_:-]*)
89
89
90 :partid: A 32bits integer (unique in the bundle) that can be used to refer
90 :partid: A 32bits integer (unique in the bundle) that can be used to refer
91 to this part.
91 to this part.
92
92
93 :parameters:
93 :parameters:
94
94
95 Part's parameter may have arbitrary content, the binary structure is::
95 Part's parameter may have arbitrary content, the binary structure is::
96
96
97 <mandatory-count><advisory-count><param-sizes><param-data>
97 <mandatory-count><advisory-count><param-sizes><param-data>
98
98
99 :mandatory-count: 1 byte, number of mandatory parameters
99 :mandatory-count: 1 byte, number of mandatory parameters
100
100
101 :advisory-count: 1 byte, number of advisory parameters
101 :advisory-count: 1 byte, number of advisory parameters
102
102
103 :param-sizes:
103 :param-sizes:
104
104
105 N couple of bytes, where N is the total number of parameters. Each
105 N couple of bytes, where N is the total number of parameters. Each
106 couple contains (<size-of-key>, <size-of-value) for one parameter.
106 couple contains (<size-of-key>, <size-of-value) for one parameter.
107
107
108 :param-data:
108 :param-data:
109
109
110 A blob of bytes from which each parameter key and value can be
110 A blob of bytes from which each parameter key and value can be
111 retrieved using the list of size couples stored in the previous
111 retrieved using the list of size couples stored in the previous
112 field.
112 field.
113
113
114 Mandatory parameters comes first, then the advisory ones.
114 Mandatory parameters comes first, then the advisory ones.
115
115
116 Each parameter's key MUST be unique within the part.
116 Each parameter's key MUST be unique within the part.
117
117
118 :payload:
118 :payload:
119
119
120 payload is a series of `<chunksize><chunkdata>`.
120 payload is a series of `<chunksize><chunkdata>`.
121
121
122 `chunksize` is an int32, `chunkdata` are plain bytes (as much as
122 `chunksize` is an int32, `chunkdata` are plain bytes (as much as
123 `chunksize` says)` The payload part is concluded by a zero size chunk.
123 `chunksize` says)` The payload part is concluded by a zero size chunk.
124
124
125 The current implementation always produces either zero or one chunk.
125 The current implementation always produces either zero or one chunk.
126 This is an implementation limitation that will ultimately be lifted.
126 This is an implementation limitation that will ultimately be lifted.
127
127
128 `chunksize` can be negative to trigger special case processing. No such
128 `chunksize` can be negative to trigger special case processing. No such
129 processing is in place yet.
129 processing is in place yet.
130
130
131 Bundle processing
131 Bundle processing
132 ============================
132 ============================
133
133
134 Each part is processed in order using a "part handler". Handler are registered
134 Each part is processed in order using a "part handler". Handler are registered
135 for a certain part type.
135 for a certain part type.
136
136
137 The matching of a part to its handler is case insensitive. The case of the
137 The matching of a part to its handler is case insensitive. The case of the
138 part type is used to know if a part is mandatory or advisory. If the Part type
138 part type is used to know if a part is mandatory or advisory. If the Part type
139 contains any uppercase char it is considered mandatory. When no handler is
139 contains any uppercase char it is considered mandatory. When no handler is
140 known for a Mandatory part, the process is aborted and an exception is raised.
140 known for a Mandatory part, the process is aborted and an exception is raised.
141 If the part is advisory and no handler is known, the part is ignored. When the
141 If the part is advisory and no handler is known, the part is ignored. When the
142 process is aborted, the full bundle is still read from the stream to keep the
142 process is aborted, the full bundle is still read from the stream to keep the
143 channel usable. But none of the part read from an abort are processed. In the
143 channel usable. But none of the part read from an abort are processed. In the
144 future, dropping the stream may become an option for channel we do not care to
144 future, dropping the stream may become an option for channel we do not care to
145 preserve.
145 preserve.
146 """
146 """
147
147
148 from __future__ import absolute_import, division
148 from __future__ import absolute_import, division
149
149
150 import collections
150 import collections
151 import errno
151 import errno
152 import os
152 import os
153 import re
153 import re
154 import string
154 import string
155 import struct
155 import struct
156 import sys
156 import sys
157
157
158 from .i18n import _
158 from .i18n import _
159 from . import (
159 from . import (
160 bookmarks,
160 bookmarks,
161 changegroup,
161 changegroup,
162 encoding,
162 encoding,
163 error,
163 error,
164 node as nodemod,
164 node as nodemod,
165 obsolete,
165 obsolete,
166 phases,
166 phases,
167 pushkey,
167 pushkey,
168 pycompat,
168 pycompat,
169 streamclone,
169 streamclone,
170 tags,
170 tags,
171 url,
171 url,
172 util,
172 util,
173 )
173 )
174 from .utils import (
174 from .utils import (
175 stringutil,
175 stringutil,
176 )
176 )
177
177
178 urlerr = util.urlerr
178 urlerr = util.urlerr
179 urlreq = util.urlreq
179 urlreq = util.urlreq
180
180
181 _pack = struct.pack
181 _pack = struct.pack
182 _unpack = struct.unpack
182 _unpack = struct.unpack
183
183
184 _fstreamparamsize = '>i'
184 _fstreamparamsize = '>i'
185 _fpartheadersize = '>i'
185 _fpartheadersize = '>i'
186 _fparttypesize = '>B'
186 _fparttypesize = '>B'
187 _fpartid = '>I'
187 _fpartid = '>I'
188 _fpayloadsize = '>i'
188 _fpayloadsize = '>i'
189 _fpartparamcount = '>BB'
189 _fpartparamcount = '>BB'
190
190
191 preferedchunksize = 32768
191 preferedchunksize = 32768
192
192
193 _parttypeforbidden = re.compile('[^a-zA-Z0-9_:-]')
193 _parttypeforbidden = re.compile('[^a-zA-Z0-9_:-]')
194
194
195 def outdebug(ui, message):
195 def outdebug(ui, message):
196 """debug regarding output stream (bundling)"""
196 """debug regarding output stream (bundling)"""
197 if ui.configbool('devel', 'bundle2.debug'):
197 if ui.configbool('devel', 'bundle2.debug'):
198 ui.debug('bundle2-output: %s\n' % message)
198 ui.debug('bundle2-output: %s\n' % message)
199
199
200 def indebug(ui, message):
200 def indebug(ui, message):
201 """debug on input stream (unbundling)"""
201 """debug on input stream (unbundling)"""
202 if ui.configbool('devel', 'bundle2.debug'):
202 if ui.configbool('devel', 'bundle2.debug'):
203 ui.debug('bundle2-input: %s\n' % message)
203 ui.debug('bundle2-input: %s\n' % message)
204
204
205 def validateparttype(parttype):
205 def validateparttype(parttype):
206 """raise ValueError if a parttype contains invalid character"""
206 """raise ValueError if a parttype contains invalid character"""
207 if _parttypeforbidden.search(parttype):
207 if _parttypeforbidden.search(parttype):
208 raise ValueError(parttype)
208 raise ValueError(parttype)
209
209
210 def _makefpartparamsizes(nbparams):
210 def _makefpartparamsizes(nbparams):
211 """return a struct format to read part parameter sizes
211 """return a struct format to read part parameter sizes
212
212
213 The number parameters is variable so we need to build that format
213 The number parameters is variable so we need to build that format
214 dynamically.
214 dynamically.
215 """
215 """
216 return '>'+('BB'*nbparams)
216 return '>'+('BB'*nbparams)
217
217
218 parthandlermapping = {}
218 parthandlermapping = {}
219
219
220 def parthandler(parttype, params=()):
220 def parthandler(parttype, params=()):
221 """decorator that register a function as a bundle2 part handler
221 """decorator that register a function as a bundle2 part handler
222
222
223 eg::
223 eg::
224
224
225 @parthandler('myparttype', ('mandatory', 'param', 'handled'))
225 @parthandler('myparttype', ('mandatory', 'param', 'handled'))
226 def myparttypehandler(...):
226 def myparttypehandler(...):
227 '''process a part of type "my part".'''
227 '''process a part of type "my part".'''
228 ...
228 ...
229 """
229 """
230 validateparttype(parttype)
230 validateparttype(parttype)
231 def _decorator(func):
231 def _decorator(func):
232 lparttype = parttype.lower() # enforce lower case matching.
232 lparttype = parttype.lower() # enforce lower case matching.
233 assert lparttype not in parthandlermapping
233 assert lparttype not in parthandlermapping
234 parthandlermapping[lparttype] = func
234 parthandlermapping[lparttype] = func
235 func.params = frozenset(params)
235 func.params = frozenset(params)
236 return func
236 return func
237 return _decorator
237 return _decorator
238
238
239 class unbundlerecords(object):
239 class unbundlerecords(object):
240 """keep record of what happens during and unbundle
240 """keep record of what happens during and unbundle
241
241
242 New records are added using `records.add('cat', obj)`. Where 'cat' is a
242 New records are added using `records.add('cat', obj)`. Where 'cat' is a
243 category of record and obj is an arbitrary object.
243 category of record and obj is an arbitrary object.
244
244
245 `records['cat']` will return all entries of this category 'cat'.
245 `records['cat']` will return all entries of this category 'cat'.
246
246
247 Iterating on the object itself will yield `('category', obj)` tuples
247 Iterating on the object itself will yield `('category', obj)` tuples
248 for all entries.
248 for all entries.
249
249
250 All iterations happens in chronological order.
250 All iterations happens in chronological order.
251 """
251 """
252
252
253 def __init__(self):
253 def __init__(self):
254 self._categories = {}
254 self._categories = {}
255 self._sequences = []
255 self._sequences = []
256 self._replies = {}
256 self._replies = {}
257
257
258 def add(self, category, entry, inreplyto=None):
258 def add(self, category, entry, inreplyto=None):
259 """add a new record of a given category.
259 """add a new record of a given category.
260
260
261 The entry can then be retrieved in the list returned by
261 The entry can then be retrieved in the list returned by
262 self['category']."""
262 self['category']."""
263 self._categories.setdefault(category, []).append(entry)
263 self._categories.setdefault(category, []).append(entry)
264 self._sequences.append((category, entry))
264 self._sequences.append((category, entry))
265 if inreplyto is not None:
265 if inreplyto is not None:
266 self.getreplies(inreplyto).add(category, entry)
266 self.getreplies(inreplyto).add(category, entry)
267
267
268 def getreplies(self, partid):
268 def getreplies(self, partid):
269 """get the records that are replies to a specific part"""
269 """get the records that are replies to a specific part"""
270 return self._replies.setdefault(partid, unbundlerecords())
270 return self._replies.setdefault(partid, unbundlerecords())
271
271
272 def __getitem__(self, cat):
272 def __getitem__(self, cat):
273 return tuple(self._categories.get(cat, ()))
273 return tuple(self._categories.get(cat, ()))
274
274
275 def __iter__(self):
275 def __iter__(self):
276 return iter(self._sequences)
276 return iter(self._sequences)
277
277
278 def __len__(self):
278 def __len__(self):
279 return len(self._sequences)
279 return len(self._sequences)
280
280
281 def __nonzero__(self):
281 def __nonzero__(self):
282 return bool(self._sequences)
282 return bool(self._sequences)
283
283
284 __bool__ = __nonzero__
284 __bool__ = __nonzero__
285
285
286 class bundleoperation(object):
286 class bundleoperation(object):
287 """an object that represents a single bundling process
287 """an object that represents a single bundling process
288
288
289 Its purpose is to carry unbundle-related objects and states.
289 Its purpose is to carry unbundle-related objects and states.
290
290
291 A new object should be created at the beginning of each bundle processing.
291 A new object should be created at the beginning of each bundle processing.
292 The object is to be returned by the processing function.
292 The object is to be returned by the processing function.
293
293
294 The object has very little content now it will ultimately contain:
294 The object has very little content now it will ultimately contain:
295 * an access to the repo the bundle is applied to,
295 * an access to the repo the bundle is applied to,
296 * a ui object,
296 * a ui object,
297 * a way to retrieve a transaction to add changes to the repo,
297 * a way to retrieve a transaction to add changes to the repo,
298 * a way to record the result of processing each part,
298 * a way to record the result of processing each part,
299 * a way to construct a bundle response when applicable.
299 * a way to construct a bundle response when applicable.
300 """
300 """
301
301
302 def __init__(self, repo, transactiongetter, captureoutput=True, source=''):
302 def __init__(self, repo, transactiongetter, captureoutput=True, source=''):
303 self.repo = repo
303 self.repo = repo
304 self.ui = repo.ui
304 self.ui = repo.ui
305 self.records = unbundlerecords()
305 self.records = unbundlerecords()
306 self.reply = None
306 self.reply = None
307 self.captureoutput = captureoutput
307 self.captureoutput = captureoutput
308 self.hookargs = {}
308 self.hookargs = {}
309 self._gettransaction = transactiongetter
309 self._gettransaction = transactiongetter
310 # carries value that can modify part behavior
310 # carries value that can modify part behavior
311 self.modes = {}
311 self.modes = {}
312 self.source = source
312 self.source = source
313
313
314 def gettransaction(self):
314 def gettransaction(self):
315 transaction = self._gettransaction()
315 transaction = self._gettransaction()
316
316
317 if self.hookargs:
317 if self.hookargs:
318 # the ones added to the transaction supercede those added
318 # the ones added to the transaction supercede those added
319 # to the operation.
319 # to the operation.
320 self.hookargs.update(transaction.hookargs)
320 self.hookargs.update(transaction.hookargs)
321 transaction.hookargs = self.hookargs
321 transaction.hookargs = self.hookargs
322
322
323 # mark the hookargs as flushed. further attempts to add to
323 # mark the hookargs as flushed. further attempts to add to
324 # hookargs will result in an abort.
324 # hookargs will result in an abort.
325 self.hookargs = None
325 self.hookargs = None
326
326
327 return transaction
327 return transaction
328
328
329 def addhookargs(self, hookargs):
329 def addhookargs(self, hookargs):
330 if self.hookargs is None:
330 if self.hookargs is None:
331 raise error.ProgrammingError('attempted to add hookargs to '
331 raise error.ProgrammingError('attempted to add hookargs to '
332 'operation after transaction started')
332 'operation after transaction started')
333 self.hookargs.update(hookargs)
333 self.hookargs.update(hookargs)
334
334
335 class TransactionUnavailable(RuntimeError):
335 class TransactionUnavailable(RuntimeError):
336 pass
336 pass
337
337
338 def _notransaction():
338 def _notransaction():
339 """default method to get a transaction while processing a bundle
339 """default method to get a transaction while processing a bundle
340
340
341 Raise an exception to highlight the fact that no transaction was expected
341 Raise an exception to highlight the fact that no transaction was expected
342 to be created"""
342 to be created"""
343 raise TransactionUnavailable()
343 raise TransactionUnavailable()
344
344
345 def applybundle(repo, unbundler, tr, source, url=None, **kwargs):
345 def applybundle(repo, unbundler, tr, source, url=None, **kwargs):
346 # transform me into unbundler.apply() as soon as the freeze is lifted
346 # transform me into unbundler.apply() as soon as the freeze is lifted
347 if isinstance(unbundler, unbundle20):
347 if isinstance(unbundler, unbundle20):
348 tr.hookargs['bundle2'] = '1'
348 tr.hookargs['bundle2'] = '1'
349 if source is not None and 'source' not in tr.hookargs:
349 if source is not None and 'source' not in tr.hookargs:
350 tr.hookargs['source'] = source
350 tr.hookargs['source'] = source
351 if url is not None and 'url' not in tr.hookargs:
351 if url is not None and 'url' not in tr.hookargs:
352 tr.hookargs['url'] = url
352 tr.hookargs['url'] = url
353 return processbundle(repo, unbundler, lambda: tr, source=source)
353 return processbundle(repo, unbundler, lambda: tr, source=source)
354 else:
354 else:
355 # the transactiongetter won't be used, but we might as well set it
355 # the transactiongetter won't be used, but we might as well set it
356 op = bundleoperation(repo, lambda: tr, source=source)
356 op = bundleoperation(repo, lambda: tr, source=source)
357 _processchangegroup(op, unbundler, tr, source, url, **kwargs)
357 _processchangegroup(op, unbundler, tr, source, url, **kwargs)
358 return op
358 return op
359
359
360 class partiterator(object):
360 class partiterator(object):
361 def __init__(self, repo, op, unbundler):
361 def __init__(self, repo, op, unbundler):
362 self.repo = repo
362 self.repo = repo
363 self.op = op
363 self.op = op
364 self.unbundler = unbundler
364 self.unbundler = unbundler
365 self.iterator = None
365 self.iterator = None
366 self.count = 0
366 self.count = 0
367 self.current = None
367 self.current = None
368
368
369 def __enter__(self):
369 def __enter__(self):
370 def func():
370 def func():
371 itr = enumerate(self.unbundler.iterparts())
371 itr = enumerate(self.unbundler.iterparts())
372 for count, p in itr:
372 for count, p in itr:
373 self.count = count
373 self.count = count
374 self.current = p
374 self.current = p
375 yield p
375 yield p
376 p.consume()
376 p.consume()
377 self.current = None
377 self.current = None
378 self.iterator = func()
378 self.iterator = func()
379 return self.iterator
379 return self.iterator
380
380
381 def __exit__(self, type, exc, tb):
381 def __exit__(self, type, exc, tb):
382 if not self.iterator:
382 if not self.iterator:
383 return
383 return
384
384
385 # Only gracefully abort in a normal exception situation. User aborts
385 # Only gracefully abort in a normal exception situation. User aborts
386 # like Ctrl+C throw a KeyboardInterrupt which is not a base Exception,
386 # like Ctrl+C throw a KeyboardInterrupt which is not a base Exception,
387 # and should not gracefully cleanup.
387 # and should not gracefully cleanup.
388 if isinstance(exc, Exception):
388 if isinstance(exc, Exception):
389 # Any exceptions seeking to the end of the bundle at this point are
389 # Any exceptions seeking to the end of the bundle at this point are
390 # almost certainly related to the underlying stream being bad.
390 # almost certainly related to the underlying stream being bad.
391 # And, chances are that the exception we're handling is related to
391 # And, chances are that the exception we're handling is related to
392 # getting in that bad state. So, we swallow the seeking error and
392 # getting in that bad state. So, we swallow the seeking error and
393 # re-raise the original error.
393 # re-raise the original error.
394 seekerror = False
394 seekerror = False
395 try:
395 try:
396 if self.current:
396 if self.current:
397 # consume the part content to not corrupt the stream.
397 # consume the part content to not corrupt the stream.
398 self.current.consume()
398 self.current.consume()
399
399
400 for part in self.iterator:
400 for part in self.iterator:
401 # consume the bundle content
401 # consume the bundle content
402 part.consume()
402 part.consume()
403 except Exception:
403 except Exception:
404 seekerror = True
404 seekerror = True
405
405
406 # Small hack to let caller code distinguish exceptions from bundle2
406 # Small hack to let caller code distinguish exceptions from bundle2
407 # processing from processing the old format. This is mostly needed
407 # processing from processing the old format. This is mostly needed
408 # to handle different return codes to unbundle according to the type
408 # to handle different return codes to unbundle according to the type
409 # of bundle. We should probably clean up or drop this return code
409 # of bundle. We should probably clean up or drop this return code
410 # craziness in a future version.
410 # craziness in a future version.
411 exc.duringunbundle2 = True
411 exc.duringunbundle2 = True
412 salvaged = []
412 salvaged = []
413 replycaps = None
413 replycaps = None
414 if self.op.reply is not None:
414 if self.op.reply is not None:
415 salvaged = self.op.reply.salvageoutput()
415 salvaged = self.op.reply.salvageoutput()
416 replycaps = self.op.reply.capabilities
416 replycaps = self.op.reply.capabilities
417 exc._replycaps = replycaps
417 exc._replycaps = replycaps
418 exc._bundle2salvagedoutput = salvaged
418 exc._bundle2salvagedoutput = salvaged
419
419
420 # Re-raising from a variable loses the original stack. So only use
420 # Re-raising from a variable loses the original stack. So only use
421 # that form if we need to.
421 # that form if we need to.
422 if seekerror:
422 if seekerror:
423 raise exc
423 raise exc
424
424
425 self.repo.ui.debug('bundle2-input-bundle: %i parts total\n' %
425 self.repo.ui.debug('bundle2-input-bundle: %i parts total\n' %
426 self.count)
426 self.count)
427
427
428 def processbundle(repo, unbundler, transactiongetter=None, op=None, source=''):
428 def processbundle(repo, unbundler, transactiongetter=None, op=None, source=''):
429 """This function process a bundle, apply effect to/from a repo
429 """This function process a bundle, apply effect to/from a repo
430
430
431 It iterates over each part then searches for and uses the proper handling
431 It iterates over each part then searches for and uses the proper handling
432 code to process the part. Parts are processed in order.
432 code to process the part. Parts are processed in order.
433
433
434 Unknown Mandatory part will abort the process.
434 Unknown Mandatory part will abort the process.
435
435
436 It is temporarily possible to provide a prebuilt bundleoperation to the
436 It is temporarily possible to provide a prebuilt bundleoperation to the
437 function. This is used to ensure output is properly propagated in case of
437 function. This is used to ensure output is properly propagated in case of
438 an error during the unbundling. This output capturing part will likely be
438 an error during the unbundling. This output capturing part will likely be
439 reworked and this ability will probably go away in the process.
439 reworked and this ability will probably go away in the process.
440 """
440 """
441 if op is None:
441 if op is None:
442 if transactiongetter is None:
442 if transactiongetter is None:
443 transactiongetter = _notransaction
443 transactiongetter = _notransaction
444 op = bundleoperation(repo, transactiongetter, source=source)
444 op = bundleoperation(repo, transactiongetter, source=source)
445 # todo:
445 # todo:
446 # - replace this is a init function soon.
446 # - replace this is a init function soon.
447 # - exception catching
447 # - exception catching
448 unbundler.params
448 unbundler.params
449 if repo.ui.debugflag:
449 if repo.ui.debugflag:
450 msg = ['bundle2-input-bundle:']
450 msg = ['bundle2-input-bundle:']
451 if unbundler.params:
451 if unbundler.params:
452 msg.append(' %i params' % len(unbundler.params))
452 msg.append(' %i params' % len(unbundler.params))
453 if op._gettransaction is None or op._gettransaction is _notransaction:
453 if op._gettransaction is None or op._gettransaction is _notransaction:
454 msg.append(' no-transaction')
454 msg.append(' no-transaction')
455 else:
455 else:
456 msg.append(' with-transaction')
456 msg.append(' with-transaction')
457 msg.append('\n')
457 msg.append('\n')
458 repo.ui.debug(''.join(msg))
458 repo.ui.debug(''.join(msg))
459
459
460 processparts(repo, op, unbundler)
460 processparts(repo, op, unbundler)
461
461
462 return op
462 return op
463
463
464 def processparts(repo, op, unbundler):
464 def processparts(repo, op, unbundler):
465 with partiterator(repo, op, unbundler) as parts:
465 with partiterator(repo, op, unbundler) as parts:
466 for part in parts:
466 for part in parts:
467 _processpart(op, part)
467 _processpart(op, part)
468
468
469 def _processchangegroup(op, cg, tr, source, url, **kwargs):
469 def _processchangegroup(op, cg, tr, source, url, **kwargs):
470 ret = cg.apply(op.repo, tr, source, url, **kwargs)
470 ret = cg.apply(op.repo, tr, source, url, **kwargs)
471 op.records.add('changegroup', {
471 op.records.add('changegroup', {
472 'return': ret,
472 'return': ret,
473 })
473 })
474 return ret
474 return ret
475
475
476 def _gethandler(op, part):
476 def _gethandler(op, part):
477 status = 'unknown' # used by debug output
477 status = 'unknown' # used by debug output
478 try:
478 try:
479 handler = parthandlermapping.get(part.type)
479 handler = parthandlermapping.get(part.type)
480 if handler is None:
480 if handler is None:
481 status = 'unsupported-type'
481 status = 'unsupported-type'
482 raise error.BundleUnknownFeatureError(parttype=part.type)
482 raise error.BundleUnknownFeatureError(parttype=part.type)
483 indebug(op.ui, 'found a handler for part %s' % part.type)
483 indebug(op.ui, 'found a handler for part %s' % part.type)
484 unknownparams = part.mandatorykeys - handler.params
484 unknownparams = part.mandatorykeys - handler.params
485 if unknownparams:
485 if unknownparams:
486 unknownparams = list(unknownparams)
486 unknownparams = list(unknownparams)
487 unknownparams.sort()
487 unknownparams.sort()
488 status = 'unsupported-params (%s)' % ', '.join(unknownparams)
488 status = 'unsupported-params (%s)' % ', '.join(unknownparams)
489 raise error.BundleUnknownFeatureError(parttype=part.type,
489 raise error.BundleUnknownFeatureError(parttype=part.type,
490 params=unknownparams)
490 params=unknownparams)
491 status = 'supported'
491 status = 'supported'
492 except error.BundleUnknownFeatureError as exc:
492 except error.BundleUnknownFeatureError as exc:
493 if part.mandatory: # mandatory parts
493 if part.mandatory: # mandatory parts
494 raise
494 raise
495 indebug(op.ui, 'ignoring unsupported advisory part %s' % exc)
495 indebug(op.ui, 'ignoring unsupported advisory part %s' % exc)
496 return # skip to part processing
496 return # skip to part processing
497 finally:
497 finally:
498 if op.ui.debugflag:
498 if op.ui.debugflag:
499 msg = ['bundle2-input-part: "%s"' % part.type]
499 msg = ['bundle2-input-part: "%s"' % part.type]
500 if not part.mandatory:
500 if not part.mandatory:
501 msg.append(' (advisory)')
501 msg.append(' (advisory)')
502 nbmp = len(part.mandatorykeys)
502 nbmp = len(part.mandatorykeys)
503 nbap = len(part.params) - nbmp
503 nbap = len(part.params) - nbmp
504 if nbmp or nbap:
504 if nbmp or nbap:
505 msg.append(' (params:')
505 msg.append(' (params:')
506 if nbmp:
506 if nbmp:
507 msg.append(' %i mandatory' % nbmp)
507 msg.append(' %i mandatory' % nbmp)
508 if nbap:
508 if nbap:
509 msg.append(' %i advisory' % nbmp)
509 msg.append(' %i advisory' % nbmp)
510 msg.append(')')
510 msg.append(')')
511 msg.append(' %s\n' % status)
511 msg.append(' %s\n' % status)
512 op.ui.debug(''.join(msg))
512 op.ui.debug(''.join(msg))
513
513
514 return handler
514 return handler
515
515
516 def _processpart(op, part):
516 def _processpart(op, part):
517 """process a single part from a bundle
517 """process a single part from a bundle
518
518
519 The part is guaranteed to have been fully consumed when the function exits
519 The part is guaranteed to have been fully consumed when the function exits
520 (even if an exception is raised)."""
520 (even if an exception is raised)."""
521 handler = _gethandler(op, part)
521 handler = _gethandler(op, part)
522 if handler is None:
522 if handler is None:
523 return
523 return
524
524
525 # handler is called outside the above try block so that we don't
525 # handler is called outside the above try block so that we don't
526 # risk catching KeyErrors from anything other than the
526 # risk catching KeyErrors from anything other than the
527 # parthandlermapping lookup (any KeyError raised by handler()
527 # parthandlermapping lookup (any KeyError raised by handler()
528 # itself represents a defect of a different variety).
528 # itself represents a defect of a different variety).
529 output = None
529 output = None
530 if op.captureoutput and op.reply is not None:
530 if op.captureoutput and op.reply is not None:
531 op.ui.pushbuffer(error=True, subproc=True)
531 op.ui.pushbuffer(error=True, subproc=True)
532 output = ''
532 output = ''
533 try:
533 try:
534 handler(op, part)
534 handler(op, part)
535 finally:
535 finally:
536 if output is not None:
536 if output is not None:
537 output = op.ui.popbuffer()
537 output = op.ui.popbuffer()
538 if output:
538 if output:
539 outpart = op.reply.newpart('output', data=output,
539 outpart = op.reply.newpart('output', data=output,
540 mandatory=False)
540 mandatory=False)
541 outpart.addparam(
541 outpart.addparam(
542 'in-reply-to', pycompat.bytestr(part.id), mandatory=False)
542 'in-reply-to', pycompat.bytestr(part.id), mandatory=False)
543
543
544 def decodecaps(blob):
544 def decodecaps(blob):
545 """decode a bundle2 caps bytes blob into a dictionary
545 """decode a bundle2 caps bytes blob into a dictionary
546
546
547 The blob is a list of capabilities (one per line)
547 The blob is a list of capabilities (one per line)
548 Capabilities may have values using a line of the form::
548 Capabilities may have values using a line of the form::
549
549
550 capability=value1,value2,value3
550 capability=value1,value2,value3
551
551
552 The values are always a list."""
552 The values are always a list."""
553 caps = {}
553 caps = {}
554 for line in blob.splitlines():
554 for line in blob.splitlines():
555 if not line:
555 if not line:
556 continue
556 continue
557 if '=' not in line:
557 if '=' not in line:
558 key, vals = line, ()
558 key, vals = line, ()
559 else:
559 else:
560 key, vals = line.split('=', 1)
560 key, vals = line.split('=', 1)
561 vals = vals.split(',')
561 vals = vals.split(',')
562 key = urlreq.unquote(key)
562 key = urlreq.unquote(key)
563 vals = [urlreq.unquote(v) for v in vals]
563 vals = [urlreq.unquote(v) for v in vals]
564 caps[key] = vals
564 caps[key] = vals
565 return caps
565 return caps
566
566
567 def encodecaps(caps):
567 def encodecaps(caps):
568 """encode a bundle2 caps dictionary into a bytes blob"""
568 """encode a bundle2 caps dictionary into a bytes blob"""
569 chunks = []
569 chunks = []
570 for ca in sorted(caps):
570 for ca in sorted(caps):
571 vals = caps[ca]
571 vals = caps[ca]
572 ca = urlreq.quote(ca)
572 ca = urlreq.quote(ca)
573 vals = [urlreq.quote(v) for v in vals]
573 vals = [urlreq.quote(v) for v in vals]
574 if vals:
574 if vals:
575 ca = "%s=%s" % (ca, ','.join(vals))
575 ca = "%s=%s" % (ca, ','.join(vals))
576 chunks.append(ca)
576 chunks.append(ca)
577 return '\n'.join(chunks)
577 return '\n'.join(chunks)
578
578
579 bundletypes = {
579 bundletypes = {
580 "": ("", 'UN'), # only when using unbundle on ssh and old http servers
580 "": ("", 'UN'), # only when using unbundle on ssh and old http servers
581 # since the unification ssh accepts a header but there
581 # since the unification ssh accepts a header but there
582 # is no capability signaling it.
582 # is no capability signaling it.
583 "HG20": (), # special-cased below
583 "HG20": (), # special-cased below
584 "HG10UN": ("HG10UN", 'UN'),
584 "HG10UN": ("HG10UN", 'UN'),
585 "HG10BZ": ("HG10", 'BZ'),
585 "HG10BZ": ("HG10", 'BZ'),
586 "HG10GZ": ("HG10GZ", 'GZ'),
586 "HG10GZ": ("HG10GZ", 'GZ'),
587 }
587 }
588
588
589 # hgweb uses this list to communicate its preferred type
589 # hgweb uses this list to communicate its preferred type
590 bundlepriority = ['HG10GZ', 'HG10BZ', 'HG10UN']
590 bundlepriority = ['HG10GZ', 'HG10BZ', 'HG10UN']
591
591
592 class bundle20(object):
592 class bundle20(object):
593 """represent an outgoing bundle2 container
593 """represent an outgoing bundle2 container
594
594
595 Use the `addparam` method to add stream level parameter. and `newpart` to
595 Use the `addparam` method to add stream level parameter. and `newpart` to
596 populate it. Then call `getchunks` to retrieve all the binary chunks of
596 populate it. Then call `getchunks` to retrieve all the binary chunks of
597 data that compose the bundle2 container."""
597 data that compose the bundle2 container."""
598
598
599 _magicstring = 'HG20'
599 _magicstring = 'HG20'
600
600
601 def __init__(self, ui, capabilities=()):
601 def __init__(self, ui, capabilities=()):
602 self.ui = ui
602 self.ui = ui
603 self._params = []
603 self._params = []
604 self._parts = []
604 self._parts = []
605 self.capabilities = dict(capabilities)
605 self.capabilities = dict(capabilities)
606 self._compengine = util.compengines.forbundletype('UN')
606 self._compengine = util.compengines.forbundletype('UN')
607 self._compopts = None
607 self._compopts = None
608 # If compression is being handled by a consumer of the raw
608 # If compression is being handled by a consumer of the raw
609 # data (e.g. the wire protocol), unsetting this flag tells
609 # data (e.g. the wire protocol), unsetting this flag tells
610 # consumers that the bundle is best left uncompressed.
610 # consumers that the bundle is best left uncompressed.
611 self.prefercompressed = True
611 self.prefercompressed = True
612
612
613 def setcompression(self, alg, compopts=None):
613 def setcompression(self, alg, compopts=None):
614 """setup core part compression to <alg>"""
614 """setup core part compression to <alg>"""
615 if alg in (None, 'UN'):
615 if alg in (None, 'UN'):
616 return
616 return
617 assert not any(n.lower() == 'compression' for n, v in self._params)
617 assert not any(n.lower() == 'compression' for n, v in self._params)
618 self.addparam('Compression', alg)
618 self.addparam('Compression', alg)
619 self._compengine = util.compengines.forbundletype(alg)
619 self._compengine = util.compengines.forbundletype(alg)
620 self._compopts = compopts
620 self._compopts = compopts
621
621
622 @property
622 @property
623 def nbparts(self):
623 def nbparts(self):
624 """total number of parts added to the bundler"""
624 """total number of parts added to the bundler"""
625 return len(self._parts)
625 return len(self._parts)
626
626
627 # methods used to defines the bundle2 content
627 # methods used to defines the bundle2 content
628 def addparam(self, name, value=None):
628 def addparam(self, name, value=None):
629 """add a stream level parameter"""
629 """add a stream level parameter"""
630 if not name:
630 if not name:
631 raise error.ProgrammingError(b'empty parameter name')
631 raise error.ProgrammingError(b'empty parameter name')
632 if name[0:1] not in pycompat.bytestr(string.ascii_letters):
632 if name[0:1] not in pycompat.bytestr(string.ascii_letters):
633 raise error.ProgrammingError(b'non letter first character: %s'
633 raise error.ProgrammingError(b'non letter first character: %s'
634 % name)
634 % name)
635 self._params.append((name, value))
635 self._params.append((name, value))
636
636
637 def addpart(self, part):
637 def addpart(self, part):
638 """add a new part to the bundle2 container
638 """add a new part to the bundle2 container
639
639
640 Parts contains the actual applicative payload."""
640 Parts contains the actual applicative payload."""
641 assert part.id is None
641 assert part.id is None
642 part.id = len(self._parts) # very cheap counter
642 part.id = len(self._parts) # very cheap counter
643 self._parts.append(part)
643 self._parts.append(part)
644
644
645 def newpart(self, typeid, *args, **kwargs):
645 def newpart(self, typeid, *args, **kwargs):
646 """create a new part and add it to the containers
646 """create a new part and add it to the containers
647
647
648 As the part is directly added to the containers. For now, this means
648 As the part is directly added to the containers. For now, this means
649 that any failure to properly initialize the part after calling
649 that any failure to properly initialize the part after calling
650 ``newpart`` should result in a failure of the whole bundling process.
650 ``newpart`` should result in a failure of the whole bundling process.
651
651
652 You can still fall back to manually create and add if you need better
652 You can still fall back to manually create and add if you need better
653 control."""
653 control."""
654 part = bundlepart(typeid, *args, **kwargs)
654 part = bundlepart(typeid, *args, **kwargs)
655 self.addpart(part)
655 self.addpart(part)
656 return part
656 return part
657
657
658 # methods used to generate the bundle2 stream
658 # methods used to generate the bundle2 stream
659 def getchunks(self):
659 def getchunks(self):
660 if self.ui.debugflag:
660 if self.ui.debugflag:
661 msg = ['bundle2-output-bundle: "%s",' % self._magicstring]
661 msg = ['bundle2-output-bundle: "%s",' % self._magicstring]
662 if self._params:
662 if self._params:
663 msg.append(' (%i params)' % len(self._params))
663 msg.append(' (%i params)' % len(self._params))
664 msg.append(' %i parts total\n' % len(self._parts))
664 msg.append(' %i parts total\n' % len(self._parts))
665 self.ui.debug(''.join(msg))
665 self.ui.debug(''.join(msg))
666 outdebug(self.ui, 'start emission of %s stream' % self._magicstring)
666 outdebug(self.ui, 'start emission of %s stream' % self._magicstring)
667 yield self._magicstring
667 yield self._magicstring
668 param = self._paramchunk()
668 param = self._paramchunk()
669 outdebug(self.ui, 'bundle parameter: %s' % param)
669 outdebug(self.ui, 'bundle parameter: %s' % param)
670 yield _pack(_fstreamparamsize, len(param))
670 yield _pack(_fstreamparamsize, len(param))
671 if param:
671 if param:
672 yield param
672 yield param
673 for chunk in self._compengine.compressstream(self._getcorechunk(),
673 for chunk in self._compengine.compressstream(self._getcorechunk(),
674 self._compopts):
674 self._compopts):
675 yield chunk
675 yield chunk
676
676
677 def _paramchunk(self):
677 def _paramchunk(self):
678 """return a encoded version of all stream parameters"""
678 """return a encoded version of all stream parameters"""
679 blocks = []
679 blocks = []
680 for par, value in self._params:
680 for par, value in self._params:
681 par = urlreq.quote(par)
681 par = urlreq.quote(par)
682 if value is not None:
682 if value is not None:
683 value = urlreq.quote(value)
683 value = urlreq.quote(value)
684 par = '%s=%s' % (par, value)
684 par = '%s=%s' % (par, value)
685 blocks.append(par)
685 blocks.append(par)
686 return ' '.join(blocks)
686 return ' '.join(blocks)
687
687
688 def _getcorechunk(self):
688 def _getcorechunk(self):
689 """yield chunk for the core part of the bundle
689 """yield chunk for the core part of the bundle
690
690
691 (all but headers and parameters)"""
691 (all but headers and parameters)"""
692 outdebug(self.ui, 'start of parts')
692 outdebug(self.ui, 'start of parts')
693 for part in self._parts:
693 for part in self._parts:
694 outdebug(self.ui, 'bundle part: "%s"' % part.type)
694 outdebug(self.ui, 'bundle part: "%s"' % part.type)
695 for chunk in part.getchunks(ui=self.ui):
695 for chunk in part.getchunks(ui=self.ui):
696 yield chunk
696 yield chunk
697 outdebug(self.ui, 'end of bundle')
697 outdebug(self.ui, 'end of bundle')
698 yield _pack(_fpartheadersize, 0)
698 yield _pack(_fpartheadersize, 0)
699
699
700
700
701 def salvageoutput(self):
701 def salvageoutput(self):
702 """return a list with a copy of all output parts in the bundle
702 """return a list with a copy of all output parts in the bundle
703
703
704 This is meant to be used during error handling to make sure we preserve
704 This is meant to be used during error handling to make sure we preserve
705 server output"""
705 server output"""
706 salvaged = []
706 salvaged = []
707 for part in self._parts:
707 for part in self._parts:
708 if part.type.startswith('output'):
708 if part.type.startswith('output'):
709 salvaged.append(part.copy())
709 salvaged.append(part.copy())
710 return salvaged
710 return salvaged
711
711
712
712
713 class unpackermixin(object):
713 class unpackermixin(object):
714 """A mixin to extract bytes and struct data from a stream"""
714 """A mixin to extract bytes and struct data from a stream"""
715
715
716 def __init__(self, fp):
716 def __init__(self, fp):
717 self._fp = fp
717 self._fp = fp
718
718
719 def _unpack(self, format):
719 def _unpack(self, format):
720 """unpack this struct format from the stream
720 """unpack this struct format from the stream
721
721
722 This method is meant for internal usage by the bundle2 protocol only.
722 This method is meant for internal usage by the bundle2 protocol only.
723 They directly manipulate the low level stream including bundle2 level
723 They directly manipulate the low level stream including bundle2 level
724 instruction.
724 instruction.
725
725
726 Do not use it to implement higher-level logic or methods."""
726 Do not use it to implement higher-level logic or methods."""
727 data = self._readexact(struct.calcsize(format))
727 data = self._readexact(struct.calcsize(format))
728 return _unpack(format, data)
728 return _unpack(format, data)
729
729
730 def _readexact(self, size):
730 def _readexact(self, size):
731 """read exactly <size> bytes from the stream
731 """read exactly <size> bytes from the stream
732
732
733 This method is meant for internal usage by the bundle2 protocol only.
733 This method is meant for internal usage by the bundle2 protocol only.
734 They directly manipulate the low level stream including bundle2 level
734 They directly manipulate the low level stream including bundle2 level
735 instruction.
735 instruction.
736
736
737 Do not use it to implement higher-level logic or methods."""
737 Do not use it to implement higher-level logic or methods."""
738 return changegroup.readexactly(self._fp, size)
738 return changegroup.readexactly(self._fp, size)
739
739
740 def getunbundler(ui, fp, magicstring=None):
740 def getunbundler(ui, fp, magicstring=None):
741 """return a valid unbundler object for a given magicstring"""
741 """return a valid unbundler object for a given magicstring"""
742 if magicstring is None:
742 if magicstring is None:
743 magicstring = changegroup.readexactly(fp, 4)
743 magicstring = changegroup.readexactly(fp, 4)
744 magic, version = magicstring[0:2], magicstring[2:4]
744 magic, version = magicstring[0:2], magicstring[2:4]
745 if magic != 'HG':
745 if magic != 'HG':
746 ui.debug(
746 ui.debug(
747 "error: invalid magic: %r (version %r), should be 'HG'\n"
747 "error: invalid magic: %r (version %r), should be 'HG'\n"
748 % (magic, version))
748 % (magic, version))
749 raise error.Abort(_('not a Mercurial bundle'))
749 raise error.Abort(_('not a Mercurial bundle'))
750 unbundlerclass = formatmap.get(version)
750 unbundlerclass = formatmap.get(version)
751 if unbundlerclass is None:
751 if unbundlerclass is None:
752 raise error.Abort(_('unknown bundle version %s') % version)
752 raise error.Abort(_('unknown bundle version %s') % version)
753 unbundler = unbundlerclass(ui, fp)
753 unbundler = unbundlerclass(ui, fp)
754 indebug(ui, 'start processing of %s stream' % magicstring)
754 indebug(ui, 'start processing of %s stream' % magicstring)
755 return unbundler
755 return unbundler
756
756
757 class unbundle20(unpackermixin):
757 class unbundle20(unpackermixin):
758 """interpret a bundle2 stream
758 """interpret a bundle2 stream
759
759
760 This class is fed with a binary stream and yields parts through its
760 This class is fed with a binary stream and yields parts through its
761 `iterparts` methods."""
761 `iterparts` methods."""
762
762
763 _magicstring = 'HG20'
763 _magicstring = 'HG20'
764
764
765 def __init__(self, ui, fp):
765 def __init__(self, ui, fp):
766 """If header is specified, we do not read it out of the stream."""
766 """If header is specified, we do not read it out of the stream."""
767 self.ui = ui
767 self.ui = ui
768 self._compengine = util.compengines.forbundletype('UN')
768 self._compengine = util.compengines.forbundletype('UN')
769 self._compressed = None
769 self._compressed = None
770 super(unbundle20, self).__init__(fp)
770 super(unbundle20, self).__init__(fp)
771
771
772 @util.propertycache
772 @util.propertycache
773 def params(self):
773 def params(self):
774 """dictionary of stream level parameters"""
774 """dictionary of stream level parameters"""
775 indebug(self.ui, 'reading bundle2 stream parameters')
775 indebug(self.ui, 'reading bundle2 stream parameters')
776 params = {}
776 params = {}
777 paramssize = self._unpack(_fstreamparamsize)[0]
777 paramssize = self._unpack(_fstreamparamsize)[0]
778 if paramssize < 0:
778 if paramssize < 0:
779 raise error.BundleValueError('negative bundle param size: %i'
779 raise error.BundleValueError('negative bundle param size: %i'
780 % paramssize)
780 % paramssize)
781 if paramssize:
781 if paramssize:
782 params = self._readexact(paramssize)
782 params = self._readexact(paramssize)
783 params = self._processallparams(params)
783 params = self._processallparams(params)
784 return params
784 return params
785
785
786 def _processallparams(self, paramsblock):
786 def _processallparams(self, paramsblock):
787 """"""
787 """"""
788 params = util.sortdict()
788 params = util.sortdict()
789 for p in paramsblock.split(' '):
789 for p in paramsblock.split(' '):
790 p = p.split('=', 1)
790 p = p.split('=', 1)
791 p = [urlreq.unquote(i) for i in p]
791 p = [urlreq.unquote(i) for i in p]
792 if len(p) < 2:
792 if len(p) < 2:
793 p.append(None)
793 p.append(None)
794 self._processparam(*p)
794 self._processparam(*p)
795 params[p[0]] = p[1]
795 params[p[0]] = p[1]
796 return params
796 return params
797
797
798
798
799 def _processparam(self, name, value):
799 def _processparam(self, name, value):
800 """process a parameter, applying its effect if needed
800 """process a parameter, applying its effect if needed
801
801
802 Parameter starting with a lower case letter are advisory and will be
802 Parameter starting with a lower case letter are advisory and will be
803 ignored when unknown. Those starting with an upper case letter are
803 ignored when unknown. Those starting with an upper case letter are
804 mandatory and will this function will raise a KeyError when unknown.
804 mandatory and will this function will raise a KeyError when unknown.
805
805
806 Note: no option are currently supported. Any input will be either
806 Note: no option are currently supported. Any input will be either
807 ignored or failing.
807 ignored or failing.
808 """
808 """
809 if not name:
809 if not name:
810 raise ValueError(r'empty parameter name')
810 raise ValueError(r'empty parameter name')
811 if name[0:1] not in pycompat.bytestr(string.ascii_letters):
811 if name[0:1] not in pycompat.bytestr(string.ascii_letters):
812 raise ValueError(r'non letter first character: %s' % name)
812 raise ValueError(r'non letter first character: %s' % name)
813 try:
813 try:
814 handler = b2streamparamsmap[name.lower()]
814 handler = b2streamparamsmap[name.lower()]
815 except KeyError:
815 except KeyError:
816 if name[0:1].islower():
816 if name[0:1].islower():
817 indebug(self.ui, "ignoring unknown parameter %s" % name)
817 indebug(self.ui, "ignoring unknown parameter %s" % name)
818 else:
818 else:
819 raise error.BundleUnknownFeatureError(params=(name,))
819 raise error.BundleUnknownFeatureError(params=(name,))
820 else:
820 else:
821 handler(self, name, value)
821 handler(self, name, value)
822
822
823 def _forwardchunks(self):
823 def _forwardchunks(self):
824 """utility to transfer a bundle2 as binary
824 """utility to transfer a bundle2 as binary
825
825
826 This is made necessary by the fact the 'getbundle' command over 'ssh'
826 This is made necessary by the fact the 'getbundle' command over 'ssh'
827 have no way to know then the reply end, relying on the bundle to be
827 have no way to know then the reply end, relying on the bundle to be
828 interpreted to know its end. This is terrible and we are sorry, but we
828 interpreted to know its end. This is terrible and we are sorry, but we
829 needed to move forward to get general delta enabled.
829 needed to move forward to get general delta enabled.
830 """
830 """
831 yield self._magicstring
831 yield self._magicstring
832 assert 'params' not in vars(self)
832 assert 'params' not in vars(self)
833 paramssize = self._unpack(_fstreamparamsize)[0]
833 paramssize = self._unpack(_fstreamparamsize)[0]
834 if paramssize < 0:
834 if paramssize < 0:
835 raise error.BundleValueError('negative bundle param size: %i'
835 raise error.BundleValueError('negative bundle param size: %i'
836 % paramssize)
836 % paramssize)
837 yield _pack(_fstreamparamsize, paramssize)
837 yield _pack(_fstreamparamsize, paramssize)
838 if paramssize:
838 if paramssize:
839 params = self._readexact(paramssize)
839 params = self._readexact(paramssize)
840 self._processallparams(params)
840 self._processallparams(params)
841 yield params
841 yield params
842 assert self._compengine.bundletype == 'UN'
842 assert self._compengine.bundletype == 'UN'
843 # From there, payload might need to be decompressed
843 # From there, payload might need to be decompressed
844 self._fp = self._compengine.decompressorreader(self._fp)
844 self._fp = self._compengine.decompressorreader(self._fp)
845 emptycount = 0
845 emptycount = 0
846 while emptycount < 2:
846 while emptycount < 2:
847 # so we can brainlessly loop
847 # so we can brainlessly loop
848 assert _fpartheadersize == _fpayloadsize
848 assert _fpartheadersize == _fpayloadsize
849 size = self._unpack(_fpartheadersize)[0]
849 size = self._unpack(_fpartheadersize)[0]
850 yield _pack(_fpartheadersize, size)
850 yield _pack(_fpartheadersize, size)
851 if size:
851 if size:
852 emptycount = 0
852 emptycount = 0
853 else:
853 else:
854 emptycount += 1
854 emptycount += 1
855 continue
855 continue
856 if size == flaginterrupt:
856 if size == flaginterrupt:
857 continue
857 continue
858 elif size < 0:
858 elif size < 0:
859 raise error.BundleValueError('negative chunk size: %i')
859 raise error.BundleValueError('negative chunk size: %i')
860 yield self._readexact(size)
860 yield self._readexact(size)
861
861
862
862
863 def iterparts(self, seekable=False):
863 def iterparts(self, seekable=False):
864 """yield all parts contained in the stream"""
864 """yield all parts contained in the stream"""
865 cls = seekableunbundlepart if seekable else unbundlepart
865 cls = seekableunbundlepart if seekable else unbundlepart
866 # make sure param have been loaded
866 # make sure param have been loaded
867 self.params
867 self.params
868 # From there, payload need to be decompressed
868 # From there, payload need to be decompressed
869 self._fp = self._compengine.decompressorreader(self._fp)
869 self._fp = self._compengine.decompressorreader(self._fp)
870 indebug(self.ui, 'start extraction of bundle2 parts')
870 indebug(self.ui, 'start extraction of bundle2 parts')
871 headerblock = self._readpartheader()
871 headerblock = self._readpartheader()
872 while headerblock is not None:
872 while headerblock is not None:
873 part = cls(self.ui, headerblock, self._fp)
873 part = cls(self.ui, headerblock, self._fp)
874 yield part
874 yield part
875 # Ensure part is fully consumed so we can start reading the next
875 # Ensure part is fully consumed so we can start reading the next
876 # part.
876 # part.
877 part.consume()
877 part.consume()
878
878
879 headerblock = self._readpartheader()
879 headerblock = self._readpartheader()
880 indebug(self.ui, 'end of bundle2 stream')
880 indebug(self.ui, 'end of bundle2 stream')
881
881
882 def _readpartheader(self):
882 def _readpartheader(self):
883 """reads a part header size and return the bytes blob
883 """reads a part header size and return the bytes blob
884
884
885 returns None if empty"""
885 returns None if empty"""
886 headersize = self._unpack(_fpartheadersize)[0]
886 headersize = self._unpack(_fpartheadersize)[0]
887 if headersize < 0:
887 if headersize < 0:
888 raise error.BundleValueError('negative part header size: %i'
888 raise error.BundleValueError('negative part header size: %i'
889 % headersize)
889 % headersize)
890 indebug(self.ui, 'part header size: %i' % headersize)
890 indebug(self.ui, 'part header size: %i' % headersize)
891 if headersize:
891 if headersize:
892 return self._readexact(headersize)
892 return self._readexact(headersize)
893 return None
893 return None
894
894
895 def compressed(self):
895 def compressed(self):
896 self.params # load params
896 self.params # load params
897 return self._compressed
897 return self._compressed
898
898
899 def close(self):
899 def close(self):
900 """close underlying file"""
900 """close underlying file"""
901 if util.safehasattr(self._fp, 'close'):
901 if util.safehasattr(self._fp, 'close'):
902 return self._fp.close()
902 return self._fp.close()
903
903
904 formatmap = {'20': unbundle20}
904 formatmap = {'20': unbundle20}
905
905
906 b2streamparamsmap = {}
906 b2streamparamsmap = {}
907
907
908 def b2streamparamhandler(name):
908 def b2streamparamhandler(name):
909 """register a handler for a stream level parameter"""
909 """register a handler for a stream level parameter"""
910 def decorator(func):
910 def decorator(func):
911 assert name not in formatmap
911 assert name not in formatmap
912 b2streamparamsmap[name] = func
912 b2streamparamsmap[name] = func
913 return func
913 return func
914 return decorator
914 return decorator
915
915
916 @b2streamparamhandler('compression')
916 @b2streamparamhandler('compression')
917 def processcompression(unbundler, param, value):
917 def processcompression(unbundler, param, value):
918 """read compression parameter and install payload decompression"""
918 """read compression parameter and install payload decompression"""
919 if value not in util.compengines.supportedbundletypes:
919 if value not in util.compengines.supportedbundletypes:
920 raise error.BundleUnknownFeatureError(params=(param,),
920 raise error.BundleUnknownFeatureError(params=(param,),
921 values=(value,))
921 values=(value,))
922 unbundler._compengine = util.compengines.forbundletype(value)
922 unbundler._compengine = util.compengines.forbundletype(value)
923 if value is not None:
923 if value is not None:
924 unbundler._compressed = True
924 unbundler._compressed = True
925
925
926 class bundlepart(object):
926 class bundlepart(object):
927 """A bundle2 part contains application level payload
927 """A bundle2 part contains application level payload
928
928
929 The part `type` is used to route the part to the application level
929 The part `type` is used to route the part to the application level
930 handler.
930 handler.
931
931
932 The part payload is contained in ``part.data``. It could be raw bytes or a
932 The part payload is contained in ``part.data``. It could be raw bytes or a
933 generator of byte chunks.
933 generator of byte chunks.
934
934
935 You can add parameters to the part using the ``addparam`` method.
935 You can add parameters to the part using the ``addparam`` method.
936 Parameters can be either mandatory (default) or advisory. Remote side
936 Parameters can be either mandatory (default) or advisory. Remote side
937 should be able to safely ignore the advisory ones.
937 should be able to safely ignore the advisory ones.
938
938
939 Both data and parameters cannot be modified after the generation has begun.
939 Both data and parameters cannot be modified after the generation has begun.
940 """
940 """
941
941
942 def __init__(self, parttype, mandatoryparams=(), advisoryparams=(),
942 def __init__(self, parttype, mandatoryparams=(), advisoryparams=(),
943 data='', mandatory=True):
943 data='', mandatory=True):
944 validateparttype(parttype)
944 validateparttype(parttype)
945 self.id = None
945 self.id = None
946 self.type = parttype
946 self.type = parttype
947 self._data = data
947 self._data = data
948 self._mandatoryparams = list(mandatoryparams)
948 self._mandatoryparams = list(mandatoryparams)
949 self._advisoryparams = list(advisoryparams)
949 self._advisoryparams = list(advisoryparams)
950 # checking for duplicated entries
950 # checking for duplicated entries
951 self._seenparams = set()
951 self._seenparams = set()
952 for pname, __ in self._mandatoryparams + self._advisoryparams:
952 for pname, __ in self._mandatoryparams + self._advisoryparams:
953 if pname in self._seenparams:
953 if pname in self._seenparams:
954 raise error.ProgrammingError('duplicated params: %s' % pname)
954 raise error.ProgrammingError('duplicated params: %s' % pname)
955 self._seenparams.add(pname)
955 self._seenparams.add(pname)
956 # status of the part's generation:
956 # status of the part's generation:
957 # - None: not started,
957 # - None: not started,
958 # - False: currently generated,
958 # - False: currently generated,
959 # - True: generation done.
959 # - True: generation done.
960 self._generated = None
960 self._generated = None
961 self.mandatory = mandatory
961 self.mandatory = mandatory
962
962
963 def __repr__(self):
963 def __repr__(self):
964 cls = "%s.%s" % (self.__class__.__module__, self.__class__.__name__)
964 cls = "%s.%s" % (self.__class__.__module__, self.__class__.__name__)
965 return ('<%s object at %x; id: %s; type: %s; mandatory: %s>'
965 return ('<%s object at %x; id: %s; type: %s; mandatory: %s>'
966 % (cls, id(self), self.id, self.type, self.mandatory))
966 % (cls, id(self), self.id, self.type, self.mandatory))
967
967
968 def copy(self):
968 def copy(self):
969 """return a copy of the part
969 """return a copy of the part
970
970
971 The new part have the very same content but no partid assigned yet.
971 The new part have the very same content but no partid assigned yet.
972 Parts with generated data cannot be copied."""
972 Parts with generated data cannot be copied."""
973 assert not util.safehasattr(self.data, 'next')
973 assert not util.safehasattr(self.data, 'next')
974 return self.__class__(self.type, self._mandatoryparams,
974 return self.__class__(self.type, self._mandatoryparams,
975 self._advisoryparams, self._data, self.mandatory)
975 self._advisoryparams, self._data, self.mandatory)
976
976
977 # methods used to defines the part content
977 # methods used to defines the part content
978 @property
978 @property
979 def data(self):
979 def data(self):
980 return self._data
980 return self._data
981
981
982 @data.setter
982 @data.setter
983 def data(self, data):
983 def data(self, data):
984 if self._generated is not None:
984 if self._generated is not None:
985 raise error.ReadOnlyPartError('part is being generated')
985 raise error.ReadOnlyPartError('part is being generated')
986 self._data = data
986 self._data = data
987
987
988 @property
988 @property
989 def mandatoryparams(self):
989 def mandatoryparams(self):
990 # make it an immutable tuple to force people through ``addparam``
990 # make it an immutable tuple to force people through ``addparam``
991 return tuple(self._mandatoryparams)
991 return tuple(self._mandatoryparams)
992
992
993 @property
993 @property
994 def advisoryparams(self):
994 def advisoryparams(self):
995 # make it an immutable tuple to force people through ``addparam``
995 # make it an immutable tuple to force people through ``addparam``
996 return tuple(self._advisoryparams)
996 return tuple(self._advisoryparams)
997
997
998 def addparam(self, name, value='', mandatory=True):
998 def addparam(self, name, value='', mandatory=True):
999 """add a parameter to the part
999 """add a parameter to the part
1000
1000
1001 If 'mandatory' is set to True, the remote handler must claim support
1001 If 'mandatory' is set to True, the remote handler must claim support
1002 for this parameter or the unbundling will be aborted.
1002 for this parameter or the unbundling will be aborted.
1003
1003
1004 The 'name' and 'value' cannot exceed 255 bytes each.
1004 The 'name' and 'value' cannot exceed 255 bytes each.
1005 """
1005 """
1006 if self._generated is not None:
1006 if self._generated is not None:
1007 raise error.ReadOnlyPartError('part is being generated')
1007 raise error.ReadOnlyPartError('part is being generated')
1008 if name in self._seenparams:
1008 if name in self._seenparams:
1009 raise ValueError('duplicated params: %s' % name)
1009 raise ValueError('duplicated params: %s' % name)
1010 self._seenparams.add(name)
1010 self._seenparams.add(name)
1011 params = self._advisoryparams
1011 params = self._advisoryparams
1012 if mandatory:
1012 if mandatory:
1013 params = self._mandatoryparams
1013 params = self._mandatoryparams
1014 params.append((name, value))
1014 params.append((name, value))
1015
1015
1016 # methods used to generates the bundle2 stream
1016 # methods used to generates the bundle2 stream
1017 def getchunks(self, ui):
1017 def getchunks(self, ui):
1018 if self._generated is not None:
1018 if self._generated is not None:
1019 raise error.ProgrammingError('part can only be consumed once')
1019 raise error.ProgrammingError('part can only be consumed once')
1020 self._generated = False
1020 self._generated = False
1021
1021
1022 if ui.debugflag:
1022 if ui.debugflag:
1023 msg = ['bundle2-output-part: "%s"' % self.type]
1023 msg = ['bundle2-output-part: "%s"' % self.type]
1024 if not self.mandatory:
1024 if not self.mandatory:
1025 msg.append(' (advisory)')
1025 msg.append(' (advisory)')
1026 nbmp = len(self.mandatoryparams)
1026 nbmp = len(self.mandatoryparams)
1027 nbap = len(self.advisoryparams)
1027 nbap = len(self.advisoryparams)
1028 if nbmp or nbap:
1028 if nbmp or nbap:
1029 msg.append(' (params:')
1029 msg.append(' (params:')
1030 if nbmp:
1030 if nbmp:
1031 msg.append(' %i mandatory' % nbmp)
1031 msg.append(' %i mandatory' % nbmp)
1032 if nbap:
1032 if nbap:
1033 msg.append(' %i advisory' % nbmp)
1033 msg.append(' %i advisory' % nbmp)
1034 msg.append(')')
1034 msg.append(')')
1035 if not self.data:
1035 if not self.data:
1036 msg.append(' empty payload')
1036 msg.append(' empty payload')
1037 elif (util.safehasattr(self.data, 'next')
1037 elif (util.safehasattr(self.data, 'next')
1038 or util.safehasattr(self.data, '__next__')):
1038 or util.safehasattr(self.data, '__next__')):
1039 msg.append(' streamed payload')
1039 msg.append(' streamed payload')
1040 else:
1040 else:
1041 msg.append(' %i bytes payload' % len(self.data))
1041 msg.append(' %i bytes payload' % len(self.data))
1042 msg.append('\n')
1042 msg.append('\n')
1043 ui.debug(''.join(msg))
1043 ui.debug(''.join(msg))
1044
1044
1045 #### header
1045 #### header
1046 if self.mandatory:
1046 if self.mandatory:
1047 parttype = self.type.upper()
1047 parttype = self.type.upper()
1048 else:
1048 else:
1049 parttype = self.type.lower()
1049 parttype = self.type.lower()
1050 outdebug(ui, 'part %s: "%s"' % (pycompat.bytestr(self.id), parttype))
1050 outdebug(ui, 'part %s: "%s"' % (pycompat.bytestr(self.id), parttype))
1051 ## parttype
1051 ## parttype
1052 header = [_pack(_fparttypesize, len(parttype)),
1052 header = [_pack(_fparttypesize, len(parttype)),
1053 parttype, _pack(_fpartid, self.id),
1053 parttype, _pack(_fpartid, self.id),
1054 ]
1054 ]
1055 ## parameters
1055 ## parameters
1056 # count
1056 # count
1057 manpar = self.mandatoryparams
1057 manpar = self.mandatoryparams
1058 advpar = self.advisoryparams
1058 advpar = self.advisoryparams
1059 header.append(_pack(_fpartparamcount, len(manpar), len(advpar)))
1059 header.append(_pack(_fpartparamcount, len(manpar), len(advpar)))
1060 # size
1060 # size
1061 parsizes = []
1061 parsizes = []
1062 for key, value in manpar:
1062 for key, value in manpar:
1063 parsizes.append(len(key))
1063 parsizes.append(len(key))
1064 parsizes.append(len(value))
1064 parsizes.append(len(value))
1065 for key, value in advpar:
1065 for key, value in advpar:
1066 parsizes.append(len(key))
1066 parsizes.append(len(key))
1067 parsizes.append(len(value))
1067 parsizes.append(len(value))
1068 paramsizes = _pack(_makefpartparamsizes(len(parsizes) // 2), *parsizes)
1068 paramsizes = _pack(_makefpartparamsizes(len(parsizes) // 2), *parsizes)
1069 header.append(paramsizes)
1069 header.append(paramsizes)
1070 # key, value
1070 # key, value
1071 for key, value in manpar:
1071 for key, value in manpar:
1072 header.append(key)
1072 header.append(key)
1073 header.append(value)
1073 header.append(value)
1074 for key, value in advpar:
1074 for key, value in advpar:
1075 header.append(key)
1075 header.append(key)
1076 header.append(value)
1076 header.append(value)
1077 ## finalize header
1077 ## finalize header
1078 try:
1078 try:
1079 headerchunk = ''.join(header)
1079 headerchunk = ''.join(header)
1080 except TypeError:
1080 except TypeError:
1081 raise TypeError(r'Found a non-bytes trying to '
1081 raise TypeError(r'Found a non-bytes trying to '
1082 r'build bundle part header: %r' % header)
1082 r'build bundle part header: %r' % header)
1083 outdebug(ui, 'header chunk size: %i' % len(headerchunk))
1083 outdebug(ui, 'header chunk size: %i' % len(headerchunk))
1084 yield _pack(_fpartheadersize, len(headerchunk))
1084 yield _pack(_fpartheadersize, len(headerchunk))
1085 yield headerchunk
1085 yield headerchunk
1086 ## payload
1086 ## payload
1087 try:
1087 try:
1088 for chunk in self._payloadchunks():
1088 for chunk in self._payloadchunks():
1089 outdebug(ui, 'payload chunk size: %i' % len(chunk))
1089 outdebug(ui, 'payload chunk size: %i' % len(chunk))
1090 yield _pack(_fpayloadsize, len(chunk))
1090 yield _pack(_fpayloadsize, len(chunk))
1091 yield chunk
1091 yield chunk
1092 except GeneratorExit:
1092 except GeneratorExit:
1093 # GeneratorExit means that nobody is listening for our
1093 # GeneratorExit means that nobody is listening for our
1094 # results anyway, so just bail quickly rather than trying
1094 # results anyway, so just bail quickly rather than trying
1095 # to produce an error part.
1095 # to produce an error part.
1096 ui.debug('bundle2-generatorexit\n')
1096 ui.debug('bundle2-generatorexit\n')
1097 raise
1097 raise
1098 except BaseException as exc:
1098 except BaseException as exc:
1099 bexc = stringutil.forcebytestr(exc)
1099 bexc = stringutil.forcebytestr(exc)
1100 # backup exception data for later
1100 # backup exception data for later
1101 ui.debug('bundle2-input-stream-interrupt: encoding exception %s'
1101 ui.debug('bundle2-input-stream-interrupt: encoding exception %s'
1102 % bexc)
1102 % bexc)
1103 tb = sys.exc_info()[2]
1103 tb = sys.exc_info()[2]
1104 msg = 'unexpected error: %s' % bexc
1104 msg = 'unexpected error: %s' % bexc
1105 interpart = bundlepart('error:abort', [('message', msg)],
1105 interpart = bundlepart('error:abort', [('message', msg)],
1106 mandatory=False)
1106 mandatory=False)
1107 interpart.id = 0
1107 interpart.id = 0
1108 yield _pack(_fpayloadsize, -1)
1108 yield _pack(_fpayloadsize, -1)
1109 for chunk in interpart.getchunks(ui=ui):
1109 for chunk in interpart.getchunks(ui=ui):
1110 yield chunk
1110 yield chunk
1111 outdebug(ui, 'closing payload chunk')
1111 outdebug(ui, 'closing payload chunk')
1112 # abort current part payload
1112 # abort current part payload
1113 yield _pack(_fpayloadsize, 0)
1113 yield _pack(_fpayloadsize, 0)
1114 pycompat.raisewithtb(exc, tb)
1114 pycompat.raisewithtb(exc, tb)
1115 # end of payload
1115 # end of payload
1116 outdebug(ui, 'closing payload chunk')
1116 outdebug(ui, 'closing payload chunk')
1117 yield _pack(_fpayloadsize, 0)
1117 yield _pack(_fpayloadsize, 0)
1118 self._generated = True
1118 self._generated = True
1119
1119
1120 def _payloadchunks(self):
1120 def _payloadchunks(self):
1121 """yield chunks of a the part payload
1121 """yield chunks of a the part payload
1122
1122
1123 Exists to handle the different methods to provide data to a part."""
1123 Exists to handle the different methods to provide data to a part."""
1124 # we only support fixed size data now.
1124 # we only support fixed size data now.
1125 # This will be improved in the future.
1125 # This will be improved in the future.
1126 if (util.safehasattr(self.data, 'next')
1126 if (util.safehasattr(self.data, 'next')
1127 or util.safehasattr(self.data, '__next__')):
1127 or util.safehasattr(self.data, '__next__')):
1128 buff = util.chunkbuffer(self.data)
1128 buff = util.chunkbuffer(self.data)
1129 chunk = buff.read(preferedchunksize)
1129 chunk = buff.read(preferedchunksize)
1130 while chunk:
1130 while chunk:
1131 yield chunk
1131 yield chunk
1132 chunk = buff.read(preferedchunksize)
1132 chunk = buff.read(preferedchunksize)
1133 elif len(self.data):
1133 elif len(self.data):
1134 yield self.data
1134 yield self.data
1135
1135
1136
1136
1137 flaginterrupt = -1
1137 flaginterrupt = -1
1138
1138
1139 class interrupthandler(unpackermixin):
1139 class interrupthandler(unpackermixin):
1140 """read one part and process it with restricted capability
1140 """read one part and process it with restricted capability
1141
1141
1142 This allows to transmit exception raised on the producer size during part
1142 This allows to transmit exception raised on the producer size during part
1143 iteration while the consumer is reading a part.
1143 iteration while the consumer is reading a part.
1144
1144
1145 Part processed in this manner only have access to a ui object,"""
1145 Part processed in this manner only have access to a ui object,"""
1146
1146
1147 def __init__(self, ui, fp):
1147 def __init__(self, ui, fp):
1148 super(interrupthandler, self).__init__(fp)
1148 super(interrupthandler, self).__init__(fp)
1149 self.ui = ui
1149 self.ui = ui
1150
1150
1151 def _readpartheader(self):
1151 def _readpartheader(self):
1152 """reads a part header size and return the bytes blob
1152 """reads a part header size and return the bytes blob
1153
1153
1154 returns None if empty"""
1154 returns None if empty"""
1155 headersize = self._unpack(_fpartheadersize)[0]
1155 headersize = self._unpack(_fpartheadersize)[0]
1156 if headersize < 0:
1156 if headersize < 0:
1157 raise error.BundleValueError('negative part header size: %i'
1157 raise error.BundleValueError('negative part header size: %i'
1158 % headersize)
1158 % headersize)
1159 indebug(self.ui, 'part header size: %i\n' % headersize)
1159 indebug(self.ui, 'part header size: %i\n' % headersize)
1160 if headersize:
1160 if headersize:
1161 return self._readexact(headersize)
1161 return self._readexact(headersize)
1162 return None
1162 return None
1163
1163
1164 def __call__(self):
1164 def __call__(self):
1165
1165
1166 self.ui.debug('bundle2-input-stream-interrupt:'
1166 self.ui.debug('bundle2-input-stream-interrupt:'
1167 ' opening out of band context\n')
1167 ' opening out of band context\n')
1168 indebug(self.ui, 'bundle2 stream interruption, looking for a part.')
1168 indebug(self.ui, 'bundle2 stream interruption, looking for a part.')
1169 headerblock = self._readpartheader()
1169 headerblock = self._readpartheader()
1170 if headerblock is None:
1170 if headerblock is None:
1171 indebug(self.ui, 'no part found during interruption.')
1171 indebug(self.ui, 'no part found during interruption.')
1172 return
1172 return
1173 part = unbundlepart(self.ui, headerblock, self._fp)
1173 part = unbundlepart(self.ui, headerblock, self._fp)
1174 op = interruptoperation(self.ui)
1174 op = interruptoperation(self.ui)
1175 hardabort = False
1175 hardabort = False
1176 try:
1176 try:
1177 _processpart(op, part)
1177 _processpart(op, part)
1178 except (SystemExit, KeyboardInterrupt):
1178 except (SystemExit, KeyboardInterrupt):
1179 hardabort = True
1179 hardabort = True
1180 raise
1180 raise
1181 finally:
1181 finally:
1182 if not hardabort:
1182 if not hardabort:
1183 part.consume()
1183 part.consume()
1184 self.ui.debug('bundle2-input-stream-interrupt:'
1184 self.ui.debug('bundle2-input-stream-interrupt:'
1185 ' closing out of band context\n')
1185 ' closing out of band context\n')
1186
1186
1187 class interruptoperation(object):
1187 class interruptoperation(object):
1188 """A limited operation to be use by part handler during interruption
1188 """A limited operation to be use by part handler during interruption
1189
1189
1190 It only have access to an ui object.
1190 It only have access to an ui object.
1191 """
1191 """
1192
1192
1193 def __init__(self, ui):
1193 def __init__(self, ui):
1194 self.ui = ui
1194 self.ui = ui
1195 self.reply = None
1195 self.reply = None
1196 self.captureoutput = False
1196 self.captureoutput = False
1197
1197
1198 @property
1198 @property
1199 def repo(self):
1199 def repo(self):
1200 raise error.ProgrammingError('no repo access from stream interruption')
1200 raise error.ProgrammingError('no repo access from stream interruption')
1201
1201
1202 def gettransaction(self):
1202 def gettransaction(self):
1203 raise TransactionUnavailable('no repo access from stream interruption')
1203 raise TransactionUnavailable('no repo access from stream interruption')
1204
1204
1205 def decodepayloadchunks(ui, fh):
1205 def decodepayloadchunks(ui, fh):
1206 """Reads bundle2 part payload data into chunks.
1206 """Reads bundle2 part payload data into chunks.
1207
1207
1208 Part payload data consists of framed chunks. This function takes
1208 Part payload data consists of framed chunks. This function takes
1209 a file handle and emits those chunks.
1209 a file handle and emits those chunks.
1210 """
1210 """
1211 dolog = ui.configbool('devel', 'bundle2.debug')
1211 dolog = ui.configbool('devel', 'bundle2.debug')
1212 debug = ui.debug
1212 debug = ui.debug
1213
1213
1214 headerstruct = struct.Struct(_fpayloadsize)
1214 headerstruct = struct.Struct(_fpayloadsize)
1215 headersize = headerstruct.size
1215 headersize = headerstruct.size
1216 unpack = headerstruct.unpack
1216 unpack = headerstruct.unpack
1217
1217
1218 readexactly = changegroup.readexactly
1218 readexactly = changegroup.readexactly
1219 read = fh.read
1219 read = fh.read
1220
1220
1221 chunksize = unpack(readexactly(fh, headersize))[0]
1221 chunksize = unpack(readexactly(fh, headersize))[0]
1222 indebug(ui, 'payload chunk size: %i' % chunksize)
1222 indebug(ui, 'payload chunk size: %i' % chunksize)
1223
1223
1224 # changegroup.readexactly() is inlined below for performance.
1224 # changegroup.readexactly() is inlined below for performance.
1225 while chunksize:
1225 while chunksize:
1226 if chunksize >= 0:
1226 if chunksize >= 0:
1227 s = read(chunksize)
1227 s = read(chunksize)
1228 if len(s) < chunksize:
1228 if len(s) < chunksize:
1229 raise error.Abort(_('stream ended unexpectedly '
1229 raise error.Abort(_('stream ended unexpectedly '
1230 ' (got %d bytes, expected %d)') %
1230 ' (got %d bytes, expected %d)') %
1231 (len(s), chunksize))
1231 (len(s), chunksize))
1232
1232
1233 yield s
1233 yield s
1234 elif chunksize == flaginterrupt:
1234 elif chunksize == flaginterrupt:
1235 # Interrupt "signal" detected. The regular stream is interrupted
1235 # Interrupt "signal" detected. The regular stream is interrupted
1236 # and a bundle2 part follows. Consume it.
1236 # and a bundle2 part follows. Consume it.
1237 interrupthandler(ui, fh)()
1237 interrupthandler(ui, fh)()
1238 else:
1238 else:
1239 raise error.BundleValueError(
1239 raise error.BundleValueError(
1240 'negative payload chunk size: %s' % chunksize)
1240 'negative payload chunk size: %s' % chunksize)
1241
1241
1242 s = read(headersize)
1242 s = read(headersize)
1243 if len(s) < headersize:
1243 if len(s) < headersize:
1244 raise error.Abort(_('stream ended unexpectedly '
1244 raise error.Abort(_('stream ended unexpectedly '
1245 ' (got %d bytes, expected %d)') %
1245 ' (got %d bytes, expected %d)') %
1246 (len(s), chunksize))
1246 (len(s), chunksize))
1247
1247
1248 chunksize = unpack(s)[0]
1248 chunksize = unpack(s)[0]
1249
1249
1250 # indebug() inlined for performance.
1250 # indebug() inlined for performance.
1251 if dolog:
1251 if dolog:
1252 debug('bundle2-input: payload chunk size: %i\n' % chunksize)
1252 debug('bundle2-input: payload chunk size: %i\n' % chunksize)
1253
1253
1254 class unbundlepart(unpackermixin):
1254 class unbundlepart(unpackermixin):
1255 """a bundle part read from a bundle"""
1255 """a bundle part read from a bundle"""
1256
1256
1257 def __init__(self, ui, header, fp):
1257 def __init__(self, ui, header, fp):
1258 super(unbundlepart, self).__init__(fp)
1258 super(unbundlepart, self).__init__(fp)
1259 self._seekable = (util.safehasattr(fp, 'seek') and
1259 self._seekable = (util.safehasattr(fp, 'seek') and
1260 util.safehasattr(fp, 'tell'))
1260 util.safehasattr(fp, 'tell'))
1261 self.ui = ui
1261 self.ui = ui
1262 # unbundle state attr
1262 # unbundle state attr
1263 self._headerdata = header
1263 self._headerdata = header
1264 self._headeroffset = 0
1264 self._headeroffset = 0
1265 self._initialized = False
1265 self._initialized = False
1266 self.consumed = False
1266 self.consumed = False
1267 # part data
1267 # part data
1268 self.id = None
1268 self.id = None
1269 self.type = None
1269 self.type = None
1270 self.mandatoryparams = None
1270 self.mandatoryparams = None
1271 self.advisoryparams = None
1271 self.advisoryparams = None
1272 self.params = None
1272 self.params = None
1273 self.mandatorykeys = ()
1273 self.mandatorykeys = ()
1274 self._readheader()
1274 self._readheader()
1275 self._mandatory = None
1275 self._mandatory = None
1276 self._pos = 0
1276 self._pos = 0
1277
1277
1278 def _fromheader(self, size):
1278 def _fromheader(self, size):
1279 """return the next <size> byte from the header"""
1279 """return the next <size> byte from the header"""
1280 offset = self._headeroffset
1280 offset = self._headeroffset
1281 data = self._headerdata[offset:(offset + size)]
1281 data = self._headerdata[offset:(offset + size)]
1282 self._headeroffset = offset + size
1282 self._headeroffset = offset + size
1283 return data
1283 return data
1284
1284
1285 def _unpackheader(self, format):
1285 def _unpackheader(self, format):
1286 """read given format from header
1286 """read given format from header
1287
1287
1288 This automatically compute the size of the format to read."""
1288 This automatically compute the size of the format to read."""
1289 data = self._fromheader(struct.calcsize(format))
1289 data = self._fromheader(struct.calcsize(format))
1290 return _unpack(format, data)
1290 return _unpack(format, data)
1291
1291
1292 def _initparams(self, mandatoryparams, advisoryparams):
1292 def _initparams(self, mandatoryparams, advisoryparams):
1293 """internal function to setup all logic related parameters"""
1293 """internal function to setup all logic related parameters"""
1294 # make it read only to prevent people touching it by mistake.
1294 # make it read only to prevent people touching it by mistake.
1295 self.mandatoryparams = tuple(mandatoryparams)
1295 self.mandatoryparams = tuple(mandatoryparams)
1296 self.advisoryparams = tuple(advisoryparams)
1296 self.advisoryparams = tuple(advisoryparams)
1297 # user friendly UI
1297 # user friendly UI
1298 self.params = util.sortdict(self.mandatoryparams)
1298 self.params = util.sortdict(self.mandatoryparams)
1299 self.params.update(self.advisoryparams)
1299 self.params.update(self.advisoryparams)
1300 self.mandatorykeys = frozenset(p[0] for p in mandatoryparams)
1300 self.mandatorykeys = frozenset(p[0] for p in mandatoryparams)
1301
1301
1302 def _readheader(self):
1302 def _readheader(self):
1303 """read the header and setup the object"""
1303 """read the header and setup the object"""
1304 typesize = self._unpackheader(_fparttypesize)[0]
1304 typesize = self._unpackheader(_fparttypesize)[0]
1305 self.type = self._fromheader(typesize)
1305 self.type = self._fromheader(typesize)
1306 indebug(self.ui, 'part type: "%s"' % self.type)
1306 indebug(self.ui, 'part type: "%s"' % self.type)
1307 self.id = self._unpackheader(_fpartid)[0]
1307 self.id = self._unpackheader(_fpartid)[0]
1308 indebug(self.ui, 'part id: "%s"' % pycompat.bytestr(self.id))
1308 indebug(self.ui, 'part id: "%s"' % pycompat.bytestr(self.id))
1309 # extract mandatory bit from type
1309 # extract mandatory bit from type
1310 self.mandatory = (self.type != self.type.lower())
1310 self.mandatory = (self.type != self.type.lower())
1311 self.type = self.type.lower()
1311 self.type = self.type.lower()
1312 ## reading parameters
1312 ## reading parameters
1313 # param count
1313 # param count
1314 mancount, advcount = self._unpackheader(_fpartparamcount)
1314 mancount, advcount = self._unpackheader(_fpartparamcount)
1315 indebug(self.ui, 'part parameters: %i' % (mancount + advcount))
1315 indebug(self.ui, 'part parameters: %i' % (mancount + advcount))
1316 # param size
1316 # param size
1317 fparamsizes = _makefpartparamsizes(mancount + advcount)
1317 fparamsizes = _makefpartparamsizes(mancount + advcount)
1318 paramsizes = self._unpackheader(fparamsizes)
1318 paramsizes = self._unpackheader(fparamsizes)
1319 # make it a list of couple again
1319 # make it a list of couple again
1320 paramsizes = list(zip(paramsizes[::2], paramsizes[1::2]))
1320 paramsizes = list(zip(paramsizes[::2], paramsizes[1::2]))
1321 # split mandatory from advisory
1321 # split mandatory from advisory
1322 mansizes = paramsizes[:mancount]
1322 mansizes = paramsizes[:mancount]
1323 advsizes = paramsizes[mancount:]
1323 advsizes = paramsizes[mancount:]
1324 # retrieve param value
1324 # retrieve param value
1325 manparams = []
1325 manparams = []
1326 for key, value in mansizes:
1326 for key, value in mansizes:
1327 manparams.append((self._fromheader(key), self._fromheader(value)))
1327 manparams.append((self._fromheader(key), self._fromheader(value)))
1328 advparams = []
1328 advparams = []
1329 for key, value in advsizes:
1329 for key, value in advsizes:
1330 advparams.append((self._fromheader(key), self._fromheader(value)))
1330 advparams.append((self._fromheader(key), self._fromheader(value)))
1331 self._initparams(manparams, advparams)
1331 self._initparams(manparams, advparams)
1332 ## part payload
1332 ## part payload
1333 self._payloadstream = util.chunkbuffer(self._payloadchunks())
1333 self._payloadstream = util.chunkbuffer(self._payloadchunks())
1334 # we read the data, tell it
1334 # we read the data, tell it
1335 self._initialized = True
1335 self._initialized = True
1336
1336
1337 def _payloadchunks(self):
1337 def _payloadchunks(self):
1338 """Generator of decoded chunks in the payload."""
1338 """Generator of decoded chunks in the payload."""
1339 return decodepayloadchunks(self.ui, self._fp)
1339 return decodepayloadchunks(self.ui, self._fp)
1340
1340
1341 def consume(self):
1341 def consume(self):
1342 """Read the part payload until completion.
1342 """Read the part payload until completion.
1343
1343
1344 By consuming the part data, the underlying stream read offset will
1344 By consuming the part data, the underlying stream read offset will
1345 be advanced to the next part (or end of stream).
1345 be advanced to the next part (or end of stream).
1346 """
1346 """
1347 if self.consumed:
1347 if self.consumed:
1348 return
1348 return
1349
1349
1350 chunk = self.read(32768)
1350 chunk = self.read(32768)
1351 while chunk:
1351 while chunk:
1352 self._pos += len(chunk)
1352 self._pos += len(chunk)
1353 chunk = self.read(32768)
1353 chunk = self.read(32768)
1354
1354
1355 def read(self, size=None):
1355 def read(self, size=None):
1356 """read payload data"""
1356 """read payload data"""
1357 if not self._initialized:
1357 if not self._initialized:
1358 self._readheader()
1358 self._readheader()
1359 if size is None:
1359 if size is None:
1360 data = self._payloadstream.read()
1360 data = self._payloadstream.read()
1361 else:
1361 else:
1362 data = self._payloadstream.read(size)
1362 data = self._payloadstream.read(size)
1363 self._pos += len(data)
1363 self._pos += len(data)
1364 if size is None or len(data) < size:
1364 if size is None or len(data) < size:
1365 if not self.consumed and self._pos:
1365 if not self.consumed and self._pos:
1366 self.ui.debug('bundle2-input-part: total payload size %i\n'
1366 self.ui.debug('bundle2-input-part: total payload size %i\n'
1367 % self._pos)
1367 % self._pos)
1368 self.consumed = True
1368 self.consumed = True
1369 return data
1369 return data
1370
1370
1371 class seekableunbundlepart(unbundlepart):
1371 class seekableunbundlepart(unbundlepart):
1372 """A bundle2 part in a bundle that is seekable.
1372 """A bundle2 part in a bundle that is seekable.
1373
1373
1374 Regular ``unbundlepart`` instances can only be read once. This class
1374 Regular ``unbundlepart`` instances can only be read once. This class
1375 extends ``unbundlepart`` to enable bi-directional seeking within the
1375 extends ``unbundlepart`` to enable bi-directional seeking within the
1376 part.
1376 part.
1377
1377
1378 Bundle2 part data consists of framed chunks. Offsets when seeking
1378 Bundle2 part data consists of framed chunks. Offsets when seeking
1379 refer to the decoded data, not the offsets in the underlying bundle2
1379 refer to the decoded data, not the offsets in the underlying bundle2
1380 stream.
1380 stream.
1381
1381
1382 To facilitate quickly seeking within the decoded data, instances of this
1382 To facilitate quickly seeking within the decoded data, instances of this
1383 class maintain a mapping between offsets in the underlying stream and
1383 class maintain a mapping between offsets in the underlying stream and
1384 the decoded payload. This mapping will consume memory in proportion
1384 the decoded payload. This mapping will consume memory in proportion
1385 to the number of chunks within the payload (which almost certainly
1385 to the number of chunks within the payload (which almost certainly
1386 increases in proportion with the size of the part).
1386 increases in proportion with the size of the part).
1387 """
1387 """
1388 def __init__(self, ui, header, fp):
1388 def __init__(self, ui, header, fp):
1389 # (payload, file) offsets for chunk starts.
1389 # (payload, file) offsets for chunk starts.
1390 self._chunkindex = []
1390 self._chunkindex = []
1391
1391
1392 super(seekableunbundlepart, self).__init__(ui, header, fp)
1392 super(seekableunbundlepart, self).__init__(ui, header, fp)
1393
1393
1394 def _payloadchunks(self, chunknum=0):
1394 def _payloadchunks(self, chunknum=0):
1395 '''seek to specified chunk and start yielding data'''
1395 '''seek to specified chunk and start yielding data'''
1396 if len(self._chunkindex) == 0:
1396 if len(self._chunkindex) == 0:
1397 assert chunknum == 0, 'Must start with chunk 0'
1397 assert chunknum == 0, 'Must start with chunk 0'
1398 self._chunkindex.append((0, self._tellfp()))
1398 self._chunkindex.append((0, self._tellfp()))
1399 else:
1399 else:
1400 assert chunknum < len(self._chunkindex), \
1400 assert chunknum < len(self._chunkindex), \
1401 'Unknown chunk %d' % chunknum
1401 'Unknown chunk %d' % chunknum
1402 self._seekfp(self._chunkindex[chunknum][1])
1402 self._seekfp(self._chunkindex[chunknum][1])
1403
1403
1404 pos = self._chunkindex[chunknum][0]
1404 pos = self._chunkindex[chunknum][0]
1405
1405
1406 for chunk in decodepayloadchunks(self.ui, self._fp):
1406 for chunk in decodepayloadchunks(self.ui, self._fp):
1407 chunknum += 1
1407 chunknum += 1
1408 pos += len(chunk)
1408 pos += len(chunk)
1409 if chunknum == len(self._chunkindex):
1409 if chunknum == len(self._chunkindex):
1410 self._chunkindex.append((pos, self._tellfp()))
1410 self._chunkindex.append((pos, self._tellfp()))
1411
1411
1412 yield chunk
1412 yield chunk
1413
1413
1414 def _findchunk(self, pos):
1414 def _findchunk(self, pos):
1415 '''for a given payload position, return a chunk number and offset'''
1415 '''for a given payload position, return a chunk number and offset'''
1416 for chunk, (ppos, fpos) in enumerate(self._chunkindex):
1416 for chunk, (ppos, fpos) in enumerate(self._chunkindex):
1417 if ppos == pos:
1417 if ppos == pos:
1418 return chunk, 0
1418 return chunk, 0
1419 elif ppos > pos:
1419 elif ppos > pos:
1420 return chunk - 1, pos - self._chunkindex[chunk - 1][0]
1420 return chunk - 1, pos - self._chunkindex[chunk - 1][0]
1421 raise ValueError('Unknown chunk')
1421 raise ValueError('Unknown chunk')
1422
1422
1423 def tell(self):
1423 def tell(self):
1424 return self._pos
1424 return self._pos
1425
1425
1426 def seek(self, offset, whence=os.SEEK_SET):
1426 def seek(self, offset, whence=os.SEEK_SET):
1427 if whence == os.SEEK_SET:
1427 if whence == os.SEEK_SET:
1428 newpos = offset
1428 newpos = offset
1429 elif whence == os.SEEK_CUR:
1429 elif whence == os.SEEK_CUR:
1430 newpos = self._pos + offset
1430 newpos = self._pos + offset
1431 elif whence == os.SEEK_END:
1431 elif whence == os.SEEK_END:
1432 if not self.consumed:
1432 if not self.consumed:
1433 # Can't use self.consume() here because it advances self._pos.
1433 # Can't use self.consume() here because it advances self._pos.
1434 chunk = self.read(32768)
1434 chunk = self.read(32768)
1435 while chunk:
1435 while chunk:
1436 chunk = self.read(32768)
1436 chunk = self.read(32768)
1437 newpos = self._chunkindex[-1][0] - offset
1437 newpos = self._chunkindex[-1][0] - offset
1438 else:
1438 else:
1439 raise ValueError('Unknown whence value: %r' % (whence,))
1439 raise ValueError('Unknown whence value: %r' % (whence,))
1440
1440
1441 if newpos > self._chunkindex[-1][0] and not self.consumed:
1441 if newpos > self._chunkindex[-1][0] and not self.consumed:
1442 # Can't use self.consume() here because it advances self._pos.
1442 # Can't use self.consume() here because it advances self._pos.
1443 chunk = self.read(32768)
1443 chunk = self.read(32768)
1444 while chunk:
1444 while chunk:
1445 chunk = self.read(32668)
1445 chunk = self.read(32668)
1446
1446
1447 if not 0 <= newpos <= self._chunkindex[-1][0]:
1447 if not 0 <= newpos <= self._chunkindex[-1][0]:
1448 raise ValueError('Offset out of range')
1448 raise ValueError('Offset out of range')
1449
1449
1450 if self._pos != newpos:
1450 if self._pos != newpos:
1451 chunk, internaloffset = self._findchunk(newpos)
1451 chunk, internaloffset = self._findchunk(newpos)
1452 self._payloadstream = util.chunkbuffer(self._payloadchunks(chunk))
1452 self._payloadstream = util.chunkbuffer(self._payloadchunks(chunk))
1453 adjust = self.read(internaloffset)
1453 adjust = self.read(internaloffset)
1454 if len(adjust) != internaloffset:
1454 if len(adjust) != internaloffset:
1455 raise error.Abort(_('Seek failed\n'))
1455 raise error.Abort(_('Seek failed\n'))
1456 self._pos = newpos
1456 self._pos = newpos
1457
1457
1458 def _seekfp(self, offset, whence=0):
1458 def _seekfp(self, offset, whence=0):
1459 """move the underlying file pointer
1459 """move the underlying file pointer
1460
1460
1461 This method is meant for internal usage by the bundle2 protocol only.
1461 This method is meant for internal usage by the bundle2 protocol only.
1462 They directly manipulate the low level stream including bundle2 level
1462 They directly manipulate the low level stream including bundle2 level
1463 instruction.
1463 instruction.
1464
1464
1465 Do not use it to implement higher-level logic or methods."""
1465 Do not use it to implement higher-level logic or methods."""
1466 if self._seekable:
1466 if self._seekable:
1467 return self._fp.seek(offset, whence)
1467 return self._fp.seek(offset, whence)
1468 else:
1468 else:
1469 raise NotImplementedError(_('File pointer is not seekable'))
1469 raise NotImplementedError(_('File pointer is not seekable'))
1470
1470
1471 def _tellfp(self):
1471 def _tellfp(self):
1472 """return the file offset, or None if file is not seekable
1472 """return the file offset, or None if file is not seekable
1473
1473
1474 This method is meant for internal usage by the bundle2 protocol only.
1474 This method is meant for internal usage by the bundle2 protocol only.
1475 They directly manipulate the low level stream including bundle2 level
1475 They directly manipulate the low level stream including bundle2 level
1476 instruction.
1476 instruction.
1477
1477
1478 Do not use it to implement higher-level logic or methods."""
1478 Do not use it to implement higher-level logic or methods."""
1479 if self._seekable:
1479 if self._seekable:
1480 try:
1480 try:
1481 return self._fp.tell()
1481 return self._fp.tell()
1482 except IOError as e:
1482 except IOError as e:
1483 if e.errno == errno.ESPIPE:
1483 if e.errno == errno.ESPIPE:
1484 self._seekable = False
1484 self._seekable = False
1485 else:
1485 else:
1486 raise
1486 raise
1487 return None
1487 return None
1488
1488
1489 # These are only the static capabilities.
1489 # These are only the static capabilities.
1490 # Check the 'getrepocaps' function for the rest.
1490 # Check the 'getrepocaps' function for the rest.
1491 capabilities = {'HG20': (),
1491 capabilities = {'HG20': (),
1492 'bookmarks': (),
1492 'bookmarks': (),
1493 'error': ('abort', 'unsupportedcontent', 'pushraced',
1493 'error': ('abort', 'unsupportedcontent', 'pushraced',
1494 'pushkey'),
1494 'pushkey'),
1495 'listkeys': (),
1495 'listkeys': (),
1496 'pushkey': (),
1496 'pushkey': (),
1497 'digests': tuple(sorted(util.DIGESTS.keys())),
1497 'digests': tuple(sorted(util.DIGESTS.keys())),
1498 'remote-changegroup': ('http', 'https'),
1498 'remote-changegroup': ('http', 'https'),
1499 'hgtagsfnodes': (),
1499 'hgtagsfnodes': (),
1500 'rev-branch-cache': (),
1500 'rev-branch-cache': (),
1501 'phases': ('heads',),
1501 'phases': ('heads',),
1502 'stream': ('v2',),
1502 'stream': ('v2',),
1503 }
1503 }
1504
1504
1505 def getrepocaps(repo, allowpushback=False, role=None):
1505 def getrepocaps(repo, allowpushback=False, role=None):
1506 """return the bundle2 capabilities for a given repo
1506 """return the bundle2 capabilities for a given repo
1507
1507
1508 Exists to allow extensions (like evolution) to mutate the capabilities.
1508 Exists to allow extensions (like evolution) to mutate the capabilities.
1509
1509
1510 The returned value is used for servers advertising their capabilities as
1510 The returned value is used for servers advertising their capabilities as
1511 well as clients advertising their capabilities to servers as part of
1511 well as clients advertising their capabilities to servers as part of
1512 bundle2 requests. The ``role`` argument specifies which is which.
1512 bundle2 requests. The ``role`` argument specifies which is which.
1513 """
1513 """
1514 if role not in ('client', 'server'):
1514 if role not in ('client', 'server'):
1515 raise error.ProgrammingError('role argument must be client or server')
1515 raise error.ProgrammingError('role argument must be client or server')
1516
1516
1517 caps = capabilities.copy()
1517 caps = capabilities.copy()
1518 caps['changegroup'] = tuple(sorted(
1518 caps['changegroup'] = tuple(sorted(
1519 changegroup.supportedincomingversions(repo)))
1519 changegroup.supportedincomingversions(repo)))
1520 if obsolete.isenabled(repo, obsolete.exchangeopt):
1520 if obsolete.isenabled(repo, obsolete.exchangeopt):
1521 supportedformat = tuple('V%i' % v for v in obsolete.formats)
1521 supportedformat = tuple('V%i' % v for v in obsolete.formats)
1522 caps['obsmarkers'] = supportedformat
1522 caps['obsmarkers'] = supportedformat
1523 if allowpushback:
1523 if allowpushback:
1524 caps['pushback'] = ()
1524 caps['pushback'] = ()
1525 cpmode = repo.ui.config('server', 'concurrent-push-mode')
1525 cpmode = repo.ui.config('server', 'concurrent-push-mode')
1526 if cpmode == 'check-related':
1526 if cpmode == 'check-related':
1527 caps['checkheads'] = ('related',)
1527 caps['checkheads'] = ('related',)
1528 if 'phases' in repo.ui.configlist('devel', 'legacy.exchange'):
1528 if 'phases' in repo.ui.configlist('devel', 'legacy.exchange'):
1529 caps.pop('phases')
1529 caps.pop('phases')
1530
1530
1531 # Don't advertise stream clone support in server mode if not configured.
1531 # Don't advertise stream clone support in server mode if not configured.
1532 if role == 'server':
1532 if role == 'server':
1533 streamsupported = repo.ui.configbool('server', 'uncompressed',
1533 streamsupported = repo.ui.configbool('server', 'uncompressed',
1534 untrusted=True)
1534 untrusted=True)
1535 featuresupported = repo.ui.configbool('experimental', 'bundle2.stream')
1535 featuresupported = repo.ui.configbool('server', 'bundle2.stream')
1536
1536
1537 if not streamsupported or not featuresupported:
1537 if not streamsupported or not featuresupported:
1538 caps.pop('stream')
1538 caps.pop('stream')
1539 # Else always advertise support on client, because payload support
1539 # Else always advertise support on client, because payload support
1540 # should always be advertised.
1540 # should always be advertised.
1541
1541
1542 return caps
1542 return caps
1543
1543
1544 def bundle2caps(remote):
1544 def bundle2caps(remote):
1545 """return the bundle capabilities of a peer as dict"""
1545 """return the bundle capabilities of a peer as dict"""
1546 raw = remote.capable('bundle2')
1546 raw = remote.capable('bundle2')
1547 if not raw and raw != '':
1547 if not raw and raw != '':
1548 return {}
1548 return {}
1549 capsblob = urlreq.unquote(remote.capable('bundle2'))
1549 capsblob = urlreq.unquote(remote.capable('bundle2'))
1550 return decodecaps(capsblob)
1550 return decodecaps(capsblob)
1551
1551
1552 def obsmarkersversion(caps):
1552 def obsmarkersversion(caps):
1553 """extract the list of supported obsmarkers versions from a bundle2caps dict
1553 """extract the list of supported obsmarkers versions from a bundle2caps dict
1554 """
1554 """
1555 obscaps = caps.get('obsmarkers', ())
1555 obscaps = caps.get('obsmarkers', ())
1556 return [int(c[1:]) for c in obscaps if c.startswith('V')]
1556 return [int(c[1:]) for c in obscaps if c.startswith('V')]
1557
1557
1558 def writenewbundle(ui, repo, source, filename, bundletype, outgoing, opts,
1558 def writenewbundle(ui, repo, source, filename, bundletype, outgoing, opts,
1559 vfs=None, compression=None, compopts=None):
1559 vfs=None, compression=None, compopts=None):
1560 if bundletype.startswith('HG10'):
1560 if bundletype.startswith('HG10'):
1561 cg = changegroup.makechangegroup(repo, outgoing, '01', source)
1561 cg = changegroup.makechangegroup(repo, outgoing, '01', source)
1562 return writebundle(ui, cg, filename, bundletype, vfs=vfs,
1562 return writebundle(ui, cg, filename, bundletype, vfs=vfs,
1563 compression=compression, compopts=compopts)
1563 compression=compression, compopts=compopts)
1564 elif not bundletype.startswith('HG20'):
1564 elif not bundletype.startswith('HG20'):
1565 raise error.ProgrammingError('unknown bundle type: %s' % bundletype)
1565 raise error.ProgrammingError('unknown bundle type: %s' % bundletype)
1566
1566
1567 caps = {}
1567 caps = {}
1568 if 'obsolescence' in opts:
1568 if 'obsolescence' in opts:
1569 caps['obsmarkers'] = ('V1',)
1569 caps['obsmarkers'] = ('V1',)
1570 bundle = bundle20(ui, caps)
1570 bundle = bundle20(ui, caps)
1571 bundle.setcompression(compression, compopts)
1571 bundle.setcompression(compression, compopts)
1572 _addpartsfromopts(ui, repo, bundle, source, outgoing, opts)
1572 _addpartsfromopts(ui, repo, bundle, source, outgoing, opts)
1573 chunkiter = bundle.getchunks()
1573 chunkiter = bundle.getchunks()
1574
1574
1575 return changegroup.writechunks(ui, chunkiter, filename, vfs=vfs)
1575 return changegroup.writechunks(ui, chunkiter, filename, vfs=vfs)
1576
1576
1577 def _addpartsfromopts(ui, repo, bundler, source, outgoing, opts):
1577 def _addpartsfromopts(ui, repo, bundler, source, outgoing, opts):
1578 # We should eventually reconcile this logic with the one behind
1578 # We should eventually reconcile this logic with the one behind
1579 # 'exchange.getbundle2partsgenerator'.
1579 # 'exchange.getbundle2partsgenerator'.
1580 #
1580 #
1581 # The type of input from 'getbundle' and 'writenewbundle' are a bit
1581 # The type of input from 'getbundle' and 'writenewbundle' are a bit
1582 # different right now. So we keep them separated for now for the sake of
1582 # different right now. So we keep them separated for now for the sake of
1583 # simplicity.
1583 # simplicity.
1584
1584
1585 # we might not always want a changegroup in such bundle, for example in
1585 # we might not always want a changegroup in such bundle, for example in
1586 # stream bundles
1586 # stream bundles
1587 if opts.get('changegroup', True):
1587 if opts.get('changegroup', True):
1588 cgversion = opts.get('cg.version')
1588 cgversion = opts.get('cg.version')
1589 if cgversion is None:
1589 if cgversion is None:
1590 cgversion = changegroup.safeversion(repo)
1590 cgversion = changegroup.safeversion(repo)
1591 cg = changegroup.makechangegroup(repo, outgoing, cgversion, source)
1591 cg = changegroup.makechangegroup(repo, outgoing, cgversion, source)
1592 part = bundler.newpart('changegroup', data=cg.getchunks())
1592 part = bundler.newpart('changegroup', data=cg.getchunks())
1593 part.addparam('version', cg.version)
1593 part.addparam('version', cg.version)
1594 if 'clcount' in cg.extras:
1594 if 'clcount' in cg.extras:
1595 part.addparam('nbchanges', '%d' % cg.extras['clcount'],
1595 part.addparam('nbchanges', '%d' % cg.extras['clcount'],
1596 mandatory=False)
1596 mandatory=False)
1597 if opts.get('phases') and repo.revs('%ln and secret()',
1597 if opts.get('phases') and repo.revs('%ln and secret()',
1598 outgoing.missingheads):
1598 outgoing.missingheads):
1599 part.addparam('targetphase', '%d' % phases.secret, mandatory=False)
1599 part.addparam('targetphase', '%d' % phases.secret, mandatory=False)
1600
1600
1601 if opts.get('streamv2', False):
1601 if opts.get('streamv2', False):
1602 addpartbundlestream2(bundler, repo, stream=True)
1602 addpartbundlestream2(bundler, repo, stream=True)
1603
1603
1604 if opts.get('tagsfnodescache', True):
1604 if opts.get('tagsfnodescache', True):
1605 addparttagsfnodescache(repo, bundler, outgoing)
1605 addparttagsfnodescache(repo, bundler, outgoing)
1606
1606
1607 if opts.get('revbranchcache', True):
1607 if opts.get('revbranchcache', True):
1608 addpartrevbranchcache(repo, bundler, outgoing)
1608 addpartrevbranchcache(repo, bundler, outgoing)
1609
1609
1610 if opts.get('obsolescence', False):
1610 if opts.get('obsolescence', False):
1611 obsmarkers = repo.obsstore.relevantmarkers(outgoing.missing)
1611 obsmarkers = repo.obsstore.relevantmarkers(outgoing.missing)
1612 buildobsmarkerspart(bundler, obsmarkers)
1612 buildobsmarkerspart(bundler, obsmarkers)
1613
1613
1614 if opts.get('phases', False):
1614 if opts.get('phases', False):
1615 headsbyphase = phases.subsetphaseheads(repo, outgoing.missing)
1615 headsbyphase = phases.subsetphaseheads(repo, outgoing.missing)
1616 phasedata = phases.binaryencode(headsbyphase)
1616 phasedata = phases.binaryencode(headsbyphase)
1617 bundler.newpart('phase-heads', data=phasedata)
1617 bundler.newpart('phase-heads', data=phasedata)
1618
1618
1619 def addparttagsfnodescache(repo, bundler, outgoing):
1619 def addparttagsfnodescache(repo, bundler, outgoing):
1620 # we include the tags fnode cache for the bundle changeset
1620 # we include the tags fnode cache for the bundle changeset
1621 # (as an optional parts)
1621 # (as an optional parts)
1622 cache = tags.hgtagsfnodescache(repo.unfiltered())
1622 cache = tags.hgtagsfnodescache(repo.unfiltered())
1623 chunks = []
1623 chunks = []
1624
1624
1625 # .hgtags fnodes are only relevant for head changesets. While we could
1625 # .hgtags fnodes are only relevant for head changesets. While we could
1626 # transfer values for all known nodes, there will likely be little to
1626 # transfer values for all known nodes, there will likely be little to
1627 # no benefit.
1627 # no benefit.
1628 #
1628 #
1629 # We don't bother using a generator to produce output data because
1629 # We don't bother using a generator to produce output data because
1630 # a) we only have 40 bytes per head and even esoteric numbers of heads
1630 # a) we only have 40 bytes per head and even esoteric numbers of heads
1631 # consume little memory (1M heads is 40MB) b) we don't want to send the
1631 # consume little memory (1M heads is 40MB) b) we don't want to send the
1632 # part if we don't have entries and knowing if we have entries requires
1632 # part if we don't have entries and knowing if we have entries requires
1633 # cache lookups.
1633 # cache lookups.
1634 for node in outgoing.missingheads:
1634 for node in outgoing.missingheads:
1635 # Don't compute missing, as this may slow down serving.
1635 # Don't compute missing, as this may slow down serving.
1636 fnode = cache.getfnode(node, computemissing=False)
1636 fnode = cache.getfnode(node, computemissing=False)
1637 if fnode is not None:
1637 if fnode is not None:
1638 chunks.extend([node, fnode])
1638 chunks.extend([node, fnode])
1639
1639
1640 if chunks:
1640 if chunks:
1641 bundler.newpart('hgtagsfnodes', data=''.join(chunks))
1641 bundler.newpart('hgtagsfnodes', data=''.join(chunks))
1642
1642
1643 def addpartrevbranchcache(repo, bundler, outgoing):
1643 def addpartrevbranchcache(repo, bundler, outgoing):
1644 # we include the rev branch cache for the bundle changeset
1644 # we include the rev branch cache for the bundle changeset
1645 # (as an optional parts)
1645 # (as an optional parts)
1646 cache = repo.revbranchcache()
1646 cache = repo.revbranchcache()
1647 cl = repo.unfiltered().changelog
1647 cl = repo.unfiltered().changelog
1648 branchesdata = collections.defaultdict(lambda: (set(), set()))
1648 branchesdata = collections.defaultdict(lambda: (set(), set()))
1649 for node in outgoing.missing:
1649 for node in outgoing.missing:
1650 branch, close = cache.branchinfo(cl.rev(node))
1650 branch, close = cache.branchinfo(cl.rev(node))
1651 branchesdata[branch][close].add(node)
1651 branchesdata[branch][close].add(node)
1652
1652
1653 def generate():
1653 def generate():
1654 for branch, (nodes, closed) in sorted(branchesdata.items()):
1654 for branch, (nodes, closed) in sorted(branchesdata.items()):
1655 utf8branch = encoding.fromlocal(branch)
1655 utf8branch = encoding.fromlocal(branch)
1656 yield rbcstruct.pack(len(utf8branch), len(nodes), len(closed))
1656 yield rbcstruct.pack(len(utf8branch), len(nodes), len(closed))
1657 yield utf8branch
1657 yield utf8branch
1658 for n in sorted(nodes):
1658 for n in sorted(nodes):
1659 yield n
1659 yield n
1660 for n in sorted(closed):
1660 for n in sorted(closed):
1661 yield n
1661 yield n
1662
1662
1663 bundler.newpart('cache:rev-branch-cache', data=generate(),
1663 bundler.newpart('cache:rev-branch-cache', data=generate(),
1664 mandatory=False)
1664 mandatory=False)
1665
1665
1666 def _formatrequirementsspec(requirements):
1666 def _formatrequirementsspec(requirements):
1667 return urlreq.quote(','.join(sorted(requirements)))
1667 return urlreq.quote(','.join(sorted(requirements)))
1668
1668
1669 def _formatrequirementsparams(requirements):
1669 def _formatrequirementsparams(requirements):
1670 requirements = _formatrequirementsspec(requirements)
1670 requirements = _formatrequirementsspec(requirements)
1671 params = "%s%s" % (urlreq.quote("requirements="), requirements)
1671 params = "%s%s" % (urlreq.quote("requirements="), requirements)
1672 return params
1672 return params
1673
1673
1674 def addpartbundlestream2(bundler, repo, **kwargs):
1674 def addpartbundlestream2(bundler, repo, **kwargs):
1675 if not kwargs.get('stream', False):
1675 if not kwargs.get('stream', False):
1676 return
1676 return
1677
1677
1678 if not streamclone.allowservergeneration(repo):
1678 if not streamclone.allowservergeneration(repo):
1679 raise error.Abort(_('stream data requested but server does not allow '
1679 raise error.Abort(_('stream data requested but server does not allow '
1680 'this feature'),
1680 'this feature'),
1681 hint=_('well-behaved clients should not be '
1681 hint=_('well-behaved clients should not be '
1682 'requesting stream data from servers not '
1682 'requesting stream data from servers not '
1683 'advertising it; the client may be buggy'))
1683 'advertising it; the client may be buggy'))
1684
1684
1685 # Stream clones don't compress well. And compression undermines a
1685 # Stream clones don't compress well. And compression undermines a
1686 # goal of stream clones, which is to be fast. Communicate the desire
1686 # goal of stream clones, which is to be fast. Communicate the desire
1687 # to avoid compression to consumers of the bundle.
1687 # to avoid compression to consumers of the bundle.
1688 bundler.prefercompressed = False
1688 bundler.prefercompressed = False
1689
1689
1690 filecount, bytecount, it = streamclone.generatev2(repo)
1690 filecount, bytecount, it = streamclone.generatev2(repo)
1691 requirements = _formatrequirementsspec(repo.requirements)
1691 requirements = _formatrequirementsspec(repo.requirements)
1692 part = bundler.newpart('stream2', data=it)
1692 part = bundler.newpart('stream2', data=it)
1693 part.addparam('bytecount', '%d' % bytecount, mandatory=True)
1693 part.addparam('bytecount', '%d' % bytecount, mandatory=True)
1694 part.addparam('filecount', '%d' % filecount, mandatory=True)
1694 part.addparam('filecount', '%d' % filecount, mandatory=True)
1695 part.addparam('requirements', requirements, mandatory=True)
1695 part.addparam('requirements', requirements, mandatory=True)
1696
1696
1697 def buildobsmarkerspart(bundler, markers):
1697 def buildobsmarkerspart(bundler, markers):
1698 """add an obsmarker part to the bundler with <markers>
1698 """add an obsmarker part to the bundler with <markers>
1699
1699
1700 No part is created if markers is empty.
1700 No part is created if markers is empty.
1701 Raises ValueError if the bundler doesn't support any known obsmarker format.
1701 Raises ValueError if the bundler doesn't support any known obsmarker format.
1702 """
1702 """
1703 if not markers:
1703 if not markers:
1704 return None
1704 return None
1705
1705
1706 remoteversions = obsmarkersversion(bundler.capabilities)
1706 remoteversions = obsmarkersversion(bundler.capabilities)
1707 version = obsolete.commonversion(remoteversions)
1707 version = obsolete.commonversion(remoteversions)
1708 if version is None:
1708 if version is None:
1709 raise ValueError('bundler does not support common obsmarker format')
1709 raise ValueError('bundler does not support common obsmarker format')
1710 stream = obsolete.encodemarkers(markers, True, version=version)
1710 stream = obsolete.encodemarkers(markers, True, version=version)
1711 return bundler.newpart('obsmarkers', data=stream)
1711 return bundler.newpart('obsmarkers', data=stream)
1712
1712
1713 def writebundle(ui, cg, filename, bundletype, vfs=None, compression=None,
1713 def writebundle(ui, cg, filename, bundletype, vfs=None, compression=None,
1714 compopts=None):
1714 compopts=None):
1715 """Write a bundle file and return its filename.
1715 """Write a bundle file and return its filename.
1716
1716
1717 Existing files will not be overwritten.
1717 Existing files will not be overwritten.
1718 If no filename is specified, a temporary file is created.
1718 If no filename is specified, a temporary file is created.
1719 bz2 compression can be turned off.
1719 bz2 compression can be turned off.
1720 The bundle file will be deleted in case of errors.
1720 The bundle file will be deleted in case of errors.
1721 """
1721 """
1722
1722
1723 if bundletype == "HG20":
1723 if bundletype == "HG20":
1724 bundle = bundle20(ui)
1724 bundle = bundle20(ui)
1725 bundle.setcompression(compression, compopts)
1725 bundle.setcompression(compression, compopts)
1726 part = bundle.newpart('changegroup', data=cg.getchunks())
1726 part = bundle.newpart('changegroup', data=cg.getchunks())
1727 part.addparam('version', cg.version)
1727 part.addparam('version', cg.version)
1728 if 'clcount' in cg.extras:
1728 if 'clcount' in cg.extras:
1729 part.addparam('nbchanges', '%d' % cg.extras['clcount'],
1729 part.addparam('nbchanges', '%d' % cg.extras['clcount'],
1730 mandatory=False)
1730 mandatory=False)
1731 chunkiter = bundle.getchunks()
1731 chunkiter = bundle.getchunks()
1732 else:
1732 else:
1733 # compression argument is only for the bundle2 case
1733 # compression argument is only for the bundle2 case
1734 assert compression is None
1734 assert compression is None
1735 if cg.version != '01':
1735 if cg.version != '01':
1736 raise error.Abort(_('old bundle types only supports v1 '
1736 raise error.Abort(_('old bundle types only supports v1 '
1737 'changegroups'))
1737 'changegroups'))
1738 header, comp = bundletypes[bundletype]
1738 header, comp = bundletypes[bundletype]
1739 if comp not in util.compengines.supportedbundletypes:
1739 if comp not in util.compengines.supportedbundletypes:
1740 raise error.Abort(_('unknown stream compression type: %s')
1740 raise error.Abort(_('unknown stream compression type: %s')
1741 % comp)
1741 % comp)
1742 compengine = util.compengines.forbundletype(comp)
1742 compengine = util.compengines.forbundletype(comp)
1743 def chunkiter():
1743 def chunkiter():
1744 yield header
1744 yield header
1745 for chunk in compengine.compressstream(cg.getchunks(), compopts):
1745 for chunk in compengine.compressstream(cg.getchunks(), compopts):
1746 yield chunk
1746 yield chunk
1747 chunkiter = chunkiter()
1747 chunkiter = chunkiter()
1748
1748
1749 # parse the changegroup data, otherwise we will block
1749 # parse the changegroup data, otherwise we will block
1750 # in case of sshrepo because we don't know the end of the stream
1750 # in case of sshrepo because we don't know the end of the stream
1751 return changegroup.writechunks(ui, chunkiter, filename, vfs=vfs)
1751 return changegroup.writechunks(ui, chunkiter, filename, vfs=vfs)
1752
1752
1753 def combinechangegroupresults(op):
1753 def combinechangegroupresults(op):
1754 """logic to combine 0 or more addchangegroup results into one"""
1754 """logic to combine 0 or more addchangegroup results into one"""
1755 results = [r.get('return', 0)
1755 results = [r.get('return', 0)
1756 for r in op.records['changegroup']]
1756 for r in op.records['changegroup']]
1757 changedheads = 0
1757 changedheads = 0
1758 result = 1
1758 result = 1
1759 for ret in results:
1759 for ret in results:
1760 # If any changegroup result is 0, return 0
1760 # If any changegroup result is 0, return 0
1761 if ret == 0:
1761 if ret == 0:
1762 result = 0
1762 result = 0
1763 break
1763 break
1764 if ret < -1:
1764 if ret < -1:
1765 changedheads += ret + 1
1765 changedheads += ret + 1
1766 elif ret > 1:
1766 elif ret > 1:
1767 changedheads += ret - 1
1767 changedheads += ret - 1
1768 if changedheads > 0:
1768 if changedheads > 0:
1769 result = 1 + changedheads
1769 result = 1 + changedheads
1770 elif changedheads < 0:
1770 elif changedheads < 0:
1771 result = -1 + changedheads
1771 result = -1 + changedheads
1772 return result
1772 return result
1773
1773
1774 @parthandler('changegroup', ('version', 'nbchanges', 'treemanifest',
1774 @parthandler('changegroup', ('version', 'nbchanges', 'treemanifest',
1775 'targetphase'))
1775 'targetphase'))
1776 def handlechangegroup(op, inpart):
1776 def handlechangegroup(op, inpart):
1777 """apply a changegroup part on the repo
1777 """apply a changegroup part on the repo
1778
1778
1779 This is a very early implementation that will massive rework before being
1779 This is a very early implementation that will massive rework before being
1780 inflicted to any end-user.
1780 inflicted to any end-user.
1781 """
1781 """
1782 from . import localrepo
1782 from . import localrepo
1783
1783
1784 tr = op.gettransaction()
1784 tr = op.gettransaction()
1785 unpackerversion = inpart.params.get('version', '01')
1785 unpackerversion = inpart.params.get('version', '01')
1786 # We should raise an appropriate exception here
1786 # We should raise an appropriate exception here
1787 cg = changegroup.getunbundler(unpackerversion, inpart, None)
1787 cg = changegroup.getunbundler(unpackerversion, inpart, None)
1788 # the source and url passed here are overwritten by the one contained in
1788 # the source and url passed here are overwritten by the one contained in
1789 # the transaction.hookargs argument. So 'bundle2' is a placeholder
1789 # the transaction.hookargs argument. So 'bundle2' is a placeholder
1790 nbchangesets = None
1790 nbchangesets = None
1791 if 'nbchanges' in inpart.params:
1791 if 'nbchanges' in inpart.params:
1792 nbchangesets = int(inpart.params.get('nbchanges'))
1792 nbchangesets = int(inpart.params.get('nbchanges'))
1793 if ('treemanifest' in inpart.params and
1793 if ('treemanifest' in inpart.params and
1794 'treemanifest' not in op.repo.requirements):
1794 'treemanifest' not in op.repo.requirements):
1795 if len(op.repo.changelog) != 0:
1795 if len(op.repo.changelog) != 0:
1796 raise error.Abort(_(
1796 raise error.Abort(_(
1797 "bundle contains tree manifests, but local repo is "
1797 "bundle contains tree manifests, but local repo is "
1798 "non-empty and does not use tree manifests"))
1798 "non-empty and does not use tree manifests"))
1799 op.repo.requirements.add('treemanifest')
1799 op.repo.requirements.add('treemanifest')
1800 op.repo.svfs.options = localrepo.resolvestorevfsoptions(
1800 op.repo.svfs.options = localrepo.resolvestorevfsoptions(
1801 op.repo.ui, op.repo.requirements)
1801 op.repo.ui, op.repo.requirements)
1802 op.repo._writerequirements()
1802 op.repo._writerequirements()
1803 extrakwargs = {}
1803 extrakwargs = {}
1804 targetphase = inpart.params.get('targetphase')
1804 targetphase = inpart.params.get('targetphase')
1805 if targetphase is not None:
1805 if targetphase is not None:
1806 extrakwargs[r'targetphase'] = int(targetphase)
1806 extrakwargs[r'targetphase'] = int(targetphase)
1807 ret = _processchangegroup(op, cg, tr, 'bundle2', 'bundle2',
1807 ret = _processchangegroup(op, cg, tr, 'bundle2', 'bundle2',
1808 expectedtotal=nbchangesets, **extrakwargs)
1808 expectedtotal=nbchangesets, **extrakwargs)
1809 if op.reply is not None:
1809 if op.reply is not None:
1810 # This is definitely not the final form of this
1810 # This is definitely not the final form of this
1811 # return. But one need to start somewhere.
1811 # return. But one need to start somewhere.
1812 part = op.reply.newpart('reply:changegroup', mandatory=False)
1812 part = op.reply.newpart('reply:changegroup', mandatory=False)
1813 part.addparam(
1813 part.addparam(
1814 'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False)
1814 'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False)
1815 part.addparam('return', '%i' % ret, mandatory=False)
1815 part.addparam('return', '%i' % ret, mandatory=False)
1816 assert not inpart.read()
1816 assert not inpart.read()
1817
1817
1818 _remotechangegroupparams = tuple(['url', 'size', 'digests'] +
1818 _remotechangegroupparams = tuple(['url', 'size', 'digests'] +
1819 ['digest:%s' % k for k in util.DIGESTS.keys()])
1819 ['digest:%s' % k for k in util.DIGESTS.keys()])
1820 @parthandler('remote-changegroup', _remotechangegroupparams)
1820 @parthandler('remote-changegroup', _remotechangegroupparams)
1821 def handleremotechangegroup(op, inpart):
1821 def handleremotechangegroup(op, inpart):
1822 """apply a bundle10 on the repo, given an url and validation information
1822 """apply a bundle10 on the repo, given an url and validation information
1823
1823
1824 All the information about the remote bundle to import are given as
1824 All the information about the remote bundle to import are given as
1825 parameters. The parameters include:
1825 parameters. The parameters include:
1826 - url: the url to the bundle10.
1826 - url: the url to the bundle10.
1827 - size: the bundle10 file size. It is used to validate what was
1827 - size: the bundle10 file size. It is used to validate what was
1828 retrieved by the client matches the server knowledge about the bundle.
1828 retrieved by the client matches the server knowledge about the bundle.
1829 - digests: a space separated list of the digest types provided as
1829 - digests: a space separated list of the digest types provided as
1830 parameters.
1830 parameters.
1831 - digest:<digest-type>: the hexadecimal representation of the digest with
1831 - digest:<digest-type>: the hexadecimal representation of the digest with
1832 that name. Like the size, it is used to validate what was retrieved by
1832 that name. Like the size, it is used to validate what was retrieved by
1833 the client matches what the server knows about the bundle.
1833 the client matches what the server knows about the bundle.
1834
1834
1835 When multiple digest types are given, all of them are checked.
1835 When multiple digest types are given, all of them are checked.
1836 """
1836 """
1837 try:
1837 try:
1838 raw_url = inpart.params['url']
1838 raw_url = inpart.params['url']
1839 except KeyError:
1839 except KeyError:
1840 raise error.Abort(_('remote-changegroup: missing "%s" param') % 'url')
1840 raise error.Abort(_('remote-changegroup: missing "%s" param') % 'url')
1841 parsed_url = util.url(raw_url)
1841 parsed_url = util.url(raw_url)
1842 if parsed_url.scheme not in capabilities['remote-changegroup']:
1842 if parsed_url.scheme not in capabilities['remote-changegroup']:
1843 raise error.Abort(_('remote-changegroup does not support %s urls') %
1843 raise error.Abort(_('remote-changegroup does not support %s urls') %
1844 parsed_url.scheme)
1844 parsed_url.scheme)
1845
1845
1846 try:
1846 try:
1847 size = int(inpart.params['size'])
1847 size = int(inpart.params['size'])
1848 except ValueError:
1848 except ValueError:
1849 raise error.Abort(_('remote-changegroup: invalid value for param "%s"')
1849 raise error.Abort(_('remote-changegroup: invalid value for param "%s"')
1850 % 'size')
1850 % 'size')
1851 except KeyError:
1851 except KeyError:
1852 raise error.Abort(_('remote-changegroup: missing "%s" param') % 'size')
1852 raise error.Abort(_('remote-changegroup: missing "%s" param') % 'size')
1853
1853
1854 digests = {}
1854 digests = {}
1855 for typ in inpart.params.get('digests', '').split():
1855 for typ in inpart.params.get('digests', '').split():
1856 param = 'digest:%s' % typ
1856 param = 'digest:%s' % typ
1857 try:
1857 try:
1858 value = inpart.params[param]
1858 value = inpart.params[param]
1859 except KeyError:
1859 except KeyError:
1860 raise error.Abort(_('remote-changegroup: missing "%s" param') %
1860 raise error.Abort(_('remote-changegroup: missing "%s" param') %
1861 param)
1861 param)
1862 digests[typ] = value
1862 digests[typ] = value
1863
1863
1864 real_part = util.digestchecker(url.open(op.ui, raw_url), size, digests)
1864 real_part = util.digestchecker(url.open(op.ui, raw_url), size, digests)
1865
1865
1866 tr = op.gettransaction()
1866 tr = op.gettransaction()
1867 from . import exchange
1867 from . import exchange
1868 cg = exchange.readbundle(op.repo.ui, real_part, raw_url)
1868 cg = exchange.readbundle(op.repo.ui, real_part, raw_url)
1869 if not isinstance(cg, changegroup.cg1unpacker):
1869 if not isinstance(cg, changegroup.cg1unpacker):
1870 raise error.Abort(_('%s: not a bundle version 1.0') %
1870 raise error.Abort(_('%s: not a bundle version 1.0') %
1871 util.hidepassword(raw_url))
1871 util.hidepassword(raw_url))
1872 ret = _processchangegroup(op, cg, tr, 'bundle2', 'bundle2')
1872 ret = _processchangegroup(op, cg, tr, 'bundle2', 'bundle2')
1873 if op.reply is not None:
1873 if op.reply is not None:
1874 # This is definitely not the final form of this
1874 # This is definitely not the final form of this
1875 # return. But one need to start somewhere.
1875 # return. But one need to start somewhere.
1876 part = op.reply.newpart('reply:changegroup')
1876 part = op.reply.newpart('reply:changegroup')
1877 part.addparam(
1877 part.addparam(
1878 'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False)
1878 'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False)
1879 part.addparam('return', '%i' % ret, mandatory=False)
1879 part.addparam('return', '%i' % ret, mandatory=False)
1880 try:
1880 try:
1881 real_part.validate()
1881 real_part.validate()
1882 except error.Abort as e:
1882 except error.Abort as e:
1883 raise error.Abort(_('bundle at %s is corrupted:\n%s') %
1883 raise error.Abort(_('bundle at %s is corrupted:\n%s') %
1884 (util.hidepassword(raw_url), bytes(e)))
1884 (util.hidepassword(raw_url), bytes(e)))
1885 assert not inpart.read()
1885 assert not inpart.read()
1886
1886
1887 @parthandler('reply:changegroup', ('return', 'in-reply-to'))
1887 @parthandler('reply:changegroup', ('return', 'in-reply-to'))
1888 def handlereplychangegroup(op, inpart):
1888 def handlereplychangegroup(op, inpart):
1889 ret = int(inpart.params['return'])
1889 ret = int(inpart.params['return'])
1890 replyto = int(inpart.params['in-reply-to'])
1890 replyto = int(inpart.params['in-reply-to'])
1891 op.records.add('changegroup', {'return': ret}, replyto)
1891 op.records.add('changegroup', {'return': ret}, replyto)
1892
1892
1893 @parthandler('check:bookmarks')
1893 @parthandler('check:bookmarks')
1894 def handlecheckbookmarks(op, inpart):
1894 def handlecheckbookmarks(op, inpart):
1895 """check location of bookmarks
1895 """check location of bookmarks
1896
1896
1897 This part is to be used to detect push race regarding bookmark, it
1897 This part is to be used to detect push race regarding bookmark, it
1898 contains binary encoded (bookmark, node) tuple. If the local state does
1898 contains binary encoded (bookmark, node) tuple. If the local state does
1899 not marks the one in the part, a PushRaced exception is raised
1899 not marks the one in the part, a PushRaced exception is raised
1900 """
1900 """
1901 bookdata = bookmarks.binarydecode(inpart)
1901 bookdata = bookmarks.binarydecode(inpart)
1902
1902
1903 msgstandard = ('repository changed while pushing - please try again '
1903 msgstandard = ('repository changed while pushing - please try again '
1904 '(bookmark "%s" move from %s to %s)')
1904 '(bookmark "%s" move from %s to %s)')
1905 msgmissing = ('repository changed while pushing - please try again '
1905 msgmissing = ('repository changed while pushing - please try again '
1906 '(bookmark "%s" is missing, expected %s)')
1906 '(bookmark "%s" is missing, expected %s)')
1907 msgexist = ('repository changed while pushing - please try again '
1907 msgexist = ('repository changed while pushing - please try again '
1908 '(bookmark "%s" set on %s, expected missing)')
1908 '(bookmark "%s" set on %s, expected missing)')
1909 for book, node in bookdata:
1909 for book, node in bookdata:
1910 currentnode = op.repo._bookmarks.get(book)
1910 currentnode = op.repo._bookmarks.get(book)
1911 if currentnode != node:
1911 if currentnode != node:
1912 if node is None:
1912 if node is None:
1913 finalmsg = msgexist % (book, nodemod.short(currentnode))
1913 finalmsg = msgexist % (book, nodemod.short(currentnode))
1914 elif currentnode is None:
1914 elif currentnode is None:
1915 finalmsg = msgmissing % (book, nodemod.short(node))
1915 finalmsg = msgmissing % (book, nodemod.short(node))
1916 else:
1916 else:
1917 finalmsg = msgstandard % (book, nodemod.short(node),
1917 finalmsg = msgstandard % (book, nodemod.short(node),
1918 nodemod.short(currentnode))
1918 nodemod.short(currentnode))
1919 raise error.PushRaced(finalmsg)
1919 raise error.PushRaced(finalmsg)
1920
1920
1921 @parthandler('check:heads')
1921 @parthandler('check:heads')
1922 def handlecheckheads(op, inpart):
1922 def handlecheckheads(op, inpart):
1923 """check that head of the repo did not change
1923 """check that head of the repo did not change
1924
1924
1925 This is used to detect a push race when using unbundle.
1925 This is used to detect a push race when using unbundle.
1926 This replaces the "heads" argument of unbundle."""
1926 This replaces the "heads" argument of unbundle."""
1927 h = inpart.read(20)
1927 h = inpart.read(20)
1928 heads = []
1928 heads = []
1929 while len(h) == 20:
1929 while len(h) == 20:
1930 heads.append(h)
1930 heads.append(h)
1931 h = inpart.read(20)
1931 h = inpart.read(20)
1932 assert not h
1932 assert not h
1933 # Trigger a transaction so that we are guaranteed to have the lock now.
1933 # Trigger a transaction so that we are guaranteed to have the lock now.
1934 if op.ui.configbool('experimental', 'bundle2lazylocking'):
1934 if op.ui.configbool('experimental', 'bundle2lazylocking'):
1935 op.gettransaction()
1935 op.gettransaction()
1936 if sorted(heads) != sorted(op.repo.heads()):
1936 if sorted(heads) != sorted(op.repo.heads()):
1937 raise error.PushRaced('repository changed while pushing - '
1937 raise error.PushRaced('repository changed while pushing - '
1938 'please try again')
1938 'please try again')
1939
1939
1940 @parthandler('check:updated-heads')
1940 @parthandler('check:updated-heads')
1941 def handlecheckupdatedheads(op, inpart):
1941 def handlecheckupdatedheads(op, inpart):
1942 """check for race on the heads touched by a push
1942 """check for race on the heads touched by a push
1943
1943
1944 This is similar to 'check:heads' but focus on the heads actually updated
1944 This is similar to 'check:heads' but focus on the heads actually updated
1945 during the push. If other activities happen on unrelated heads, it is
1945 during the push. If other activities happen on unrelated heads, it is
1946 ignored.
1946 ignored.
1947
1947
1948 This allow server with high traffic to avoid push contention as long as
1948 This allow server with high traffic to avoid push contention as long as
1949 unrelated parts of the graph are involved."""
1949 unrelated parts of the graph are involved."""
1950 h = inpart.read(20)
1950 h = inpart.read(20)
1951 heads = []
1951 heads = []
1952 while len(h) == 20:
1952 while len(h) == 20:
1953 heads.append(h)
1953 heads.append(h)
1954 h = inpart.read(20)
1954 h = inpart.read(20)
1955 assert not h
1955 assert not h
1956 # trigger a transaction so that we are guaranteed to have the lock now.
1956 # trigger a transaction so that we are guaranteed to have the lock now.
1957 if op.ui.configbool('experimental', 'bundle2lazylocking'):
1957 if op.ui.configbool('experimental', 'bundle2lazylocking'):
1958 op.gettransaction()
1958 op.gettransaction()
1959
1959
1960 currentheads = set()
1960 currentheads = set()
1961 for ls in op.repo.branchmap().itervalues():
1961 for ls in op.repo.branchmap().itervalues():
1962 currentheads.update(ls)
1962 currentheads.update(ls)
1963
1963
1964 for h in heads:
1964 for h in heads:
1965 if h not in currentheads:
1965 if h not in currentheads:
1966 raise error.PushRaced('repository changed while pushing - '
1966 raise error.PushRaced('repository changed while pushing - '
1967 'please try again')
1967 'please try again')
1968
1968
1969 @parthandler('check:phases')
1969 @parthandler('check:phases')
1970 def handlecheckphases(op, inpart):
1970 def handlecheckphases(op, inpart):
1971 """check that phase boundaries of the repository did not change
1971 """check that phase boundaries of the repository did not change
1972
1972
1973 This is used to detect a push race.
1973 This is used to detect a push race.
1974 """
1974 """
1975 phasetonodes = phases.binarydecode(inpart)
1975 phasetonodes = phases.binarydecode(inpart)
1976 unfi = op.repo.unfiltered()
1976 unfi = op.repo.unfiltered()
1977 cl = unfi.changelog
1977 cl = unfi.changelog
1978 phasecache = unfi._phasecache
1978 phasecache = unfi._phasecache
1979 msg = ('repository changed while pushing - please try again '
1979 msg = ('repository changed while pushing - please try again '
1980 '(%s is %s expected %s)')
1980 '(%s is %s expected %s)')
1981 for expectedphase, nodes in enumerate(phasetonodes):
1981 for expectedphase, nodes in enumerate(phasetonodes):
1982 for n in nodes:
1982 for n in nodes:
1983 actualphase = phasecache.phase(unfi, cl.rev(n))
1983 actualphase = phasecache.phase(unfi, cl.rev(n))
1984 if actualphase != expectedphase:
1984 if actualphase != expectedphase:
1985 finalmsg = msg % (nodemod.short(n),
1985 finalmsg = msg % (nodemod.short(n),
1986 phases.phasenames[actualphase],
1986 phases.phasenames[actualphase],
1987 phases.phasenames[expectedphase])
1987 phases.phasenames[expectedphase])
1988 raise error.PushRaced(finalmsg)
1988 raise error.PushRaced(finalmsg)
1989
1989
1990 @parthandler('output')
1990 @parthandler('output')
1991 def handleoutput(op, inpart):
1991 def handleoutput(op, inpart):
1992 """forward output captured on the server to the client"""
1992 """forward output captured on the server to the client"""
1993 for line in inpart.read().splitlines():
1993 for line in inpart.read().splitlines():
1994 op.ui.status(_('remote: %s\n') % line)
1994 op.ui.status(_('remote: %s\n') % line)
1995
1995
1996 @parthandler('replycaps')
1996 @parthandler('replycaps')
1997 def handlereplycaps(op, inpart):
1997 def handlereplycaps(op, inpart):
1998 """Notify that a reply bundle should be created
1998 """Notify that a reply bundle should be created
1999
1999
2000 The payload contains the capabilities information for the reply"""
2000 The payload contains the capabilities information for the reply"""
2001 caps = decodecaps(inpart.read())
2001 caps = decodecaps(inpart.read())
2002 if op.reply is None:
2002 if op.reply is None:
2003 op.reply = bundle20(op.ui, caps)
2003 op.reply = bundle20(op.ui, caps)
2004
2004
2005 class AbortFromPart(error.Abort):
2005 class AbortFromPart(error.Abort):
2006 """Sub-class of Abort that denotes an error from a bundle2 part."""
2006 """Sub-class of Abort that denotes an error from a bundle2 part."""
2007
2007
2008 @parthandler('error:abort', ('message', 'hint'))
2008 @parthandler('error:abort', ('message', 'hint'))
2009 def handleerrorabort(op, inpart):
2009 def handleerrorabort(op, inpart):
2010 """Used to transmit abort error over the wire"""
2010 """Used to transmit abort error over the wire"""
2011 raise AbortFromPart(inpart.params['message'],
2011 raise AbortFromPart(inpart.params['message'],
2012 hint=inpart.params.get('hint'))
2012 hint=inpart.params.get('hint'))
2013
2013
2014 @parthandler('error:pushkey', ('namespace', 'key', 'new', 'old', 'ret',
2014 @parthandler('error:pushkey', ('namespace', 'key', 'new', 'old', 'ret',
2015 'in-reply-to'))
2015 'in-reply-to'))
2016 def handleerrorpushkey(op, inpart):
2016 def handleerrorpushkey(op, inpart):
2017 """Used to transmit failure of a mandatory pushkey over the wire"""
2017 """Used to transmit failure of a mandatory pushkey over the wire"""
2018 kwargs = {}
2018 kwargs = {}
2019 for name in ('namespace', 'key', 'new', 'old', 'ret'):
2019 for name in ('namespace', 'key', 'new', 'old', 'ret'):
2020 value = inpart.params.get(name)
2020 value = inpart.params.get(name)
2021 if value is not None:
2021 if value is not None:
2022 kwargs[name] = value
2022 kwargs[name] = value
2023 raise error.PushkeyFailed(inpart.params['in-reply-to'],
2023 raise error.PushkeyFailed(inpart.params['in-reply-to'],
2024 **pycompat.strkwargs(kwargs))
2024 **pycompat.strkwargs(kwargs))
2025
2025
2026 @parthandler('error:unsupportedcontent', ('parttype', 'params'))
2026 @parthandler('error:unsupportedcontent', ('parttype', 'params'))
2027 def handleerrorunsupportedcontent(op, inpart):
2027 def handleerrorunsupportedcontent(op, inpart):
2028 """Used to transmit unknown content error over the wire"""
2028 """Used to transmit unknown content error over the wire"""
2029 kwargs = {}
2029 kwargs = {}
2030 parttype = inpart.params.get('parttype')
2030 parttype = inpart.params.get('parttype')
2031 if parttype is not None:
2031 if parttype is not None:
2032 kwargs['parttype'] = parttype
2032 kwargs['parttype'] = parttype
2033 params = inpart.params.get('params')
2033 params = inpart.params.get('params')
2034 if params is not None:
2034 if params is not None:
2035 kwargs['params'] = params.split('\0')
2035 kwargs['params'] = params.split('\0')
2036
2036
2037 raise error.BundleUnknownFeatureError(**pycompat.strkwargs(kwargs))
2037 raise error.BundleUnknownFeatureError(**pycompat.strkwargs(kwargs))
2038
2038
2039 @parthandler('error:pushraced', ('message',))
2039 @parthandler('error:pushraced', ('message',))
2040 def handleerrorpushraced(op, inpart):
2040 def handleerrorpushraced(op, inpart):
2041 """Used to transmit push race error over the wire"""
2041 """Used to transmit push race error over the wire"""
2042 raise error.ResponseError(_('push failed:'), inpart.params['message'])
2042 raise error.ResponseError(_('push failed:'), inpart.params['message'])
2043
2043
2044 @parthandler('listkeys', ('namespace',))
2044 @parthandler('listkeys', ('namespace',))
2045 def handlelistkeys(op, inpart):
2045 def handlelistkeys(op, inpart):
2046 """retrieve pushkey namespace content stored in a bundle2"""
2046 """retrieve pushkey namespace content stored in a bundle2"""
2047 namespace = inpart.params['namespace']
2047 namespace = inpart.params['namespace']
2048 r = pushkey.decodekeys(inpart.read())
2048 r = pushkey.decodekeys(inpart.read())
2049 op.records.add('listkeys', (namespace, r))
2049 op.records.add('listkeys', (namespace, r))
2050
2050
2051 @parthandler('pushkey', ('namespace', 'key', 'old', 'new'))
2051 @parthandler('pushkey', ('namespace', 'key', 'old', 'new'))
2052 def handlepushkey(op, inpart):
2052 def handlepushkey(op, inpart):
2053 """process a pushkey request"""
2053 """process a pushkey request"""
2054 dec = pushkey.decode
2054 dec = pushkey.decode
2055 namespace = dec(inpart.params['namespace'])
2055 namespace = dec(inpart.params['namespace'])
2056 key = dec(inpart.params['key'])
2056 key = dec(inpart.params['key'])
2057 old = dec(inpart.params['old'])
2057 old = dec(inpart.params['old'])
2058 new = dec(inpart.params['new'])
2058 new = dec(inpart.params['new'])
2059 # Grab the transaction to ensure that we have the lock before performing the
2059 # Grab the transaction to ensure that we have the lock before performing the
2060 # pushkey.
2060 # pushkey.
2061 if op.ui.configbool('experimental', 'bundle2lazylocking'):
2061 if op.ui.configbool('experimental', 'bundle2lazylocking'):
2062 op.gettransaction()
2062 op.gettransaction()
2063 ret = op.repo.pushkey(namespace, key, old, new)
2063 ret = op.repo.pushkey(namespace, key, old, new)
2064 record = {'namespace': namespace,
2064 record = {'namespace': namespace,
2065 'key': key,
2065 'key': key,
2066 'old': old,
2066 'old': old,
2067 'new': new}
2067 'new': new}
2068 op.records.add('pushkey', record)
2068 op.records.add('pushkey', record)
2069 if op.reply is not None:
2069 if op.reply is not None:
2070 rpart = op.reply.newpart('reply:pushkey')
2070 rpart = op.reply.newpart('reply:pushkey')
2071 rpart.addparam(
2071 rpart.addparam(
2072 'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False)
2072 'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False)
2073 rpart.addparam('return', '%i' % ret, mandatory=False)
2073 rpart.addparam('return', '%i' % ret, mandatory=False)
2074 if inpart.mandatory and not ret:
2074 if inpart.mandatory and not ret:
2075 kwargs = {}
2075 kwargs = {}
2076 for key in ('namespace', 'key', 'new', 'old', 'ret'):
2076 for key in ('namespace', 'key', 'new', 'old', 'ret'):
2077 if key in inpart.params:
2077 if key in inpart.params:
2078 kwargs[key] = inpart.params[key]
2078 kwargs[key] = inpart.params[key]
2079 raise error.PushkeyFailed(partid='%d' % inpart.id,
2079 raise error.PushkeyFailed(partid='%d' % inpart.id,
2080 **pycompat.strkwargs(kwargs))
2080 **pycompat.strkwargs(kwargs))
2081
2081
2082 @parthandler('bookmarks')
2082 @parthandler('bookmarks')
2083 def handlebookmark(op, inpart):
2083 def handlebookmark(op, inpart):
2084 """transmit bookmark information
2084 """transmit bookmark information
2085
2085
2086 The part contains binary encoded bookmark information.
2086 The part contains binary encoded bookmark information.
2087
2087
2088 The exact behavior of this part can be controlled by the 'bookmarks' mode
2088 The exact behavior of this part can be controlled by the 'bookmarks' mode
2089 on the bundle operation.
2089 on the bundle operation.
2090
2090
2091 When mode is 'apply' (the default) the bookmark information is applied as
2091 When mode is 'apply' (the default) the bookmark information is applied as
2092 is to the unbundling repository. Make sure a 'check:bookmarks' part is
2092 is to the unbundling repository. Make sure a 'check:bookmarks' part is
2093 issued earlier to check for push races in such update. This behavior is
2093 issued earlier to check for push races in such update. This behavior is
2094 suitable for pushing.
2094 suitable for pushing.
2095
2095
2096 When mode is 'records', the information is recorded into the 'bookmarks'
2096 When mode is 'records', the information is recorded into the 'bookmarks'
2097 records of the bundle operation. This behavior is suitable for pulling.
2097 records of the bundle operation. This behavior is suitable for pulling.
2098 """
2098 """
2099 changes = bookmarks.binarydecode(inpart)
2099 changes = bookmarks.binarydecode(inpart)
2100
2100
2101 pushkeycompat = op.repo.ui.configbool('server', 'bookmarks-pushkey-compat')
2101 pushkeycompat = op.repo.ui.configbool('server', 'bookmarks-pushkey-compat')
2102 bookmarksmode = op.modes.get('bookmarks', 'apply')
2102 bookmarksmode = op.modes.get('bookmarks', 'apply')
2103
2103
2104 if bookmarksmode == 'apply':
2104 if bookmarksmode == 'apply':
2105 tr = op.gettransaction()
2105 tr = op.gettransaction()
2106 bookstore = op.repo._bookmarks
2106 bookstore = op.repo._bookmarks
2107 if pushkeycompat:
2107 if pushkeycompat:
2108 allhooks = []
2108 allhooks = []
2109 for book, node in changes:
2109 for book, node in changes:
2110 hookargs = tr.hookargs.copy()
2110 hookargs = tr.hookargs.copy()
2111 hookargs['pushkeycompat'] = '1'
2111 hookargs['pushkeycompat'] = '1'
2112 hookargs['namespace'] = 'bookmarks'
2112 hookargs['namespace'] = 'bookmarks'
2113 hookargs['key'] = book
2113 hookargs['key'] = book
2114 hookargs['old'] = nodemod.hex(bookstore.get(book, ''))
2114 hookargs['old'] = nodemod.hex(bookstore.get(book, ''))
2115 hookargs['new'] = nodemod.hex(node if node is not None else '')
2115 hookargs['new'] = nodemod.hex(node if node is not None else '')
2116 allhooks.append(hookargs)
2116 allhooks.append(hookargs)
2117
2117
2118 for hookargs in allhooks:
2118 for hookargs in allhooks:
2119 op.repo.hook('prepushkey', throw=True,
2119 op.repo.hook('prepushkey', throw=True,
2120 **pycompat.strkwargs(hookargs))
2120 **pycompat.strkwargs(hookargs))
2121
2121
2122 bookstore.applychanges(op.repo, op.gettransaction(), changes)
2122 bookstore.applychanges(op.repo, op.gettransaction(), changes)
2123
2123
2124 if pushkeycompat:
2124 if pushkeycompat:
2125 def runhook():
2125 def runhook():
2126 for hookargs in allhooks:
2126 for hookargs in allhooks:
2127 op.repo.hook('pushkey', **pycompat.strkwargs(hookargs))
2127 op.repo.hook('pushkey', **pycompat.strkwargs(hookargs))
2128 op.repo._afterlock(runhook)
2128 op.repo._afterlock(runhook)
2129
2129
2130 elif bookmarksmode == 'records':
2130 elif bookmarksmode == 'records':
2131 for book, node in changes:
2131 for book, node in changes:
2132 record = {'bookmark': book, 'node': node}
2132 record = {'bookmark': book, 'node': node}
2133 op.records.add('bookmarks', record)
2133 op.records.add('bookmarks', record)
2134 else:
2134 else:
2135 raise error.ProgrammingError('unkown bookmark mode: %s' % bookmarksmode)
2135 raise error.ProgrammingError('unkown bookmark mode: %s' % bookmarksmode)
2136
2136
2137 @parthandler('phase-heads')
2137 @parthandler('phase-heads')
2138 def handlephases(op, inpart):
2138 def handlephases(op, inpart):
2139 """apply phases from bundle part to repo"""
2139 """apply phases from bundle part to repo"""
2140 headsbyphase = phases.binarydecode(inpart)
2140 headsbyphase = phases.binarydecode(inpart)
2141 phases.updatephases(op.repo.unfiltered(), op.gettransaction, headsbyphase)
2141 phases.updatephases(op.repo.unfiltered(), op.gettransaction, headsbyphase)
2142
2142
2143 @parthandler('reply:pushkey', ('return', 'in-reply-to'))
2143 @parthandler('reply:pushkey', ('return', 'in-reply-to'))
2144 def handlepushkeyreply(op, inpart):
2144 def handlepushkeyreply(op, inpart):
2145 """retrieve the result of a pushkey request"""
2145 """retrieve the result of a pushkey request"""
2146 ret = int(inpart.params['return'])
2146 ret = int(inpart.params['return'])
2147 partid = int(inpart.params['in-reply-to'])
2147 partid = int(inpart.params['in-reply-to'])
2148 op.records.add('pushkey', {'return': ret}, partid)
2148 op.records.add('pushkey', {'return': ret}, partid)
2149
2149
2150 @parthandler('obsmarkers')
2150 @parthandler('obsmarkers')
2151 def handleobsmarker(op, inpart):
2151 def handleobsmarker(op, inpart):
2152 """add a stream of obsmarkers to the repo"""
2152 """add a stream of obsmarkers to the repo"""
2153 tr = op.gettransaction()
2153 tr = op.gettransaction()
2154 markerdata = inpart.read()
2154 markerdata = inpart.read()
2155 if op.ui.config('experimental', 'obsmarkers-exchange-debug'):
2155 if op.ui.config('experimental', 'obsmarkers-exchange-debug'):
2156 op.ui.write(('obsmarker-exchange: %i bytes received\n')
2156 op.ui.write(('obsmarker-exchange: %i bytes received\n')
2157 % len(markerdata))
2157 % len(markerdata))
2158 # The mergemarkers call will crash if marker creation is not enabled.
2158 # The mergemarkers call will crash if marker creation is not enabled.
2159 # we want to avoid this if the part is advisory.
2159 # we want to avoid this if the part is advisory.
2160 if not inpart.mandatory and op.repo.obsstore.readonly:
2160 if not inpart.mandatory and op.repo.obsstore.readonly:
2161 op.repo.ui.debug('ignoring obsolescence markers, feature not enabled\n')
2161 op.repo.ui.debug('ignoring obsolescence markers, feature not enabled\n')
2162 return
2162 return
2163 new = op.repo.obsstore.mergemarkers(tr, markerdata)
2163 new = op.repo.obsstore.mergemarkers(tr, markerdata)
2164 op.repo.invalidatevolatilesets()
2164 op.repo.invalidatevolatilesets()
2165 if new:
2165 if new:
2166 op.repo.ui.status(_('%i new obsolescence markers\n') % new)
2166 op.repo.ui.status(_('%i new obsolescence markers\n') % new)
2167 op.records.add('obsmarkers', {'new': new})
2167 op.records.add('obsmarkers', {'new': new})
2168 if op.reply is not None:
2168 if op.reply is not None:
2169 rpart = op.reply.newpart('reply:obsmarkers')
2169 rpart = op.reply.newpart('reply:obsmarkers')
2170 rpart.addparam(
2170 rpart.addparam(
2171 'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False)
2171 'in-reply-to', pycompat.bytestr(inpart.id), mandatory=False)
2172 rpart.addparam('new', '%i' % new, mandatory=False)
2172 rpart.addparam('new', '%i' % new, mandatory=False)
2173
2173
2174
2174
2175 @parthandler('reply:obsmarkers', ('new', 'in-reply-to'))
2175 @parthandler('reply:obsmarkers', ('new', 'in-reply-to'))
2176 def handleobsmarkerreply(op, inpart):
2176 def handleobsmarkerreply(op, inpart):
2177 """retrieve the result of a pushkey request"""
2177 """retrieve the result of a pushkey request"""
2178 ret = int(inpart.params['new'])
2178 ret = int(inpart.params['new'])
2179 partid = int(inpart.params['in-reply-to'])
2179 partid = int(inpart.params['in-reply-to'])
2180 op.records.add('obsmarkers', {'new': ret}, partid)
2180 op.records.add('obsmarkers', {'new': ret}, partid)
2181
2181
2182 @parthandler('hgtagsfnodes')
2182 @parthandler('hgtagsfnodes')
2183 def handlehgtagsfnodes(op, inpart):
2183 def handlehgtagsfnodes(op, inpart):
2184 """Applies .hgtags fnodes cache entries to the local repo.
2184 """Applies .hgtags fnodes cache entries to the local repo.
2185
2185
2186 Payload is pairs of 20 byte changeset nodes and filenodes.
2186 Payload is pairs of 20 byte changeset nodes and filenodes.
2187 """
2187 """
2188 # Grab the transaction so we ensure that we have the lock at this point.
2188 # Grab the transaction so we ensure that we have the lock at this point.
2189 if op.ui.configbool('experimental', 'bundle2lazylocking'):
2189 if op.ui.configbool('experimental', 'bundle2lazylocking'):
2190 op.gettransaction()
2190 op.gettransaction()
2191 cache = tags.hgtagsfnodescache(op.repo.unfiltered())
2191 cache = tags.hgtagsfnodescache(op.repo.unfiltered())
2192
2192
2193 count = 0
2193 count = 0
2194 while True:
2194 while True:
2195 node = inpart.read(20)
2195 node = inpart.read(20)
2196 fnode = inpart.read(20)
2196 fnode = inpart.read(20)
2197 if len(node) < 20 or len(fnode) < 20:
2197 if len(node) < 20 or len(fnode) < 20:
2198 op.ui.debug('ignoring incomplete received .hgtags fnodes data\n')
2198 op.ui.debug('ignoring incomplete received .hgtags fnodes data\n')
2199 break
2199 break
2200 cache.setfnode(node, fnode)
2200 cache.setfnode(node, fnode)
2201 count += 1
2201 count += 1
2202
2202
2203 cache.write()
2203 cache.write()
2204 op.ui.debug('applied %i hgtags fnodes cache entries\n' % count)
2204 op.ui.debug('applied %i hgtags fnodes cache entries\n' % count)
2205
2205
2206 rbcstruct = struct.Struct('>III')
2206 rbcstruct = struct.Struct('>III')
2207
2207
2208 @parthandler('cache:rev-branch-cache')
2208 @parthandler('cache:rev-branch-cache')
2209 def handlerbc(op, inpart):
2209 def handlerbc(op, inpart):
2210 """receive a rev-branch-cache payload and update the local cache
2210 """receive a rev-branch-cache payload and update the local cache
2211
2211
2212 The payload is a series of data related to each branch
2212 The payload is a series of data related to each branch
2213
2213
2214 1) branch name length
2214 1) branch name length
2215 2) number of open heads
2215 2) number of open heads
2216 3) number of closed heads
2216 3) number of closed heads
2217 4) open heads nodes
2217 4) open heads nodes
2218 5) closed heads nodes
2218 5) closed heads nodes
2219 """
2219 """
2220 total = 0
2220 total = 0
2221 rawheader = inpart.read(rbcstruct.size)
2221 rawheader = inpart.read(rbcstruct.size)
2222 cache = op.repo.revbranchcache()
2222 cache = op.repo.revbranchcache()
2223 cl = op.repo.unfiltered().changelog
2223 cl = op.repo.unfiltered().changelog
2224 while rawheader:
2224 while rawheader:
2225 header = rbcstruct.unpack(rawheader)
2225 header = rbcstruct.unpack(rawheader)
2226 total += header[1] + header[2]
2226 total += header[1] + header[2]
2227 utf8branch = inpart.read(header[0])
2227 utf8branch = inpart.read(header[0])
2228 branch = encoding.tolocal(utf8branch)
2228 branch = encoding.tolocal(utf8branch)
2229 for x in pycompat.xrange(header[1]):
2229 for x in pycompat.xrange(header[1]):
2230 node = inpart.read(20)
2230 node = inpart.read(20)
2231 rev = cl.rev(node)
2231 rev = cl.rev(node)
2232 cache.setdata(branch, rev, node, False)
2232 cache.setdata(branch, rev, node, False)
2233 for x in pycompat.xrange(header[2]):
2233 for x in pycompat.xrange(header[2]):
2234 node = inpart.read(20)
2234 node = inpart.read(20)
2235 rev = cl.rev(node)
2235 rev = cl.rev(node)
2236 cache.setdata(branch, rev, node, True)
2236 cache.setdata(branch, rev, node, True)
2237 rawheader = inpart.read(rbcstruct.size)
2237 rawheader = inpart.read(rbcstruct.size)
2238 cache.write()
2238 cache.write()
2239
2239
2240 @parthandler('pushvars')
2240 @parthandler('pushvars')
2241 def bundle2getvars(op, part):
2241 def bundle2getvars(op, part):
2242 '''unbundle a bundle2 containing shellvars on the server'''
2242 '''unbundle a bundle2 containing shellvars on the server'''
2243 # An option to disable unbundling on server-side for security reasons
2243 # An option to disable unbundling on server-side for security reasons
2244 if op.ui.configbool('push', 'pushvars.server'):
2244 if op.ui.configbool('push', 'pushvars.server'):
2245 hookargs = {}
2245 hookargs = {}
2246 for key, value in part.advisoryparams:
2246 for key, value in part.advisoryparams:
2247 key = key.upper()
2247 key = key.upper()
2248 # We want pushed variables to have USERVAR_ prepended so we know
2248 # We want pushed variables to have USERVAR_ prepended so we know
2249 # they came from the --pushvar flag.
2249 # they came from the --pushvar flag.
2250 key = "USERVAR_" + key
2250 key = "USERVAR_" + key
2251 hookargs[key] = value
2251 hookargs[key] = value
2252 op.addhookargs(hookargs)
2252 op.addhookargs(hookargs)
2253
2253
2254 @parthandler('stream2', ('requirements', 'filecount', 'bytecount'))
2254 @parthandler('stream2', ('requirements', 'filecount', 'bytecount'))
2255 def handlestreamv2bundle(op, part):
2255 def handlestreamv2bundle(op, part):
2256
2256
2257 requirements = urlreq.unquote(part.params['requirements']).split(',')
2257 requirements = urlreq.unquote(part.params['requirements']).split(',')
2258 filecount = int(part.params['filecount'])
2258 filecount = int(part.params['filecount'])
2259 bytecount = int(part.params['bytecount'])
2259 bytecount = int(part.params['bytecount'])
2260
2260
2261 repo = op.repo
2261 repo = op.repo
2262 if len(repo):
2262 if len(repo):
2263 msg = _('cannot apply stream clone to non empty repository')
2263 msg = _('cannot apply stream clone to non empty repository')
2264 raise error.Abort(msg)
2264 raise error.Abort(msg)
2265
2265
2266 repo.ui.debug('applying stream bundle\n')
2266 repo.ui.debug('applying stream bundle\n')
2267 streamclone.applybundlev2(repo, part, filecount, bytecount,
2267 streamclone.applybundlev2(repo, part, filecount, bytecount,
2268 requirements)
2268 requirements)
@@ -1,1404 +1,1405 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('annotate', 'word-diff',
150 coreconfigitem('annotate', 'word-diff',
151 default=False,
151 default=False,
152 )
152 )
153 coreconfigitem('auth', 'cookiefile',
153 coreconfigitem('auth', 'cookiefile',
154 default=None,
154 default=None,
155 )
155 )
156 # bookmarks.pushing: internal hack for discovery
156 # bookmarks.pushing: internal hack for discovery
157 coreconfigitem('bookmarks', 'pushing',
157 coreconfigitem('bookmarks', 'pushing',
158 default=list,
158 default=list,
159 )
159 )
160 # bundle.mainreporoot: internal hack for bundlerepo
160 # bundle.mainreporoot: internal hack for bundlerepo
161 coreconfigitem('bundle', 'mainreporoot',
161 coreconfigitem('bundle', 'mainreporoot',
162 default='',
162 default='',
163 )
163 )
164 # bundle.reorder: experimental config
164 # bundle.reorder: experimental config
165 coreconfigitem('bundle', 'reorder',
165 coreconfigitem('bundle', 'reorder',
166 default='auto',
166 default='auto',
167 )
167 )
168 coreconfigitem('censor', 'policy',
168 coreconfigitem('censor', 'policy',
169 default='abort',
169 default='abort',
170 )
170 )
171 coreconfigitem('chgserver', 'idletimeout',
171 coreconfigitem('chgserver', 'idletimeout',
172 default=3600,
172 default=3600,
173 )
173 )
174 coreconfigitem('chgserver', 'skiphash',
174 coreconfigitem('chgserver', 'skiphash',
175 default=False,
175 default=False,
176 )
176 )
177 coreconfigitem('cmdserver', 'log',
177 coreconfigitem('cmdserver', 'log',
178 default=None,
178 default=None,
179 )
179 )
180 coreconfigitem('color', '.*',
180 coreconfigitem('color', '.*',
181 default=None,
181 default=None,
182 generic=True,
182 generic=True,
183 )
183 )
184 coreconfigitem('color', 'mode',
184 coreconfigitem('color', 'mode',
185 default='auto',
185 default='auto',
186 )
186 )
187 coreconfigitem('color', 'pagermode',
187 coreconfigitem('color', 'pagermode',
188 default=dynamicdefault,
188 default=dynamicdefault,
189 )
189 )
190 coreconfigitem('commands', 'grep.all-files',
190 coreconfigitem('commands', 'grep.all-files',
191 default=False,
191 default=False,
192 )
192 )
193 coreconfigitem('commands', 'resolve.confirm',
193 coreconfigitem('commands', 'resolve.confirm',
194 default=False,
194 default=False,
195 )
195 )
196 coreconfigitem('commands', 'resolve.explicit-re-merge',
196 coreconfigitem('commands', 'resolve.explicit-re-merge',
197 default=False,
197 default=False,
198 )
198 )
199 coreconfigitem('commands', 'resolve.mark-check',
199 coreconfigitem('commands', 'resolve.mark-check',
200 default='none',
200 default='none',
201 )
201 )
202 coreconfigitem('commands', 'show.aliasprefix',
202 coreconfigitem('commands', 'show.aliasprefix',
203 default=list,
203 default=list,
204 )
204 )
205 coreconfigitem('commands', 'status.relative',
205 coreconfigitem('commands', 'status.relative',
206 default=False,
206 default=False,
207 )
207 )
208 coreconfigitem('commands', 'status.skipstates',
208 coreconfigitem('commands', 'status.skipstates',
209 default=[],
209 default=[],
210 )
210 )
211 coreconfigitem('commands', 'status.terse',
211 coreconfigitem('commands', 'status.terse',
212 default='',
212 default='',
213 )
213 )
214 coreconfigitem('commands', 'status.verbose',
214 coreconfigitem('commands', 'status.verbose',
215 default=False,
215 default=False,
216 )
216 )
217 coreconfigitem('commands', 'update.check',
217 coreconfigitem('commands', 'update.check',
218 default=None,
218 default=None,
219 )
219 )
220 coreconfigitem('commands', 'update.requiredest',
220 coreconfigitem('commands', 'update.requiredest',
221 default=False,
221 default=False,
222 )
222 )
223 coreconfigitem('committemplate', '.*',
223 coreconfigitem('committemplate', '.*',
224 default=None,
224 default=None,
225 generic=True,
225 generic=True,
226 )
226 )
227 coreconfigitem('convert', 'bzr.saverev',
227 coreconfigitem('convert', 'bzr.saverev',
228 default=True,
228 default=True,
229 )
229 )
230 coreconfigitem('convert', 'cvsps.cache',
230 coreconfigitem('convert', 'cvsps.cache',
231 default=True,
231 default=True,
232 )
232 )
233 coreconfigitem('convert', 'cvsps.fuzz',
233 coreconfigitem('convert', 'cvsps.fuzz',
234 default=60,
234 default=60,
235 )
235 )
236 coreconfigitem('convert', 'cvsps.logencoding',
236 coreconfigitem('convert', 'cvsps.logencoding',
237 default=None,
237 default=None,
238 )
238 )
239 coreconfigitem('convert', 'cvsps.mergefrom',
239 coreconfigitem('convert', 'cvsps.mergefrom',
240 default=None,
240 default=None,
241 )
241 )
242 coreconfigitem('convert', 'cvsps.mergeto',
242 coreconfigitem('convert', 'cvsps.mergeto',
243 default=None,
243 default=None,
244 )
244 )
245 coreconfigitem('convert', 'git.committeractions',
245 coreconfigitem('convert', 'git.committeractions',
246 default=lambda: ['messagedifferent'],
246 default=lambda: ['messagedifferent'],
247 )
247 )
248 coreconfigitem('convert', 'git.extrakeys',
248 coreconfigitem('convert', 'git.extrakeys',
249 default=list,
249 default=list,
250 )
250 )
251 coreconfigitem('convert', 'git.findcopiesharder',
251 coreconfigitem('convert', 'git.findcopiesharder',
252 default=False,
252 default=False,
253 )
253 )
254 coreconfigitem('convert', 'git.remoteprefix',
254 coreconfigitem('convert', 'git.remoteprefix',
255 default='remote',
255 default='remote',
256 )
256 )
257 coreconfigitem('convert', 'git.renamelimit',
257 coreconfigitem('convert', 'git.renamelimit',
258 default=400,
258 default=400,
259 )
259 )
260 coreconfigitem('convert', 'git.saverev',
260 coreconfigitem('convert', 'git.saverev',
261 default=True,
261 default=True,
262 )
262 )
263 coreconfigitem('convert', 'git.similarity',
263 coreconfigitem('convert', 'git.similarity',
264 default=50,
264 default=50,
265 )
265 )
266 coreconfigitem('convert', 'git.skipsubmodules',
266 coreconfigitem('convert', 'git.skipsubmodules',
267 default=False,
267 default=False,
268 )
268 )
269 coreconfigitem('convert', 'hg.clonebranches',
269 coreconfigitem('convert', 'hg.clonebranches',
270 default=False,
270 default=False,
271 )
271 )
272 coreconfigitem('convert', 'hg.ignoreerrors',
272 coreconfigitem('convert', 'hg.ignoreerrors',
273 default=False,
273 default=False,
274 )
274 )
275 coreconfigitem('convert', 'hg.revs',
275 coreconfigitem('convert', 'hg.revs',
276 default=None,
276 default=None,
277 )
277 )
278 coreconfigitem('convert', 'hg.saverev',
278 coreconfigitem('convert', 'hg.saverev',
279 default=False,
279 default=False,
280 )
280 )
281 coreconfigitem('convert', 'hg.sourcename',
281 coreconfigitem('convert', 'hg.sourcename',
282 default=None,
282 default=None,
283 )
283 )
284 coreconfigitem('convert', 'hg.startrev',
284 coreconfigitem('convert', 'hg.startrev',
285 default=None,
285 default=None,
286 )
286 )
287 coreconfigitem('convert', 'hg.tagsbranch',
287 coreconfigitem('convert', 'hg.tagsbranch',
288 default='default',
288 default='default',
289 )
289 )
290 coreconfigitem('convert', 'hg.usebranchnames',
290 coreconfigitem('convert', 'hg.usebranchnames',
291 default=True,
291 default=True,
292 )
292 )
293 coreconfigitem('convert', 'ignoreancestorcheck',
293 coreconfigitem('convert', 'ignoreancestorcheck',
294 default=False,
294 default=False,
295 )
295 )
296 coreconfigitem('convert', 'localtimezone',
296 coreconfigitem('convert', 'localtimezone',
297 default=False,
297 default=False,
298 )
298 )
299 coreconfigitem('convert', 'p4.encoding',
299 coreconfigitem('convert', 'p4.encoding',
300 default=dynamicdefault,
300 default=dynamicdefault,
301 )
301 )
302 coreconfigitem('convert', 'p4.startrev',
302 coreconfigitem('convert', 'p4.startrev',
303 default=0,
303 default=0,
304 )
304 )
305 coreconfigitem('convert', 'skiptags',
305 coreconfigitem('convert', 'skiptags',
306 default=False,
306 default=False,
307 )
307 )
308 coreconfigitem('convert', 'svn.debugsvnlog',
308 coreconfigitem('convert', 'svn.debugsvnlog',
309 default=True,
309 default=True,
310 )
310 )
311 coreconfigitem('convert', 'svn.trunk',
311 coreconfigitem('convert', 'svn.trunk',
312 default=None,
312 default=None,
313 )
313 )
314 coreconfigitem('convert', 'svn.tags',
314 coreconfigitem('convert', 'svn.tags',
315 default=None,
315 default=None,
316 )
316 )
317 coreconfigitem('convert', 'svn.branches',
317 coreconfigitem('convert', 'svn.branches',
318 default=None,
318 default=None,
319 )
319 )
320 coreconfigitem('convert', 'svn.startrev',
320 coreconfigitem('convert', 'svn.startrev',
321 default=0,
321 default=0,
322 )
322 )
323 coreconfigitem('debug', 'dirstate.delaywrite',
323 coreconfigitem('debug', 'dirstate.delaywrite',
324 default=0,
324 default=0,
325 )
325 )
326 coreconfigitem('defaults', '.*',
326 coreconfigitem('defaults', '.*',
327 default=None,
327 default=None,
328 generic=True,
328 generic=True,
329 )
329 )
330 coreconfigitem('devel', 'all-warnings',
330 coreconfigitem('devel', 'all-warnings',
331 default=False,
331 default=False,
332 )
332 )
333 coreconfigitem('devel', 'bundle2.debug',
333 coreconfigitem('devel', 'bundle2.debug',
334 default=False,
334 default=False,
335 )
335 )
336 coreconfigitem('devel', 'cache-vfs',
336 coreconfigitem('devel', 'cache-vfs',
337 default=None,
337 default=None,
338 )
338 )
339 coreconfigitem('devel', 'check-locks',
339 coreconfigitem('devel', 'check-locks',
340 default=False,
340 default=False,
341 )
341 )
342 coreconfigitem('devel', 'check-relroot',
342 coreconfigitem('devel', 'check-relroot',
343 default=False,
343 default=False,
344 )
344 )
345 coreconfigitem('devel', 'default-date',
345 coreconfigitem('devel', 'default-date',
346 default=None,
346 default=None,
347 )
347 )
348 coreconfigitem('devel', 'deprec-warn',
348 coreconfigitem('devel', 'deprec-warn',
349 default=False,
349 default=False,
350 )
350 )
351 coreconfigitem('devel', 'disableloaddefaultcerts',
351 coreconfigitem('devel', 'disableloaddefaultcerts',
352 default=False,
352 default=False,
353 )
353 )
354 coreconfigitem('devel', 'warn-empty-changegroup',
354 coreconfigitem('devel', 'warn-empty-changegroup',
355 default=False,
355 default=False,
356 )
356 )
357 coreconfigitem('devel', 'legacy.exchange',
357 coreconfigitem('devel', 'legacy.exchange',
358 default=list,
358 default=list,
359 )
359 )
360 coreconfigitem('devel', 'servercafile',
360 coreconfigitem('devel', 'servercafile',
361 default='',
361 default='',
362 )
362 )
363 coreconfigitem('devel', 'serverexactprotocol',
363 coreconfigitem('devel', 'serverexactprotocol',
364 default='',
364 default='',
365 )
365 )
366 coreconfigitem('devel', 'serverrequirecert',
366 coreconfigitem('devel', 'serverrequirecert',
367 default=False,
367 default=False,
368 )
368 )
369 coreconfigitem('devel', 'strip-obsmarkers',
369 coreconfigitem('devel', 'strip-obsmarkers',
370 default=True,
370 default=True,
371 )
371 )
372 coreconfigitem('devel', 'warn-config',
372 coreconfigitem('devel', 'warn-config',
373 default=None,
373 default=None,
374 )
374 )
375 coreconfigitem('devel', 'warn-config-default',
375 coreconfigitem('devel', 'warn-config-default',
376 default=None,
376 default=None,
377 )
377 )
378 coreconfigitem('devel', 'user.obsmarker',
378 coreconfigitem('devel', 'user.obsmarker',
379 default=None,
379 default=None,
380 )
380 )
381 coreconfigitem('devel', 'warn-config-unknown',
381 coreconfigitem('devel', 'warn-config-unknown',
382 default=None,
382 default=None,
383 )
383 )
384 coreconfigitem('devel', 'debug.extensions',
384 coreconfigitem('devel', 'debug.extensions',
385 default=False,
385 default=False,
386 )
386 )
387 coreconfigitem('devel', 'debug.peer-request',
387 coreconfigitem('devel', 'debug.peer-request',
388 default=False,
388 default=False,
389 )
389 )
390 coreconfigitem('diff', 'nodates',
390 coreconfigitem('diff', 'nodates',
391 default=False,
391 default=False,
392 )
392 )
393 coreconfigitem('diff', 'showfunc',
393 coreconfigitem('diff', 'showfunc',
394 default=False,
394 default=False,
395 )
395 )
396 coreconfigitem('diff', 'unified',
396 coreconfigitem('diff', 'unified',
397 default=None,
397 default=None,
398 )
398 )
399 coreconfigitem('diff', 'git',
399 coreconfigitem('diff', 'git',
400 default=False,
400 default=False,
401 )
401 )
402 coreconfigitem('diff', 'ignorews',
402 coreconfigitem('diff', 'ignorews',
403 default=False,
403 default=False,
404 )
404 )
405 coreconfigitem('diff', 'ignorewsamount',
405 coreconfigitem('diff', 'ignorewsamount',
406 default=False,
406 default=False,
407 )
407 )
408 coreconfigitem('diff', 'ignoreblanklines',
408 coreconfigitem('diff', 'ignoreblanklines',
409 default=False,
409 default=False,
410 )
410 )
411 coreconfigitem('diff', 'ignorewseol',
411 coreconfigitem('diff', 'ignorewseol',
412 default=False,
412 default=False,
413 )
413 )
414 coreconfigitem('diff', 'nobinary',
414 coreconfigitem('diff', 'nobinary',
415 default=False,
415 default=False,
416 )
416 )
417 coreconfigitem('diff', 'noprefix',
417 coreconfigitem('diff', 'noprefix',
418 default=False,
418 default=False,
419 )
419 )
420 coreconfigitem('diff', 'word-diff',
420 coreconfigitem('diff', 'word-diff',
421 default=False,
421 default=False,
422 )
422 )
423 coreconfigitem('email', 'bcc',
423 coreconfigitem('email', 'bcc',
424 default=None,
424 default=None,
425 )
425 )
426 coreconfigitem('email', 'cc',
426 coreconfigitem('email', 'cc',
427 default=None,
427 default=None,
428 )
428 )
429 coreconfigitem('email', 'charsets',
429 coreconfigitem('email', 'charsets',
430 default=list,
430 default=list,
431 )
431 )
432 coreconfigitem('email', 'from',
432 coreconfigitem('email', 'from',
433 default=None,
433 default=None,
434 )
434 )
435 coreconfigitem('email', 'method',
435 coreconfigitem('email', 'method',
436 default='smtp',
436 default='smtp',
437 )
437 )
438 coreconfigitem('email', 'reply-to',
438 coreconfigitem('email', 'reply-to',
439 default=None,
439 default=None,
440 )
440 )
441 coreconfigitem('email', 'to',
441 coreconfigitem('email', 'to',
442 default=None,
442 default=None,
443 )
443 )
444 coreconfigitem('experimental', 'archivemetatemplate',
444 coreconfigitem('experimental', 'archivemetatemplate',
445 default=dynamicdefault,
445 default=dynamicdefault,
446 )
446 )
447 coreconfigitem('experimental', 'bundle-phases',
447 coreconfigitem('experimental', 'bundle-phases',
448 default=False,
448 default=False,
449 )
449 )
450 coreconfigitem('experimental', 'bundle2-advertise',
450 coreconfigitem('experimental', 'bundle2-advertise',
451 default=True,
451 default=True,
452 )
452 )
453 coreconfigitem('experimental', 'bundle2-output-capture',
453 coreconfigitem('experimental', 'bundle2-output-capture',
454 default=False,
454 default=False,
455 )
455 )
456 coreconfigitem('experimental', 'bundle2.pushback',
456 coreconfigitem('experimental', 'bundle2.pushback',
457 default=False,
457 default=False,
458 )
458 )
459 coreconfigitem('experimental', 'bundle2.stream',
460 default=False,
461 )
462 coreconfigitem('experimental', 'bundle2lazylocking',
459 coreconfigitem('experimental', 'bundle2lazylocking',
463 default=False,
460 default=False,
464 )
461 )
465 coreconfigitem('experimental', 'bundlecomplevel',
462 coreconfigitem('experimental', 'bundlecomplevel',
466 default=None,
463 default=None,
467 )
464 )
468 coreconfigitem('experimental', 'bundlecomplevel.bzip2',
465 coreconfigitem('experimental', 'bundlecomplevel.bzip2',
469 default=None,
466 default=None,
470 )
467 )
471 coreconfigitem('experimental', 'bundlecomplevel.gzip',
468 coreconfigitem('experimental', 'bundlecomplevel.gzip',
472 default=None,
469 default=None,
473 )
470 )
474 coreconfigitem('experimental', 'bundlecomplevel.none',
471 coreconfigitem('experimental', 'bundlecomplevel.none',
475 default=None,
472 default=None,
476 )
473 )
477 coreconfigitem('experimental', 'bundlecomplevel.zstd',
474 coreconfigitem('experimental', 'bundlecomplevel.zstd',
478 default=None,
475 default=None,
479 )
476 )
480 coreconfigitem('experimental', 'changegroup3',
477 coreconfigitem('experimental', 'changegroup3',
481 default=False,
478 default=False,
482 )
479 )
483 coreconfigitem('experimental', 'clientcompressionengines',
480 coreconfigitem('experimental', 'clientcompressionengines',
484 default=list,
481 default=list,
485 )
482 )
486 coreconfigitem('experimental', 'copytrace',
483 coreconfigitem('experimental', 'copytrace',
487 default='on',
484 default='on',
488 )
485 )
489 coreconfigitem('experimental', 'copytrace.movecandidateslimit',
486 coreconfigitem('experimental', 'copytrace.movecandidateslimit',
490 default=100,
487 default=100,
491 )
488 )
492 coreconfigitem('experimental', 'copytrace.sourcecommitlimit',
489 coreconfigitem('experimental', 'copytrace.sourcecommitlimit',
493 default=100,
490 default=100,
494 )
491 )
495 coreconfigitem('experimental', 'crecordtest',
492 coreconfigitem('experimental', 'crecordtest',
496 default=None,
493 default=None,
497 )
494 )
498 coreconfigitem('experimental', 'directaccess',
495 coreconfigitem('experimental', 'directaccess',
499 default=False,
496 default=False,
500 )
497 )
501 coreconfigitem('experimental', 'directaccess.revnums',
498 coreconfigitem('experimental', 'directaccess.revnums',
502 default=False,
499 default=False,
503 )
500 )
504 coreconfigitem('experimental', 'editortmpinhg',
501 coreconfigitem('experimental', 'editortmpinhg',
505 default=False,
502 default=False,
506 )
503 )
507 coreconfigitem('experimental', 'evolution',
504 coreconfigitem('experimental', 'evolution',
508 default=list,
505 default=list,
509 )
506 )
510 coreconfigitem('experimental', 'evolution.allowdivergence',
507 coreconfigitem('experimental', 'evolution.allowdivergence',
511 default=False,
508 default=False,
512 alias=[('experimental', 'allowdivergence')]
509 alias=[('experimental', 'allowdivergence')]
513 )
510 )
514 coreconfigitem('experimental', 'evolution.allowunstable',
511 coreconfigitem('experimental', 'evolution.allowunstable',
515 default=None,
512 default=None,
516 )
513 )
517 coreconfigitem('experimental', 'evolution.createmarkers',
514 coreconfigitem('experimental', 'evolution.createmarkers',
518 default=None,
515 default=None,
519 )
516 )
520 coreconfigitem('experimental', 'evolution.effect-flags',
517 coreconfigitem('experimental', 'evolution.effect-flags',
521 default=True,
518 default=True,
522 alias=[('experimental', 'effect-flags')]
519 alias=[('experimental', 'effect-flags')]
523 )
520 )
524 coreconfigitem('experimental', 'evolution.exchange',
521 coreconfigitem('experimental', 'evolution.exchange',
525 default=None,
522 default=None,
526 )
523 )
527 coreconfigitem('experimental', 'evolution.bundle-obsmarker',
524 coreconfigitem('experimental', 'evolution.bundle-obsmarker',
528 default=False,
525 default=False,
529 )
526 )
530 coreconfigitem('experimental', 'evolution.report-instabilities',
527 coreconfigitem('experimental', 'evolution.report-instabilities',
531 default=True,
528 default=True,
532 )
529 )
533 coreconfigitem('experimental', 'evolution.track-operation',
530 coreconfigitem('experimental', 'evolution.track-operation',
534 default=True,
531 default=True,
535 )
532 )
536 coreconfigitem('experimental', 'maxdeltachainspan',
533 coreconfigitem('experimental', 'maxdeltachainspan',
537 default=-1,
534 default=-1,
538 )
535 )
539 coreconfigitem('experimental', 'mergetempdirprefix',
536 coreconfigitem('experimental', 'mergetempdirprefix',
540 default=None,
537 default=None,
541 )
538 )
542 coreconfigitem('experimental', 'mmapindexthreshold',
539 coreconfigitem('experimental', 'mmapindexthreshold',
543 default=None,
540 default=None,
544 )
541 )
545 coreconfigitem('experimental', 'nonnormalparanoidcheck',
542 coreconfigitem('experimental', 'nonnormalparanoidcheck',
546 default=False,
543 default=False,
547 )
544 )
548 coreconfigitem('experimental', 'exportableenviron',
545 coreconfigitem('experimental', 'exportableenviron',
549 default=list,
546 default=list,
550 )
547 )
551 coreconfigitem('experimental', 'extendedheader.index',
548 coreconfigitem('experimental', 'extendedheader.index',
552 default=None,
549 default=None,
553 )
550 )
554 coreconfigitem('experimental', 'extendedheader.similarity',
551 coreconfigitem('experimental', 'extendedheader.similarity',
555 default=False,
552 default=False,
556 )
553 )
557 coreconfigitem('experimental', 'format.compression',
554 coreconfigitem('experimental', 'format.compression',
558 default='zlib',
555 default='zlib',
559 )
556 )
560 coreconfigitem('experimental', 'graphshorten',
557 coreconfigitem('experimental', 'graphshorten',
561 default=False,
558 default=False,
562 )
559 )
563 coreconfigitem('experimental', 'graphstyle.parent',
560 coreconfigitem('experimental', 'graphstyle.parent',
564 default=dynamicdefault,
561 default=dynamicdefault,
565 )
562 )
566 coreconfigitem('experimental', 'graphstyle.missing',
563 coreconfigitem('experimental', 'graphstyle.missing',
567 default=dynamicdefault,
564 default=dynamicdefault,
568 )
565 )
569 coreconfigitem('experimental', 'graphstyle.grandparent',
566 coreconfigitem('experimental', 'graphstyle.grandparent',
570 default=dynamicdefault,
567 default=dynamicdefault,
571 )
568 )
572 coreconfigitem('experimental', 'hook-track-tags',
569 coreconfigitem('experimental', 'hook-track-tags',
573 default=False,
570 default=False,
574 )
571 )
575 coreconfigitem('experimental', 'httppeer.advertise-v2',
572 coreconfigitem('experimental', 'httppeer.advertise-v2',
576 default=False,
573 default=False,
577 )
574 )
578 coreconfigitem('experimental', 'httppostargs',
575 coreconfigitem('experimental', 'httppostargs',
579 default=False,
576 default=False,
580 )
577 )
581 coreconfigitem('experimental', 'mergedriver',
578 coreconfigitem('experimental', 'mergedriver',
582 default=None,
579 default=None,
583 )
580 )
584 coreconfigitem('experimental', 'nointerrupt', default=False)
581 coreconfigitem('experimental', 'nointerrupt', default=False)
585 coreconfigitem('experimental', 'nointerrupt-interactiveonly', default=True)
582 coreconfigitem('experimental', 'nointerrupt-interactiveonly', default=True)
586
583
587 coreconfigitem('experimental', 'obsmarkers-exchange-debug',
584 coreconfigitem('experimental', 'obsmarkers-exchange-debug',
588 default=False,
585 default=False,
589 )
586 )
590 coreconfigitem('experimental', 'remotenames',
587 coreconfigitem('experimental', 'remotenames',
591 default=False,
588 default=False,
592 )
589 )
593 coreconfigitem('experimental', 'removeemptydirs',
590 coreconfigitem('experimental', 'removeemptydirs',
594 default=True,
591 default=True,
595 )
592 )
596 coreconfigitem('experimental', 'revisions.prefixhexnode',
593 coreconfigitem('experimental', 'revisions.prefixhexnode',
597 default=False,
594 default=False,
598 )
595 )
599 coreconfigitem('experimental', 'revlogv2',
596 coreconfigitem('experimental', 'revlogv2',
600 default=None,
597 default=None,
601 )
598 )
602 coreconfigitem('experimental', 'revisions.disambiguatewithin',
599 coreconfigitem('experimental', 'revisions.disambiguatewithin',
603 default=None,
600 default=None,
604 )
601 )
605 coreconfigitem('experimental', 'single-head-per-branch',
602 coreconfigitem('experimental', 'single-head-per-branch',
606 default=False,
603 default=False,
607 )
604 )
608 coreconfigitem('experimental', 'sshserver.support-v2',
605 coreconfigitem('experimental', 'sshserver.support-v2',
609 default=False,
606 default=False,
610 )
607 )
611 coreconfigitem('experimental', 'spacemovesdown',
608 coreconfigitem('experimental', 'spacemovesdown',
612 default=False,
609 default=False,
613 )
610 )
614 coreconfigitem('experimental', 'sparse-read',
611 coreconfigitem('experimental', 'sparse-read',
615 default=False,
612 default=False,
616 )
613 )
617 coreconfigitem('experimental', 'sparse-read.density-threshold',
614 coreconfigitem('experimental', 'sparse-read.density-threshold',
618 default=0.50,
615 default=0.50,
619 )
616 )
620 coreconfigitem('experimental', 'sparse-read.min-gap-size',
617 coreconfigitem('experimental', 'sparse-read.min-gap-size',
621 default='65K',
618 default='65K',
622 )
619 )
623 coreconfigitem('experimental', 'treemanifest',
620 coreconfigitem('experimental', 'treemanifest',
624 default=False,
621 default=False,
625 )
622 )
626 coreconfigitem('experimental', 'update.atomic-file',
623 coreconfigitem('experimental', 'update.atomic-file',
627 default=False,
624 default=False,
628 )
625 )
629 coreconfigitem('experimental', 'sshpeer.advertise-v2',
626 coreconfigitem('experimental', 'sshpeer.advertise-v2',
630 default=False,
627 default=False,
631 )
628 )
632 coreconfigitem('experimental', 'web.apiserver',
629 coreconfigitem('experimental', 'web.apiserver',
633 default=False,
630 default=False,
634 )
631 )
635 coreconfigitem('experimental', 'web.api.http-v2',
632 coreconfigitem('experimental', 'web.api.http-v2',
636 default=False,
633 default=False,
637 )
634 )
638 coreconfigitem('experimental', 'web.api.debugreflect',
635 coreconfigitem('experimental', 'web.api.debugreflect',
639 default=False,
636 default=False,
640 )
637 )
641 coreconfigitem('experimental', 'worker.wdir-get-thread-safe',
638 coreconfigitem('experimental', 'worker.wdir-get-thread-safe',
642 default=False,
639 default=False,
643 )
640 )
644 coreconfigitem('experimental', 'xdiff',
641 coreconfigitem('experimental', 'xdiff',
645 default=False,
642 default=False,
646 )
643 )
647 coreconfigitem('extensions', '.*',
644 coreconfigitem('extensions', '.*',
648 default=None,
645 default=None,
649 generic=True,
646 generic=True,
650 )
647 )
651 coreconfigitem('extdata', '.*',
648 coreconfigitem('extdata', '.*',
652 default=None,
649 default=None,
653 generic=True,
650 generic=True,
654 )
651 )
655 coreconfigitem('format', 'chunkcachesize',
652 coreconfigitem('format', 'chunkcachesize',
656 default=None,
653 default=None,
657 )
654 )
658 coreconfigitem('format', 'dotencode',
655 coreconfigitem('format', 'dotencode',
659 default=True,
656 default=True,
660 )
657 )
661 coreconfigitem('format', 'generaldelta',
658 coreconfigitem('format', 'generaldelta',
662 default=False,
659 default=False,
663 )
660 )
664 coreconfigitem('format', 'manifestcachesize',
661 coreconfigitem('format', 'manifestcachesize',
665 default=None,
662 default=None,
666 )
663 )
667 coreconfigitem('format', 'maxchainlen',
664 coreconfigitem('format', 'maxchainlen',
668 default=dynamicdefault,
665 default=dynamicdefault,
669 )
666 )
670 coreconfigitem('format', 'obsstore-version',
667 coreconfigitem('format', 'obsstore-version',
671 default=None,
668 default=None,
672 )
669 )
673 coreconfigitem('format', 'sparse-revlog',
670 coreconfigitem('format', 'sparse-revlog',
674 default=False,
671 default=False,
675 )
672 )
676 coreconfigitem('format', 'usefncache',
673 coreconfigitem('format', 'usefncache',
677 default=True,
674 default=True,
678 )
675 )
679 coreconfigitem('format', 'usegeneraldelta',
676 coreconfigitem('format', 'usegeneraldelta',
680 default=True,
677 default=True,
681 )
678 )
682 coreconfigitem('format', 'usestore',
679 coreconfigitem('format', 'usestore',
683 default=True,
680 default=True,
684 )
681 )
685 coreconfigitem('format', 'internal-phase',
682 coreconfigitem('format', 'internal-phase',
686 default=False,
683 default=False,
687 )
684 )
688 coreconfigitem('fsmonitor', 'warn_when_unused',
685 coreconfigitem('fsmonitor', 'warn_when_unused',
689 default=True,
686 default=True,
690 )
687 )
691 coreconfigitem('fsmonitor', 'warn_update_file_count',
688 coreconfigitem('fsmonitor', 'warn_update_file_count',
692 default=50000,
689 default=50000,
693 )
690 )
694 coreconfigitem('hooks', '.*',
691 coreconfigitem('hooks', '.*',
695 default=dynamicdefault,
692 default=dynamicdefault,
696 generic=True,
693 generic=True,
697 )
694 )
698 coreconfigitem('hgweb-paths', '.*',
695 coreconfigitem('hgweb-paths', '.*',
699 default=list,
696 default=list,
700 generic=True,
697 generic=True,
701 )
698 )
702 coreconfigitem('hostfingerprints', '.*',
699 coreconfigitem('hostfingerprints', '.*',
703 default=list,
700 default=list,
704 generic=True,
701 generic=True,
705 )
702 )
706 coreconfigitem('hostsecurity', 'ciphers',
703 coreconfigitem('hostsecurity', 'ciphers',
707 default=None,
704 default=None,
708 )
705 )
709 coreconfigitem('hostsecurity', 'disabletls10warning',
706 coreconfigitem('hostsecurity', 'disabletls10warning',
710 default=False,
707 default=False,
711 )
708 )
712 coreconfigitem('hostsecurity', 'minimumprotocol',
709 coreconfigitem('hostsecurity', 'minimumprotocol',
713 default=dynamicdefault,
710 default=dynamicdefault,
714 )
711 )
715 coreconfigitem('hostsecurity', '.*:minimumprotocol$',
712 coreconfigitem('hostsecurity', '.*:minimumprotocol$',
716 default=dynamicdefault,
713 default=dynamicdefault,
717 generic=True,
714 generic=True,
718 )
715 )
719 coreconfigitem('hostsecurity', '.*:ciphers$',
716 coreconfigitem('hostsecurity', '.*:ciphers$',
720 default=dynamicdefault,
717 default=dynamicdefault,
721 generic=True,
718 generic=True,
722 )
719 )
723 coreconfigitem('hostsecurity', '.*:fingerprints$',
720 coreconfigitem('hostsecurity', '.*:fingerprints$',
724 default=list,
721 default=list,
725 generic=True,
722 generic=True,
726 )
723 )
727 coreconfigitem('hostsecurity', '.*:verifycertsfile$',
724 coreconfigitem('hostsecurity', '.*:verifycertsfile$',
728 default=None,
725 default=None,
729 generic=True,
726 generic=True,
730 )
727 )
731
728
732 coreconfigitem('http_proxy', 'always',
729 coreconfigitem('http_proxy', 'always',
733 default=False,
730 default=False,
734 )
731 )
735 coreconfigitem('http_proxy', 'host',
732 coreconfigitem('http_proxy', 'host',
736 default=None,
733 default=None,
737 )
734 )
738 coreconfigitem('http_proxy', 'no',
735 coreconfigitem('http_proxy', 'no',
739 default=list,
736 default=list,
740 )
737 )
741 coreconfigitem('http_proxy', 'passwd',
738 coreconfigitem('http_proxy', 'passwd',
742 default=None,
739 default=None,
743 )
740 )
744 coreconfigitem('http_proxy', 'user',
741 coreconfigitem('http_proxy', 'user',
745 default=None,
742 default=None,
746 )
743 )
747 coreconfigitem('logtoprocess', 'commandexception',
744 coreconfigitem('logtoprocess', 'commandexception',
748 default=None,
745 default=None,
749 )
746 )
750 coreconfigitem('logtoprocess', 'commandfinish',
747 coreconfigitem('logtoprocess', 'commandfinish',
751 default=None,
748 default=None,
752 )
749 )
753 coreconfigitem('logtoprocess', 'command',
750 coreconfigitem('logtoprocess', 'command',
754 default=None,
751 default=None,
755 )
752 )
756 coreconfigitem('logtoprocess', 'develwarn',
753 coreconfigitem('logtoprocess', 'develwarn',
757 default=None,
754 default=None,
758 )
755 )
759 coreconfigitem('logtoprocess', 'uiblocked',
756 coreconfigitem('logtoprocess', 'uiblocked',
760 default=None,
757 default=None,
761 )
758 )
762 coreconfigitem('merge', 'checkunknown',
759 coreconfigitem('merge', 'checkunknown',
763 default='abort',
760 default='abort',
764 )
761 )
765 coreconfigitem('merge', 'checkignored',
762 coreconfigitem('merge', 'checkignored',
766 default='abort',
763 default='abort',
767 )
764 )
768 coreconfigitem('experimental', 'merge.checkpathconflicts',
765 coreconfigitem('experimental', 'merge.checkpathconflicts',
769 default=False,
766 default=False,
770 )
767 )
771 coreconfigitem('merge', 'followcopies',
768 coreconfigitem('merge', 'followcopies',
772 default=True,
769 default=True,
773 )
770 )
774 coreconfigitem('merge', 'on-failure',
771 coreconfigitem('merge', 'on-failure',
775 default='continue',
772 default='continue',
776 )
773 )
777 coreconfigitem('merge', 'preferancestor',
774 coreconfigitem('merge', 'preferancestor',
778 default=lambda: ['*'],
775 default=lambda: ['*'],
779 )
776 )
780 coreconfigitem('merge', 'strict-capability-check',
777 coreconfigitem('merge', 'strict-capability-check',
781 default=False,
778 default=False,
782 )
779 )
783 coreconfigitem('merge-tools', '.*',
780 coreconfigitem('merge-tools', '.*',
784 default=None,
781 default=None,
785 generic=True,
782 generic=True,
786 )
783 )
787 coreconfigitem('merge-tools', br'.*\.args$',
784 coreconfigitem('merge-tools', br'.*\.args$',
788 default="$local $base $other",
785 default="$local $base $other",
789 generic=True,
786 generic=True,
790 priority=-1,
787 priority=-1,
791 )
788 )
792 coreconfigitem('merge-tools', br'.*\.binary$',
789 coreconfigitem('merge-tools', br'.*\.binary$',
793 default=False,
790 default=False,
794 generic=True,
791 generic=True,
795 priority=-1,
792 priority=-1,
796 )
793 )
797 coreconfigitem('merge-tools', br'.*\.check$',
794 coreconfigitem('merge-tools', br'.*\.check$',
798 default=list,
795 default=list,
799 generic=True,
796 generic=True,
800 priority=-1,
797 priority=-1,
801 )
798 )
802 coreconfigitem('merge-tools', br'.*\.checkchanged$',
799 coreconfigitem('merge-tools', br'.*\.checkchanged$',
803 default=False,
800 default=False,
804 generic=True,
801 generic=True,
805 priority=-1,
802 priority=-1,
806 )
803 )
807 coreconfigitem('merge-tools', br'.*\.executable$',
804 coreconfigitem('merge-tools', br'.*\.executable$',
808 default=dynamicdefault,
805 default=dynamicdefault,
809 generic=True,
806 generic=True,
810 priority=-1,
807 priority=-1,
811 )
808 )
812 coreconfigitem('merge-tools', br'.*\.fixeol$',
809 coreconfigitem('merge-tools', br'.*\.fixeol$',
813 default=False,
810 default=False,
814 generic=True,
811 generic=True,
815 priority=-1,
812 priority=-1,
816 )
813 )
817 coreconfigitem('merge-tools', br'.*\.gui$',
814 coreconfigitem('merge-tools', br'.*\.gui$',
818 default=False,
815 default=False,
819 generic=True,
816 generic=True,
820 priority=-1,
817 priority=-1,
821 )
818 )
822 coreconfigitem('merge-tools', br'.*\.mergemarkers$',
819 coreconfigitem('merge-tools', br'.*\.mergemarkers$',
823 default='basic',
820 default='basic',
824 generic=True,
821 generic=True,
825 priority=-1,
822 priority=-1,
826 )
823 )
827 coreconfigitem('merge-tools', br'.*\.mergemarkertemplate$',
824 coreconfigitem('merge-tools', br'.*\.mergemarkertemplate$',
828 default=dynamicdefault, # take from ui.mergemarkertemplate
825 default=dynamicdefault, # take from ui.mergemarkertemplate
829 generic=True,
826 generic=True,
830 priority=-1,
827 priority=-1,
831 )
828 )
832 coreconfigitem('merge-tools', br'.*\.priority$',
829 coreconfigitem('merge-tools', br'.*\.priority$',
833 default=0,
830 default=0,
834 generic=True,
831 generic=True,
835 priority=-1,
832 priority=-1,
836 )
833 )
837 coreconfigitem('merge-tools', br'.*\.premerge$',
834 coreconfigitem('merge-tools', br'.*\.premerge$',
838 default=dynamicdefault,
835 default=dynamicdefault,
839 generic=True,
836 generic=True,
840 priority=-1,
837 priority=-1,
841 )
838 )
842 coreconfigitem('merge-tools', br'.*\.symlink$',
839 coreconfigitem('merge-tools', br'.*\.symlink$',
843 default=False,
840 default=False,
844 generic=True,
841 generic=True,
845 priority=-1,
842 priority=-1,
846 )
843 )
847 coreconfigitem('pager', 'attend-.*',
844 coreconfigitem('pager', 'attend-.*',
848 default=dynamicdefault,
845 default=dynamicdefault,
849 generic=True,
846 generic=True,
850 )
847 )
851 coreconfigitem('pager', 'ignore',
848 coreconfigitem('pager', 'ignore',
852 default=list,
849 default=list,
853 )
850 )
854 coreconfigitem('pager', 'pager',
851 coreconfigitem('pager', 'pager',
855 default=dynamicdefault,
852 default=dynamicdefault,
856 )
853 )
857 coreconfigitem('patch', 'eol',
854 coreconfigitem('patch', 'eol',
858 default='strict',
855 default='strict',
859 )
856 )
860 coreconfigitem('patch', 'fuzz',
857 coreconfigitem('patch', 'fuzz',
861 default=2,
858 default=2,
862 )
859 )
863 coreconfigitem('paths', 'default',
860 coreconfigitem('paths', 'default',
864 default=None,
861 default=None,
865 )
862 )
866 coreconfigitem('paths', 'default-push',
863 coreconfigitem('paths', 'default-push',
867 default=None,
864 default=None,
868 )
865 )
869 coreconfigitem('paths', '.*',
866 coreconfigitem('paths', '.*',
870 default=None,
867 default=None,
871 generic=True,
868 generic=True,
872 )
869 )
873 coreconfigitem('phases', 'checksubrepos',
870 coreconfigitem('phases', 'checksubrepos',
874 default='follow',
871 default='follow',
875 )
872 )
876 coreconfigitem('phases', 'new-commit',
873 coreconfigitem('phases', 'new-commit',
877 default='draft',
874 default='draft',
878 )
875 )
879 coreconfigitem('phases', 'publish',
876 coreconfigitem('phases', 'publish',
880 default=True,
877 default=True,
881 )
878 )
882 coreconfigitem('profiling', 'enabled',
879 coreconfigitem('profiling', 'enabled',
883 default=False,
880 default=False,
884 )
881 )
885 coreconfigitem('profiling', 'format',
882 coreconfigitem('profiling', 'format',
886 default='text',
883 default='text',
887 )
884 )
888 coreconfigitem('profiling', 'freq',
885 coreconfigitem('profiling', 'freq',
889 default=1000,
886 default=1000,
890 )
887 )
891 coreconfigitem('profiling', 'limit',
888 coreconfigitem('profiling', 'limit',
892 default=30,
889 default=30,
893 )
890 )
894 coreconfigitem('profiling', 'nested',
891 coreconfigitem('profiling', 'nested',
895 default=0,
892 default=0,
896 )
893 )
897 coreconfigitem('profiling', 'output',
894 coreconfigitem('profiling', 'output',
898 default=None,
895 default=None,
899 )
896 )
900 coreconfigitem('profiling', 'showmax',
897 coreconfigitem('profiling', 'showmax',
901 default=0.999,
898 default=0.999,
902 )
899 )
903 coreconfigitem('profiling', 'showmin',
900 coreconfigitem('profiling', 'showmin',
904 default=dynamicdefault,
901 default=dynamicdefault,
905 )
902 )
906 coreconfigitem('profiling', 'sort',
903 coreconfigitem('profiling', 'sort',
907 default='inlinetime',
904 default='inlinetime',
908 )
905 )
909 coreconfigitem('profiling', 'statformat',
906 coreconfigitem('profiling', 'statformat',
910 default='hotpath',
907 default='hotpath',
911 )
908 )
912 coreconfigitem('profiling', 'time-track',
909 coreconfigitem('profiling', 'time-track',
913 default='cpu',
910 default='cpu',
914 )
911 )
915 coreconfigitem('profiling', 'type',
912 coreconfigitem('profiling', 'type',
916 default='stat',
913 default='stat',
917 )
914 )
918 coreconfigitem('progress', 'assume-tty',
915 coreconfigitem('progress', 'assume-tty',
919 default=False,
916 default=False,
920 )
917 )
921 coreconfigitem('progress', 'changedelay',
918 coreconfigitem('progress', 'changedelay',
922 default=1,
919 default=1,
923 )
920 )
924 coreconfigitem('progress', 'clear-complete',
921 coreconfigitem('progress', 'clear-complete',
925 default=True,
922 default=True,
926 )
923 )
927 coreconfigitem('progress', 'debug',
924 coreconfigitem('progress', 'debug',
928 default=False,
925 default=False,
929 )
926 )
930 coreconfigitem('progress', 'delay',
927 coreconfigitem('progress', 'delay',
931 default=3,
928 default=3,
932 )
929 )
933 coreconfigitem('progress', 'disable',
930 coreconfigitem('progress', 'disable',
934 default=False,
931 default=False,
935 )
932 )
936 coreconfigitem('progress', 'estimateinterval',
933 coreconfigitem('progress', 'estimateinterval',
937 default=60.0,
934 default=60.0,
938 )
935 )
939 coreconfigitem('progress', 'format',
936 coreconfigitem('progress', 'format',
940 default=lambda: ['topic', 'bar', 'number', 'estimate'],
937 default=lambda: ['topic', 'bar', 'number', 'estimate'],
941 )
938 )
942 coreconfigitem('progress', 'refresh',
939 coreconfigitem('progress', 'refresh',
943 default=0.1,
940 default=0.1,
944 )
941 )
945 coreconfigitem('progress', 'width',
942 coreconfigitem('progress', 'width',
946 default=dynamicdefault,
943 default=dynamicdefault,
947 )
944 )
948 coreconfigitem('push', 'pushvars.server',
945 coreconfigitem('push', 'pushvars.server',
949 default=False,
946 default=False,
950 )
947 )
951 coreconfigitem('storage', 'revlog.optimize-delta-parent-choice',
948 coreconfigitem('storage', 'revlog.optimize-delta-parent-choice',
952 default=True,
949 default=True,
953 alias=[('format', 'aggressivemergedeltas')],
950 alias=[('format', 'aggressivemergedeltas')],
954 )
951 )
955 coreconfigitem('server', 'bookmarks-pushkey-compat',
952 coreconfigitem('server', 'bookmarks-pushkey-compat',
956 default=True,
953 default=True,
957 )
954 )
958 coreconfigitem('server', 'bundle1',
955 coreconfigitem('server', 'bundle1',
959 default=True,
956 default=True,
960 )
957 )
961 coreconfigitem('server', 'bundle1gd',
958 coreconfigitem('server', 'bundle1gd',
962 default=None,
959 default=None,
963 )
960 )
964 coreconfigitem('server', 'bundle1.pull',
961 coreconfigitem('server', 'bundle1.pull',
965 default=None,
962 default=None,
966 )
963 )
967 coreconfigitem('server', 'bundle1gd.pull',
964 coreconfigitem('server', 'bundle1gd.pull',
968 default=None,
965 default=None,
969 )
966 )
970 coreconfigitem('server', 'bundle1.push',
967 coreconfigitem('server', 'bundle1.push',
971 default=None,
968 default=None,
972 )
969 )
973 coreconfigitem('server', 'bundle1gd.push',
970 coreconfigitem('server', 'bundle1gd.push',
974 default=None,
971 default=None,
975 )
972 )
973 coreconfigitem('server', 'bundle2.stream',
974 default=False,
975 alias=[('experimental', 'bundle2.stream')]
976 )
976 coreconfigitem('server', 'compressionengines',
977 coreconfigitem('server', 'compressionengines',
977 default=list,
978 default=list,
978 )
979 )
979 coreconfigitem('server', 'concurrent-push-mode',
980 coreconfigitem('server', 'concurrent-push-mode',
980 default='strict',
981 default='strict',
981 )
982 )
982 coreconfigitem('server', 'disablefullbundle',
983 coreconfigitem('server', 'disablefullbundle',
983 default=False,
984 default=False,
984 )
985 )
985 coreconfigitem('server', 'maxhttpheaderlen',
986 coreconfigitem('server', 'maxhttpheaderlen',
986 default=1024,
987 default=1024,
987 )
988 )
988 coreconfigitem('server', 'pullbundle',
989 coreconfigitem('server', 'pullbundle',
989 default=False,
990 default=False,
990 )
991 )
991 coreconfigitem('server', 'preferuncompressed',
992 coreconfigitem('server', 'preferuncompressed',
992 default=False,
993 default=False,
993 )
994 )
994 coreconfigitem('server', 'streamunbundle',
995 coreconfigitem('server', 'streamunbundle',
995 default=False,
996 default=False,
996 )
997 )
997 coreconfigitem('server', 'uncompressed',
998 coreconfigitem('server', 'uncompressed',
998 default=True,
999 default=True,
999 )
1000 )
1000 coreconfigitem('server', 'uncompressedallowsecret',
1001 coreconfigitem('server', 'uncompressedallowsecret',
1001 default=False,
1002 default=False,
1002 )
1003 )
1003 coreconfigitem('server', 'validate',
1004 coreconfigitem('server', 'validate',
1004 default=False,
1005 default=False,
1005 )
1006 )
1006 coreconfigitem('server', 'zliblevel',
1007 coreconfigitem('server', 'zliblevel',
1007 default=-1,
1008 default=-1,
1008 )
1009 )
1009 coreconfigitem('server', 'zstdlevel',
1010 coreconfigitem('server', 'zstdlevel',
1010 default=3,
1011 default=3,
1011 )
1012 )
1012 coreconfigitem('share', 'pool',
1013 coreconfigitem('share', 'pool',
1013 default=None,
1014 default=None,
1014 )
1015 )
1015 coreconfigitem('share', 'poolnaming',
1016 coreconfigitem('share', 'poolnaming',
1016 default='identity',
1017 default='identity',
1017 )
1018 )
1018 coreconfigitem('smtp', 'host',
1019 coreconfigitem('smtp', 'host',
1019 default=None,
1020 default=None,
1020 )
1021 )
1021 coreconfigitem('smtp', 'local_hostname',
1022 coreconfigitem('smtp', 'local_hostname',
1022 default=None,
1023 default=None,
1023 )
1024 )
1024 coreconfigitem('smtp', 'password',
1025 coreconfigitem('smtp', 'password',
1025 default=None,
1026 default=None,
1026 )
1027 )
1027 coreconfigitem('smtp', 'port',
1028 coreconfigitem('smtp', 'port',
1028 default=dynamicdefault,
1029 default=dynamicdefault,
1029 )
1030 )
1030 coreconfigitem('smtp', 'tls',
1031 coreconfigitem('smtp', 'tls',
1031 default='none',
1032 default='none',
1032 )
1033 )
1033 coreconfigitem('smtp', 'username',
1034 coreconfigitem('smtp', 'username',
1034 default=None,
1035 default=None,
1035 )
1036 )
1036 coreconfigitem('sparse', 'missingwarning',
1037 coreconfigitem('sparse', 'missingwarning',
1037 default=True,
1038 default=True,
1038 )
1039 )
1039 coreconfigitem('subrepos', 'allowed',
1040 coreconfigitem('subrepos', 'allowed',
1040 default=dynamicdefault, # to make backporting simpler
1041 default=dynamicdefault, # to make backporting simpler
1041 )
1042 )
1042 coreconfigitem('subrepos', 'hg:allowed',
1043 coreconfigitem('subrepos', 'hg:allowed',
1043 default=dynamicdefault,
1044 default=dynamicdefault,
1044 )
1045 )
1045 coreconfigitem('subrepos', 'git:allowed',
1046 coreconfigitem('subrepos', 'git:allowed',
1046 default=dynamicdefault,
1047 default=dynamicdefault,
1047 )
1048 )
1048 coreconfigitem('subrepos', 'svn:allowed',
1049 coreconfigitem('subrepos', 'svn:allowed',
1049 default=dynamicdefault,
1050 default=dynamicdefault,
1050 )
1051 )
1051 coreconfigitem('templates', '.*',
1052 coreconfigitem('templates', '.*',
1052 default=None,
1053 default=None,
1053 generic=True,
1054 generic=True,
1054 )
1055 )
1055 coreconfigitem('trusted', 'groups',
1056 coreconfigitem('trusted', 'groups',
1056 default=list,
1057 default=list,
1057 )
1058 )
1058 coreconfigitem('trusted', 'users',
1059 coreconfigitem('trusted', 'users',
1059 default=list,
1060 default=list,
1060 )
1061 )
1061 coreconfigitem('ui', '_usedassubrepo',
1062 coreconfigitem('ui', '_usedassubrepo',
1062 default=False,
1063 default=False,
1063 )
1064 )
1064 coreconfigitem('ui', 'allowemptycommit',
1065 coreconfigitem('ui', 'allowemptycommit',
1065 default=False,
1066 default=False,
1066 )
1067 )
1067 coreconfigitem('ui', 'archivemeta',
1068 coreconfigitem('ui', 'archivemeta',
1068 default=True,
1069 default=True,
1069 )
1070 )
1070 coreconfigitem('ui', 'askusername',
1071 coreconfigitem('ui', 'askusername',
1071 default=False,
1072 default=False,
1072 )
1073 )
1073 coreconfigitem('ui', 'clonebundlefallback',
1074 coreconfigitem('ui', 'clonebundlefallback',
1074 default=False,
1075 default=False,
1075 )
1076 )
1076 coreconfigitem('ui', 'clonebundleprefers',
1077 coreconfigitem('ui', 'clonebundleprefers',
1077 default=list,
1078 default=list,
1078 )
1079 )
1079 coreconfigitem('ui', 'clonebundles',
1080 coreconfigitem('ui', 'clonebundles',
1080 default=True,
1081 default=True,
1081 )
1082 )
1082 coreconfigitem('ui', 'color',
1083 coreconfigitem('ui', 'color',
1083 default='auto',
1084 default='auto',
1084 )
1085 )
1085 coreconfigitem('ui', 'commitsubrepos',
1086 coreconfigitem('ui', 'commitsubrepos',
1086 default=False,
1087 default=False,
1087 )
1088 )
1088 coreconfigitem('ui', 'debug',
1089 coreconfigitem('ui', 'debug',
1089 default=False,
1090 default=False,
1090 )
1091 )
1091 coreconfigitem('ui', 'debugger',
1092 coreconfigitem('ui', 'debugger',
1092 default=None,
1093 default=None,
1093 )
1094 )
1094 coreconfigitem('ui', 'editor',
1095 coreconfigitem('ui', 'editor',
1095 default=dynamicdefault,
1096 default=dynamicdefault,
1096 )
1097 )
1097 coreconfigitem('ui', 'fallbackencoding',
1098 coreconfigitem('ui', 'fallbackencoding',
1098 default=None,
1099 default=None,
1099 )
1100 )
1100 coreconfigitem('ui', 'forcecwd',
1101 coreconfigitem('ui', 'forcecwd',
1101 default=None,
1102 default=None,
1102 )
1103 )
1103 coreconfigitem('ui', 'forcemerge',
1104 coreconfigitem('ui', 'forcemerge',
1104 default=None,
1105 default=None,
1105 )
1106 )
1106 coreconfigitem('ui', 'formatdebug',
1107 coreconfigitem('ui', 'formatdebug',
1107 default=False,
1108 default=False,
1108 )
1109 )
1109 coreconfigitem('ui', 'formatjson',
1110 coreconfigitem('ui', 'formatjson',
1110 default=False,
1111 default=False,
1111 )
1112 )
1112 coreconfigitem('ui', 'formatted',
1113 coreconfigitem('ui', 'formatted',
1113 default=None,
1114 default=None,
1114 )
1115 )
1115 coreconfigitem('ui', 'graphnodetemplate',
1116 coreconfigitem('ui', 'graphnodetemplate',
1116 default=None,
1117 default=None,
1117 )
1118 )
1118 coreconfigitem('ui', 'history-editing-backup',
1119 coreconfigitem('ui', 'history-editing-backup',
1119 default=True,
1120 default=True,
1120 )
1121 )
1121 coreconfigitem('ui', 'interactive',
1122 coreconfigitem('ui', 'interactive',
1122 default=None,
1123 default=None,
1123 )
1124 )
1124 coreconfigitem('ui', 'interface',
1125 coreconfigitem('ui', 'interface',
1125 default=None,
1126 default=None,
1126 )
1127 )
1127 coreconfigitem('ui', 'interface.chunkselector',
1128 coreconfigitem('ui', 'interface.chunkselector',
1128 default=None,
1129 default=None,
1129 )
1130 )
1130 coreconfigitem('ui', 'large-file-limit',
1131 coreconfigitem('ui', 'large-file-limit',
1131 default=10000000,
1132 default=10000000,
1132 )
1133 )
1133 coreconfigitem('ui', 'logblockedtimes',
1134 coreconfigitem('ui', 'logblockedtimes',
1134 default=False,
1135 default=False,
1135 )
1136 )
1136 coreconfigitem('ui', 'logtemplate',
1137 coreconfigitem('ui', 'logtemplate',
1137 default=None,
1138 default=None,
1138 )
1139 )
1139 coreconfigitem('ui', 'merge',
1140 coreconfigitem('ui', 'merge',
1140 default=None,
1141 default=None,
1141 )
1142 )
1142 coreconfigitem('ui', 'mergemarkers',
1143 coreconfigitem('ui', 'mergemarkers',
1143 default='basic',
1144 default='basic',
1144 )
1145 )
1145 coreconfigitem('ui', 'mergemarkertemplate',
1146 coreconfigitem('ui', 'mergemarkertemplate',
1146 default=('{node|short} '
1147 default=('{node|short} '
1147 '{ifeq(tags, "tip", "", '
1148 '{ifeq(tags, "tip", "", '
1148 'ifeq(tags, "", "", "{tags} "))}'
1149 'ifeq(tags, "", "", "{tags} "))}'
1149 '{if(bookmarks, "{bookmarks} ")}'
1150 '{if(bookmarks, "{bookmarks} ")}'
1150 '{ifeq(branch, "default", "", "{branch} ")}'
1151 '{ifeq(branch, "default", "", "{branch} ")}'
1151 '- {author|user}: {desc|firstline}')
1152 '- {author|user}: {desc|firstline}')
1152 )
1153 )
1153 coreconfigitem('ui', 'nontty',
1154 coreconfigitem('ui', 'nontty',
1154 default=False,
1155 default=False,
1155 )
1156 )
1156 coreconfigitem('ui', 'origbackuppath',
1157 coreconfigitem('ui', 'origbackuppath',
1157 default=None,
1158 default=None,
1158 )
1159 )
1159 coreconfigitem('ui', 'paginate',
1160 coreconfigitem('ui', 'paginate',
1160 default=True,
1161 default=True,
1161 )
1162 )
1162 coreconfigitem('ui', 'patch',
1163 coreconfigitem('ui', 'patch',
1163 default=None,
1164 default=None,
1164 )
1165 )
1165 coreconfigitem('ui', 'portablefilenames',
1166 coreconfigitem('ui', 'portablefilenames',
1166 default='warn',
1167 default='warn',
1167 )
1168 )
1168 coreconfigitem('ui', 'promptecho',
1169 coreconfigitem('ui', 'promptecho',
1169 default=False,
1170 default=False,
1170 )
1171 )
1171 coreconfigitem('ui', 'quiet',
1172 coreconfigitem('ui', 'quiet',
1172 default=False,
1173 default=False,
1173 )
1174 )
1174 coreconfigitem('ui', 'quietbookmarkmove',
1175 coreconfigitem('ui', 'quietbookmarkmove',
1175 default=False,
1176 default=False,
1176 )
1177 )
1177 coreconfigitem('ui', 'remotecmd',
1178 coreconfigitem('ui', 'remotecmd',
1178 default='hg',
1179 default='hg',
1179 )
1180 )
1180 coreconfigitem('ui', 'report_untrusted',
1181 coreconfigitem('ui', 'report_untrusted',
1181 default=True,
1182 default=True,
1182 )
1183 )
1183 coreconfigitem('ui', 'rollback',
1184 coreconfigitem('ui', 'rollback',
1184 default=True,
1185 default=True,
1185 )
1186 )
1186 coreconfigitem('ui', 'signal-safe-lock',
1187 coreconfigitem('ui', 'signal-safe-lock',
1187 default=True,
1188 default=True,
1188 )
1189 )
1189 coreconfigitem('ui', 'slash',
1190 coreconfigitem('ui', 'slash',
1190 default=False,
1191 default=False,
1191 )
1192 )
1192 coreconfigitem('ui', 'ssh',
1193 coreconfigitem('ui', 'ssh',
1193 default='ssh',
1194 default='ssh',
1194 )
1195 )
1195 coreconfigitem('ui', 'ssherrorhint',
1196 coreconfigitem('ui', 'ssherrorhint',
1196 default=None,
1197 default=None,
1197 )
1198 )
1198 coreconfigitem('ui', 'statuscopies',
1199 coreconfigitem('ui', 'statuscopies',
1199 default=False,
1200 default=False,
1200 )
1201 )
1201 coreconfigitem('ui', 'strict',
1202 coreconfigitem('ui', 'strict',
1202 default=False,
1203 default=False,
1203 )
1204 )
1204 coreconfigitem('ui', 'style',
1205 coreconfigitem('ui', 'style',
1205 default='',
1206 default='',
1206 )
1207 )
1207 coreconfigitem('ui', 'supportcontact',
1208 coreconfigitem('ui', 'supportcontact',
1208 default=None,
1209 default=None,
1209 )
1210 )
1210 coreconfigitem('ui', 'textwidth',
1211 coreconfigitem('ui', 'textwidth',
1211 default=78,
1212 default=78,
1212 )
1213 )
1213 coreconfigitem('ui', 'timeout',
1214 coreconfigitem('ui', 'timeout',
1214 default='600',
1215 default='600',
1215 )
1216 )
1216 coreconfigitem('ui', 'timeout.warn',
1217 coreconfigitem('ui', 'timeout.warn',
1217 default=0,
1218 default=0,
1218 )
1219 )
1219 coreconfigitem('ui', 'traceback',
1220 coreconfigitem('ui', 'traceback',
1220 default=False,
1221 default=False,
1221 )
1222 )
1222 coreconfigitem('ui', 'tweakdefaults',
1223 coreconfigitem('ui', 'tweakdefaults',
1223 default=False,
1224 default=False,
1224 )
1225 )
1225 coreconfigitem('ui', 'username',
1226 coreconfigitem('ui', 'username',
1226 alias=[('ui', 'user')]
1227 alias=[('ui', 'user')]
1227 )
1228 )
1228 coreconfigitem('ui', 'verbose',
1229 coreconfigitem('ui', 'verbose',
1229 default=False,
1230 default=False,
1230 )
1231 )
1231 coreconfigitem('verify', 'skipflags',
1232 coreconfigitem('verify', 'skipflags',
1232 default=None,
1233 default=None,
1233 )
1234 )
1234 coreconfigitem('web', 'allowbz2',
1235 coreconfigitem('web', 'allowbz2',
1235 default=False,
1236 default=False,
1236 )
1237 )
1237 coreconfigitem('web', 'allowgz',
1238 coreconfigitem('web', 'allowgz',
1238 default=False,
1239 default=False,
1239 )
1240 )
1240 coreconfigitem('web', 'allow-pull',
1241 coreconfigitem('web', 'allow-pull',
1241 alias=[('web', 'allowpull')],
1242 alias=[('web', 'allowpull')],
1242 default=True,
1243 default=True,
1243 )
1244 )
1244 coreconfigitem('web', 'allow-push',
1245 coreconfigitem('web', 'allow-push',
1245 alias=[('web', 'allow_push')],
1246 alias=[('web', 'allow_push')],
1246 default=list,
1247 default=list,
1247 )
1248 )
1248 coreconfigitem('web', 'allowzip',
1249 coreconfigitem('web', 'allowzip',
1249 default=False,
1250 default=False,
1250 )
1251 )
1251 coreconfigitem('web', 'archivesubrepos',
1252 coreconfigitem('web', 'archivesubrepos',
1252 default=False,
1253 default=False,
1253 )
1254 )
1254 coreconfigitem('web', 'cache',
1255 coreconfigitem('web', 'cache',
1255 default=True,
1256 default=True,
1256 )
1257 )
1257 coreconfigitem('web', 'contact',
1258 coreconfigitem('web', 'contact',
1258 default=None,
1259 default=None,
1259 )
1260 )
1260 coreconfigitem('web', 'deny_push',
1261 coreconfigitem('web', 'deny_push',
1261 default=list,
1262 default=list,
1262 )
1263 )
1263 coreconfigitem('web', 'guessmime',
1264 coreconfigitem('web', 'guessmime',
1264 default=False,
1265 default=False,
1265 )
1266 )
1266 coreconfigitem('web', 'hidden',
1267 coreconfigitem('web', 'hidden',
1267 default=False,
1268 default=False,
1268 )
1269 )
1269 coreconfigitem('web', 'labels',
1270 coreconfigitem('web', 'labels',
1270 default=list,
1271 default=list,
1271 )
1272 )
1272 coreconfigitem('web', 'logoimg',
1273 coreconfigitem('web', 'logoimg',
1273 default='hglogo.png',
1274 default='hglogo.png',
1274 )
1275 )
1275 coreconfigitem('web', 'logourl',
1276 coreconfigitem('web', 'logourl',
1276 default='https://mercurial-scm.org/',
1277 default='https://mercurial-scm.org/',
1277 )
1278 )
1278 coreconfigitem('web', 'accesslog',
1279 coreconfigitem('web', 'accesslog',
1279 default='-',
1280 default='-',
1280 )
1281 )
1281 coreconfigitem('web', 'address',
1282 coreconfigitem('web', 'address',
1282 default='',
1283 default='',
1283 )
1284 )
1284 coreconfigitem('web', 'allow-archive',
1285 coreconfigitem('web', 'allow-archive',
1285 alias=[('web', 'allow_archive')],
1286 alias=[('web', 'allow_archive')],
1286 default=list,
1287 default=list,
1287 )
1288 )
1288 coreconfigitem('web', 'allow_read',
1289 coreconfigitem('web', 'allow_read',
1289 default=list,
1290 default=list,
1290 )
1291 )
1291 coreconfigitem('web', 'baseurl',
1292 coreconfigitem('web', 'baseurl',
1292 default=None,
1293 default=None,
1293 )
1294 )
1294 coreconfigitem('web', 'cacerts',
1295 coreconfigitem('web', 'cacerts',
1295 default=None,
1296 default=None,
1296 )
1297 )
1297 coreconfigitem('web', 'certificate',
1298 coreconfigitem('web', 'certificate',
1298 default=None,
1299 default=None,
1299 )
1300 )
1300 coreconfigitem('web', 'collapse',
1301 coreconfigitem('web', 'collapse',
1301 default=False,
1302 default=False,
1302 )
1303 )
1303 coreconfigitem('web', 'csp',
1304 coreconfigitem('web', 'csp',
1304 default=None,
1305 default=None,
1305 )
1306 )
1306 coreconfigitem('web', 'deny_read',
1307 coreconfigitem('web', 'deny_read',
1307 default=list,
1308 default=list,
1308 )
1309 )
1309 coreconfigitem('web', 'descend',
1310 coreconfigitem('web', 'descend',
1310 default=True,
1311 default=True,
1311 )
1312 )
1312 coreconfigitem('web', 'description',
1313 coreconfigitem('web', 'description',
1313 default="",
1314 default="",
1314 )
1315 )
1315 coreconfigitem('web', 'encoding',
1316 coreconfigitem('web', 'encoding',
1316 default=lambda: encoding.encoding,
1317 default=lambda: encoding.encoding,
1317 )
1318 )
1318 coreconfigitem('web', 'errorlog',
1319 coreconfigitem('web', 'errorlog',
1319 default='-',
1320 default='-',
1320 )
1321 )
1321 coreconfigitem('web', 'ipv6',
1322 coreconfigitem('web', 'ipv6',
1322 default=False,
1323 default=False,
1323 )
1324 )
1324 coreconfigitem('web', 'maxchanges',
1325 coreconfigitem('web', 'maxchanges',
1325 default=10,
1326 default=10,
1326 )
1327 )
1327 coreconfigitem('web', 'maxfiles',
1328 coreconfigitem('web', 'maxfiles',
1328 default=10,
1329 default=10,
1329 )
1330 )
1330 coreconfigitem('web', 'maxshortchanges',
1331 coreconfigitem('web', 'maxshortchanges',
1331 default=60,
1332 default=60,
1332 )
1333 )
1333 coreconfigitem('web', 'motd',
1334 coreconfigitem('web', 'motd',
1334 default='',
1335 default='',
1335 )
1336 )
1336 coreconfigitem('web', 'name',
1337 coreconfigitem('web', 'name',
1337 default=dynamicdefault,
1338 default=dynamicdefault,
1338 )
1339 )
1339 coreconfigitem('web', 'port',
1340 coreconfigitem('web', 'port',
1340 default=8000,
1341 default=8000,
1341 )
1342 )
1342 coreconfigitem('web', 'prefix',
1343 coreconfigitem('web', 'prefix',
1343 default='',
1344 default='',
1344 )
1345 )
1345 coreconfigitem('web', 'push_ssl',
1346 coreconfigitem('web', 'push_ssl',
1346 default=True,
1347 default=True,
1347 )
1348 )
1348 coreconfigitem('web', 'refreshinterval',
1349 coreconfigitem('web', 'refreshinterval',
1349 default=20,
1350 default=20,
1350 )
1351 )
1351 coreconfigitem('web', 'server-header',
1352 coreconfigitem('web', 'server-header',
1352 default=None,
1353 default=None,
1353 )
1354 )
1354 coreconfigitem('web', 'staticurl',
1355 coreconfigitem('web', 'staticurl',
1355 default=None,
1356 default=None,
1356 )
1357 )
1357 coreconfigitem('web', 'stripes',
1358 coreconfigitem('web', 'stripes',
1358 default=1,
1359 default=1,
1359 )
1360 )
1360 coreconfigitem('web', 'style',
1361 coreconfigitem('web', 'style',
1361 default='paper',
1362 default='paper',
1362 )
1363 )
1363 coreconfigitem('web', 'templates',
1364 coreconfigitem('web', 'templates',
1364 default=None,
1365 default=None,
1365 )
1366 )
1366 coreconfigitem('web', 'view',
1367 coreconfigitem('web', 'view',
1367 default='served',
1368 default='served',
1368 )
1369 )
1369 coreconfigitem('worker', 'backgroundclose',
1370 coreconfigitem('worker', 'backgroundclose',
1370 default=dynamicdefault,
1371 default=dynamicdefault,
1371 )
1372 )
1372 # Windows defaults to a limit of 512 open files. A buffer of 128
1373 # Windows defaults to a limit of 512 open files. A buffer of 128
1373 # should give us enough headway.
1374 # should give us enough headway.
1374 coreconfigitem('worker', 'backgroundclosemaxqueue',
1375 coreconfigitem('worker', 'backgroundclosemaxqueue',
1375 default=384,
1376 default=384,
1376 )
1377 )
1377 coreconfigitem('worker', 'backgroundcloseminfilecount',
1378 coreconfigitem('worker', 'backgroundcloseminfilecount',
1378 default=2048,
1379 default=2048,
1379 )
1380 )
1380 coreconfigitem('worker', 'backgroundclosethreadcount',
1381 coreconfigitem('worker', 'backgroundclosethreadcount',
1381 default=4,
1382 default=4,
1382 )
1383 )
1383 coreconfigitem('worker', 'enabled',
1384 coreconfigitem('worker', 'enabled',
1384 default=True,
1385 default=True,
1385 )
1386 )
1386 coreconfigitem('worker', 'numcpus',
1387 coreconfigitem('worker', 'numcpus',
1387 default=None,
1388 default=None,
1388 )
1389 )
1389
1390
1390 # Rebase related configuration moved to core because other extension are doing
1391 # Rebase related configuration moved to core because other extension are doing
1391 # strange things. For example, shelve import the extensions to reuse some bit
1392 # strange things. For example, shelve import the extensions to reuse some bit
1392 # without formally loading it.
1393 # without formally loading it.
1393 coreconfigitem('commands', 'rebase.requiredest',
1394 coreconfigitem('commands', 'rebase.requiredest',
1394 default=False,
1395 default=False,
1395 )
1396 )
1396 coreconfigitem('experimental', 'rebaseskipobsolete',
1397 coreconfigitem('experimental', 'rebaseskipobsolete',
1397 default=True,
1398 default=True,
1398 )
1399 )
1399 coreconfigitem('rebase', 'singletransaction',
1400 coreconfigitem('rebase', 'singletransaction',
1400 default=False,
1401 default=False,
1401 )
1402 )
1402 coreconfigitem('rebase', 'experimental.inmemory',
1403 coreconfigitem('rebase', 'experimental.inmemory',
1403 default=False,
1404 default=False,
1404 )
1405 )
@@ -1,2715 +1,2719 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 ``resolve.confirm``
441 ``resolve.confirm``
442 Confirm before performing action if no filename is passed.
442 Confirm before performing action if no filename is passed.
443 (default: False)
443 (default: False)
444
444
445 ``resolve.explicit-re-merge``
445 ``resolve.explicit-re-merge``
446 Require uses of ``hg resolve`` to specify which action it should perform,
446 Require uses of ``hg resolve`` to specify which action it should perform,
447 instead of re-merging files by default.
447 instead of re-merging files by default.
448 (default: False)
448 (default: False)
449
449
450 ``resolve.mark-check``
450 ``resolve.mark-check``
451 Determines what level of checking :hg:`resolve --mark` will perform before
451 Determines what level of checking :hg:`resolve --mark` will perform before
452 marking files as resolved. Valid values are ``none`, ``warn``, and
452 marking files as resolved. Valid values are ``none`, ``warn``, and
453 ``abort``. ``warn`` will output a warning listing the file(s) that still
453 ``abort``. ``warn`` will output a warning listing the file(s) that still
454 have conflict markers in them, but will still mark everything resolved.
454 have conflict markers in them, but will still mark everything resolved.
455 ``abort`` will output the same warning but will not mark things as resolved.
455 ``abort`` will output the same warning but will not mark things as resolved.
456 If --all is passed and this is set to ``abort``, only a warning will be
456 If --all is passed and this is set to ``abort``, only a warning will be
457 shown (an error will not be raised).
457 shown (an error will not be raised).
458 (default: ``none``)
458 (default: ``none``)
459
459
460 ``status.relative``
460 ``status.relative``
461 Make paths in :hg:`status` output relative to the current directory.
461 Make paths in :hg:`status` output relative to the current directory.
462 (default: False)
462 (default: False)
463
463
464 ``status.terse``
464 ``status.terse``
465 Default value for the --terse flag, which condenes status output.
465 Default value for the --terse flag, which condenes status output.
466 (default: empty)
466 (default: empty)
467
467
468 ``update.check``
468 ``update.check``
469 Determines what level of checking :hg:`update` will perform before moving
469 Determines what level of checking :hg:`update` will perform before moving
470 to a destination revision. Valid values are ``abort``, ``none``,
470 to a destination revision. Valid values are ``abort``, ``none``,
471 ``linear``, and ``noconflict``. ``abort`` always fails if the working
471 ``linear``, and ``noconflict``. ``abort`` always fails if the working
472 directory has uncommitted changes. ``none`` performs no checking, and may
472 directory has uncommitted changes. ``none`` performs no checking, and may
473 result in a merge with uncommitted changes. ``linear`` allows any update
473 result in a merge with uncommitted changes. ``linear`` allows any update
474 as long as it follows a straight line in the revision history, and may
474 as long as it follows a straight line in the revision history, and may
475 trigger a merge with uncommitted changes. ``noconflict`` will allow any
475 trigger a merge with uncommitted changes. ``noconflict`` will allow any
476 update which would not trigger a merge with uncommitted changes, if any
476 update which would not trigger a merge with uncommitted changes, if any
477 are present.
477 are present.
478 (default: ``linear``)
478 (default: ``linear``)
479
479
480 ``update.requiredest``
480 ``update.requiredest``
481 Require that the user pass a destination when running :hg:`update`.
481 Require that the user pass a destination when running :hg:`update`.
482 For example, :hg:`update .::` will be allowed, but a plain :hg:`update`
482 For example, :hg:`update .::` will be allowed, but a plain :hg:`update`
483 will be disallowed.
483 will be disallowed.
484 (default: False)
484 (default: False)
485
485
486 ``committemplate``
486 ``committemplate``
487 ------------------
487 ------------------
488
488
489 ``changeset``
489 ``changeset``
490 String: configuration in this section is used as the template to
490 String: configuration in this section is used as the template to
491 customize the text shown in the editor when committing.
491 customize the text shown in the editor when committing.
492
492
493 In addition to pre-defined template keywords, commit log specific one
493 In addition to pre-defined template keywords, commit log specific one
494 below can be used for customization:
494 below can be used for customization:
495
495
496 ``extramsg``
496 ``extramsg``
497 String: Extra message (typically 'Leave message empty to abort
497 String: Extra message (typically 'Leave message empty to abort
498 commit.'). This may be changed by some commands or extensions.
498 commit.'). This may be changed by some commands or extensions.
499
499
500 For example, the template configuration below shows as same text as
500 For example, the template configuration below shows as same text as
501 one shown by default::
501 one shown by default::
502
502
503 [committemplate]
503 [committemplate]
504 changeset = {desc}\n\n
504 changeset = {desc}\n\n
505 HG: Enter commit message. Lines beginning with 'HG:' are removed.
505 HG: Enter commit message. Lines beginning with 'HG:' are removed.
506 HG: {extramsg}
506 HG: {extramsg}
507 HG: --
507 HG: --
508 HG: user: {author}\n{ifeq(p2rev, "-1", "",
508 HG: user: {author}\n{ifeq(p2rev, "-1", "",
509 "HG: branch merge\n")
509 "HG: branch merge\n")
510 }HG: branch '{branch}'\n{if(activebookmark,
510 }HG: branch '{branch}'\n{if(activebookmark,
511 "HG: bookmark '{activebookmark}'\n") }{subrepos %
511 "HG: bookmark '{activebookmark}'\n") }{subrepos %
512 "HG: subrepo {subrepo}\n" }{file_adds %
512 "HG: subrepo {subrepo}\n" }{file_adds %
513 "HG: added {file}\n" }{file_mods %
513 "HG: added {file}\n" }{file_mods %
514 "HG: changed {file}\n" }{file_dels %
514 "HG: changed {file}\n" }{file_dels %
515 "HG: removed {file}\n" }{if(files, "",
515 "HG: removed {file}\n" }{if(files, "",
516 "HG: no files changed\n")}
516 "HG: no files changed\n")}
517
517
518 ``diff()``
518 ``diff()``
519 String: show the diff (see :hg:`help templates` for detail)
519 String: show the diff (see :hg:`help templates` for detail)
520
520
521 Sometimes it is helpful to show the diff of the changeset in the editor without
521 Sometimes it is helpful to show the diff of the changeset in the editor without
522 having to prefix 'HG: ' to each line so that highlighting works correctly. For
522 having to prefix 'HG: ' to each line so that highlighting works correctly. For
523 this, Mercurial provides a special string which will ignore everything below
523 this, Mercurial provides a special string which will ignore everything below
524 it::
524 it::
525
525
526 HG: ------------------------ >8 ------------------------
526 HG: ------------------------ >8 ------------------------
527
527
528 For example, the template configuration below will show the diff below the
528 For example, the template configuration below will show the diff below the
529 extra message::
529 extra message::
530
530
531 [committemplate]
531 [committemplate]
532 changeset = {desc}\n\n
532 changeset = {desc}\n\n
533 HG: Enter commit message. Lines beginning with 'HG:' are removed.
533 HG: Enter commit message. Lines beginning with 'HG:' are removed.
534 HG: {extramsg}
534 HG: {extramsg}
535 HG: ------------------------ >8 ------------------------
535 HG: ------------------------ >8 ------------------------
536 HG: Do not touch the line above.
536 HG: Do not touch the line above.
537 HG: Everything below will be removed.
537 HG: Everything below will be removed.
538 {diff()}
538 {diff()}
539
539
540 .. note::
540 .. note::
541
541
542 For some problematic encodings (see :hg:`help win32mbcs` for
542 For some problematic encodings (see :hg:`help win32mbcs` for
543 detail), this customization should be configured carefully, to
543 detail), this customization should be configured carefully, to
544 avoid showing broken characters.
544 avoid showing broken characters.
545
545
546 For example, if a multibyte character ending with backslash (0x5c) is
546 For example, if a multibyte character ending with backslash (0x5c) is
547 followed by the ASCII character 'n' in the customized template,
547 followed by the ASCII character 'n' in the customized template,
548 the sequence of backslash and 'n' is treated as line-feed unexpectedly
548 the sequence of backslash and 'n' is treated as line-feed unexpectedly
549 (and the multibyte character is broken, too).
549 (and the multibyte character is broken, too).
550
550
551 Customized template is used for commands below (``--edit`` may be
551 Customized template is used for commands below (``--edit`` may be
552 required):
552 required):
553
553
554 - :hg:`backout`
554 - :hg:`backout`
555 - :hg:`commit`
555 - :hg:`commit`
556 - :hg:`fetch` (for merge commit only)
556 - :hg:`fetch` (for merge commit only)
557 - :hg:`graft`
557 - :hg:`graft`
558 - :hg:`histedit`
558 - :hg:`histedit`
559 - :hg:`import`
559 - :hg:`import`
560 - :hg:`qfold`, :hg:`qnew` and :hg:`qrefresh`
560 - :hg:`qfold`, :hg:`qnew` and :hg:`qrefresh`
561 - :hg:`rebase`
561 - :hg:`rebase`
562 - :hg:`shelve`
562 - :hg:`shelve`
563 - :hg:`sign`
563 - :hg:`sign`
564 - :hg:`tag`
564 - :hg:`tag`
565 - :hg:`transplant`
565 - :hg:`transplant`
566
566
567 Configuring items below instead of ``changeset`` allows showing
567 Configuring items below instead of ``changeset`` allows showing
568 customized message only for specific actions, or showing different
568 customized message only for specific actions, or showing different
569 messages for each action.
569 messages for each action.
570
570
571 - ``changeset.backout`` for :hg:`backout`
571 - ``changeset.backout`` for :hg:`backout`
572 - ``changeset.commit.amend.merge`` for :hg:`commit --amend` on merges
572 - ``changeset.commit.amend.merge`` for :hg:`commit --amend` on merges
573 - ``changeset.commit.amend.normal`` for :hg:`commit --amend` on other
573 - ``changeset.commit.amend.normal`` for :hg:`commit --amend` on other
574 - ``changeset.commit.normal.merge`` for :hg:`commit` on merges
574 - ``changeset.commit.normal.merge`` for :hg:`commit` on merges
575 - ``changeset.commit.normal.normal`` for :hg:`commit` on other
575 - ``changeset.commit.normal.normal`` for :hg:`commit` on other
576 - ``changeset.fetch`` for :hg:`fetch` (impling merge commit)
576 - ``changeset.fetch`` for :hg:`fetch` (impling merge commit)
577 - ``changeset.gpg.sign`` for :hg:`sign`
577 - ``changeset.gpg.sign`` for :hg:`sign`
578 - ``changeset.graft`` for :hg:`graft`
578 - ``changeset.graft`` for :hg:`graft`
579 - ``changeset.histedit.edit`` for ``edit`` of :hg:`histedit`
579 - ``changeset.histedit.edit`` for ``edit`` of :hg:`histedit`
580 - ``changeset.histedit.fold`` for ``fold`` of :hg:`histedit`
580 - ``changeset.histedit.fold`` for ``fold`` of :hg:`histedit`
581 - ``changeset.histedit.mess`` for ``mess`` of :hg:`histedit`
581 - ``changeset.histedit.mess`` for ``mess`` of :hg:`histedit`
582 - ``changeset.histedit.pick`` for ``pick`` of :hg:`histedit`
582 - ``changeset.histedit.pick`` for ``pick`` of :hg:`histedit`
583 - ``changeset.import.bypass`` for :hg:`import --bypass`
583 - ``changeset.import.bypass`` for :hg:`import --bypass`
584 - ``changeset.import.normal.merge`` for :hg:`import` on merges
584 - ``changeset.import.normal.merge`` for :hg:`import` on merges
585 - ``changeset.import.normal.normal`` for :hg:`import` on other
585 - ``changeset.import.normal.normal`` for :hg:`import` on other
586 - ``changeset.mq.qnew`` for :hg:`qnew`
586 - ``changeset.mq.qnew`` for :hg:`qnew`
587 - ``changeset.mq.qfold`` for :hg:`qfold`
587 - ``changeset.mq.qfold`` for :hg:`qfold`
588 - ``changeset.mq.qrefresh`` for :hg:`qrefresh`
588 - ``changeset.mq.qrefresh`` for :hg:`qrefresh`
589 - ``changeset.rebase.collapse`` for :hg:`rebase --collapse`
589 - ``changeset.rebase.collapse`` for :hg:`rebase --collapse`
590 - ``changeset.rebase.merge`` for :hg:`rebase` on merges
590 - ``changeset.rebase.merge`` for :hg:`rebase` on merges
591 - ``changeset.rebase.normal`` for :hg:`rebase` on other
591 - ``changeset.rebase.normal`` for :hg:`rebase` on other
592 - ``changeset.shelve.shelve`` for :hg:`shelve`
592 - ``changeset.shelve.shelve`` for :hg:`shelve`
593 - ``changeset.tag.add`` for :hg:`tag` without ``--remove``
593 - ``changeset.tag.add`` for :hg:`tag` without ``--remove``
594 - ``changeset.tag.remove`` for :hg:`tag --remove`
594 - ``changeset.tag.remove`` for :hg:`tag --remove`
595 - ``changeset.transplant.merge`` for :hg:`transplant` on merges
595 - ``changeset.transplant.merge`` for :hg:`transplant` on merges
596 - ``changeset.transplant.normal`` for :hg:`transplant` on other
596 - ``changeset.transplant.normal`` for :hg:`transplant` on other
597
597
598 These dot-separated lists of names are treated as hierarchical ones.
598 These dot-separated lists of names are treated as hierarchical ones.
599 For example, ``changeset.tag.remove`` customizes the commit message
599 For example, ``changeset.tag.remove`` customizes the commit message
600 only for :hg:`tag --remove`, but ``changeset.tag`` customizes the
600 only for :hg:`tag --remove`, but ``changeset.tag`` customizes the
601 commit message for :hg:`tag` regardless of ``--remove`` option.
601 commit message for :hg:`tag` regardless of ``--remove`` option.
602
602
603 When the external editor is invoked for a commit, the corresponding
603 When the external editor is invoked for a commit, the corresponding
604 dot-separated list of names without the ``changeset.`` prefix
604 dot-separated list of names without the ``changeset.`` prefix
605 (e.g. ``commit.normal.normal``) is in the ``HGEDITFORM`` environment
605 (e.g. ``commit.normal.normal``) is in the ``HGEDITFORM`` environment
606 variable.
606 variable.
607
607
608 In this section, items other than ``changeset`` can be referred from
608 In this section, items other than ``changeset`` can be referred from
609 others. For example, the configuration to list committed files up
609 others. For example, the configuration to list committed files up
610 below can be referred as ``{listupfiles}``::
610 below can be referred as ``{listupfiles}``::
611
611
612 [committemplate]
612 [committemplate]
613 listupfiles = {file_adds %
613 listupfiles = {file_adds %
614 "HG: added {file}\n" }{file_mods %
614 "HG: added {file}\n" }{file_mods %
615 "HG: changed {file}\n" }{file_dels %
615 "HG: changed {file}\n" }{file_dels %
616 "HG: removed {file}\n" }{if(files, "",
616 "HG: removed {file}\n" }{if(files, "",
617 "HG: no files changed\n")}
617 "HG: no files changed\n")}
618
618
619 ``decode/encode``
619 ``decode/encode``
620 -----------------
620 -----------------
621
621
622 Filters for transforming files on checkout/checkin. This would
622 Filters for transforming files on checkout/checkin. This would
623 typically be used for newline processing or other
623 typically be used for newline processing or other
624 localization/canonicalization of files.
624 localization/canonicalization of files.
625
625
626 Filters consist of a filter pattern followed by a filter command.
626 Filters consist of a filter pattern followed by a filter command.
627 Filter patterns are globs by default, rooted at the repository root.
627 Filter patterns are globs by default, rooted at the repository root.
628 For example, to match any file ending in ``.txt`` in the root
628 For example, to match any file ending in ``.txt`` in the root
629 directory only, use the pattern ``*.txt``. To match any file ending
629 directory only, use the pattern ``*.txt``. To match any file ending
630 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
630 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
631 For each file only the first matching filter applies.
631 For each file only the first matching filter applies.
632
632
633 The filter command can start with a specifier, either ``pipe:`` or
633 The filter command can start with a specifier, either ``pipe:`` or
634 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
634 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
635
635
636 A ``pipe:`` command must accept data on stdin and return the transformed
636 A ``pipe:`` command must accept data on stdin and return the transformed
637 data on stdout.
637 data on stdout.
638
638
639 Pipe example::
639 Pipe example::
640
640
641 [encode]
641 [encode]
642 # uncompress gzip files on checkin to improve delta compression
642 # uncompress gzip files on checkin to improve delta compression
643 # note: not necessarily a good idea, just an example
643 # note: not necessarily a good idea, just an example
644 *.gz = pipe: gunzip
644 *.gz = pipe: gunzip
645
645
646 [decode]
646 [decode]
647 # recompress gzip files when writing them to the working dir (we
647 # recompress gzip files when writing them to the working dir (we
648 # can safely omit "pipe:", because it's the default)
648 # can safely omit "pipe:", because it's the default)
649 *.gz = gzip
649 *.gz = gzip
650
650
651 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
651 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
652 with the name of a temporary file that contains the data to be
652 with the name of a temporary file that contains the data to be
653 filtered by the command. The string ``OUTFILE`` is replaced with the name
653 filtered by the command. The string ``OUTFILE`` is replaced with the name
654 of an empty temporary file, where the filtered data must be written by
654 of an empty temporary file, where the filtered data must be written by
655 the command.
655 the command.
656
656
657 .. container:: windows
657 .. container:: windows
658
658
659 .. note::
659 .. note::
660
660
661 The tempfile mechanism is recommended for Windows systems,
661 The tempfile mechanism is recommended for Windows systems,
662 where the standard shell I/O redirection operators often have
662 where the standard shell I/O redirection operators often have
663 strange effects and may corrupt the contents of your files.
663 strange effects and may corrupt the contents of your files.
664
664
665 This filter mechanism is used internally by the ``eol`` extension to
665 This filter mechanism is used internally by the ``eol`` extension to
666 translate line ending characters between Windows (CRLF) and Unix (LF)
666 translate line ending characters between Windows (CRLF) and Unix (LF)
667 format. We suggest you use the ``eol`` extension for convenience.
667 format. We suggest you use the ``eol`` extension for convenience.
668
668
669
669
670 ``defaults``
670 ``defaults``
671 ------------
671 ------------
672
672
673 (defaults are deprecated. Don't use them. Use aliases instead.)
673 (defaults are deprecated. Don't use them. Use aliases instead.)
674
674
675 Use the ``[defaults]`` section to define command defaults, i.e. the
675 Use the ``[defaults]`` section to define command defaults, i.e. the
676 default options/arguments to pass to the specified commands.
676 default options/arguments to pass to the specified commands.
677
677
678 The following example makes :hg:`log` run in verbose mode, and
678 The following example makes :hg:`log` run in verbose mode, and
679 :hg:`status` show only the modified files, by default::
679 :hg:`status` show only the modified files, by default::
680
680
681 [defaults]
681 [defaults]
682 log = -v
682 log = -v
683 status = -m
683 status = -m
684
684
685 The actual commands, instead of their aliases, must be used when
685 The actual commands, instead of their aliases, must be used when
686 defining command defaults. The command defaults will also be applied
686 defining command defaults. The command defaults will also be applied
687 to the aliases of the commands defined.
687 to the aliases of the commands defined.
688
688
689
689
690 ``diff``
690 ``diff``
691 --------
691 --------
692
692
693 Settings used when displaying diffs. Everything except for ``unified``
693 Settings used when displaying diffs. Everything except for ``unified``
694 is a Boolean and defaults to False. See :hg:`help config.annotate`
694 is a Boolean and defaults to False. See :hg:`help config.annotate`
695 for related options for the annotate command.
695 for related options for the annotate command.
696
696
697 ``git``
697 ``git``
698 Use git extended diff format.
698 Use git extended diff format.
699
699
700 ``nobinary``
700 ``nobinary``
701 Omit git binary patches.
701 Omit git binary patches.
702
702
703 ``nodates``
703 ``nodates``
704 Don't include dates in diff headers.
704 Don't include dates in diff headers.
705
705
706 ``noprefix``
706 ``noprefix``
707 Omit 'a/' and 'b/' prefixes from filenames. Ignored in plain mode.
707 Omit 'a/' and 'b/' prefixes from filenames. Ignored in plain mode.
708
708
709 ``showfunc``
709 ``showfunc``
710 Show which function each change is in.
710 Show which function each change is in.
711
711
712 ``ignorews``
712 ``ignorews``
713 Ignore white space when comparing lines.
713 Ignore white space when comparing lines.
714
714
715 ``ignorewsamount``
715 ``ignorewsamount``
716 Ignore changes in the amount of white space.
716 Ignore changes in the amount of white space.
717
717
718 ``ignoreblanklines``
718 ``ignoreblanklines``
719 Ignore changes whose lines are all blank.
719 Ignore changes whose lines are all blank.
720
720
721 ``unified``
721 ``unified``
722 Number of lines of context to show.
722 Number of lines of context to show.
723
723
724 ``word-diff``
724 ``word-diff``
725 Highlight changed words.
725 Highlight changed words.
726
726
727 ``email``
727 ``email``
728 ---------
728 ---------
729
729
730 Settings for extensions that send email messages.
730 Settings for extensions that send email messages.
731
731
732 ``from``
732 ``from``
733 Optional. Email address to use in "From" header and SMTP envelope
733 Optional. Email address to use in "From" header and SMTP envelope
734 of outgoing messages.
734 of outgoing messages.
735
735
736 ``to``
736 ``to``
737 Optional. Comma-separated list of recipients' email addresses.
737 Optional. Comma-separated list of recipients' email addresses.
738
738
739 ``cc``
739 ``cc``
740 Optional. Comma-separated list of carbon copy recipients'
740 Optional. Comma-separated list of carbon copy recipients'
741 email addresses.
741 email addresses.
742
742
743 ``bcc``
743 ``bcc``
744 Optional. Comma-separated list of blind carbon copy recipients'
744 Optional. Comma-separated list of blind carbon copy recipients'
745 email addresses.
745 email addresses.
746
746
747 ``method``
747 ``method``
748 Optional. Method to use to send email messages. If value is ``smtp``
748 Optional. Method to use to send email messages. If value is ``smtp``
749 (default), use SMTP (see the ``[smtp]`` section for configuration).
749 (default), use SMTP (see the ``[smtp]`` section for configuration).
750 Otherwise, use as name of program to run that acts like sendmail
750 Otherwise, use as name of program to run that acts like sendmail
751 (takes ``-f`` option for sender, list of recipients on command line,
751 (takes ``-f`` option for sender, list of recipients on command line,
752 message on stdin). Normally, setting this to ``sendmail`` or
752 message on stdin). Normally, setting this to ``sendmail`` or
753 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
753 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
754
754
755 ``charsets``
755 ``charsets``
756 Optional. Comma-separated list of character sets considered
756 Optional. Comma-separated list of character sets considered
757 convenient for recipients. Addresses, headers, and parts not
757 convenient for recipients. Addresses, headers, and parts not
758 containing patches of outgoing messages will be encoded in the
758 containing patches of outgoing messages will be encoded in the
759 first character set to which conversion from local encoding
759 first character set to which conversion from local encoding
760 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
760 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
761 conversion fails, the text in question is sent as is.
761 conversion fails, the text in question is sent as is.
762 (default: '')
762 (default: '')
763
763
764 Order of outgoing email character sets:
764 Order of outgoing email character sets:
765
765
766 1. ``us-ascii``: always first, regardless of settings
766 1. ``us-ascii``: always first, regardless of settings
767 2. ``email.charsets``: in order given by user
767 2. ``email.charsets``: in order given by user
768 3. ``ui.fallbackencoding``: if not in email.charsets
768 3. ``ui.fallbackencoding``: if not in email.charsets
769 4. ``$HGENCODING``: if not in email.charsets
769 4. ``$HGENCODING``: if not in email.charsets
770 5. ``utf-8``: always last, regardless of settings
770 5. ``utf-8``: always last, regardless of settings
771
771
772 Email example::
772 Email example::
773
773
774 [email]
774 [email]
775 from = Joseph User <joe.user@example.com>
775 from = Joseph User <joe.user@example.com>
776 method = /usr/sbin/sendmail
776 method = /usr/sbin/sendmail
777 # charsets for western Europeans
777 # charsets for western Europeans
778 # us-ascii, utf-8 omitted, as they are tried first and last
778 # us-ascii, utf-8 omitted, as they are tried first and last
779 charsets = iso-8859-1, iso-8859-15, windows-1252
779 charsets = iso-8859-1, iso-8859-15, windows-1252
780
780
781
781
782 ``extensions``
782 ``extensions``
783 --------------
783 --------------
784
784
785 Mercurial has an extension mechanism for adding new features. To
785 Mercurial has an extension mechanism for adding new features. To
786 enable an extension, create an entry for it in this section.
786 enable an extension, create an entry for it in this section.
787
787
788 If you know that the extension is already in Python's search path,
788 If you know that the extension is already in Python's search path,
789 you can give the name of the module, followed by ``=``, with nothing
789 you can give the name of the module, followed by ``=``, with nothing
790 after the ``=``.
790 after the ``=``.
791
791
792 Otherwise, give a name that you choose, followed by ``=``, followed by
792 Otherwise, give a name that you choose, followed by ``=``, followed by
793 the path to the ``.py`` file (including the file name extension) that
793 the path to the ``.py`` file (including the file name extension) that
794 defines the extension.
794 defines the extension.
795
795
796 To explicitly disable an extension that is enabled in an hgrc of
796 To explicitly disable an extension that is enabled in an hgrc of
797 broader scope, prepend its path with ``!``, as in ``foo = !/ext/path``
797 broader scope, prepend its path with ``!``, as in ``foo = !/ext/path``
798 or ``foo = !`` when path is not supplied.
798 or ``foo = !`` when path is not supplied.
799
799
800 Example for ``~/.hgrc``::
800 Example for ``~/.hgrc``::
801
801
802 [extensions]
802 [extensions]
803 # (the churn extension will get loaded from Mercurial's path)
803 # (the churn extension will get loaded from Mercurial's path)
804 churn =
804 churn =
805 # (this extension will get loaded from the file specified)
805 # (this extension will get loaded from the file specified)
806 myfeature = ~/.hgext/myfeature.py
806 myfeature = ~/.hgext/myfeature.py
807
807
808
808
809 ``format``
809 ``format``
810 ----------
810 ----------
811
811
812 Configuration that controls the repository format. Newer format options are more
812 Configuration that controls the repository format. Newer format options are more
813 powerful but incompatible with some older versions of Mercurial. Format options
813 powerful but incompatible with some older versions of Mercurial. Format options
814 are considered at repository initialization only. You need to make a new clone
814 are considered at repository initialization only. You need to make a new clone
815 for config change to be taken into account.
815 for config change to be taken into account.
816
816
817 For more details about repository format and version compatibility, see
817 For more details about repository format and version compatibility, see
818 https://www.mercurial-scm.org/wiki/MissingRequirement
818 https://www.mercurial-scm.org/wiki/MissingRequirement
819
819
820 ``usegeneraldelta``
820 ``usegeneraldelta``
821 Enable or disable the "generaldelta" repository format which improves
821 Enable or disable the "generaldelta" repository format which improves
822 repository compression by allowing "revlog" to store delta against arbitrary
822 repository compression by allowing "revlog" to store delta against arbitrary
823 revision instead of the previous stored one. This provides significant
823 revision instead of the previous stored one. This provides significant
824 improvement for repositories with branches.
824 improvement for repositories with branches.
825
825
826 Repositories with this on-disk format require Mercurial version 1.9.
826 Repositories with this on-disk format require Mercurial version 1.9.
827
827
828 Enabled by default.
828 Enabled by default.
829
829
830 ``dotencode``
830 ``dotencode``
831 Enable or disable the "dotencode" repository format which enhances
831 Enable or disable the "dotencode" repository format which enhances
832 the "fncache" repository format (which has to be enabled to use
832 the "fncache" repository format (which has to be enabled to use
833 dotencode) to avoid issues with filenames starting with ._ on
833 dotencode) to avoid issues with filenames starting with ._ on
834 Mac OS X and spaces on Windows.
834 Mac OS X and spaces on Windows.
835
835
836 Repositories with this on-disk format require Mercurial version 1.7.
836 Repositories with this on-disk format require Mercurial version 1.7.
837
837
838 Enabled by default.
838 Enabled by default.
839
839
840 ``usefncache``
840 ``usefncache``
841 Enable or disable the "fncache" repository format which enhances
841 Enable or disable the "fncache" repository format which enhances
842 the "store" repository format (which has to be enabled to use
842 the "store" repository format (which has to be enabled to use
843 fncache) to allow longer filenames and avoids using Windows
843 fncache) to allow longer filenames and avoids using Windows
844 reserved names, e.g. "nul".
844 reserved names, e.g. "nul".
845
845
846 Repositories with this on-disk format require Mercurial version 1.1.
846 Repositories with this on-disk format require Mercurial version 1.1.
847
847
848 Enabled by default.
848 Enabled by default.
849
849
850 ``usestore``
850 ``usestore``
851 Enable or disable the "store" repository format which improves
851 Enable or disable the "store" repository format which improves
852 compatibility with systems that fold case or otherwise mangle
852 compatibility with systems that fold case or otherwise mangle
853 filenames. Disabling this option will allow you to store longer filenames
853 filenames. Disabling this option will allow you to store longer filenames
854 in some situations at the expense of compatibility.
854 in some situations at the expense of compatibility.
855
855
856 Repositories with this on-disk format require Mercurial version 0.9.4.
856 Repositories with this on-disk format require Mercurial version 0.9.4.
857
857
858 Enabled by default.
858 Enabled by default.
859
859
860 ``graph``
860 ``graph``
861 ---------
861 ---------
862
862
863 Web graph view configuration. This section let you change graph
863 Web graph view configuration. This section let you change graph
864 elements display properties by branches, for instance to make the
864 elements display properties by branches, for instance to make the
865 ``default`` branch stand out.
865 ``default`` branch stand out.
866
866
867 Each line has the following format::
867 Each line has the following format::
868
868
869 <branch>.<argument> = <value>
869 <branch>.<argument> = <value>
870
870
871 where ``<branch>`` is the name of the branch being
871 where ``<branch>`` is the name of the branch being
872 customized. Example::
872 customized. Example::
873
873
874 [graph]
874 [graph]
875 # 2px width
875 # 2px width
876 default.width = 2
876 default.width = 2
877 # red color
877 # red color
878 default.color = FF0000
878 default.color = FF0000
879
879
880 Supported arguments:
880 Supported arguments:
881
881
882 ``width``
882 ``width``
883 Set branch edges width in pixels.
883 Set branch edges width in pixels.
884
884
885 ``color``
885 ``color``
886 Set branch edges color in hexadecimal RGB notation.
886 Set branch edges color in hexadecimal RGB notation.
887
887
888 ``hooks``
888 ``hooks``
889 ---------
889 ---------
890
890
891 Commands or Python functions that get automatically executed by
891 Commands or Python functions that get automatically executed by
892 various actions such as starting or finishing a commit. Multiple
892 various actions such as starting or finishing a commit. Multiple
893 hooks can be run for the same action by appending a suffix to the
893 hooks can be run for the same action by appending a suffix to the
894 action. Overriding a site-wide hook can be done by changing its
894 action. Overriding a site-wide hook can be done by changing its
895 value or setting it to an empty string. Hooks can be prioritized
895 value or setting it to an empty string. Hooks can be prioritized
896 by adding a prefix of ``priority.`` to the hook name on a new line
896 by adding a prefix of ``priority.`` to the hook name on a new line
897 and setting the priority. The default priority is 0.
897 and setting the priority. The default priority is 0.
898
898
899 Example ``.hg/hgrc``::
899 Example ``.hg/hgrc``::
900
900
901 [hooks]
901 [hooks]
902 # update working directory after adding changesets
902 # update working directory after adding changesets
903 changegroup.update = hg update
903 changegroup.update = hg update
904 # do not use the site-wide hook
904 # do not use the site-wide hook
905 incoming =
905 incoming =
906 incoming.email = /my/email/hook
906 incoming.email = /my/email/hook
907 incoming.autobuild = /my/build/hook
907 incoming.autobuild = /my/build/hook
908 # force autobuild hook to run before other incoming hooks
908 # force autobuild hook to run before other incoming hooks
909 priority.incoming.autobuild = 1
909 priority.incoming.autobuild = 1
910
910
911 Most hooks are run with environment variables set that give useful
911 Most hooks are run with environment variables set that give useful
912 additional information. For each hook below, the environment variables
912 additional information. For each hook below, the environment variables
913 it is passed are listed with names in the form ``$HG_foo``. The
913 it is passed are listed with names in the form ``$HG_foo``. The
914 ``$HG_HOOKTYPE`` and ``$HG_HOOKNAME`` variables are set for all hooks.
914 ``$HG_HOOKTYPE`` and ``$HG_HOOKNAME`` variables are set for all hooks.
915 They contain the type of hook which triggered the run and the full name
915 They contain the type of hook which triggered the run and the full name
916 of the hook in the config, respectively. In the example above, this will
916 of the hook in the config, respectively. In the example above, this will
917 be ``$HG_HOOKTYPE=incoming`` and ``$HG_HOOKNAME=incoming.email``.
917 be ``$HG_HOOKTYPE=incoming`` and ``$HG_HOOKNAME=incoming.email``.
918
918
919 .. container:: windows
919 .. container:: windows
920
920
921 Some basic Unix syntax can be enabled for portability, including ``$VAR``
921 Some basic Unix syntax can be enabled for portability, including ``$VAR``
922 and ``${VAR}`` style variables. A ``~`` followed by ``\`` or ``/`` will
922 and ``${VAR}`` style variables. A ``~`` followed by ``\`` or ``/`` will
923 be expanded to ``%USERPROFILE%`` to simulate a subset of tilde expansion
923 be expanded to ``%USERPROFILE%`` to simulate a subset of tilde expansion
924 on Unix. To use a literal ``$`` or ``~``, it must be escaped with a back
924 on Unix. To use a literal ``$`` or ``~``, it must be escaped with a back
925 slash or inside of a strong quote. Strong quotes will be replaced by
925 slash or inside of a strong quote. Strong quotes will be replaced by
926 double quotes after processing.
926 double quotes after processing.
927
927
928 This feature is enabled by adding a prefix of ``tonative.`` to the hook
928 This feature is enabled by adding a prefix of ``tonative.`` to the hook
929 name on a new line, and setting it to ``True``. For example::
929 name on a new line, and setting it to ``True``. For example::
930
930
931 [hooks]
931 [hooks]
932 incoming.autobuild = /my/build/hook
932 incoming.autobuild = /my/build/hook
933 # enable translation to cmd.exe syntax for autobuild hook
933 # enable translation to cmd.exe syntax for autobuild hook
934 tonative.incoming.autobuild = True
934 tonative.incoming.autobuild = True
935
935
936 ``changegroup``
936 ``changegroup``
937 Run after a changegroup has been added via push, pull or unbundle. The ID of
937 Run after a changegroup has been added via push, pull or unbundle. The ID of
938 the first new changeset is in ``$HG_NODE`` and last is in ``$HG_NODE_LAST``.
938 the first new changeset is in ``$HG_NODE`` and last is in ``$HG_NODE_LAST``.
939 The URL from which changes came is in ``$HG_URL``.
939 The URL from which changes came is in ``$HG_URL``.
940
940
941 ``commit``
941 ``commit``
942 Run after a changeset has been created in the local repository. The ID
942 Run after a changeset has been created in the local repository. The ID
943 of the newly created changeset is in ``$HG_NODE``. Parent changeset
943 of the newly created changeset is in ``$HG_NODE``. Parent changeset
944 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
944 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
945
945
946 ``incoming``
946 ``incoming``
947 Run after a changeset has been pulled, pushed, or unbundled into
947 Run after a changeset has been pulled, pushed, or unbundled into
948 the local repository. The ID of the newly arrived changeset is in
948 the local repository. The ID of the newly arrived changeset is in
949 ``$HG_NODE``. The URL that was source of the changes is in ``$HG_URL``.
949 ``$HG_NODE``. The URL that was source of the changes is in ``$HG_URL``.
950
950
951 ``outgoing``
951 ``outgoing``
952 Run after sending changes from the local repository to another. The ID of
952 Run after sending changes from the local repository to another. The ID of
953 first changeset sent is in ``$HG_NODE``. The source of operation is in
953 first changeset sent is in ``$HG_NODE``. The source of operation is in
954 ``$HG_SOURCE``. Also see :hg:`help config.hooks.preoutgoing`.
954 ``$HG_SOURCE``. Also see :hg:`help config.hooks.preoutgoing`.
955
955
956 ``post-<command>``
956 ``post-<command>``
957 Run after successful invocations of the associated command. The
957 Run after successful invocations of the associated command. The
958 contents of the command line are passed as ``$HG_ARGS`` and the result
958 contents of the command line are passed as ``$HG_ARGS`` and the result
959 code in ``$HG_RESULT``. Parsed command line arguments are passed as
959 code in ``$HG_RESULT``. Parsed command line arguments are passed as
960 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
960 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
961 the python data internally passed to <command>. ``$HG_OPTS`` is a
961 the python data internally passed to <command>. ``$HG_OPTS`` is a
962 dictionary of options (with unspecified options set to their defaults).
962 dictionary of options (with unspecified options set to their defaults).
963 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
963 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
964
964
965 ``fail-<command>``
965 ``fail-<command>``
966 Run after a failed invocation of an associated command. The contents
966 Run after a failed invocation of an associated command. The contents
967 of the command line are passed as ``$HG_ARGS``. Parsed command line
967 of the command line are passed as ``$HG_ARGS``. Parsed command line
968 arguments are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain
968 arguments are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain
969 string representations of the python data internally passed to
969 string representations of the python data internally passed to
970 <command>. ``$HG_OPTS`` is a dictionary of options (with unspecified
970 <command>. ``$HG_OPTS`` is a dictionary of options (with unspecified
971 options set to their defaults). ``$HG_PATS`` is a list of arguments.
971 options set to their defaults). ``$HG_PATS`` is a list of arguments.
972 Hook failure is ignored.
972 Hook failure is ignored.
973
973
974 ``pre-<command>``
974 ``pre-<command>``
975 Run before executing the associated command. The contents of the
975 Run before executing the associated command. The contents of the
976 command line are passed as ``$HG_ARGS``. Parsed command line arguments
976 command line are passed as ``$HG_ARGS``. Parsed command line arguments
977 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
977 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
978 representations of the data internally passed to <command>. ``$HG_OPTS``
978 representations of the data internally passed to <command>. ``$HG_OPTS``
979 is a dictionary of options (with unspecified options set to their
979 is a dictionary of options (with unspecified options set to their
980 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
980 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
981 failure, the command doesn't execute and Mercurial returns the failure
981 failure, the command doesn't execute and Mercurial returns the failure
982 code.
982 code.
983
983
984 ``prechangegroup``
984 ``prechangegroup``
985 Run before a changegroup is added via push, pull or unbundle. Exit
985 Run before a changegroup is added via push, pull or unbundle. Exit
986 status 0 allows the changegroup to proceed. A non-zero status will
986 status 0 allows the changegroup to proceed. A non-zero status will
987 cause the push, pull or unbundle to fail. The URL from which changes
987 cause the push, pull or unbundle to fail. The URL from which changes
988 will come is in ``$HG_URL``.
988 will come is in ``$HG_URL``.
989
989
990 ``precommit``
990 ``precommit``
991 Run before starting a local commit. Exit status 0 allows the
991 Run before starting a local commit. Exit status 0 allows the
992 commit to proceed. A non-zero status will cause the commit to fail.
992 commit to proceed. A non-zero status will cause the commit to fail.
993 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
993 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
994
994
995 ``prelistkeys``
995 ``prelistkeys``
996 Run before listing pushkeys (like bookmarks) in the
996 Run before listing pushkeys (like bookmarks) in the
997 repository. A non-zero status will cause failure. The key namespace is
997 repository. A non-zero status will cause failure. The key namespace is
998 in ``$HG_NAMESPACE``.
998 in ``$HG_NAMESPACE``.
999
999
1000 ``preoutgoing``
1000 ``preoutgoing``
1001 Run before collecting changes to send from the local repository to
1001 Run before collecting changes to send from the local repository to
1002 another. A non-zero status will cause failure. This lets you prevent
1002 another. A non-zero status will cause failure. This lets you prevent
1003 pull over HTTP or SSH. It can also prevent propagating commits (via
1003 pull over HTTP or SSH. It can also prevent propagating commits (via
1004 local pull, push (outbound) or bundle commands), but not completely,
1004 local pull, push (outbound) or bundle commands), but not completely,
1005 since you can just copy files instead. The source of operation is in
1005 since you can just copy files instead. The source of operation is in
1006 ``$HG_SOURCE``. If "serve", the operation is happening on behalf of a remote
1006 ``$HG_SOURCE``. If "serve", the operation is happening on behalf of a remote
1007 SSH or HTTP repository. If "push", "pull" or "bundle", the operation
1007 SSH or HTTP repository. If "push", "pull" or "bundle", the operation
1008 is happening on behalf of a repository on same system.
1008 is happening on behalf of a repository on same system.
1009
1009
1010 ``prepushkey``
1010 ``prepushkey``
1011 Run before a pushkey (like a bookmark) is added to the
1011 Run before a pushkey (like a bookmark) is added to the
1012 repository. A non-zero status will cause the key to be rejected. The
1012 repository. A non-zero status will cause the key to be rejected. The
1013 key namespace is in ``$HG_NAMESPACE``, the key is in ``$HG_KEY``,
1013 key namespace is in ``$HG_NAMESPACE``, the key is in ``$HG_KEY``,
1014 the old value (if any) is in ``$HG_OLD``, and the new value is in
1014 the old value (if any) is in ``$HG_OLD``, and the new value is in
1015 ``$HG_NEW``.
1015 ``$HG_NEW``.
1016
1016
1017 ``pretag``
1017 ``pretag``
1018 Run before creating a tag. Exit status 0 allows the tag to be
1018 Run before creating a tag. Exit status 0 allows the tag to be
1019 created. A non-zero status will cause the tag to fail. The ID of the
1019 created. A non-zero status will cause the tag to fail. The ID of the
1020 changeset to tag is in ``$HG_NODE``. The name of tag is in ``$HG_TAG``. The
1020 changeset to tag is in ``$HG_NODE``. The name of tag is in ``$HG_TAG``. The
1021 tag is local if ``$HG_LOCAL=1``, or in the repository if ``$HG_LOCAL=0``.
1021 tag is local if ``$HG_LOCAL=1``, or in the repository if ``$HG_LOCAL=0``.
1022
1022
1023 ``pretxnopen``
1023 ``pretxnopen``
1024 Run before any new repository transaction is open. The reason for the
1024 Run before any new repository transaction is open. The reason for the
1025 transaction will be in ``$HG_TXNNAME``, and a unique identifier for the
1025 transaction will be in ``$HG_TXNNAME``, and a unique identifier for the
1026 transaction will be in ``HG_TXNID``. A non-zero status will prevent the
1026 transaction will be in ``HG_TXNID``. A non-zero status will prevent the
1027 transaction from being opened.
1027 transaction from being opened.
1028
1028
1029 ``pretxnclose``
1029 ``pretxnclose``
1030 Run right before the transaction is actually finalized. Any repository change
1030 Run right before the transaction is actually finalized. Any repository change
1031 will be visible to the hook program. This lets you validate the transaction
1031 will be visible to the hook program. This lets you validate the transaction
1032 content or change it. Exit status 0 allows the commit to proceed. A non-zero
1032 content or change it. Exit status 0 allows the commit to proceed. A non-zero
1033 status will cause the transaction to be rolled back. The reason for the
1033 status will cause the transaction to be rolled back. The reason for the
1034 transaction opening will be in ``$HG_TXNNAME``, and a unique identifier for
1034 transaction opening will be in ``$HG_TXNNAME``, and a unique identifier for
1035 the transaction will be in ``HG_TXNID``. The rest of the available data will
1035 the transaction will be in ``HG_TXNID``. The rest of the available data will
1036 vary according the transaction type. New changesets will add ``$HG_NODE``
1036 vary according the transaction type. New changesets will add ``$HG_NODE``
1037 (the ID of the first added changeset), ``$HG_NODE_LAST`` (the ID of the last
1037 (the ID of the first added changeset), ``$HG_NODE_LAST`` (the ID of the last
1038 added changeset), ``$HG_URL`` and ``$HG_SOURCE`` variables. Bookmark and
1038 added changeset), ``$HG_URL`` and ``$HG_SOURCE`` variables. Bookmark and
1039 phase changes will set ``HG_BOOKMARK_MOVED`` and ``HG_PHASES_MOVED`` to ``1``
1039 phase changes will set ``HG_BOOKMARK_MOVED`` and ``HG_PHASES_MOVED`` to ``1``
1040 respectively, etc.
1040 respectively, etc.
1041
1041
1042 ``pretxnclose-bookmark``
1042 ``pretxnclose-bookmark``
1043 Run right before a bookmark change is actually finalized. Any repository
1043 Run right before a bookmark change is actually finalized. Any repository
1044 change will be visible to the hook program. This lets you validate the
1044 change will be visible to the hook program. This lets you validate the
1045 transaction content or change it. Exit status 0 allows the commit to
1045 transaction content or change it. Exit status 0 allows the commit to
1046 proceed. A non-zero status will cause the transaction to be rolled back.
1046 proceed. A non-zero status will cause the transaction to be rolled back.
1047 The name of the bookmark will be available in ``$HG_BOOKMARK``, the new
1047 The name of the bookmark will be available in ``$HG_BOOKMARK``, the new
1048 bookmark location will be available in ``$HG_NODE`` while the previous
1048 bookmark location will be available in ``$HG_NODE`` while the previous
1049 location will be available in ``$HG_OLDNODE``. In case of a bookmark
1049 location will be available in ``$HG_OLDNODE``. In case of a bookmark
1050 creation ``$HG_OLDNODE`` will be empty. In case of deletion ``$HG_NODE``
1050 creation ``$HG_OLDNODE`` will be empty. In case of deletion ``$HG_NODE``
1051 will be empty.
1051 will be empty.
1052 In addition, the reason for the transaction opening will be in
1052 In addition, the reason for the transaction opening will be in
1053 ``$HG_TXNNAME``, and a unique identifier for the transaction will be in
1053 ``$HG_TXNNAME``, and a unique identifier for the transaction will be in
1054 ``HG_TXNID``.
1054 ``HG_TXNID``.
1055
1055
1056 ``pretxnclose-phase``
1056 ``pretxnclose-phase``
1057 Run right before a phase change is actually finalized. Any repository change
1057 Run right before a phase change is actually finalized. Any repository change
1058 will be visible to the hook program. This lets you validate the transaction
1058 will be visible to the hook program. This lets you validate the transaction
1059 content or change it. Exit status 0 allows the commit to proceed. A non-zero
1059 content or change it. Exit status 0 allows the commit to proceed. A non-zero
1060 status will cause the transaction to be rolled back. The hook is called
1060 status will cause the transaction to be rolled back. The hook is called
1061 multiple times, once for each revision affected by a phase change.
1061 multiple times, once for each revision affected by a phase change.
1062 The affected node is available in ``$HG_NODE``, the phase in ``$HG_PHASE``
1062 The affected node is available in ``$HG_NODE``, the phase in ``$HG_PHASE``
1063 while the previous ``$HG_OLDPHASE``. In case of new node, ``$HG_OLDPHASE``
1063 while the previous ``$HG_OLDPHASE``. In case of new node, ``$HG_OLDPHASE``
1064 will be empty. In addition, the reason for the transaction opening will be in
1064 will be empty. In addition, the reason for the transaction opening will be in
1065 ``$HG_TXNNAME``, and a unique identifier for the transaction will be in
1065 ``$HG_TXNNAME``, and a unique identifier for the transaction will be in
1066 ``HG_TXNID``. The hook is also run for newly added revisions. In this case
1066 ``HG_TXNID``. The hook is also run for newly added revisions. In this case
1067 the ``$HG_OLDPHASE`` entry will be empty.
1067 the ``$HG_OLDPHASE`` entry will be empty.
1068
1068
1069 ``txnclose``
1069 ``txnclose``
1070 Run after any repository transaction has been committed. At this
1070 Run after any repository transaction has been committed. At this
1071 point, the transaction can no longer be rolled back. The hook will run
1071 point, the transaction can no longer be rolled back. The hook will run
1072 after the lock is released. See :hg:`help config.hooks.pretxnclose` for
1072 after the lock is released. See :hg:`help config.hooks.pretxnclose` for
1073 details about available variables.
1073 details about available variables.
1074
1074
1075 ``txnclose-bookmark``
1075 ``txnclose-bookmark``
1076 Run after any bookmark change has been committed. At this point, the
1076 Run after any bookmark change has been committed. At this point, the
1077 transaction can no longer be rolled back. The hook will run after the lock
1077 transaction can no longer be rolled back. The hook will run after the lock
1078 is released. See :hg:`help config.hooks.pretxnclose-bookmark` for details
1078 is released. See :hg:`help config.hooks.pretxnclose-bookmark` for details
1079 about available variables.
1079 about available variables.
1080
1080
1081 ``txnclose-phase``
1081 ``txnclose-phase``
1082 Run after any phase change has been committed. At this point, the
1082 Run after any phase change has been committed. At this point, the
1083 transaction can no longer be rolled back. The hook will run after the lock
1083 transaction can no longer be rolled back. The hook will run after the lock
1084 is released. See :hg:`help config.hooks.pretxnclose-phase` for details about
1084 is released. See :hg:`help config.hooks.pretxnclose-phase` for details about
1085 available variables.
1085 available variables.
1086
1086
1087 ``txnabort``
1087 ``txnabort``
1088 Run when a transaction is aborted. See :hg:`help config.hooks.pretxnclose`
1088 Run when a transaction is aborted. See :hg:`help config.hooks.pretxnclose`
1089 for details about available variables.
1089 for details about available variables.
1090
1090
1091 ``pretxnchangegroup``
1091 ``pretxnchangegroup``
1092 Run after a changegroup has been added via push, pull or unbundle, but before
1092 Run after a changegroup has been added via push, pull or unbundle, but before
1093 the transaction has been committed. The changegroup is visible to the hook
1093 the transaction has been committed. The changegroup is visible to the hook
1094 program. This allows validation of incoming changes before accepting them.
1094 program. This allows validation of incoming changes before accepting them.
1095 The ID of the first new changeset is in ``$HG_NODE`` and last is in
1095 The ID of the first new changeset is in ``$HG_NODE`` and last is in
1096 ``$HG_NODE_LAST``. Exit status 0 allows the transaction to commit. A non-zero
1096 ``$HG_NODE_LAST``. Exit status 0 allows the transaction to commit. A non-zero
1097 status will cause the transaction to be rolled back, and the push, pull or
1097 status will cause the transaction to be rolled back, and the push, pull or
1098 unbundle will fail. The URL that was the source of changes is in ``$HG_URL``.
1098 unbundle will fail. The URL that was the source of changes is in ``$HG_URL``.
1099
1099
1100 ``pretxncommit``
1100 ``pretxncommit``
1101 Run after a changeset has been created, but before the transaction is
1101 Run after a changeset has been created, but before the transaction is
1102 committed. The changeset is visible to the hook program. This allows
1102 committed. The changeset is visible to the hook program. This allows
1103 validation of the commit message and changes. Exit status 0 allows the
1103 validation of the commit message and changes. Exit status 0 allows the
1104 commit to proceed. A non-zero status will cause the transaction to
1104 commit to proceed. A non-zero status will cause the transaction to
1105 be rolled back. The ID of the new changeset is in ``$HG_NODE``. The parent
1105 be rolled back. The ID of the new changeset is in ``$HG_NODE``. The parent
1106 changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
1106 changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
1107
1107
1108 ``preupdate``
1108 ``preupdate``
1109 Run before updating the working directory. Exit status 0 allows
1109 Run before updating the working directory. Exit status 0 allows
1110 the update to proceed. A non-zero status will prevent the update.
1110 the update to proceed. A non-zero status will prevent the update.
1111 The changeset ID of first new parent is in ``$HG_PARENT1``. If updating to a
1111 The changeset ID of first new parent is in ``$HG_PARENT1``. If updating to a
1112 merge, the ID of second new parent is in ``$HG_PARENT2``.
1112 merge, the ID of second new parent is in ``$HG_PARENT2``.
1113
1113
1114 ``listkeys``
1114 ``listkeys``
1115 Run after listing pushkeys (like bookmarks) in the repository. The
1115 Run after listing pushkeys (like bookmarks) in the repository. The
1116 key namespace is in ``$HG_NAMESPACE``. ``$HG_VALUES`` is a
1116 key namespace is in ``$HG_NAMESPACE``. ``$HG_VALUES`` is a
1117 dictionary containing the keys and values.
1117 dictionary containing the keys and values.
1118
1118
1119 ``pushkey``
1119 ``pushkey``
1120 Run after a pushkey (like a bookmark) is added to the
1120 Run after a pushkey (like a bookmark) is added to the
1121 repository. The key namespace is in ``$HG_NAMESPACE``, the key is in
1121 repository. The key namespace is in ``$HG_NAMESPACE``, the key is in
1122 ``$HG_KEY``, the old value (if any) is in ``$HG_OLD``, and the new
1122 ``$HG_KEY``, the old value (if any) is in ``$HG_OLD``, and the new
1123 value is in ``$HG_NEW``.
1123 value is in ``$HG_NEW``.
1124
1124
1125 ``tag``
1125 ``tag``
1126 Run after a tag is created. The ID of the tagged changeset is in ``$HG_NODE``.
1126 Run after a tag is created. The ID of the tagged changeset is in ``$HG_NODE``.
1127 The name of tag is in ``$HG_TAG``. The tag is local if ``$HG_LOCAL=1``, or in
1127 The name of tag is in ``$HG_TAG``. The tag is local if ``$HG_LOCAL=1``, or in
1128 the repository if ``$HG_LOCAL=0``.
1128 the repository if ``$HG_LOCAL=0``.
1129
1129
1130 ``update``
1130 ``update``
1131 Run after updating the working directory. The changeset ID of first
1131 Run after updating the working directory. The changeset ID of first
1132 new parent is in ``$HG_PARENT1``. If updating to a merge, the ID of second new
1132 new parent is in ``$HG_PARENT1``. If updating to a merge, the ID of second new
1133 parent is in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
1133 parent is in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
1134 update failed (e.g. because conflicts were not resolved), ``$HG_ERROR=1``.
1134 update failed (e.g. because conflicts were not resolved), ``$HG_ERROR=1``.
1135
1135
1136 .. note::
1136 .. note::
1137
1137
1138 It is generally better to use standard hooks rather than the
1138 It is generally better to use standard hooks rather than the
1139 generic pre- and post- command hooks, as they are guaranteed to be
1139 generic pre- and post- command hooks, as they are guaranteed to be
1140 called in the appropriate contexts for influencing transactions.
1140 called in the appropriate contexts for influencing transactions.
1141 Also, hooks like "commit" will be called in all contexts that
1141 Also, hooks like "commit" will be called in all contexts that
1142 generate a commit (e.g. tag) and not just the commit command.
1142 generate a commit (e.g. tag) and not just the commit command.
1143
1143
1144 .. note::
1144 .. note::
1145
1145
1146 Environment variables with empty values may not be passed to
1146 Environment variables with empty values may not be passed to
1147 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
1147 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
1148 will have an empty value under Unix-like platforms for non-merge
1148 will have an empty value under Unix-like platforms for non-merge
1149 changesets, while it will not be available at all under Windows.
1149 changesets, while it will not be available at all under Windows.
1150
1150
1151 The syntax for Python hooks is as follows::
1151 The syntax for Python hooks is as follows::
1152
1152
1153 hookname = python:modulename.submodule.callable
1153 hookname = python:modulename.submodule.callable
1154 hookname = python:/path/to/python/module.py:callable
1154 hookname = python:/path/to/python/module.py:callable
1155
1155
1156 Python hooks are run within the Mercurial process. Each hook is
1156 Python hooks are run within the Mercurial process. Each hook is
1157 called with at least three keyword arguments: a ui object (keyword
1157 called with at least three keyword arguments: a ui object (keyword
1158 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
1158 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
1159 keyword that tells what kind of hook is used. Arguments listed as
1159 keyword that tells what kind of hook is used. Arguments listed as
1160 environment variables above are passed as keyword arguments, with no
1160 environment variables above are passed as keyword arguments, with no
1161 ``HG_`` prefix, and names in lower case.
1161 ``HG_`` prefix, and names in lower case.
1162
1162
1163 If a Python hook returns a "true" value or raises an exception, this
1163 If a Python hook returns a "true" value or raises an exception, this
1164 is treated as a failure.
1164 is treated as a failure.
1165
1165
1166
1166
1167 ``hostfingerprints``
1167 ``hostfingerprints``
1168 --------------------
1168 --------------------
1169
1169
1170 (Deprecated. Use ``[hostsecurity]``'s ``fingerprints`` options instead.)
1170 (Deprecated. Use ``[hostsecurity]``'s ``fingerprints`` options instead.)
1171
1171
1172 Fingerprints of the certificates of known HTTPS servers.
1172 Fingerprints of the certificates of known HTTPS servers.
1173
1173
1174 A HTTPS connection to a server with a fingerprint configured here will
1174 A HTTPS connection to a server with a fingerprint configured here will
1175 only succeed if the servers certificate matches the fingerprint.
1175 only succeed if the servers certificate matches the fingerprint.
1176 This is very similar to how ssh known hosts works.
1176 This is very similar to how ssh known hosts works.
1177
1177
1178 The fingerprint is the SHA-1 hash value of the DER encoded certificate.
1178 The fingerprint is the SHA-1 hash value of the DER encoded certificate.
1179 Multiple values can be specified (separated by spaces or commas). This can
1179 Multiple values can be specified (separated by spaces or commas). This can
1180 be used to define both old and new fingerprints while a host transitions
1180 be used to define both old and new fingerprints while a host transitions
1181 to a new certificate.
1181 to a new certificate.
1182
1182
1183 The CA chain and web.cacerts is not used for servers with a fingerprint.
1183 The CA chain and web.cacerts is not used for servers with a fingerprint.
1184
1184
1185 For example::
1185 For example::
1186
1186
1187 [hostfingerprints]
1187 [hostfingerprints]
1188 hg.intevation.de = fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1188 hg.intevation.de = fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1189 hg.intevation.org = fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1189 hg.intevation.org = fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1190
1190
1191 ``hostsecurity``
1191 ``hostsecurity``
1192 ----------------
1192 ----------------
1193
1193
1194 Used to specify global and per-host security settings for connecting to
1194 Used to specify global and per-host security settings for connecting to
1195 other machines.
1195 other machines.
1196
1196
1197 The following options control default behavior for all hosts.
1197 The following options control default behavior for all hosts.
1198
1198
1199 ``ciphers``
1199 ``ciphers``
1200 Defines the cryptographic ciphers to use for connections.
1200 Defines the cryptographic ciphers to use for connections.
1201
1201
1202 Value must be a valid OpenSSL Cipher List Format as documented at
1202 Value must be a valid OpenSSL Cipher List Format as documented at
1203 https://www.openssl.org/docs/manmaster/apps/ciphers.html#CIPHER-LIST-FORMAT.
1203 https://www.openssl.org/docs/manmaster/apps/ciphers.html#CIPHER-LIST-FORMAT.
1204
1204
1205 This setting is for advanced users only. Setting to incorrect values
1205 This setting is for advanced users only. Setting to incorrect values
1206 can significantly lower connection security or decrease performance.
1206 can significantly lower connection security or decrease performance.
1207 You have been warned.
1207 You have been warned.
1208
1208
1209 This option requires Python 2.7.
1209 This option requires Python 2.7.
1210
1210
1211 ``minimumprotocol``
1211 ``minimumprotocol``
1212 Defines the minimum channel encryption protocol to use.
1212 Defines the minimum channel encryption protocol to use.
1213
1213
1214 By default, the highest version of TLS supported by both client and server
1214 By default, the highest version of TLS supported by both client and server
1215 is used.
1215 is used.
1216
1216
1217 Allowed values are: ``tls1.0``, ``tls1.1``, ``tls1.2``.
1217 Allowed values are: ``tls1.0``, ``tls1.1``, ``tls1.2``.
1218
1218
1219 When running on an old Python version, only ``tls1.0`` is allowed since
1219 When running on an old Python version, only ``tls1.0`` is allowed since
1220 old versions of Python only support up to TLS 1.0.
1220 old versions of Python only support up to TLS 1.0.
1221
1221
1222 When running a Python that supports modern TLS versions, the default is
1222 When running a Python that supports modern TLS versions, the default is
1223 ``tls1.1``. ``tls1.0`` can still be used to allow TLS 1.0. However, this
1223 ``tls1.1``. ``tls1.0`` can still be used to allow TLS 1.0. However, this
1224 weakens security and should only be used as a feature of last resort if
1224 weakens security and should only be used as a feature of last resort if
1225 a server does not support TLS 1.1+.
1225 a server does not support TLS 1.1+.
1226
1226
1227 Options in the ``[hostsecurity]`` section can have the form
1227 Options in the ``[hostsecurity]`` section can have the form
1228 ``hostname``:``setting``. This allows multiple settings to be defined on a
1228 ``hostname``:``setting``. This allows multiple settings to be defined on a
1229 per-host basis.
1229 per-host basis.
1230
1230
1231 The following per-host settings can be defined.
1231 The following per-host settings can be defined.
1232
1232
1233 ``ciphers``
1233 ``ciphers``
1234 This behaves like ``ciphers`` as described above except it only applies
1234 This behaves like ``ciphers`` as described above except it only applies
1235 to the host on which it is defined.
1235 to the host on which it is defined.
1236
1236
1237 ``fingerprints``
1237 ``fingerprints``
1238 A list of hashes of the DER encoded peer/remote certificate. Values have
1238 A list of hashes of the DER encoded peer/remote certificate. Values have
1239 the form ``algorithm``:``fingerprint``. e.g.
1239 the form ``algorithm``:``fingerprint``. e.g.
1240 ``sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2``.
1240 ``sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2``.
1241 In addition, colons (``:``) can appear in the fingerprint part.
1241 In addition, colons (``:``) can appear in the fingerprint part.
1242
1242
1243 The following algorithms/prefixes are supported: ``sha1``, ``sha256``,
1243 The following algorithms/prefixes are supported: ``sha1``, ``sha256``,
1244 ``sha512``.
1244 ``sha512``.
1245
1245
1246 Use of ``sha256`` or ``sha512`` is preferred.
1246 Use of ``sha256`` or ``sha512`` is preferred.
1247
1247
1248 If a fingerprint is specified, the CA chain is not validated for this
1248 If a fingerprint is specified, the CA chain is not validated for this
1249 host and Mercurial will require the remote certificate to match one
1249 host and Mercurial will require the remote certificate to match one
1250 of the fingerprints specified. This means if the server updates its
1250 of the fingerprints specified. This means if the server updates its
1251 certificate, Mercurial will abort until a new fingerprint is defined.
1251 certificate, Mercurial will abort until a new fingerprint is defined.
1252 This can provide stronger security than traditional CA-based validation
1252 This can provide stronger security than traditional CA-based validation
1253 at the expense of convenience.
1253 at the expense of convenience.
1254
1254
1255 This option takes precedence over ``verifycertsfile``.
1255 This option takes precedence over ``verifycertsfile``.
1256
1256
1257 ``minimumprotocol``
1257 ``minimumprotocol``
1258 This behaves like ``minimumprotocol`` as described above except it
1258 This behaves like ``minimumprotocol`` as described above except it
1259 only applies to the host on which it is defined.
1259 only applies to the host on which it is defined.
1260
1260
1261 ``verifycertsfile``
1261 ``verifycertsfile``
1262 Path to file a containing a list of PEM encoded certificates used to
1262 Path to file a containing a list of PEM encoded certificates used to
1263 verify the server certificate. Environment variables and ``~user``
1263 verify the server certificate. Environment variables and ``~user``
1264 constructs are expanded in the filename.
1264 constructs are expanded in the filename.
1265
1265
1266 The server certificate or the certificate's certificate authority (CA)
1266 The server certificate or the certificate's certificate authority (CA)
1267 must match a certificate from this file or certificate verification
1267 must match a certificate from this file or certificate verification
1268 will fail and connections to the server will be refused.
1268 will fail and connections to the server will be refused.
1269
1269
1270 If defined, only certificates provided by this file will be used:
1270 If defined, only certificates provided by this file will be used:
1271 ``web.cacerts`` and any system/default certificates will not be
1271 ``web.cacerts`` and any system/default certificates will not be
1272 used.
1272 used.
1273
1273
1274 This option has no effect if the per-host ``fingerprints`` option
1274 This option has no effect if the per-host ``fingerprints`` option
1275 is set.
1275 is set.
1276
1276
1277 The format of the file is as follows::
1277 The format of the file is as follows::
1278
1278
1279 -----BEGIN CERTIFICATE-----
1279 -----BEGIN CERTIFICATE-----
1280 ... (certificate in base64 PEM encoding) ...
1280 ... (certificate in base64 PEM encoding) ...
1281 -----END CERTIFICATE-----
1281 -----END CERTIFICATE-----
1282 -----BEGIN CERTIFICATE-----
1282 -----BEGIN CERTIFICATE-----
1283 ... (certificate in base64 PEM encoding) ...
1283 ... (certificate in base64 PEM encoding) ...
1284 -----END CERTIFICATE-----
1284 -----END CERTIFICATE-----
1285
1285
1286 For example::
1286 For example::
1287
1287
1288 [hostsecurity]
1288 [hostsecurity]
1289 hg.example.com:fingerprints = sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2
1289 hg.example.com:fingerprints = sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2
1290 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
1290 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
1291 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
1291 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
1292 foo.example.com:verifycertsfile = /etc/ssl/trusted-ca-certs.pem
1292 foo.example.com:verifycertsfile = /etc/ssl/trusted-ca-certs.pem
1293
1293
1294 To change the default minimum protocol version to TLS 1.2 but to allow TLS 1.1
1294 To change the default minimum protocol version to TLS 1.2 but to allow TLS 1.1
1295 when connecting to ``hg.example.com``::
1295 when connecting to ``hg.example.com``::
1296
1296
1297 [hostsecurity]
1297 [hostsecurity]
1298 minimumprotocol = tls1.2
1298 minimumprotocol = tls1.2
1299 hg.example.com:minimumprotocol = tls1.1
1299 hg.example.com:minimumprotocol = tls1.1
1300
1300
1301 ``http_proxy``
1301 ``http_proxy``
1302 --------------
1302 --------------
1303
1303
1304 Used to access web-based Mercurial repositories through a HTTP
1304 Used to access web-based Mercurial repositories through a HTTP
1305 proxy.
1305 proxy.
1306
1306
1307 ``host``
1307 ``host``
1308 Host name and (optional) port of the proxy server, for example
1308 Host name and (optional) port of the proxy server, for example
1309 "myproxy:8000".
1309 "myproxy:8000".
1310
1310
1311 ``no``
1311 ``no``
1312 Optional. Comma-separated list of host names that should bypass
1312 Optional. Comma-separated list of host names that should bypass
1313 the proxy.
1313 the proxy.
1314
1314
1315 ``passwd``
1315 ``passwd``
1316 Optional. Password to authenticate with at the proxy server.
1316 Optional. Password to authenticate with at the proxy server.
1317
1317
1318 ``user``
1318 ``user``
1319 Optional. User name to authenticate with at the proxy server.
1319 Optional. User name to authenticate with at the proxy server.
1320
1320
1321 ``always``
1321 ``always``
1322 Optional. Always use the proxy, even for localhost and any entries
1322 Optional. Always use the proxy, even for localhost and any entries
1323 in ``http_proxy.no``. (default: False)
1323 in ``http_proxy.no``. (default: False)
1324
1324
1325 ``merge``
1325 ``merge``
1326 ---------
1326 ---------
1327
1327
1328 This section specifies behavior during merges and updates.
1328 This section specifies behavior during merges and updates.
1329
1329
1330 ``checkignored``
1330 ``checkignored``
1331 Controls behavior when an ignored file on disk has the same name as a tracked
1331 Controls behavior when an ignored file on disk has the same name as a tracked
1332 file in the changeset being merged or updated to, and has different
1332 file in the changeset being merged or updated to, and has different
1333 contents. Options are ``abort``, ``warn`` and ``ignore``. With ``abort``,
1333 contents. Options are ``abort``, ``warn`` and ``ignore``. With ``abort``,
1334 abort on such files. With ``warn``, warn on such files and back them up as
1334 abort on such files. With ``warn``, warn on such files and back them up as
1335 ``.orig``. With ``ignore``, don't print a warning and back them up as
1335 ``.orig``. With ``ignore``, don't print a warning and back them up as
1336 ``.orig``. (default: ``abort``)
1336 ``.orig``. (default: ``abort``)
1337
1337
1338 ``checkunknown``
1338 ``checkunknown``
1339 Controls behavior when an unknown file that isn't ignored has the same name
1339 Controls behavior when an unknown file that isn't ignored has the same name
1340 as a tracked file in the changeset being merged or updated to, and has
1340 as a tracked file in the changeset being merged or updated to, and has
1341 different contents. Similar to ``merge.checkignored``, except for files that
1341 different contents. Similar to ``merge.checkignored``, except for files that
1342 are not ignored. (default: ``abort``)
1342 are not ignored. (default: ``abort``)
1343
1343
1344 ``on-failure``
1344 ``on-failure``
1345 When set to ``continue`` (the default), the merge process attempts to
1345 When set to ``continue`` (the default), the merge process attempts to
1346 merge all unresolved files using the merge chosen tool, regardless of
1346 merge all unresolved files using the merge chosen tool, regardless of
1347 whether previous file merge attempts during the process succeeded or not.
1347 whether previous file merge attempts during the process succeeded or not.
1348 Setting this to ``prompt`` will prompt after any merge failure continue
1348 Setting this to ``prompt`` will prompt after any merge failure continue
1349 or halt the merge process. Setting this to ``halt`` will automatically
1349 or halt the merge process. Setting this to ``halt`` will automatically
1350 halt the merge process on any merge tool failure. The merge process
1350 halt the merge process on any merge tool failure. The merge process
1351 can be restarted by using the ``resolve`` command. When a merge is
1351 can be restarted by using the ``resolve`` command. When a merge is
1352 halted, the repository is left in a normal ``unresolved`` merge state.
1352 halted, the repository is left in a normal ``unresolved`` merge state.
1353 (default: ``continue``)
1353 (default: ``continue``)
1354
1354
1355 ``strict-capability-check``
1355 ``strict-capability-check``
1356 Whether capabilities of internal merge tools are checked strictly
1356 Whether capabilities of internal merge tools are checked strictly
1357 or not, while examining rules to decide merge tool to be used.
1357 or not, while examining rules to decide merge tool to be used.
1358 (default: False)
1358 (default: False)
1359
1359
1360 ``merge-patterns``
1360 ``merge-patterns``
1361 ------------------
1361 ------------------
1362
1362
1363 This section specifies merge tools to associate with particular file
1363 This section specifies merge tools to associate with particular file
1364 patterns. Tools matched here will take precedence over the default
1364 patterns. Tools matched here will take precedence over the default
1365 merge tool. Patterns are globs by default, rooted at the repository
1365 merge tool. Patterns are globs by default, rooted at the repository
1366 root.
1366 root.
1367
1367
1368 Example::
1368 Example::
1369
1369
1370 [merge-patterns]
1370 [merge-patterns]
1371 **.c = kdiff3
1371 **.c = kdiff3
1372 **.jpg = myimgmerge
1372 **.jpg = myimgmerge
1373
1373
1374 ``merge-tools``
1374 ``merge-tools``
1375 ---------------
1375 ---------------
1376
1376
1377 This section configures external merge tools to use for file-level
1377 This section configures external merge tools to use for file-level
1378 merges. This section has likely been preconfigured at install time.
1378 merges. This section has likely been preconfigured at install time.
1379 Use :hg:`config merge-tools` to check the existing configuration.
1379 Use :hg:`config merge-tools` to check the existing configuration.
1380 Also see :hg:`help merge-tools` for more details.
1380 Also see :hg:`help merge-tools` for more details.
1381
1381
1382 Example ``~/.hgrc``::
1382 Example ``~/.hgrc``::
1383
1383
1384 [merge-tools]
1384 [merge-tools]
1385 # Override stock tool location
1385 # Override stock tool location
1386 kdiff3.executable = ~/bin/kdiff3
1386 kdiff3.executable = ~/bin/kdiff3
1387 # Specify command line
1387 # Specify command line
1388 kdiff3.args = $base $local $other -o $output
1388 kdiff3.args = $base $local $other -o $output
1389 # Give higher priority
1389 # Give higher priority
1390 kdiff3.priority = 1
1390 kdiff3.priority = 1
1391
1391
1392 # Changing the priority of preconfigured tool
1392 # Changing the priority of preconfigured tool
1393 meld.priority = 0
1393 meld.priority = 0
1394
1394
1395 # Disable a preconfigured tool
1395 # Disable a preconfigured tool
1396 vimdiff.disabled = yes
1396 vimdiff.disabled = yes
1397
1397
1398 # Define new tool
1398 # Define new tool
1399 myHtmlTool.args = -m $local $other $base $output
1399 myHtmlTool.args = -m $local $other $base $output
1400 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
1400 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
1401 myHtmlTool.priority = 1
1401 myHtmlTool.priority = 1
1402
1402
1403 Supported arguments:
1403 Supported arguments:
1404
1404
1405 ``priority``
1405 ``priority``
1406 The priority in which to evaluate this tool.
1406 The priority in which to evaluate this tool.
1407 (default: 0)
1407 (default: 0)
1408
1408
1409 ``executable``
1409 ``executable``
1410 Either just the name of the executable or its pathname.
1410 Either just the name of the executable or its pathname.
1411
1411
1412 .. container:: windows
1412 .. container:: windows
1413
1413
1414 On Windows, the path can use environment variables with ${ProgramFiles}
1414 On Windows, the path can use environment variables with ${ProgramFiles}
1415 syntax.
1415 syntax.
1416
1416
1417 (default: the tool name)
1417 (default: the tool name)
1418
1418
1419 ``args``
1419 ``args``
1420 The arguments to pass to the tool executable. You can refer to the
1420 The arguments to pass to the tool executable. You can refer to the
1421 files being merged as well as the output file through these
1421 files being merged as well as the output file through these
1422 variables: ``$base``, ``$local``, ``$other``, ``$output``.
1422 variables: ``$base``, ``$local``, ``$other``, ``$output``.
1423
1423
1424 The meaning of ``$local`` and ``$other`` can vary depending on which action is
1424 The meaning of ``$local`` and ``$other`` can vary depending on which action is
1425 being performed. During an update or merge, ``$local`` represents the original
1425 being performed. During an update or merge, ``$local`` represents the original
1426 state of the file, while ``$other`` represents the commit you are updating to or
1426 state of the file, while ``$other`` represents the commit you are updating to or
1427 the commit you are merging with. During a rebase, ``$local`` represents the
1427 the commit you are merging with. During a rebase, ``$local`` represents the
1428 destination of the rebase, and ``$other`` represents the commit being rebased.
1428 destination of the rebase, and ``$other`` represents the commit being rebased.
1429
1429
1430 Some operations define custom labels to assist with identifying the revisions,
1430 Some operations define custom labels to assist with identifying the revisions,
1431 accessible via ``$labellocal``, ``$labelother``, and ``$labelbase``. If custom
1431 accessible via ``$labellocal``, ``$labelother``, and ``$labelbase``. If custom
1432 labels are not available, these will be ``local``, ``other``, and ``base``,
1432 labels are not available, these will be ``local``, ``other``, and ``base``,
1433 respectively.
1433 respectively.
1434 (default: ``$local $base $other``)
1434 (default: ``$local $base $other``)
1435
1435
1436 ``premerge``
1436 ``premerge``
1437 Attempt to run internal non-interactive 3-way merge tool before
1437 Attempt to run internal non-interactive 3-way merge tool before
1438 launching external tool. Options are ``true``, ``false``, ``keep`` or
1438 launching external tool. Options are ``true``, ``false``, ``keep`` or
1439 ``keep-merge3``. The ``keep`` option will leave markers in the file if the
1439 ``keep-merge3``. The ``keep`` option will leave markers in the file if the
1440 premerge fails. The ``keep-merge3`` will do the same but include information
1440 premerge fails. The ``keep-merge3`` will do the same but include information
1441 about the base of the merge in the marker (see internal :merge3 in
1441 about the base of the merge in the marker (see internal :merge3 in
1442 :hg:`help merge-tools`).
1442 :hg:`help merge-tools`).
1443 (default: True)
1443 (default: True)
1444
1444
1445 ``binary``
1445 ``binary``
1446 This tool can merge binary files. (default: False, unless tool
1446 This tool can merge binary files. (default: False, unless tool
1447 was selected by file pattern match)
1447 was selected by file pattern match)
1448
1448
1449 ``symlink``
1449 ``symlink``
1450 This tool can merge symlinks. (default: False)
1450 This tool can merge symlinks. (default: False)
1451
1451
1452 ``check``
1452 ``check``
1453 A list of merge success-checking options:
1453 A list of merge success-checking options:
1454
1454
1455 ``changed``
1455 ``changed``
1456 Ask whether merge was successful when the merged file shows no changes.
1456 Ask whether merge was successful when the merged file shows no changes.
1457 ``conflicts``
1457 ``conflicts``
1458 Check whether there are conflicts even though the tool reported success.
1458 Check whether there are conflicts even though the tool reported success.
1459 ``prompt``
1459 ``prompt``
1460 Always prompt for merge success, regardless of success reported by tool.
1460 Always prompt for merge success, regardless of success reported by tool.
1461
1461
1462 ``fixeol``
1462 ``fixeol``
1463 Attempt to fix up EOL changes caused by the merge tool.
1463 Attempt to fix up EOL changes caused by the merge tool.
1464 (default: False)
1464 (default: False)
1465
1465
1466 ``gui``
1466 ``gui``
1467 This tool requires a graphical interface to run. (default: False)
1467 This tool requires a graphical interface to run. (default: False)
1468
1468
1469 ``mergemarkers``
1469 ``mergemarkers``
1470 Controls whether the labels passed via ``$labellocal``, ``$labelother``, and
1470 Controls whether the labels passed via ``$labellocal``, ``$labelother``, and
1471 ``$labelbase`` are ``detailed`` (respecting ``mergemarkertemplate``) or
1471 ``$labelbase`` are ``detailed`` (respecting ``mergemarkertemplate``) or
1472 ``basic``. If ``premerge`` is ``keep`` or ``keep-merge3``, the conflict
1472 ``basic``. If ``premerge`` is ``keep`` or ``keep-merge3``, the conflict
1473 markers generated during premerge will be ``detailed`` if either this option or
1473 markers generated during premerge will be ``detailed`` if either this option or
1474 the corresponding option in the ``[ui]`` section is ``detailed``.
1474 the corresponding option in the ``[ui]`` section is ``detailed``.
1475 (default: ``basic``)
1475 (default: ``basic``)
1476
1476
1477 ``mergemarkertemplate``
1477 ``mergemarkertemplate``
1478 This setting can be used to override ``mergemarkertemplate`` from the ``[ui]``
1478 This setting can be used to override ``mergemarkertemplate`` from the ``[ui]``
1479 section on a per-tool basis; this applies to the ``$label``-prefixed variables
1479 section on a per-tool basis; this applies to the ``$label``-prefixed variables
1480 and to the conflict markers that are generated if ``premerge`` is ``keep` or
1480 and to the conflict markers that are generated if ``premerge`` is ``keep` or
1481 ``keep-merge3``. See the corresponding variable in ``[ui]`` for more
1481 ``keep-merge3``. See the corresponding variable in ``[ui]`` for more
1482 information.
1482 information.
1483
1483
1484 .. container:: windows
1484 .. container:: windows
1485
1485
1486 ``regkey``
1486 ``regkey``
1487 Windows registry key which describes install location of this
1487 Windows registry key which describes install location of this
1488 tool. Mercurial will search for this key first under
1488 tool. Mercurial will search for this key first under
1489 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
1489 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
1490 (default: None)
1490 (default: None)
1491
1491
1492 ``regkeyalt``
1492 ``regkeyalt``
1493 An alternate Windows registry key to try if the first key is not
1493 An alternate Windows registry key to try if the first key is not
1494 found. The alternate key uses the same ``regname`` and ``regappend``
1494 found. The alternate key uses the same ``regname`` and ``regappend``
1495 semantics of the primary key. The most common use for this key
1495 semantics of the primary key. The most common use for this key
1496 is to search for 32bit applications on 64bit operating systems.
1496 is to search for 32bit applications on 64bit operating systems.
1497 (default: None)
1497 (default: None)
1498
1498
1499 ``regname``
1499 ``regname``
1500 Name of value to read from specified registry key.
1500 Name of value to read from specified registry key.
1501 (default: the unnamed (default) value)
1501 (default: the unnamed (default) value)
1502
1502
1503 ``regappend``
1503 ``regappend``
1504 String to append to the value read from the registry, typically
1504 String to append to the value read from the registry, typically
1505 the executable name of the tool.
1505 the executable name of the tool.
1506 (default: None)
1506 (default: None)
1507
1507
1508 ``pager``
1508 ``pager``
1509 ---------
1509 ---------
1510
1510
1511 Setting used to control when to paginate and with what external tool. See
1511 Setting used to control when to paginate and with what external tool. See
1512 :hg:`help pager` for details.
1512 :hg:`help pager` for details.
1513
1513
1514 ``pager``
1514 ``pager``
1515 Define the external tool used as pager.
1515 Define the external tool used as pager.
1516
1516
1517 If no pager is set, Mercurial uses the environment variable $PAGER.
1517 If no pager is set, Mercurial uses the environment variable $PAGER.
1518 If neither pager.pager, nor $PAGER is set, a default pager will be
1518 If neither pager.pager, nor $PAGER is set, a default pager will be
1519 used, typically `less` on Unix and `more` on Windows. Example::
1519 used, typically `less` on Unix and `more` on Windows. Example::
1520
1520
1521 [pager]
1521 [pager]
1522 pager = less -FRX
1522 pager = less -FRX
1523
1523
1524 ``ignore``
1524 ``ignore``
1525 List of commands to disable the pager for. Example::
1525 List of commands to disable the pager for. Example::
1526
1526
1527 [pager]
1527 [pager]
1528 ignore = version, help, update
1528 ignore = version, help, update
1529
1529
1530 ``patch``
1530 ``patch``
1531 ---------
1531 ---------
1532
1532
1533 Settings used when applying patches, for instance through the 'import'
1533 Settings used when applying patches, for instance through the 'import'
1534 command or with Mercurial Queues extension.
1534 command or with Mercurial Queues extension.
1535
1535
1536 ``eol``
1536 ``eol``
1537 When set to 'strict' patch content and patched files end of lines
1537 When set to 'strict' patch content and patched files end of lines
1538 are preserved. When set to ``lf`` or ``crlf``, both files end of
1538 are preserved. When set to ``lf`` or ``crlf``, both files end of
1539 lines are ignored when patching and the result line endings are
1539 lines are ignored when patching and the result line endings are
1540 normalized to either LF (Unix) or CRLF (Windows). When set to
1540 normalized to either LF (Unix) or CRLF (Windows). When set to
1541 ``auto``, end of lines are again ignored while patching but line
1541 ``auto``, end of lines are again ignored while patching but line
1542 endings in patched files are normalized to their original setting
1542 endings in patched files are normalized to their original setting
1543 on a per-file basis. If target file does not exist or has no end
1543 on a per-file basis. If target file does not exist or has no end
1544 of line, patch line endings are preserved.
1544 of line, patch line endings are preserved.
1545 (default: strict)
1545 (default: strict)
1546
1546
1547 ``fuzz``
1547 ``fuzz``
1548 The number of lines of 'fuzz' to allow when applying patches. This
1548 The number of lines of 'fuzz' to allow when applying patches. This
1549 controls how much context the patcher is allowed to ignore when
1549 controls how much context the patcher is allowed to ignore when
1550 trying to apply a patch.
1550 trying to apply a patch.
1551 (default: 2)
1551 (default: 2)
1552
1552
1553 ``paths``
1553 ``paths``
1554 ---------
1554 ---------
1555
1555
1556 Assigns symbolic names and behavior to repositories.
1556 Assigns symbolic names and behavior to repositories.
1557
1557
1558 Options are symbolic names defining the URL or directory that is the
1558 Options are symbolic names defining the URL or directory that is the
1559 location of the repository. Example::
1559 location of the repository. Example::
1560
1560
1561 [paths]
1561 [paths]
1562 my_server = https://example.com/my_repo
1562 my_server = https://example.com/my_repo
1563 local_path = /home/me/repo
1563 local_path = /home/me/repo
1564
1564
1565 These symbolic names can be used from the command line. To pull
1565 These symbolic names can be used from the command line. To pull
1566 from ``my_server``: :hg:`pull my_server`. To push to ``local_path``:
1566 from ``my_server``: :hg:`pull my_server`. To push to ``local_path``:
1567 :hg:`push local_path`.
1567 :hg:`push local_path`.
1568
1568
1569 Options containing colons (``:``) denote sub-options that can influence
1569 Options containing colons (``:``) denote sub-options that can influence
1570 behavior for that specific path. Example::
1570 behavior for that specific path. Example::
1571
1571
1572 [paths]
1572 [paths]
1573 my_server = https://example.com/my_path
1573 my_server = https://example.com/my_path
1574 my_server:pushurl = ssh://example.com/my_path
1574 my_server:pushurl = ssh://example.com/my_path
1575
1575
1576 The following sub-options can be defined:
1576 The following sub-options can be defined:
1577
1577
1578 ``pushurl``
1578 ``pushurl``
1579 The URL to use for push operations. If not defined, the location
1579 The URL to use for push operations. If not defined, the location
1580 defined by the path's main entry is used.
1580 defined by the path's main entry is used.
1581
1581
1582 ``pushrev``
1582 ``pushrev``
1583 A revset defining which revisions to push by default.
1583 A revset defining which revisions to push by default.
1584
1584
1585 When :hg:`push` is executed without a ``-r`` argument, the revset
1585 When :hg:`push` is executed without a ``-r`` argument, the revset
1586 defined by this sub-option is evaluated to determine what to push.
1586 defined by this sub-option is evaluated to determine what to push.
1587
1587
1588 For example, a value of ``.`` will push the working directory's
1588 For example, a value of ``.`` will push the working directory's
1589 revision by default.
1589 revision by default.
1590
1590
1591 Revsets specifying bookmarks will not result in the bookmark being
1591 Revsets specifying bookmarks will not result in the bookmark being
1592 pushed.
1592 pushed.
1593
1593
1594 The following special named paths exist:
1594 The following special named paths exist:
1595
1595
1596 ``default``
1596 ``default``
1597 The URL or directory to use when no source or remote is specified.
1597 The URL or directory to use when no source or remote is specified.
1598
1598
1599 :hg:`clone` will automatically define this path to the location the
1599 :hg:`clone` will automatically define this path to the location the
1600 repository was cloned from.
1600 repository was cloned from.
1601
1601
1602 ``default-push``
1602 ``default-push``
1603 (deprecated) The URL or directory for the default :hg:`push` location.
1603 (deprecated) The URL or directory for the default :hg:`push` location.
1604 ``default:pushurl`` should be used instead.
1604 ``default:pushurl`` should be used instead.
1605
1605
1606 ``phases``
1606 ``phases``
1607 ----------
1607 ----------
1608
1608
1609 Specifies default handling of phases. See :hg:`help phases` for more
1609 Specifies default handling of phases. See :hg:`help phases` for more
1610 information about working with phases.
1610 information about working with phases.
1611
1611
1612 ``publish``
1612 ``publish``
1613 Controls draft phase behavior when working as a server. When true,
1613 Controls draft phase behavior when working as a server. When true,
1614 pushed changesets are set to public in both client and server and
1614 pushed changesets are set to public in both client and server and
1615 pulled or cloned changesets are set to public in the client.
1615 pulled or cloned changesets are set to public in the client.
1616 (default: True)
1616 (default: True)
1617
1617
1618 ``new-commit``
1618 ``new-commit``
1619 Phase of newly-created commits.
1619 Phase of newly-created commits.
1620 (default: draft)
1620 (default: draft)
1621
1621
1622 ``checksubrepos``
1622 ``checksubrepos``
1623 Check the phase of the current revision of each subrepository. Allowed
1623 Check the phase of the current revision of each subrepository. Allowed
1624 values are "ignore", "follow" and "abort". For settings other than
1624 values are "ignore", "follow" and "abort". For settings other than
1625 "ignore", the phase of the current revision of each subrepository is
1625 "ignore", the phase of the current revision of each subrepository is
1626 checked before committing the parent repository. If any of those phases is
1626 checked before committing the parent repository. If any of those phases is
1627 greater than the phase of the parent repository (e.g. if a subrepo is in a
1627 greater than the phase of the parent repository (e.g. if a subrepo is in a
1628 "secret" phase while the parent repo is in "draft" phase), the commit is
1628 "secret" phase while the parent repo is in "draft" phase), the commit is
1629 either aborted (if checksubrepos is set to "abort") or the higher phase is
1629 either aborted (if checksubrepos is set to "abort") or the higher phase is
1630 used for the parent repository commit (if set to "follow").
1630 used for the parent repository commit (if set to "follow").
1631 (default: follow)
1631 (default: follow)
1632
1632
1633
1633
1634 ``profiling``
1634 ``profiling``
1635 -------------
1635 -------------
1636
1636
1637 Specifies profiling type, format, and file output. Two profilers are
1637 Specifies profiling type, format, and file output. Two profilers are
1638 supported: an instrumenting profiler (named ``ls``), and a sampling
1638 supported: an instrumenting profiler (named ``ls``), and a sampling
1639 profiler (named ``stat``).
1639 profiler (named ``stat``).
1640
1640
1641 In this section description, 'profiling data' stands for the raw data
1641 In this section description, 'profiling data' stands for the raw data
1642 collected during profiling, while 'profiling report' stands for a
1642 collected during profiling, while 'profiling report' stands for a
1643 statistical text report generated from the profiling data.
1643 statistical text report generated from the profiling data.
1644
1644
1645 ``enabled``
1645 ``enabled``
1646 Enable the profiler.
1646 Enable the profiler.
1647 (default: false)
1647 (default: false)
1648
1648
1649 This is equivalent to passing ``--profile`` on the command line.
1649 This is equivalent to passing ``--profile`` on the command line.
1650
1650
1651 ``type``
1651 ``type``
1652 The type of profiler to use.
1652 The type of profiler to use.
1653 (default: stat)
1653 (default: stat)
1654
1654
1655 ``ls``
1655 ``ls``
1656 Use Python's built-in instrumenting profiler. This profiler
1656 Use Python's built-in instrumenting profiler. This profiler
1657 works on all platforms, but each line number it reports is the
1657 works on all platforms, but each line number it reports is the
1658 first line of a function. This restriction makes it difficult to
1658 first line of a function. This restriction makes it difficult to
1659 identify the expensive parts of a non-trivial function.
1659 identify the expensive parts of a non-trivial function.
1660 ``stat``
1660 ``stat``
1661 Use a statistical profiler, statprof. This profiler is most
1661 Use a statistical profiler, statprof. This profiler is most
1662 useful for profiling commands that run for longer than about 0.1
1662 useful for profiling commands that run for longer than about 0.1
1663 seconds.
1663 seconds.
1664
1664
1665 ``format``
1665 ``format``
1666 Profiling format. Specific to the ``ls`` instrumenting profiler.
1666 Profiling format. Specific to the ``ls`` instrumenting profiler.
1667 (default: text)
1667 (default: text)
1668
1668
1669 ``text``
1669 ``text``
1670 Generate a profiling report. When saving to a file, it should be
1670 Generate a profiling report. When saving to a file, it should be
1671 noted that only the report is saved, and the profiling data is
1671 noted that only the report is saved, and the profiling data is
1672 not kept.
1672 not kept.
1673 ``kcachegrind``
1673 ``kcachegrind``
1674 Format profiling data for kcachegrind use: when saving to a
1674 Format profiling data for kcachegrind use: when saving to a
1675 file, the generated file can directly be loaded into
1675 file, the generated file can directly be loaded into
1676 kcachegrind.
1676 kcachegrind.
1677
1677
1678 ``statformat``
1678 ``statformat``
1679 Profiling format for the ``stat`` profiler.
1679 Profiling format for the ``stat`` profiler.
1680 (default: hotpath)
1680 (default: hotpath)
1681
1681
1682 ``hotpath``
1682 ``hotpath``
1683 Show a tree-based display containing the hot path of execution (where
1683 Show a tree-based display containing the hot path of execution (where
1684 most time was spent).
1684 most time was spent).
1685 ``bymethod``
1685 ``bymethod``
1686 Show a table of methods ordered by how frequently they are active.
1686 Show a table of methods ordered by how frequently they are active.
1687 ``byline``
1687 ``byline``
1688 Show a table of lines in files ordered by how frequently they are active.
1688 Show a table of lines in files ordered by how frequently they are active.
1689 ``json``
1689 ``json``
1690 Render profiling data as JSON.
1690 Render profiling data as JSON.
1691
1691
1692 ``frequency``
1692 ``frequency``
1693 Sampling frequency. Specific to the ``stat`` sampling profiler.
1693 Sampling frequency. Specific to the ``stat`` sampling profiler.
1694 (default: 1000)
1694 (default: 1000)
1695
1695
1696 ``output``
1696 ``output``
1697 File path where profiling data or report should be saved. If the
1697 File path where profiling data or report should be saved. If the
1698 file exists, it is replaced. (default: None, data is printed on
1698 file exists, it is replaced. (default: None, data is printed on
1699 stderr)
1699 stderr)
1700
1700
1701 ``sort``
1701 ``sort``
1702 Sort field. Specific to the ``ls`` instrumenting profiler.
1702 Sort field. Specific to the ``ls`` instrumenting profiler.
1703 One of ``callcount``, ``reccallcount``, ``totaltime`` and
1703 One of ``callcount``, ``reccallcount``, ``totaltime`` and
1704 ``inlinetime``.
1704 ``inlinetime``.
1705 (default: inlinetime)
1705 (default: inlinetime)
1706
1706
1707 ``time-track``
1707 ``time-track``
1708 Control if the stat profiler track ``cpu`` or ``real`` time.
1708 Control if the stat profiler track ``cpu`` or ``real`` time.
1709 (default: ``cpu``)
1709 (default: ``cpu``)
1710
1710
1711 ``limit``
1711 ``limit``
1712 Number of lines to show. Specific to the ``ls`` instrumenting profiler.
1712 Number of lines to show. Specific to the ``ls`` instrumenting profiler.
1713 (default: 30)
1713 (default: 30)
1714
1714
1715 ``nested``
1715 ``nested``
1716 Show at most this number of lines of drill-down info after each main entry.
1716 Show at most this number of lines of drill-down info after each main entry.
1717 This can help explain the difference between Total and Inline.
1717 This can help explain the difference between Total and Inline.
1718 Specific to the ``ls`` instrumenting profiler.
1718 Specific to the ``ls`` instrumenting profiler.
1719 (default: 0)
1719 (default: 0)
1720
1720
1721 ``showmin``
1721 ``showmin``
1722 Minimum fraction of samples an entry must have for it to be displayed.
1722 Minimum fraction of samples an entry must have for it to be displayed.
1723 Can be specified as a float between ``0.0`` and ``1.0`` or can have a
1723 Can be specified as a float between ``0.0`` and ``1.0`` or can have a
1724 ``%`` afterwards to allow values up to ``100``. e.g. ``5%``.
1724 ``%`` afterwards to allow values up to ``100``. e.g. ``5%``.
1725
1725
1726 Only used by the ``stat`` profiler.
1726 Only used by the ``stat`` profiler.
1727
1727
1728 For the ``hotpath`` format, default is ``0.05``.
1728 For the ``hotpath`` format, default is ``0.05``.
1729 For the ``chrome`` format, default is ``0.005``.
1729 For the ``chrome`` format, default is ``0.005``.
1730
1730
1731 The option is unused on other formats.
1731 The option is unused on other formats.
1732
1732
1733 ``showmax``
1733 ``showmax``
1734 Maximum fraction of samples an entry can have before it is ignored in
1734 Maximum fraction of samples an entry can have before it is ignored in
1735 display. Values format is the same as ``showmin``.
1735 display. Values format is the same as ``showmin``.
1736
1736
1737 Only used by the ``stat`` profiler.
1737 Only used by the ``stat`` profiler.
1738
1738
1739 For the ``chrome`` format, default is ``0.999``.
1739 For the ``chrome`` format, default is ``0.999``.
1740
1740
1741 The option is unused on other formats.
1741 The option is unused on other formats.
1742
1742
1743 ``progress``
1743 ``progress``
1744 ------------
1744 ------------
1745
1745
1746 Mercurial commands can draw progress bars that are as informative as
1746 Mercurial commands can draw progress bars that are as informative as
1747 possible. Some progress bars only offer indeterminate information, while others
1747 possible. Some progress bars only offer indeterminate information, while others
1748 have a definite end point.
1748 have a definite end point.
1749
1749
1750 ``delay``
1750 ``delay``
1751 Number of seconds (float) before showing the progress bar. (default: 3)
1751 Number of seconds (float) before showing the progress bar. (default: 3)
1752
1752
1753 ``changedelay``
1753 ``changedelay``
1754 Minimum delay before showing a new topic. When set to less than 3 * refresh,
1754 Minimum delay before showing a new topic. When set to less than 3 * refresh,
1755 that value will be used instead. (default: 1)
1755 that value will be used instead. (default: 1)
1756
1756
1757 ``estimateinterval``
1757 ``estimateinterval``
1758 Maximum sampling interval in seconds for speed and estimated time
1758 Maximum sampling interval in seconds for speed and estimated time
1759 calculation. (default: 60)
1759 calculation. (default: 60)
1760
1760
1761 ``refresh``
1761 ``refresh``
1762 Time in seconds between refreshes of the progress bar. (default: 0.1)
1762 Time in seconds between refreshes of the progress bar. (default: 0.1)
1763
1763
1764 ``format``
1764 ``format``
1765 Format of the progress bar.
1765 Format of the progress bar.
1766
1766
1767 Valid entries for the format field are ``topic``, ``bar``, ``number``,
1767 Valid entries for the format field are ``topic``, ``bar``, ``number``,
1768 ``unit``, ``estimate``, ``speed``, and ``item``. ``item`` defaults to the
1768 ``unit``, ``estimate``, ``speed``, and ``item``. ``item`` defaults to the
1769 last 20 characters of the item, but this can be changed by adding either
1769 last 20 characters of the item, but this can be changed by adding either
1770 ``-<num>`` which would take the last num characters, or ``+<num>`` for the
1770 ``-<num>`` which would take the last num characters, or ``+<num>`` for the
1771 first num characters.
1771 first num characters.
1772
1772
1773 (default: topic bar number estimate)
1773 (default: topic bar number estimate)
1774
1774
1775 ``width``
1775 ``width``
1776 If set, the maximum width of the progress information (that is, min(width,
1776 If set, the maximum width of the progress information (that is, min(width,
1777 term width) will be used).
1777 term width) will be used).
1778
1778
1779 ``clear-complete``
1779 ``clear-complete``
1780 Clear the progress bar after it's done. (default: True)
1780 Clear the progress bar after it's done. (default: True)
1781
1781
1782 ``disable``
1782 ``disable``
1783 If true, don't show a progress bar.
1783 If true, don't show a progress bar.
1784
1784
1785 ``assume-tty``
1785 ``assume-tty``
1786 If true, ALWAYS show a progress bar, unless disable is given.
1786 If true, ALWAYS show a progress bar, unless disable is given.
1787
1787
1788 ``rebase``
1788 ``rebase``
1789 ----------
1789 ----------
1790
1790
1791 ``evolution.allowdivergence``
1791 ``evolution.allowdivergence``
1792 Default to False, when True allow creating divergence when performing
1792 Default to False, when True allow creating divergence when performing
1793 rebase of obsolete changesets.
1793 rebase of obsolete changesets.
1794
1794
1795 ``revsetalias``
1795 ``revsetalias``
1796 ---------------
1796 ---------------
1797
1797
1798 Alias definitions for revsets. See :hg:`help revsets` for details.
1798 Alias definitions for revsets. See :hg:`help revsets` for details.
1799
1799
1800 ``storage``
1800 ``storage``
1801 -----------
1801 -----------
1802
1802
1803 Control the strategy Mercurial uses internally to store history. Options in this
1803 Control the strategy Mercurial uses internally to store history. Options in this
1804 category impact performance and repository size.
1804 category impact performance and repository size.
1805
1805
1806 ``revlog.optimize-delta-parent-choice``
1806 ``revlog.optimize-delta-parent-choice``
1807 When storing a merge revision, both parents will be equally considered as
1807 When storing a merge revision, both parents will be equally considered as
1808 a possible delta base. This results in better delta selection and improved
1808 a possible delta base. This results in better delta selection and improved
1809 revlog compression. This option is enabled by default.
1809 revlog compression. This option is enabled by default.
1810
1810
1811 Turning this option off can result in large increase of repository size for
1811 Turning this option off can result in large increase of repository size for
1812 repository with many merges.
1812 repository with many merges.
1813
1813
1814 ``server``
1814 ``server``
1815 ----------
1815 ----------
1816
1816
1817 Controls generic server settings.
1817 Controls generic server settings.
1818
1818
1819 ``bookmarks-pushkey-compat``
1819 ``bookmarks-pushkey-compat``
1820 Trigger pushkey hook when being pushed bookmark updates. This config exist
1820 Trigger pushkey hook when being pushed bookmark updates. This config exist
1821 for compatibility purpose (default to True)
1821 for compatibility purpose (default to True)
1822
1822
1823 If you use ``pushkey`` and ``pre-pushkey`` hooks to control bookmark
1823 If you use ``pushkey`` and ``pre-pushkey`` hooks to control bookmark
1824 movement we recommend you migrate them to ``txnclose-bookmark`` and
1824 movement we recommend you migrate them to ``txnclose-bookmark`` and
1825 ``pretxnclose-bookmark``.
1825 ``pretxnclose-bookmark``.
1826
1826
1827 ``compressionengines``
1827 ``compressionengines``
1828 List of compression engines and their relative priority to advertise
1828 List of compression engines and their relative priority to advertise
1829 to clients.
1829 to clients.
1830
1830
1831 The order of compression engines determines their priority, the first
1831 The order of compression engines determines their priority, the first
1832 having the highest priority. If a compression engine is not listed
1832 having the highest priority. If a compression engine is not listed
1833 here, it won't be advertised to clients.
1833 here, it won't be advertised to clients.
1834
1834
1835 If not set (the default), built-in defaults are used. Run
1835 If not set (the default), built-in defaults are used. Run
1836 :hg:`debuginstall` to list available compression engines and their
1836 :hg:`debuginstall` to list available compression engines and their
1837 default wire protocol priority.
1837 default wire protocol priority.
1838
1838
1839 Older Mercurial clients only support zlib compression and this setting
1839 Older Mercurial clients only support zlib compression and this setting
1840 has no effect for legacy clients.
1840 has no effect for legacy clients.
1841
1841
1842 ``uncompressed``
1842 ``uncompressed``
1843 Whether to allow clients to clone a repository using the
1843 Whether to allow clients to clone a repository using the
1844 uncompressed streaming protocol. This transfers about 40% more
1844 uncompressed streaming protocol. This transfers about 40% more
1845 data than a regular clone, but uses less memory and CPU on both
1845 data than a regular clone, but uses less memory and CPU on both
1846 server and client. Over a LAN (100 Mbps or better) or a very fast
1846 server and client. Over a LAN (100 Mbps or better) or a very fast
1847 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
1847 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
1848 regular clone. Over most WAN connections (anything slower than
1848 regular clone. Over most WAN connections (anything slower than
1849 about 6 Mbps), uncompressed streaming is slower, because of the
1849 about 6 Mbps), uncompressed streaming is slower, because of the
1850 extra data transfer overhead. This mode will also temporarily hold
1850 extra data transfer overhead. This mode will also temporarily hold
1851 the write lock while determining what data to transfer.
1851 the write lock while determining what data to transfer.
1852 (default: True)
1852 (default: True)
1853
1853
1854 ``uncompressedallowsecret``
1854 ``uncompressedallowsecret``
1855 Whether to allow stream clones when the repository contains secret
1855 Whether to allow stream clones when the repository contains secret
1856 changesets. (default: False)
1856 changesets. (default: False)
1857
1857
1858 ``preferuncompressed``
1858 ``preferuncompressed``
1859 When set, clients will try to use the uncompressed streaming
1859 When set, clients will try to use the uncompressed streaming
1860 protocol. (default: False)
1860 protocol. (default: False)
1861
1861
1862 ``disablefullbundle``
1862 ``disablefullbundle``
1863 When set, servers will refuse attempts to do pull-based clones.
1863 When set, servers will refuse attempts to do pull-based clones.
1864 If this option is set, ``preferuncompressed`` and/or clone bundles
1864 If this option is set, ``preferuncompressed`` and/or clone bundles
1865 are highly recommended. Partial clones will still be allowed.
1865 are highly recommended. Partial clones will still be allowed.
1866 (default: False)
1866 (default: False)
1867
1867
1868 ``streamunbundle``
1868 ``streamunbundle``
1869 When set, servers will apply data sent from the client directly,
1869 When set, servers will apply data sent from the client directly,
1870 otherwise it will be written to a temporary file first. This option
1870 otherwise it will be written to a temporary file first. This option
1871 effectively prevents concurrent pushes.
1871 effectively prevents concurrent pushes.
1872
1872
1873 ``pullbundle``
1873 ``pullbundle``
1874 When set, the server will check pullbundle.manifest for bundles
1874 When set, the server will check pullbundle.manifest for bundles
1875 covering the requested heads and common nodes. The first matching
1875 covering the requested heads and common nodes. The first matching
1876 entry will be streamed to the client.
1876 entry will be streamed to the client.
1877
1877
1878 For HTTP transport, the stream will still use zlib compression
1878 For HTTP transport, the stream will still use zlib compression
1879 for older clients.
1879 for older clients.
1880
1880
1881 ``concurrent-push-mode``
1881 ``concurrent-push-mode``
1882 Level of allowed race condition between two pushing clients.
1882 Level of allowed race condition between two pushing clients.
1883
1883
1884 - 'strict': push is abort if another client touched the repository
1884 - 'strict': push is abort if another client touched the repository
1885 while the push was preparing. (default)
1885 while the push was preparing. (default)
1886 - 'check-related': push is only aborted if it affects head that got also
1886 - 'check-related': push is only aborted if it affects head that got also
1887 affected while the push was preparing.
1887 affected while the push was preparing.
1888
1888
1889 This requires compatible client (version 4.3 and later). Old client will
1889 This requires compatible client (version 4.3 and later). Old client will
1890 use 'strict'.
1890 use 'strict'.
1891
1891
1892 ``validate``
1892 ``validate``
1893 Whether to validate the completeness of pushed changesets by
1893 Whether to validate the completeness of pushed changesets by
1894 checking that all new file revisions specified in manifests are
1894 checking that all new file revisions specified in manifests are
1895 present. (default: False)
1895 present. (default: False)
1896
1896
1897 ``maxhttpheaderlen``
1897 ``maxhttpheaderlen``
1898 Instruct HTTP clients not to send request headers longer than this
1898 Instruct HTTP clients not to send request headers longer than this
1899 many bytes. (default: 1024)
1899 many bytes. (default: 1024)
1900
1900
1901 ``bundle1``
1901 ``bundle1``
1902 Whether to allow clients to push and pull using the legacy bundle1
1902 Whether to allow clients to push and pull using the legacy bundle1
1903 exchange format. (default: True)
1903 exchange format. (default: True)
1904
1904
1905 ``bundle1gd``
1905 ``bundle1gd``
1906 Like ``bundle1`` but only used if the repository is using the
1906 Like ``bundle1`` but only used if the repository is using the
1907 *generaldelta* storage format. (default: True)
1907 *generaldelta* storage format. (default: True)
1908
1908
1909 ``bundle1.push``
1909 ``bundle1.push``
1910 Whether to allow clients to push using the legacy bundle1 exchange
1910 Whether to allow clients to push using the legacy bundle1 exchange
1911 format. (default: True)
1911 format. (default: True)
1912
1912
1913 ``bundle1gd.push``
1913 ``bundle1gd.push``
1914 Like ``bundle1.push`` but only used if the repository is using the
1914 Like ``bundle1.push`` but only used if the repository is using the
1915 *generaldelta* storage format. (default: True)
1915 *generaldelta* storage format. (default: True)
1916
1916
1917 ``bundle1.pull``
1917 ``bundle1.pull``
1918 Whether to allow clients to pull using the legacy bundle1 exchange
1918 Whether to allow clients to pull using the legacy bundle1 exchange
1919 format. (default: True)
1919 format. (default: True)
1920
1920
1921 ``bundle1gd.pull``
1921 ``bundle1gd.pull``
1922 Like ``bundle1.pull`` but only used if the repository is using the
1922 Like ``bundle1.pull`` but only used if the repository is using the
1923 *generaldelta* storage format. (default: True)
1923 *generaldelta* storage format. (default: True)
1924
1924
1925 Large repositories using the *generaldelta* storage format should
1925 Large repositories using the *generaldelta* storage format should
1926 consider setting this option because converting *generaldelta*
1926 consider setting this option because converting *generaldelta*
1927 repositories to the exchange format required by the bundle1 data
1927 repositories to the exchange format required by the bundle1 data
1928 format can consume a lot of CPU.
1928 format can consume a lot of CPU.
1929
1929
1930 ``bundle2.stream``
1931 Whether to allow clients to pull using the bundle2 streaming protocol.
1932 (default: False)
1933
1930 ``zliblevel``
1934 ``zliblevel``
1931 Integer between ``-1`` and ``9`` that controls the zlib compression level
1935 Integer between ``-1`` and ``9`` that controls the zlib compression level
1932 for wire protocol commands that send zlib compressed output (notably the
1936 for wire protocol commands that send zlib compressed output (notably the
1933 commands that send repository history data).
1937 commands that send repository history data).
1934
1938
1935 The default (``-1``) uses the default zlib compression level, which is
1939 The default (``-1``) uses the default zlib compression level, which is
1936 likely equivalent to ``6``. ``0`` means no compression. ``9`` means
1940 likely equivalent to ``6``. ``0`` means no compression. ``9`` means
1937 maximum compression.
1941 maximum compression.
1938
1942
1939 Setting this option allows server operators to make trade-offs between
1943 Setting this option allows server operators to make trade-offs between
1940 bandwidth and CPU used. Lowering the compression lowers CPU utilization
1944 bandwidth and CPU used. Lowering the compression lowers CPU utilization
1941 but sends more bytes to clients.
1945 but sends more bytes to clients.
1942
1946
1943 This option only impacts the HTTP server.
1947 This option only impacts the HTTP server.
1944
1948
1945 ``zstdlevel``
1949 ``zstdlevel``
1946 Integer between ``1`` and ``22`` that controls the zstd compression level
1950 Integer between ``1`` and ``22`` that controls the zstd compression level
1947 for wire protocol commands. ``1`` is the minimal amount of compression and
1951 for wire protocol commands. ``1`` is the minimal amount of compression and
1948 ``22`` is the highest amount of compression.
1952 ``22`` is the highest amount of compression.
1949
1953
1950 The default (``3``) should be significantly faster than zlib while likely
1954 The default (``3``) should be significantly faster than zlib while likely
1951 delivering better compression ratios.
1955 delivering better compression ratios.
1952
1956
1953 This option only impacts the HTTP server.
1957 This option only impacts the HTTP server.
1954
1958
1955 See also ``server.zliblevel``.
1959 See also ``server.zliblevel``.
1956
1960
1957 ``smtp``
1961 ``smtp``
1958 --------
1962 --------
1959
1963
1960 Configuration for extensions that need to send email messages.
1964 Configuration for extensions that need to send email messages.
1961
1965
1962 ``host``
1966 ``host``
1963 Host name of mail server, e.g. "mail.example.com".
1967 Host name of mail server, e.g. "mail.example.com".
1964
1968
1965 ``port``
1969 ``port``
1966 Optional. Port to connect to on mail server. (default: 465 if
1970 Optional. Port to connect to on mail server. (default: 465 if
1967 ``tls`` is smtps; 25 otherwise)
1971 ``tls`` is smtps; 25 otherwise)
1968
1972
1969 ``tls``
1973 ``tls``
1970 Optional. Method to enable TLS when connecting to mail server: starttls,
1974 Optional. Method to enable TLS when connecting to mail server: starttls,
1971 smtps or none. (default: none)
1975 smtps or none. (default: none)
1972
1976
1973 ``username``
1977 ``username``
1974 Optional. User name for authenticating with the SMTP server.
1978 Optional. User name for authenticating with the SMTP server.
1975 (default: None)
1979 (default: None)
1976
1980
1977 ``password``
1981 ``password``
1978 Optional. Password for authenticating with the SMTP server. If not
1982 Optional. Password for authenticating with the SMTP server. If not
1979 specified, interactive sessions will prompt the user for a
1983 specified, interactive sessions will prompt the user for a
1980 password; non-interactive sessions will fail. (default: None)
1984 password; non-interactive sessions will fail. (default: None)
1981
1985
1982 ``local_hostname``
1986 ``local_hostname``
1983 Optional. The hostname that the sender can use to identify
1987 Optional. The hostname that the sender can use to identify
1984 itself to the MTA.
1988 itself to the MTA.
1985
1989
1986
1990
1987 ``subpaths``
1991 ``subpaths``
1988 ------------
1992 ------------
1989
1993
1990 Subrepository source URLs can go stale if a remote server changes name
1994 Subrepository source URLs can go stale if a remote server changes name
1991 or becomes temporarily unavailable. This section lets you define
1995 or becomes temporarily unavailable. This section lets you define
1992 rewrite rules of the form::
1996 rewrite rules of the form::
1993
1997
1994 <pattern> = <replacement>
1998 <pattern> = <replacement>
1995
1999
1996 where ``pattern`` is a regular expression matching a subrepository
2000 where ``pattern`` is a regular expression matching a subrepository
1997 source URL and ``replacement`` is the replacement string used to
2001 source URL and ``replacement`` is the replacement string used to
1998 rewrite it. Groups can be matched in ``pattern`` and referenced in
2002 rewrite it. Groups can be matched in ``pattern`` and referenced in
1999 ``replacements``. For instance::
2003 ``replacements``. For instance::
2000
2004
2001 http://server/(.*)-hg/ = http://hg.server/\1/
2005 http://server/(.*)-hg/ = http://hg.server/\1/
2002
2006
2003 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
2007 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
2004
2008
2005 Relative subrepository paths are first made absolute, and the
2009 Relative subrepository paths are first made absolute, and the
2006 rewrite rules are then applied on the full (absolute) path. If ``pattern``
2010 rewrite rules are then applied on the full (absolute) path. If ``pattern``
2007 doesn't match the full path, an attempt is made to apply it on the
2011 doesn't match the full path, an attempt is made to apply it on the
2008 relative path alone. The rules are applied in definition order.
2012 relative path alone. The rules are applied in definition order.
2009
2013
2010 ``subrepos``
2014 ``subrepos``
2011 ------------
2015 ------------
2012
2016
2013 This section contains options that control the behavior of the
2017 This section contains options that control the behavior of the
2014 subrepositories feature. See also :hg:`help subrepos`.
2018 subrepositories feature. See also :hg:`help subrepos`.
2015
2019
2016 Security note: auditing in Mercurial is known to be insufficient to
2020 Security note: auditing in Mercurial is known to be insufficient to
2017 prevent clone-time code execution with carefully constructed Git
2021 prevent clone-time code execution with carefully constructed Git
2018 subrepos. It is unknown if a similar detect is present in Subversion
2022 subrepos. It is unknown if a similar detect is present in Subversion
2019 subrepos. Both Git and Subversion subrepos are disabled by default
2023 subrepos. Both Git and Subversion subrepos are disabled by default
2020 out of security concerns. These subrepo types can be enabled using
2024 out of security concerns. These subrepo types can be enabled using
2021 the respective options below.
2025 the respective options below.
2022
2026
2023 ``allowed``
2027 ``allowed``
2024 Whether subrepositories are allowed in the working directory.
2028 Whether subrepositories are allowed in the working directory.
2025
2029
2026 When false, commands involving subrepositories (like :hg:`update`)
2030 When false, commands involving subrepositories (like :hg:`update`)
2027 will fail for all subrepository types.
2031 will fail for all subrepository types.
2028 (default: true)
2032 (default: true)
2029
2033
2030 ``hg:allowed``
2034 ``hg:allowed``
2031 Whether Mercurial subrepositories are allowed in the working
2035 Whether Mercurial subrepositories are allowed in the working
2032 directory. This option only has an effect if ``subrepos.allowed``
2036 directory. This option only has an effect if ``subrepos.allowed``
2033 is true.
2037 is true.
2034 (default: true)
2038 (default: true)
2035
2039
2036 ``git:allowed``
2040 ``git:allowed``
2037 Whether Git subrepositories are allowed in the working directory.
2041 Whether Git subrepositories are allowed in the working directory.
2038 This option only has an effect if ``subrepos.allowed`` is true.
2042 This option only has an effect if ``subrepos.allowed`` is true.
2039
2043
2040 See the security note above before enabling Git subrepos.
2044 See the security note above before enabling Git subrepos.
2041 (default: false)
2045 (default: false)
2042
2046
2043 ``svn:allowed``
2047 ``svn:allowed``
2044 Whether Subversion subrepositories are allowed in the working
2048 Whether Subversion subrepositories are allowed in the working
2045 directory. This option only has an effect if ``subrepos.allowed``
2049 directory. This option only has an effect if ``subrepos.allowed``
2046 is true.
2050 is true.
2047
2051
2048 See the security note above before enabling Subversion subrepos.
2052 See the security note above before enabling Subversion subrepos.
2049 (default: false)
2053 (default: false)
2050
2054
2051 ``templatealias``
2055 ``templatealias``
2052 -----------------
2056 -----------------
2053
2057
2054 Alias definitions for templates. See :hg:`help templates` for details.
2058 Alias definitions for templates. See :hg:`help templates` for details.
2055
2059
2056 ``templates``
2060 ``templates``
2057 -------------
2061 -------------
2058
2062
2059 Use the ``[templates]`` section to define template strings.
2063 Use the ``[templates]`` section to define template strings.
2060 See :hg:`help templates` for details.
2064 See :hg:`help templates` for details.
2061
2065
2062 ``trusted``
2066 ``trusted``
2063 -----------
2067 -----------
2064
2068
2065 Mercurial will not use the settings in the
2069 Mercurial will not use the settings in the
2066 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
2070 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
2067 user or to a trusted group, as various hgrc features allow arbitrary
2071 user or to a trusted group, as various hgrc features allow arbitrary
2068 commands to be run. This issue is often encountered when configuring
2072 commands to be run. This issue is often encountered when configuring
2069 hooks or extensions for shared repositories or servers. However,
2073 hooks or extensions for shared repositories or servers. However,
2070 the web interface will use some safe settings from the ``[web]``
2074 the web interface will use some safe settings from the ``[web]``
2071 section.
2075 section.
2072
2076
2073 This section specifies what users and groups are trusted. The
2077 This section specifies what users and groups are trusted. The
2074 current user is always trusted. To trust everybody, list a user or a
2078 current user is always trusted. To trust everybody, list a user or a
2075 group with name ``*``. These settings must be placed in an
2079 group with name ``*``. These settings must be placed in an
2076 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
2080 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
2077 user or service running Mercurial.
2081 user or service running Mercurial.
2078
2082
2079 ``users``
2083 ``users``
2080 Comma-separated list of trusted users.
2084 Comma-separated list of trusted users.
2081
2085
2082 ``groups``
2086 ``groups``
2083 Comma-separated list of trusted groups.
2087 Comma-separated list of trusted groups.
2084
2088
2085
2089
2086 ``ui``
2090 ``ui``
2087 ------
2091 ------
2088
2092
2089 User interface controls.
2093 User interface controls.
2090
2094
2091 ``archivemeta``
2095 ``archivemeta``
2092 Whether to include the .hg_archival.txt file containing meta data
2096 Whether to include the .hg_archival.txt file containing meta data
2093 (hashes for the repository base and for tip) in archives created
2097 (hashes for the repository base and for tip) in archives created
2094 by the :hg:`archive` command or downloaded via hgweb.
2098 by the :hg:`archive` command or downloaded via hgweb.
2095 (default: True)
2099 (default: True)
2096
2100
2097 ``askusername``
2101 ``askusername``
2098 Whether to prompt for a username when committing. If True, and
2102 Whether to prompt for a username when committing. If True, and
2099 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
2103 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
2100 be prompted to enter a username. If no username is entered, the
2104 be prompted to enter a username. If no username is entered, the
2101 default ``USER@HOST`` is used instead.
2105 default ``USER@HOST`` is used instead.
2102 (default: False)
2106 (default: False)
2103
2107
2104 ``clonebundles``
2108 ``clonebundles``
2105 Whether the "clone bundles" feature is enabled.
2109 Whether the "clone bundles" feature is enabled.
2106
2110
2107 When enabled, :hg:`clone` may download and apply a server-advertised
2111 When enabled, :hg:`clone` may download and apply a server-advertised
2108 bundle file from a URL instead of using the normal exchange mechanism.
2112 bundle file from a URL instead of using the normal exchange mechanism.
2109
2113
2110 This can likely result in faster and more reliable clones.
2114 This can likely result in faster and more reliable clones.
2111
2115
2112 (default: True)
2116 (default: True)
2113
2117
2114 ``clonebundlefallback``
2118 ``clonebundlefallback``
2115 Whether failure to apply an advertised "clone bundle" from a server
2119 Whether failure to apply an advertised "clone bundle" from a server
2116 should result in fallback to a regular clone.
2120 should result in fallback to a regular clone.
2117
2121
2118 This is disabled by default because servers advertising "clone
2122 This is disabled by default because servers advertising "clone
2119 bundles" often do so to reduce server load. If advertised bundles
2123 bundles" often do so to reduce server load. If advertised bundles
2120 start mass failing and clients automatically fall back to a regular
2124 start mass failing and clients automatically fall back to a regular
2121 clone, this would add significant and unexpected load to the server
2125 clone, this would add significant and unexpected load to the server
2122 since the server is expecting clone operations to be offloaded to
2126 since the server is expecting clone operations to be offloaded to
2123 pre-generated bundles. Failing fast (the default behavior) ensures
2127 pre-generated bundles. Failing fast (the default behavior) ensures
2124 clients don't overwhelm the server when "clone bundle" application
2128 clients don't overwhelm the server when "clone bundle" application
2125 fails.
2129 fails.
2126
2130
2127 (default: False)
2131 (default: False)
2128
2132
2129 ``clonebundleprefers``
2133 ``clonebundleprefers``
2130 Defines preferences for which "clone bundles" to use.
2134 Defines preferences for which "clone bundles" to use.
2131
2135
2132 Servers advertising "clone bundles" may advertise multiple available
2136 Servers advertising "clone bundles" may advertise multiple available
2133 bundles. Each bundle may have different attributes, such as the bundle
2137 bundles. Each bundle may have different attributes, such as the bundle
2134 type and compression format. This option is used to prefer a particular
2138 type and compression format. This option is used to prefer a particular
2135 bundle over another.
2139 bundle over another.
2136
2140
2137 The following keys are defined by Mercurial:
2141 The following keys are defined by Mercurial:
2138
2142
2139 BUNDLESPEC
2143 BUNDLESPEC
2140 A bundle type specifier. These are strings passed to :hg:`bundle -t`.
2144 A bundle type specifier. These are strings passed to :hg:`bundle -t`.
2141 e.g. ``gzip-v2`` or ``bzip2-v1``.
2145 e.g. ``gzip-v2`` or ``bzip2-v1``.
2142
2146
2143 COMPRESSION
2147 COMPRESSION
2144 The compression format of the bundle. e.g. ``gzip`` and ``bzip2``.
2148 The compression format of the bundle. e.g. ``gzip`` and ``bzip2``.
2145
2149
2146 Server operators may define custom keys.
2150 Server operators may define custom keys.
2147
2151
2148 Example values: ``COMPRESSION=bzip2``,
2152 Example values: ``COMPRESSION=bzip2``,
2149 ``BUNDLESPEC=gzip-v2, COMPRESSION=gzip``.
2153 ``BUNDLESPEC=gzip-v2, COMPRESSION=gzip``.
2150
2154
2151 By default, the first bundle advertised by the server is used.
2155 By default, the first bundle advertised by the server is used.
2152
2156
2153 ``color``
2157 ``color``
2154 When to colorize output. Possible value are Boolean ("yes" or "no"), or
2158 When to colorize output. Possible value are Boolean ("yes" or "no"), or
2155 "debug", or "always". (default: "yes"). "yes" will use color whenever it
2159 "debug", or "always". (default: "yes"). "yes" will use color whenever it
2156 seems possible. See :hg:`help color` for details.
2160 seems possible. See :hg:`help color` for details.
2157
2161
2158 ``commitsubrepos``
2162 ``commitsubrepos``
2159 Whether to commit modified subrepositories when committing the
2163 Whether to commit modified subrepositories when committing the
2160 parent repository. If False and one subrepository has uncommitted
2164 parent repository. If False and one subrepository has uncommitted
2161 changes, abort the commit.
2165 changes, abort the commit.
2162 (default: False)
2166 (default: False)
2163
2167
2164 ``debug``
2168 ``debug``
2165 Print debugging information. (default: False)
2169 Print debugging information. (default: False)
2166
2170
2167 ``editor``
2171 ``editor``
2168 The editor to use during a commit. (default: ``$EDITOR`` or ``vi``)
2172 The editor to use during a commit. (default: ``$EDITOR`` or ``vi``)
2169
2173
2170 ``fallbackencoding``
2174 ``fallbackencoding``
2171 Encoding to try if it's not possible to decode the changelog using
2175 Encoding to try if it's not possible to decode the changelog using
2172 UTF-8. (default: ISO-8859-1)
2176 UTF-8. (default: ISO-8859-1)
2173
2177
2174 ``graphnodetemplate``
2178 ``graphnodetemplate``
2175 The template used to print changeset nodes in an ASCII revision graph.
2179 The template used to print changeset nodes in an ASCII revision graph.
2176 (default: ``{graphnode}``)
2180 (default: ``{graphnode}``)
2177
2181
2178 ``ignore``
2182 ``ignore``
2179 A file to read per-user ignore patterns from. This file should be
2183 A file to read per-user ignore patterns from. This file should be
2180 in the same format as a repository-wide .hgignore file. Filenames
2184 in the same format as a repository-wide .hgignore file. Filenames
2181 are relative to the repository root. This option supports hook syntax,
2185 are relative to the repository root. This option supports hook syntax,
2182 so if you want to specify multiple ignore files, you can do so by
2186 so if you want to specify multiple ignore files, you can do so by
2183 setting something like ``ignore.other = ~/.hgignore2``. For details
2187 setting something like ``ignore.other = ~/.hgignore2``. For details
2184 of the ignore file format, see the ``hgignore(5)`` man page.
2188 of the ignore file format, see the ``hgignore(5)`` man page.
2185
2189
2186 ``interactive``
2190 ``interactive``
2187 Allow to prompt the user. (default: True)
2191 Allow to prompt the user. (default: True)
2188
2192
2189 ``interface``
2193 ``interface``
2190 Select the default interface for interactive features (default: text).
2194 Select the default interface for interactive features (default: text).
2191 Possible values are 'text' and 'curses'.
2195 Possible values are 'text' and 'curses'.
2192
2196
2193 ``interface.chunkselector``
2197 ``interface.chunkselector``
2194 Select the interface for change recording (e.g. :hg:`commit -i`).
2198 Select the interface for change recording (e.g. :hg:`commit -i`).
2195 Possible values are 'text' and 'curses'.
2199 Possible values are 'text' and 'curses'.
2196 This config overrides the interface specified by ui.interface.
2200 This config overrides the interface specified by ui.interface.
2197
2201
2198 ``large-file-limit``
2202 ``large-file-limit``
2199 Largest file size that gives no memory use warning.
2203 Largest file size that gives no memory use warning.
2200 Possible values are integers or 0 to disable the check.
2204 Possible values are integers or 0 to disable the check.
2201 (default: 10000000)
2205 (default: 10000000)
2202
2206
2203 ``logtemplate``
2207 ``logtemplate``
2204 Template string for commands that print changesets.
2208 Template string for commands that print changesets.
2205
2209
2206 ``merge``
2210 ``merge``
2207 The conflict resolution program to use during a manual merge.
2211 The conflict resolution program to use during a manual merge.
2208 For more information on merge tools see :hg:`help merge-tools`.
2212 For more information on merge tools see :hg:`help merge-tools`.
2209 For configuring merge tools see the ``[merge-tools]`` section.
2213 For configuring merge tools see the ``[merge-tools]`` section.
2210
2214
2211 ``mergemarkers``
2215 ``mergemarkers``
2212 Sets the merge conflict marker label styling. The ``detailed``
2216 Sets the merge conflict marker label styling. The ``detailed``
2213 style uses the ``mergemarkertemplate`` setting to style the labels.
2217 style uses the ``mergemarkertemplate`` setting to style the labels.
2214 The ``basic`` style just uses 'local' and 'other' as the marker label.
2218 The ``basic`` style just uses 'local' and 'other' as the marker label.
2215 One of ``basic`` or ``detailed``.
2219 One of ``basic`` or ``detailed``.
2216 (default: ``basic``)
2220 (default: ``basic``)
2217
2221
2218 ``mergemarkertemplate``
2222 ``mergemarkertemplate``
2219 The template used to print the commit description next to each conflict
2223 The template used to print the commit description next to each conflict
2220 marker during merge conflicts. See :hg:`help templates` for the template
2224 marker during merge conflicts. See :hg:`help templates` for the template
2221 format.
2225 format.
2222
2226
2223 Defaults to showing the hash, tags, branches, bookmarks, author, and
2227 Defaults to showing the hash, tags, branches, bookmarks, author, and
2224 the first line of the commit description.
2228 the first line of the commit description.
2225
2229
2226 If you use non-ASCII characters in names for tags, branches, bookmarks,
2230 If you use non-ASCII characters in names for tags, branches, bookmarks,
2227 authors, and/or commit descriptions, you must pay attention to encodings of
2231 authors, and/or commit descriptions, you must pay attention to encodings of
2228 managed files. At template expansion, non-ASCII characters use the encoding
2232 managed files. At template expansion, non-ASCII characters use the encoding
2229 specified by the ``--encoding`` global option, ``HGENCODING`` or other
2233 specified by the ``--encoding`` global option, ``HGENCODING`` or other
2230 environment variables that govern your locale. If the encoding of the merge
2234 environment variables that govern your locale. If the encoding of the merge
2231 markers is different from the encoding of the merged files,
2235 markers is different from the encoding of the merged files,
2232 serious problems may occur.
2236 serious problems may occur.
2233
2237
2234 Can be overridden per-merge-tool, see the ``[merge-tools]`` section.
2238 Can be overridden per-merge-tool, see the ``[merge-tools]`` section.
2235
2239
2236 ``origbackuppath``
2240 ``origbackuppath``
2237 The path to a directory used to store generated .orig files. If the path is
2241 The path to a directory used to store generated .orig files. If the path is
2238 not a directory, one will be created. If set, files stored in this
2242 not a directory, one will be created. If set, files stored in this
2239 directory have the same name as the original file and do not have a .orig
2243 directory have the same name as the original file and do not have a .orig
2240 suffix.
2244 suffix.
2241
2245
2242 ``paginate``
2246 ``paginate``
2243 Control the pagination of command output (default: True). See :hg:`help pager`
2247 Control the pagination of command output (default: True). See :hg:`help pager`
2244 for details.
2248 for details.
2245
2249
2246 ``patch``
2250 ``patch``
2247 An optional external tool that ``hg import`` and some extensions
2251 An optional external tool that ``hg import`` and some extensions
2248 will use for applying patches. By default Mercurial uses an
2252 will use for applying patches. By default Mercurial uses an
2249 internal patch utility. The external tool must work as the common
2253 internal patch utility. The external tool must work as the common
2250 Unix ``patch`` program. In particular, it must accept a ``-p``
2254 Unix ``patch`` program. In particular, it must accept a ``-p``
2251 argument to strip patch headers, a ``-d`` argument to specify the
2255 argument to strip patch headers, a ``-d`` argument to specify the
2252 current directory, a file name to patch, and a patch file to take
2256 current directory, a file name to patch, and a patch file to take
2253 from stdin.
2257 from stdin.
2254
2258
2255 It is possible to specify a patch tool together with extra
2259 It is possible to specify a patch tool together with extra
2256 arguments. For example, setting this option to ``patch --merge``
2260 arguments. For example, setting this option to ``patch --merge``
2257 will use the ``patch`` program with its 2-way merge option.
2261 will use the ``patch`` program with its 2-way merge option.
2258
2262
2259 ``portablefilenames``
2263 ``portablefilenames``
2260 Check for portable filenames. Can be ``warn``, ``ignore`` or ``abort``.
2264 Check for portable filenames. Can be ``warn``, ``ignore`` or ``abort``.
2261 (default: ``warn``)
2265 (default: ``warn``)
2262
2266
2263 ``warn``
2267 ``warn``
2264 Print a warning message on POSIX platforms, if a file with a non-portable
2268 Print a warning message on POSIX platforms, if a file with a non-portable
2265 filename is added (e.g. a file with a name that can't be created on
2269 filename is added (e.g. a file with a name that can't be created on
2266 Windows because it contains reserved parts like ``AUX``, reserved
2270 Windows because it contains reserved parts like ``AUX``, reserved
2267 characters like ``:``, or would cause a case collision with an existing
2271 characters like ``:``, or would cause a case collision with an existing
2268 file).
2272 file).
2269
2273
2270 ``ignore``
2274 ``ignore``
2271 Don't print a warning.
2275 Don't print a warning.
2272
2276
2273 ``abort``
2277 ``abort``
2274 The command is aborted.
2278 The command is aborted.
2275
2279
2276 ``true``
2280 ``true``
2277 Alias for ``warn``.
2281 Alias for ``warn``.
2278
2282
2279 ``false``
2283 ``false``
2280 Alias for ``ignore``.
2284 Alias for ``ignore``.
2281
2285
2282 .. container:: windows
2286 .. container:: windows
2283
2287
2284 On Windows, this configuration option is ignored and the command aborted.
2288 On Windows, this configuration option is ignored and the command aborted.
2285
2289
2286 ``quiet``
2290 ``quiet``
2287 Reduce the amount of output printed.
2291 Reduce the amount of output printed.
2288 (default: False)
2292 (default: False)
2289
2293
2290 ``remotecmd``
2294 ``remotecmd``
2291 Remote command to use for clone/push/pull operations.
2295 Remote command to use for clone/push/pull operations.
2292 (default: ``hg``)
2296 (default: ``hg``)
2293
2297
2294 ``report_untrusted``
2298 ``report_untrusted``
2295 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
2299 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
2296 trusted user or group.
2300 trusted user or group.
2297 (default: True)
2301 (default: True)
2298
2302
2299 ``slash``
2303 ``slash``
2300 (Deprecated. Use ``slashpath`` template filter instead.)
2304 (Deprecated. Use ``slashpath`` template filter instead.)
2301
2305
2302 Display paths using a slash (``/``) as the path separator. This
2306 Display paths using a slash (``/``) as the path separator. This
2303 only makes a difference on systems where the default path
2307 only makes a difference on systems where the default path
2304 separator is not the slash character (e.g. Windows uses the
2308 separator is not the slash character (e.g. Windows uses the
2305 backslash character (``\``)).
2309 backslash character (``\``)).
2306 (default: False)
2310 (default: False)
2307
2311
2308 ``statuscopies``
2312 ``statuscopies``
2309 Display copies in the status command.
2313 Display copies in the status command.
2310
2314
2311 ``ssh``
2315 ``ssh``
2312 Command to use for SSH connections. (default: ``ssh``)
2316 Command to use for SSH connections. (default: ``ssh``)
2313
2317
2314 ``ssherrorhint``
2318 ``ssherrorhint``
2315 A hint shown to the user in the case of SSH error (e.g.
2319 A hint shown to the user in the case of SSH error (e.g.
2316 ``Please see http://company/internalwiki/ssh.html``)
2320 ``Please see http://company/internalwiki/ssh.html``)
2317
2321
2318 ``strict``
2322 ``strict``
2319 Require exact command names, instead of allowing unambiguous
2323 Require exact command names, instead of allowing unambiguous
2320 abbreviations. (default: False)
2324 abbreviations. (default: False)
2321
2325
2322 ``style``
2326 ``style``
2323 Name of style to use for command output.
2327 Name of style to use for command output.
2324
2328
2325 ``supportcontact``
2329 ``supportcontact``
2326 A URL where users should report a Mercurial traceback. Use this if you are a
2330 A URL where users should report a Mercurial traceback. Use this if you are a
2327 large organisation with its own Mercurial deployment process and crash
2331 large organisation with its own Mercurial deployment process and crash
2328 reports should be addressed to your internal support.
2332 reports should be addressed to your internal support.
2329
2333
2330 ``textwidth``
2334 ``textwidth``
2331 Maximum width of help text. A longer line generated by ``hg help`` or
2335 Maximum width of help text. A longer line generated by ``hg help`` or
2332 ``hg subcommand --help`` will be broken after white space to get this
2336 ``hg subcommand --help`` will be broken after white space to get this
2333 width or the terminal width, whichever comes first.
2337 width or the terminal width, whichever comes first.
2334 A non-positive value will disable this and the terminal width will be
2338 A non-positive value will disable this and the terminal width will be
2335 used. (default: 78)
2339 used. (default: 78)
2336
2340
2337 ``timeout``
2341 ``timeout``
2338 The timeout used when a lock is held (in seconds), a negative value
2342 The timeout used when a lock is held (in seconds), a negative value
2339 means no timeout. (default: 600)
2343 means no timeout. (default: 600)
2340
2344
2341 ``timeout.warn``
2345 ``timeout.warn``
2342 Time (in seconds) before a warning is printed about held lock. A negative
2346 Time (in seconds) before a warning is printed about held lock. A negative
2343 value means no warning. (default: 0)
2347 value means no warning. (default: 0)
2344
2348
2345 ``traceback``
2349 ``traceback``
2346 Mercurial always prints a traceback when an unknown exception
2350 Mercurial always prints a traceback when an unknown exception
2347 occurs. Setting this to True will make Mercurial print a traceback
2351 occurs. Setting this to True will make Mercurial print a traceback
2348 on all exceptions, even those recognized by Mercurial (such as
2352 on all exceptions, even those recognized by Mercurial (such as
2349 IOError or MemoryError). (default: False)
2353 IOError or MemoryError). (default: False)
2350
2354
2351 ``tweakdefaults``
2355 ``tweakdefaults``
2352
2356
2353 By default Mercurial's behavior changes very little from release
2357 By default Mercurial's behavior changes very little from release
2354 to release, but over time the recommended config settings
2358 to release, but over time the recommended config settings
2355 shift. Enable this config to opt in to get automatic tweaks to
2359 shift. Enable this config to opt in to get automatic tweaks to
2356 Mercurial's behavior over time. This config setting will have no
2360 Mercurial's behavior over time. This config setting will have no
2357 effect if ``HGPLAIN` is set or ``HGPLAINEXCEPT`` is set and does
2361 effect if ``HGPLAIN` is set or ``HGPLAINEXCEPT`` is set and does
2358 not include ``tweakdefaults``. (default: False)
2362 not include ``tweakdefaults``. (default: False)
2359
2363
2360 ``username``
2364 ``username``
2361 The committer of a changeset created when running "commit".
2365 The committer of a changeset created when running "commit".
2362 Typically a person's name and email address, e.g. ``Fred Widget
2366 Typically a person's name and email address, e.g. ``Fred Widget
2363 <fred@example.com>``. Environment variables in the
2367 <fred@example.com>``. Environment variables in the
2364 username are expanded.
2368 username are expanded.
2365
2369
2366 (default: ``$EMAIL`` or ``username@hostname``. If the username in
2370 (default: ``$EMAIL`` or ``username@hostname``. If the username in
2367 hgrc is empty, e.g. if the system admin set ``username =`` in the
2371 hgrc is empty, e.g. if the system admin set ``username =`` in the
2368 system hgrc, it has to be specified manually or in a different
2372 system hgrc, it has to be specified manually or in a different
2369 hgrc file)
2373 hgrc file)
2370
2374
2371 ``verbose``
2375 ``verbose``
2372 Increase the amount of output printed. (default: False)
2376 Increase the amount of output printed. (default: False)
2373
2377
2374
2378
2375 ``web``
2379 ``web``
2376 -------
2380 -------
2377
2381
2378 Web interface configuration. The settings in this section apply to
2382 Web interface configuration. The settings in this section apply to
2379 both the builtin webserver (started by :hg:`serve`) and the script you
2383 both the builtin webserver (started by :hg:`serve`) and the script you
2380 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
2384 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
2381 and WSGI).
2385 and WSGI).
2382
2386
2383 The Mercurial webserver does no authentication (it does not prompt for
2387 The Mercurial webserver does no authentication (it does not prompt for
2384 usernames and passwords to validate *who* users are), but it does do
2388 usernames and passwords to validate *who* users are), but it does do
2385 authorization (it grants or denies access for *authenticated users*
2389 authorization (it grants or denies access for *authenticated users*
2386 based on settings in this section). You must either configure your
2390 based on settings in this section). You must either configure your
2387 webserver to do authentication for you, or disable the authorization
2391 webserver to do authentication for you, or disable the authorization
2388 checks.
2392 checks.
2389
2393
2390 For a quick setup in a trusted environment, e.g., a private LAN, where
2394 For a quick setup in a trusted environment, e.g., a private LAN, where
2391 you want it to accept pushes from anybody, you can use the following
2395 you want it to accept pushes from anybody, you can use the following
2392 command line::
2396 command line::
2393
2397
2394 $ hg --config web.allow-push=* --config web.push_ssl=False serve
2398 $ hg --config web.allow-push=* --config web.push_ssl=False serve
2395
2399
2396 Note that this will allow anybody to push anything to the server and
2400 Note that this will allow anybody to push anything to the server and
2397 that this should not be used for public servers.
2401 that this should not be used for public servers.
2398
2402
2399 The full set of options is:
2403 The full set of options is:
2400
2404
2401 ``accesslog``
2405 ``accesslog``
2402 Where to output the access log. (default: stdout)
2406 Where to output the access log. (default: stdout)
2403
2407
2404 ``address``
2408 ``address``
2405 Interface address to bind to. (default: all)
2409 Interface address to bind to. (default: all)
2406
2410
2407 ``allow-archive``
2411 ``allow-archive``
2408 List of archive format (bz2, gz, zip) allowed for downloading.
2412 List of archive format (bz2, gz, zip) allowed for downloading.
2409 (default: empty)
2413 (default: empty)
2410
2414
2411 ``allowbz2``
2415 ``allowbz2``
2412 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
2416 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
2413 revisions.
2417 revisions.
2414 (default: False)
2418 (default: False)
2415
2419
2416 ``allowgz``
2420 ``allowgz``
2417 (DEPRECATED) Whether to allow .tar.gz downloading of repository
2421 (DEPRECATED) Whether to allow .tar.gz downloading of repository
2418 revisions.
2422 revisions.
2419 (default: False)
2423 (default: False)
2420
2424
2421 ``allow-pull``
2425 ``allow-pull``
2422 Whether to allow pulling from the repository. (default: True)
2426 Whether to allow pulling from the repository. (default: True)
2423
2427
2424 ``allow-push``
2428 ``allow-push``
2425 Whether to allow pushing to the repository. If empty or not set,
2429 Whether to allow pushing to the repository. If empty or not set,
2426 pushing is not allowed. If the special value ``*``, any remote
2430 pushing is not allowed. If the special value ``*``, any remote
2427 user can push, including unauthenticated users. Otherwise, the
2431 user can push, including unauthenticated users. Otherwise, the
2428 remote user must have been authenticated, and the authenticated
2432 remote user must have been authenticated, and the authenticated
2429 user name must be present in this list. The contents of the
2433 user name must be present in this list. The contents of the
2430 allow-push list are examined after the deny_push list.
2434 allow-push list are examined after the deny_push list.
2431
2435
2432 ``allow_read``
2436 ``allow_read``
2433 If the user has not already been denied repository access due to
2437 If the user has not already been denied repository access due to
2434 the contents of deny_read, this list determines whether to grant
2438 the contents of deny_read, this list determines whether to grant
2435 repository access to the user. If this list is not empty, and the
2439 repository access to the user. If this list is not empty, and the
2436 user is unauthenticated or not present in the list, then access is
2440 user is unauthenticated or not present in the list, then access is
2437 denied for the user. If the list is empty or not set, then access
2441 denied for the user. If the list is empty or not set, then access
2438 is permitted to all users by default. Setting allow_read to the
2442 is permitted to all users by default. Setting allow_read to the
2439 special value ``*`` is equivalent to it not being set (i.e. access
2443 special value ``*`` is equivalent to it not being set (i.e. access
2440 is permitted to all users). The contents of the allow_read list are
2444 is permitted to all users). The contents of the allow_read list are
2441 examined after the deny_read list.
2445 examined after the deny_read list.
2442
2446
2443 ``allowzip``
2447 ``allowzip``
2444 (DEPRECATED) Whether to allow .zip downloading of repository
2448 (DEPRECATED) Whether to allow .zip downloading of repository
2445 revisions. This feature creates temporary files.
2449 revisions. This feature creates temporary files.
2446 (default: False)
2450 (default: False)
2447
2451
2448 ``archivesubrepos``
2452 ``archivesubrepos``
2449 Whether to recurse into subrepositories when archiving.
2453 Whether to recurse into subrepositories when archiving.
2450 (default: False)
2454 (default: False)
2451
2455
2452 ``baseurl``
2456 ``baseurl``
2453 Base URL to use when publishing URLs in other locations, so
2457 Base URL to use when publishing URLs in other locations, so
2454 third-party tools like email notification hooks can construct
2458 third-party tools like email notification hooks can construct
2455 URLs. Example: ``http://hgserver/repos/``.
2459 URLs. Example: ``http://hgserver/repos/``.
2456
2460
2457 ``cacerts``
2461 ``cacerts``
2458 Path to file containing a list of PEM encoded certificate
2462 Path to file containing a list of PEM encoded certificate
2459 authority certificates. Environment variables and ``~user``
2463 authority certificates. Environment variables and ``~user``
2460 constructs are expanded in the filename. If specified on the
2464 constructs are expanded in the filename. If specified on the
2461 client, then it will verify the identity of remote HTTPS servers
2465 client, then it will verify the identity of remote HTTPS servers
2462 with these certificates.
2466 with these certificates.
2463
2467
2464 To disable SSL verification temporarily, specify ``--insecure`` from
2468 To disable SSL verification temporarily, specify ``--insecure`` from
2465 command line.
2469 command line.
2466
2470
2467 You can use OpenSSL's CA certificate file if your platform has
2471 You can use OpenSSL's CA certificate file if your platform has
2468 one. On most Linux systems this will be
2472 one. On most Linux systems this will be
2469 ``/etc/ssl/certs/ca-certificates.crt``. Otherwise you will have to
2473 ``/etc/ssl/certs/ca-certificates.crt``. Otherwise you will have to
2470 generate this file manually. The form must be as follows::
2474 generate this file manually. The form must be as follows::
2471
2475
2472 -----BEGIN CERTIFICATE-----
2476 -----BEGIN CERTIFICATE-----
2473 ... (certificate in base64 PEM encoding) ...
2477 ... (certificate in base64 PEM encoding) ...
2474 -----END CERTIFICATE-----
2478 -----END CERTIFICATE-----
2475 -----BEGIN CERTIFICATE-----
2479 -----BEGIN CERTIFICATE-----
2476 ... (certificate in base64 PEM encoding) ...
2480 ... (certificate in base64 PEM encoding) ...
2477 -----END CERTIFICATE-----
2481 -----END CERTIFICATE-----
2478
2482
2479 ``cache``
2483 ``cache``
2480 Whether to support caching in hgweb. (default: True)
2484 Whether to support caching in hgweb. (default: True)
2481
2485
2482 ``certificate``
2486 ``certificate``
2483 Certificate to use when running :hg:`serve`.
2487 Certificate to use when running :hg:`serve`.
2484
2488
2485 ``collapse``
2489 ``collapse``
2486 With ``descend`` enabled, repositories in subdirectories are shown at
2490 With ``descend`` enabled, repositories in subdirectories are shown at
2487 a single level alongside repositories in the current path. With
2491 a single level alongside repositories in the current path. With
2488 ``collapse`` also enabled, repositories residing at a deeper level than
2492 ``collapse`` also enabled, repositories residing at a deeper level than
2489 the current path are grouped behind navigable directory entries that
2493 the current path are grouped behind navigable directory entries that
2490 lead to the locations of these repositories. In effect, this setting
2494 lead to the locations of these repositories. In effect, this setting
2491 collapses each collection of repositories found within a subdirectory
2495 collapses each collection of repositories found within a subdirectory
2492 into a single entry for that subdirectory. (default: False)
2496 into a single entry for that subdirectory. (default: False)
2493
2497
2494 ``comparisoncontext``
2498 ``comparisoncontext``
2495 Number of lines of context to show in side-by-side file comparison. If
2499 Number of lines of context to show in side-by-side file comparison. If
2496 negative or the value ``full``, whole files are shown. (default: 5)
2500 negative or the value ``full``, whole files are shown. (default: 5)
2497
2501
2498 This setting can be overridden by a ``context`` request parameter to the
2502 This setting can be overridden by a ``context`` request parameter to the
2499 ``comparison`` command, taking the same values.
2503 ``comparison`` command, taking the same values.
2500
2504
2501 ``contact``
2505 ``contact``
2502 Name or email address of the person in charge of the repository.
2506 Name or email address of the person in charge of the repository.
2503 (default: ui.username or ``$EMAIL`` or "unknown" if unset or empty)
2507 (default: ui.username or ``$EMAIL`` or "unknown" if unset or empty)
2504
2508
2505 ``csp``
2509 ``csp``
2506 Send a ``Content-Security-Policy`` HTTP header with this value.
2510 Send a ``Content-Security-Policy`` HTTP header with this value.
2507
2511
2508 The value may contain a special string ``%nonce%``, which will be replaced
2512 The value may contain a special string ``%nonce%``, which will be replaced
2509 by a randomly-generated one-time use value. If the value contains
2513 by a randomly-generated one-time use value. If the value contains
2510 ``%nonce%``, ``web.cache`` will be disabled, as caching undermines the
2514 ``%nonce%``, ``web.cache`` will be disabled, as caching undermines the
2511 one-time property of the nonce. This nonce will also be inserted into
2515 one-time property of the nonce. This nonce will also be inserted into
2512 ``<script>`` elements containing inline JavaScript.
2516 ``<script>`` elements containing inline JavaScript.
2513
2517
2514 Note: lots of HTML content sent by the server is derived from repository
2518 Note: lots of HTML content sent by the server is derived from repository
2515 data. Please consider the potential for malicious repository data to
2519 data. Please consider the potential for malicious repository data to
2516 "inject" itself into generated HTML content as part of your security
2520 "inject" itself into generated HTML content as part of your security
2517 threat model.
2521 threat model.
2518
2522
2519 ``deny_push``
2523 ``deny_push``
2520 Whether to deny pushing to the repository. If empty or not set,
2524 Whether to deny pushing to the repository. If empty or not set,
2521 push is not denied. If the special value ``*``, all remote users are
2525 push is not denied. If the special value ``*``, all remote users are
2522 denied push. Otherwise, unauthenticated users are all denied, and
2526 denied push. Otherwise, unauthenticated users are all denied, and
2523 any authenticated user name present in this list is also denied. The
2527 any authenticated user name present in this list is also denied. The
2524 contents of the deny_push list are examined before the allow-push list.
2528 contents of the deny_push list are examined before the allow-push list.
2525
2529
2526 ``deny_read``
2530 ``deny_read``
2527 Whether to deny reading/viewing of the repository. If this list is
2531 Whether to deny reading/viewing of the repository. If this list is
2528 not empty, unauthenticated users are all denied, and any
2532 not empty, unauthenticated users are all denied, and any
2529 authenticated user name present in this list is also denied access to
2533 authenticated user name present in this list is also denied access to
2530 the repository. If set to the special value ``*``, all remote users
2534 the repository. If set to the special value ``*``, all remote users
2531 are denied access (rarely needed ;). If deny_read is empty or not set,
2535 are denied access (rarely needed ;). If deny_read is empty or not set,
2532 the determination of repository access depends on the presence and
2536 the determination of repository access depends on the presence and
2533 content of the allow_read list (see description). If both
2537 content of the allow_read list (see description). If both
2534 deny_read and allow_read are empty or not set, then access is
2538 deny_read and allow_read are empty or not set, then access is
2535 permitted to all users by default. If the repository is being
2539 permitted to all users by default. If the repository is being
2536 served via hgwebdir, denied users will not be able to see it in
2540 served via hgwebdir, denied users will not be able to see it in
2537 the list of repositories. The contents of the deny_read list have
2541 the list of repositories. The contents of the deny_read list have
2538 priority over (are examined before) the contents of the allow_read
2542 priority over (are examined before) the contents of the allow_read
2539 list.
2543 list.
2540
2544
2541 ``descend``
2545 ``descend``
2542 hgwebdir indexes will not descend into subdirectories. Only repositories
2546 hgwebdir indexes will not descend into subdirectories. Only repositories
2543 directly in the current path will be shown (other repositories are still
2547 directly in the current path will be shown (other repositories are still
2544 available from the index corresponding to their containing path).
2548 available from the index corresponding to their containing path).
2545
2549
2546 ``description``
2550 ``description``
2547 Textual description of the repository's purpose or contents.
2551 Textual description of the repository's purpose or contents.
2548 (default: "unknown")
2552 (default: "unknown")
2549
2553
2550 ``encoding``
2554 ``encoding``
2551 Character encoding name. (default: the current locale charset)
2555 Character encoding name. (default: the current locale charset)
2552 Example: "UTF-8".
2556 Example: "UTF-8".
2553
2557
2554 ``errorlog``
2558 ``errorlog``
2555 Where to output the error log. (default: stderr)
2559 Where to output the error log. (default: stderr)
2556
2560
2557 ``guessmime``
2561 ``guessmime``
2558 Control MIME types for raw download of file content.
2562 Control MIME types for raw download of file content.
2559 Set to True to let hgweb guess the content type from the file
2563 Set to True to let hgweb guess the content type from the file
2560 extension. This will serve HTML files as ``text/html`` and might
2564 extension. This will serve HTML files as ``text/html`` and might
2561 allow cross-site scripting attacks when serving untrusted
2565 allow cross-site scripting attacks when serving untrusted
2562 repositories. (default: False)
2566 repositories. (default: False)
2563
2567
2564 ``hidden``
2568 ``hidden``
2565 Whether to hide the repository in the hgwebdir index.
2569 Whether to hide the repository in the hgwebdir index.
2566 (default: False)
2570 (default: False)
2567
2571
2568 ``ipv6``
2572 ``ipv6``
2569 Whether to use IPv6. (default: False)
2573 Whether to use IPv6. (default: False)
2570
2574
2571 ``labels``
2575 ``labels``
2572 List of string *labels* associated with the repository.
2576 List of string *labels* associated with the repository.
2573
2577
2574 Labels are exposed as a template keyword and can be used to customize
2578 Labels are exposed as a template keyword and can be used to customize
2575 output. e.g. the ``index`` template can group or filter repositories
2579 output. e.g. the ``index`` template can group or filter repositories
2576 by labels and the ``summary`` template can display additional content
2580 by labels and the ``summary`` template can display additional content
2577 if a specific label is present.
2581 if a specific label is present.
2578
2582
2579 ``logoimg``
2583 ``logoimg``
2580 File name of the logo image that some templates display on each page.
2584 File name of the logo image that some templates display on each page.
2581 The file name is relative to ``staticurl``. That is, the full path to
2585 The file name is relative to ``staticurl``. That is, the full path to
2582 the logo image is "staticurl/logoimg".
2586 the logo image is "staticurl/logoimg".
2583 If unset, ``hglogo.png`` will be used.
2587 If unset, ``hglogo.png`` will be used.
2584
2588
2585 ``logourl``
2589 ``logourl``
2586 Base URL to use for logos. If unset, ``https://mercurial-scm.org/``
2590 Base URL to use for logos. If unset, ``https://mercurial-scm.org/``
2587 will be used.
2591 will be used.
2588
2592
2589 ``maxchanges``
2593 ``maxchanges``
2590 Maximum number of changes to list on the changelog. (default: 10)
2594 Maximum number of changes to list on the changelog. (default: 10)
2591
2595
2592 ``maxfiles``
2596 ``maxfiles``
2593 Maximum number of files to list per changeset. (default: 10)
2597 Maximum number of files to list per changeset. (default: 10)
2594
2598
2595 ``maxshortchanges``
2599 ``maxshortchanges``
2596 Maximum number of changes to list on the shortlog, graph or filelog
2600 Maximum number of changes to list on the shortlog, graph or filelog
2597 pages. (default: 60)
2601 pages. (default: 60)
2598
2602
2599 ``name``
2603 ``name``
2600 Repository name to use in the web interface.
2604 Repository name to use in the web interface.
2601 (default: current working directory)
2605 (default: current working directory)
2602
2606
2603 ``port``
2607 ``port``
2604 Port to listen on. (default: 8000)
2608 Port to listen on. (default: 8000)
2605
2609
2606 ``prefix``
2610 ``prefix``
2607 Prefix path to serve from. (default: '' (server root))
2611 Prefix path to serve from. (default: '' (server root))
2608
2612
2609 ``push_ssl``
2613 ``push_ssl``
2610 Whether to require that inbound pushes be transported over SSL to
2614 Whether to require that inbound pushes be transported over SSL to
2611 prevent password sniffing. (default: True)
2615 prevent password sniffing. (default: True)
2612
2616
2613 ``refreshinterval``
2617 ``refreshinterval``
2614 How frequently directory listings re-scan the filesystem for new
2618 How frequently directory listings re-scan the filesystem for new
2615 repositories, in seconds. This is relevant when wildcards are used
2619 repositories, in seconds. This is relevant when wildcards are used
2616 to define paths. Depending on how much filesystem traversal is
2620 to define paths. Depending on how much filesystem traversal is
2617 required, refreshing may negatively impact performance.
2621 required, refreshing may negatively impact performance.
2618
2622
2619 Values less than or equal to 0 always refresh.
2623 Values less than or equal to 0 always refresh.
2620 (default: 20)
2624 (default: 20)
2621
2625
2622 ``server-header``
2626 ``server-header``
2623 Value for HTTP ``Server`` response header.
2627 Value for HTTP ``Server`` response header.
2624
2628
2625 ``staticurl``
2629 ``staticurl``
2626 Base URL to use for static files. If unset, static files (e.g. the
2630 Base URL to use for static files. If unset, static files (e.g. the
2627 hgicon.png favicon) will be served by the CGI script itself. Use
2631 hgicon.png favicon) will be served by the CGI script itself. Use
2628 this setting to serve them directly with the HTTP server.
2632 this setting to serve them directly with the HTTP server.
2629 Example: ``http://hgserver/static/``.
2633 Example: ``http://hgserver/static/``.
2630
2634
2631 ``stripes``
2635 ``stripes``
2632 How many lines a "zebra stripe" should span in multi-line output.
2636 How many lines a "zebra stripe" should span in multi-line output.
2633 Set to 0 to disable. (default: 1)
2637 Set to 0 to disable. (default: 1)
2634
2638
2635 ``style``
2639 ``style``
2636 Which template map style to use. The available options are the names of
2640 Which template map style to use. The available options are the names of
2637 subdirectories in the HTML templates path. (default: ``paper``)
2641 subdirectories in the HTML templates path. (default: ``paper``)
2638 Example: ``monoblue``.
2642 Example: ``monoblue``.
2639
2643
2640 ``templates``
2644 ``templates``
2641 Where to find the HTML templates. The default path to the HTML templates
2645 Where to find the HTML templates. The default path to the HTML templates
2642 can be obtained from ``hg debuginstall``.
2646 can be obtained from ``hg debuginstall``.
2643
2647
2644 ``websub``
2648 ``websub``
2645 ----------
2649 ----------
2646
2650
2647 Web substitution filter definition. You can use this section to
2651 Web substitution filter definition. You can use this section to
2648 define a set of regular expression substitution patterns which
2652 define a set of regular expression substitution patterns which
2649 let you automatically modify the hgweb server output.
2653 let you automatically modify the hgweb server output.
2650
2654
2651 The default hgweb templates only apply these substitution patterns
2655 The default hgweb templates only apply these substitution patterns
2652 on the revision description fields. You can apply them anywhere
2656 on the revision description fields. You can apply them anywhere
2653 you want when you create your own templates by adding calls to the
2657 you want when you create your own templates by adding calls to the
2654 "websub" filter (usually after calling the "escape" filter).
2658 "websub" filter (usually after calling the "escape" filter).
2655
2659
2656 This can be used, for example, to convert issue references to links
2660 This can be used, for example, to convert issue references to links
2657 to your issue tracker, or to convert "markdown-like" syntax into
2661 to your issue tracker, or to convert "markdown-like" syntax into
2658 HTML (see the examples below).
2662 HTML (see the examples below).
2659
2663
2660 Each entry in this section names a substitution filter.
2664 Each entry in this section names a substitution filter.
2661 The value of each entry defines the substitution expression itself.
2665 The value of each entry defines the substitution expression itself.
2662 The websub expressions follow the old interhg extension syntax,
2666 The websub expressions follow the old interhg extension syntax,
2663 which in turn imitates the Unix sed replacement syntax::
2667 which in turn imitates the Unix sed replacement syntax::
2664
2668
2665 patternname = s/SEARCH_REGEX/REPLACE_EXPRESSION/[i]
2669 patternname = s/SEARCH_REGEX/REPLACE_EXPRESSION/[i]
2666
2670
2667 You can use any separator other than "/". The final "i" is optional
2671 You can use any separator other than "/". The final "i" is optional
2668 and indicates that the search must be case insensitive.
2672 and indicates that the search must be case insensitive.
2669
2673
2670 Examples::
2674 Examples::
2671
2675
2672 [websub]
2676 [websub]
2673 issues = s|issue(\d+)|<a href="http://bts.example.org/issue\1">issue\1</a>|i
2677 issues = s|issue(\d+)|<a href="http://bts.example.org/issue\1">issue\1</a>|i
2674 italic = s/\b_(\S+)_\b/<i>\1<\/i>/
2678 italic = s/\b_(\S+)_\b/<i>\1<\/i>/
2675 bold = s/\*\b(\S+)\b\*/<b>\1<\/b>/
2679 bold = s/\*\b(\S+)\b\*/<b>\1<\/b>/
2676
2680
2677 ``worker``
2681 ``worker``
2678 ----------
2682 ----------
2679
2683
2680 Parallel master/worker configuration. We currently perform working
2684 Parallel master/worker configuration. We currently perform working
2681 directory updates in parallel on Unix-like systems, which greatly
2685 directory updates in parallel on Unix-like systems, which greatly
2682 helps performance.
2686 helps performance.
2683
2687
2684 ``enabled``
2688 ``enabled``
2685 Whether to enable workers code to be used.
2689 Whether to enable workers code to be used.
2686 (default: true)
2690 (default: true)
2687
2691
2688 ``numcpus``
2692 ``numcpus``
2689 Number of CPUs to use for parallel operations. A zero or
2693 Number of CPUs to use for parallel operations. A zero or
2690 negative value is treated as ``use the default``.
2694 negative value is treated as ``use the default``.
2691 (default: 4 or the number of CPUs on the system, whichever is larger)
2695 (default: 4 or the number of CPUs on the system, whichever is larger)
2692
2696
2693 ``backgroundclose``
2697 ``backgroundclose``
2694 Whether to enable closing file handles on background threads during certain
2698 Whether to enable closing file handles on background threads during certain
2695 operations. Some platforms aren't very efficient at closing file
2699 operations. Some platforms aren't very efficient at closing file
2696 handles that have been written or appended to. By performing file closing
2700 handles that have been written or appended to. By performing file closing
2697 on background threads, file write rate can increase substantially.
2701 on background threads, file write rate can increase substantially.
2698 (default: true on Windows, false elsewhere)
2702 (default: true on Windows, false elsewhere)
2699
2703
2700 ``backgroundcloseminfilecount``
2704 ``backgroundcloseminfilecount``
2701 Minimum number of files required to trigger background file closing.
2705 Minimum number of files required to trigger background file closing.
2702 Operations not writing this many files won't start background close
2706 Operations not writing this many files won't start background close
2703 threads.
2707 threads.
2704 (default: 2048)
2708 (default: 2048)
2705
2709
2706 ``backgroundclosemaxqueue``
2710 ``backgroundclosemaxqueue``
2707 The maximum number of opened file handles waiting to be closed in the
2711 The maximum number of opened file handles waiting to be closed in the
2708 background. This option only has an effect if ``backgroundclose`` is
2712 background. This option only has an effect if ``backgroundclose`` is
2709 enabled.
2713 enabled.
2710 (default: 384)
2714 (default: 384)
2711
2715
2712 ``backgroundclosethreadcount``
2716 ``backgroundclosethreadcount``
2713 Number of threads to process background file closes. Only relevant if
2717 Number of threads to process background file closes. Only relevant if
2714 ``backgroundclose`` is enabled.
2718 ``backgroundclose`` is enabled.
2715 (default: 4)
2719 (default: 4)
@@ -1,514 +1,514 b''
1 #require serve no-reposimplestore no-chg
1 #require serve no-reposimplestore no-chg
2
2
3 #testcases stream-legacy stream-bundle2
3 #testcases stream-legacy stream-bundle2
4
4
5 #if stream-bundle2
5 #if stream-bundle2
6 $ cat << EOF >> $HGRCPATH
6 $ cat << EOF >> $HGRCPATH
7 > [experimental]
7 > [server]
8 > bundle2.stream = yes
8 > bundle2.stream = yes
9 > EOF
9 > EOF
10 #endif
10 #endif
11
11
12 Initialize repository
12 Initialize repository
13 the status call is to check for issue5130
13 the status call is to check for issue5130
14
14
15 $ hg init server
15 $ hg init server
16 $ cd server
16 $ cd server
17 $ touch foo
17 $ touch foo
18 $ hg -q commit -A -m initial
18 $ hg -q commit -A -m initial
19 >>> for i in range(1024):
19 >>> for i in range(1024):
20 ... with open(str(i), 'wb') as fh:
20 ... with open(str(i), 'wb') as fh:
21 ... fh.write(b"%d" % i) and None
21 ... fh.write(b"%d" % i) and None
22 $ hg -q commit -A -m 'add a lot of files'
22 $ hg -q commit -A -m 'add a lot of files'
23 $ hg st
23 $ hg st
24 $ hg --config server.uncompressed=false serve -p $HGPORT -d --pid-file=hg.pid
24 $ hg --config server.uncompressed=false serve -p $HGPORT -d --pid-file=hg.pid
25 $ cat hg.pid > $DAEMON_PIDS
25 $ cat hg.pid > $DAEMON_PIDS
26 $ cd ..
26 $ cd ..
27
27
28 Cannot stream clone when server.uncompressed is set
28 Cannot stream clone when server.uncompressed is set
29
29
30 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=stream_out'
30 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=stream_out'
31 200 Script output follows
31 200 Script output follows
32
32
33 1
33 1
34
34
35 #if stream-legacy
35 #if stream-legacy
36 $ hg debugcapabilities http://localhost:$HGPORT
36 $ hg debugcapabilities http://localhost:$HGPORT
37 Main capabilities:
37 Main capabilities:
38 batch
38 batch
39 branchmap
39 branchmap
40 $USUAL_BUNDLE2_CAPS_SERVER$
40 $USUAL_BUNDLE2_CAPS_SERVER$
41 changegroupsubset
41 changegroupsubset
42 compression=$BUNDLE2_COMPRESSIONS$
42 compression=$BUNDLE2_COMPRESSIONS$
43 getbundle
43 getbundle
44 httpheader=1024
44 httpheader=1024
45 httpmediatype=0.1rx,0.1tx,0.2tx
45 httpmediatype=0.1rx,0.1tx,0.2tx
46 known
46 known
47 lookup
47 lookup
48 pushkey
48 pushkey
49 unbundle=HG10GZ,HG10BZ,HG10UN
49 unbundle=HG10GZ,HG10BZ,HG10UN
50 unbundlehash
50 unbundlehash
51 Bundle2 capabilities:
51 Bundle2 capabilities:
52 HG20
52 HG20
53 bookmarks
53 bookmarks
54 changegroup
54 changegroup
55 01
55 01
56 02
56 02
57 digests
57 digests
58 md5
58 md5
59 sha1
59 sha1
60 sha512
60 sha512
61 error
61 error
62 abort
62 abort
63 unsupportedcontent
63 unsupportedcontent
64 pushraced
64 pushraced
65 pushkey
65 pushkey
66 hgtagsfnodes
66 hgtagsfnodes
67 listkeys
67 listkeys
68 phases
68 phases
69 heads
69 heads
70 pushkey
70 pushkey
71 remote-changegroup
71 remote-changegroup
72 http
72 http
73 https
73 https
74 rev-branch-cache
74 rev-branch-cache
75
75
76 $ hg clone --stream -U http://localhost:$HGPORT server-disabled
76 $ hg clone --stream -U http://localhost:$HGPORT server-disabled
77 warning: stream clone requested but server has them disabled
77 warning: stream clone requested but server has them disabled
78 requesting all changes
78 requesting all changes
79 adding changesets
79 adding changesets
80 adding manifests
80 adding manifests
81 adding file changes
81 adding file changes
82 added 2 changesets with 1025 changes to 1025 files
82 added 2 changesets with 1025 changes to 1025 files
83 new changesets 96ee1d7354c4:c17445101a72
83 new changesets 96ee1d7354c4:c17445101a72
84
84
85 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle' content-type --bodyfile body --hgproto 0.2 --requestheader "x-hgarg-1=bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=0000000000000000000000000000000000000000&heads=c17445101a72edac06facd130d14808dfbd5c7c2&stream=1"
85 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle' content-type --bodyfile body --hgproto 0.2 --requestheader "x-hgarg-1=bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=0000000000000000000000000000000000000000&heads=c17445101a72edac06facd130d14808dfbd5c7c2&stream=1"
86 200 Script output follows
86 200 Script output follows
87 content-type: application/mercurial-0.2
87 content-type: application/mercurial-0.2
88
88
89
89
90 $ f --size body --hexdump --bytes 100
90 $ f --size body --hexdump --bytes 100
91 body: size=232
91 body: size=232
92 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......|
92 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......|
93 0010: cf 0b 45 52 52 4f 52 3a 41 42 4f 52 54 00 00 00 |..ERROR:ABORT...|
93 0010: cf 0b 45 52 52 4f 52 3a 41 42 4f 52 54 00 00 00 |..ERROR:ABORT...|
94 0020: 00 01 01 07 3c 04 72 6d 65 73 73 61 67 65 73 74 |....<.rmessagest|
94 0020: 00 01 01 07 3c 04 72 6d 65 73 73 61 67 65 73 74 |....<.rmessagest|
95 0030: 72 65 61 6d 20 64 61 74 61 20 72 65 71 75 65 73 |ream data reques|
95 0030: 72 65 61 6d 20 64 61 74 61 20 72 65 71 75 65 73 |ream data reques|
96 0040: 74 65 64 20 62 75 74 20 73 65 72 76 65 72 20 64 |ted but server d|
96 0040: 74 65 64 20 62 75 74 20 73 65 72 76 65 72 20 64 |ted but server d|
97 0050: 6f 65 73 20 6e 6f 74 20 61 6c 6c 6f 77 20 74 68 |oes not allow th|
97 0050: 6f 65 73 20 6e 6f 74 20 61 6c 6c 6f 77 20 74 68 |oes not allow th|
98 0060: 69 73 20 66 |is f|
98 0060: 69 73 20 66 |is f|
99
99
100 #endif
100 #endif
101 #if stream-bundle2
101 #if stream-bundle2
102 $ hg debugcapabilities http://localhost:$HGPORT
102 $ hg debugcapabilities http://localhost:$HGPORT
103 Main capabilities:
103 Main capabilities:
104 batch
104 batch
105 branchmap
105 branchmap
106 $USUAL_BUNDLE2_CAPS_SERVER$
106 $USUAL_BUNDLE2_CAPS_SERVER$
107 changegroupsubset
107 changegroupsubset
108 compression=$BUNDLE2_COMPRESSIONS$
108 compression=$BUNDLE2_COMPRESSIONS$
109 getbundle
109 getbundle
110 httpheader=1024
110 httpheader=1024
111 httpmediatype=0.1rx,0.1tx,0.2tx
111 httpmediatype=0.1rx,0.1tx,0.2tx
112 known
112 known
113 lookup
113 lookup
114 pushkey
114 pushkey
115 unbundle=HG10GZ,HG10BZ,HG10UN
115 unbundle=HG10GZ,HG10BZ,HG10UN
116 unbundlehash
116 unbundlehash
117 Bundle2 capabilities:
117 Bundle2 capabilities:
118 HG20
118 HG20
119 bookmarks
119 bookmarks
120 changegroup
120 changegroup
121 01
121 01
122 02
122 02
123 digests
123 digests
124 md5
124 md5
125 sha1
125 sha1
126 sha512
126 sha512
127 error
127 error
128 abort
128 abort
129 unsupportedcontent
129 unsupportedcontent
130 pushraced
130 pushraced
131 pushkey
131 pushkey
132 hgtagsfnodes
132 hgtagsfnodes
133 listkeys
133 listkeys
134 phases
134 phases
135 heads
135 heads
136 pushkey
136 pushkey
137 remote-changegroup
137 remote-changegroup
138 http
138 http
139 https
139 https
140 rev-branch-cache
140 rev-branch-cache
141
141
142 $ hg clone --stream -U http://localhost:$HGPORT server-disabled
142 $ hg clone --stream -U http://localhost:$HGPORT server-disabled
143 warning: stream clone requested but server has them disabled
143 warning: stream clone requested but server has them disabled
144 requesting all changes
144 requesting all changes
145 adding changesets
145 adding changesets
146 adding manifests
146 adding manifests
147 adding file changes
147 adding file changes
148 added 2 changesets with 1025 changes to 1025 files
148 added 2 changesets with 1025 changes to 1025 files
149 new changesets 96ee1d7354c4:c17445101a72
149 new changesets 96ee1d7354c4:c17445101a72
150
150
151 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle' content-type --bodyfile body --hgproto 0.2 --requestheader "x-hgarg-1=bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=0000000000000000000000000000000000000000&heads=c17445101a72edac06facd130d14808dfbd5c7c2&stream=1"
151 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle' content-type --bodyfile body --hgproto 0.2 --requestheader "x-hgarg-1=bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=0000000000000000000000000000000000000000&heads=c17445101a72edac06facd130d14808dfbd5c7c2&stream=1"
152 200 Script output follows
152 200 Script output follows
153 content-type: application/mercurial-0.2
153 content-type: application/mercurial-0.2
154
154
155
155
156 $ f --size body --hexdump --bytes 100
156 $ f --size body --hexdump --bytes 100
157 body: size=232
157 body: size=232
158 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......|
158 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......|
159 0010: cf 0b 45 52 52 4f 52 3a 41 42 4f 52 54 00 00 00 |..ERROR:ABORT...|
159 0010: cf 0b 45 52 52 4f 52 3a 41 42 4f 52 54 00 00 00 |..ERROR:ABORT...|
160 0020: 00 01 01 07 3c 04 72 6d 65 73 73 61 67 65 73 74 |....<.rmessagest|
160 0020: 00 01 01 07 3c 04 72 6d 65 73 73 61 67 65 73 74 |....<.rmessagest|
161 0030: 72 65 61 6d 20 64 61 74 61 20 72 65 71 75 65 73 |ream data reques|
161 0030: 72 65 61 6d 20 64 61 74 61 20 72 65 71 75 65 73 |ream data reques|
162 0040: 74 65 64 20 62 75 74 20 73 65 72 76 65 72 20 64 |ted but server d|
162 0040: 74 65 64 20 62 75 74 20 73 65 72 76 65 72 20 64 |ted but server d|
163 0050: 6f 65 73 20 6e 6f 74 20 61 6c 6c 6f 77 20 74 68 |oes not allow th|
163 0050: 6f 65 73 20 6e 6f 74 20 61 6c 6c 6f 77 20 74 68 |oes not allow th|
164 0060: 69 73 20 66 |is f|
164 0060: 69 73 20 66 |is f|
165
165
166 #endif
166 #endif
167
167
168 $ killdaemons.py
168 $ killdaemons.py
169 $ cd server
169 $ cd server
170 $ hg serve -p $HGPORT -d --pid-file=hg.pid
170 $ hg serve -p $HGPORT -d --pid-file=hg.pid
171 $ cat hg.pid > $DAEMON_PIDS
171 $ cat hg.pid > $DAEMON_PIDS
172 $ cd ..
172 $ cd ..
173
173
174 Basic clone
174 Basic clone
175
175
176 #if stream-legacy
176 #if stream-legacy
177 $ hg clone --stream -U http://localhost:$HGPORT clone1
177 $ hg clone --stream -U http://localhost:$HGPORT clone1
178 streaming all changes
178 streaming all changes
179 1027 files to transfer, 96.3 KB of data
179 1027 files to transfer, 96.3 KB of data
180 transferred 96.3 KB in * seconds (*/sec) (glob)
180 transferred 96.3 KB in * seconds (*/sec) (glob)
181 searching for changes
181 searching for changes
182 no changes found
182 no changes found
183 #endif
183 #endif
184 #if stream-bundle2
184 #if stream-bundle2
185 $ hg clone --stream -U http://localhost:$HGPORT clone1
185 $ hg clone --stream -U http://localhost:$HGPORT clone1
186 streaming all changes
186 streaming all changes
187 1030 files to transfer, 96.4 KB of data
187 1030 files to transfer, 96.4 KB of data
188 transferred 96.4 KB in * seconds (* */sec) (glob)
188 transferred 96.4 KB in * seconds (* */sec) (glob)
189
189
190 $ ls -1 clone1/.hg/cache
190 $ ls -1 clone1/.hg/cache
191 branch2-served
191 branch2-served
192 rbc-names-v1
192 rbc-names-v1
193 rbc-revs-v1
193 rbc-revs-v1
194 #endif
194 #endif
195
195
196 getbundle requests with stream=1 are uncompressed
196 getbundle requests with stream=1 are uncompressed
197
197
198 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle' content-type --bodyfile body --hgproto '0.1 0.2 comp=zlib,none' --requestheader "x-hgarg-1=bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=0000000000000000000000000000000000000000&heads=c17445101a72edac06facd130d14808dfbd5c7c2&stream=1"
198 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle' content-type --bodyfile body --hgproto '0.1 0.2 comp=zlib,none' --requestheader "x-hgarg-1=bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=0000000000000000000000000000000000000000&heads=c17445101a72edac06facd130d14808dfbd5c7c2&stream=1"
199 200 Script output follows
199 200 Script output follows
200 content-type: application/mercurial-0.2
200 content-type: application/mercurial-0.2
201
201
202
202
203 $ f --size --hex --bytes 256 body
203 $ f --size --hex --bytes 256 body
204 body: size=112230
204 body: size=112230
205 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......|
205 0000: 04 6e 6f 6e 65 48 47 32 30 00 00 00 00 00 00 00 |.noneHG20.......|
206 0010: 70 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 |p.STREAM2.......|
206 0010: 70 07 53 54 52 45 41 4d 32 00 00 00 00 03 00 09 |p.STREAM2.......|
207 0020: 05 09 04 0c 35 62 79 74 65 63 6f 75 6e 74 39 38 |....5bytecount98|
207 0020: 05 09 04 0c 35 62 79 74 65 63 6f 75 6e 74 39 38 |....5bytecount98|
208 0030: 37 35 38 66 69 6c 65 63 6f 75 6e 74 31 30 33 30 |758filecount1030|
208 0030: 37 35 38 66 69 6c 65 63 6f 75 6e 74 31 30 33 30 |758filecount1030|
209 0040: 72 65 71 75 69 72 65 6d 65 6e 74 73 64 6f 74 65 |requirementsdote|
209 0040: 72 65 71 75 69 72 65 6d 65 6e 74 73 64 6f 74 65 |requirementsdote|
210 0050: 6e 63 6f 64 65 25 32 43 66 6e 63 61 63 68 65 25 |ncode%2Cfncache%|
210 0050: 6e 63 6f 64 65 25 32 43 66 6e 63 61 63 68 65 25 |ncode%2Cfncache%|
211 0060: 32 43 67 65 6e 65 72 61 6c 64 65 6c 74 61 25 32 |2Cgeneraldelta%2|
211 0060: 32 43 67 65 6e 65 72 61 6c 64 65 6c 74 61 25 32 |2Cgeneraldelta%2|
212 0070: 43 72 65 76 6c 6f 67 76 31 25 32 43 73 74 6f 72 |Crevlogv1%2Cstor|
212 0070: 43 72 65 76 6c 6f 67 76 31 25 32 43 73 74 6f 72 |Crevlogv1%2Cstor|
213 0080: 65 00 00 80 00 73 08 42 64 61 74 61 2f 30 2e 69 |e....s.Bdata/0.i|
213 0080: 65 00 00 80 00 73 08 42 64 61 74 61 2f 30 2e 69 |e....s.Bdata/0.i|
214 0090: 00 03 00 01 00 00 00 00 00 00 00 02 00 00 00 01 |................|
214 0090: 00 03 00 01 00 00 00 00 00 00 00 02 00 00 00 01 |................|
215 00a0: 00 00 00 00 00 00 00 01 ff ff ff ff ff ff ff ff |................|
215 00a0: 00 00 00 00 00 00 00 01 ff ff ff ff ff ff ff ff |................|
216 00b0: 80 29 63 a0 49 d3 23 87 bf ce fe 56 67 92 67 2c |.)c.I.#....Vg.g,|
216 00b0: 80 29 63 a0 49 d3 23 87 bf ce fe 56 67 92 67 2c |.)c.I.#....Vg.g,|
217 00c0: 69 d1 ec 39 00 00 00 00 00 00 00 00 00 00 00 00 |i..9............|
217 00c0: 69 d1 ec 39 00 00 00 00 00 00 00 00 00 00 00 00 |i..9............|
218 00d0: 75 30 73 08 42 64 61 74 61 2f 31 2e 69 00 03 00 |u0s.Bdata/1.i...|
218 00d0: 75 30 73 08 42 64 61 74 61 2f 31 2e 69 00 03 00 |u0s.Bdata/1.i...|
219 00e0: 01 00 00 00 00 00 00 00 02 00 00 00 01 00 00 00 |................|
219 00e0: 01 00 00 00 00 00 00 00 02 00 00 00 01 00 00 00 |................|
220 00f0: 00 00 00 00 01 ff ff ff ff ff ff ff ff f9 76 da |..............v.|
220 00f0: 00 00 00 00 01 ff ff ff ff ff ff ff ff f9 76 da |..............v.|
221
221
222 --uncompressed is an alias to --stream
222 --uncompressed is an alias to --stream
223
223
224 #if stream-legacy
224 #if stream-legacy
225 $ hg clone --uncompressed -U http://localhost:$HGPORT clone1-uncompressed
225 $ hg clone --uncompressed -U http://localhost:$HGPORT clone1-uncompressed
226 streaming all changes
226 streaming all changes
227 1027 files to transfer, 96.3 KB of data
227 1027 files to transfer, 96.3 KB of data
228 transferred 96.3 KB in * seconds (*/sec) (glob)
228 transferred 96.3 KB in * seconds (*/sec) (glob)
229 searching for changes
229 searching for changes
230 no changes found
230 no changes found
231 #endif
231 #endif
232 #if stream-bundle2
232 #if stream-bundle2
233 $ hg clone --uncompressed -U http://localhost:$HGPORT clone1-uncompressed
233 $ hg clone --uncompressed -U http://localhost:$HGPORT clone1-uncompressed
234 streaming all changes
234 streaming all changes
235 1030 files to transfer, 96.4 KB of data
235 1030 files to transfer, 96.4 KB of data
236 transferred 96.4 KB in * seconds (* */sec) (glob)
236 transferred 96.4 KB in * seconds (* */sec) (glob)
237 #endif
237 #endif
238
238
239 Clone with background file closing enabled
239 Clone with background file closing enabled
240
240
241 #if stream-legacy
241 #if stream-legacy
242 $ hg --debug --config worker.backgroundclose=true --config worker.backgroundcloseminfilecount=1 clone --stream -U http://localhost:$HGPORT clone-background | grep -v adding
242 $ hg --debug --config worker.backgroundclose=true --config worker.backgroundcloseminfilecount=1 clone --stream -U http://localhost:$HGPORT clone-background | grep -v adding
243 using http://localhost:$HGPORT/
243 using http://localhost:$HGPORT/
244 sending capabilities command
244 sending capabilities command
245 sending branchmap command
245 sending branchmap command
246 streaming all changes
246 streaming all changes
247 sending stream_out command
247 sending stream_out command
248 1027 files to transfer, 96.3 KB of data
248 1027 files to transfer, 96.3 KB of data
249 starting 4 threads for background file closing
249 starting 4 threads for background file closing
250 updating the branch cache
250 updating the branch cache
251 transferred 96.3 KB in * seconds (*/sec) (glob)
251 transferred 96.3 KB in * seconds (*/sec) (glob)
252 query 1; heads
252 query 1; heads
253 sending batch command
253 sending batch command
254 searching for changes
254 searching for changes
255 all remote heads known locally
255 all remote heads known locally
256 no changes found
256 no changes found
257 sending getbundle command
257 sending getbundle command
258 bundle2-input-bundle: with-transaction
258 bundle2-input-bundle: with-transaction
259 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
259 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
260 bundle2-input-part: "phase-heads" supported
260 bundle2-input-part: "phase-heads" supported
261 bundle2-input-part: total payload size 24
261 bundle2-input-part: total payload size 24
262 bundle2-input-bundle: 1 parts total
262 bundle2-input-bundle: 1 parts total
263 checking for updated bookmarks
263 checking for updated bookmarks
264 #endif
264 #endif
265 #if stream-bundle2
265 #if stream-bundle2
266 $ hg --debug --config worker.backgroundclose=true --config worker.backgroundcloseminfilecount=1 clone --stream -U http://localhost:$HGPORT clone-background | grep -v adding
266 $ hg --debug --config worker.backgroundclose=true --config worker.backgroundcloseminfilecount=1 clone --stream -U http://localhost:$HGPORT clone-background | grep -v adding
267 using http://localhost:$HGPORT/
267 using http://localhost:$HGPORT/
268 sending capabilities command
268 sending capabilities command
269 query 1; heads
269 query 1; heads
270 sending batch command
270 sending batch command
271 streaming all changes
271 streaming all changes
272 sending getbundle command
272 sending getbundle command
273 bundle2-input-bundle: with-transaction
273 bundle2-input-bundle: with-transaction
274 bundle2-input-part: "stream2" (params: 3 mandatory) supported
274 bundle2-input-part: "stream2" (params: 3 mandatory) supported
275 applying stream bundle
275 applying stream bundle
276 1030 files to transfer, 96.4 KB of data
276 1030 files to transfer, 96.4 KB of data
277 starting 4 threads for background file closing
277 starting 4 threads for background file closing
278 starting 4 threads for background file closing
278 starting 4 threads for background file closing
279 updating the branch cache
279 updating the branch cache
280 transferred 96.4 KB in * seconds (* */sec) (glob)
280 transferred 96.4 KB in * seconds (* */sec) (glob)
281 bundle2-input-part: total payload size 112077
281 bundle2-input-part: total payload size 112077
282 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
282 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
283 bundle2-input-bundle: 1 parts total
283 bundle2-input-bundle: 1 parts total
284 checking for updated bookmarks
284 checking for updated bookmarks
285 #endif
285 #endif
286
286
287 Cannot stream clone when there are secret changesets
287 Cannot stream clone when there are secret changesets
288
288
289 $ hg -R server phase --force --secret -r tip
289 $ hg -R server phase --force --secret -r tip
290 $ hg clone --stream -U http://localhost:$HGPORT secret-denied
290 $ hg clone --stream -U http://localhost:$HGPORT secret-denied
291 warning: stream clone requested but server has them disabled
291 warning: stream clone requested but server has them disabled
292 requesting all changes
292 requesting all changes
293 adding changesets
293 adding changesets
294 adding manifests
294 adding manifests
295 adding file changes
295 adding file changes
296 added 1 changesets with 1 changes to 1 files
296 added 1 changesets with 1 changes to 1 files
297 new changesets 96ee1d7354c4
297 new changesets 96ee1d7354c4
298
298
299 $ killdaemons.py
299 $ killdaemons.py
300
300
301 Streaming of secrets can be overridden by server config
301 Streaming of secrets can be overridden by server config
302
302
303 $ cd server
303 $ cd server
304 $ hg serve --config server.uncompressedallowsecret=true -p $HGPORT -d --pid-file=hg.pid
304 $ hg serve --config server.uncompressedallowsecret=true -p $HGPORT -d --pid-file=hg.pid
305 $ cat hg.pid > $DAEMON_PIDS
305 $ cat hg.pid > $DAEMON_PIDS
306 $ cd ..
306 $ cd ..
307
307
308 #if stream-legacy
308 #if stream-legacy
309 $ hg clone --stream -U http://localhost:$HGPORT secret-allowed
309 $ hg clone --stream -U http://localhost:$HGPORT secret-allowed
310 streaming all changes
310 streaming all changes
311 1027 files to transfer, 96.3 KB of data
311 1027 files to transfer, 96.3 KB of data
312 transferred 96.3 KB in * seconds (*/sec) (glob)
312 transferred 96.3 KB in * seconds (*/sec) (glob)
313 searching for changes
313 searching for changes
314 no changes found
314 no changes found
315 #endif
315 #endif
316 #if stream-bundle2
316 #if stream-bundle2
317 $ hg clone --stream -U http://localhost:$HGPORT secret-allowed
317 $ hg clone --stream -U http://localhost:$HGPORT secret-allowed
318 streaming all changes
318 streaming all changes
319 1030 files to transfer, 96.4 KB of data
319 1030 files to transfer, 96.4 KB of data
320 transferred 96.4 KB in * seconds (* */sec) (glob)
320 transferred 96.4 KB in * seconds (* */sec) (glob)
321 #endif
321 #endif
322
322
323 $ killdaemons.py
323 $ killdaemons.py
324
324
325 Verify interaction between preferuncompressed and secret presence
325 Verify interaction between preferuncompressed and secret presence
326
326
327 $ cd server
327 $ cd server
328 $ hg serve --config server.preferuncompressed=true -p $HGPORT -d --pid-file=hg.pid
328 $ hg serve --config server.preferuncompressed=true -p $HGPORT -d --pid-file=hg.pid
329 $ cat hg.pid > $DAEMON_PIDS
329 $ cat hg.pid > $DAEMON_PIDS
330 $ cd ..
330 $ cd ..
331
331
332 $ hg clone -U http://localhost:$HGPORT preferuncompressed-secret
332 $ hg clone -U http://localhost:$HGPORT preferuncompressed-secret
333 requesting all changes
333 requesting all changes
334 adding changesets
334 adding changesets
335 adding manifests
335 adding manifests
336 adding file changes
336 adding file changes
337 added 1 changesets with 1 changes to 1 files
337 added 1 changesets with 1 changes to 1 files
338 new changesets 96ee1d7354c4
338 new changesets 96ee1d7354c4
339
339
340 $ killdaemons.py
340 $ killdaemons.py
341
341
342 Clone not allowed when full bundles disabled and can't serve secrets
342 Clone not allowed when full bundles disabled and can't serve secrets
343
343
344 $ cd server
344 $ cd server
345 $ hg serve --config server.disablefullbundle=true -p $HGPORT -d --pid-file=hg.pid
345 $ hg serve --config server.disablefullbundle=true -p $HGPORT -d --pid-file=hg.pid
346 $ cat hg.pid > $DAEMON_PIDS
346 $ cat hg.pid > $DAEMON_PIDS
347 $ cd ..
347 $ cd ..
348
348
349 $ hg clone --stream http://localhost:$HGPORT secret-full-disabled
349 $ hg clone --stream http://localhost:$HGPORT secret-full-disabled
350 warning: stream clone requested but server has them disabled
350 warning: stream clone requested but server has them disabled
351 requesting all changes
351 requesting all changes
352 remote: abort: server has pull-based clones disabled
352 remote: abort: server has pull-based clones disabled
353 abort: pull failed on remote
353 abort: pull failed on remote
354 (remove --pull if specified or upgrade Mercurial)
354 (remove --pull if specified or upgrade Mercurial)
355 [255]
355 [255]
356
356
357 Local stream clone with secrets involved
357 Local stream clone with secrets involved
358 (This is just a test over behavior: if you have access to the repo's files,
358 (This is just a test over behavior: if you have access to the repo's files,
359 there is no security so it isn't important to prevent a clone here.)
359 there is no security so it isn't important to prevent a clone here.)
360
360
361 $ hg clone -U --stream server local-secret
361 $ hg clone -U --stream server local-secret
362 warning: stream clone requested but server has them disabled
362 warning: stream clone requested but server has them disabled
363 requesting all changes
363 requesting all changes
364 adding changesets
364 adding changesets
365 adding manifests
365 adding manifests
366 adding file changes
366 adding file changes
367 added 1 changesets with 1 changes to 1 files
367 added 1 changesets with 1 changes to 1 files
368 new changesets 96ee1d7354c4
368 new changesets 96ee1d7354c4
369
369
370 Stream clone while repo is changing:
370 Stream clone while repo is changing:
371
371
372 $ mkdir changing
372 $ mkdir changing
373 $ cd changing
373 $ cd changing
374
374
375 extension for delaying the server process so we reliably can modify the repo
375 extension for delaying the server process so we reliably can modify the repo
376 while cloning
376 while cloning
377
377
378 $ cat > delayer.py <<EOF
378 $ cat > delayer.py <<EOF
379 > import time
379 > import time
380 > from mercurial import extensions, vfs
380 > from mercurial import extensions, vfs
381 > def __call__(orig, self, path, *args, **kwargs):
381 > def __call__(orig, self, path, *args, **kwargs):
382 > if path == 'data/f1.i':
382 > if path == 'data/f1.i':
383 > time.sleep(2)
383 > time.sleep(2)
384 > return orig(self, path, *args, **kwargs)
384 > return orig(self, path, *args, **kwargs)
385 > extensions.wrapfunction(vfs.vfs, '__call__', __call__)
385 > extensions.wrapfunction(vfs.vfs, '__call__', __call__)
386 > EOF
386 > EOF
387
387
388 prepare repo with small and big file to cover both code paths in emitrevlogdata
388 prepare repo with small and big file to cover both code paths in emitrevlogdata
389
389
390 $ hg init repo
390 $ hg init repo
391 $ touch repo/f1
391 $ touch repo/f1
392 $ $TESTDIR/seq.py 50000 > repo/f2
392 $ $TESTDIR/seq.py 50000 > repo/f2
393 $ hg -R repo ci -Aqm "0"
393 $ hg -R repo ci -Aqm "0"
394 $ hg serve -R repo -p $HGPORT1 -d --pid-file=hg.pid --config extensions.delayer=delayer.py
394 $ hg serve -R repo -p $HGPORT1 -d --pid-file=hg.pid --config extensions.delayer=delayer.py
395 $ cat hg.pid >> $DAEMON_PIDS
395 $ cat hg.pid >> $DAEMON_PIDS
396
396
397 clone while modifying the repo between stating file with write lock and
397 clone while modifying the repo between stating file with write lock and
398 actually serving file content
398 actually serving file content
399
399
400 $ hg clone -q --stream -U http://localhost:$HGPORT1 clone &
400 $ hg clone -q --stream -U http://localhost:$HGPORT1 clone &
401 $ sleep 1
401 $ sleep 1
402 $ echo >> repo/f1
402 $ echo >> repo/f1
403 $ echo >> repo/f2
403 $ echo >> repo/f2
404 $ hg -R repo ci -m "1"
404 $ hg -R repo ci -m "1"
405 $ wait
405 $ wait
406 $ hg -R clone id
406 $ hg -R clone id
407 000000000000
407 000000000000
408 $ cd ..
408 $ cd ..
409
409
410 Stream repository with bookmarks
410 Stream repository with bookmarks
411 --------------------------------
411 --------------------------------
412
412
413 (revert introduction of secret changeset)
413 (revert introduction of secret changeset)
414
414
415 $ hg -R server phase --draft 'secret()'
415 $ hg -R server phase --draft 'secret()'
416
416
417 add a bookmark
417 add a bookmark
418
418
419 $ hg -R server bookmark -r tip some-bookmark
419 $ hg -R server bookmark -r tip some-bookmark
420
420
421 clone it
421 clone it
422
422
423 #if stream-legacy
423 #if stream-legacy
424 $ hg clone --stream http://localhost:$HGPORT with-bookmarks
424 $ hg clone --stream http://localhost:$HGPORT with-bookmarks
425 streaming all changes
425 streaming all changes
426 1027 files to transfer, 96.3 KB of data
426 1027 files to transfer, 96.3 KB of data
427 transferred 96.3 KB in * seconds (*) (glob)
427 transferred 96.3 KB in * seconds (*) (glob)
428 searching for changes
428 searching for changes
429 no changes found
429 no changes found
430 updating to branch default
430 updating to branch default
431 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
431 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
432 #endif
432 #endif
433 #if stream-bundle2
433 #if stream-bundle2
434 $ hg clone --stream http://localhost:$HGPORT with-bookmarks
434 $ hg clone --stream http://localhost:$HGPORT with-bookmarks
435 streaming all changes
435 streaming all changes
436 1033 files to transfer, 96.6 KB of data
436 1033 files to transfer, 96.6 KB of data
437 transferred 96.6 KB in * seconds (* */sec) (glob)
437 transferred 96.6 KB in * seconds (* */sec) (glob)
438 updating to branch default
438 updating to branch default
439 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
439 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
440 #endif
440 #endif
441 $ hg -R with-bookmarks bookmarks
441 $ hg -R with-bookmarks bookmarks
442 some-bookmark 1:c17445101a72
442 some-bookmark 1:c17445101a72
443
443
444 Stream repository with phases
444 Stream repository with phases
445 -----------------------------
445 -----------------------------
446
446
447 Clone as publishing
447 Clone as publishing
448
448
449 $ hg -R server phase -r 'all()'
449 $ hg -R server phase -r 'all()'
450 0: draft
450 0: draft
451 1: draft
451 1: draft
452
452
453 #if stream-legacy
453 #if stream-legacy
454 $ hg clone --stream http://localhost:$HGPORT phase-publish
454 $ hg clone --stream http://localhost:$HGPORT phase-publish
455 streaming all changes
455 streaming all changes
456 1027 files to transfer, 96.3 KB of data
456 1027 files to transfer, 96.3 KB of data
457 transferred 96.3 KB in * seconds (*) (glob)
457 transferred 96.3 KB in * seconds (*) (glob)
458 searching for changes
458 searching for changes
459 no changes found
459 no changes found
460 updating to branch default
460 updating to branch default
461 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
461 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
462 #endif
462 #endif
463 #if stream-bundle2
463 #if stream-bundle2
464 $ hg clone --stream http://localhost:$HGPORT phase-publish
464 $ hg clone --stream http://localhost:$HGPORT phase-publish
465 streaming all changes
465 streaming all changes
466 1033 files to transfer, 96.6 KB of data
466 1033 files to transfer, 96.6 KB of data
467 transferred 96.6 KB in * seconds (* */sec) (glob)
467 transferred 96.6 KB in * seconds (* */sec) (glob)
468 updating to branch default
468 updating to branch default
469 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
469 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
470 #endif
470 #endif
471 $ hg -R phase-publish phase -r 'all()'
471 $ hg -R phase-publish phase -r 'all()'
472 0: public
472 0: public
473 1: public
473 1: public
474
474
475 Clone as non publishing
475 Clone as non publishing
476
476
477 $ cat << EOF >> server/.hg/hgrc
477 $ cat << EOF >> server/.hg/hgrc
478 > [phases]
478 > [phases]
479 > publish = False
479 > publish = False
480 > EOF
480 > EOF
481 $ killdaemons.py
481 $ killdaemons.py
482 $ hg -R server serve -p $HGPORT -d --pid-file=hg.pid
482 $ hg -R server serve -p $HGPORT -d --pid-file=hg.pid
483 $ cat hg.pid > $DAEMON_PIDS
483 $ cat hg.pid > $DAEMON_PIDS
484
484
485 #if stream-legacy
485 #if stream-legacy
486
486
487 With v1 of the stream protocol, changeset are always cloned as public. It make
487 With v1 of the stream protocol, changeset are always cloned as public. It make
488 stream v1 unsuitable for non-publishing repository.
488 stream v1 unsuitable for non-publishing repository.
489
489
490 $ hg clone --stream http://localhost:$HGPORT phase-no-publish
490 $ hg clone --stream http://localhost:$HGPORT phase-no-publish
491 streaming all changes
491 streaming all changes
492 1027 files to transfer, 96.3 KB of data
492 1027 files to transfer, 96.3 KB of data
493 transferred 96.3 KB in * seconds (*) (glob)
493 transferred 96.3 KB in * seconds (*) (glob)
494 searching for changes
494 searching for changes
495 no changes found
495 no changes found
496 updating to branch default
496 updating to branch default
497 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
497 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
498 $ hg -R phase-no-publish phase -r 'all()'
498 $ hg -R phase-no-publish phase -r 'all()'
499 0: public
499 0: public
500 1: public
500 1: public
501 #endif
501 #endif
502 #if stream-bundle2
502 #if stream-bundle2
503 $ hg clone --stream http://localhost:$HGPORT phase-no-publish
503 $ hg clone --stream http://localhost:$HGPORT phase-no-publish
504 streaming all changes
504 streaming all changes
505 1034 files to transfer, 96.7 KB of data
505 1034 files to transfer, 96.7 KB of data
506 transferred 96.7 KB in * seconds (* */sec) (glob)
506 transferred 96.7 KB in * seconds (* */sec) (glob)
507 updating to branch default
507 updating to branch default
508 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
508 1025 files updated, 0 files merged, 0 files removed, 0 files unresolved
509 $ hg -R phase-no-publish phase -r 'all()'
509 $ hg -R phase-no-publish phase -r 'all()'
510 0: draft
510 0: draft
511 1: draft
511 1: draft
512 #endif
512 #endif
513
513
514 $ killdaemons.py
514 $ killdaemons.py
General Comments 0
You need to be logged in to leave comments. Login now